@vellumai/assistant 0.12.1-dev.202609141913.5e16607 → 0.12.1-staging.2

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 (439) hide show
  1. package/AGENTS.md +0 -4
  2. package/ARCHITECTURE.md +12 -11
  3. package/docs/architecture/turn-actor.md +8 -15
  4. package/docs/guardian-request-flow.md +0 -16
  5. package/openapi.yaml +49 -291
  6. package/package.json +1 -1
  7. package/src/__tests__/always-loaded-tools-guard.test.ts +10 -18
  8. package/src/__tests__/app-compiler.test.ts +0 -6
  9. package/src/__tests__/app-control-tool-schemas.test.ts +2 -5
  10. package/src/__tests__/app-dir-path-guard.test.ts +3 -1
  11. package/src/__tests__/app-source-watcher.test.ts +218 -0
  12. package/src/{calls/__tests__ → __tests__}/call-controller.test.ts +82 -503
  13. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +2 -5
  14. package/src/__tests__/computer-use-tools.test.ts +5 -17
  15. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  16. package/src/__tests__/config-schema.test.ts +29 -28
  17. package/src/__tests__/config-watcher-skill-reseed.test.ts +359 -0
  18. package/src/__tests__/config-watcher.test.ts +8 -23
  19. package/src/__tests__/connection-model-compat.test.ts +2 -2
  20. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  21. package/src/__tests__/conversation-pairing.test.ts +0 -26
  22. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -4
  23. package/src/__tests__/conversation-queue.test.ts +207 -48
  24. package/src/__tests__/conversation-retry-discard.test.ts +1 -54
  25. package/src/__tests__/conversation-skill-tools.test.ts +0 -27
  26. package/src/__tests__/conversation-surfaces-app-control.test.ts +3 -8
  27. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -67
  28. package/src/__tests__/conversation-title-service.test.ts +10 -14
  29. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +5 -3
  30. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -51
  31. package/src/__tests__/credential-record-retire.test.ts +1 -171
  32. package/src/__tests__/credential-routes.test.ts +3 -212
  33. package/src/__tests__/credential-security-invariants.test.ts +2 -4
  34. package/src/__tests__/cu-unified-flow.test.ts +2 -8
  35. package/src/__tests__/document-sync-tags.test.ts +0 -25
  36. package/src/__tests__/drain-kick-guard.test.ts +2 -0
  37. package/src/__tests__/drain-requeue-on-contention.test.ts +6 -0
  38. package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
  39. package/src/__tests__/host-bash-proxy.test.ts +45 -26
  40. package/src/__tests__/host-browser-proxy.test.ts +17 -6
  41. package/src/__tests__/host-file-proxy-targeted.test.ts +0 -23
  42. package/src/__tests__/host-file-proxy.test.ts +23 -11
  43. package/src/__tests__/host-transfer-proxy-targeted.test.ts +9 -30
  44. package/src/__tests__/llm-catalog-parity.test.ts +0 -25
  45. package/src/__tests__/mcp-auth-routes.test.ts +9 -6
  46. package/src/__tests__/mcp-config-secret-boundary.test.ts +136 -78
  47. package/src/__tests__/mcp-health-check.test.ts +11 -8
  48. package/src/__tests__/mcp-list-plugin-servers.test.ts +10 -8
  49. package/src/{calls/__tests__ → __tests__}/media-stream-audio-transcode.test.ts +1 -1
  50. package/src/{calls/__tests__ → __tests__}/media-stream-output.test.ts +8 -37
  51. package/src/{calls/__tests__ → __tests__}/media-stream-parser.test.ts +1 -1
  52. package/src/{calls/__tests__ → __tests__}/media-stream-server-integration.test.ts +57 -150
  53. package/src/{calls/__tests__ → __tests__}/media-stream-stt-session.test.ts +5 -5
  54. package/src/{calls/__tests__ → __tests__}/media-turn-detector.test.ts +1 -1
  55. package/src/__tests__/messages-after-tiebreaker.test.ts +0 -91
  56. package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
  57. package/src/__tests__/messaging-send-tool.test.ts +548 -355
  58. package/src/__tests__/model-intents.test.ts +0 -3
  59. package/src/__tests__/notification-vellum-adapter.test.ts +2 -85
  60. package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
  61. package/src/__tests__/platform-callback-registration.test.ts +16 -8
  62. package/src/__tests__/platform-client-verify-credential.test.ts +0 -2
  63. package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -13
  64. package/src/__tests__/script-proxy-certs.test.ts +0 -35
  65. package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
  66. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  67. package/src/__tests__/speaker-identification.test.ts +56 -0
  68. package/src/__tests__/subagent-tool-gate-mode.test.ts +3 -19
  69. package/src/__tests__/subagent-tools.test.ts +2 -3
  70. package/src/__tests__/telephony-tts-guard.test.ts +3 -38
  71. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -4
  72. package/src/{calls/__tests__/voice-session-bridge-turn-flow.test.ts → __tests__/voice-session-bridge.test.ts} +12 -20
  73. package/src/__tests__/watch-retro-tool-availability.test.ts +17 -8
  74. package/src/__tests__/workspace-git-service.test.ts +0 -26
  75. package/src/acp/__tests__/agent-process.test.ts +4 -258
  76. package/src/acp/__tests__/auth-required.test.ts +0 -96
  77. package/src/acp/__tests__/client-handler.test.ts +2 -90
  78. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -5
  79. package/src/acp/__tests__/session-manager-resume.test.ts +6 -270
  80. package/src/acp/__tests__/session-manager-usage.test.ts +2 -4
  81. package/src/acp/__tests__/session-manager.test.ts +4 -895
  82. package/src/acp/agent-process.test.ts +1 -4
  83. package/src/acp/agent-process.ts +9 -94
  84. package/src/acp/auth-required.ts +1 -50
  85. package/src/acp/auto-install.test.ts +7 -9
  86. package/src/acp/client-handler.ts +3 -16
  87. package/src/acp/resolve-agent.test.ts +6 -220
  88. package/src/acp/resolve-agent.ts +23 -88
  89. package/src/acp/session-manager.test.ts +3 -196
  90. package/src/acp/session-manager.ts +18 -441
  91. package/src/acp/types.ts +5 -50
  92. package/src/api/events/app-files-changed.ts +3 -4
  93. package/src/api/events/notification-intent.ts +0 -2
  94. package/src/api/index.ts +0 -6
  95. package/src/apps/app-store.ts +1 -1
  96. package/src/bundler/app-compiler.ts +0 -15
  97. package/src/calls/__tests__/voice-control-protocol.test.ts +25 -58
  98. package/src/calls/__tests__/voice-session-bridge.test.ts +1 -37
  99. package/src/calls/__tests__/voice-triage-escalate.test.ts +0 -105
  100. package/src/calls/call-constants.ts +4 -24
  101. package/src/calls/call-controller.ts +199 -499
  102. package/src/calls/call-transport.ts +0 -16
  103. package/src/calls/media-stream-output.ts +0 -32
  104. package/src/calls/media-stream-server.ts +30 -82
  105. package/src/calls/media-stream-stt-session.ts +0 -15
  106. package/src/calls/resolve-call-tts-provider.ts +2 -33
  107. package/src/calls/speaker-identification.ts +233 -0
  108. package/src/calls/tts-call-strategy.ts +5 -9
  109. package/src/calls/types.ts +0 -2
  110. package/src/calls/voice-control-protocol.ts +21 -53
  111. package/src/calls/voice-session-bridge.ts +46 -59
  112. package/src/calls/voice-triage-escalate.ts +56 -175
  113. package/src/cli/commands/apps.help.ts +13 -67
  114. package/src/cli/commands/apps.ts +0 -183
  115. package/src/cli/commands/bash.help.ts +13 -8
  116. package/src/cli/commands/bash.ts +25 -7
  117. package/src/cli/commands/channels/index.help.ts +2 -70
  118. package/src/cli/commands/channels/index.ts +3 -16
  119. package/src/cli/commands/credentials.help.ts +2 -6
  120. package/src/cli/commands/credentials.ts +2 -2
  121. package/src/cli/commands/mcp.help.ts +8 -8
  122. package/src/cli/commands/mcp.ts +1 -1
  123. package/src/cli/commands/roadmap.help.ts +1 -5
  124. package/src/cli/commands/roadmap.ts +1 -1
  125. package/src/cli/lib/bundled-marketplace.json +90 -103
  126. package/src/config/__tests__/default-profile-catalog.test.ts +0 -22
  127. package/src/config/__tests__/memory-retrospective-schema.test.ts +1 -15
  128. package/src/config/__tests__/platform-rehydration.test.ts +9 -99
  129. package/src/config/acp-defaults.test.ts +3 -13
  130. package/src/config/acp-defaults.ts +6 -23
  131. package/src/config/acp-schema.ts +2 -30
  132. package/src/config/bundled-skills/acp/SKILL.md +14 -22
  133. package/src/config/bundled-skills/acp/TOOLS.json +1 -5
  134. package/src/config/bundled-skills/app-builder/SKILL.md +9 -12
  135. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
  136. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  137. package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
  138. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +139 -67
  139. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
  140. package/src/config/bundled-skills/schedule/SKILL.md +4 -3
  141. package/src/config/bundled-skills/screen-annotation/SKILL.md +1 -8
  142. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +1 -4
  143. package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
  144. package/src/config/default-profile-catalog.ts +1 -1
  145. package/src/config/env.ts +2 -2
  146. package/src/config/feature-flag-registry.json +12 -24
  147. package/src/config/loader.ts +0 -1
  148. package/src/config/memory-v3-gate.test.ts +0 -31
  149. package/src/config/memory-v3-gate.ts +16 -20
  150. package/src/config/platform-rehydration.ts +27 -11
  151. package/src/config/schema.ts +2 -2
  152. package/src/config/schemas/__tests__/live-voice.test.ts +158 -8
  153. package/src/config/schemas/calls.ts +28 -1
  154. package/src/config/schemas/live-voice.ts +173 -1
  155. package/src/config/schemas/mcp.ts +1 -1
  156. package/src/config/schemas/memory-retrospective.ts +0 -10
  157. package/src/config/schemas/services.ts +0 -8
  158. package/src/config/schemas/skills.ts +14 -0
  159. package/src/credential-execution/process-manager.test.ts +19 -18
  160. package/src/daemon/__tests__/conversation-tool-setup.test.ts +121 -66
  161. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +1 -4
  162. package/src/daemon/app-source-watcher.ts +218 -0
  163. package/src/daemon/config-watcher.ts +194 -13
  164. package/src/daemon/conversation-process.ts +64 -35
  165. package/src/daemon/conversation-skill-tools.ts +31 -13
  166. package/src/daemon/conversation-store.ts +1 -1
  167. package/src/daemon/conversation-surfaces.ts +8 -10
  168. package/src/daemon/conversation-tool-setup.ts +43 -37
  169. package/src/daemon/conversation.ts +3 -0
  170. package/src/daemon/host-bash-proxy.ts +12 -8
  171. package/src/daemon/host-browser-proxy.ts +1 -15
  172. package/src/daemon/host-file-proxy.ts +10 -8
  173. package/src/daemon/host-transfer-proxy.ts +18 -14
  174. package/src/daemon/lifecycle.ts +5 -0
  175. package/src/daemon/mcp-reload-service.ts +5 -5
  176. package/src/daemon/message-types/sync.ts +0 -1
  177. package/src/daemon/orphan-reaper.ts +1 -1
  178. package/src/daemon/providers-setup.ts +1 -1
  179. package/src/daemon/shutdown-handlers.ts +9 -1
  180. package/src/daemon/skill-memory-refresh.ts +0 -64
  181. package/src/daemon/tool-side-effects.ts +18 -7
  182. package/src/home/__tests__/feed-writer.test.ts +0 -22
  183. package/src/home/feed-writer.ts +2 -11
  184. package/src/hooks/types.ts +0 -33
  185. package/src/inbound/platform-callback-registration.ts +5 -4
  186. package/src/live-voice/__tests__/live-voice-metrics.test.ts +3 -0
  187. package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -15
  188. package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
  189. package/src/{calls → live-voice}/__tests__/progress-narration.test.ts +4 -4
  190. package/src/{calls → live-voice}/__tests__/progress-phrases.test.ts +1 -1
  191. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +69 -13
  192. package/src/live-voice/live-voice-session.ts +693 -213
  193. package/src/{calls → live-voice}/progress-narration.ts +2 -2
  194. package/src/live-voice/protocol.ts +2 -0
  195. package/src/mcp/__tests__/effective-config.test.ts +2 -2
  196. package/src/mcp/effective-config.ts +3 -3
  197. package/src/mcp/mcp-header-store.ts +45 -29
  198. package/src/mcp/startup.ts +4 -8
  199. package/src/messaging/provider.ts +3 -10
  200. package/src/messaging/providers/callback-routing.ts +0 -18
  201. package/src/messaging/providers/channel-transport.ts +0 -56
  202. package/src/messaging/providers/discord/transport.ts +0 -17
  203. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +17 -6
  204. package/src/messaging/providers/slack/adapter.ts +44 -7
  205. package/src/messaging/providers/slack/transport.ts +0 -16
  206. package/src/messaging/providers/telegram-bot/adapter.ts +48 -1
  207. package/src/messaging/providers/telegram-bot/client.ts +26 -0
  208. package/src/messaging/providers/telegram-bot/transport.ts +0 -20
  209. package/src/messaging/providers/whatsapp/adapter.ts +48 -1
  210. package/src/messaging/providers/whatsapp/client.ts +29 -0
  211. package/src/messaging/providers/whatsapp/transport.ts +0 -18
  212. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +0 -8
  213. package/src/notifications/__tests__/assistant-reply-producer.test.ts +0 -55
  214. package/src/notifications/__tests__/guardian-feed-projection.test.ts +2 -158
  215. package/src/notifications/__tests__/home-feed-side-effect.test.ts +3 -153
  216. package/src/notifications/__tests__/schedule-result-producer.test.ts +3 -99
  217. package/src/notifications/adapters/macos.ts +0 -3
  218. package/src/notifications/assistant-reply-producer.ts +3 -8
  219. package/src/notifications/conversation-pairing.ts +16 -36
  220. package/src/notifications/delivered-post-record.ts +1 -11
  221. package/src/notifications/guardian-feed-projection.ts +5 -125
  222. package/src/notifications/home-feed-side-effect.ts +7 -55
  223. package/src/notifications/schedule-result-producer.ts +22 -66
  224. package/src/oauth/__tests__/seed-providers-managed.test.ts +0 -54
  225. package/src/oauth/byo-connection.test.ts +0 -45
  226. package/src/oauth/byo-connection.ts +6 -36
  227. package/src/oauth/connection-resolver.test.ts +0 -73
  228. package/src/oauth/connection-resolver.ts +2 -95
  229. package/src/oauth/seed-providers.ts +0 -165
  230. package/src/outbound-proxy/certs.ts +5 -3
  231. package/src/permissions/checker.test.ts +6 -11
  232. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  233. package/src/persistence/conversation-crud.ts +63 -71
  234. package/src/persistence/conversation-lineage.ts +4 -12
  235. package/src/persistence/conversation-title-service.ts +26 -9
  236. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  237. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  238. package/src/persistence/message-reads.ts +0 -30
  239. package/src/persistence/migrations/157-invite-contact-id.ts +6 -18
  240. package/src/persistence/schema/memory-core.ts +0 -5
  241. package/src/platform/client.test.ts +2 -4
  242. package/src/platform/client.ts +10 -2
  243. package/src/plugin-api/constants.ts +0 -2
  244. package/src/plugin-api/index.ts +0 -1
  245. package/src/plugin-api/types.ts +0 -2
  246. package/src/plugins/defaults/index.ts +0 -2
  247. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +0 -46
  248. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +5 -9
  249. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +10 -20
  250. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +0 -219
  251. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +0 -31
  252. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -63
  253. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +0 -4
  254. package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -4
  255. package/src/plugins/defaults/memory/hooks/init.ts +0 -10
  256. package/src/plugins/defaults/memory/hooks/shutdown.ts +0 -2
  257. package/src/plugins/defaults/memory/jobs-worker.ts +0 -13
  258. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +60 -34
  259. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +5 -3
  260. package/src/plugins/defaults/memory/memory-retrospective-job.ts +3 -12
  261. package/src/plugins/defaults/memory/memory-retrospective-state.ts +71 -312
  262. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +1 -2
  263. package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +3 -5
  264. package/src/plugins/defaults/memory/startup.ts +1 -6
  265. package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +9 -7
  266. package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
  267. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +0 -89
  268. package/src/plugins/defaults/memory/worker.ts +0 -6
  269. package/src/plugins/mcp-servers.ts +75 -15
  270. package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
  271. package/src/providers/gemini/client.ts +23 -9
  272. package/src/providers/inference/auth.ts +3 -2
  273. package/src/providers/inference/connection-availability.ts +8 -27
  274. package/src/providers/inference/resolve-auth.ts +4 -22
  275. package/src/providers/model-catalog.ts +0 -34
  276. package/src/providers/model-intents.ts +5 -10
  277. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +18 -146
  278. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +1 -83
  279. package/src/providers/openai/chat-completions-provider.ts +78 -192
  280. package/src/providers/openai/codex-models.ts +4 -0
  281. package/src/runtime/AGENTS.md +0 -2
  282. package/src/runtime/auth/same-actor.ts +3 -38
  283. package/src/runtime/http-server.ts +151 -160
  284. package/src/runtime/routes/__tests__/acp-routes.test.ts +4 -159
  285. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -108
  286. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
  287. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +12 -16
  288. package/src/runtime/routes/acp-routes.test.ts +0 -15
  289. package/src/runtime/routes/acp-routes.ts +9 -72
  290. package/src/runtime/routes/app-management-routes.ts +0 -73
  291. package/src/runtime/routes/app-routes.ts +1 -1
  292. package/src/runtime/routes/conversation-list-routes.ts +3 -14
  293. package/src/runtime/routes/conversation-query-routes.ts +0 -40
  294. package/src/runtime/routes/credential-routes.ts +10 -19
  295. package/src/runtime/routes/debug-bash-routes.ts +173 -0
  296. package/src/runtime/routes/diagnostics-routes.ts +3 -55
  297. package/src/runtime/routes/index.ts +2 -4
  298. package/src/runtime/routes/log-export-routes.ts +0 -2
  299. package/src/runtime/routes/mcp-auth-routes.ts +47 -39
  300. package/src/runtime/routes/migration-routes.ts +20 -6
  301. package/src/runtime/routes/platform-routes.ts +15 -18
  302. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -28
  303. package/src/runtime/services/conversation-serializer.ts +3 -16
  304. package/src/runtime/sync/resource-sync-events.ts +1 -2
  305. package/src/schedule/worker.ts +1 -1
  306. package/src/security/ces-rpc-record-backend.ts +0 -7
  307. package/src/subagent/consult-context.ts +25 -12
  308. package/src/tools/acp/list-agents.test.ts +1 -3
  309. package/src/tools/acp/spawn.test.ts +11 -146
  310. package/src/tools/acp/spawn.ts +3 -21
  311. package/src/tools/acp/status.ts +3 -40
  312. package/src/tools/app-control/skill-proxy-bridge.ts +1 -2
  313. package/src/tools/capability-offer.test.ts +2 -22
  314. package/src/tools/capability-offer.ts +1 -16
  315. package/src/tools/computer-use/definitions.ts +2 -4
  316. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -2
  317. package/src/tools/credentials/metadata-store.ts +0 -100
  318. package/src/tools/host-filesystem/edit.test.ts +1 -2
  319. package/src/tools/host-filesystem/edit.ts +2 -2
  320. package/src/tools/host-filesystem/read.test.ts +1 -2
  321. package/src/tools/host-filesystem/read.ts +2 -2
  322. package/src/tools/host-filesystem/transfer.test.ts +1 -2
  323. package/src/tools/host-filesystem/transfer.ts +2 -2
  324. package/src/tools/host-filesystem/write.test.ts +1 -2
  325. package/src/tools/host-filesystem/write.ts +2 -2
  326. package/src/tools/host-terminal/host-shell.test.ts +0 -16
  327. package/src/tools/host-terminal/host-shell.ts +20 -4
  328. package/src/tools/policy-context.ts +7 -6
  329. package/src/tools/subagent/spawn.ts +8 -5
  330. package/src/tools/watch/watch-retro-report.ts +8 -0
  331. package/src/util/__tests__/language-subtag.test.ts +1 -23
  332. package/src/util/fs-watcher-error.ts +36 -0
  333. package/src/util/language-subtag.ts +0 -16
  334. package/src/util/platform.ts +0 -8
  335. package/src/workspace/git-service.ts +54 -5
  336. package/src/workspace/migrations/registry.ts +0 -6
  337. package/scripts/smoke-desktop-window-theme.ts +0 -186
  338. package/src/__tests__/git-porcelain.test.ts +0 -47
  339. package/src/__tests__/helpers/set-workspace-mcp.ts +0 -11
  340. package/src/__tests__/message-deleted-hook-dispatch.test.ts +0 -119
  341. package/src/__tests__/resolve-app.test.ts +0 -135
  342. package/src/__tests__/service-account-token.test.ts +0 -247
  343. package/src/__tests__/source-fingerprint.test.ts +0 -184
  344. package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +0 -336
  345. package/src/acp/__tests__/helpers/acp-model-option.ts +0 -51
  346. package/src/acp/model-config.test.ts +0 -166
  347. package/src/acp/model-config.ts +0 -138
  348. package/src/api/events/acp-session-model-update.test.ts +0 -88
  349. package/src/api/events/acp-session-model-update.ts +0 -46
  350. package/src/apps/resolve-app.ts +0 -81
  351. package/src/apps/source-fingerprint.ts +0 -266
  352. package/src/calls/__tests__/barge-in-guard.test.ts +0 -81
  353. package/src/calls/__tests__/voice-leg-coordinator.test.ts +0 -229
  354. package/src/calls/__tests__/voice-progress-cadence.test.ts +0 -274
  355. package/src/calls/barge-in-guard.ts +0 -118
  356. package/src/calls/voice-leg-coordinator.ts +0 -189
  357. package/src/calls/voice-progress-cadence.ts +0 -423
  358. package/src/cli/commands/__tests__/apps.test.ts +0 -245
  359. package/src/cli/commands/__tests__/bash.test.ts +0 -53
  360. package/src/cli/commands/__tests__/roadmap.help.test.ts +0 -19
  361. package/src/cli/commands/channels/__tests__/send.test.ts +0 -218
  362. package/src/cli/commands/channels/send.ts +0 -128
  363. package/src/config/__tests__/platform-identity.test.ts +0 -255
  364. package/src/config/acp-agent-write.ts +0 -43
  365. package/src/config/acp-schema.test.ts +0 -81
  366. package/src/config/platform-identity.ts +0 -201
  367. package/src/config/schemas/__tests__/voice.test.ts +0 -148
  368. package/src/config/schemas/voice.ts +0 -150
  369. package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +0 -133
  370. package/src/daemon/app-change-notify.ts +0 -45
  371. package/src/desktop/__tests__/fake-desktop.ts +0 -119
  372. package/src/desktop/desktop-chrome-policy.test.ts +0 -71
  373. package/src/desktop/desktop-chrome-policy.ts +0 -42
  374. package/src/desktop/desktop-dependencies.test.ts +0 -102
  375. package/src/desktop/desktop-dependencies.ts +0 -306
  376. package/src/desktop/desktop-feature.test.ts +0 -18
  377. package/src/desktop/desktop-feature.ts +0 -19
  378. package/src/desktop/desktop-panel-config.test.ts +0 -135
  379. package/src/desktop/desktop-panel-config.ts +0 -149
  380. package/src/desktop/desktop-session-manager.test.ts +0 -627
  381. package/src/desktop/desktop-session-manager.ts +0 -814
  382. package/src/desktop/desktop-stream-bridge.test.ts +0 -395
  383. package/src/desktop/desktop-stream-bridge.ts +0 -214
  384. package/src/desktop/desktop-wallpaper.test.ts +0 -191
  385. package/src/desktop/desktop-wallpaper.ts +0 -113
  386. package/src/desktop/desktop-window-theme.ts +0 -170
  387. package/src/i18n/AGENTS.md +0 -22
  388. package/src/i18n/__tests__/i18n.test.ts +0 -108
  389. package/src/i18n/index.ts +0 -16
  390. package/src/i18n/locales.ts +0 -93
  391. package/src/i18n/messages.ts +0 -61
  392. package/src/i18n/title.ts +0 -25
  393. package/src/mcp/__tests__/workspace-mcp-config.test.ts +0 -135
  394. package/src/mcp/spec-schema.ts +0 -111
  395. package/src/mcp/workspace-mcp-config.ts +0 -188
  396. package/src/messaging/providers/__tests__/proactive-address.test.ts +0 -95
  397. package/src/persistence/conversation-title-placeholders.ts +0 -23
  398. package/src/persistence/message-cursor.ts +0 -78
  399. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +0 -149
  400. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +0 -118
  401. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +0 -83
  402. package/src/plugins/defaults/memory/hooks/message-deleted.ts +0 -21
  403. package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +0 -126
  404. package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +0 -79
  405. package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +0 -28
  406. package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +0 -9
  407. package/src/providers/gemini-thought-signature.test.ts +0 -63
  408. package/src/providers/gemini-thought-signature.ts +0 -44
  409. package/src/providers/inference/service-account-token.ts +0 -248
  410. package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +0 -613
  411. package/src/providers/openai/__tests__/google-thought-signature.test.ts +0 -235
  412. package/src/providers/openai/google-thought-signature.ts +0 -320
  413. package/src/runtime/__tests__/channel-send.test.ts +0 -443
  414. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +0 -89
  415. package/src/runtime/__tests__/live-voice-upgrade.test.ts +0 -58
  416. package/src/runtime/__tests__/runtime-ws-test-utils.ts +0 -72
  417. package/src/runtime/__tests__/watch-stream-upgrade.test.ts +0 -59
  418. package/src/runtime/channel-send.ts +0 -316
  419. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +0 -205
  420. package/src/runtime/routes/__tests__/channel-send-routes.test.ts +0 -127
  421. package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +0 -107
  422. package/src/runtime/routes/channel-send-routes.ts +0 -85
  423. package/src/runtime/routes/desktop-setup-routes.test.ts +0 -74
  424. package/src/runtime/routes/desktop-setup-routes.ts +0 -35
  425. package/src/security/__tests__/ces-http-record-backend.test.ts +0 -137
  426. package/src/security/ces-http-record-backend.ts +0 -120
  427. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +0 -60
  428. package/src/skills/workspace-skill-md-signature.ts +0 -50
  429. package/src/tools/acp/status.test.ts +0 -94
  430. package/src/tools/terminal/__tests__/sanitized-bash.test.ts +0 -57
  431. package/src/tools/terminal/sanitized-bash.ts +0 -105
  432. package/src/util/ca-bundle.ts +0 -13
  433. package/src/workspace/git-porcelain.ts +0 -66
  434. package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +0 -258
  435. package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +0 -78
  436. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +0 -214
  437. package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +0 -102
  438. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +0 -199
  439. /package/src/{calls → live-voice}/progress-phrases.ts +0 -0
@@ -43,7 +43,7 @@ import {
43
43
  deleteCredentialMetadata,
44
44
  getCredentialMetadata,
45
45
  getCredentialMetadataById,
46
- listCredentialRecordsLive,
46
+ listCredentialMetadata,
47
47
  } from "../../tools/credentials/metadata-store.js";
48
48
  import type { CredentialInjectionTemplate } from "../../tools/credentials/policy-types.js";
49
49
  import {
@@ -228,9 +228,6 @@ function assertNotPlatformManaged(
228
228
  }
229
229
  }
230
230
 
231
- const CREDENTIAL_STORE_UNREACHABLE =
232
- "Credential store is unreachable. Retry in a moment, or check that the credential vault is running.";
233
-
234
231
  // ---------------------------------------------------------------------------
235
232
  // Handlers
236
233
  // ---------------------------------------------------------------------------
@@ -238,14 +235,9 @@ const CREDENTIAL_STORE_UNREACHABLE =
238
235
  async function handleCredentialsList({ body }: RouteHandlerArgs) {
239
236
  const search = (body as { search?: string } | undefined)?.search;
240
237
 
241
- const live = await listCredentialRecordsLive();
242
- if (live.unreachable) {
243
- throw new InternalError(CREDENTIAL_STORE_UNREACHABLE);
244
- }
245
-
246
238
  // Platform-provisioned credentials are not the user's to act on, so they
247
239
  // never become a Settings row (and never a click-to-reveal).
248
- let allMetadata = live.records.filter(
240
+ let allMetadata = listCredentialMetadata().filter(
249
241
  (m) => !isPlatformManagedCredential(m.service, m.field),
250
242
  );
251
243
 
@@ -280,12 +272,7 @@ async function handleCredentialsList({ body }: RouteHandlerArgs) {
280
272
 
281
273
  const credentials = await Promise.all(
282
274
  allMetadata.map(async (m) => {
283
- const { value: secret, unreachable } = await getSecureKeyResultAsync(
284
- credentialKey(m.service, m.field),
285
- );
286
- if (unreachable) {
287
- throw new InternalError(CREDENTIAL_STORE_UNREACHABLE);
288
- }
275
+ const secret = await getSecureKeyAsync(credentialKey(m.service, m.field));
289
276
  const connection = connectionsByProvider.get(m.service);
290
277
  return buildCredentialOutput(m, secret, connection);
291
278
  }),
@@ -323,7 +310,9 @@ async function handleCredentialsInspect({ body }: RouteHandlerArgs) {
323
310
 
324
311
  if (!lookup.metadata && (secret == null || secret.length === 0)) {
325
312
  if (unreachable) {
326
- throw new InternalError(CREDENTIAL_STORE_UNREACHABLE);
313
+ throw new InternalError(
314
+ "Credential store is unreachable — ensure the assistant is running",
315
+ );
327
316
  }
328
317
  throw new BadRequestError("Credential not found");
329
318
  }
@@ -385,7 +374,9 @@ async function handleCredentialsReveal({ body, headers }: RouteHandlerArgs) {
385
374
 
386
375
  if (secret == null || secret.length === 0) {
387
376
  if (unreachable) {
388
- throw new InternalError(CREDENTIAL_STORE_UNREACHABLE);
377
+ throw new InternalError(
378
+ "Credential store is unreachable — ensure the assistant is running",
379
+ );
389
380
  }
390
381
  throw new BadRequestError("Credential not found");
391
382
  }
@@ -629,7 +620,7 @@ export const ROUTES: RouteDefinition[] = [
629
620
  },
630
621
  summary: "List all credentials with metadata",
631
622
  description:
632
- "Return credentials from the live credential vault, with OAuth connection info and platform-managed credentials. Fails if the vault is unreachable.",
623
+ "Return all stored credentials with metadata, OAuth connection info, and platform-managed credentials.",
633
624
  tags: ["credentials"],
634
625
  requestBody: z.object({
635
626
  search: z.string().optional().describe("Filter by substring match"),
@@ -0,0 +1,173 @@
1
+ /**
2
+ * IPC route for executing shell commands through the assistant process.
3
+ *
4
+ * The CLI sends the command over the IPC socket and receives a single
5
+ * response containing stdout, stderr, and the exit code.
6
+ *
7
+ * **Security**: Gated behind VELLUM_DEBUG=1. When debug mode is off (the
8
+ * default), the handler returns an error immediately so the CLI surfaces a
9
+ * clear rejection instead of hanging. The assistant must be restarted with
10
+ * VELLUM_DEBUG=1 for this route to execute commands.
11
+ */
12
+
13
+ import { spawn } from "node:child_process";
14
+
15
+ import { z } from "zod";
16
+
17
+ import { getIsContainerized } from "../../config/env-registry.js";
18
+ import { buildSanitizedEnv } from "../../tools/terminal/safe-env.js";
19
+ import { getWorkspaceDir } from "../../util/platform.js";
20
+ import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
21
+ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
22
+
23
+ const DEFAULT_TIMEOUT_MS = 30_000;
24
+
25
+ function isDebugMode(): boolean {
26
+ return (
27
+ process.env.VELLUM_DEBUG === "1" || process.env.VELLUM_DEBUG === "true"
28
+ );
29
+ }
30
+
31
+ interface DebugBashResult {
32
+ stdout: string;
33
+ stderr: string;
34
+ exitCode: number | null;
35
+ timedOut: boolean;
36
+ error?: string;
37
+ }
38
+
39
+ function handleDebugBash({ body }: RouteHandlerArgs): Promise<DebugBashResult> {
40
+ if (getIsContainerized()) {
41
+ return Promise.resolve({
42
+ stdout: "",
43
+ stderr: "",
44
+ exitCode: null,
45
+ timedOut: false,
46
+ error: "debug bash is not available in containerized environments",
47
+ });
48
+ }
49
+
50
+ if (!isDebugMode()) {
51
+ return Promise.resolve({
52
+ stdout: "",
53
+ stderr: "",
54
+ exitCode: null,
55
+ timedOut: false,
56
+ error:
57
+ "Bash debug execution is disabled. The running assistant process must have been started with VELLUM_DEBUG=1 (setting it on the CLI command alone is not enough). Restart the assistant with: vellum sleep && VELLUM_DEBUG=1 vellum wake",
58
+ });
59
+ }
60
+
61
+ const { command, timeoutMs } = body as {
62
+ command?: string;
63
+ timeoutMs?: number;
64
+ };
65
+
66
+ if (!command || typeof command !== "string") {
67
+ return Promise.resolve({
68
+ stdout: "",
69
+ stderr: "",
70
+ exitCode: null,
71
+ timedOut: false,
72
+ error: "command is required",
73
+ });
74
+ }
75
+
76
+ const effectiveTimeout =
77
+ typeof timeoutMs === "number" && timeoutMs > 0
78
+ ? timeoutMs
79
+ : DEFAULT_TIMEOUT_MS;
80
+
81
+ return new Promise<DebugBashResult>((resolve) => {
82
+ const stdoutChunks: Buffer[] = [];
83
+ const stderrChunks: Buffer[] = [];
84
+ let timedOut = false;
85
+ let settled = false;
86
+
87
+ const finish = (result: DebugBashResult) => {
88
+ if (settled) {
89
+ return;
90
+ }
91
+ settled = true;
92
+ resolve(result);
93
+ };
94
+
95
+ const child = spawn("bash", ["-c", command], {
96
+ cwd: getWorkspaceDir(),
97
+ stdio: ["ignore", "pipe", "pipe"],
98
+ detached: true,
99
+ env: buildSanitizedEnv(),
100
+ windowsHide: true,
101
+ });
102
+
103
+ const timer = setTimeout(() => {
104
+ timedOut = true;
105
+ try {
106
+ process.kill(-child.pid!, "SIGKILL");
107
+ } catch {
108
+ // Process group may have already exited.
109
+ }
110
+ }, effectiveTimeout);
111
+
112
+ child.stdout.on("data", (data: Buffer) => {
113
+ stdoutChunks.push(data);
114
+ });
115
+
116
+ child.stderr.on("data", (data: Buffer) => {
117
+ stderrChunks.push(data);
118
+ });
119
+
120
+ child.on("close", (code) => {
121
+ clearTimeout(timer);
122
+ finish({
123
+ stdout: Buffer.concat(stdoutChunks).toString(),
124
+ stderr: Buffer.concat(stderrChunks).toString(),
125
+ exitCode: code,
126
+ timedOut,
127
+ });
128
+ });
129
+
130
+ child.on("error", (err) => {
131
+ clearTimeout(timer);
132
+ finish({
133
+ stdout: "",
134
+ stderr: "",
135
+ exitCode: null,
136
+ timedOut: false,
137
+ error: err.message,
138
+ });
139
+ });
140
+ });
141
+ }
142
+
143
+ export const ROUTES: RouteDefinition[] = [
144
+ {
145
+ operationId: "debug_bash",
146
+ endpoint: "debug/bash",
147
+ method: "POST",
148
+ policy: {
149
+ requiredScopes: ["settings.write"],
150
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
151
+ },
152
+ requireGuardian: false,
153
+ summary: "Execute a shell command in the assistant process",
154
+ description:
155
+ "Developer debugging tool. Requires the assistant to be running with VELLUM_DEBUG=1.",
156
+ tags: ["debug"],
157
+ requestBody: z.object({
158
+ command: z.string().describe("Shell command to execute via bash -c"),
159
+ timeoutMs: z
160
+ .number()
161
+ .optional()
162
+ .describe("Execution timeout in milliseconds (default: 30000)"),
163
+ }),
164
+ responseBody: z.object({
165
+ stdout: z.string(),
166
+ stderr: z.string(),
167
+ exitCode: z.number().nullable(),
168
+ timedOut: z.boolean(),
169
+ error: z.string().optional(),
170
+ }),
171
+ handler: handleDebugBash,
172
+ },
173
+ ];
@@ -22,7 +22,6 @@ import {
22
22
  getConfiguredProvider,
23
23
  userMessage,
24
24
  } from "../../providers/provider-send-message.js";
25
- import { isMaxTokensStopReason } from "../../providers/stop-reasons.js";
26
25
  import { getLogger } from "../../util/logger.js";
27
26
  import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
28
27
  import { BadRequestError } from "./errors.js";
@@ -177,44 +176,9 @@ function buildCommandPrompt(body: DictationBody, stylePrompt?: string): string {
177
176
  return sections.join("\n");
178
177
  }
179
178
 
180
- export function computeMaxTokens(inputLength: number): number {
179
+ function computeMaxTokens(inputLength: number): number {
181
180
  const estimatedInputTokens = Math.ceil(inputLength / 3);
182
- // The cleanup tool call carries the whole transcript back in its `text`
183
- // argument, plus a `reasoning` string and the JSON scaffolding around both,
184
- // so the budget has to cover well more than the input alone. `max_tokens` is
185
- // a ceiling rather than a target: a call that stops short of it costs no
186
- // extra latency.
187
- return Math.max(512, estimatedInputTokens * 2 + 256);
188
- }
189
-
190
- export type CleanupRejection = "truncated";
191
-
192
- /**
193
- * Decide whether the cleanup model's rewrite is safe to use as the payload.
194
- *
195
- * The rewrite replaces what the user actually said. A token-cap stop means the
196
- * tool JSON was cut mid-argument, so however complete the `text` argument
197
- * happens to look, it is a fragment; the raw transcript is the safer payload
198
- * then. Unpolished beats wrong.
199
- *
200
- * Whether a shorter rewrite still preserved the meaning is the model's call
201
- * (the prompt asks it to drop fillers and tighten phrasing), so there is no
202
- * length check here: a deterministic ratio cannot tell a concise cleanup from
203
- * a summary.
204
- */
205
- export function resolveCleanedDictation(
206
- raw: string,
207
- cleaned: string,
208
- stopReason: string | null | undefined,
209
- ): { text: string; rejected: CleanupRejection | null } {
210
- const trimmed = cleaned.trim();
211
- if (!trimmed) {
212
- return { text: raw, rejected: null };
213
- }
214
- if (isMaxTokensStopReason(stopReason)) {
215
- return { text: raw, rejected: "truncated" };
216
- }
217
- return { text: trimmed, rejected: null };
181
+ return Math.max(256, estimatedInputTokens + 128);
218
182
  }
219
183
 
220
184
  interface DictationResult {
@@ -365,23 +329,7 @@ async function handleDictation(body: DictationBody): Promise<DictationResult> {
365
329
  ...profileMeta,
366
330
  };
367
331
  }
368
- const { text: cleanedText, rejected } = resolveCleanedDictation(
369
- transcription,
370
- input.text ?? "",
371
- response.stopReason,
372
- );
373
- if (rejected) {
374
- // Lengths only -- transcript content must never be logged.
375
- log.warn(
376
- {
377
- rejected,
378
- stopReason: response.stopReason,
379
- rawChars: transcription.length,
380
- cleanedChars: input.text?.trim().length ?? 0,
381
- },
382
- "Dictation cleanup rejected, using raw transcription",
383
- );
384
- }
332
+ const cleanedText = input.text?.trim() || transcription;
385
333
  const normalizedText = applyDictionary(cleanedText, profile.dictionary);
386
334
  return {
387
335
  text: normalizedText,
@@ -39,7 +39,6 @@ import { ROUTES as CALL_ROUTES } from "./call-routes.js";
39
39
  import { ROUTES as CHANNEL_AVAILABILITY_ROUTES } from "./channel-availability-routes.js";
40
40
  import { ROUTES as CHANNEL_READINESS_ROUTES } from "./channel-readiness-routes.js";
41
41
  import { CHANNEL_ROUTES } from "./channel-route-definitions.js";
42
- import { ROUTES as CHANNEL_SEND_ROUTES } from "./channel-send-routes.js";
43
42
  import { ROUTES as CHANNEL_VERIFICATION_ROUTES } from "./channel-verification-routes.js";
44
43
  import { ROUTES as CHATGPT_SUBSCRIPTION_AUTH_ROUTES } from "./chatgpt-subscription-auth-routes.js";
45
44
  import { ROUTES as CLIENT_ROUTES } from "./client-routes.js";
@@ -59,10 +58,10 @@ import { ROUTES as CONVERSATIONS_IMPORT_ROUTES } from "./conversations-import-ro
59
58
  import { ROUTES as CREDENTIAL_PROMPT_ROUTES } from "./credential-prompt-routes.js";
60
59
  import { ROUTES as CREDENTIAL_REQUEST_ROUTES } from "./credential-request-routes.js";
61
60
  import { ROUTES as CREDENTIAL_ROUTES } from "./credential-routes.js";
61
+ import { ROUTES as DEBUG_BASH_ROUTES } from "./debug-bash-routes.js";
62
62
  import { ROUTES as DEBUG_ROUTES } from "./debug-routes.js";
63
63
  import { ROUTES as DEFAULT_PROVIDER_ROUTES } from "./default-provider-routes.js";
64
64
  import { ROUTES as DEFER_ROUTES } from "./defer-routes.js";
65
- import { ROUTES as DESKTOP_SETUP_ROUTES } from "./desktop-setup-routes.js";
66
65
  import { ROUTES as DIAGNOSTICS_ROUTES } from "./diagnostics-routes.js";
67
66
  import { ROUTES as DISK_PRESSURE_ROUTES } from "./disk-pressure-routes.js";
68
67
  import { ROUTES as DOCUMENT_COMMENT_ROUTES } from "./document-comments-routes.js";
@@ -192,7 +191,6 @@ export const ROUTES: RouteDefinition[] = [
192
191
  ...CHANNEL_VERIFICATION_ROUTES,
193
192
  ...CHANNEL_AVAILABILITY_ROUTES,
194
193
  ...CHANNEL_READINESS_ROUTES,
195
- ...CHANNEL_SEND_ROUTES,
196
194
  ...BROWSER_ROUTES,
197
195
  ...BROWSER_TABS_ROUTES,
198
196
  ...BTW_ROUTES,
@@ -217,9 +215,9 @@ export const ROUTES: RouteDefinition[] = [
217
215
  ...CONVERSATION_QUERY_ROUTES,
218
216
  ...CONVERSATION_STARTER_ROUTES,
219
217
  ...ACTIVATION_ROUTES,
218
+ ...DEBUG_BASH_ROUTES,
220
219
  ...DEBUG_ROUTES,
221
220
  ...DEFAULT_PROVIDER_ROUTES,
222
- ...DESKTOP_SETUP_ROUTES,
223
221
  ...DIAGNOSTICS_ROUTES,
224
222
  ...DISK_PRESSURE_ROUTES,
225
223
  ...RESOURCE_PRESSURE_ROUTES,
@@ -22,7 +22,6 @@ import { join } from "node:path";
22
22
  import { and, desc, eq, gte, lte } from "drizzle-orm";
23
23
  import { z } from "zod";
24
24
 
25
- import { overlayWorkspaceMcpForConfigRead } from "../../mcp/workspace-mcp-config.js";
26
25
  import { getDb, getLogsDb } from "../../persistence/db-connection.js";
27
26
  import {
28
27
  llmRequestLogs,
@@ -569,7 +568,6 @@ function readSanitizedConfig(): Record<string, unknown> | undefined {
569
568
  }
570
569
  }
571
570
 
572
- overlayWorkspaceMcpForConfigRead(config);
573
571
  const mcpServers = asRecord(asRecord(config.mcp)?.servers);
574
572
  for (const server of Object.values(mcpServers ?? {})) {
575
573
  const transport = asRecord(asRecord(server)?.transport);
@@ -14,7 +14,8 @@
14
14
 
15
15
  import { z } from "zod";
16
16
 
17
- import type { McpServerConfig } from "../../config/schemas/mcp.js";
17
+ import { loadRawConfig, saveRawConfig } from "../../config/loader.js";
18
+ import type { McpConfig, McpServerConfig } from "../../config/schemas/mcp.js";
18
19
  import { estimateToolDefinitionTokens } from "../../context/token-estimator.js";
19
20
  import { reloadMcpServers } from "../../daemon/mcp-reload-service.js";
20
21
  import { McpClient } from "../../mcp/client.js";
@@ -30,10 +31,6 @@ import {
30
31
  deleteMcpOAuthCredentials,
31
32
  hasMcpOAuthTokens,
32
33
  } from "../../mcp/mcp-oauth-provider.js";
33
- import {
34
- loadWorkspaceMcpConfig,
35
- saveWorkspaceMcpConfig,
36
- } from "../../mcp/workspace-mcp-config.js";
37
34
  import { readPluginMcpServers } from "../../plugins/mcp-servers.js";
38
35
  import { getMcpToolsByServer } from "../../tools/registry.js";
39
36
  import { getLogger } from "../../util/logger.js";
@@ -68,18 +65,6 @@ const McpAddParams = z.object({
68
65
 
69
66
  const McpRemoveParams = z.object({ name: z.string() });
70
67
 
71
- function persistWorkspaceMcpConfig(config: {
72
- servers: Record<string, McpServerConfig>;
73
- }): void {
74
- try {
75
- saveWorkspaceMcpConfig(config);
76
- } catch (err) {
77
- throw new InternalError(
78
- err instanceof Error ? err.message : String(err),
79
- );
80
- }
81
- }
82
-
83
68
  async function handleMcpAuthStart({
84
69
  body,
85
70
  }: {
@@ -91,7 +76,8 @@ async function handleMcpAuthStart({
91
76
  }> {
92
77
  const { serverId } = parseBody(McpServerIdParams, body);
93
78
 
94
- const servers = loadWorkspaceMcpConfig().servers;
79
+ const raw = loadRawConfig();
80
+ const servers = (raw.mcp as Partial<McpConfig> | undefined)?.servers ?? {};
95
81
  const serverConfig = servers[serverId];
96
82
 
97
83
  if (!serverConfig) {
@@ -267,7 +253,9 @@ function detectAuthType(headers: Record<string, string>): "bearer" | "api-key" {
267
253
  async function handleMcpList(_args: {
268
254
  body?: Record<string, unknown>;
269
255
  }): Promise<{ servers: McpServerEntry[] }> {
270
- const servers = loadWorkspaceMcpConfig().servers;
256
+ const raw = loadRawConfig();
257
+ const mcpConfig = raw.mcp as Partial<McpConfig> | undefined;
258
+ const servers = mcpConfig?.servers ?? {};
271
259
  const configEntries = (
272
260
  Object.entries(servers) as [string, McpServerConfig][]
273
261
  ).filter(([, config]) => config && typeof config === "object");
@@ -446,13 +434,18 @@ async function handleMcpUpdate({
446
434
  }): Promise<{ updated: true }> {
447
435
  const { name, headers } = parseBody(McpUpdateParams, body);
448
436
 
449
- const servers = loadWorkspaceMcpConfig().servers;
450
- const server = servers[name];
437
+ const raw = loadRawConfig();
438
+ const mcpConfig = raw.mcp as Record<string, unknown> | undefined;
439
+ const serverMap = mcpConfig?.servers as
440
+ | Record<string, Record<string, unknown>>
441
+ | undefined;
451
442
 
452
- if (!server) {
443
+ if (!serverMap || !serverMap[name]) {
453
444
  throw new NotFoundError(`MCP server "${name}" not found.`);
454
445
  }
455
446
 
447
+ const server = serverMap[name];
448
+
456
449
  if (headers !== undefined) {
457
450
  const transport = server.transport as Record<string, unknown> | undefined;
458
451
  if (
@@ -481,7 +474,7 @@ async function handleMcpUpdate({
481
474
  }
482
475
  }
483
476
 
484
- persistWorkspaceMcpConfig({ servers });
477
+ saveRawConfig(raw);
485
478
  triggerReload("internal_mcp_update");
486
479
 
487
480
  return { updated: true };
@@ -501,7 +494,7 @@ async function handleMcpAdd({
501
494
  body,
502
495
  );
503
496
 
504
- let transport: McpServerConfig["transport"];
497
+ let transport: Record<string, unknown>;
505
498
  switch (transportType) {
506
499
  case "stdio":
507
500
  if (!command) {
@@ -524,16 +517,27 @@ async function handleMcpAdd({
524
517
  );
525
518
  }
526
519
 
527
- const servers = { ...loadWorkspaceMcpConfig().servers };
520
+ const raw = loadRawConfig();
521
+ if (!raw.mcp) {
522
+ raw.mcp = { servers: {} };
523
+ }
524
+ const mcpConfig = raw.mcp as Record<string, unknown>;
525
+ if (!mcpConfig.servers) {
526
+ mcpConfig.servers = {};
527
+ }
528
+ const serverMap = mcpConfig.servers as Record<string, unknown>;
528
529
 
529
- if (servers[name]) {
530
+ if (serverMap[name]) {
530
531
  throw new BadRequestError(
531
532
  `MCP server "${name}" already exists. Remove it first with: assistant mcp remove ${name}`,
532
533
  );
533
534
  }
534
535
 
535
- servers[name] = { transport };
536
+ serverMap[name] = {
537
+ transport,
538
+ };
536
539
 
540
+ // Store auth headers in credential store, not config
537
541
  if (headers && Object.keys(headers).length > 0) {
538
542
  const ok = await setMcpHeaders(name, headers);
539
543
  if (!ok) {
@@ -543,7 +547,7 @@ async function handleMcpAdd({
543
547
  }
544
548
  }
545
549
 
546
- persistWorkspaceMcpConfig({ servers });
550
+ saveRawConfig(raw);
547
551
  triggerReload("internal_mcp_add");
548
552
 
549
553
  return { added: true };
@@ -560,7 +564,8 @@ async function handleMcpAuthRevoke({
560
564
  }): Promise<{ revoked: true }> {
561
565
  const { serverId } = parseBody(McpServerIdParams, body);
562
566
 
563
- const servers = loadWorkspaceMcpConfig().servers;
567
+ const raw = loadRawConfig();
568
+ const servers = (raw.mcp as Partial<McpConfig> | undefined)?.servers ?? {};
564
569
  const serverConfig = servers[serverId];
565
570
 
566
571
  if (!serverConfig) {
@@ -597,29 +602,32 @@ async function handleMcpRemove({
597
602
  }): Promise<{ removed: true }> {
598
603
  const { name } = parseBody(McpRemoveParams, body);
599
604
 
600
- const servers = { ...loadWorkspaceMcpConfig().servers };
601
- const serverConfig = servers[name];
605
+ const raw = loadRawConfig();
606
+ const mcpConfig = raw.mcp as Record<string, unknown> | undefined;
607
+ const serverMap = mcpConfig?.servers as Record<string, unknown> | undefined;
602
608
 
603
- if (!serverConfig) {
609
+ if (!serverMap || !serverMap[name]) {
604
610
  throw new NotFoundError(`MCP server "${name}" not found.`);
605
611
  }
606
612
 
607
- if (
608
- serverConfig.transport.type === "sse" ||
609
- serverConfig.transport.type === "streamable-http"
610
- ) {
613
+ // Best-effort cleanup of credentials stored for this server
614
+ const serverConfig = serverMap[name] as Record<string, unknown>;
615
+ const transport = serverConfig?.transport as
616
+ | Record<string, unknown>
617
+ | undefined;
618
+ if (transport?.type === "sse" || transport?.type === "streamable-http") {
611
619
  try {
612
620
  await Promise.all([
613
621
  deleteMcpOAuthCredentials(name),
614
622
  deleteMcpHeaders(name),
615
623
  ]);
616
624
  } catch {
617
- // Credentials may not exist.
625
+ // Ignore — credentials may not exist
618
626
  }
619
627
  }
620
628
 
621
- delete servers[name];
622
- persistWorkspaceMcpConfig({ servers });
629
+ delete serverMap[name];
630
+ saveRawConfig(raw);
623
631
  triggerReload("internal_mcp_remove");
624
632
 
625
633
  return { removed: true };
@@ -22,8 +22,8 @@ import { PassThrough, Readable } from "node:stream";
22
22
 
23
23
  import { z } from "zod";
24
24
 
25
+ import { getPlatformAssistantId } from "../../config/env.js";
25
26
  import { invalidateConfigCache } from "../../config/loader.js";
26
- import { resolvePlatformAssistantId } from "../../config/platform-identity.js";
27
27
  import { getAssistantName } from "../../daemon/identity-helpers.js";
28
28
  import { runAsyncSqlite } from "../../persistence/db-async-query.js";
29
29
  import {
@@ -236,14 +236,28 @@ interface ExportManifestInputs {
236
236
  /**
237
237
  * Resolve the `assistant.id` for an export.
238
238
  *
239
- * In-memory identity (validate rehydration or secret-routes). The schema
240
- * requires `id` to be non-empty, so we fall back to
239
+ * Mirrors `platform/client.ts`'s precedence: in-memory override (set at
240
+ * daemon startup or by secret-routes) → credential store → daemon-internal
241
+ * fallback. The schema requires `id` to be non-empty, so we fall back to
241
242
  * `DAEMON_INTERNAL_ASSISTANT_ID` rather than the empty string.
242
243
  */
243
244
  async function resolveAssistantId(): Promise<string> {
244
- const resolved = await resolvePlatformAssistantId();
245
- if (resolved) {
246
- return resolved;
245
+ const inMemory = getPlatformAssistantId();
246
+ if (inMemory) {
247
+ return inMemory;
248
+ }
249
+ try {
250
+ const stored = await getSecureKeyAsync(
251
+ credentialKey("vellum", "platform_assistant_id"),
252
+ );
253
+ if (stored) {
254
+ return stored;
255
+ }
256
+ } catch (err) {
257
+ log.warn(
258
+ { err },
259
+ "Failed to read platform_assistant_id from credential store; falling back to daemon-internal id",
260
+ );
247
261
  }
248
262
  return DAEMON_INTERNAL_ASSISTANT_ID;
249
263
  }
@@ -39,17 +39,7 @@ import {
39
39
  } from "@vellumai/service-contracts/platform-credential";
40
40
  import { z } from "zod";
41
41
 
42
- import {
43
- setPlatformAssistantId,
44
- setPlatformBaseUrl,
45
- setPlatformOrganizationId,
46
- setPlatformUserId,
47
- } from "../../config/env.js";
48
42
  import { isPlatformRemote } from "../../config/env-registry.js";
49
- import {
50
- resolvePlatformOrganizationId,
51
- resolvePlatformUserId,
52
- } from "../../config/platform-identity.js";
53
43
  import {
54
44
  registerCallbackRoute,
55
45
  resolvePlatformCallbackRegistrationContext,
@@ -299,12 +289,24 @@ async function handlePlatformStatus(
299
289
  ): Promise<PlatformStatusResponse> {
300
290
  const context = await resolvePlatformCallbackRegistrationContext();
301
291
 
302
- const [organizationId, userId, webhookSecretRaw] = await Promise.all([
303
- resolvePlatformOrganizationId(),
304
- resolvePlatformUserId(),
292
+ const [orgIdRaw, userIdRaw, webhookSecretRaw] = await Promise.all([
293
+ getSecureKeyAsync(
294
+ credentialKey(
295
+ CREDENTIAL_KEYS.organizationId.service,
296
+ CREDENTIAL_KEYS.organizationId.field,
297
+ ),
298
+ ),
299
+ getSecureKeyAsync(
300
+ credentialKey(
301
+ CREDENTIAL_KEYS.userId.service,
302
+ CREDENTIAL_KEYS.userId.field,
303
+ ),
304
+ ),
305
305
  getSecureKeyAsync(credentialKey("vellum", "webhook_secret")),
306
306
  ]);
307
307
 
308
+ const organizationId = orgIdRaw?.trim() ?? "";
309
+ const userId = userIdRaw?.trim() ?? "";
308
310
  const hasWebhookSecret = !!webhookSecretRaw;
309
311
 
310
312
  return {
@@ -465,11 +467,6 @@ async function handlePlatformDisconnect(
465
467
  );
466
468
  }
467
469
 
468
- setPlatformBaseUrl(undefined);
469
- setPlatformAssistantId(undefined);
470
- setPlatformOrganizationId(undefined);
471
- setPlatformUserId(undefined);
472
-
473
470
  // Notify connected clients
474
471
  broadcastMessage({ type: "platform_disconnected" });
475
472