@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
@@ -22,7 +22,6 @@ import {
22
22
  getConfiguredProvider,
23
23
  userMessage,
24
24
  } from "../../providers/provider-send-message.js";
25
- import { isMaxTokensStopReason } from "../../providers/stop-reasons.js";
26
25
  import { getLogger } from "../../util/logger.js";
27
26
  import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
28
27
  import { BadRequestError } from "./errors.js";
@@ -177,44 +176,9 @@ function buildCommandPrompt(body: DictationBody, stylePrompt?: string): string {
177
176
  return sections.join("\n");
178
177
  }
179
178
 
180
- export function computeMaxTokens(inputLength: number): number {
179
+ function computeMaxTokens(inputLength: number): number {
181
180
  const estimatedInputTokens = Math.ceil(inputLength / 3);
182
- // The cleanup tool call carries the whole transcript back in its `text`
183
- // argument, plus a `reasoning` string and the JSON scaffolding around both,
184
- // so the budget has to cover well more than the input alone. `max_tokens` is
185
- // a ceiling rather than a target: a call that stops short of it costs no
186
- // extra latency.
187
- return Math.max(512, estimatedInputTokens * 2 + 256);
188
- }
189
-
190
- export type CleanupRejection = "truncated";
191
-
192
- /**
193
- * Decide whether the cleanup model's rewrite is safe to use as the payload.
194
- *
195
- * The rewrite replaces what the user actually said. A token-cap stop means the
196
- * tool JSON was cut mid-argument, so however complete the `text` argument
197
- * happens to look, it is a fragment; the raw transcript is the safer payload
198
- * then. Unpolished beats wrong.
199
- *
200
- * Whether a shorter rewrite still preserved the meaning is the model's call
201
- * (the prompt asks it to drop fillers and tighten phrasing), so there is no
202
- * length check here: a deterministic ratio cannot tell a concise cleanup from
203
- * a summary.
204
- */
205
- export function resolveCleanedDictation(
206
- raw: string,
207
- cleaned: string,
208
- stopReason: string | null | undefined,
209
- ): { text: string; rejected: CleanupRejection | null } {
210
- const trimmed = cleaned.trim();
211
- if (!trimmed) {
212
- return { text: raw, rejected: null };
213
- }
214
- if (isMaxTokensStopReason(stopReason)) {
215
- return { text: raw, rejected: "truncated" };
216
- }
217
- return { text: trimmed, rejected: null };
181
+ return Math.max(256, estimatedInputTokens + 128);
218
182
  }
219
183
 
220
184
  interface DictationResult {
@@ -365,23 +329,7 @@ async function handleDictation(body: DictationBody): Promise<DictationResult> {
365
329
  ...profileMeta,
366
330
  };
367
331
  }
368
- const { text: cleanedText, rejected } = resolveCleanedDictation(
369
- transcription,
370
- input.text ?? "",
371
- response.stopReason,
372
- );
373
- if (rejected) {
374
- // Lengths only -- transcript content must never be logged.
375
- log.warn(
376
- {
377
- rejected,
378
- stopReason: response.stopReason,
379
- rawChars: transcription.length,
380
- cleanedChars: input.text?.trim().length ?? 0,
381
- },
382
- "Dictation cleanup rejected, using raw transcription",
383
- );
384
- }
332
+ const cleanedText = input.text?.trim() || transcription;
385
333
  const normalizedText = applyDictionary(cleanedText, profile.dictionary);
386
334
  return {
387
335
  text: normalizedText,
@@ -39,7 +39,6 @@ import { ROUTES as CALL_ROUTES } from "./call-routes.js";
39
39
  import { ROUTES as CHANNEL_AVAILABILITY_ROUTES } from "./channel-availability-routes.js";
40
40
  import { ROUTES as CHANNEL_READINESS_ROUTES } from "./channel-readiness-routes.js";
41
41
  import { CHANNEL_ROUTES } from "./channel-route-definitions.js";
42
- import { ROUTES as CHANNEL_SEND_ROUTES } from "./channel-send-routes.js";
43
42
  import { ROUTES as CHANNEL_VERIFICATION_ROUTES } from "./channel-verification-routes.js";
44
43
  import { ROUTES as CHATGPT_SUBSCRIPTION_AUTH_ROUTES } from "./chatgpt-subscription-auth-routes.js";
45
44
  import { ROUTES as CLIENT_ROUTES } from "./client-routes.js";
@@ -63,7 +62,6 @@ import { ROUTES as DEBUG_BASH_ROUTES } from "./debug-bash-routes.js";
63
62
  import { ROUTES as DEBUG_ROUTES } from "./debug-routes.js";
64
63
  import { ROUTES as DEFAULT_PROVIDER_ROUTES } from "./default-provider-routes.js";
65
64
  import { ROUTES as DEFER_ROUTES } from "./defer-routes.js";
66
- import { ROUTES as DESKTOP_SETUP_ROUTES } from "./desktop-setup-routes.js";
67
65
  import { ROUTES as DIAGNOSTICS_ROUTES } from "./diagnostics-routes.js";
68
66
  import { ROUTES as DISK_PRESSURE_ROUTES } from "./disk-pressure-routes.js";
69
67
  import { ROUTES as DOCUMENT_COMMENT_ROUTES } from "./document-comments-routes.js";
@@ -193,7 +191,6 @@ export const ROUTES: RouteDefinition[] = [
193
191
  ...CHANNEL_VERIFICATION_ROUTES,
194
192
  ...CHANNEL_AVAILABILITY_ROUTES,
195
193
  ...CHANNEL_READINESS_ROUTES,
196
- ...CHANNEL_SEND_ROUTES,
197
194
  ...BROWSER_ROUTES,
198
195
  ...BROWSER_TABS_ROUTES,
199
196
  ...BTW_ROUTES,
@@ -221,7 +218,6 @@ export const ROUTES: RouteDefinition[] = [
221
218
  ...DEBUG_BASH_ROUTES,
222
219
  ...DEBUG_ROUTES,
223
220
  ...DEFAULT_PROVIDER_ROUTES,
224
- ...DESKTOP_SETUP_ROUTES,
225
221
  ...DIAGNOSTICS_ROUTES,
226
222
  ...DISK_PRESSURE_ROUTES,
227
223
  ...RESOURCE_PRESSURE_ROUTES,
@@ -22,7 +22,6 @@ import { join } from "node:path";
22
22
  import { and, desc, eq, gte, lte } from "drizzle-orm";
23
23
  import { z } from "zod";
24
24
 
25
- import { overlayWorkspaceMcpForConfigRead } from "../../mcp/workspace-mcp-config.js";
26
25
  import { getDb, getLogsDb } from "../../persistence/db-connection.js";
27
26
  import {
28
27
  llmRequestLogs,
@@ -569,7 +568,6 @@ function readSanitizedConfig(): Record<string, unknown> | undefined {
569
568
  }
570
569
  }
571
570
 
572
- overlayWorkspaceMcpForConfigRead(config);
573
571
  const mcpServers = asRecord(asRecord(config.mcp)?.servers);
574
572
  for (const server of Object.values(mcpServers ?? {})) {
575
573
  const transport = asRecord(asRecord(server)?.transport);
@@ -14,7 +14,8 @@
14
14
 
15
15
  import { z } from "zod";
16
16
 
17
- import type { McpServerConfig } from "../../config/schemas/mcp.js";
17
+ import { loadRawConfig, saveRawConfig } from "../../config/loader.js";
18
+ import type { McpConfig, McpServerConfig } from "../../config/schemas/mcp.js";
18
19
  import { estimateToolDefinitionTokens } from "../../context/token-estimator.js";
19
20
  import { reloadMcpServers } from "../../daemon/mcp-reload-service.js";
20
21
  import { McpClient } from "../../mcp/client.js";
@@ -30,10 +31,6 @@ import {
30
31
  deleteMcpOAuthCredentials,
31
32
  hasMcpOAuthTokens,
32
33
  } from "../../mcp/mcp-oauth-provider.js";
33
- import {
34
- loadWorkspaceMcpConfig,
35
- saveWorkspaceMcpConfig,
36
- } from "../../mcp/workspace-mcp-config.js";
37
34
  import { readPluginMcpServers } from "../../plugins/mcp-servers.js";
38
35
  import { getMcpToolsByServer } from "../../tools/registry.js";
39
36
  import { getLogger } from "../../util/logger.js";
@@ -68,18 +65,6 @@ const McpAddParams = z.object({
68
65
 
69
66
  const McpRemoveParams = z.object({ name: z.string() });
70
67
 
71
- function persistWorkspaceMcpConfig(config: {
72
- servers: Record<string, McpServerConfig>;
73
- }): void {
74
- try {
75
- saveWorkspaceMcpConfig(config);
76
- } catch (err) {
77
- throw new InternalError(
78
- err instanceof Error ? err.message : String(err),
79
- );
80
- }
81
- }
82
-
83
68
  async function handleMcpAuthStart({
84
69
  body,
85
70
  }: {
@@ -91,7 +76,8 @@ async function handleMcpAuthStart({
91
76
  }> {
92
77
  const { serverId } = parseBody(McpServerIdParams, body);
93
78
 
94
- const servers = loadWorkspaceMcpConfig().servers;
79
+ const raw = loadRawConfig();
80
+ const servers = (raw.mcp as Partial<McpConfig> | undefined)?.servers ?? {};
95
81
  const serverConfig = servers[serverId];
96
82
 
97
83
  if (!serverConfig) {
@@ -267,7 +253,9 @@ function detectAuthType(headers: Record<string, string>): "bearer" | "api-key" {
267
253
  async function handleMcpList(_args: {
268
254
  body?: Record<string, unknown>;
269
255
  }): Promise<{ servers: McpServerEntry[] }> {
270
- const servers = loadWorkspaceMcpConfig().servers;
256
+ const raw = loadRawConfig();
257
+ const mcpConfig = raw.mcp as Partial<McpConfig> | undefined;
258
+ const servers = mcpConfig?.servers ?? {};
271
259
  const configEntries = (
272
260
  Object.entries(servers) as [string, McpServerConfig][]
273
261
  ).filter(([, config]) => config && typeof config === "object");
@@ -446,13 +434,18 @@ async function handleMcpUpdate({
446
434
  }): Promise<{ updated: true }> {
447
435
  const { name, headers } = parseBody(McpUpdateParams, body);
448
436
 
449
- const servers = loadWorkspaceMcpConfig().servers;
450
- const server = servers[name];
437
+ const raw = loadRawConfig();
438
+ const mcpConfig = raw.mcp as Record<string, unknown> | undefined;
439
+ const serverMap = mcpConfig?.servers as
440
+ | Record<string, Record<string, unknown>>
441
+ | undefined;
451
442
 
452
- if (!server) {
443
+ if (!serverMap || !serverMap[name]) {
453
444
  throw new NotFoundError(`MCP server "${name}" not found.`);
454
445
  }
455
446
 
447
+ const server = serverMap[name];
448
+
456
449
  if (headers !== undefined) {
457
450
  const transport = server.transport as Record<string, unknown> | undefined;
458
451
  if (
@@ -481,7 +474,7 @@ async function handleMcpUpdate({
481
474
  }
482
475
  }
483
476
 
484
- persistWorkspaceMcpConfig({ servers });
477
+ saveRawConfig(raw);
485
478
  triggerReload("internal_mcp_update");
486
479
 
487
480
  return { updated: true };
@@ -501,7 +494,7 @@ async function handleMcpAdd({
501
494
  body,
502
495
  );
503
496
 
504
- let transport: McpServerConfig["transport"];
497
+ let transport: Record<string, unknown>;
505
498
  switch (transportType) {
506
499
  case "stdio":
507
500
  if (!command) {
@@ -524,16 +517,27 @@ async function handleMcpAdd({
524
517
  );
525
518
  }
526
519
 
527
- const servers = { ...loadWorkspaceMcpConfig().servers };
520
+ const raw = loadRawConfig();
521
+ if (!raw.mcp) {
522
+ raw.mcp = { servers: {} };
523
+ }
524
+ const mcpConfig = raw.mcp as Record<string, unknown>;
525
+ if (!mcpConfig.servers) {
526
+ mcpConfig.servers = {};
527
+ }
528
+ const serverMap = mcpConfig.servers as Record<string, unknown>;
528
529
 
529
- if (servers[name]) {
530
+ if (serverMap[name]) {
530
531
  throw new BadRequestError(
531
532
  `MCP server "${name}" already exists. Remove it first with: assistant mcp remove ${name}`,
532
533
  );
533
534
  }
534
535
 
535
- servers[name] = { transport };
536
+ serverMap[name] = {
537
+ transport,
538
+ };
536
539
 
540
+ // Store auth headers in credential store, not config
537
541
  if (headers && Object.keys(headers).length > 0) {
538
542
  const ok = await setMcpHeaders(name, headers);
539
543
  if (!ok) {
@@ -543,7 +547,7 @@ async function handleMcpAdd({
543
547
  }
544
548
  }
545
549
 
546
- persistWorkspaceMcpConfig({ servers });
550
+ saveRawConfig(raw);
547
551
  triggerReload("internal_mcp_add");
548
552
 
549
553
  return { added: true };
@@ -560,7 +564,8 @@ async function handleMcpAuthRevoke({
560
564
  }): Promise<{ revoked: true }> {
561
565
  const { serverId } = parseBody(McpServerIdParams, body);
562
566
 
563
- const servers = loadWorkspaceMcpConfig().servers;
567
+ const raw = loadRawConfig();
568
+ const servers = (raw.mcp as Partial<McpConfig> | undefined)?.servers ?? {};
564
569
  const serverConfig = servers[serverId];
565
570
 
566
571
  if (!serverConfig) {
@@ -597,29 +602,32 @@ async function handleMcpRemove({
597
602
  }): Promise<{ removed: true }> {
598
603
  const { name } = parseBody(McpRemoveParams, body);
599
604
 
600
- const servers = { ...loadWorkspaceMcpConfig().servers };
601
- const serverConfig = servers[name];
605
+ const raw = loadRawConfig();
606
+ const mcpConfig = raw.mcp as Record<string, unknown> | undefined;
607
+ const serverMap = mcpConfig?.servers as Record<string, unknown> | undefined;
602
608
 
603
- if (!serverConfig) {
609
+ if (!serverMap || !serverMap[name]) {
604
610
  throw new NotFoundError(`MCP server "${name}" not found.`);
605
611
  }
606
612
 
607
- if (
608
- serverConfig.transport.type === "sse" ||
609
- serverConfig.transport.type === "streamable-http"
610
- ) {
613
+ // Best-effort cleanup of credentials stored for this server
614
+ const serverConfig = serverMap[name] as Record<string, unknown>;
615
+ const transport = serverConfig?.transport as
616
+ | Record<string, unknown>
617
+ | undefined;
618
+ if (transport?.type === "sse" || transport?.type === "streamable-http") {
611
619
  try {
612
620
  await Promise.all([
613
621
  deleteMcpOAuthCredentials(name),
614
622
  deleteMcpHeaders(name),
615
623
  ]);
616
624
  } catch {
617
- // Credentials may not exist.
625
+ // Ignore — credentials may not exist
618
626
  }
619
627
  }
620
628
 
621
- delete servers[name];
622
- persistWorkspaceMcpConfig({ servers });
629
+ delete serverMap[name];
630
+ saveRawConfig(raw);
623
631
  triggerReload("internal_mcp_remove");
624
632
 
625
633
  return { removed: true };
@@ -22,8 +22,8 @@ import { PassThrough, Readable } from "node:stream";
22
22
 
23
23
  import { z } from "zod";
24
24
 
25
+ import { getPlatformAssistantId } from "../../config/env.js";
25
26
  import { invalidateConfigCache } from "../../config/loader.js";
26
- import { resolvePlatformAssistantId } from "../../config/platform-identity.js";
27
27
  import { getAssistantName } from "../../daemon/identity-helpers.js";
28
28
  import { runAsyncSqlite } from "../../persistence/db-async-query.js";
29
29
  import {
@@ -236,15 +236,28 @@ interface ExportManifestInputs {
236
236
  /**
237
237
  * Resolve the `assistant.id` for an export.
238
238
  *
239
- * In-memory identity (validate rehydration or secret-routes) first, then
240
- * the vault copy of `platform_assistant_id`. The schema requires `id` to be
241
- * non-empty, so we fall back to `DAEMON_INTERNAL_ASSISTANT_ID` rather than
242
- * the empty string.
239
+ * Mirrors `platform/client.ts`'s precedence: in-memory override (set at
240
+ * daemon startup or by secret-routes) → credential store → daemon-internal
241
+ * fallback. The schema requires `id` to be non-empty, so we fall back to
242
+ * `DAEMON_INTERNAL_ASSISTANT_ID` rather than the empty string.
243
243
  */
244
244
  async function resolveAssistantId(): Promise<string> {
245
- const resolved = await resolvePlatformAssistantId();
246
- if (resolved) {
247
- return resolved;
245
+ const inMemory = getPlatformAssistantId();
246
+ if (inMemory) {
247
+ return inMemory;
248
+ }
249
+ try {
250
+ const stored = await getSecureKeyAsync(
251
+ credentialKey("vellum", "platform_assistant_id"),
252
+ );
253
+ if (stored) {
254
+ return stored;
255
+ }
256
+ } catch (err) {
257
+ log.warn(
258
+ { err },
259
+ "Failed to read platform_assistant_id from credential store; falling back to daemon-internal id",
260
+ );
248
261
  }
249
262
  return DAEMON_INTERNAL_ASSISTANT_ID;
250
263
  }
@@ -39,17 +39,7 @@ import {
39
39
  } from "@vellumai/service-contracts/platform-credential";
40
40
  import { z } from "zod";
41
41
 
42
- import {
43
- setPlatformAssistantId,
44
- setPlatformBaseUrl,
45
- setPlatformOrganizationId,
46
- setPlatformUserId,
47
- } from "../../config/env.js";
48
42
  import { isPlatformRemote } from "../../config/env-registry.js";
49
- import {
50
- resolvePlatformOrganizationId,
51
- resolvePlatformUserId,
52
- } from "../../config/platform-identity.js";
53
43
  import {
54
44
  registerCallbackRoute,
55
45
  resolvePlatformCallbackRegistrationContext,
@@ -299,12 +289,24 @@ async function handlePlatformStatus(
299
289
  ): Promise<PlatformStatusResponse> {
300
290
  const context = await resolvePlatformCallbackRegistrationContext();
301
291
 
302
- const [organizationId, userId, webhookSecretRaw] = await Promise.all([
303
- resolvePlatformOrganizationId(),
304
- resolvePlatformUserId(),
292
+ const [orgIdRaw, userIdRaw, webhookSecretRaw] = await Promise.all([
293
+ getSecureKeyAsync(
294
+ credentialKey(
295
+ CREDENTIAL_KEYS.organizationId.service,
296
+ CREDENTIAL_KEYS.organizationId.field,
297
+ ),
298
+ ),
299
+ getSecureKeyAsync(
300
+ credentialKey(
301
+ CREDENTIAL_KEYS.userId.service,
302
+ CREDENTIAL_KEYS.userId.field,
303
+ ),
304
+ ),
305
305
  getSecureKeyAsync(credentialKey("vellum", "webhook_secret")),
306
306
  ]);
307
307
 
308
+ const organizationId = orgIdRaw?.trim() ?? "";
309
+ const userId = userIdRaw?.trim() ?? "";
308
310
  const hasWebhookSecret = !!webhookSecretRaw;
309
311
 
310
312
  return {
@@ -465,11 +467,6 @@ async function handlePlatformDisconnect(
465
467
  );
466
468
  }
467
469
 
468
- setPlatformBaseUrl(undefined);
469
- setPlatformAssistantId(undefined);
470
- setPlatformOrganizationId(undefined);
471
- setPlatformUserId(undefined);
472
-
473
470
  // Notify connected clients
474
471
  broadcastMessage({ type: "platform_disconnected" });
475
472
 
@@ -159,31 +159,3 @@ describe("serializeConversationSummary · enabledPlugins", () => {
159
159
  expect("enabledPlugins" in summary).toBe(false);
160
160
  });
161
161
  });
162
-
163
- describe("serializeConversationSummary · title keys", () => {
164
- test("resolves a stored title key for the locale", () => {
165
- const summary = serializeConversationSummary({
166
- conversation: makeConversationRow({
167
- title: "conversation.title.generating",
168
- }),
169
- displayMeta: { displayOrder: null, isPinned: false, groupId: null },
170
- parentCache: new Map(),
171
- isProcessing: false,
172
- locale: "es",
173
- });
174
- expect(summary.title).toBe("Generando título...");
175
- expect("titleState" in summary).toBe(false);
176
- });
177
-
178
- test("passes a stored display string through", () => {
179
- const summary = serialize(
180
- makeConversationRow({ title: "Untitled Conversation" }),
181
- );
182
- expect(summary.title).toBe("Untitled Conversation");
183
- });
184
-
185
- test("passes a custom title through", () => {
186
- const summary = serialize(makeConversationRow({ title: "Weekly planning" }));
187
- expect(summary.title).toBe("Weekly planning");
188
- });
189
- });
@@ -8,10 +8,6 @@
8
8
 
9
9
  import { parseChannelId } from "../../channels/types.js";
10
10
  import { normalizeConversationType } from "../../daemon/message-types/shared.js";
11
- import {
12
- resolveConversationTitle,
13
- type SupportedLocale,
14
- } from "../../i18n/index.js";
15
11
  import { buildChannelBindingMetadata } from "../../messaging/channel-binding-metadata.js";
16
12
  import {
17
13
  type AttentionState,
@@ -82,7 +78,6 @@ interface ForkLineage {
82
78
  function buildForkLineage(
83
79
  conversation: ConversationRow,
84
80
  parentCache: Map<string, ConversationRow | null>,
85
- locale?: SupportedLocale,
86
81
  ): ForkLineage {
87
82
  const parentConversationId = conversation.forkParentConversationId;
88
83
  const parentMessageId = conversation.forkParentMessageId;
@@ -106,7 +101,7 @@ function buildForkLineage(
106
101
  forkParent: {
107
102
  conversationId: parentConversationId,
108
103
  messageId: parentMessageId,
109
- title: resolveConversationTitle(parentConversation.title, locale),
104
+ title: parentConversation.title ?? "Untitled",
110
105
  },
111
106
  };
112
107
  }
@@ -183,11 +178,6 @@ export function serializeConversationSummary(params: {
183
178
  * with no daemon-store coupling.
184
179
  */
185
180
  isProcessing: boolean;
186
- /**
187
- * Locale used to resolve stored title keys. Omitted locale is English
188
- * inside {@link resolveConversationTitle}.
189
- */
190
- locale?: SupportedLocale;
191
181
  }) {
192
182
  const {
193
183
  conversation,
@@ -196,15 +186,14 @@ export function serializeConversationSummary(params: {
196
186
  displayMeta,
197
187
  parentCache,
198
188
  isProcessing,
199
- locale,
200
189
  } = params;
201
190
  const originChannel = parseChannelId(conversation.originChannel);
202
191
  const assistantAttention = buildAssistantAttention(attentionState);
203
- const forkLineage = buildForkLineage(conversation, parentCache, locale);
192
+ const forkLineage = buildForkLineage(conversation, parentCache);
204
193
 
205
194
  return {
206
195
  id: conversation.id,
207
- title: resolveConversationTitle(conversation.title, locale),
196
+ title: conversation.title ?? "Untitled",
208
197
  createdAt: conversation.createdAt,
209
198
  updatedAt: conversation.updatedAt,
210
199
  lastMessageAt: conversation.lastMessageAt,
@@ -264,7 +253,6 @@ export function serializeConversationSummary(params: {
264
253
  */
265
254
  export function buildConversationDetailResponse(
266
255
  conversationId: string,
267
- locale?: SupportedLocale,
268
256
  ): { conversation: ReturnType<typeof serializeConversationSummary> } | null {
269
257
  const conversation = getConversation(conversationId);
270
258
  if (!conversation || conversation.conversationType === "private") {
@@ -286,7 +274,6 @@ export function buildConversationDetailResponse(
286
274
  // Checks in-memory flag first (hot path), falls back to the
287
275
  // persisted `processing_started_at` column for cold conversations.
288
276
  isProcessing: isConversationProcessing(conversation.id),
289
- locale,
290
277
  }),
291
278
  };
292
279
  }
@@ -4,7 +4,6 @@ import {
4
4
  conversationMetadataSyncTag,
5
5
  SYNC_TAGS,
6
6
  } from "../../daemon/message-types/sync.js";
7
- import { resolveConversationTitle } from "../../i18n/index.js";
8
7
  import { syncAvatarToPlatform } from "../../platform/sync-avatar.js";
9
8
  import { getAvatarImagePath } from "../../util/platform.js";
10
9
  import { broadcastMessage } from "../assistant-event-hub.js";
@@ -258,7 +257,7 @@ export function publishConversationTitleChanged(
258
257
  {
259
258
  type: "conversation_title_updated",
260
259
  conversationId,
261
- title: resolveConversationTitle(title),
260
+ title,
262
261
  },
263
262
  conversationId,
264
263
  );
@@ -195,7 +195,7 @@ async function main(): Promise<void> {
195
195
  //
196
196
  // Bounded by MCP_STARTUP_GRACE_MS: unreachable servers must not hold the
197
197
  // schedules that do not use them. The connect runs on past the deadline.
198
- const mcpStartup = startConfiguredMcpServers();
198
+ const mcpStartup = startConfiguredMcpServers(getConfig().mcp);
199
199
  await Promise.race([
200
200
  mcpStartup,
201
201
  // Unref'd so a connect that beats the deadline leaves nothing pending.
@@ -11,11 +11,6 @@ import { getLogger } from "../util/logger.js";
11
11
  const log = getLogger("ces-rpc-record-backend");
12
12
 
13
13
  export interface CredentialRecordBackend {
14
- /**
15
- * Transport id. `"ces-rpc"` is the attached CES socket backend; live
16
- * catalog listing fails over to CES HTTP when that transport is down.
17
- */
18
- readonly name?: string;
19
14
  isAvailable(): boolean;
20
15
  get(account: string): Promise<CredentialRecord | undefined>;
21
16
  set(account: string, record: CredentialRecord): Promise<boolean>;
@@ -34,8 +29,6 @@ export interface CredentialRecordBackend {
34
29
  }
35
30
 
36
31
  export class CesRpcRecordBackend implements CredentialRecordBackend {
37
- readonly name = "ces-rpc";
38
-
39
32
  constructor(private readonly client: CesClient) {}
40
33
 
41
34
  isAvailable(): boolean {
@@ -33,6 +33,7 @@
33
33
  import { readdir } from "node:fs/promises";
34
34
  import { join } from "node:path";
35
35
 
36
+ import type { SkillSummary } from "../config/skills.js";
36
37
  import type { TrustContext } from "../daemon/trust-context-types.js";
37
38
  import type { TrustClass } from "../runtime/actor-trust-resolver.js";
38
39
  import { truncate as truncateText } from "../util/truncate.js";
@@ -55,6 +56,15 @@ export interface AdvisorContextSources {
55
56
  * from the catalog section, mirroring the `skill_load` gate.
56
57
  */
57
58
  enabledPluginSet?: ReadonlySet<string> | null;
59
+ /**
60
+ * Pre-resolved skill catalog, typically the parent conversation's warm
61
+ * `skillProjectionCache.catalog`. Passing it keeps the synchronous on-disk
62
+ * catalog scan out of the consult path (and matches the catalog view the
63
+ * parent turn's tool projection used). When absent, the section falls back
64
+ * to a fresh `loadSkillCatalog()` scan, the same call every agent turn's
65
+ * projection already makes.
66
+ */
67
+ skillCatalog?: readonly SkillSummary[];
58
68
  }
59
69
 
60
70
  /** Cap a block so the assembled context never balloons the consult prompt. */
@@ -104,6 +114,7 @@ async function buildToolsSection(
104
114
  */
105
115
  async function buildSkillsSection(
106
116
  enabledPluginSet: ReadonlySet<string> | null | undefined,
117
+ preResolvedCatalog: readonly SkillSummary[] | undefined,
107
118
  ): Promise<string | null> {
108
119
  try {
109
120
  const [
@@ -119,17 +130,19 @@ async function buildSkillsSection(
119
130
  ]);
120
131
  const config = getConfig();
121
132
  const pluginScope = enabledPluginSet ?? null;
122
- const catalog = loadSkillCatalog().filter((skill) => {
123
- if (
124
- pluginScope !== null &&
125
- skill.owner?.kind === "plugin" &&
126
- !pluginScope.has(skill.owner.id)
127
- ) {
128
- return false;
129
- }
130
- const flagKey = skillFlagKey(skill);
131
- return !flagKey || isAssistantFeatureFlagEnabled(flagKey, config);
132
- });
133
+ const catalog = (preResolvedCatalog ?? loadSkillCatalog()).filter(
134
+ (skill) => {
135
+ if (
136
+ pluginScope !== null &&
137
+ skill.owner?.kind === "plugin" &&
138
+ !pluginScope.has(skill.owner.id)
139
+ ) {
140
+ return false;
141
+ }
142
+ const flagKey = skillFlagKey(skill);
143
+ return !flagKey || isAssistantFeatureFlagEnabled(flagKey, config);
144
+ },
145
+ );
133
146
  if (catalog.length === 0) {
134
147
  return null;
135
148
  }
@@ -371,7 +384,7 @@ export async function buildAdvisorContext(
371
384
  const sections = await Promise.all(
372
385
  [
373
386
  buildToolsSection(sources.allowedToolNames),
374
- buildSkillsSection(sources.enabledPluginSet),
387
+ buildSkillsSection(sources.enabledPluginSet, sources.skillCatalog),
375
388
  buildWorkspaceSection(sources),
376
389
  ].map((section) => withSectionTimeout(section, sectionTimeoutMs)),
377
390
  );
@@ -90,9 +90,7 @@ describe("executeAcpListAgents", () => {
90
90
  const codex = parsed.agents.find((a: { id: string }) => a.id === "codex");
91
91
  expect(codex.available).toBe(false);
92
92
  expect(codex.unavailableReason).toBe("'codex-acp' is not on PATH");
93
- expect(codex.setupHint).toBe(
94
- "bun add -g @agentclientprotocol/codex-acp@1.10.0",
95
- );
93
+ expect(codex.setupHint).toBe("bun add -g @agentclientprotocol/codex-acp");
96
94
 
97
95
  const claude = parsed.agents.find((a: { id: string }) => a.id === "claude");
98
96
  expect(claude.available).toBe(true);