@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
@@ -6,7 +6,6 @@
6
6
  import { randomUUID } from "node:crypto";
7
7
  import { basename } from "node:path";
8
8
 
9
- import type { SessionConfigOption } from "@agentclientprotocol/sdk";
10
9
  import { eq, inArray } from "drizzle-orm";
11
10
 
12
11
  import type { AcpSessionUpdateEvent } from "../api/events/acp-session-update.js";
@@ -27,27 +26,17 @@ import { AcpAgentProcess } from "./agent-process.js";
27
26
  import {
28
27
  ACP_AUTH_RECOVERY_GUIDANCE,
29
28
  ACP_CLAUDE_AUTH_REQUIRED_CODE,
30
- AcpAuthRequiredError,
31
29
  CLAUDE_ACP_COMMAND,
32
30
  isAcpAuthRequired,
33
31
  isClaudeAuthFailureMessage,
34
- requestErrorReason,
35
32
  } from "./auth-required.js";
36
33
  import { resolveAgentWithAutoInstall } from "./auto-install.js";
37
34
  import { VellumAcpClientHandler } from "./client-handler.js";
38
35
  import { deriveFailureError } from "./failure-error.js";
39
- import type { AcpModelInfo } from "./model-config.js";
40
- import { deriveModelInfo, resolveAcpModel } from "./model-config.js";
41
36
  import { prepareAgentEnv } from "./prepare-agent-env.js";
42
37
  import { formatResolveFailure } from "./resolve-agent.js";
43
38
  import { claudeResumeHint } from "./resume-hint.js";
44
- import {
45
- ACP_LIVE_STATUSES,
46
- type AcpAgentConfig,
47
- AcpConfigOptionRefusedError,
48
- type AcpSessionState,
49
- isLiveAcpStatus,
50
- } from "./types.js";
39
+ import type { AcpAgentConfig, AcpSessionState } from "./types.js";
51
40
 
52
41
  const log = getLogger("acp:session-manager");
53
42
 
@@ -57,9 +46,7 @@ const log = getLogger("acp:session-manager");
57
46
  * and the marker promises a repair only the Connect Claude flow can perform.
58
47
  * Checks both auth-failure shapes (see `auth-required.ts`) against both the
59
48
  * raw rejection and the derived failure message, since `deriveFailureError`
60
- * may replace one with the other. The raw side reads both the rejection's own
61
- * message and its decoded reason, because an adapter's words travel in either
62
- * depending on how it raised the error.
49
+ * may replace one with the other.
63
50
  */
64
51
  function claudeAuthRequiredCode(
65
52
  err: unknown,
@@ -72,7 +59,6 @@ function claudeAuthRequiredCode(
72
59
  const rawMessage = err instanceof Error ? err.message : String(err);
73
60
  return isAcpAuthRequired(err) ||
74
61
  isClaudeAuthFailureMessage(rawMessage) ||
75
- isClaudeAuthFailureMessage(requestErrorReason(err)) ||
76
62
  isClaudeAuthFailureMessage(failureMessage)
77
63
  ? ACP_CLAUDE_AUTH_REQUIRED_CODE
78
64
  : undefined;
@@ -139,28 +125,6 @@ interface SessionEntry {
139
125
  * rather than needing a sweep to retire it. Absent for agents that use no
140
126
  * Claude credential. */
141
127
  credentialDigest?: string;
142
- /** Config id of the adapter's model selector, absent when it advertises
143
- * none. Both the id to write a model back through and the flag that says
144
- * this session has a model to publish at all. */
145
- modelConfigId?: string;
146
- }
147
-
148
- /** What a spawn or resume pin did about the model it was asked for. */
149
- interface ModelPinResult {
150
- /** False when the session is not on the model asked for: the adapter
151
- * refused it, or advertises no selector at all. */
152
- applied: boolean;
153
- /** Message to relay, present only when the caller named the model. */
154
- warning?: string;
155
- }
156
-
157
- /**
158
- * The sentence a caller who named a model gets when the session has no model
159
- * selector to put it through, whether the adapter never advertised one or its
160
- * answer to the pin dropped the one it had.
161
- */
162
- function noModelSelectionWarning(agentId: string): string {
163
- return `Agent "${agentId}" does not support model selection, so the session is running on the agent's own model.`;
164
128
  }
165
129
 
166
130
  /**
@@ -185,10 +149,6 @@ export interface AcpCancellationOptions {
185
149
 
186
150
  export class AcpSessionManager {
187
151
  private sessions = new Map<string, SessionEntry>();
188
- /** Scopes process-local model revisions across assistant restarts. */
189
- private readonly modelRevisionEpoch = randomUUID();
190
- /** Orders model snapshots within this assistant process. */
191
- private modelRevision = 0;
192
152
  /**
193
153
  * Per-session ring buffer of wire-shaped update events forwarded to
194
154
  * clients. Bounded by event count and aggregate JSON byte size; oldest
@@ -241,7 +201,7 @@ export class AcpSessionManager {
241
201
  stopReason: "daemon_restarted",
242
202
  completedAt: Date.now(),
243
203
  })
244
- .where(inArray(acpSessionHistory.status, [...ACP_LIVE_STATUSES]))
204
+ .where(inArray(acpSessionHistory.status, ["running", "initializing"]))
245
205
  .run();
246
206
  } catch (err) {
247
207
  log.error(
@@ -283,12 +243,6 @@ export class AcpSessionManager {
283
243
  *
284
244
  * The prompt is fired in the background — results stream via sessionUpdate
285
245
  * callbacks and completion/error messages are sent when the prompt finishes.
286
- *
287
- * `requestedModel` is the normalized explicit request this spawn acted on.
288
- * `effectiveModel` is the model the adapter reports for the live session.
289
- * `modelWarning` comes back when the adapter refused the model the session
290
- * was asked for: the caller relays the reason rather than treating the spawn
291
- * as failed.
292
246
  */
293
247
  async spawn(
294
248
  agentId: string,
@@ -297,17 +251,11 @@ export class AcpSessionManager {
297
251
  cwd: string,
298
252
  parentConversationId: string,
299
253
  sendToVellum: (msg: AssistantEvent) => void,
300
- options?: { parentToolUseId?: string; model?: string },
301
- cancellation?: AcpCancellationOptions,
302
- ): Promise<{
303
- acpSessionId: string;
304
- protocolSessionId: string;
305
- requestedModel?: string;
306
- effectiveModel?: string;
307
- modelWarning?: string;
308
- }> {
254
+ parentToolUseId?: string,
255
+ opts?: AcpCancellationOptions,
256
+ ): Promise<{ acpSessionId: string; protocolSessionId: string }> {
309
257
  this.assertCapacity();
310
- cancellation?.signal?.throwIfAborted();
258
+ opts?.signal?.throwIfAborted();
311
259
 
312
260
  const acpSessionId = randomUUID();
313
261
  log.info(
@@ -329,20 +277,11 @@ export class AcpSessionManager {
329
277
  cwd,
330
278
  startedAt: Date.now(),
331
279
  sendToVellum,
332
- parentToolUseId: options?.parentToolUseId,
280
+ parentToolUseId,
333
281
  task,
334
282
  });
335
283
  const { process: agentProcess, state } = entry;
336
284
 
337
- const requestedModel = options?.model?.trim() || undefined;
338
- // Resolved before the adapter is asked for anything, so the ladder is
339
- // walked once against the config the spawn was made under.
340
- const resolvedModel = resolveAcpModel({
341
- requestedModel,
342
- agentModel: agentConfig.model,
343
- });
344
-
345
- let configOptions: SessionConfigOption[] = [];
346
285
  try {
347
286
  log.info({ acpSessionId, agentId }, "ACP spawning child process");
348
287
  agentProcess.spawn(cwd);
@@ -352,9 +291,7 @@ export class AcpSessionManager {
352
291
  );
353
292
  await agentProcess.initialize();
354
293
  log.info({ acpSessionId, agentId }, "ACP creating session");
355
- const created = await agentProcess.createSession(cwd);
356
- const acpProtocolSessionId = created.sessionId;
357
- configOptions = created.configOptions;
294
+ const acpProtocolSessionId = await agentProcess.createSession(cwd);
358
295
  state.acpSessionId = acpProtocolSessionId;
359
296
  state.status = "running";
360
297
  log.info(
@@ -380,47 +317,16 @@ export class AcpSessionManager {
380
317
  // awaits, and the child process is already running. A turn stopped in that
381
318
  // window must not be told a session started, nor have the agent handed the
382
319
  // task, so the process is torn down and the abort let out instead.
383
- if (cancellation?.signal?.aborted) {
320
+ if (opts?.signal?.aborted) {
384
321
  log.info(
385
322
  { acpSessionId, agentId },
386
323
  "ACP spawn cancelled during setup; tearing the session down",
387
324
  );
388
325
  this.teardownSession(acpSessionId, entry);
389
- cancellation.signal.throwIfAborted();
390
- }
391
-
392
- let modelWarning: string | undefined;
393
- try {
394
- ({ warning: modelWarning } = await this.pinSessionModel(
395
- entry,
396
- configOptions,
397
- requestedModel,
398
- resolvedModel,
399
- ));
400
- } catch (err) {
401
- log.error(
402
- { acpSessionId, agentId, err },
403
- "ACP spawn failed while applying the model",
404
- );
405
- const failure = this.classifyPinFailure(err, agentId, agentConfig);
406
- // No prompt has fired yet, so no permissions can be pending.
407
- this.teardownSession(acpSessionId, entry);
408
- throw failure;
409
- }
410
-
411
- // Recheck: the model pin is an await too, and everything below it either
412
- // announces the session or hands the agent the task.
413
- if (cancellation?.signal?.aborted) {
414
- log.info(
415
- { acpSessionId, agentId },
416
- "ACP spawn cancelled during the model pin; tearing the session down",
417
- );
418
- this.teardownSession(acpSessionId, entry);
419
- cancellation.signal.throwIfAborted();
326
+ opts.signal.throwIfAborted();
420
327
  }
421
328
 
422
329
  this.sendSpawnedEvent(acpSessionId, entry);
423
- this.sendModelEvent(acpSessionId, entry);
424
330
 
425
331
  // Fire prompt in the background, do not await
426
332
  entry.currentPrompt = this.firePromptInBackground(
@@ -430,179 +336,7 @@ export class AcpSessionManager {
430
336
  task,
431
337
  );
432
338
 
433
- return {
434
- acpSessionId,
435
- protocolSessionId: state.acpSessionId,
436
- requestedModel,
437
- effectiveModel: state.model,
438
- ...(modelWarning ? { modelWarning } : {}),
439
- };
440
- }
441
-
442
- /** Records what a config-option set says about the session's model. */
443
- private applyModelInfo(
444
- entry: SessionEntry,
445
- configOptions: SessionConfigOption[],
446
- ): void {
447
- this.recordModelInfo(entry, deriveModelInfo(configOptions));
448
- }
449
-
450
- /**
451
- * Records the model state a `session/new`, `session/load`, or
452
- * `session/resume` response reports. The response is authoritative when it
453
- * names a selector, or when nothing has announced one yet; otherwise the
454
- * selector a `config_option_update` announced while the call was open
455
- * stands, because an omitted optional field is not a removal.
456
- */
457
- private applyOpeningModelInfo(
458
- entry: SessionEntry,
459
- configOptions: SessionConfigOption[],
460
- ): void {
461
- const info = deriveModelInfo(configOptions);
462
- if (info.modelConfigId || entry.modelConfigId === undefined) {
463
- this.recordModelInfo(entry, info);
464
- }
465
- }
466
-
467
- /**
468
- * Writes what the adapter reports onto the entry. `modelConfigId` doubles
469
- * as the "this adapter has a model selector" flag, so state is left
470
- * untouched when there is none: an adapter that reports no selector cannot
471
- * wipe a model another response already named.
472
- */
473
- private recordModelInfo(entry: SessionEntry, info: AcpModelInfo): void {
474
- entry.modelConfigId = info.modelConfigId;
475
- if (info.modelConfigId) {
476
- entry.state.model = info.model;
477
- entry.state.availableModels = info.availableModels;
478
- }
479
- }
480
-
481
- /**
482
- * Records what the opening response says about the model, then puts the
483
- * session on `resolvedModel` if that is somewhere else. The value crosses
484
- * the wire unvalidated: the adapter's own resolver accepts aliases and full
485
- * ids and rejects everything else, and duplicating that judgement here
486
- * would refuse values it would have taken. A refusal leaves the run on the
487
- * adapter's default and comes back as the message to relay, because a
488
- * session that is live and working is worth more than one that never
489
- * started over a model name.
490
- *
491
- * An answer that carries no model selector is not a pin that landed: the
492
- * session is left with no model rather than one only the superseded
493
- * response ever named, and the empty picker goes out so no client is left
494
- * holding a selector the answer retired.
495
- *
496
- * A caller who named the model is owed the news when it was not applied,
497
- * whether the adapter has no selector or refused the value; an inherited
498
- * rung (the per-agent config model) is only logged, so a value the caller
499
- * never named does not surface as a warning on every spawn.
500
- */
501
- /**
502
- * A model pin that fails for authentication is the same failure a session
503
- * that could not open: Claude refused the configured credential, so it is
504
- * written down before teardown and surfaced in the shape the spawn boundary
505
- * recognises, whether the adapter answered with a structured
506
- * `auth_required` or with Claude's message-shaped 401.
507
- */
508
- private classifyPinFailure(
509
- err: unknown,
510
- agentId: string,
511
- agentConfig: { command: string; credentialDigest?: string },
512
- ): unknown {
513
- const message = requestErrorReason(err);
514
- const authCode = claudeAuthRequiredCode(err, message, {
515
- command: basename(agentConfig.command),
516
- });
517
- if (authCode === undefined && !isAcpAuthRequired(err)) {
518
- return err;
519
- }
520
- noteClaudeTokenRefused(agentConfig.credentialDigest, Date.now());
521
- return isAcpAuthRequired(err)
522
- ? err
523
- : new AcpAuthRequiredError(agentId, message);
524
- }
525
-
526
- private async pinSessionModel(
527
- entry: SessionEntry,
528
- configOptions: SessionConfigOption[],
529
- requestedModel: string | undefined,
530
- resolvedModel: string | undefined,
531
- options?: { keepReportedModel?: boolean },
532
- ): Promise<ModelPinResult> {
533
- const { state } = entry;
534
- this.applyOpeningModelInfo(entry, configOptions);
535
-
536
- // A resume reattaches a session the adapter restored from its own
537
- // transcript, so any model it has named by now is the model the run stays
538
- // on, whether the opening reply carried it or a replayed
539
- // `config_option_update` did.
540
- if (options?.keepReportedModel && state.model) {
541
- log.info(
542
- { acpSessionId: state.id, agentId: state.agentId, model: state.model },
543
- "ACP agent reported the resumed session's model; leaving it there",
544
- );
545
- return { applied: true };
546
- }
547
-
548
- if (!resolvedModel || resolvedModel === state.model) {
549
- return { applied: true };
550
- }
551
- if (!entry.modelConfigId) {
552
- log.info(
553
- { acpSessionId: state.id, agentId: state.agentId, resolvedModel },
554
- "ACP agent advertises no model selector; running on its own model",
555
- );
556
- return {
557
- applied: false,
558
- ...(requestedModel
559
- ? { warning: noModelSelectionWarning(state.agentId) }
560
- : {}),
561
- };
562
- }
563
-
564
- try {
565
- const refreshed = await entry.process.setConfigOption(
566
- state.acpSessionId,
567
- entry.modelConfigId,
568
- resolvedModel,
569
- );
570
- this.applyModelInfo(entry, refreshed);
571
- if (!entry.modelConfigId) {
572
- // Published, not just recorded: a `config_option_update` that arrived
573
- // while the round trip was open has already put its selector in front
574
- // of clients, and a session no client holds yet drops the frame.
575
- this.clearVanishedModelSelector(state.id, entry);
576
- log.warn(
577
- { acpSessionId: state.id, agentId: state.agentId, resolvedModel },
578
- "ACP agent dropped its model selector while applying the model; running on its own model",
579
- );
580
- return {
581
- applied: false,
582
- ...(requestedModel
583
- ? { warning: noModelSelectionWarning(state.agentId) }
584
- : {}),
585
- };
586
- }
587
- return { applied: true };
588
- } catch (err) {
589
- // Only the adapter's own answer is a refusal. A closed connection, an
590
- // exited process, or a failed authentication is the caller's failure
591
- // to tear down, not a model to fall back from.
592
- if (!(err instanceof AcpConfigOptionRefusedError)) {
593
- throw err;
594
- }
595
- log.warn(
596
- { acpSessionId: state.id, agentId: state.agentId, resolvedModel, err },
597
- "ACP agent refused the requested model; running on its own model",
598
- );
599
- return {
600
- applied: false,
601
- ...(requestedModel
602
- ? { warning: err instanceof Error ? err.message : String(err) }
603
- : {}),
604
- };
605
- }
339
+ return { acpSessionId, protocolSessionId: state.acpSessionId };
606
340
  }
607
341
 
608
342
  /**
@@ -628,20 +362,10 @@ export class AcpSessionManager {
628
362
  // Initialize the per-session ring buffer before any update can fire.
629
363
  this.eventBuffers.set(acpSessionId, []);
630
364
 
631
- // The map is the evidence, as everywhere else in this class: an id whose
632
- // entry is no longer this one was cancelled and resumed, so this
633
- // process's late frames must not reach the buffer, the state, or the
634
- // clients the replacement now owns. `entry` is declared below and read
635
- // only from inside closures the process cannot fire until it exists.
636
- const ownsSession = () => this.sessions.get(acpSessionId) === entry;
637
-
638
365
  // Wrap the sender so every emitted message is mirrored into the buffer
639
366
  // when it's an `acp_session_update`. The wrapper preserves the original
640
367
  // call semantics: it forwards every message unchanged.
641
368
  const wrappedSend = (msg: AssistantEvent) => {
642
- if (!ownsSession()) {
643
- return;
644
- }
645
369
  if (msg.type === "acp_session_update") {
646
370
  this.appendToBuffer(acpSessionId, msg);
647
371
  } else if (msg.type === "acp_session_usage") {
@@ -662,15 +386,10 @@ export class AcpSessionManager {
662
386
  opts.sendToVellum(msg);
663
387
  };
664
388
 
665
- // The callback runs once the agent is connected and sending
666
- // notifications, which is after agentProcess is constructed just below.
667
389
  const clientHandler = new VellumAcpClientHandler(
668
390
  acpSessionId,
669
391
  wrappedSend,
670
392
  opts.parentConversationId,
671
- (configOptions) => {
672
- this.applyUnsolicitedConfigOptions(acpSessionId, entry, configOptions);
673
- },
674
393
  );
675
394
 
676
395
  const agentProcess = new AcpAgentProcess(
@@ -725,98 +444,6 @@ export class AcpSessionManager {
725
444
  });
726
445
  }
727
446
 
728
- /**
729
- * Publishes the session's model selection. Silent for adapters with no
730
- * model selector: the client renders nothing rather than an empty picker.
731
- * A separate frame from `acp_session_spawned`, which carries a fixed subset
732
- * older clients parse.
733
- */
734
- private sendModelEvent(acpSessionId: string, entry: SessionEntry): void {
735
- if (!entry.modelConfigId) {
736
- return;
737
- }
738
- this.sendModelSnapshot(acpSessionId, entry);
739
- }
740
-
741
- /** Publishes model state with the same revision exposed by session reads. */
742
- private sendModelSnapshot(acpSessionId: string, entry: SessionEntry): void {
743
- const modelRevision = ++this.modelRevision;
744
- entry.state.modelRevisionEpoch = this.modelRevisionEpoch;
745
- entry.state.modelRevision = modelRevision;
746
- entry.sendToVellum({
747
- type: "acp_session_model_update",
748
- acpSessionId,
749
- modelRevisionEpoch: this.modelRevisionEpoch,
750
- modelRevision,
751
- model: entry.state.model,
752
- availableModels: entry.state.availableModels ?? [],
753
- });
754
- }
755
-
756
- /**
757
- * Whether `entry` is still this manager's live entry for `acpSessionId`.
758
- * A notification that lands after close, cancellation, or prompt completion
759
- * has nothing left to update: the terminal row is already written, so
760
- * applying it would leave history on one model and clients on another.
761
- */
762
- private isEntryLive(acpSessionId: string, entry: SessionEntry): boolean {
763
- return (
764
- this.sessions.get(acpSessionId) === entry &&
765
- isLiveAcpStatus(entry.state.status)
766
- );
767
- }
768
-
769
- /**
770
- * Drops the live model snapshot a vanished selector took with it and
771
- * publishes the empty picker. `applyModelInfo` keeps the model already
772
- * recorded for adapters that never had a selector, which here would leave
773
- * the client holding options the session cannot reach. Returns whether it
774
- * fired, so callers skip the publish that assumes a model is still there.
775
- *
776
- * A published picker is what says the selector was there to vanish: only an
777
- * adapter that advertised one ever populates it, so an adapter that never
778
- * had one publishes nothing.
779
- */
780
- private clearVanishedModelSelector(
781
- acpSessionId: string,
782
- entry: SessionEntry,
783
- ): boolean {
784
- if (entry.modelConfigId || entry.state.availableModels === undefined) {
785
- return false;
786
- }
787
- entry.state.model = undefined;
788
- entry.state.availableModels = [];
789
- this.sendModelSnapshot(acpSessionId, entry);
790
- return true;
791
- }
792
-
793
- /**
794
- * Takes in a `config_option_update` the adapter sent unprompted, which is
795
- * how a `/model` the user typed straight into the transcript reaches the
796
- * daemon: record what it reports, publish it, and drop the live snapshot
797
- * when the selector it announced has vanished.
798
- *
799
- * A session past its terminal transition takes nothing from a late
800
- * notification at all: its history row is already written, so mutating
801
- * state or emitting here would leave clients and history disagreeing about
802
- * the same run.
803
- */
804
- private applyUnsolicitedConfigOptions(
805
- acpSessionId: string,
806
- entry: SessionEntry,
807
- configOptions: SessionConfigOption[],
808
- ): void {
809
- if (!this.isEntryLive(acpSessionId, entry)) {
810
- return;
811
- }
812
- this.applyModelInfo(entry, configOptions);
813
-
814
- if (this.clearVanishedModelSelector(acpSessionId, entry)) {
815
- return;
816
- }
817
- this.sendModelEvent(acpSessionId, entry);
818
- }
819
-
820
447
  /**
821
448
  * Resumes a terminal-state session from its persisted
822
449
  * `acp_session_history` row, reattaching to the agent's stored
@@ -996,7 +623,6 @@ export class AcpSessionManager {
996
623
  // Seed before the child process spawns so no live update can fire first.
997
624
  entry.clientHandler.seedSeq(maxSeq);
998
625
 
999
- let configOptions: SessionConfigOption[] = [];
1000
626
  try {
1001
627
  log.info(
1002
628
  { acpSessionId, agentId: row.agentId },
@@ -1006,20 +632,14 @@ export class AcpSessionManager {
1006
632
  await agentProcess.initialize();
1007
633
  if (agentProcess.supportsSessionResume) {
1008
634
  // session/resume reattaches without replaying history.
1009
- ({ configOptions } = await agentProcess.resumeSession(
1010
- row.acpSessionId,
1011
- row.cwd,
1012
- ));
635
+ await agentProcess.resumeSession(row.acpSessionId, row.cwd);
1013
636
  } else if (agentProcess.supportsLoadSession) {
1014
637
  // session/load replays the full history as session/update
1015
638
  // notifications before resolving; suppress forwarding so the
1016
639
  // conversation and ring buffer don't receive duplicates.
1017
640
  entry.clientHandler.beginReplaySuppression();
1018
641
  try {
1019
- ({ configOptions } = await agentProcess.loadSession(
1020
- row.acpSessionId,
1021
- row.cwd,
1022
- ));
642
+ await agentProcess.loadSession(row.acpSessionId, row.cwd);
1023
643
  } finally {
1024
644
  entry.clientHandler.endReplaySuppression();
1025
645
  }
@@ -1048,43 +668,7 @@ export class AcpSessionManager {
1048
668
  throw err;
1049
669
  }
1050
670
 
1051
- // The ladder a spawn walks, for the case the adapter reports no model of
1052
- // its own; a reattached session that comes back naming one keeps it.
1053
- const resolvedModel = resolveAcpModel({ agentModel: agentConfig.model });
1054
- let applied: boolean;
1055
- try {
1056
- ({ applied } = await this.pinSessionModel(
1057
- entry,
1058
- configOptions,
1059
- undefined,
1060
- resolvedModel,
1061
- { keepReportedModel: true },
1062
- ));
1063
- } catch (err) {
1064
- log.error(
1065
- { acpSessionId, agentId: row.agentId, err },
1066
- "ACP resume failed while applying the model",
1067
- );
1068
- const failure = this.classifyPinFailure(err, row.agentId, agentConfig);
1069
- this.teardownSession(acpSessionId, entry);
1070
- throw failure;
1071
- }
1072
- if (resolvedModel && !applied) {
1073
- // State keeps the adapter's own answer, so the model event, the status
1074
- // projection and the panel all name the model the run is really on.
1075
- log.warn(
1076
- {
1077
- acpSessionId,
1078
- agentId: row.agentId,
1079
- resolvedModel,
1080
- model: state.model,
1081
- },
1082
- "ACP resume could not apply the configured model; running on the agent's own model",
1083
- );
1084
- }
1085
-
1086
671
  this.sendSpawnedEvent(acpSessionId, entry);
1087
- this.sendModelEvent(acpSessionId, entry);
1088
672
  }
1089
673
 
1090
674
  /**
@@ -1345,7 +929,10 @@ export class AcpSessionManager {
1345
929
  if (!entry) {
1346
930
  throw new AcpSessionNotFoundError(acpSessionId);
1347
931
  }
1348
- if (isLiveAcpStatus(entry.state.status)) {
932
+ if (
933
+ entry.state.status === "running" ||
934
+ entry.state.status === "initializing"
935
+ ) {
1349
936
  entry.state.status = "cancelled";
1350
937
  entry.state.completedAt = Date.now();
1351
938
  }
@@ -1355,13 +942,6 @@ export class AcpSessionManager {
1355
942
 
1356
943
  /**
1357
944
  * Denies pending ACP permissions, kills the process, and removes the session.
1358
- *
1359
- * The permissions and the process belong to `entry`, so they are always
1360
- * torn down; the map slot and its buffer belong to whichever entry holds
1361
- * the id, so they are only cleared while that is still this one. A caller
1362
- * whose entry the map has since replaced (a cancel that persisted a
1363
- * resumable row, then a resume of the same id, while an await was pending)
1364
- * would otherwise evict the live session that took its place.
1365
945
  */
1366
946
  private teardownSession(acpSessionId: string, entry: SessionEntry): void {
1367
947
  for (const requestId of entry.clientHandler.pendingRequestIds) {
@@ -1371,9 +951,6 @@ export class AcpSessionManager {
1371
951
  }
1372
952
  }
1373
953
  entry.process.kill();
1374
- if (this.sessions.get(acpSessionId) !== entry) {
1375
- return;
1376
- }
1377
954
  this.sessions.delete(acpSessionId);
1378
955
  // Free the buffer in case persistTerminal hasn't already (e.g. close()
1379
956
  // before terminal transition).