@vellumai/assistant 0.7.0 → 0.7.1

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 (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -3,7 +3,7 @@ import { z } from "zod";
3
3
  import { SttServiceSchema } from "./stt.js";
4
4
  import { TtsServiceSchema } from "./tts.js";
5
5
 
6
- export const ServiceModeSchema = z.enum(["managed", "your-own"]);
6
+ const ServiceModeSchema = z.enum(["managed", "your-own"]);
7
7
  export type ServiceMode = z.infer<typeof ServiceModeSchema>;
8
8
 
9
9
  export const VALID_INFERENCE_PROVIDERS = [
@@ -15,9 +15,9 @@ export const VALID_INFERENCE_PROVIDERS = [
15
15
  "openrouter",
16
16
  ] as const;
17
17
 
18
- export const VALID_IMAGE_GEN_PROVIDERS = ["gemini", "openai"] as const;
18
+ const VALID_IMAGE_GEN_PROVIDERS = ["gemini", "openai"] as const;
19
19
 
20
- export const VALID_WEB_SEARCH_PROVIDERS = [
20
+ const VALID_WEB_SEARCH_PROVIDERS = [
21
21
  "perplexity",
22
22
  "brave",
23
23
  "inference-provider-native",
@@ -36,10 +36,10 @@ export type BaseService = z.infer<typeof BaseServiceSchema>;
36
36
  * legacy configs that still carry them have those keys stripped by
37
37
  * workspace migration `039-drop-legacy-llm-keys`.
38
38
  */
39
- export const InferenceServiceSchema = BaseServiceSchema;
39
+ const InferenceServiceSchema = BaseServiceSchema;
40
40
  export type InferenceService = z.infer<typeof InferenceServiceSchema>;
41
41
 
42
- export const ImageGenerationServiceSchema = BaseServiceSchema.extend({
42
+ const ImageGenerationServiceSchema = BaseServiceSchema.extend({
43
43
  provider: z.enum(VALID_IMAGE_GEN_PROVIDERS).default("gemini"),
44
44
  model: z.string().default("gemini-3.1-flash-image-preview"),
45
45
  });
@@ -47,7 +47,7 @@ export type ImageGenerationService = z.infer<
47
47
  typeof ImageGenerationServiceSchema
48
48
  >;
49
49
 
50
- export const WebSearchServiceSchema = BaseServiceSchema.extend({
50
+ const WebSearchServiceSchema = BaseServiceSchema.extend({
51
51
  provider: z
52
52
  .enum(VALID_WEB_SEARCH_PROVIDERS)
53
53
  .default("inference-provider-native"),
@@ -24,7 +24,7 @@ export const SkillEntryConfigSchema = z
24
24
  })
25
25
  .describe("Configuration for an individual skill");
26
26
 
27
- export const SkillsLoadConfigSchema = z
27
+ const SkillsLoadConfigSchema = z
28
28
  .object({
29
29
  extraDirs: z
30
30
  .array(
@@ -49,7 +49,7 @@ export const SkillsLoadConfigSchema = z
49
49
  })
50
50
  .describe("Controls how skills are discovered and loaded");
51
51
 
52
- export const SkillsInstallConfigSchema = z
52
+ const SkillsInstallConfigSchema = z
53
53
  .object({
54
54
  nodeManager: z
55
55
  .enum(["npm", "pnpm", "yarn", "bun"], {
@@ -61,7 +61,7 @@ export const SkillsInstallConfigSchema = z
61
61
  })
62
62
  .describe("Skill dependency installation settings");
63
63
 
64
- export const RemoteProviderConfigSchema = z
64
+ const RemoteProviderConfigSchema = z
65
65
  .object({
66
66
  enabled: z
67
67
  .boolean({
@@ -72,7 +72,7 @@ export const RemoteProviderConfigSchema = z
72
72
  })
73
73
  .describe("Configuration for a remote skill provider");
74
74
 
75
- export const RemoteProvidersConfigSchema = z
75
+ const RemoteProvidersConfigSchema = z
76
76
  .object({
77
77
  skillssh: RemoteProviderConfigSchema.default(
78
78
  RemoteProviderConfigSchema.parse({}),
@@ -93,7 +93,7 @@ const VALID_MAX_RISK_LEVELS = [
93
93
  "critical",
94
94
  ] as const;
95
95
 
96
- export const RemotePolicyConfigSchema = z
96
+ const RemotePolicyConfigSchema = z
97
97
  .object({
98
98
  blockSuspicious: z
99
99
  .boolean({
@@ -220,7 +220,7 @@ export const TtsXaiProviderConfigSchema = z
220
220
 
221
221
  export type TtsXaiProviderConfig = z.infer<typeof TtsXaiProviderConfigSchema>;
222
222
 
223
- export const TtsProvidersSchema = z.object({
223
+ const TtsProvidersSchema = z.object({
224
224
  elevenlabs: TtsElevenLabsProviderConfigSchema.default(
225
225
  TtsElevenLabsProviderConfigSchema.parse({}),
226
226
  ),
@@ -0,0 +1,117 @@
1
+ import { loadRawConfig, saveRawConfig } from "./loader.js";
2
+ import {
3
+ DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS,
4
+ type ProfileEntry,
5
+ } from "./schemas/llm.js";
6
+
7
+ /**
8
+ * Declarative seed data for daemon-managed inference profiles.
9
+ *
10
+ * These profiles are overwritten on every startup so upstream model
11
+ * updates propagate automatically. User-created profiles (keyed by
12
+ * different names) are never touched.
13
+ */
14
+ export const MANAGED_PROFILE_SEED_DATA: Record<string, ProfileEntry> = {
15
+ balanced: {
16
+ source: "managed",
17
+ label: "Balanced",
18
+ description: "Good balance of quality, cost, and speed",
19
+ provider: "anthropic",
20
+ model: "claude-sonnet-4-6",
21
+ maxTokens: 16000,
22
+ effort: "high",
23
+ thinking: { enabled: true, streamThinking: true },
24
+ contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
25
+ },
26
+ "quality-optimized": {
27
+ source: "managed",
28
+ label: "Quality",
29
+ description: "Best results with the most capable model",
30
+ provider: "anthropic",
31
+ model: "claude-opus-4-7",
32
+ maxTokens: 32000,
33
+ effort: "max",
34
+ thinking: { enabled: true, streamThinking: true },
35
+ contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
36
+ },
37
+ "cost-optimized": {
38
+ source: "managed",
39
+ label: "Speed",
40
+ description: "Fastest responses at lower cost",
41
+ provider: "anthropic",
42
+ model: "claude-haiku-4-5-20251001",
43
+ maxTokens: 8192,
44
+ effort: "low",
45
+ thinking: { enabled: false, streamThinking: false },
46
+ contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
47
+ },
48
+ };
49
+
50
+ export const MANAGED_PROFILE_NAMES = new Set(
51
+ Object.keys(MANAGED_PROFILE_SEED_DATA),
52
+ );
53
+
54
+ /**
55
+ * Seed managed inference profiles into the workspace config.
56
+ *
57
+ * Called on every daemon startup after workspace migrations and before
58
+ * the first `loadConfig()`. Managed profiles are overwritten entirely
59
+ * (replace, not merge) so upstream model/effort changes propagate.
60
+ * User-created profiles are never touched; pre-existing profiles
61
+ * without a `source` field get `source: "user"` backfilled.
62
+ *
63
+ * No-op when `VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH` is set (same guard
64
+ * as migration 052) because the platform-provided default-config overlay
65
+ * is the authoritative source for profile seeds.
66
+ */
67
+ export function seedInferenceProfiles(): void {
68
+ if (process.env.VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH) return;
69
+
70
+ const config = loadRawConfig();
71
+
72
+ if (config.llm == null || typeof config.llm !== "object") {
73
+ config.llm = {};
74
+ }
75
+ const llm = config.llm as Record<string, unknown>;
76
+
77
+ if (llm.profiles == null || typeof llm.profiles !== "object") {
78
+ llm.profiles = {};
79
+ }
80
+ const profiles = llm.profiles as Record<string, Record<string, unknown>>;
81
+
82
+ for (const [name, seed] of Object.entries(MANAGED_PROFILE_SEED_DATA)) {
83
+ profiles[name] = { ...seed };
84
+ }
85
+
86
+ // Reset to the default managed profile when the current value is missing.
87
+ if (
88
+ typeof llm.activeProfile !== "string" ||
89
+ !(llm.activeProfile in profiles)
90
+ ) {
91
+ llm.activeProfile = "balanced";
92
+ }
93
+
94
+ const profileOrder = Array.isArray(llm.profileOrder)
95
+ ? (llm.profileOrder as string[])
96
+ : [];
97
+ const orderSet = new Set(profileOrder);
98
+ for (const name of MANAGED_PROFILE_NAMES) {
99
+ if (!orderSet.has(name)) {
100
+ profileOrder.push(name);
101
+ }
102
+ }
103
+ llm.profileOrder = profileOrder;
104
+
105
+ for (const [name, profile] of Object.entries(profiles)) {
106
+ if (MANAGED_PROFILE_NAMES.has(name)) continue;
107
+ if (
108
+ profile != null &&
109
+ typeof profile === "object" &&
110
+ !("source" in profile)
111
+ ) {
112
+ profile.source = "user";
113
+ }
114
+ }
115
+
116
+ saveRawConfig(config);
117
+ }
@@ -5,7 +5,6 @@ import {
5
5
  readFileSync,
6
6
  realpathSync,
7
7
  statSync,
8
- writeFileSync,
9
8
  } from "node:fs";
10
9
  import {
11
10
  basename,
@@ -22,11 +21,6 @@ import {
22
21
  getPluginContributedSkillDefinition,
23
22
  getPluginContributedSkillSummaries,
24
23
  } from "../plugins/plugin-skill-contributions.js";
25
- import {
26
- extractAllText,
27
- getConfiguredProvider,
28
- userMessage,
29
- } from "../providers/provider-send-message.js";
30
24
  import { parseFrontmatterFields } from "../skills/frontmatter.js";
31
25
  import type { InlineCommandExpansion } from "../skills/inline-command-expansions.js";
32
26
  import { parseInlineCommandExpansions } from "../skills/inline-command-expansions.js";
@@ -1232,87 +1226,3 @@ export function loadSkillBySelector(
1232
1226
  }
1233
1227
 
1234
1228
  // ─── Icon generation ─────────────────────────────────────────────────────────
1235
-
1236
- async function generateSkillIcon(
1237
- name: string,
1238
- description: string,
1239
- ): Promise<string> {
1240
- const provider = await getConfiguredProvider("skillCategoryInference");
1241
- if (!provider) {
1242
- throw new Error("Configured provider unavailable for icon generation");
1243
- }
1244
-
1245
- const response = await provider.sendMessage(
1246
- [
1247
- userMessage(
1248
- `Create a 16x16 pixel art SVG icon representing this skill:\nName: ${name}\nDescription: ${description}`,
1249
- ),
1250
- ],
1251
- undefined,
1252
- 'You are a pixel art icon designer. When asked, return ONLY a single <svg> element — no explanation, no markdown, no code fences. The SVG must be a 16x16 grid pixel art icon using <rect> elements. Use a limited palette (3-5 colors). Keep it under 2KB. The viewBox should be "0 0 16 16" with each pixel being a 1x1 rect.',
1253
- {
1254
- config: {
1255
- callSite: "skillCategoryInference",
1256
- max_tokens: 1024,
1257
- },
1258
- },
1259
- );
1260
-
1261
- const text = extractAllText(response);
1262
-
1263
- const svgMatch = text.match(/<svg[\s\S]*<\/svg>/i);
1264
- if (!svgMatch) {
1265
- throw new Error("No <svg> element found in response");
1266
- }
1267
-
1268
- return svgMatch[0];
1269
- }
1270
-
1271
- /**
1272
- * Synchronously read a cached icon if it exists on disk. Returns undefined if not cached yet.
1273
- */
1274
- export function readCachedSkillIcon(directoryPath: string): string | undefined {
1275
- const iconPath = join(directoryPath, "icon.svg");
1276
- if (existsSync(iconPath)) {
1277
- try {
1278
- return readFileSync(iconPath, "utf-8");
1279
- } catch {
1280
- return undefined;
1281
- }
1282
- }
1283
- return undefined;
1284
- }
1285
-
1286
- export async function ensureSkillIcon(
1287
- directoryPath: string,
1288
- name: string,
1289
- description: string,
1290
- ): Promise<string | undefined> {
1291
- const iconPath = join(directoryPath, "icon.svg");
1292
-
1293
- if (existsSync(iconPath)) {
1294
- try {
1295
- return readFileSync(iconPath, "utf-8");
1296
- } catch {
1297
- log.warn({ iconPath }, "Failed to read existing icon.svg");
1298
- return undefined;
1299
- }
1300
- }
1301
-
1302
- try {
1303
- const svg = await generateSkillIcon(name, description);
1304
- try {
1305
- writeFileSync(iconPath, svg, "utf-8");
1306
- log.info({ iconPath }, "Generated skill icon");
1307
- } catch (writeErr) {
1308
- log.warn(
1309
- { err: writeErr, iconPath },
1310
- "Failed to cache icon.svg (returning generated icon anyway)",
1311
- );
1312
- }
1313
- return svg;
1314
- } catch (err) {
1315
- log.warn({ err, iconPath }, "Failed to generate skill icon");
1316
- return undefined;
1317
- }
1318
- }
@@ -1,6 +1,3 @@
1
- export type {
2
- AssistantConfig,
3
- ContextWindowConfig,
4
- MemoryConfig,
5
- RateLimitConfig,
6
- } from "./schema.js";
1
+ export type { AssistantConfig, ContextWindowConfig } from "./schema.js";
2
+ export type { MemoryConfig } from "./schemas/memory.js";
3
+ export type { RateLimitConfig } from "./schemas/timeouts.js";
@@ -839,23 +839,6 @@ export function findContactChannel(params: {
839
839
  return null;
840
840
  }
841
841
 
842
- /**
843
- * Find the guardian contact regardless of channel.
844
- * Returns the first contact with role='guardian', or null if none exists.
845
- */
846
- export function findGuardianContact(): ContactWithChannels | null {
847
- const db = getDb();
848
- const row = db
849
- .select()
850
- .from(contacts)
851
- .where(eq(contacts.role, "guardian"))
852
- .orderBy(asc(contacts.createdAt))
853
- .limit(1)
854
- .get();
855
- if (!row) return null;
856
- return withChannels(parseContact(row));
857
- }
858
-
859
842
  /**
860
843
  * Find the guardian contact and their specific channel entry for a given channel type.
861
844
  * This is the contacts-based equivalent of getGuardianBinding(assistantId, channel).
@@ -7,8 +7,6 @@
7
7
  */
8
8
 
9
9
  import type { ChannelId } from "../channels/types.js";
10
- import type { GuardianBinding } from "../memory/channel-verification-sessions.js";
11
- import { ensureGuardianPersonaFile } from "../prompts/persona-resolver.js";
12
10
  import { canonicalizeInboundIdentity } from "../util/canonicalize-identity.js";
13
11
  import { getLogger } from "../util/logger.js";
14
12
  import { emitContactChange } from "./contact-events.js";
@@ -32,110 +30,8 @@ import type {
32
30
 
33
31
  const log = getLogger("contacts-write");
34
32
 
35
- // ── Helpers ──────────────────────────────────────────────────────────
36
-
37
- function parseDisplayNameFromMetadata(
38
- metadataJson: string | null | undefined,
39
- ): string | null {
40
- if (!metadataJson) return null;
41
- try {
42
- const parsed = JSON.parse(metadataJson);
43
- if (
44
- typeof parsed.displayName === "string" &&
45
- parsed.displayName.length > 0
46
- ) {
47
- return parsed.displayName;
48
- }
49
- } catch {
50
- // Malformed JSON — fall through
51
- }
52
- return null;
53
- }
54
-
55
33
  // ── Guardian operations ──────────────────────────────────────────────
56
34
 
57
- /**
58
- * Create a guardian binding by writing to the contacts table.
59
- * Returns a GuardianBinding-compatible object synthesized from the input params
60
- * (so callers expecting binding.id still work).
61
- */
62
- export function createGuardianBinding(params: {
63
- channel: string;
64
- guardianExternalUserId: string;
65
- guardianDeliveryChatId: string;
66
- guardianPrincipalId: string;
67
- verifiedVia?: string;
68
- metadataJson?: string | null;
69
- }): GuardianBinding {
70
- const canonicalId =
71
- canonicalizeInboundIdentity(
72
- params.channel as ChannelId,
73
- params.guardianExternalUserId,
74
- ) ?? params.guardianExternalUserId;
75
-
76
- const displayName =
77
- parseDisplayNameFromMetadata(params.metadataJson) ??
78
- params.guardianExternalUserId;
79
-
80
- const contact = upsertContact({
81
- displayName,
82
- role: "guardian",
83
- notes: "guardian",
84
- principalId: params.guardianPrincipalId,
85
- channels: [
86
- {
87
- type: params.channel,
88
- address: canonicalId,
89
- externalUserId: canonicalId,
90
- externalChatId: params.guardianDeliveryChatId,
91
- status: "active",
92
- verifiedAt: Date.now(),
93
- verifiedVia: params.verifiedVia ?? "challenge",
94
- },
95
- ],
96
- });
97
-
98
- // Seed the per-user persona file so downstream readers (journaling,
99
- // persona resolution) can rely on `users/<slug>.md` existing on disk.
100
- // Idempotent: pre-existing customized files are preserved.
101
- //
102
- // Seeding is restricted to the guardian-creation path only — it must
103
- // NOT run from inbound-message upsertContactChannel calls, since the
104
- // `users/` directory watcher would fire on every new contact and
105
- // evict live conversations.
106
- if (contact.userFile) {
107
- // Tolerate filesystem failures (read-only or full workspace) so a
108
- // disk error doesn't leave the DB commit orphaned. The persona file
109
- // can be reseeded later; failing the binding here would be worse.
110
- try {
111
- ensureGuardianPersonaFile(contact.userFile);
112
- } catch (err) {
113
- log.warn(
114
- { err, userFile: contact.userFile },
115
- "failed to seed guardian persona file; continuing",
116
- );
117
- }
118
- }
119
-
120
- const now = Date.now();
121
- const result: GuardianBinding = {
122
- id: `contact-binding-${params.channel}`,
123
- assistantId: "self",
124
- channel: params.channel,
125
- guardianExternalUserId: params.guardianExternalUserId,
126
- guardianDeliveryChatId: params.guardianDeliveryChatId,
127
- guardianPrincipalId: params.guardianPrincipalId,
128
- status: "active",
129
- verifiedAt: now,
130
- verifiedVia: params.verifiedVia ?? "challenge",
131
- metadataJson: params.metadataJson ?? null,
132
- createdAt: now,
133
- updatedAt: now,
134
- };
135
-
136
- return result;
137
- }
138
-
139
35
  /**
140
36
  * Revoke a guardian binding by updating the contacts table.
141
37
  * Returns true when a guardian channel was found and revoked, false otherwise.
@@ -237,7 +133,7 @@ export function upsertContactChannel(params: {
237
133
  // inbound-message hot path — every new contact (Slack, phone, email, etc)
238
134
  // would otherwise fire the `users/` directory watcher in
239
135
  // config-watcher.ts and evict live conversations. Persona-file seeding
240
- // is the sole responsibility of `createGuardianBinding`.
136
+ // is handled by the gateway's guardian bootstrap flow.
241
137
 
242
138
  const contactResult = findContactChannel({
243
139
  channelType: params.sourceChannel,
@@ -1,6 +1,7 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
 
4
+ import type { LLMCallSite } from "../config/schemas/llm.js";
4
5
  import type { ContextWindowConfig } from "../config/types.js";
5
6
  import type {
6
7
  ContentBlock,
@@ -21,6 +22,8 @@ import { truncateToolResultsAcrossHistory } from "./tool-result-truncation.js";
21
22
  const log = getLogger("context-window");
22
23
 
23
24
  export const CONTEXT_SUMMARY_MARKER = "<context_summary>";
25
+ export const CONVERSATION_SUMMARY_CALL_SITE: LLMCallSite =
26
+ "conversationSummarization";
24
27
  const MAX_BLOCK_PREVIEW_CHARS = 3000;
25
28
  const MAX_FALLBACK_SUMMARY_CHARS = 12000;
26
29
  const COMPACTION_COOLDOWN_MS = 2 * 60 * 1000;
@@ -241,6 +244,8 @@ export interface ContextWindowResult {
241
244
  summaryInputTokens: number;
242
245
  summaryOutputTokens: number;
243
246
  summaryModel: string;
247
+ summaryCallSite?: LLMCallSite;
248
+ summaryOverrideProfile?: string | null;
244
249
  summaryCacheCreationInputTokens?: number;
245
250
  summaryCacheReadInputTokens?: number;
246
251
  summaryRawResponses?: unknown[];
@@ -278,6 +283,11 @@ export interface ContextWindowCompactOptions {
278
283
  * aggressively. Explicit `minKeepRecentUserTurns` overrides this hint.
279
284
  */
280
285
  conversationOriginChannel?: string;
286
+ /**
287
+ * Per-conversation inference-profile override forwarded to the summary LLM
288
+ * call and usage attribution.
289
+ */
290
+ overrideProfile?: string | null;
281
291
  /**
282
292
  * Override the target input token budget used for keep-boundary
283
293
  * projected-fit checks. Clamped to no looser than `config.targetInputTokens`
@@ -305,7 +315,7 @@ export interface ContextWindowManagerOptions {
305
315
  export class ContextWindowManager {
306
316
  private readonly provider: Provider;
307
317
  private readonly _systemPrompt: string | (() => string);
308
- private readonly config: ContextWindowConfig;
318
+ private config: ContextWindowConfig;
309
319
  private readonly toolTokenBudget: number;
310
320
  /**
311
321
  * Number of leading messages that are non-persisted (injected inherited
@@ -339,6 +349,10 @@ export class ContextWindowManager {
339
349
  this.toolTokenBudget = options.toolTokenBudget ?? 0;
340
350
  }
341
351
 
352
+ updateConfig(config: ContextWindowConfig): void {
353
+ this.config = config;
354
+ }
355
+
342
356
  /**
343
357
  * Provider key for the local token estimator. Wrapper providers (e.g.
344
358
  * OpenRouter routing to `anthropic/*`) override `tokenEstimationProvider`
@@ -480,6 +494,7 @@ export class ContextWindowManager {
480
494
  targetInputTokensOverride: options?.targetInputTokensOverride,
481
495
  conversationOriginChannel: options?.conversationOriginChannel,
482
496
  force: options?.force,
497
+ previousEstimatedInputTokens,
483
498
  });
484
499
  if (keepPlan.keepFromIndex <= summaryOffset) {
485
500
  // All turns fit after truncation projection, but the real in-memory
@@ -672,6 +687,7 @@ export class ContextWindowManager {
672
687
  transcriptBlocks,
673
688
  retainedThreadRefs,
674
689
  signal,
690
+ options?.overrideProfile ?? null,
675
691
  );
676
692
  const summary = summaryUpdate.summary;
677
693
  const summaryInputTokens = summaryUpdate.inputTokens;
@@ -748,6 +764,8 @@ export class ContextWindowManager {
748
764
  summaryInputTokens,
749
765
  summaryOutputTokens,
750
766
  summaryModel,
767
+ summaryCallSite: CONVERSATION_SUMMARY_CALL_SITE,
768
+ summaryOverrideProfile: options?.overrideProfile ?? null,
751
769
  summaryCacheCreationInputTokens,
752
770
  summaryCacheReadInputTokens,
753
771
  summaryRawResponses,
@@ -771,6 +789,7 @@ export class ContextWindowManager {
771
789
  targetInputTokensOverride?: number;
772
790
  conversationOriginChannel?: string;
773
791
  force?: boolean;
792
+ previousEstimatedInputTokens?: number;
774
793
  },
775
794
  ): { keepFromIndex: number; keepTurns: number } {
776
795
  // Slack-originated conversations rely on multi-turn thread context
@@ -854,6 +873,20 @@ export class ContextWindowManager {
854
873
  }
855
874
  }
856
875
 
876
+ // The projection's summary-swap and tool_result truncation can make
877
+ // projectedTokensForKeep(hi) optimistically fit even when the live
878
+ // conversation is well over target — sending /compact through the
879
+ // "already fits" skip path as a no-op. Clamp lo so summarization runs.
880
+ if (
881
+ opts?.force &&
882
+ floorIsImplicitDefault &&
883
+ lo === userTurnStarts.length &&
884
+ lo > 0 &&
885
+ (opts?.previousEstimatedInputTokens ?? 0) > targetTokens
886
+ ) {
887
+ lo -= 1;
888
+ }
889
+
857
890
  const keepTurns = lo;
858
891
  const rawKeepFromIndex =
859
892
  keepTurns === 0
@@ -994,6 +1027,7 @@ export class ContextWindowManager {
994
1027
  transcriptBlocks: ContentBlock[],
995
1028
  retainedThreadRefs: string[],
996
1029
  signal?: AbortSignal,
1030
+ overrideProfile?: string | null,
997
1031
  ): Promise<{
998
1032
  summary: string;
999
1033
  inputTokens: number;
@@ -1025,15 +1059,20 @@ export class ContextWindowManager {
1025
1059
  const summaryMessage: Message = { role: "user", content: contentBlocks };
1026
1060
  let failed = false;
1027
1061
  try {
1062
+ const providerConfig: Record<string, unknown> = {
1063
+ callSite: CONVERSATION_SUMMARY_CALL_SITE,
1064
+ usageTracking: "manual",
1065
+ max_tokens: this.summaryMaxTokens,
1066
+ };
1067
+ if (overrideProfile) {
1068
+ providerConfig.overrideProfile = overrideProfile;
1069
+ }
1028
1070
  const response = await this.provider.sendMessage(
1029
1071
  [summaryMessage],
1030
1072
  undefined,
1031
1073
  SUMMARY_SYSTEM_PROMPT,
1032
1074
  {
1033
- config: {
1034
- callSite: "conversationSummarization" as const,
1035
- max_tokens: this.summaryMaxTokens,
1036
- },
1075
+ config: providerConfig,
1037
1076
  signal,
1038
1077
  },
1039
1078
  );
@@ -241,11 +241,7 @@ export function createCesProcessManager(
241
241
  stdin: "pipe",
242
242
  stdout: "pipe",
243
243
  stderr: "pipe",
244
- env: {
245
- ...process.env,
246
- // Signal to CES that it was launched by the assistant
247
- CES_LAUNCHED_BY: "assistant",
248
- },
244
+ env: buildLocalCesEnv(),
249
245
  });
250
246
 
251
247
  childProcess = proc;
@@ -274,11 +270,7 @@ export function createCesProcessManager(
274
270
  stdin: "pipe",
275
271
  stdout: "pipe",
276
272
  stderr: "pipe",
277
- env: {
278
- ...process.env,
279
- // Signal to CES that it was launched by the assistant
280
- CES_LAUNCHED_BY: "assistant",
281
- },
273
+ env: buildLocalCesEnv(),
282
274
  });
283
275
 
284
276
  childProcess = proc;
@@ -313,6 +305,38 @@ export function createCesProcessManager(
313
305
  }
314
306
  }
315
307
 
308
+ // ---------------------------------------------------------------------------
309
+ // Local CES env
310
+ // ---------------------------------------------------------------------------
311
+
312
+ /**
313
+ * Build the environment for a locally-spawned CES child process.
314
+ *
315
+ * Inherits the daemon's process env (which already has VELLUM_WORKSPACE_DIR
316
+ * and GATEWAY_SECURITY_DIR from the CLI) and adds CES-specific env vars:
317
+ *
318
+ * - `CREDENTIAL_SECURITY_DIR`: CES reads this to find its key store and
319
+ * encryption data. In local mode this is the same directory as the
320
+ * gateway security dir (both point to `<instance>/.vellum/protected`).
321
+ *
322
+ * - `VELLUM_WORKSPACE_DIR`: Forwarded so CES can locate the assistant
323
+ * workspace (credential metadata, OAuth DB, token refresh).
324
+ */
325
+ function buildLocalCesEnv(): Record<string, string | undefined> {
326
+ return {
327
+ ...process.env,
328
+ CES_LAUNCHED_BY: "assistant",
329
+ // Map the daemon's GATEWAY_SECURITY_DIR to CES's own env var.
330
+ // In local mode, both services share the same protected/ directory.
331
+ CREDENTIAL_SECURITY_DIR:
332
+ process.env["CREDENTIAL_SECURITY_DIR"] ||
333
+ process.env["GATEWAY_SECURITY_DIR"],
334
+ // VELLUM_WORKSPACE_DIR is already in process.env from the CLI,
335
+ // but be explicit for clarity.
336
+ VELLUM_WORKSPACE_DIR: process.env["VELLUM_WORKSPACE_DIR"],
337
+ };
338
+ }
339
+
316
340
  // ---------------------------------------------------------------------------
317
341
  // Stdio transport (local mode)
318
342
  // ---------------------------------------------------------------------------