@vellumai/assistant 0.12.1-staging.1 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (404) 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/openapi.yaml +1 -291
  5. package/package.json +1 -1
  6. package/src/__tests__/always-loaded-tools-guard.test.ts +10 -18
  7. package/src/__tests__/app-compiler.test.ts +0 -6
  8. package/src/__tests__/app-control-tool-schemas.test.ts +2 -5
  9. package/src/__tests__/app-dir-path-guard.test.ts +3 -1
  10. package/src/__tests__/app-source-watcher.test.ts +218 -0
  11. package/src/{calls/__tests__ → __tests__}/call-controller.test.ts +82 -503
  12. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +2 -5
  13. package/src/__tests__/computer-use-tools.test.ts +5 -17
  14. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  15. package/src/__tests__/config-schema.test.ts +29 -28
  16. package/src/__tests__/config-watcher-skill-reseed.test.ts +359 -0
  17. package/src/__tests__/config-watcher.test.ts +8 -23
  18. package/src/__tests__/connection-model-compat.test.ts +2 -2
  19. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  20. package/src/__tests__/conversation-pairing.test.ts +0 -26
  21. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -4
  22. package/src/__tests__/conversation-queue.test.ts +207 -48
  23. package/src/__tests__/conversation-retry-discard.test.ts +1 -54
  24. package/src/__tests__/conversation-skill-tools.test.ts +0 -27
  25. package/src/__tests__/conversation-surfaces-app-control.test.ts +3 -8
  26. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -67
  27. package/src/__tests__/conversation-title-service.test.ts +10 -14
  28. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +5 -3
  29. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -51
  30. package/src/__tests__/credential-record-retire.test.ts +1 -171
  31. package/src/__tests__/credential-routes.test.ts +3 -212
  32. package/src/__tests__/credential-security-invariants.test.ts +1 -2
  33. package/src/__tests__/cu-unified-flow.test.ts +2 -8
  34. package/src/__tests__/drain-kick-guard.test.ts +2 -0
  35. package/src/__tests__/drain-requeue-on-contention.test.ts +6 -0
  36. package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
  37. package/src/__tests__/host-bash-proxy.test.ts +45 -26
  38. package/src/__tests__/host-browser-proxy.test.ts +17 -6
  39. package/src/__tests__/host-file-proxy-targeted.test.ts +0 -23
  40. package/src/__tests__/host-file-proxy.test.ts +23 -11
  41. package/src/__tests__/host-transfer-proxy-targeted.test.ts +9 -30
  42. package/src/__tests__/llm-catalog-parity.test.ts +0 -25
  43. package/src/__tests__/mcp-auth-routes.test.ts +9 -6
  44. package/src/__tests__/mcp-config-secret-boundary.test.ts +136 -78
  45. package/src/__tests__/mcp-health-check.test.ts +11 -8
  46. package/src/__tests__/mcp-list-plugin-servers.test.ts +10 -8
  47. package/src/{calls/__tests__ → __tests__}/media-stream-audio-transcode.test.ts +1 -1
  48. package/src/{calls/__tests__ → __tests__}/media-stream-output.test.ts +8 -37
  49. package/src/{calls/__tests__ → __tests__}/media-stream-parser.test.ts +1 -1
  50. package/src/{calls/__tests__ → __tests__}/media-stream-server-integration.test.ts +57 -150
  51. package/src/{calls/__tests__ → __tests__}/media-stream-stt-session.test.ts +5 -5
  52. package/src/{calls/__tests__ → __tests__}/media-turn-detector.test.ts +1 -1
  53. package/src/__tests__/messages-after-tiebreaker.test.ts +0 -91
  54. package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
  55. package/src/__tests__/messaging-send-tool.test.ts +548 -355
  56. package/src/__tests__/model-intents.test.ts +0 -3
  57. package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
  58. package/src/__tests__/platform-client-verify-credential.test.ts +0 -2
  59. package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -13
  60. package/src/__tests__/script-proxy-certs.test.ts +0 -35
  61. package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
  62. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  63. package/src/__tests__/speaker-identification.test.ts +56 -0
  64. package/src/__tests__/subagent-tool-gate-mode.test.ts +3 -19
  65. package/src/__tests__/subagent-tools.test.ts +2 -3
  66. package/src/__tests__/telephony-tts-guard.test.ts +3 -38
  67. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -4
  68. package/src/{calls/__tests__/voice-session-bridge-turn-flow.test.ts → __tests__/voice-session-bridge.test.ts} +12 -20
  69. package/src/__tests__/watch-retro-tool-availability.test.ts +17 -8
  70. package/src/__tests__/workspace-git-service.test.ts +0 -26
  71. package/src/acp/__tests__/agent-process.test.ts +4 -258
  72. package/src/acp/__tests__/auth-required.test.ts +0 -96
  73. package/src/acp/__tests__/client-handler.test.ts +2 -90
  74. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -5
  75. package/src/acp/__tests__/session-manager-resume.test.ts +6 -270
  76. package/src/acp/__tests__/session-manager-usage.test.ts +2 -4
  77. package/src/acp/__tests__/session-manager.test.ts +4 -895
  78. package/src/acp/agent-process.test.ts +1 -4
  79. package/src/acp/agent-process.ts +9 -94
  80. package/src/acp/auth-required.ts +1 -50
  81. package/src/acp/auto-install.test.ts +7 -9
  82. package/src/acp/client-handler.ts +3 -16
  83. package/src/acp/resolve-agent.test.ts +6 -220
  84. package/src/acp/resolve-agent.ts +23 -88
  85. package/src/acp/session-manager.test.ts +3 -196
  86. package/src/acp/session-manager.ts +18 -441
  87. package/src/acp/types.ts +5 -50
  88. package/src/api/events/app-files-changed.ts +3 -4
  89. package/src/api/index.ts +0 -6
  90. package/src/apps/app-store.ts +1 -1
  91. package/src/bundler/app-compiler.ts +0 -15
  92. package/src/calls/__tests__/voice-control-protocol.test.ts +25 -58
  93. package/src/calls/__tests__/voice-session-bridge.test.ts +1 -37
  94. package/src/calls/__tests__/voice-triage-escalate.test.ts +0 -105
  95. package/src/calls/call-constants.ts +4 -24
  96. package/src/calls/call-controller.ts +199 -499
  97. package/src/calls/call-transport.ts +0 -16
  98. package/src/calls/media-stream-output.ts +0 -32
  99. package/src/calls/media-stream-server.ts +30 -82
  100. package/src/calls/media-stream-stt-session.ts +0 -15
  101. package/src/calls/resolve-call-tts-provider.ts +2 -33
  102. package/src/calls/speaker-identification.ts +233 -0
  103. package/src/calls/tts-call-strategy.ts +5 -9
  104. package/src/calls/types.ts +0 -2
  105. package/src/calls/voice-control-protocol.ts +21 -53
  106. package/src/calls/voice-session-bridge.ts +46 -59
  107. package/src/calls/voice-triage-escalate.ts +56 -175
  108. package/src/cli/commands/apps.help.ts +13 -67
  109. package/src/cli/commands/apps.ts +0 -183
  110. package/src/cli/commands/channels/index.help.ts +2 -70
  111. package/src/cli/commands/channels/index.ts +3 -16
  112. package/src/cli/commands/credentials.help.ts +2 -6
  113. package/src/cli/commands/credentials.ts +2 -2
  114. package/src/cli/commands/mcp.help.ts +8 -8
  115. package/src/cli/commands/mcp.ts +1 -1
  116. package/src/cli/commands/roadmap.help.ts +1 -5
  117. package/src/cli/commands/roadmap.ts +1 -1
  118. package/src/cli/lib/bundled-marketplace.json +90 -103
  119. package/src/config/__tests__/default-profile-catalog.test.ts +0 -22
  120. package/src/config/__tests__/memory-retrospective-schema.test.ts +1 -15
  121. package/src/config/__tests__/platform-rehydration.test.ts +0 -93
  122. package/src/config/acp-defaults.test.ts +3 -13
  123. package/src/config/acp-defaults.ts +6 -23
  124. package/src/config/acp-schema.ts +2 -30
  125. package/src/config/bundled-skills/acp/SKILL.md +14 -22
  126. package/src/config/bundled-skills/acp/TOOLS.json +1 -5
  127. package/src/config/bundled-skills/app-builder/SKILL.md +9 -12
  128. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
  129. package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
  130. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +139 -67
  131. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
  132. package/src/config/bundled-skills/screen-annotation/SKILL.md +1 -8
  133. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +1 -4
  134. package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
  135. package/src/config/default-profile-catalog.ts +1 -1
  136. package/src/config/env.ts +2 -2
  137. package/src/config/feature-flag-registry.json +12 -8
  138. package/src/config/memory-v3-gate.test.ts +0 -31
  139. package/src/config/memory-v3-gate.ts +16 -20
  140. package/src/config/platform-rehydration.ts +21 -75
  141. package/src/config/schema.ts +2 -2
  142. package/src/config/schemas/__tests__/live-voice.test.ts +158 -8
  143. package/src/config/schemas/calls.ts +28 -1
  144. package/src/config/schemas/live-voice.ts +173 -1
  145. package/src/config/schemas/mcp.ts +1 -1
  146. package/src/config/schemas/memory-retrospective.ts +0 -10
  147. package/src/config/schemas/skills.ts +14 -0
  148. package/src/credential-execution/process-manager.test.ts +19 -18
  149. package/src/daemon/__tests__/conversation-tool-setup.test.ts +121 -66
  150. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +1 -4
  151. package/src/daemon/app-source-watcher.ts +218 -0
  152. package/src/daemon/config-watcher.ts +194 -13
  153. package/src/daemon/conversation-process.ts +64 -35
  154. package/src/daemon/conversation-skill-tools.ts +31 -13
  155. package/src/daemon/conversation-store.ts +1 -1
  156. package/src/daemon/conversation-surfaces.ts +8 -10
  157. package/src/daemon/conversation-tool-setup.ts +43 -37
  158. package/src/daemon/conversation.ts +3 -0
  159. package/src/daemon/host-bash-proxy.ts +12 -8
  160. package/src/daemon/host-browser-proxy.ts +1 -15
  161. package/src/daemon/host-file-proxy.ts +10 -8
  162. package/src/daemon/host-transfer-proxy.ts +18 -14
  163. package/src/daemon/lifecycle.ts +5 -0
  164. package/src/daemon/mcp-reload-service.ts +5 -5
  165. package/src/daemon/message-types/sync.ts +0 -1
  166. package/src/daemon/providers-setup.ts +1 -1
  167. package/src/daemon/shutdown-handlers.ts +9 -1
  168. package/src/daemon/skill-memory-refresh.ts +0 -64
  169. package/src/daemon/tool-side-effects.ts +18 -7
  170. package/src/hooks/types.ts +0 -33
  171. package/src/inbound/platform-callback-registration.ts +5 -4
  172. package/src/live-voice/__tests__/live-voice-metrics.test.ts +3 -0
  173. package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -15
  174. package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
  175. package/src/{calls → live-voice}/__tests__/progress-narration.test.ts +4 -4
  176. package/src/{calls → live-voice}/__tests__/progress-phrases.test.ts +1 -1
  177. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +69 -13
  178. package/src/live-voice/live-voice-session.ts +693 -213
  179. package/src/{calls → live-voice}/progress-narration.ts +2 -2
  180. package/src/live-voice/protocol.ts +2 -0
  181. package/src/mcp/__tests__/effective-config.test.ts +2 -2
  182. package/src/mcp/effective-config.ts +3 -3
  183. package/src/mcp/mcp-header-store.ts +45 -29
  184. package/src/mcp/startup.ts +4 -8
  185. package/src/messaging/provider.ts +3 -10
  186. package/src/messaging/providers/callback-routing.ts +0 -18
  187. package/src/messaging/providers/channel-transport.ts +0 -56
  188. package/src/messaging/providers/discord/transport.ts +0 -17
  189. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +17 -6
  190. package/src/messaging/providers/slack/adapter.ts +44 -7
  191. package/src/messaging/providers/slack/transport.ts +0 -16
  192. package/src/messaging/providers/telegram-bot/adapter.ts +48 -1
  193. package/src/messaging/providers/telegram-bot/client.ts +26 -0
  194. package/src/messaging/providers/telegram-bot/transport.ts +0 -20
  195. package/src/messaging/providers/whatsapp/adapter.ts +48 -1
  196. package/src/messaging/providers/whatsapp/client.ts +29 -0
  197. package/src/messaging/providers/whatsapp/transport.ts +0 -18
  198. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +0 -8
  199. package/src/notifications/__tests__/assistant-reply-producer.test.ts +0 -55
  200. package/src/notifications/__tests__/home-feed-side-effect.test.ts +3 -153
  201. package/src/notifications/assistant-reply-producer.ts +3 -8
  202. package/src/notifications/conversation-pairing.ts +16 -36
  203. package/src/notifications/delivered-post-record.ts +1 -11
  204. package/src/notifications/home-feed-side-effect.ts +7 -55
  205. package/src/outbound-proxy/certs.ts +5 -3
  206. package/src/permissions/checker.test.ts +6 -11
  207. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  208. package/src/persistence/conversation-crud.ts +63 -71
  209. package/src/persistence/conversation-lineage.ts +4 -12
  210. package/src/persistence/conversation-title-service.ts +26 -9
  211. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  212. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  213. package/src/persistence/message-reads.ts +0 -30
  214. package/src/persistence/migrations/157-invite-contact-id.ts +6 -18
  215. package/src/persistence/schema/memory-core.ts +0 -5
  216. package/src/platform/client.test.ts +0 -2
  217. package/src/platform/client.ts +10 -2
  218. package/src/plugin-api/constants.ts +0 -2
  219. package/src/plugin-api/index.ts +0 -1
  220. package/src/plugin-api/types.ts +0 -2
  221. package/src/plugins/defaults/index.ts +0 -2
  222. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +0 -46
  223. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +5 -9
  224. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +10 -20
  225. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +0 -219
  226. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +0 -31
  227. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -63
  228. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +0 -4
  229. package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -4
  230. package/src/plugins/defaults/memory/hooks/init.ts +0 -10
  231. package/src/plugins/defaults/memory/hooks/shutdown.ts +0 -2
  232. package/src/plugins/defaults/memory/jobs-worker.ts +0 -13
  233. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +60 -34
  234. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +5 -3
  235. package/src/plugins/defaults/memory/memory-retrospective-job.ts +3 -12
  236. package/src/plugins/defaults/memory/memory-retrospective-state.ts +71 -312
  237. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +1 -2
  238. package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +3 -5
  239. package/src/plugins/defaults/memory/startup.ts +1 -6
  240. package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +9 -7
  241. package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
  242. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +0 -89
  243. package/src/plugins/defaults/memory/worker.ts +0 -6
  244. package/src/plugins/mcp-servers.ts +75 -15
  245. package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
  246. package/src/providers/gemini/client.ts +23 -9
  247. package/src/providers/model-catalog.ts +0 -34
  248. package/src/providers/model-intents.ts +5 -10
  249. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +18 -146
  250. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +1 -83
  251. package/src/providers/openai/chat-completions-provider.ts +78 -192
  252. package/src/providers/openai/codex-models.ts +4 -0
  253. package/src/runtime/AGENTS.md +0 -2
  254. package/src/runtime/auth/same-actor.ts +3 -38
  255. package/src/runtime/http-server.ts +151 -160
  256. package/src/runtime/routes/__tests__/acp-routes.test.ts +4 -159
  257. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -108
  258. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +12 -16
  259. package/src/runtime/routes/acp-routes.test.ts +0 -15
  260. package/src/runtime/routes/acp-routes.ts +9 -72
  261. package/src/runtime/routes/app-management-routes.ts +0 -73
  262. package/src/runtime/routes/app-routes.ts +1 -1
  263. package/src/runtime/routes/conversation-list-routes.ts +3 -14
  264. package/src/runtime/routes/conversation-query-routes.ts +0 -40
  265. package/src/runtime/routes/credential-routes.ts +10 -19
  266. package/src/runtime/routes/diagnostics-routes.ts +3 -55
  267. package/src/runtime/routes/index.ts +0 -4
  268. package/src/runtime/routes/log-export-routes.ts +0 -2
  269. package/src/runtime/routes/mcp-auth-routes.ts +47 -39
  270. package/src/runtime/routes/migration-routes.ts +21 -8
  271. package/src/runtime/routes/platform-routes.ts +15 -18
  272. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -28
  273. package/src/runtime/services/conversation-serializer.ts +3 -16
  274. package/src/runtime/sync/resource-sync-events.ts +1 -2
  275. package/src/schedule/worker.ts +1 -1
  276. package/src/security/ces-rpc-record-backend.ts +0 -7
  277. package/src/subagent/consult-context.ts +25 -12
  278. package/src/tools/acp/list-agents.test.ts +1 -3
  279. package/src/tools/acp/spawn.test.ts +11 -146
  280. package/src/tools/acp/spawn.ts +3 -21
  281. package/src/tools/acp/status.ts +3 -40
  282. package/src/tools/app-control/skill-proxy-bridge.ts +1 -2
  283. package/src/tools/capability-offer.test.ts +2 -22
  284. package/src/tools/capability-offer.ts +1 -16
  285. package/src/tools/computer-use/definitions.ts +2 -4
  286. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -2
  287. package/src/tools/credentials/metadata-store.ts +0 -100
  288. package/src/tools/host-filesystem/edit.test.ts +1 -2
  289. package/src/tools/host-filesystem/edit.ts +2 -2
  290. package/src/tools/host-filesystem/read.test.ts +1 -2
  291. package/src/tools/host-filesystem/read.ts +2 -2
  292. package/src/tools/host-filesystem/transfer.test.ts +1 -2
  293. package/src/tools/host-filesystem/transfer.ts +2 -2
  294. package/src/tools/host-filesystem/write.test.ts +1 -2
  295. package/src/tools/host-filesystem/write.ts +2 -2
  296. package/src/tools/host-terminal/host-shell.test.ts +0 -16
  297. package/src/tools/host-terminal/host-shell.ts +20 -4
  298. package/src/tools/policy-context.ts +7 -6
  299. package/src/tools/subagent/spawn.ts +8 -5
  300. package/src/tools/watch/watch-retro-report.ts +8 -0
  301. package/src/util/__tests__/language-subtag.test.ts +1 -23
  302. package/src/util/fs-watcher-error.ts +36 -0
  303. package/src/util/language-subtag.ts +0 -16
  304. package/src/util/platform.ts +0 -8
  305. package/src/workspace/git-service.ts +54 -5
  306. package/src/workspace/migrations/registry.ts +0 -6
  307. package/scripts/smoke-desktop-window-theme.ts +0 -186
  308. package/src/__tests__/git-porcelain.test.ts +0 -47
  309. package/src/__tests__/helpers/set-workspace-mcp.ts +0 -11
  310. package/src/__tests__/message-deleted-hook-dispatch.test.ts +0 -119
  311. package/src/__tests__/resolve-app.test.ts +0 -135
  312. package/src/__tests__/source-fingerprint.test.ts +0 -184
  313. package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +0 -336
  314. package/src/acp/__tests__/helpers/acp-model-option.ts +0 -51
  315. package/src/acp/model-config.test.ts +0 -166
  316. package/src/acp/model-config.ts +0 -138
  317. package/src/api/events/acp-session-model-update.test.ts +0 -88
  318. package/src/api/events/acp-session-model-update.ts +0 -46
  319. package/src/apps/resolve-app.ts +0 -81
  320. package/src/apps/source-fingerprint.ts +0 -266
  321. package/src/calls/__tests__/barge-in-guard.test.ts +0 -81
  322. package/src/calls/__tests__/voice-leg-coordinator.test.ts +0 -229
  323. package/src/calls/__tests__/voice-progress-cadence.test.ts +0 -274
  324. package/src/calls/barge-in-guard.ts +0 -118
  325. package/src/calls/voice-leg-coordinator.ts +0 -189
  326. package/src/calls/voice-progress-cadence.ts +0 -423
  327. package/src/cli/commands/__tests__/apps.test.ts +0 -245
  328. package/src/cli/commands/__tests__/roadmap.help.test.ts +0 -19
  329. package/src/cli/commands/channels/__tests__/send.test.ts +0 -218
  330. package/src/cli/commands/channels/send.ts +0 -128
  331. package/src/config/__tests__/platform-identity.test.ts +0 -117
  332. package/src/config/acp-agent-write.ts +0 -43
  333. package/src/config/acp-schema.test.ts +0 -81
  334. package/src/config/platform-identity.ts +0 -144
  335. package/src/config/schemas/__tests__/voice.test.ts +0 -148
  336. package/src/config/schemas/voice.ts +0 -150
  337. package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +0 -133
  338. package/src/daemon/app-change-notify.ts +0 -45
  339. package/src/desktop/__tests__/fake-desktop.ts +0 -119
  340. package/src/desktop/desktop-chrome-policy.test.ts +0 -71
  341. package/src/desktop/desktop-chrome-policy.ts +0 -42
  342. package/src/desktop/desktop-dependencies.test.ts +0 -102
  343. package/src/desktop/desktop-dependencies.ts +0 -306
  344. package/src/desktop/desktop-feature.test.ts +0 -18
  345. package/src/desktop/desktop-feature.ts +0 -19
  346. package/src/desktop/desktop-panel-config.test.ts +0 -135
  347. package/src/desktop/desktop-panel-config.ts +0 -149
  348. package/src/desktop/desktop-session-manager.test.ts +0 -627
  349. package/src/desktop/desktop-session-manager.ts +0 -814
  350. package/src/desktop/desktop-stream-bridge.test.ts +0 -395
  351. package/src/desktop/desktop-stream-bridge.ts +0 -214
  352. package/src/desktop/desktop-wallpaper.test.ts +0 -191
  353. package/src/desktop/desktop-wallpaper.ts +0 -113
  354. package/src/desktop/desktop-window-theme.ts +0 -170
  355. package/src/i18n/AGENTS.md +0 -22
  356. package/src/i18n/__tests__/i18n.test.ts +0 -108
  357. package/src/i18n/index.ts +0 -16
  358. package/src/i18n/locales.ts +0 -93
  359. package/src/i18n/messages.ts +0 -61
  360. package/src/i18n/title.ts +0 -25
  361. package/src/mcp/__tests__/workspace-mcp-config.test.ts +0 -135
  362. package/src/mcp/spec-schema.ts +0 -111
  363. package/src/mcp/workspace-mcp-config.ts +0 -188
  364. package/src/messaging/providers/__tests__/proactive-address.test.ts +0 -95
  365. package/src/persistence/conversation-title-placeholders.ts +0 -23
  366. package/src/persistence/message-cursor.ts +0 -78
  367. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +0 -149
  368. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +0 -118
  369. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +0 -83
  370. package/src/plugins/defaults/memory/hooks/message-deleted.ts +0 -21
  371. package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +0 -126
  372. package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +0 -79
  373. package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +0 -28
  374. package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +0 -9
  375. package/src/providers/gemini-thought-signature.test.ts +0 -63
  376. package/src/providers/gemini-thought-signature.ts +0 -44
  377. package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +0 -613
  378. package/src/providers/openai/__tests__/google-thought-signature.test.ts +0 -235
  379. package/src/providers/openai/google-thought-signature.ts +0 -320
  380. package/src/runtime/__tests__/channel-send.test.ts +0 -443
  381. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +0 -89
  382. package/src/runtime/__tests__/live-voice-upgrade.test.ts +0 -58
  383. package/src/runtime/__tests__/runtime-ws-test-utils.ts +0 -72
  384. package/src/runtime/__tests__/watch-stream-upgrade.test.ts +0 -59
  385. package/src/runtime/channel-send.ts +0 -316
  386. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +0 -205
  387. package/src/runtime/routes/__tests__/channel-send-routes.test.ts +0 -127
  388. package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +0 -107
  389. package/src/runtime/routes/channel-send-routes.ts +0 -85
  390. package/src/runtime/routes/desktop-setup-routes.test.ts +0 -74
  391. package/src/runtime/routes/desktop-setup-routes.ts +0 -35
  392. package/src/security/__tests__/ces-http-record-backend.test.ts +0 -137
  393. package/src/security/ces-http-record-backend.ts +0 -120
  394. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +0 -60
  395. package/src/skills/workspace-skill-md-signature.ts +0 -50
  396. package/src/tools/acp/status.test.ts +0 -94
  397. package/src/util/ca-bundle.ts +0 -13
  398. package/src/workspace/git-porcelain.ts +0 -66
  399. package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +0 -258
  400. package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +0 -78
  401. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +0 -214
  402. package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +0 -102
  403. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +0 -199
  404. /package/src/{calls → live-voice}/progress-phrases.ts +0 -0
@@ -124,22 +124,11 @@ const spawnMock = mock(
124
124
  _cwd: string,
125
125
  _parentConversationId: string,
126
126
  _sendToVellum: (msg: unknown) => void,
127
- _options?: { parentToolUseId?: string; model?: string },
128
- ): Promise<{
129
- acpSessionId: string;
130
- protocolSessionId: string;
131
- requestedModel?: string;
132
- effectiveModel?: string;
133
- modelWarning?: string;
134
- }> => {
135
- const requestedModel = _options?.model?.trim() || undefined;
136
- return {
137
- acpSessionId: "acp-session-test",
138
- protocolSessionId: "proto-session-test",
139
- requestedModel,
140
- effectiveModel: "opus",
141
- };
142
- },
127
+ _parentToolUseId?: string,
128
+ ) => ({
129
+ acpSessionId: "acp-session-test",
130
+ protocolSessionId: "proto-session-test",
131
+ }),
143
132
  );
144
133
 
145
134
  // Spread the real module's exports so transitive importers that pull other
@@ -212,8 +201,6 @@ describe("executeAcpSpawn - happy path", () => {
212
201
  const payload = JSON.parse(result.content);
213
202
  expect(payload.acpSessionId).toBe("acp-session-test");
214
203
  expect(payload.status).toBe("running");
215
- expect(payload.requestedModel).toBeNull();
216
- expect(payload.effectiveModel).toBe("opus");
217
204
  // The real adapter binary is spawned (no `bun x` wrapper).
218
205
  const agentConfigArg = spawnMock.mock.calls[0][1] as { command: string };
219
206
  expect(agentConfigArg.command).toBe("claude-agent-acp");
@@ -227,10 +214,8 @@ describe("executeAcpSpawn - happy path", () => {
227
214
 
228
215
  expect(result.isError).toBe(false);
229
216
  expect(spawnMock).toHaveBeenCalledTimes(1);
230
- // The options bag is the 7th positional arg to spawn().
231
- expect(spawnMock.mock.calls[0][6]).toEqual({
232
- parentToolUseId: "toolu_abc123",
233
- });
217
+ // parentToolUseId is the 7th positional arg to spawn().
218
+ expect(spawnMock.mock.calls[0][6]).toBe("toolu_abc123");
234
219
  });
235
220
 
236
221
  test("default-profile fallback when user config is empty", async () => {
@@ -287,7 +272,7 @@ describe("executeAcpSpawn — input validation", () => {
287
272
  expect(result.isError).toBe(true);
288
273
  expect(result.content).toContain("claude-agent-acp is not on PATH");
289
274
  expect(result.content).toContain(
290
- "bun add -g @agentclientprotocol/claude-agent-acp@0.75.1",
275
+ "bun add -g @agentclientprotocol/claude-agent-acp",
291
276
  );
292
277
  expect(execFileMock).not.toHaveBeenCalled();
293
278
  expect(spawnMock).not.toHaveBeenCalled();
@@ -324,7 +309,7 @@ describe("executeAcpSpawn: sandboxed bun auto-install on missing binary", () =>
324
309
  expect(spawnMock).toHaveBeenCalledTimes(1);
325
310
  const payload = JSON.parse(result.content);
326
311
  expect(payload.message).toContain(
327
- "Installed @agentclientprotocol/claude-agent-acp@0.75.1 automatically.",
312
+ "Installed @agentclientprotocol/claude-agent-acp automatically.",
328
313
  );
329
314
  // The real binary was spawned with cwd = the project dir and token
330
315
  // injected (trusted-binary config, no resolution at spawn).
@@ -345,7 +330,7 @@ describe("executeAcpSpawn: sandboxed bun auto-install on missing binary", () =>
345
330
  expect(args).toEqual([
346
331
  "add",
347
332
  "--global",
348
- "@agentclientprotocol/claude-agent-acp@0.75.1",
333
+ "@agentclientprotocol/claude-agent-acp",
349
334
  ]);
350
335
  });
351
336
 
@@ -434,7 +419,7 @@ describe("executeAcpSpawn: sandboxed bun auto-install on missing binary", () =>
434
419
  expect(result.isError).toBe(true);
435
420
  expect(result.content).toContain("claude-agent-acp is not on PATH");
436
421
  expect(result.content).toContain(
437
- "bun add -g @agentclientprotocol/claude-agent-acp@0.75.1",
422
+ "bun add -g @agentclientprotocol/claude-agent-acp",
438
423
  );
439
424
  expect(result.content).toContain("auto-install failed");
440
425
  expect(result.content).toContain("EACCES");
@@ -473,126 +458,6 @@ describe("executeAcpSpawn — per-agent resume hint", () => {
473
458
  });
474
459
  });
475
460
 
476
- describe("executeAcpSpawn - model selection", () => {
477
- test("threads the requested model into manager.spawn's options", async () => {
478
- const result = await executeAcpSpawn(
479
- { agent: "claude", task: "do something", model: "opus" },
480
- { ...makeContext(), toolUseId: "toolu_model" },
481
- );
482
-
483
- expect(result.isError).toBe(false);
484
- expect(spawnMock.mock.calls[0][6]).toEqual({
485
- parentToolUseId: "toolu_model",
486
- model: "opus",
487
- });
488
- const payload = JSON.parse(result.content);
489
- expect(payload.requestedModel).toBe("opus");
490
- expect(payload.effectiveModel).toBe("opus");
491
- expect(payload.message).toContain(
492
- 'The top-level ACP session reports "opus" as its effective model.',
493
- );
494
- });
495
-
496
- test("reports the manager-normalized requested model", async () => {
497
- const result = await executeAcpSpawn(
498
- { agent: "claude", task: "do something", model: " opus " },
499
- makeContext(),
500
- );
501
-
502
- expect(spawnMock.mock.calls[0][6]).toEqual({
503
- parentToolUseId: undefined,
504
- model: " opus ",
505
- });
506
- expect(JSON.parse(result.content).requestedModel).toBe("opus");
507
- });
508
-
509
- test("a null model is treated as omitted", async () => {
510
- const result = await executeAcpSpawn(
511
- { agent: "claude", task: "do something", model: null },
512
- makeContext(),
513
- );
514
-
515
- expect(result.isError).toBe(false);
516
- const options = spawnMock.mock.calls[0][6] as { model?: string };
517
- expect(options.model).toBeUndefined();
518
- });
519
-
520
- test("a modelWarning from the spawn is relayed in the result message", async () => {
521
- spawnMock.mockImplementationOnce(async () => ({
522
- acpSessionId: "acp-session-test",
523
- protocolSessionId: "proto-session-test",
524
- requestedModel: "nope",
525
- effectiveModel: "opus",
526
- modelWarning: "Unknown model: nope",
527
- }));
528
-
529
- const result = await executeAcpSpawn(
530
- { agent: "claude", task: "do something", model: "nope" },
531
- makeContext(),
532
- );
533
-
534
- expect(result.isError).toBe(false);
535
- const payload = JSON.parse(result.content);
536
- expect(payload.message).toContain(
537
- "The requested model was not applied: Unknown model: nope",
538
- );
539
- expect(payload.requestedModel).toBe("nope");
540
- expect(payload.effectiveModel).toBe("opus");
541
- });
542
-
543
- test("the note relays a no-selector warning without calling it a refusal", async () => {
544
- spawnMock.mockImplementationOnce(async () => ({
545
- acpSessionId: "acp-session-test",
546
- protocolSessionId: "proto-session-test",
547
- requestedModel: "opus",
548
- modelWarning:
549
- 'Agent "claude" does not support model selection, so the session is running on the agent\'s own model.',
550
- }));
551
-
552
- const result = await executeAcpSpawn(
553
- { agent: "claude", task: "do something", model: "opus" },
554
- makeContext(),
555
- );
556
-
557
- const payload = JSON.parse(result.content);
558
- expect(payload.message).toContain("does not support model selection");
559
- expect(payload.message).not.toContain("refused");
560
- });
561
-
562
- test("no model note when the spawn reports no warning", async () => {
563
- const result = await executeAcpSpawn(
564
- { agent: "claude", task: "do something", model: "opus" },
565
- makeContext(),
566
- );
567
-
568
- expect(result.isError).toBe(false);
569
- const payload = JSON.parse(result.content);
570
- expect(payload.message).not.toContain(
571
- "The requested model was not applied",
572
- );
573
- });
574
-
575
- test("reports when the adapter does not identify the effective model", async () => {
576
- spawnMock.mockImplementationOnce(async () => ({
577
- acpSessionId: "acp-session-test",
578
- protocolSessionId: "proto-session-test",
579
- requestedModel: "sonnet",
580
- }));
581
-
582
- const result = await executeAcpSpawn(
583
- { agent: "claude", task: "do something", model: "sonnet" },
584
- makeContext(),
585
- );
586
-
587
- const payload = JSON.parse(result.content);
588
- expect(payload.requestedModel).toBe("sonnet");
589
- expect(payload.effectiveModel).toBeNull();
590
- expect(payload.message).toContain(
591
- "The top-level ACP session did not report an effective model.",
592
- );
593
- });
594
- });
595
-
596
461
  // ---------------------------------------------------------------------------
597
462
  // executeAcpSpawn — CLAUDE_CODE_OAUTH_TOKEN env injection + preflight
598
463
  //
@@ -37,7 +37,6 @@ export const acpSpawnInputSchema = z.looseObject({
37
37
  agent: nullAsOmitted(z.string()),
38
38
  task: nullAsOmitted(z.string()),
39
39
  cwd: nullAsOmitted(z.string()),
40
- model: nullAsOmitted(z.string()),
41
40
  });
42
41
 
43
42
  /**
@@ -67,7 +66,6 @@ export async function executeAcpSpawn(
67
66
  }
68
67
  const agent = parsedInput.data.agent || "claude";
69
68
  const task = parsedInput.data.task;
70
- const model = parsedInput.data.model;
71
69
 
72
70
  if (!task) {
73
71
  return { content: '"task" is required.', isError: true };
@@ -126,20 +124,14 @@ export async function executeAcpSpawn(
126
124
  // Recheck: the auto-install and the agent-env preparation above are both
127
125
  // awaits, and this is the point a long-lived subprocess starts.
128
126
  throwIfCancelled(context);
129
- const {
130
- acpSessionId,
131
- protocolSessionId,
132
- requestedModel,
133
- effectiveModel,
134
- modelWarning,
135
- } = await manager.spawn(
127
+ const { acpSessionId, protocolSessionId } = await manager.spawn(
136
128
  agent,
137
129
  agentConfig,
138
130
  task,
139
131
  cwd,
140
132
  context.conversationId,
141
133
  sendToClient,
142
- { parentToolUseId: context.toolUseId, model },
134
+ context.toolUseId,
143
135
  // The manager rechecks after its own protocol handshake and session
144
136
  // creation, so a turn stopped in that window tears the child process
145
137
  // down instead of handing it the task.
@@ -158,26 +150,16 @@ export async function executeAcpSpawn(
158
150
  const installNote = autoInstalledPackage
159
151
  ? ` Installed ${autoInstalledPackage} automatically.`
160
152
  : "";
161
- // Relayed verbatim: the warning already distinguishes an adapter with no
162
- // selector from one that refused the value.
163
- const modelNote = modelWarning
164
- ? ` The requested model was not applied: ${modelWarning}`
165
- : "";
166
- const effectiveModelNote = effectiveModel
167
- ? ` The top-level ACP session reports "${effectiveModel}" as its effective model.`
168
- : " The top-level ACP session did not report an effective model.";
169
153
  const payload = JSON.stringify({
170
154
  acpSessionId,
171
155
  protocolSessionId,
172
156
  agent,
173
157
  cwd,
174
- requestedModel: requestedModel ?? null,
175
- effectiveModel: effectiveModel ?? null,
176
158
  status: "running",
177
159
  message:
178
160
  `ACP agent "${agent}" spawned (session: ${protocolSessionId}). ` +
179
161
  `Results stream back via SSE. You will be notified when it completes.` +
180
- `${installNote}${modelNote}${effectiveModelNote}${resumeHint}`,
162
+ `${installNote}${resumeHint}`,
181
163
  });
182
164
 
183
165
  return { content: payload, isError: false };
@@ -1,7 +1,6 @@
1
1
  import { z } from "zod";
2
2
 
3
3
  import { getAcpSessionManager } from "../../acp/index.js";
4
- import type { AcpSessionState } from "../../acp/types.js";
5
4
  import {
6
5
  invalidToolInputResult,
7
6
  nullAsOmitted,
@@ -17,40 +16,6 @@ export const acpStatusInputSchema = z.looseObject({
17
16
  acp_session_id: nullAsOmitted(z.string()),
18
17
  });
19
18
 
20
- /**
21
- * The session fields worth spending LLM context on. An allowlist rather than
22
- * an omission: `availableModels` is a picker for the human surfaces (HTTP and
23
- * SSE) that says nothing the agent can act on, and a field added to
24
- * `AcpSessionState` for those surfaces should not reach this one by default.
25
- * `model` stays: which model a session is running on is answerable.
26
- */
27
- function projectSession(state: AcpSessionState) {
28
- return {
29
- id: state.id,
30
- agentId: state.agentId,
31
- acpSessionId: state.acpSessionId,
32
- parentConversationId: state.parentConversationId,
33
- status: state.status,
34
- startedAt: state.startedAt,
35
- completedAt: state.completedAt,
36
- error: state.error,
37
- stopReason: state.stopReason,
38
- task: state.task,
39
- parentToolUseId: state.parentToolUseId,
40
- authErrorCode: state.authErrorCode,
41
- authErrorCredential: state.authErrorCredential,
42
- latestUsage: state.latestUsage,
43
- model: state.model,
44
- };
45
- }
46
-
47
- /** Projects either shape `getStatus` answers with. */
48
- function projectStatus(status: AcpSessionState | AcpSessionState[]): unknown {
49
- return Array.isArray(status)
50
- ? status.map(projectSession)
51
- : projectSession(status);
52
- }
53
-
54
19
  export async function executeAcpStatus(
55
20
  input: Record<string, unknown>,
56
21
  _context: ToolContext,
@@ -64,8 +29,9 @@ export async function executeAcpStatus(
64
29
 
65
30
  try {
66
31
  if (acpSessionId) {
32
+ const state = manager.getStatus(acpSessionId);
67
33
  return {
68
- content: JSON.stringify(projectStatus(manager.getStatus(acpSessionId))),
34
+ content: JSON.stringify(state),
69
35
  isError: false,
70
36
  };
71
37
  }
@@ -76,10 +42,7 @@ export async function executeAcpStatus(
76
42
  return { content: "No ACP sessions found.", isError: false };
77
43
  }
78
44
 
79
- return {
80
- content: JSON.stringify(projectStatus(allStates)),
81
- isError: false,
82
- };
45
+ return { content: JSON.stringify(allStates), isError: false };
83
46
  } catch (err) {
84
47
  const msg = err instanceof Error ? err.message : String(err);
85
48
  return { content: msg, isError: true };
@@ -5,7 +5,6 @@
5
5
  * the proxy resolver, which forwards the call to the connected client.
6
6
  */
7
7
 
8
- import { formatDesktopAppRequired } from "../capability-offer.js";
9
8
  import { throwIfCancelled } from "../shared/abort.js";
10
9
  import type { ToolContext, ToolExecutionResult } from "../types.js";
11
10
 
@@ -33,7 +32,7 @@ export function forwardAppControlProxyTool(
33
32
  }
34
33
  if (!context.proxyToolResolver) {
35
34
  return Promise.resolve({
36
- content: formatDesktopAppRequired("apps"),
35
+ content: `Cannot execute ${toolName}: no proxy resolver available. This tool requires a connected client.`,
37
36
  isError: true,
38
37
  });
39
38
  }
@@ -4,26 +4,11 @@ import {
4
4
  appendLoggedInBrowserOffer,
5
5
  CHROME_WEB_STORE_INSTALL_URL,
6
6
  DESKTOP_APP_DOWNLOAD_URL,
7
- formatDesktopAppRequired,
8
7
  formatLoggedInBrowserOffer,
9
8
  isPhoneSurface,
10
9
  shouldOfferLoggedInBrowser,
11
10
  } from "./capability-offer.js";
12
11
 
13
- describe("formatDesktopAppRequired", () => {
14
- test("offers a direct desktop-app download and retry step", () => {
15
- const message = formatDesktopAppRequired("shell");
16
-
17
- expect(message).toContain(
18
- "The Vellum desktop app is needed to run commands on your computer",
19
- );
20
- expect(message).toContain(DESKTOP_APP_DOWNLOAD_URL);
21
- expect(message).toContain("Open it, then retry.");
22
- expect(message).not.toContain("client");
23
- expect(message).not.toContain("daemon");
24
- });
25
- });
26
-
27
12
  describe("isPhoneSurface", () => {
28
13
  test("is true for iOS transport and mobile client OS", () => {
29
14
  expect(isPhoneSurface({ transportInterface: "ios" })).toBe(true);
@@ -64,9 +49,7 @@ describe("shouldOfferLoggedInBrowser", () => {
64
49
  expect(shouldOfferLoggedInBrowser('Invalid browser_mode "bogus"')).toBe(
65
50
  false,
66
51
  );
67
- expect(shouldOfferLoggedInBrowser("url must use http or https")).toBe(
68
- false,
69
- );
52
+ expect(shouldOfferLoggedInBrowser("url must use http or https")).toBe(false);
70
53
  });
71
54
  });
72
55
 
@@ -88,7 +71,6 @@ describe("formatLoggedInBrowserOffer", () => {
88
71
  });
89
72
  expect(offer).toContain("no in-app browser");
90
73
  expect(offer).toContain("Do not describe a browser panel");
91
- expect(offer).toContain("Mac or Windows PC");
92
74
  expect(offer).toContain(DESKTOP_APP_DOWNLOAD_URL);
93
75
  expect(offer).toContain(CHROME_WEB_STORE_INSTALL_URL);
94
76
  });
@@ -96,9 +78,7 @@ describe("formatLoggedInBrowserOffer", () => {
96
78
 
97
79
  describe("appendLoggedInBrowserOffer", () => {
98
80
  test("appends the offer once", () => {
99
- const once = appendLoggedInBrowserOffer(
100
- "Error: Navigation failed: timeout",
101
- );
81
+ const once = appendLoggedInBrowserOffer("Error: Navigation failed: timeout");
102
82
  expect(once).toContain("Error: Navigation failed: timeout");
103
83
  expect(once).toContain(DESKTOP_APP_DOWNLOAD_URL);
104
84
  const twice = appendLoggedInBrowserOffer(once);
@@ -7,22 +7,7 @@ export const DESKTOP_APP_DOWNLOAD_URL = "https://www.vellum.ai/downloads";
7
7
  export const CHROME_WEB_STORE_INSTALL_URL =
8
8
  "https://chromewebstore.google.com/detail/vellum-assistant-browser/hphbdmpffeigpcdjkckleobjmhhokpne";
9
9
 
10
- export const DESKTOP_APP_INSTALL_HINT = `Download the Vellum desktop app: ${DESKTOP_APP_DOWNLOAD_URL}. Open it, then retry.`;
11
-
12
- export type DesktopAppCapability = "files" | "screen" | "shell" | "apps";
13
-
14
- const DESKTOP_APP_CAPABILITY_ACTION: Record<DesktopAppCapability, string> = {
15
- files: "access files on your computer",
16
- screen: "view or control your screen",
17
- shell: "run commands on your computer",
18
- apps: "control apps on your computer",
19
- };
20
-
21
- export function formatDesktopAppRequired(
22
- capability: DesktopAppCapability,
23
- ): string {
24
- return `Error: The Vellum desktop app is needed to ${DESKTOP_APP_CAPABILITY_ACTION[capability]}. ${DESKTOP_APP_INSTALL_HINT}`;
25
- }
10
+ export const DESKTOP_APP_INSTALL_HINT = `Install the Vellum desktop app: ${DESKTOP_APP_DOWNLOAD_URL}`;
26
11
 
27
12
  /** User-facing install step for status userActions and command-failure hints. */
28
13
  export const CHROME_EXTENSION_INSTALL_HINT = `Install the Vellum Assistant Chrome extension from the Chrome Web Store: ${CHROME_WEB_STORE_INSTALL_URL}`;
@@ -8,7 +8,6 @@
8
8
  */
9
9
 
10
10
  import { RiskLevel } from "../../permissions/types.js";
11
- import { formatDesktopAppRequired } from "../capability-offer.js";
12
11
  import type {
13
12
  ToolContext,
14
13
  ToolDefinition,
@@ -32,7 +31,7 @@ function proxyExecute(toolName: string) {
32
31
  ): Promise<ToolExecutionResult> => {
33
32
  if (!context.proxyToolResolver) {
34
33
  return {
35
- content: formatDesktopAppRequired("screen"),
34
+ content: `No proxy resolver configured for proxy tool "${toolName}". This tool requires a connected desktop client.`,
36
35
  isError: true,
37
36
  };
38
37
  }
@@ -457,8 +456,7 @@ export const computerUseObserveTool = {
457
456
  type: "integer",
458
457
  minimum: 1,
459
458
  maximum: 4294967295,
460
- description:
461
- "macOS only: capture this native CGWindowID instead of the desktop, including only its accessibility tree. Obtain a current native window ID first; do not guess or use a browser tab ID. Applies to this observation only, not subsequent actions. Requires a desktop helper with window-capture support. Screenshot coordinates are window-relative; use accessibility element IDs for later actions, not desktop scaling.",
459
+ description: "macOS only: capture this native CGWindowID instead of the desktop, including only its accessibility tree. Obtain a current native window ID first; do not guess or use a browser tab ID. Applies to this observation only, not subsequent actions. Requires a desktop helper with window-capture support. Screenshot coordinates are window-relative; use accessibility element IDs for later actions, not desktop scaling.",
462
460
  },
463
461
  target_client_id: {
464
462
  type: "string",
@@ -5,7 +5,6 @@
5
5
  * the proxy resolver, which forwards the call to the connected desktop client.
6
6
  */
7
7
 
8
- import { formatDesktopAppRequired } from "../capability-offer.js";
9
8
  import { throwIfCancelled } from "../shared/abort.js";
10
9
  import type { ToolContext, ToolExecutionResult } from "../types.js";
11
10
 
@@ -46,7 +45,7 @@ export function forwardComputerUseProxyTool(
46
45
  }
47
46
  if (!context.proxyToolResolver) {
48
47
  return Promise.resolve({
49
- content: formatDesktopAppRequired("screen"),
48
+ content: `Cannot execute ${toolName}: no proxy resolver available. This tool requires a connected desktop client.`,
50
49
  isError: true,
51
50
  });
52
51
  }
@@ -20,7 +20,6 @@ import {
20
20
  } from "@vellumai/credential-storage";
21
21
  import type { CredentialRecord } from "@vellumai/service-contracts/credential-rpc";
22
22
 
23
- import { createCesHttpRecordBackendIfConfigured } from "../../security/ces-http-record-backend.js";
24
23
  import type { CredentialRecordBackend } from "../../security/ces-rpc-record-backend.js";
25
24
  import { getLogger } from "../../util/logger.js";
26
25
  import type { CredentialInjectionTemplate } from "./policy-types.js";
@@ -56,11 +55,6 @@ const CES_MEMORY_PATH = "ces-in-memory-credential-metadata";
56
55
  let _store: StaticCredentialMetadataStore | undefined;
57
56
  let _overridePath: string | null = null;
58
57
  let _recordBackend: CredentialRecordBackend | undefined;
59
- /**
60
- * Test override for the CES HTTP listing fallback. `undefined` uses the
61
- * production factory. `null` disables HTTP fallback.
62
- */
63
- let _httpRecordBackendOverride: CredentialRecordBackend | null | undefined;
64
58
  let _cesRecordsLoaded = false;
65
59
  let _cesLoad: Promise<void> | undefined;
66
60
  let _cesLoadGeneration = 0;
@@ -261,93 +255,6 @@ export function listCredentialMetadata(): CredentialMetadata[] {
261
255
  return getStore().list() as CredentialMetadata[];
262
256
  }
263
257
 
264
- export type CredentialRecordListResult = {
265
- records: CredentialMetadata[];
266
- unreachable: boolean;
267
- };
268
-
269
- type ListedCredentialRecords = Array<{
270
- account: string;
271
- record: CredentialRecord;
272
- }>;
273
-
274
- function backendIsAvailable(backend: CredentialRecordBackend): boolean {
275
- try {
276
- return backend.isAvailable();
277
- } catch {
278
- return false;
279
- }
280
- }
281
-
282
- async function listFromRecordBackend(
283
- backend: CredentialRecordBackend,
284
- ): Promise<ListedCredentialRecords | null> {
285
- if (!backendIsAvailable(backend)) {
286
- return null;
287
- }
288
- return backend.list();
289
- }
290
-
291
- function resolveHttpRecordBackend(): CredentialRecordBackend | null {
292
- if (_httpRecordBackendOverride !== undefined) {
293
- return _httpRecordBackendOverride;
294
- }
295
- return createCesHttpRecordBackendIfConfigured();
296
- }
297
-
298
- async function listFromHttpFallback(): Promise<ListedCredentialRecords | null> {
299
- const httpBackend = resolveHttpRecordBackend();
300
- if (!httpBackend) {
301
- return null;
302
- }
303
- return listFromRecordBackend(httpBackend);
304
- }
305
-
306
- /**
307
- * Live catalog from the credential record backend. Does not read the
308
- * daemon in-process cache, so an outage cannot be mistaken for an empty
309
- * vault. `unreachable` is true when the backend is missing, down, or
310
- * the list RPC fails, and CES HTTP failover is also unavailable.
311
- *
312
- * When the attached backend is CES RPC (or none is attached), listing
313
- * fails over to CES HTTP in containerized deployments so a down RPC
314
- * socket does not hide a healthy vault sidecar. A successful empty
315
- * catalog (`[]`) does not fall through to HTTP.
316
- *
317
- * The file-backed test store is the catalog when a test override path is set.
318
- */
319
- export async function listCredentialRecordsLive(): Promise<CredentialRecordListResult> {
320
- if (_overridePath) {
321
- return {
322
- records: getStore().list() as CredentialMetadata[],
323
- unreachable: false,
324
- };
325
- }
326
- if (_recordBackend) {
327
- const remote = await listFromRecordBackend(_recordBackend);
328
- if (remote !== null) {
329
- return {
330
- records: remote.map((entry) => entry.record as CredentialMetadata),
331
- unreachable: false,
332
- };
333
- }
334
- if (_recordBackend.name !== "ces-rpc") {
335
- return { records: [], unreachable: true };
336
- }
337
- }
338
- const httpRemote = await listFromHttpFallback();
339
- if (httpRemote !== null) {
340
- log.warn(
341
- "CES RPC credential record list unavailable. Failing over to CES HTTP.",
342
- );
343
- return {
344
- records: httpRemote.map((entry) => entry.record as CredentialMetadata),
345
- unreachable: false,
346
- };
347
- }
348
- return { records: [], unreachable: true };
349
- }
350
-
351
258
  /**
352
259
  * Delete metadata for a credential.
353
260
  */
@@ -380,10 +287,3 @@ export function _setMetadataPath(path: string | null): void {
380
287
  }
381
288
  }
382
289
  }
383
-
384
- /** @internal Test-only: override the CES HTTP listing fallback. */
385
- export function _setHttpRecordBackendForTests(
386
- backend: CredentialRecordBackend | null | undefined,
387
- ): void {
388
- _httpRecordBackendOverride = backend;
389
- }
@@ -71,9 +71,8 @@ describe("host_file_edit cross-client guards", () => {
71
71
  );
72
72
  expect(result.isError).toBe(true);
73
73
  expect(result.content).toContain(
74
- "The Vellum desktop app is needed to access files on your computer",
74
+ "no client with host_file capability is connected",
75
75
  );
76
- expect(result.content).toContain("https://www.vellum.ai/downloads");
77
76
  });
78
77
 
79
78
  test("returns 'specified client disconnected' error when targetClientId set but proxy unavailable on web", async () => {
@@ -4,7 +4,7 @@ import { supportsHostProxy } from "../../channels/types.js";
4
4
  import { HostFileProxy } from "../../daemon/host-file-proxy.js";
5
5
  import { RiskLevel } from "../../permissions/types.js";
6
6
  import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
7
- import { formatDesktopAppRequired } from "../capability-offer.js";
7
+ import { desktopClientName } from "../client-os.js";
8
8
  import { FileSystemOps } from "../shared/filesystem/file-ops-service.js";
9
9
  import { formatEditDiff } from "../shared/filesystem/format-diff.js";
10
10
  import { hostPolicy } from "../shared/filesystem/path-policy.js";
@@ -115,7 +115,7 @@ export const hostFileEditTool = {
115
115
  !HostFileProxy.instance.isAvailable()
116
116
  ) {
117
117
  return {
118
- content: formatDesktopAppRequired("files"),
118
+ content: `Error: no client with host_file capability is connected. Connect a ${desktopClientName(context)} client to use host_file from a non-desktop interface.`,
119
119
  isError: true,
120
120
  };
121
121
  }
@@ -67,9 +67,8 @@ describe("host_file_read cross-client guards", () => {
67
67
  );
68
68
  expect(result.isError).toBe(true);
69
69
  expect(result.content).toContain(
70
- "The Vellum desktop app is needed to access files on your computer",
70
+ "no client with host_file capability is connected",
71
71
  );
72
- expect(result.content).toContain("https://www.vellum.ai/downloads");
73
72
  });
74
73
 
75
74
  test("returns 'specified client disconnected' error when targetClientId set but proxy unavailable on web", async () => {
@@ -6,7 +6,7 @@ import { supportsHostProxy } from "../../channels/types.js";
6
6
  import { HostFileProxy } from "../../daemon/host-file-proxy.js";
7
7
  import { RiskLevel } from "../../permissions/types.js";
8
8
  import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
9
- import { formatDesktopAppRequired } from "../capability-offer.js";
9
+ import { desktopClientName } from "../client-os.js";
10
10
  import {
11
11
  AUDIO_EXTENSIONS,
12
12
  readAudioFile,
@@ -121,7 +121,7 @@ export const hostFileReadTool = {
121
121
  !HostFileProxy.instance.isAvailable()
122
122
  ) {
123
123
  return {
124
- content: formatDesktopAppRequired("files"),
124
+ content: `Error: no client with host_file capability is connected. Connect a ${desktopClientName(context)} client to use host_file from a non-desktop interface.`,
125
125
  isError: true,
126
126
  };
127
127
  }