@vellumai/assistant 0.12.0 → 0.12.1-dev.202609141913.5e16607

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 (441) hide show
  1. package/AGENTS.md +5 -1
  2. package/ARCHITECTURE.md +11 -12
  3. package/docs/architecture/turn-actor.md +15 -8
  4. package/docs/guardian-request-flow.md +16 -0
  5. package/openapi.yaml +292 -50
  6. package/package.json +1 -1
  7. package/scripts/smoke-desktop-window-theme.ts +186 -0
  8. package/src/__tests__/always-loaded-tools-guard.test.ts +18 -10
  9. package/src/__tests__/app-compiler.test.ts +6 -0
  10. package/src/__tests__/app-control-tool-schemas.test.ts +5 -2
  11. package/src/__tests__/app-dir-path-guard.test.ts +1 -3
  12. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +5 -2
  13. package/src/__tests__/computer-use-tools.test.ts +17 -5
  14. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  15. package/src/__tests__/config-schema.test.ts +28 -29
  16. package/src/__tests__/config-watcher.test.ts +23 -8
  17. package/src/__tests__/connection-model-compat.test.ts +2 -2
  18. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  19. package/src/__tests__/conversation-pairing.test.ts +26 -0
  20. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -10
  21. package/src/__tests__/conversation-queue.test.ts +48 -207
  22. package/src/__tests__/conversation-retry-discard.test.ts +54 -1
  23. package/src/__tests__/conversation-skill-tools.test.ts +27 -0
  24. package/src/__tests__/conversation-surfaces-app-control.test.ts +8 -3
  25. package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
  26. package/src/__tests__/conversation-title-service.test.ts +14 -10
  27. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +3 -5
  28. package/src/__tests__/conversation-tool-setup-attribution.test.ts +51 -0
  29. package/src/__tests__/credential-record-retire.test.ts +171 -1
  30. package/src/__tests__/credential-routes.test.ts +212 -3
  31. package/src/__tests__/credential-security-invariants.test.ts +4 -2
  32. package/src/__tests__/cu-unified-flow.test.ts +8 -2
  33. package/src/__tests__/document-sync-tags.test.ts +25 -0
  34. package/src/__tests__/drain-kick-guard.test.ts +0 -2
  35. package/src/__tests__/drain-requeue-on-contention.test.ts +0 -6
  36. package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
  37. package/src/__tests__/git-porcelain.test.ts +47 -0
  38. package/src/__tests__/helpers/set-workspace-mcp.ts +11 -0
  39. package/src/__tests__/host-bash-proxy.test.ts +26 -45
  40. package/src/__tests__/host-browser-proxy.test.ts +6 -17
  41. package/src/__tests__/host-file-proxy-targeted.test.ts +23 -0
  42. package/src/__tests__/host-file-proxy.test.ts +11 -23
  43. package/src/__tests__/host-transfer-proxy-targeted.test.ts +30 -9
  44. package/src/__tests__/llm-catalog-parity.test.ts +25 -0
  45. package/src/__tests__/mcp-auth-routes.test.ts +6 -9
  46. package/src/__tests__/mcp-config-secret-boundary.test.ts +78 -136
  47. package/src/__tests__/mcp-health-check.test.ts +8 -11
  48. package/src/__tests__/mcp-list-plugin-servers.test.ts +8 -10
  49. package/src/__tests__/message-deleted-hook-dispatch.test.ts +119 -0
  50. package/src/__tests__/messages-after-tiebreaker.test.ts +91 -0
  51. package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
  52. package/src/__tests__/messaging-send-tool.test.ts +355 -548
  53. package/src/__tests__/model-intents.test.ts +3 -0
  54. package/src/__tests__/notification-vellum-adapter.test.ts +85 -2
  55. package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
  56. package/src/__tests__/platform-callback-registration.test.ts +8 -16
  57. package/src/__tests__/platform-client-verify-credential.test.ts +2 -0
  58. package/src/__tests__/plugin-import-boundary-guard.test.ts +13 -0
  59. package/src/__tests__/resolve-app.test.ts +135 -0
  60. package/src/__tests__/script-proxy-certs.test.ts +35 -0
  61. package/src/__tests__/service-account-token.test.ts +247 -0
  62. package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
  63. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  64. package/src/__tests__/source-fingerprint.test.ts +184 -0
  65. package/src/__tests__/subagent-tool-gate-mode.test.ts +19 -3
  66. package/src/__tests__/subagent-tools.test.ts +3 -2
  67. package/src/__tests__/telephony-tts-guard.test.ts +38 -3
  68. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +4 -0
  69. package/src/__tests__/watch-retro-tool-availability.test.ts +8 -17
  70. package/src/__tests__/workspace-git-service.test.ts +26 -0
  71. package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +336 -0
  72. package/src/acp/__tests__/agent-process.test.ts +258 -4
  73. package/src/acp/__tests__/auth-required.test.ts +96 -0
  74. package/src/acp/__tests__/client-handler.test.ts +90 -2
  75. package/src/acp/__tests__/helpers/acp-model-option.ts +51 -0
  76. package/src/acp/__tests__/session-manager-persistence.test.ts +5 -1
  77. package/src/acp/__tests__/session-manager-resume.test.ts +270 -6
  78. package/src/acp/__tests__/session-manager-usage.test.ts +4 -2
  79. package/src/acp/__tests__/session-manager.test.ts +895 -4
  80. package/src/acp/agent-process.test.ts +4 -1
  81. package/src/acp/agent-process.ts +94 -9
  82. package/src/acp/auth-required.ts +50 -1
  83. package/src/acp/auto-install.test.ts +9 -7
  84. package/src/acp/client-handler.ts +16 -3
  85. package/src/acp/model-config.test.ts +166 -0
  86. package/src/acp/model-config.ts +138 -0
  87. package/src/acp/resolve-agent.test.ts +220 -6
  88. package/src/acp/resolve-agent.ts +88 -23
  89. package/src/acp/session-manager.test.ts +196 -3
  90. package/src/acp/session-manager.ts +441 -18
  91. package/src/acp/types.ts +50 -5
  92. package/src/api/events/acp-session-model-update.test.ts +88 -0
  93. package/src/api/events/acp-session-model-update.ts +46 -0
  94. package/src/api/events/app-files-changed.ts +4 -3
  95. package/src/api/events/notification-intent.ts +2 -0
  96. package/src/api/index.ts +6 -0
  97. package/src/apps/app-store.ts +1 -1
  98. package/src/apps/resolve-app.ts +81 -0
  99. package/src/apps/source-fingerprint.ts +266 -0
  100. package/src/bundler/app-compiler.ts +15 -0
  101. package/src/calls/__tests__/barge-in-guard.test.ts +81 -0
  102. package/src/{__tests__ → calls/__tests__}/call-controller.test.ts +503 -82
  103. package/src/{__tests__ → calls/__tests__}/media-stream-audio-transcode.test.ts +1 -1
  104. package/src/{__tests__ → calls/__tests__}/media-stream-output.test.ts +37 -8
  105. package/src/{__tests__ → calls/__tests__}/media-stream-parser.test.ts +1 -1
  106. package/src/{__tests__ → calls/__tests__}/media-stream-server-integration.test.ts +150 -57
  107. package/src/{__tests__ → calls/__tests__}/media-stream-stt-session.test.ts +5 -5
  108. package/src/{__tests__ → calls/__tests__}/media-turn-detector.test.ts +1 -1
  109. package/src/{live-voice → calls}/__tests__/progress-narration.test.ts +4 -4
  110. package/src/{live-voice → calls}/__tests__/progress-phrases.test.ts +1 -1
  111. package/src/calls/__tests__/voice-control-protocol.test.ts +58 -25
  112. package/src/calls/__tests__/voice-leg-coordinator.test.ts +229 -0
  113. package/src/calls/__tests__/voice-progress-cadence.test.ts +274 -0
  114. package/src/{__tests__/voice-session-bridge.test.ts → calls/__tests__/voice-session-bridge-turn-flow.test.ts} +20 -12
  115. package/src/calls/__tests__/voice-session-bridge.test.ts +37 -1
  116. package/src/calls/__tests__/voice-triage-escalate.test.ts +105 -0
  117. package/src/calls/barge-in-guard.ts +118 -0
  118. package/src/calls/call-constants.ts +24 -4
  119. package/src/calls/call-controller.ts +499 -199
  120. package/src/calls/call-transport.ts +16 -0
  121. package/src/calls/media-stream-output.ts +32 -0
  122. package/src/calls/media-stream-server.ts +82 -30
  123. package/src/calls/media-stream-stt-session.ts +15 -0
  124. package/src/{live-voice → calls}/progress-narration.ts +2 -2
  125. package/src/calls/resolve-call-tts-provider.ts +33 -2
  126. package/src/calls/tts-call-strategy.ts +9 -5
  127. package/src/calls/types.ts +2 -0
  128. package/src/calls/voice-control-protocol.ts +53 -21
  129. package/src/calls/voice-leg-coordinator.ts +189 -0
  130. package/src/calls/voice-progress-cadence.ts +423 -0
  131. package/src/calls/voice-session-bridge.ts +59 -46
  132. package/src/calls/voice-triage-escalate.ts +175 -56
  133. package/src/cli/commands/__tests__/apps.test.ts +245 -0
  134. package/src/cli/commands/__tests__/bash.test.ts +53 -0
  135. package/src/cli/commands/__tests__/roadmap.help.test.ts +19 -0
  136. package/src/cli/commands/apps.help.ts +67 -13
  137. package/src/cli/commands/apps.ts +183 -0
  138. package/src/cli/commands/bash.help.ts +8 -13
  139. package/src/cli/commands/bash.ts +7 -25
  140. package/src/cli/commands/channels/__tests__/send.test.ts +218 -0
  141. package/src/cli/commands/channels/index.help.ts +70 -2
  142. package/src/cli/commands/channels/index.ts +16 -3
  143. package/src/cli/commands/channels/send.ts +128 -0
  144. package/src/cli/commands/credentials.help.ts +6 -2
  145. package/src/cli/commands/credentials.ts +2 -2
  146. package/src/cli/commands/mcp.help.ts +8 -8
  147. package/src/cli/commands/mcp.ts +1 -1
  148. package/src/cli/commands/roadmap.help.ts +5 -1
  149. package/src/cli/commands/roadmap.ts +1 -1
  150. package/src/cli/lib/bundled-marketplace.json +103 -90
  151. package/src/config/__tests__/default-profile-catalog.test.ts +22 -0
  152. package/src/config/__tests__/memory-retrospective-schema.test.ts +15 -1
  153. package/src/config/__tests__/platform-identity.test.ts +255 -0
  154. package/src/config/__tests__/platform-rehydration.test.ts +99 -9
  155. package/src/config/acp-agent-write.ts +43 -0
  156. package/src/config/acp-defaults.test.ts +13 -3
  157. package/src/config/acp-defaults.ts +23 -6
  158. package/src/config/acp-schema.test.ts +81 -0
  159. package/src/config/acp-schema.ts +30 -2
  160. package/src/config/bundled-skills/acp/SKILL.md +22 -14
  161. package/src/config/bundled-skills/acp/TOOLS.json +5 -1
  162. package/src/config/bundled-skills/app-builder/SKILL.md +12 -9
  163. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
  164. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  165. package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
  166. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +67 -139
  167. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
  168. package/src/config/bundled-skills/schedule/SKILL.md +3 -4
  169. package/src/config/bundled-skills/screen-annotation/SKILL.md +8 -1
  170. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +4 -1
  171. package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
  172. package/src/config/default-profile-catalog.ts +1 -1
  173. package/src/config/env.ts +2 -2
  174. package/src/config/feature-flag-registry.json +24 -12
  175. package/src/config/loader.ts +1 -0
  176. package/src/config/memory-v3-gate.test.ts +31 -0
  177. package/src/config/memory-v3-gate.ts +20 -16
  178. package/src/config/platform-identity.ts +201 -0
  179. package/src/config/platform-rehydration.ts +11 -27
  180. package/src/config/schema.ts +2 -2
  181. package/src/config/schemas/__tests__/live-voice.test.ts +8 -158
  182. package/src/config/schemas/__tests__/voice.test.ts +148 -0
  183. package/src/config/schemas/calls.ts +1 -28
  184. package/src/config/schemas/live-voice.ts +1 -173
  185. package/src/config/schemas/mcp.ts +1 -1
  186. package/src/config/schemas/memory-retrospective.ts +10 -0
  187. package/src/config/schemas/services.ts +8 -0
  188. package/src/config/schemas/skills.ts +0 -14
  189. package/src/config/schemas/voice.ts +150 -0
  190. package/src/credential-execution/process-manager.test.ts +18 -19
  191. package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -121
  192. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +4 -1
  193. package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +133 -0
  194. package/src/daemon/app-change-notify.ts +45 -0
  195. package/src/daemon/config-watcher.ts +13 -194
  196. package/src/daemon/conversation-process.ts +35 -64
  197. package/src/daemon/conversation-skill-tools.ts +13 -31
  198. package/src/daemon/conversation-store.ts +1 -1
  199. package/src/daemon/conversation-surfaces.ts +10 -8
  200. package/src/daemon/conversation-tool-setup.ts +37 -43
  201. package/src/daemon/conversation.ts +0 -3
  202. package/src/daemon/host-bash-proxy.ts +8 -12
  203. package/src/daemon/host-browser-proxy.ts +15 -1
  204. package/src/daemon/host-file-proxy.ts +8 -10
  205. package/src/daemon/host-transfer-proxy.ts +14 -18
  206. package/src/daemon/lifecycle.ts +0 -5
  207. package/src/daemon/mcp-reload-service.ts +5 -5
  208. package/src/daemon/message-types/sync.ts +1 -0
  209. package/src/daemon/orphan-reaper.ts +1 -1
  210. package/src/daemon/providers-setup.ts +1 -1
  211. package/src/daemon/shutdown-handlers.ts +1 -9
  212. package/src/daemon/skill-memory-refresh.ts +64 -0
  213. package/src/daemon/tool-side-effects.ts +7 -18
  214. package/src/desktop/__tests__/fake-desktop.ts +119 -0
  215. package/src/desktop/desktop-chrome-policy.test.ts +71 -0
  216. package/src/desktop/desktop-chrome-policy.ts +42 -0
  217. package/src/desktop/desktop-dependencies.test.ts +102 -0
  218. package/src/desktop/desktop-dependencies.ts +306 -0
  219. package/src/desktop/desktop-feature.test.ts +18 -0
  220. package/src/desktop/desktop-feature.ts +19 -0
  221. package/src/desktop/desktop-panel-config.test.ts +135 -0
  222. package/src/desktop/desktop-panel-config.ts +149 -0
  223. package/src/desktop/desktop-session-manager.test.ts +627 -0
  224. package/src/desktop/desktop-session-manager.ts +814 -0
  225. package/src/desktop/desktop-stream-bridge.test.ts +395 -0
  226. package/src/desktop/desktop-stream-bridge.ts +214 -0
  227. package/src/desktop/desktop-wallpaper.test.ts +191 -0
  228. package/src/desktop/desktop-wallpaper.ts +113 -0
  229. package/src/desktop/desktop-window-theme.ts +170 -0
  230. package/src/home/__tests__/feed-writer.test.ts +22 -0
  231. package/src/home/feed-writer.ts +11 -2
  232. package/src/hooks/types.ts +33 -0
  233. package/src/i18n/AGENTS.md +22 -0
  234. package/src/i18n/__tests__/i18n.test.ts +108 -0
  235. package/src/i18n/index.ts +16 -0
  236. package/src/i18n/locales.ts +93 -0
  237. package/src/i18n/messages.ts +61 -0
  238. package/src/i18n/title.ts +25 -0
  239. package/src/inbound/platform-callback-registration.ts +4 -5
  240. package/src/live-voice/__tests__/live-voice-metrics.test.ts +0 -3
  241. package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -15
  242. package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
  243. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +13 -69
  244. package/src/live-voice/live-voice-session.ts +213 -693
  245. package/src/live-voice/protocol.ts +0 -2
  246. package/src/mcp/__tests__/effective-config.test.ts +2 -2
  247. package/src/mcp/__tests__/workspace-mcp-config.test.ts +135 -0
  248. package/src/mcp/effective-config.ts +3 -3
  249. package/src/mcp/mcp-header-store.ts +29 -45
  250. package/src/mcp/spec-schema.ts +111 -0
  251. package/src/mcp/startup.ts +8 -4
  252. package/src/mcp/workspace-mcp-config.ts +188 -0
  253. package/src/messaging/provider.ts +10 -3
  254. package/src/messaging/providers/__tests__/proactive-address.test.ts +95 -0
  255. package/src/messaging/providers/callback-routing.ts +18 -0
  256. package/src/messaging/providers/channel-transport.ts +56 -0
  257. package/src/messaging/providers/discord/transport.ts +17 -0
  258. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +6 -17
  259. package/src/messaging/providers/slack/adapter.ts +7 -44
  260. package/src/messaging/providers/slack/transport.ts +16 -0
  261. package/src/messaging/providers/telegram-bot/adapter.ts +1 -48
  262. package/src/messaging/providers/telegram-bot/client.ts +0 -26
  263. package/src/messaging/providers/telegram-bot/transport.ts +20 -0
  264. package/src/messaging/providers/whatsapp/adapter.ts +1 -48
  265. package/src/messaging/providers/whatsapp/transport.ts +18 -0
  266. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +8 -0
  267. package/src/notifications/__tests__/assistant-reply-producer.test.ts +55 -0
  268. package/src/notifications/__tests__/guardian-feed-projection.test.ts +158 -2
  269. package/src/notifications/__tests__/home-feed-side-effect.test.ts +153 -3
  270. package/src/notifications/__tests__/schedule-result-producer.test.ts +99 -3
  271. package/src/notifications/adapters/macos.ts +3 -0
  272. package/src/notifications/assistant-reply-producer.ts +8 -3
  273. package/src/notifications/conversation-pairing.ts +36 -16
  274. package/src/notifications/delivered-post-record.ts +11 -1
  275. package/src/notifications/guardian-feed-projection.ts +125 -5
  276. package/src/notifications/home-feed-side-effect.ts +55 -7
  277. package/src/notifications/schedule-result-producer.ts +66 -22
  278. package/src/oauth/__tests__/seed-providers-managed.test.ts +54 -0
  279. package/src/oauth/byo-connection.test.ts +45 -0
  280. package/src/oauth/byo-connection.ts +36 -6
  281. package/src/oauth/connection-resolver.test.ts +73 -0
  282. package/src/oauth/connection-resolver.ts +95 -2
  283. package/src/oauth/seed-providers.ts +165 -0
  284. package/src/outbound-proxy/certs.ts +3 -5
  285. package/src/permissions/checker.test.ts +11 -6
  286. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  287. package/src/persistence/conversation-crud.ts +71 -63
  288. package/src/persistence/conversation-lineage.ts +12 -4
  289. package/src/persistence/conversation-title-placeholders.ts +23 -0
  290. package/src/persistence/conversation-title-service.ts +9 -26
  291. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  292. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  293. package/src/persistence/message-cursor.ts +78 -0
  294. package/src/persistence/message-reads.ts +30 -0
  295. package/src/persistence/migrations/157-invite-contact-id.ts +18 -6
  296. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +149 -0
  297. package/src/persistence/schema/memory-core.ts +5 -0
  298. package/src/platform/client.test.ts +4 -2
  299. package/src/platform/client.ts +2 -10
  300. package/src/plugin-api/constants.ts +2 -0
  301. package/src/plugin-api/index.ts +1 -0
  302. package/src/plugin-api/types.ts +2 -0
  303. package/src/plugins/defaults/index.ts +2 -0
  304. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +46 -0
  305. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +118 -0
  306. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +83 -0
  307. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +9 -5
  308. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +20 -10
  309. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +219 -0
  310. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +31 -0
  311. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +63 -0
  312. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +4 -0
  313. package/src/plugins/defaults/memory/graph/capability-seed.ts +4 -6
  314. package/src/plugins/defaults/memory/hooks/init.ts +10 -0
  315. package/src/plugins/defaults/memory/hooks/message-deleted.ts +21 -0
  316. package/src/plugins/defaults/memory/hooks/shutdown.ts +2 -0
  317. package/src/plugins/defaults/memory/jobs-worker.ts +13 -0
  318. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +34 -60
  319. package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +126 -0
  320. package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +79 -0
  321. package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +28 -0
  322. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +3 -5
  323. package/src/plugins/defaults/memory/memory-retrospective-job.ts +12 -3
  324. package/src/plugins/defaults/memory/memory-retrospective-state.ts +312 -71
  325. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +2 -1
  326. package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +5 -3
  327. package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +9 -0
  328. package/src/plugins/defaults/memory/startup.ts +6 -1
  329. package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +7 -9
  330. package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
  331. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +89 -0
  332. package/src/plugins/defaults/memory/worker.ts +6 -0
  333. package/src/plugins/mcp-servers.ts +15 -75
  334. package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
  335. package/src/providers/gemini/client.ts +9 -23
  336. package/src/providers/gemini-thought-signature.test.ts +63 -0
  337. package/src/providers/gemini-thought-signature.ts +44 -0
  338. package/src/providers/inference/auth.ts +2 -3
  339. package/src/providers/inference/connection-availability.ts +27 -8
  340. package/src/providers/inference/resolve-auth.ts +22 -4
  341. package/src/providers/inference/service-account-token.ts +248 -0
  342. package/src/providers/model-catalog.ts +34 -0
  343. package/src/providers/model-intents.ts +10 -5
  344. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +146 -18
  345. package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +613 -0
  346. package/src/providers/openai/__tests__/google-thought-signature.test.ts +235 -0
  347. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +83 -1
  348. package/src/providers/openai/chat-completions-provider.ts +192 -78
  349. package/src/providers/openai/codex-models.ts +0 -4
  350. package/src/providers/openai/google-thought-signature.ts +320 -0
  351. package/src/runtime/AGENTS.md +2 -0
  352. package/src/runtime/__tests__/channel-send.test.ts +443 -0
  353. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +89 -0
  354. package/src/runtime/__tests__/live-voice-upgrade.test.ts +58 -0
  355. package/src/runtime/__tests__/runtime-ws-test-utils.ts +72 -0
  356. package/src/runtime/__tests__/watch-stream-upgrade.test.ts +59 -0
  357. package/src/runtime/auth/same-actor.ts +38 -3
  358. package/src/runtime/channel-send.ts +316 -0
  359. package/src/runtime/http-server.ts +160 -151
  360. package/src/runtime/routes/__tests__/acp-routes.test.ts +159 -4
  361. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +205 -0
  362. package/src/runtime/routes/__tests__/channel-send-routes.test.ts +127 -0
  363. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +108 -1
  364. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
  365. package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +107 -0
  366. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +16 -12
  367. package/src/runtime/routes/acp-routes.test.ts +15 -0
  368. package/src/runtime/routes/acp-routes.ts +72 -9
  369. package/src/runtime/routes/app-management-routes.ts +73 -0
  370. package/src/runtime/routes/app-routes.ts +1 -1
  371. package/src/runtime/routes/channel-send-routes.ts +85 -0
  372. package/src/runtime/routes/conversation-list-routes.ts +14 -3
  373. package/src/runtime/routes/conversation-query-routes.ts +40 -0
  374. package/src/runtime/routes/credential-routes.ts +19 -10
  375. package/src/runtime/routes/desktop-setup-routes.test.ts +74 -0
  376. package/src/runtime/routes/desktop-setup-routes.ts +35 -0
  377. package/src/runtime/routes/diagnostics-routes.ts +55 -3
  378. package/src/runtime/routes/index.ts +4 -2
  379. package/src/runtime/routes/log-export-routes.ts +2 -0
  380. package/src/runtime/routes/mcp-auth-routes.ts +39 -47
  381. package/src/runtime/routes/migration-routes.ts +6 -20
  382. package/src/runtime/routes/platform-routes.ts +18 -15
  383. package/src/runtime/services/__tests__/conversation-serializer.test.ts +28 -0
  384. package/src/runtime/services/conversation-serializer.ts +16 -3
  385. package/src/runtime/sync/resource-sync-events.ts +2 -1
  386. package/src/schedule/worker.ts +1 -1
  387. package/src/security/__tests__/ces-http-record-backend.test.ts +137 -0
  388. package/src/security/ces-http-record-backend.ts +120 -0
  389. package/src/security/ces-rpc-record-backend.ts +7 -0
  390. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +60 -0
  391. package/src/skills/workspace-skill-md-signature.ts +50 -0
  392. package/src/subagent/consult-context.ts +12 -25
  393. package/src/tools/acp/list-agents.test.ts +3 -1
  394. package/src/tools/acp/spawn.test.ts +146 -11
  395. package/src/tools/acp/spawn.ts +21 -3
  396. package/src/tools/acp/status.test.ts +94 -0
  397. package/src/tools/acp/status.ts +40 -3
  398. package/src/tools/app-control/skill-proxy-bridge.ts +2 -1
  399. package/src/tools/capability-offer.test.ts +22 -2
  400. package/src/tools/capability-offer.ts +16 -1
  401. package/src/tools/computer-use/definitions.ts +4 -2
  402. package/src/tools/computer-use/skill-proxy-bridge.ts +2 -1
  403. package/src/tools/credentials/metadata-store.ts +100 -0
  404. package/src/tools/host-filesystem/edit.test.ts +2 -1
  405. package/src/tools/host-filesystem/edit.ts +2 -2
  406. package/src/tools/host-filesystem/read.test.ts +2 -1
  407. package/src/tools/host-filesystem/read.ts +2 -2
  408. package/src/tools/host-filesystem/transfer.test.ts +2 -1
  409. package/src/tools/host-filesystem/transfer.ts +2 -2
  410. package/src/tools/host-filesystem/write.test.ts +2 -1
  411. package/src/tools/host-filesystem/write.ts +2 -2
  412. package/src/tools/host-terminal/host-shell.test.ts +16 -0
  413. package/src/tools/host-terminal/host-shell.ts +4 -20
  414. package/src/tools/policy-context.ts +6 -7
  415. package/src/tools/subagent/spawn.ts +5 -8
  416. package/src/tools/terminal/__tests__/safe-env.test.ts +6 -6
  417. package/src/tools/terminal/__tests__/sanitized-bash.test.ts +57 -0
  418. package/src/tools/terminal/safe-env.ts +23 -3
  419. package/src/tools/terminal/sanitized-bash.ts +105 -0
  420. package/src/tools/watch/watch-retro-report.ts +0 -8
  421. package/src/util/__tests__/language-subtag.test.ts +23 -1
  422. package/src/util/ca-bundle.ts +13 -0
  423. package/src/util/language-subtag.ts +16 -0
  424. package/src/util/platform.ts +8 -0
  425. package/src/workspace/git-porcelain.ts +66 -0
  426. package/src/workspace/git-service.ts +5 -54
  427. package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +258 -0
  428. package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +78 -0
  429. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +214 -0
  430. package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +102 -0
  431. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +199 -0
  432. package/src/workspace/migrations/registry.ts +6 -0
  433. package/src/__tests__/app-source-watcher.test.ts +0 -218
  434. package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -359
  435. package/src/__tests__/speaker-identification.test.ts +0 -56
  436. package/src/calls/speaker-identification.ts +0 -233
  437. package/src/daemon/app-source-watcher.ts +0 -218
  438. package/src/messaging/providers/whatsapp/client.ts +0 -29
  439. package/src/runtime/routes/debug-bash-routes.ts +0 -173
  440. package/src/util/fs-watcher-error.ts +0 -36
  441. /package/src/{live-voice → calls}/progress-phrases.ts +0 -0
@@ -12,6 +12,15 @@
12
12
  import { tmpdir } from "node:os";
13
13
  import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
14
14
 
15
+ import type { SessionConfigOption } from "@agentclientprotocol/sdk";
16
+
17
+ import {
18
+ MODEL_OPTION_MODELS,
19
+ modelOption,
20
+ modelOptionWithoutCurrent,
21
+ nonModelOption,
22
+ } from "./helpers/acp-model-option.js";
23
+
15
24
  // ---------------------------------------------------------------------------
16
25
  // Fake AcpAgentProcess with scriptable capabilities and history replay.
17
26
  // ---------------------------------------------------------------------------
@@ -31,6 +40,24 @@ let promptThrowsSync = false;
31
40
  * the resume has not yet settled.
32
41
  */
33
42
  let resumeSessionGate: Promise<void> | null = null;
43
+ /** Config options session/resume and session/load report back. */
44
+ let resumeConfigOptions: SessionConfigOption[] = [];
45
+ /**
46
+ * One `config_option_update` per entry, announced during session/load's
47
+ * replay, the way an adapter reports what the reattached session moved
48
+ * through before the load resolves.
49
+ */
50
+ let replayConfigOptionUpdates: SessionConfigOption[][] = [];
51
+ /** When set, setConfigOption rejects with it (the adapter refusing a pin). */
52
+ let setConfigOptionError: Error | null = null;
53
+ /** When set, setConfigOption answers with this instead of the moved selector. */
54
+ let setConfigOptionResult: SessionConfigOption[] | null = null;
55
+ /** Every `setConfigOption` the manager dispatched during a resume. */
56
+ const setConfigOptionCalls: Array<{
57
+ sessionId: string;
58
+ configId: string;
59
+ value: string | boolean;
60
+ }> = [];
34
61
  const fakeInstances: FakeAcpAgentProcess[] = [];
35
62
 
36
63
  class FakeAcpAgentProcess {
@@ -67,24 +94,63 @@ class FakeAcpAgentProcess {
67
94
  return fakeCaps.resume;
68
95
  }
69
96
 
70
- async createSession(_cwd: string): Promise<string> {
71
- return "proto-new";
97
+ async createSession(
98
+ _cwd: string,
99
+ ): Promise<{ sessionId: string; configOptions: SessionConfigOption[] }> {
100
+ return { sessionId: "proto-new", configOptions: [] };
72
101
  }
73
102
 
74
- async loadSession(sessionId: string, cwd: string): Promise<void> {
103
+ async loadSession(
104
+ sessionId: string,
105
+ cwd: string,
106
+ ): Promise<{ configOptions: SessionConfigOption[] }> {
75
107
  this.loadSessionCalls.push({ sessionId, cwd });
76
108
  // Replay history through the client handler before resolving, exactly
77
109
  // as a real agent does per the ACP spec for session/load.
78
110
  for (const text of replayChunks) {
79
111
  await this.emitChunk(text);
80
112
  }
113
+ for (const configOptions of replayConfigOptionUpdates) {
114
+ await this.emitConfigOptions(configOptions);
115
+ }
116
+ return { configOptions: resumeConfigOptions };
81
117
  }
82
118
 
83
- async resumeSession(sessionId: string, cwd: string): Promise<void> {
119
+ async resumeSession(
120
+ sessionId: string,
121
+ cwd: string,
122
+ ): Promise<{ configOptions: SessionConfigOption[] }> {
84
123
  if (resumeSessionGate) {
85
124
  await resumeSessionGate;
86
125
  }
87
126
  this.resumeSessionCalls.push({ sessionId, cwd });
127
+ return { configOptions: resumeConfigOptions };
128
+ }
129
+
130
+ /** Answers the way an adapter does: the selector now sits on `value`. */
131
+ async setConfigOption(
132
+ sessionId: string,
133
+ configId: string,
134
+ value: string | boolean,
135
+ ): Promise<SessionConfigOption[]> {
136
+ setConfigOptionCalls.push({ sessionId, configId, value });
137
+ if (setConfigOptionError) {
138
+ throw setConfigOptionError;
139
+ }
140
+ if (setConfigOptionResult) {
141
+ return setConfigOptionResult;
142
+ }
143
+ return typeof value === "string"
144
+ ? [modelOption(value)]
145
+ : resumeConfigOptions;
146
+ }
147
+
148
+ /** Drives a config_option_update through the real client handler. */
149
+ async emitConfigOptions(configOptions: SessionConfigOption[]): Promise<void> {
150
+ await this.clientFactory(this).sessionUpdate({
151
+ sessionId: "proto-old",
152
+ update: { sessionUpdate: "config_option_update", configOptions },
153
+ });
88
154
  }
89
155
 
90
156
  /** Drives an agent_message_chunk through the real client handler. */
@@ -174,7 +240,7 @@ mock.module("../prepare-agent-env.js", () => ({
174
240
  type ResolveResult =
175
241
  | {
176
242
  ok: true;
177
- agent: { command: string; args: string[] };
243
+ agent: { command: string; args: string[]; model?: string };
178
244
  }
179
245
  | { ok: false; reason: "binary_not_found"; hint: string; command: string };
180
246
  let resolveImpl: (id: string) => ResolveResult = () => ({
@@ -212,6 +278,7 @@ import type { AssistantEvent } from "../../api/index.js";
212
278
  import { getSqlite } from "../../persistence/db-connection.js";
213
279
  import { initializeDb } from "../../persistence/db-init.js";
214
280
  import type { AcpSessionState } from "../types.js";
281
+ import { AcpConfigOptionRefusedError } from "../types.js";
215
282
  import {
216
283
  clearHistory,
217
284
  insertHistoryRow,
@@ -264,6 +331,11 @@ beforeEach(() => {
264
331
  prepareAgentEnvGate = null;
265
332
  prepareAgentEnvCommands = [];
266
333
  resumeSessionGate = null;
334
+ resumeConfigOptions = [];
335
+ replayConfigOptionUpdates = [];
336
+ setConfigOptionError = null;
337
+ setConfigOptionResult = null;
338
+ setConfigOptionCalls.length = 0;
267
339
  resolveImpl = () => ({
268
340
  ok: true,
269
341
  agent: { command: "claude-agent-acp", args: [] },
@@ -510,7 +582,7 @@ describe("AcpSessionManager.resumeFromHistory", () => {
510
582
  expect(args).toEqual([
511
583
  "add",
512
584
  "--global",
513
- "@agentclientprotocol/claude-agent-acp",
585
+ "@agentclientprotocol/claude-agent-acp@0.75.1",
514
586
  ]);
515
587
  const { cwd, env } = options as { cwd?: string; env?: NodeJS.ProcessEnv };
516
588
  expect(cwd).toBeDefined();
@@ -711,6 +783,198 @@ describe("AcpSessionManager.resumeFromHistory", () => {
711
783
  expect(row.cost_currency).toBe("USD");
712
784
  });
713
785
 
786
+ test("a resume with no configured model leaves the adapter on its own", async () => {
787
+ fakeCaps.resume = true;
788
+ resumeConfigOptions = [modelOption("default")];
789
+ insertHistoryRow({ id: "resume-model-1" });
790
+
791
+ const manager = new AcpSessionManager(4);
792
+ await manager.resumeFromHistory("resume-model-1", () => {});
793
+
794
+ expect(setConfigOptionCalls).toEqual([]);
795
+ expect((manager.getStatus("resume-model-1") as AcpSessionState).model).toBe(
796
+ "default",
797
+ );
798
+ });
799
+
800
+ test("a resume keeps the model the adapter restored from the session", async () => {
801
+ fakeCaps.resume = true;
802
+ // The bundled Claude profile names opus, but the reattached session was
803
+ // running on sonnet and the adapter reports it back.
804
+ resolveImpl = () => ({
805
+ ok: true,
806
+ agent: { command: "claude-agent-acp", args: [], model: "opus" },
807
+ });
808
+ resumeConfigOptions = [modelOption("sonnet")];
809
+ insertHistoryRow({ id: "resume-model-2" });
810
+
811
+ const manager = new AcpSessionManager(4);
812
+ const sent: AssistantEvent[] = [];
813
+ await manager.resumeFromHistory("resume-model-2", (msg) => sent.push(msg));
814
+
815
+ expect(setConfigOptionCalls).toEqual([]);
816
+ const state = manager.getStatus("resume-model-2") as AcpSessionState;
817
+ expect(state.model).toBe("sonnet");
818
+ expect(sent.map((m) => m.type)).toEqual([
819
+ "acp_session_spawned",
820
+ "acp_session_model_update",
821
+ ]);
822
+ expect(sent.filter((m) => m.type === "acp_session_model_update")).toEqual([
823
+ {
824
+ type: "acp_session_model_update",
825
+ acpSessionId: "resume-model-2",
826
+ modelRevisionEpoch: state.modelRevisionEpoch!,
827
+ modelRevision: 1,
828
+ model: "sonnet",
829
+ availableModels: MODEL_OPTION_MODELS,
830
+ },
831
+ ]);
832
+ });
833
+
834
+ test("a model named only by the load replay keeps the session off the re-pin", async () => {
835
+ fakeCaps.loadSession = true;
836
+ // The selector reaches the manager only through the replayed
837
+ // notification: the load itself answers with no config options at all.
838
+ replayConfigOptionUpdates = [[modelOption("sonnet")]];
839
+ resumeConfigOptions = [];
840
+ resolveImpl = () => ({
841
+ ok: true,
842
+ agent: { command: "claude-agent-acp", args: [], model: "opus" },
843
+ });
844
+ insertHistoryRow({ id: "resume-replay-only" });
845
+
846
+ const manager = new AcpSessionManager(4);
847
+ const sent: AssistantEvent[] = [];
848
+ await manager.resumeFromHistory("resume-replay-only", (msg) =>
849
+ sent.push(msg),
850
+ );
851
+
852
+ // The replay is the adapter reporting what the session came back on, so
853
+ // the per-agent default has nothing to put right.
854
+ expect(setConfigOptionCalls).toEqual([]);
855
+ expect(
856
+ (manager.getStatus("resume-replay-only") as AcpSessionState).model,
857
+ ).toBe("sonnet");
858
+ const modelEvents = sent.filter(
859
+ (m) => m.type === "acp_session_model_update",
860
+ );
861
+ expect(modelEvents.map((m) => m.model)).toEqual(["sonnet", "sonnet"]);
862
+ expect(modelEvents[1]).toMatchObject({
863
+ acpSessionId: "resume-replay-only",
864
+ availableModels: MODEL_OPTION_MODELS,
865
+ });
866
+ });
867
+
868
+ test("a re-pin answered without the selector withdraws the picker the replay announced", async () => {
869
+ fakeCaps.loadSession = true;
870
+ // The replay puts the selector in front of clients before the re-pin
871
+ // runs, so the answer that drops it has something to correct. It names no
872
+ // model, which is what leaves the ladder something to apply.
873
+ replayConfigOptionUpdates = [[modelOptionWithoutCurrent()]];
874
+ resumeConfigOptions = [];
875
+ setConfigOptionResult = [nonModelOption()];
876
+ resolveImpl = () => ({
877
+ ok: true,
878
+ agent: { command: "claude-agent-acp", args: [], model: "opus" },
879
+ });
880
+ insertHistoryRow({
881
+ id: "resume-selector-gone",
882
+ eventLogJson: JSON.stringify([PERSISTED_EVENT]),
883
+ });
884
+
885
+ const manager = new AcpSessionManager(4);
886
+ const sent: AssistantEvent[] = [];
887
+ await manager.resumeFromHistory("resume-selector-gone", (msg) =>
888
+ sent.push(msg),
889
+ );
890
+
891
+ const state = manager.getStatus("resume-selector-gone") as AcpSessionState;
892
+ expect(state.model).toBeUndefined();
893
+ expect(state.availableModels).toEqual([]);
894
+ expect(sent.filter((m) => m.type === "acp_session_model_update")).toEqual([
895
+ {
896
+ type: "acp_session_model_update",
897
+ acpSessionId: "resume-selector-gone",
898
+ modelRevisionEpoch: state.modelRevisionEpoch!,
899
+ modelRevision: 1,
900
+ availableModels: MODEL_OPTION_MODELS,
901
+ },
902
+ {
903
+ type: "acp_session_model_update",
904
+ acpSessionId: "resume-selector-gone",
905
+ modelRevisionEpoch: state.modelRevisionEpoch!,
906
+ modelRevision: 2,
907
+ availableModels: [],
908
+ },
909
+ ]);
910
+ });
911
+
912
+ test("a re-pin the connection cannot carry tears the resume down", async () => {
913
+ fakeCaps.resume = true;
914
+ resumeConfigOptions = [modelOptionWithoutCurrent()];
915
+ setConfigOptionError = new Error("ACP connection closed");
916
+ resolveImpl = () => ({
917
+ ok: true,
918
+ agent: { command: "claude-agent-acp", args: [], model: "opus" },
919
+ });
920
+ insertHistoryRow({
921
+ id: "resume-pin-transport",
922
+ eventLogJson: JSON.stringify([PERSISTED_EVENT]),
923
+ });
924
+
925
+ const manager = new AcpSessionManager(4);
926
+ const sent: AssistantEvent[] = [];
927
+ await expect(
928
+ manager.resumeFromHistory("resume-pin-transport", (msg) =>
929
+ sent.push(msg),
930
+ ),
931
+ ).rejects.toThrow("ACP connection closed");
932
+
933
+ expect(sent.filter((m) => m.type === "acp_session_model_update")).toEqual(
934
+ [],
935
+ );
936
+ expect(manager.getStatus()).toEqual([]);
937
+ });
938
+
939
+ test("a resume the adapter refuses to re-pin runs on the adapter's model", async () => {
940
+ fakeCaps.resume = true;
941
+ resumeConfigOptions = [modelOptionWithoutCurrent()];
942
+ setConfigOptionError = new AcpConfigOptionRefusedError(
943
+ "Invalid value for config option model: opus",
944
+ );
945
+ resolveImpl = () => ({
946
+ ok: true,
947
+ agent: { command: "claude-agent-acp", args: [], model: "opus" },
948
+ });
949
+ insertHistoryRow({
950
+ id: "resume-refused-model",
951
+ eventLogJson: JSON.stringify([PERSISTED_EVENT]),
952
+ });
953
+
954
+ const manager = new AcpSessionManager(4);
955
+ const sent: AssistantEvent[] = [];
956
+ await manager.resumeFromHistory("resume-refused-model", (msg) =>
957
+ sent.push(msg),
958
+ );
959
+
960
+ // State and the published event name the model the run is really on, which
961
+ // is whatever the adapter reported, never the one it refused.
962
+ expect(
963
+ (manager.getStatus("resume-refused-model") as AcpSessionState).model,
964
+ ).toBeUndefined();
965
+ expect(sent.filter((m) => m.type === "acp_session_model_update")).toEqual([
966
+ {
967
+ type: "acp_session_model_update",
968
+ acpSessionId: "resume-refused-model",
969
+ modelRevisionEpoch: (
970
+ manager.getStatus("resume-refused-model") as AcpSessionState
971
+ ).modelRevisionEpoch!,
972
+ modelRevision: 1,
973
+ availableModels: MODEL_OPTION_MODELS,
974
+ },
975
+ ]);
976
+ });
977
+
714
978
  test("concurrent resumes of the same id: one wins, the loser fails cleanly without leaking a process", async () => {
715
979
  fakeCaps.resume = true;
716
980
  insertHistoryRow({ id: "race-1" });
@@ -28,8 +28,10 @@ mock.module("../agent-process.js", () => ({
28
28
  }
29
29
  spawn(_cwd: string): void {}
30
30
  async initialize(): Promise<void> {}
31
- async createSession(_cwd: string): Promise<string> {
32
- return `proto-${this.agentId}`;
31
+ async createSession(
32
+ _cwd: string,
33
+ ): Promise<{ sessionId: string; configOptions: [] }> {
34
+ return { sessionId: `proto-${this.agentId}`, configOptions: [] };
33
35
  }
34
36
  async prompt(): Promise<{ stopReason: string }> {
35
37
  return new Promise(() => {});