@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
@@ -1,93 +0,0 @@
1
- /**
2
- * Locales the daemon can resolve user-facing copy into.
3
- *
4
- * Keep this set aligned with `clients/web/src/i18n/supported-locales.ts`.
5
- * A locale that exists only here cannot be requested by the web app; a
6
- * locale that exists only there cannot be resolved for CLI or HTTP
7
- * consumers that go through this module.
8
- */
9
-
10
- export const DEFAULT_LOCALE = "en";
11
-
12
- export const SUPPORTED_LOCALES = ["en", "es", "ru", "zh", "zh-TW"] as const;
13
-
14
- export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];
15
-
16
- export function isSupportedLocale(value: unknown): value is SupportedLocale {
17
- return (
18
- typeof value === "string" &&
19
- (SUPPORTED_LOCALES as readonly string[]).includes(value)
20
- );
21
- }
22
-
23
- /**
24
- * Pick the best shipped locale for an ordered list of preferred BCP 47 tags.
25
- *
26
- * Full tag first, then the primary language subtag, so `es-MX` resolves to
27
- * `es`. `zh-Hant` / `zh-HK` / `zh-MO` map to `zh-TW`.
28
- */
29
- export function negotiateLocale(preferred: readonly string[]): SupportedLocale {
30
- for (const tag of preferred) {
31
- const normalized = tag.trim();
32
- if (normalized === "") {
33
- continue;
34
- }
35
- const exact = SUPPORTED_LOCALES.find(
36
- (locale) => locale.toLowerCase() === normalized.toLowerCase(),
37
- );
38
- if (exact) {
39
- return exact;
40
- }
41
- const lower = normalized.toLowerCase();
42
- if (
43
- lower === "zh-hant" ||
44
- lower.startsWith("zh-hant-") ||
45
- lower === "zh-hk" ||
46
- lower === "zh-mo"
47
- ) {
48
- return "zh-TW";
49
- }
50
- const base = normalized.split("-")[0]?.toLowerCase();
51
- const baseMatched = SUPPORTED_LOCALES.find(
52
- (locale) => locale.toLowerCase() === base,
53
- );
54
- if (baseMatched) {
55
- return baseMatched;
56
- }
57
- }
58
- return DEFAULT_LOCALE;
59
- }
60
-
61
- /**
62
- * Parse an `Accept-Language` header into preference order and negotiate.
63
- *
64
- * Quality values are honored; the header is a hint, not a required input.
65
- * Missing or empty headers resolve to {@link DEFAULT_LOCALE}.
66
- */
67
- export function localeFromAcceptLanguage(
68
- header: string | null | undefined,
69
- ): SupportedLocale {
70
- if (header == null || header.trim() === "") {
71
- return DEFAULT_LOCALE;
72
- }
73
- const tags = header
74
- .split(",")
75
- .map((part) => {
76
- const [tag, ...params] = part.trim().split(";");
77
- let quality = 1;
78
- for (const param of params) {
79
- const [name, value] = param.trim().split("=");
80
- if (name === "q" && value !== undefined) {
81
- const parsed = Number.parseFloat(value);
82
- if (Number.isFinite(parsed)) {
83
- quality = parsed;
84
- }
85
- }
86
- }
87
- return { tag: tag?.trim() ?? "", quality };
88
- })
89
- .filter((entry) => entry.tag.length > 0)
90
- .sort((a, b) => b.quality - a.quality)
91
- .map((entry) => entry.tag);
92
- return negotiateLocale(tags);
93
- }
@@ -1,61 +0,0 @@
1
- /**
2
- * Daemon message catalog.
3
- *
4
- * Keys are the stable identity of a hardcoded constant. English is the
5
- * source language. Add a key here, then add the same key to every locale
6
- * catalog. A key present in a translated catalog but missing from English
7
- * is a test failure.
8
- *
9
- * Persist the key when a column holds a system constant. Never persist a
10
- * translated string, and never treat a stored display string as a key:
11
- * a user title may be in any language.
12
- */
13
-
14
- import {
15
- DEFAULT_LOCALE,
16
- type SupportedLocale,
17
- } from "./locales.js";
18
-
19
- export const MESSAGE_KEYS = {
20
- CONVERSATION_TITLE_GENERATING: "conversation.title.generating",
21
- CONVERSATION_TITLE_UNTITLED: "conversation.title.untitled",
22
- } as const;
23
-
24
- export type MessageKey = (typeof MESSAGE_KEYS)[keyof typeof MESSAGE_KEYS];
25
-
26
- export const MESSAGE_CATALOGS: Record<
27
- SupportedLocale,
28
- Record<MessageKey, string>
29
- > = {
30
- en: {
31
- "conversation.title.generating": "Generating title...",
32
- "conversation.title.untitled": "Untitled Conversation",
33
- },
34
- es: {
35
- "conversation.title.generating": "Generando título...",
36
- "conversation.title.untitled": "Sin título",
37
- },
38
- ru: {
39
- "conversation.title.generating": "Создание названия...",
40
- "conversation.title.untitled": "Без названия",
41
- },
42
- zh: {
43
- "conversation.title.generating": "标题生成中...",
44
- "conversation.title.untitled": "无标题",
45
- },
46
- "zh-TW": {
47
- "conversation.title.generating": "標題產生中...",
48
- "conversation.title.untitled": "未命名",
49
- },
50
- };
51
-
52
- export function t(
53
- key: MessageKey,
54
- locale: SupportedLocale = DEFAULT_LOCALE,
55
- ): string {
56
- return MESSAGE_CATALOGS[locale][key] ?? MESSAGE_CATALOGS[DEFAULT_LOCALE][key];
57
- }
58
-
59
- export function isMessageKey(value: string): value is MessageKey {
60
- return (Object.values(MESSAGE_KEYS) as string[]).includes(value);
61
- }
package/src/i18n/title.ts DELETED
@@ -1,25 +0,0 @@
1
- /**
2
- * Resolve a conversation title for a locale.
3
- *
4
- * A stored message key (or an empty title) is a hardcoded constant and
5
- * resolves through the catalog. Any other stored string is user or model
6
- * copy and passes through, including English placeholders written before
7
- * keys were persisted.
8
- */
9
-
10
- import { DEFAULT_LOCALE, type SupportedLocale } from "./locales.js";
11
- import { isMessageKey, MESSAGE_KEYS, t } from "./messages.js";
12
-
13
- export function resolveConversationTitle(
14
- title: string | null | undefined,
15
- locale: SupportedLocale = DEFAULT_LOCALE,
16
- ): string {
17
- const trimmed = title?.trim() ?? "";
18
- if (trimmed === "") {
19
- return t(MESSAGE_KEYS.CONVERSATION_TITLE_UNTITLED, locale);
20
- }
21
- if (isMessageKey(trimmed)) {
22
- return t(trimmed, locale);
23
- }
24
- return trimmed;
25
- }
@@ -1,135 +0,0 @@
1
- import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { beforeEach, describe, expect, test } from "bun:test";
4
-
5
- import { AGENT_PLUGINS_MCP_SCHEMA_URL } from "../spec-schema.js";
6
- import {
7
- loadWorkspaceMcpConfig,
8
- overlayWorkspaceMcpForConfigRead,
9
- readWorkspaceMcpFile,
10
- saveWorkspaceMcpConfig,
11
- } from "../workspace-mcp-config.js";
12
-
13
- function mcpPath(): string {
14
- return join(process.env.VELLUM_WORKSPACE_DIR!, "mcp.json");
15
- }
16
-
17
- describe("workspace mcp.json", () => {
18
- beforeEach(() => {
19
- mkdirSync(process.env.VELLUM_WORKSPACE_DIR!, { recursive: true });
20
- rmSync(mcpPath(), { force: true });
21
- });
22
-
23
- test("missing file is an empty server map", () => {
24
- expect(loadWorkspaceMcpConfig()).toEqual({ servers: {} });
25
- expect(readWorkspaceMcpFile().fileState).toBe("missing");
26
- });
27
-
28
- test("round-trips a spec document without wrapping transport", () => {
29
- saveWorkspaceMcpConfig({
30
- servers: {
31
- remote: {
32
- transport: {
33
- type: "streamable-http",
34
- url: "https://example.com/mcp",
35
- },
36
- },
37
- local: {
38
- transport: {
39
- type: "stdio",
40
- command: "npx",
41
- args: ["-y", "srv"],
42
- },
43
- },
44
- },
45
- });
46
-
47
- expect(JSON.parse(readFileSync(mcpPath(), "utf8"))).toEqual({
48
- $schema: AGENT_PLUGINS_MCP_SCHEMA_URL,
49
- mcpServers: {
50
- remote: {
51
- type: "streamable-http",
52
- url: "https://example.com/mcp",
53
- },
54
- local: {
55
- type: "stdio",
56
- command: "npx",
57
- args: ["-y", "srv"],
58
- },
59
- },
60
- });
61
- expect(loadWorkspaceMcpConfig()).toEqual({
62
- servers: {
63
- remote: {
64
- transport: {
65
- type: "streamable-http",
66
- url: "https://example.com/mcp",
67
- },
68
- },
69
- local: {
70
- transport: {
71
- type: "stdio",
72
- command: "npx",
73
- args: ["-y", "srv"],
74
- },
75
- },
76
- },
77
- });
78
- });
79
-
80
- test("does not persist transport headers", () => {
81
- saveWorkspaceMcpConfig({
82
- servers: {
83
- remote: {
84
- transport: {
85
- type: "streamable-http",
86
- url: "https://example.com/mcp",
87
- headers: { Authorization: "Bearer secret" },
88
- },
89
- },
90
- },
91
- });
92
-
93
- const onDisk = readFileSync(mcpPath(), "utf8");
94
- expect(onDisk).not.toContain("secret");
95
- expect(loadWorkspaceMcpConfig().servers.remote?.transport).toEqual({
96
- type: "streamable-http",
97
- url: "https://example.com/mcp",
98
- });
99
- });
100
-
101
- test("invalid file does not throw on read and refuses a later write", () => {
102
- mkdirSync(process.env.VELLUM_WORKSPACE_DIR!, { recursive: true });
103
- writeFileSync(mcpPath(), "{ not json");
104
-
105
- expect(loadWorkspaceMcpConfig()).toEqual({ servers: {} });
106
- expect(readWorkspaceMcpFile().fileState).toBe("invalid");
107
- expect(() => saveWorkspaceMcpConfig({ servers: {} })).toThrow(/invalid JSON/);
108
- });
109
-
110
- test("overlay projects transport-only servers for config reads", () => {
111
- saveWorkspaceMcpConfig({
112
- servers: {
113
- remote: {
114
- transport: {
115
- type: "streamable-http",
116
- url: "https://example.com/mcp",
117
- },
118
- },
119
- },
120
- });
121
-
122
- const config: Record<string, unknown> = { llm: { activeProfile: "balanced" } };
123
- overlayWorkspaceMcpForConfigRead(config);
124
- expect(config.mcp).toEqual({
125
- servers: {
126
- remote: {
127
- transport: {
128
- type: "streamable-http",
129
- url: "https://example.com/mcp",
130
- },
131
- },
132
- },
133
- });
134
- });
135
- });
@@ -1,111 +0,0 @@
1
- /**
2
- * Agent Plugins 1.0.0 `mcp.json` wire schema and projections onto the
3
- * assistant's in-memory `McpTransport` union.
4
- *
5
- * Workspace `/workspace/mcp.json` and each plugin's root `mcp.json` share
6
- * this document shape. Origin (`workspace` vs `plugin`) is resolved from
7
- * which file was read, never from a field in the file.
8
- */
9
-
10
- import { z } from "zod";
11
-
12
- import type { McpTransport } from "../config/schemas/mcp.js";
13
-
14
- /** Canonical `$schema` value for an Agent Plugins 1.0.0 MCP document. */
15
- export const AGENT_PLUGINS_MCP_SCHEMA_URL =
16
- "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json";
17
-
18
- const SpecStdioServerSchema = z.object({
19
- type: z.literal("stdio"),
20
- command: z.string().min(1),
21
- args: z.array(z.string()).optional(),
22
- env: z.record(z.string(), z.string()).optional(),
23
- cwd: z.string().optional(),
24
- });
25
-
26
- /**
27
- * Remote MCP entry. Agent Plugins 1.0.0 requires `type` and names no
28
- * default. MCP's current remote transport is Streamable HTTP, so this
29
- * host fills omitted `type` and the Claude-style `http` alias as
30
- * `streamable-http`. `sse` stays explicit.
31
- */
32
- const SpecHttpServerSchema = z.object({
33
- type: z
34
- .union([
35
- z.literal("streamable-http"),
36
- z.literal("sse"),
37
- z.literal("http").transform(() => "streamable-http" as const),
38
- ])
39
- .default("streamable-http"),
40
- url: z.string().min(1),
41
- headers: z.record(z.string(), z.string()).optional(),
42
- });
43
-
44
- export const SpecMcpServerSchema = z.union([
45
- SpecStdioServerSchema,
46
- SpecHttpServerSchema,
47
- ]);
48
-
49
- export const SpecMcpDocumentSchema = z.object({
50
- $schema: z.string().optional(),
51
- mcpServers: z.record(z.string(), z.unknown()),
52
- });
53
-
54
- export type SpecMcpServer = z.infer<typeof SpecMcpServerSchema>;
55
- export type SpecMcpDocument = z.infer<typeof SpecMcpDocumentSchema>;
56
-
57
- /**
58
- * Project one spec-shaped entry onto the assistant's transport union. The
59
- * two vocabularies already agree on type names and required fields, so this
60
- * is a field copy plus an optional expander for plugin path variables.
61
- */
62
- export function projectSpecServerToTransport(
63
- entry: SpecMcpServer,
64
- expand?: (value: string) => string,
65
- ): McpTransport {
66
- if (entry.type === "stdio") {
67
- const map = expand ?? ((value: string) => value);
68
- return {
69
- type: "stdio",
70
- command: entry.command,
71
- args: (entry.args ?? []).map(map),
72
- ...(entry.env && {
73
- env: Object.fromEntries(
74
- Object.entries(entry.env).map(([key, value]) => [key, map(value)]),
75
- ),
76
- }),
77
- };
78
- }
79
- return {
80
- type: entry.type,
81
- url: entry.url,
82
- ...(entry.headers && { headers: entry.headers }),
83
- };
84
- }
85
-
86
- /**
87
- * Project an in-memory transport onto a spec server entry. Headers are
88
- * omitted: workspace secrets live in the credential store, and a write
89
- * must not copy them into `mcp.json`.
90
- */
91
- export function projectTransportToSpecServer(
92
- transport: McpTransport,
93
- ): Record<string, unknown> {
94
- if (transport.type === "stdio") {
95
- const entry: Record<string, unknown> = {
96
- type: "stdio",
97
- command: transport.command,
98
- };
99
- if (transport.args && transport.args.length > 0) {
100
- entry.args = transport.args;
101
- }
102
- if (transport.env) {
103
- entry.env = transport.env;
104
- }
105
- return entry;
106
- }
107
- return {
108
- type: transport.type,
109
- url: transport.url,
110
- };
111
- }
@@ -1,188 +0,0 @@
1
- /**
2
- * User-owned MCP servers in `$VELLUM_WORKSPACE_DIR/mcp.json`.
3
- *
4
- * The file is an Agent Plugins 1.0.0 document (`$schema` + `mcpServers`).
5
- * This module is the only reader and writer of that file. Presence of a
6
- * server starts it. Headers are never persisted here.
7
- */
8
-
9
- import {
10
- existsSync,
11
- mkdirSync,
12
- readFileSync,
13
- renameSync,
14
- writeFileSync,
15
- } from "node:fs";
16
- import { dirname } from "node:path";
17
-
18
- import type { McpConfig, McpServerConfig } from "../config/schemas/mcp.js";
19
- import { McpConfigSchema } from "../config/schemas/mcp.js";
20
- import { getLogger } from "../util/logger.js";
21
- import { getWorkspaceMcpConfigPath } from "../util/platform.js";
22
- import {
23
- AGENT_PLUGINS_MCP_SCHEMA_URL,
24
- projectSpecServerToTransport,
25
- projectTransportToSpecServer,
26
- SpecMcpDocumentSchema,
27
- SpecMcpServerSchema,
28
- } from "./spec-schema.js";
29
-
30
- const log = getLogger("workspace-mcp-config");
31
-
32
- export type WorkspaceMcpFileState = "missing" | "ok" | "invalid";
33
-
34
- export interface WorkspaceMcpLoadResult {
35
- readonly config: McpConfig;
36
- readonly issues: readonly string[];
37
- readonly fileState: WorkspaceMcpFileState;
38
- }
39
-
40
- /**
41
- * Read `/workspace/mcp.json` and project it onto the in-memory MCP config.
42
- *
43
- * A missing file is an empty server map. An invalid file disables the
44
- * workspace half only (plugin servers still load) and is reported so a
45
- * write can refuse to overwrite it.
46
- */
47
- export function readWorkspaceMcpFile(
48
- path: string = getWorkspaceMcpConfigPath(),
49
- ): WorkspaceMcpLoadResult {
50
- if (!existsSync(path)) {
51
- return {
52
- config: McpConfigSchema.parse({}),
53
- issues: [],
54
- fileState: "missing",
55
- };
56
- }
57
-
58
- let raw: string;
59
- try {
60
- raw = readFileSync(path, "utf8");
61
- } catch (err) {
62
- const message = `mcp.json unreadable: ${err instanceof Error ? err.message : String(err)}`;
63
- return {
64
- config: McpConfigSchema.parse({}),
65
- issues: [message],
66
- fileState: "invalid",
67
- };
68
- }
69
-
70
- let json: unknown;
71
- try {
72
- json = JSON.parse(raw);
73
- } catch (err) {
74
- const message = `mcp.json invalid JSON: ${err instanceof Error ? err.message : String(err)}`;
75
- return {
76
- config: McpConfigSchema.parse({}),
77
- issues: [message],
78
- fileState: "invalid",
79
- };
80
- }
81
-
82
- const document = SpecMcpDocumentSchema.safeParse(json);
83
- if (!document.success) {
84
- return {
85
- config: McpConfigSchema.parse({}),
86
- issues: ['mcp.json is missing a valid "mcpServers" object'],
87
- fileState: "invalid",
88
- };
89
- }
90
-
91
- const servers: Record<string, McpServerConfig> = {};
92
- const issues: string[] = [];
93
-
94
- for (const [serverKey, rawEntry] of Object.entries(document.data.mcpServers)) {
95
- if (serverKey.trim().length === 0) {
96
- issues.push("server key must be a non-empty string; skipping");
97
- continue;
98
- }
99
-
100
- const entry = SpecMcpServerSchema.safeParse(rawEntry);
101
- if (!entry.success) {
102
- issues.push(
103
- `invalid server entry "${serverKey}": ${entry.error.issues
104
- .map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`)
105
- .join("; ")}`,
106
- );
107
- continue;
108
- }
109
-
110
- if (entry.data.type === "stdio" && entry.data.cwd) {
111
- issues.push(
112
- `"${serverKey}": "cwd" is not supported by this host and was ignored; the server runs in the assistant's working directory`,
113
- );
114
- }
115
-
116
- servers[serverKey] = {
117
- transport: projectSpecServerToTransport(entry.data),
118
- };
119
- }
120
-
121
- return {
122
- config: { servers },
123
- issues,
124
- fileState: "ok",
125
- };
126
- }
127
-
128
- /** Load the workspace MCP config, logging any declaration problems. */
129
- export function loadWorkspaceMcpConfig(): McpConfig {
130
- const result = readWorkspaceMcpFile();
131
- for (const issue of result.issues) {
132
- log.warn(issue);
133
- }
134
- return result.config;
135
- }
136
-
137
- /**
138
- * Refuse a write when `mcp.json` exists but is not a usable document, so a
139
- * later add/remove cannot clobber a hand-edit the user still means to fix.
140
- */
141
- export function assertWorkspaceMcpWritable(): void {
142
- const result = readWorkspaceMcpFile();
143
- if (result.fileState === "invalid") {
144
- throw new Error(result.issues[0] ?? "mcp.json is not a valid document");
145
- }
146
- }
147
-
148
- /** Persist the in-memory workspace MCP config as a spec-pure document. */
149
- export function saveWorkspaceMcpConfig(config: McpConfig): void {
150
- assertWorkspaceMcpWritable();
151
- const path = getWorkspaceMcpConfigPath();
152
- const mcpServers: Record<string, unknown> = {};
153
- for (const [id, server] of Object.entries(config.servers)) {
154
- mcpServers[id] = projectTransportToSpecServer(server.transport);
155
- }
156
-
157
- const document = {
158
- $schema: AGENT_PLUGINS_MCP_SCHEMA_URL,
159
- mcpServers,
160
- };
161
-
162
- mkdirSync(dirname(path), { recursive: true });
163
- const tmpPath = `${path}.tmp`;
164
- writeFileSync(tmpPath, JSON.stringify(document, null, 2) + "\n");
165
- renameSync(tmpPath, path);
166
- }
167
-
168
- /**
169
- * Replace `config.mcp` on a settings/export payload with the projected
170
- * workspace servers (transport only, headers stripped). Old clients that
171
- * still read `mcp.servers` from `/v1/config` keep seeing the same shape.
172
- */
173
- export function overlayWorkspaceMcpForConfigRead(config: unknown): void {
174
- if (config === null || typeof config !== "object" || Array.isArray(config)) {
175
- return;
176
- }
177
- const root = config as Record<string, unknown>;
178
- const { servers } = loadWorkspaceMcpConfig();
179
- const projected: Record<string, unknown> = {};
180
- for (const [id, server] of Object.entries(servers)) {
181
- const { headers: _headers, ...safeTransport } = server.transport as Record<
182
- string,
183
- unknown
184
- >;
185
- projected[id] = { transport: safeTransport };
186
- }
187
- root.mcp = { servers: projected };
188
- }