@vellumai/assistant 0.12.1 → 0.12.2-staging.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (577) hide show
  1. package/AGENTS.md +4 -0
  2. package/ARCHITECTURE.md +20 -21
  3. package/docs/architecture/turn-actor.md +15 -8
  4. package/docs/guardian-request-flow.md +16 -0
  5. package/node_modules/@vellumai/slack-text/src/index.ts +13 -8
  6. package/node_modules/@vellumai/slack-text/src/label-resolution-entities.test.ts +95 -0
  7. package/openapi.yaml +360 -51
  8. package/package.json +3 -1
  9. package/scripts/smoke-desktop-window-theme.ts +186 -0
  10. package/src/__tests__/always-loaded-tools-guard.test.ts +18 -10
  11. package/src/__tests__/anthropic-provider.test.ts +0 -63
  12. package/src/__tests__/app-compiler.test.ts +6 -0
  13. package/src/__tests__/app-control-tool-schemas.test.ts +5 -2
  14. package/src/__tests__/app-dir-path-guard.test.ts +1 -3
  15. package/src/__tests__/assistant-event-hub-machine-name.test.ts +6 -7
  16. package/src/__tests__/assistant-event-hub.test.ts +44 -0
  17. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
  18. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +5 -2
  19. package/src/__tests__/computer-use-tools.test.ts +19 -7
  20. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  21. package/src/__tests__/config-schema.test.ts +28 -29
  22. package/src/__tests__/config-watcher.test.ts +23 -8
  23. package/src/__tests__/connection-model-compat.test.ts +2 -2
  24. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  25. package/src/__tests__/conversation-pairing.test.ts +26 -0
  26. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -10
  27. package/src/__tests__/conversation-queue.test.ts +48 -207
  28. package/src/__tests__/conversation-retry-discard.test.ts +54 -1
  29. package/src/__tests__/conversation-runtime-assembly.test.ts +28 -0
  30. package/src/__tests__/conversation-skill-tools.test.ts +27 -0
  31. package/src/__tests__/conversation-surfaces-app-control.test.ts +8 -3
  32. package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +1 -0
  33. package/src/__tests__/conversation-surfaces-point-at-capability.test.ts +1 -0
  34. package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
  35. package/src/__tests__/conversation-title-service.test.ts +14 -10
  36. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +3 -5
  37. package/src/__tests__/conversation-tool-setup-attribution.test.ts +51 -0
  38. package/src/__tests__/credential-record-retire.test.ts +171 -1
  39. package/src/__tests__/credential-routes.test.ts +250 -3
  40. package/src/__tests__/credential-security-invariants.test.ts +5 -3
  41. package/src/__tests__/cu-unified-flow.test.ts +14 -4
  42. package/src/__tests__/document-sync-tags.test.ts +25 -0
  43. package/src/__tests__/drain-kick-guard.test.ts +0 -2
  44. package/src/__tests__/drain-requeue-on-contention.test.ts +0 -6
  45. package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
  46. package/src/__tests__/git-porcelain.test.ts +47 -0
  47. package/src/__tests__/heartbeat-service.test.ts +56 -40
  48. package/src/__tests__/helpers/set-workspace-mcp.ts +11 -0
  49. package/src/__tests__/host-bash-proxy.test.ts +26 -45
  50. package/src/__tests__/host-browser-proxy.test.ts +6 -17
  51. package/src/__tests__/host-cu-proxy.test.ts +596 -0
  52. package/src/__tests__/host-file-proxy-targeted.test.ts +23 -0
  53. package/src/__tests__/host-file-proxy.test.ts +11 -23
  54. package/src/__tests__/host-transfer-proxy-targeted.test.ts +30 -9
  55. package/src/__tests__/list-messages-camera-frame.test.ts +121 -0
  56. package/src/__tests__/llm-catalog-parity.test.ts +25 -0
  57. package/src/__tests__/mcp-auth-routes.test.ts +6 -9
  58. package/src/__tests__/mcp-config-secret-boundary.test.ts +78 -136
  59. package/src/__tests__/mcp-health-check.test.ts +8 -11
  60. package/src/__tests__/mcp-list-plugin-servers.test.ts +8 -10
  61. package/src/__tests__/message-deleted-hook-dispatch.test.ts +119 -0
  62. package/src/__tests__/messages-after-tiebreaker.test.ts +91 -0
  63. package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
  64. package/src/__tests__/messaging-send-tool.test.ts +355 -548
  65. package/src/__tests__/model-intents.test.ts +3 -0
  66. package/src/__tests__/notification-vellum-adapter.test.ts +85 -2
  67. package/src/__tests__/oauth-commands-routes.test.ts +168 -0
  68. package/src/__tests__/oauth-provider-profiles.test.ts +18 -0
  69. package/src/__tests__/oauth-provider-serializer.test.ts +22 -0
  70. package/src/__tests__/oauth-providers-routes.test.ts +1 -0
  71. package/src/__tests__/openai-provider.test.ts +1 -0
  72. package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
  73. package/src/__tests__/platform-callback-registration.test.ts +8 -16
  74. package/src/__tests__/platform-client-verify-credential.test.ts +2 -0
  75. package/src/__tests__/plugin-import-boundary-guard.test.ts +14 -0
  76. package/src/__tests__/qdrant-manager.test.ts +132 -0
  77. package/src/__tests__/resolve-app.test.ts +135 -0
  78. package/src/__tests__/scaffold-managed-skill-tool.test.ts +229 -6
  79. package/src/__tests__/script-proxy-certs.test.ts +35 -0
  80. package/src/__tests__/secret-routes-acp-guard.test.ts +59 -1
  81. package/src/__tests__/service-account-token.test.ts +247 -0
  82. package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
  83. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  84. package/src/__tests__/skills.test.ts +9 -4
  85. package/src/__tests__/source-fingerprint.test.ts +184 -0
  86. package/src/__tests__/subagent-tool-gate-mode.test.ts +70 -3
  87. package/src/__tests__/subagent-tools.test.ts +3 -2
  88. package/src/__tests__/telephony-tts-guard.test.ts +38 -3
  89. package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
  90. package/src/__tests__/ui-channel-variants.test.ts +1 -56
  91. package/src/__tests__/unicode.test.ts +13 -0
  92. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +4 -0
  93. package/src/__tests__/watch-retro-tool-availability.test.ts +8 -17
  94. package/src/__tests__/workspace-git-service.test.ts +26 -0
  95. package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +336 -0
  96. package/src/acp/__tests__/acp-claude-oauth.test.ts +257 -6
  97. package/src/acp/__tests__/acp-credentials.test.ts +13 -0
  98. package/src/acp/__tests__/agent-process.test.ts +258 -4
  99. package/src/acp/__tests__/auth-required.test.ts +96 -0
  100. package/src/acp/__tests__/claude-token-refresh.test.ts +257 -0
  101. package/src/acp/__tests__/client-handler.test.ts +90 -2
  102. package/src/acp/__tests__/helpers/acp-model-option.ts +51 -0
  103. package/src/acp/__tests__/prepare-agent-env.test.ts +60 -1
  104. package/src/acp/__tests__/session-manager-persistence.test.ts +5 -1
  105. package/src/acp/__tests__/session-manager-resume.test.ts +270 -6
  106. package/src/acp/__tests__/session-manager-usage.test.ts +4 -2
  107. package/src/acp/__tests__/session-manager.test.ts +895 -4
  108. package/src/acp/acp-claude-oauth.ts +328 -14
  109. package/src/acp/acp-credentials.ts +19 -0
  110. package/src/acp/agent-process.test.ts +4 -1
  111. package/src/acp/agent-process.ts +96 -10
  112. package/src/acp/auth-required.ts +50 -1
  113. package/src/acp/auto-install.test.ts +9 -7
  114. package/src/acp/claude-token-refresh.ts +150 -0
  115. package/src/acp/client-handler.ts +16 -3
  116. package/src/acp/model-config.test.ts +166 -0
  117. package/src/acp/model-config.ts +138 -0
  118. package/src/acp/prepare-agent-env.ts +21 -6
  119. package/src/acp/resolve-agent.test.ts +220 -6
  120. package/src/acp/resolve-agent.ts +88 -23
  121. package/src/acp/session-manager.test.ts +196 -3
  122. package/src/acp/session-manager.ts +441 -18
  123. package/src/acp/types.ts +50 -5
  124. package/src/agent/loop.ts +1 -0
  125. package/src/api/events/acp-session-model-update.test.ts +88 -0
  126. package/src/api/events/acp-session-model-update.ts +46 -0
  127. package/src/api/events/app-files-changed.ts +4 -3
  128. package/src/api/events/notification-intent.ts +2 -0
  129. package/src/api/events/user-message-echo.ts +7 -1
  130. package/src/api/index.ts +6 -0
  131. package/src/api/responses/conversation-message.ts +5 -0
  132. package/src/apps/app-store.ts +1 -1
  133. package/src/apps/resolve-app.ts +81 -0
  134. package/src/apps/source-fingerprint.ts +266 -0
  135. package/src/avatar/identity-avatar.ts +7 -2
  136. package/src/bundler/app-compiler.ts +15 -0
  137. package/src/calls/__tests__/barge-in-guard.test.ts +81 -0
  138. package/src/{__tests__ → calls/__tests__}/call-controller.test.ts +503 -82
  139. package/src/{__tests__ → calls/__tests__}/media-stream-audio-transcode.test.ts +1 -1
  140. package/src/{__tests__ → calls/__tests__}/media-stream-output.test.ts +37 -8
  141. package/src/{__tests__ → calls/__tests__}/media-stream-parser.test.ts +1 -1
  142. package/src/{__tests__ → calls/__tests__}/media-stream-server-integration.test.ts +150 -57
  143. package/src/{__tests__ → calls/__tests__}/media-stream-stt-session.test.ts +5 -5
  144. package/src/{__tests__ → calls/__tests__}/media-turn-detector.test.ts +1 -1
  145. package/src/{live-voice → calls}/__tests__/progress-narration.test.ts +4 -4
  146. package/src/{live-voice → calls}/__tests__/progress-phrases.test.ts +1 -1
  147. package/src/calls/__tests__/voice-control-protocol.test.ts +120 -25
  148. package/src/calls/__tests__/voice-leg-coordinator.test.ts +229 -0
  149. package/src/calls/__tests__/voice-progress-cadence.test.ts +274 -0
  150. package/src/{__tests__/voice-session-bridge.test.ts → calls/__tests__/voice-session-bridge-turn-flow.test.ts} +20 -12
  151. package/src/calls/__tests__/voice-session-bridge.test.ts +56 -1
  152. package/src/calls/__tests__/voice-triage-escalate.test.ts +105 -0
  153. package/src/calls/barge-in-guard.ts +118 -0
  154. package/src/calls/call-constants.ts +24 -4
  155. package/src/calls/call-controller.ts +499 -199
  156. package/src/calls/call-transport.ts +16 -0
  157. package/src/calls/media-stream-output.ts +32 -0
  158. package/src/calls/media-stream-server.ts +82 -30
  159. package/src/calls/media-stream-stt-session.ts +15 -0
  160. package/src/{live-voice → calls}/progress-narration.ts +2 -2
  161. package/src/calls/resolve-call-tts-provider.ts +33 -2
  162. package/src/calls/tts-call-strategy.ts +9 -5
  163. package/src/calls/types.ts +2 -0
  164. package/src/calls/voice-control-protocol.ts +155 -21
  165. package/src/calls/voice-leg-coordinator.ts +189 -0
  166. package/src/calls/voice-progress-cadence.ts +423 -0
  167. package/src/calls/voice-session-bridge.ts +92 -72
  168. package/src/calls/voice-triage-escalate.ts +178 -59
  169. package/src/cli/commands/__tests__/apps.test.ts +245 -0
  170. package/src/cli/commands/__tests__/bash.test.ts +53 -0
  171. package/src/cli/commands/__tests__/roadmap.help.test.ts +19 -0
  172. package/src/cli/commands/apps.help.ts +67 -13
  173. package/src/cli/commands/apps.ts +183 -0
  174. package/src/cli/commands/bash.help.ts +8 -13
  175. package/src/cli/commands/bash.ts +7 -25
  176. package/src/cli/commands/channels/__tests__/send.test.ts +218 -0
  177. package/src/cli/commands/channels/index.help.ts +70 -2
  178. package/src/cli/commands/channels/index.ts +16 -3
  179. package/src/cli/commands/channels/send.ts +128 -0
  180. package/src/cli/commands/credentials.help.ts +6 -2
  181. package/src/cli/commands/credentials.ts +2 -2
  182. package/src/cli/commands/mcp.help.ts +8 -8
  183. package/src/cli/commands/mcp.ts +1 -1
  184. package/src/cli/commands/oauth/status.ts +5 -0
  185. package/src/cli/commands/roadmap.help.ts +5 -1
  186. package/src/cli/commands/roadmap.ts +1 -1
  187. package/src/cli/lib/bundled-marketplace.json +103 -90
  188. package/src/config/__tests__/default-profile-catalog.test.ts +22 -0
  189. package/src/config/__tests__/memory-retrospective-schema.test.ts +15 -1
  190. package/src/config/__tests__/platform-identity.test.ts +255 -0
  191. package/src/config/__tests__/platform-rehydration.test.ts +99 -9
  192. package/src/config/acp-agent-write.ts +43 -0
  193. package/src/config/acp-defaults.test.ts +13 -3
  194. package/src/config/acp-defaults.ts +23 -6
  195. package/src/config/acp-schema.test.ts +81 -0
  196. package/src/config/acp-schema.ts +30 -2
  197. package/src/config/bundled-skills/acp/SKILL.md +22 -14
  198. package/src/config/bundled-skills/acp/TOOLS.json +5 -1
  199. package/src/config/bundled-skills/app-builder/SKILL.md +12 -9
  200. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
  201. package/src/config/bundled-skills/computer-use/SKILL.md +29 -2
  202. package/src/config/bundled-skills/computer-use/TOOLS.json +99 -0
  203. package/src/config/bundled-skills/computer-use/tools/computer-use-sequence.ts +12 -0
  204. package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -1
  205. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -1
  206. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -1
  207. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  208. package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
  209. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +67 -139
  210. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
  211. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -1
  212. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -1
  213. package/src/config/bundled-skills/schedule/SKILL.md +3 -4
  214. package/src/config/bundled-skills/screen-annotation/SKILL.md +8 -1
  215. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +4 -1
  216. package/src/config/bundled-skills/skill-management/TOOLS.json +6 -2
  217. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +5 -2
  218. package/src/config/default-profile-catalog.ts +1 -1
  219. package/src/config/env.ts +2 -2
  220. package/src/config/feature-flag-registry.json +33 -13
  221. package/src/config/loader.ts +2 -0
  222. package/src/config/memory-v3-gate.test.ts +31 -0
  223. package/src/config/memory-v3-gate.ts +20 -16
  224. package/src/config/platform-identity.ts +201 -0
  225. package/src/config/platform-rehydration.ts +11 -27
  226. package/src/config/schema.ts +2 -2
  227. package/src/config/schemas/__tests__/live-voice.test.ts +8 -158
  228. package/src/config/schemas/__tests__/voice.test.ts +148 -0
  229. package/src/config/schemas/calls.ts +1 -28
  230. package/src/config/schemas/live-voice.ts +1 -173
  231. package/src/config/schemas/mcp.ts +1 -1
  232. package/src/config/schemas/memory-retrospective.ts +10 -0
  233. package/src/config/schemas/services.ts +18 -0
  234. package/src/config/schemas/skills.ts +0 -14
  235. package/src/config/schemas/voice.ts +150 -0
  236. package/src/credential-execution/process-manager.test.ts +18 -19
  237. package/src/credential-health/credential-health-service.ts +11 -17
  238. package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -121
  239. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +4 -1
  240. package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +133 -0
  241. package/src/daemon/app-change-notify.ts +45 -0
  242. package/src/daemon/config-watcher.ts +13 -194
  243. package/src/daemon/conversation-error.ts +3 -2
  244. package/src/daemon/conversation-media-retry.ts +2 -1
  245. package/src/daemon/conversation-process.ts +35 -64
  246. package/src/daemon/conversation-runtime-assembly.ts +20 -7
  247. package/src/daemon/conversation-skill-tools.ts +13 -31
  248. package/src/daemon/conversation-store.ts +1 -1
  249. package/src/daemon/conversation-surfaces.ts +21 -10
  250. package/src/daemon/conversation-tool-setup.ts +45 -59
  251. package/src/daemon/conversation.ts +0 -3
  252. package/src/daemon/dictation-profile-store.ts +2 -1
  253. package/src/daemon/handlers/shared.ts +2 -1
  254. package/src/daemon/handlers/skills.ts +6 -3
  255. package/src/daemon/host-bash-proxy.ts +8 -12
  256. package/src/daemon/host-browser-proxy.ts +15 -1
  257. package/src/daemon/host-cu-proxy.ts +224 -19
  258. package/src/daemon/host-file-proxy.ts +8 -10
  259. package/src/daemon/host-proxy-preactivation.ts +2 -1
  260. package/src/daemon/host-transfer-proxy.ts +14 -18
  261. package/src/daemon/lifecycle.ts +0 -5
  262. package/src/daemon/mcp-reload-service.ts +5 -5
  263. package/src/daemon/message-types/sync.ts +1 -0
  264. package/src/daemon/orphan-reaper.ts +1 -1
  265. package/src/daemon/providers-setup.ts +1 -1
  266. package/src/daemon/reaction-history-render.ts +2 -1
  267. package/src/daemon/shutdown-handlers.ts +1 -9
  268. package/src/daemon/skill-memory-refresh.ts +64 -0
  269. package/src/daemon/tool-side-effects.ts +7 -18
  270. package/src/desktop/__tests__/fake-desktop.ts +122 -0
  271. package/src/desktop/desktop-chrome-policy.test.ts +79 -0
  272. package/src/desktop/desktop-chrome-policy.ts +47 -0
  273. package/src/desktop/desktop-chrome-session.ts +37 -0
  274. package/src/desktop/desktop-dependencies.test.ts +102 -0
  275. package/src/desktop/desktop-dependencies.ts +308 -0
  276. package/src/desktop/desktop-feature.test.ts +18 -0
  277. package/src/desktop/desktop-feature.ts +19 -0
  278. package/src/desktop/desktop-panel-config.test.ts +135 -0
  279. package/src/desktop/desktop-panel-config.ts +149 -0
  280. package/src/desktop/desktop-session-manager.test.ts +730 -0
  281. package/src/desktop/desktop-session-manager.ts +850 -0
  282. package/src/desktop/desktop-stream-bridge.test.ts +395 -0
  283. package/src/desktop/desktop-stream-bridge.ts +214 -0
  284. package/src/desktop/desktop-wallpaper.test.ts +191 -0
  285. package/src/desktop/desktop-wallpaper.ts +113 -0
  286. package/src/desktop/desktop-window-drag.ts +177 -0
  287. package/src/desktop/desktop-window-manager-config.test.ts +230 -0
  288. package/src/desktop/desktop-window-manager-config.ts +238 -0
  289. package/src/desktop/desktop-window-theme.ts +170 -0
  290. package/src/heartbeat/heartbeat-service.ts +21 -3
  291. package/src/home/__tests__/feed-writer.test.ts +22 -0
  292. package/src/home/feed-writer.ts +11 -2
  293. package/src/hooks/types.ts +33 -0
  294. package/src/i18n/AGENTS.md +22 -0
  295. package/src/i18n/__tests__/i18n.test.ts +108 -0
  296. package/src/i18n/index.ts +16 -0
  297. package/src/i18n/locales.ts +93 -0
  298. package/src/i18n/messages.ts +61 -0
  299. package/src/i18n/title.ts +25 -0
  300. package/src/inbound/platform-callback-registration.ts +4 -5
  301. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +121 -0
  302. package/src/live-voice/__tests__/live-voice-events.test.ts +8 -7
  303. package/src/live-voice/__tests__/live-voice-metrics.test.ts +0 -3
  304. package/src/live-voice/__tests__/live-voice-progress.test.ts +94 -15
  305. package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +238 -0
  306. package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
  307. package/src/live-voice/__tests__/protocol.test.ts +39 -0
  308. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +13 -69
  309. package/src/live-voice/__tests__/session-controls.test.ts +79 -0
  310. package/src/live-voice/live-voice-photo.ts +25 -6
  311. package/src/live-voice/live-voice-session.ts +297 -699
  312. package/src/live-voice/protocol.ts +60 -2
  313. package/src/live-voice/session-controls.ts +111 -0
  314. package/src/mcp/__tests__/effective-config.test.ts +2 -2
  315. package/src/mcp/__tests__/workspace-mcp-config.test.ts +135 -0
  316. package/src/mcp/effective-config.ts +3 -3
  317. package/src/mcp/mcp-header-store.ts +29 -45
  318. package/src/mcp/spec-schema.ts +111 -0
  319. package/src/mcp/startup.ts +8 -4
  320. package/src/mcp/workspace-mcp-config.ts +188 -0
  321. package/src/messaging/provider.ts +10 -3
  322. package/src/messaging/providers/__tests__/proactive-address.test.ts +95 -0
  323. package/src/messaging/providers/callback-routing.ts +18 -0
  324. package/src/messaging/providers/channel-transport.ts +56 -0
  325. package/src/messaging/providers/discord/transport.ts +17 -0
  326. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +6 -17
  327. package/src/messaging/providers/slack/adapter.ts +7 -44
  328. package/src/messaging/providers/slack/transport.ts +16 -0
  329. package/src/messaging/providers/telegram-bot/adapter.ts +1 -48
  330. package/src/messaging/providers/telegram-bot/client.ts +0 -26
  331. package/src/messaging/providers/telegram-bot/transport.ts +20 -0
  332. package/src/messaging/providers/whatsapp/adapter.ts +1 -48
  333. package/src/messaging/providers/whatsapp/transport.ts +18 -0
  334. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +8 -0
  335. package/src/notifications/__tests__/assistant-reply-producer.test.ts +55 -0
  336. package/src/notifications/__tests__/guardian-feed-projection.test.ts +158 -2
  337. package/src/notifications/__tests__/home-feed-side-effect.test.ts +153 -3
  338. package/src/notifications/__tests__/schedule-result-producer.test.ts +99 -3
  339. package/src/notifications/adapters/macos.ts +3 -0
  340. package/src/notifications/assistant-reply-producer.ts +8 -3
  341. package/src/notifications/conversation-pairing.ts +36 -16
  342. package/src/notifications/delivered-post-record.ts +11 -1
  343. package/src/notifications/guardian-feed-projection.ts +125 -5
  344. package/src/notifications/home-feed-side-effect.ts +55 -7
  345. package/src/notifications/schedule-result-producer.ts +66 -22
  346. package/src/oauth/AGENTS.md +2 -0
  347. package/src/oauth/__tests__/seed-providers-managed.test.ts +149 -0
  348. package/src/oauth/byo-connection.test.ts +105 -0
  349. package/src/oauth/byo-connection.ts +36 -6
  350. package/src/oauth/connection-resolver.test.ts +100 -0
  351. package/src/oauth/connection-resolver.ts +120 -3
  352. package/src/oauth/provider-serializer.ts +9 -0
  353. package/src/oauth/scope-utils.ts +24 -0
  354. package/src/oauth/seed-providers.ts +314 -27
  355. package/src/outbound-proxy/certs.ts +3 -5
  356. package/src/permissions/checker.test.ts +11 -6
  357. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  358. package/src/persistence/conversation-crud.ts +71 -63
  359. package/src/persistence/conversation-lineage.ts +12 -4
  360. package/src/persistence/conversation-queries.ts +2 -2
  361. package/src/persistence/conversation-title-placeholders.ts +23 -0
  362. package/src/persistence/conversation-title-service.ts +9 -26
  363. package/src/persistence/embeddings/qdrant-manager.ts +163 -18
  364. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  365. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  366. package/src/persistence/message-cursor.ts +78 -0
  367. package/src/persistence/message-reads.ts +30 -0
  368. package/src/persistence/migrations/157-invite-contact-id.ts +18 -6
  369. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +149 -0
  370. package/src/persistence/schema/memory-core.ts +5 -0
  371. package/src/platform/client.test.ts +4 -2
  372. package/src/platform/client.ts +2 -10
  373. package/src/plugin-api/constants.ts +2 -0
  374. package/src/plugin-api/index.ts +1 -0
  375. package/src/plugin-api/types.ts +2 -0
  376. package/src/plugins/defaults/index.ts +2 -0
  377. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +46 -0
  378. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +118 -0
  379. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +83 -0
  380. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +9 -5
  381. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +20 -10
  382. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +5 -0
  383. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +219 -0
  384. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +31 -0
  385. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +63 -0
  386. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +4 -0
  387. package/src/plugins/defaults/memory/context-search/agent-runner.ts +3 -2
  388. package/src/plugins/defaults/memory/context-search/format.ts +3 -2
  389. package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +6 -3
  390. package/src/plugins/defaults/memory/context-search/sources/workspace.ts +3 -2
  391. package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -7
  392. package/src/plugins/defaults/memory/hooks/init.ts +10 -0
  393. package/src/plugins/defaults/memory/hooks/message-deleted.ts +21 -0
  394. package/src/plugins/defaults/memory/hooks/shutdown.ts +2 -0
  395. package/src/plugins/defaults/memory/host-utils.ts +10 -0
  396. package/src/plugins/defaults/memory/jobs-worker.ts +13 -0
  397. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +34 -60
  398. package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +126 -0
  399. package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +79 -0
  400. package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +28 -0
  401. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +3 -5
  402. package/src/plugins/defaults/memory/memory-retrospective-job.ts +12 -3
  403. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +1 -1
  404. package/src/plugins/defaults/memory/memory-retrospective-state.ts +312 -71
  405. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +2 -1
  406. package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +5 -3
  407. package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +9 -0
  408. package/src/plugins/defaults/memory/startup.ts +28 -2
  409. package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +7 -9
  410. package/src/plugins/defaults/memory/substrate/page-index.ts +6 -1
  411. package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
  412. package/src/plugins/defaults/memory/v1/graph/consolidation.ts +4 -2
  413. package/src/plugins/defaults/memory/v1/graph/extraction.ts +4 -2
  414. package/src/plugins/defaults/memory/v1/graph/retriever.ts +4 -1
  415. package/src/plugins/defaults/memory/v2/reranker.ts +6 -1
  416. package/src/plugins/defaults/memory/v3/__tests__/card.test.ts +24 -0
  417. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +125 -0
  418. package/src/plugins/defaults/memory/v3/__tests__/sections.test.ts +26 -0
  419. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +30 -0
  420. package/src/plugins/defaults/memory/v3/card.ts +3 -2
  421. package/src/plugins/defaults/memory/v3/pool-select.ts +5 -3
  422. package/src/plugins/defaults/memory/v3/sections.ts +9 -3
  423. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +5 -2
  424. package/src/plugins/defaults/memory/worker.ts +6 -0
  425. package/src/plugins/mcp-servers.ts +15 -75
  426. package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
  427. package/src/providers/__tests__/retry-callsite.test.ts +41 -0
  428. package/src/providers/__tests__/retry-outbound-sanitize.test.ts +176 -0
  429. package/src/providers/anthropic/client.ts +0 -47
  430. package/src/providers/gemini/client.ts +9 -23
  431. package/src/providers/gemini-thought-signature.test.ts +63 -0
  432. package/src/providers/gemini-thought-signature.ts +44 -0
  433. package/src/providers/inference/__tests__/endpoint-probe.test.ts +42 -3
  434. package/src/providers/inference/auth.ts +2 -3
  435. package/src/providers/inference/connection-availability.ts +27 -8
  436. package/src/providers/inference/endpoint-probe.ts +10 -1
  437. package/src/providers/inference/resolve-auth.ts +22 -4
  438. package/src/providers/inference/service-account-token.ts +248 -0
  439. package/src/providers/model-catalog.ts +34 -0
  440. package/src/providers/model-intents.ts +10 -5
  441. package/src/providers/openai/__tests__/chat-completions-output-token-limit.test.ts +141 -0
  442. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +146 -18
  443. package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +613 -0
  444. package/src/providers/openai/__tests__/google-thought-signature.test.ts +235 -0
  445. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +83 -1
  446. package/src/providers/openai/chat-completions-provider.ts +212 -79
  447. package/src/providers/openai/codex-models.ts +0 -4
  448. package/src/providers/openai/google-thought-signature.ts +320 -0
  449. package/src/providers/opencode/client.test.ts +73 -4
  450. package/src/providers/opencode/client.ts +60 -3
  451. package/src/providers/openrouter/client.ts +20 -0
  452. package/src/providers/outbound-request-sanitize.ts +96 -0
  453. package/src/providers/retry.ts +30 -19
  454. package/src/providers/unparseable-tool-args.ts +5 -1
  455. package/src/runtime/AGENTS.md +3 -1
  456. package/src/runtime/__tests__/channel-send.test.ts +443 -0
  457. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +89 -0
  458. package/src/runtime/__tests__/host-observe.test.ts +40 -1
  459. package/src/runtime/__tests__/live-voice-upgrade.test.ts +58 -0
  460. package/src/runtime/__tests__/runtime-ws-test-utils.ts +72 -0
  461. package/src/runtime/__tests__/watch-stream-upgrade.test.ts +59 -0
  462. package/src/runtime/agent-wake.ts +2 -1
  463. package/src/runtime/assistant-event-hub.ts +21 -3
  464. package/src/runtime/auth/same-actor.ts +38 -3
  465. package/src/runtime/channel-send.ts +316 -0
  466. package/src/runtime/host-observe.ts +11 -1
  467. package/src/runtime/http-server.ts +160 -151
  468. package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +16 -5
  469. package/src/runtime/routes/__tests__/acp-routes.test.ts +159 -4
  470. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +275 -0
  471. package/src/runtime/routes/__tests__/channel-send-routes.test.ts +127 -0
  472. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +108 -1
  473. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
  474. package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +107 -0
  475. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +16 -12
  476. package/src/runtime/routes/acp-claude-auth-routes.ts +11 -3
  477. package/src/runtime/routes/acp-routes.test.ts +15 -0
  478. package/src/runtime/routes/acp-routes.ts +72 -9
  479. package/src/runtime/routes/app-management-routes.ts +90 -2
  480. package/src/runtime/routes/app-routes.ts +1 -1
  481. package/src/runtime/routes/channel-send-routes.ts +85 -0
  482. package/src/runtime/routes/conversation-list-routes.ts +14 -3
  483. package/src/runtime/routes/conversation-query-routes.ts +40 -0
  484. package/src/runtime/routes/conversation-routes.ts +16 -3
  485. package/src/runtime/routes/credential-routes.ts +20 -14
  486. package/src/runtime/routes/desktop-setup-routes.test.ts +74 -0
  487. package/src/runtime/routes/desktop-setup-routes.ts +35 -0
  488. package/src/runtime/routes/diagnostics-routes.ts +61 -4
  489. package/src/runtime/routes/events-routes.ts +4 -0
  490. package/src/runtime/routes/host-cu-routes.ts +6 -0
  491. package/src/runtime/routes/index.ts +4 -2
  492. package/src/runtime/routes/log-export-routes.ts +2 -0
  493. package/src/runtime/routes/mcp-auth-routes.ts +39 -47
  494. package/src/runtime/routes/migration-routes.ts +6 -20
  495. package/src/runtime/routes/oauth-commands-routes.ts +50 -0
  496. package/src/runtime/routes/oauth-providers.ts +7 -0
  497. package/src/runtime/routes/platform-routes.ts +18 -15
  498. package/src/runtime/routes/workspace-routes.test.ts +55 -26
  499. package/src/runtime/routes/workspace-routes.ts +46 -63
  500. package/src/runtime/routes/workspace-tree-walk.test.ts +244 -0
  501. package/src/runtime/routes/workspace-tree-walk.ts +240 -0
  502. package/src/runtime/routes/workspace-utils.ts +17 -0
  503. package/src/runtime/services/__tests__/conversation-serializer.test.ts +28 -0
  504. package/src/runtime/services/conversation-serializer.ts +16 -3
  505. package/src/runtime/sync/resource-sync-events.ts +2 -1
  506. package/src/schedule/run-script.ts +2 -1
  507. package/src/schedule/schedule-store.ts +9 -2
  508. package/src/schedule/worker.ts +1 -1
  509. package/src/security/__tests__/ces-http-record-backend.test.ts +137 -0
  510. package/src/security/ces-http-record-backend.ts +120 -0
  511. package/src/security/ces-rpc-record-backend.ts +7 -0
  512. package/src/security/untrusted-content.ts +3 -1
  513. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +60 -0
  514. package/src/skills/workspace-skill-md-signature.ts +50 -0
  515. package/src/subagent/consult-context.ts +12 -25
  516. package/src/tools/__tests__/side-effect-abort-guard.test.ts +1 -0
  517. package/src/tools/acp/list-agents.test.ts +3 -1
  518. package/src/tools/acp/spawn.test.ts +146 -11
  519. package/src/tools/acp/spawn.ts +21 -3
  520. package/src/tools/acp/status.test.ts +94 -0
  521. package/src/tools/acp/status.ts +40 -3
  522. package/src/tools/app-control/skill-proxy-bridge.ts +2 -1
  523. package/src/tools/browser/browser-execution.ts +1 -1
  524. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +9 -3
  525. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +2 -1
  526. package/src/tools/browser/cdp-client/extension-cdp-client.ts +3 -2
  527. package/src/tools/browser/network-recorder.ts +2 -1
  528. package/src/tools/capability-offer.test.ts +22 -2
  529. package/src/tools/capability-offer.ts +16 -1
  530. package/src/tools/computer-use/definitions.ts +121 -2
  531. package/src/tools/computer-use/skill-proxy-bridge.ts +2 -1
  532. package/src/tools/credentials/metadata-store.ts +100 -0
  533. package/src/tools/filesystem/search.ts +2 -1
  534. package/src/tools/host-filesystem/edit.test.ts +2 -1
  535. package/src/tools/host-filesystem/edit.ts +2 -2
  536. package/src/tools/host-filesystem/read.test.ts +2 -1
  537. package/src/tools/host-filesystem/read.ts +2 -2
  538. package/src/tools/host-filesystem/transfer.test.ts +2 -1
  539. package/src/tools/host-filesystem/transfer.ts +2 -2
  540. package/src/tools/host-filesystem/write.test.ts +2 -1
  541. package/src/tools/host-filesystem/write.ts +2 -2
  542. package/src/tools/host-terminal/host-shell.test.ts +16 -0
  543. package/src/tools/host-terminal/host-shell.ts +4 -20
  544. package/src/tools/network/web-search.ts +6 -1
  545. package/src/tools/policy-context.ts +6 -7
  546. package/src/tools/skills/scaffold-managed.ts +61 -3
  547. package/src/tools/subagent/spawn.ts +5 -8
  548. package/src/tools/terminal/__tests__/sanitized-bash.test.ts +57 -0
  549. package/src/tools/terminal/sanitized-bash.ts +105 -0
  550. package/src/tools/ui-surface/channel-variants.ts +10 -59
  551. package/src/tools/watch/watch-retro-report.ts +0 -8
  552. package/src/types/host-capabilities.ts +5 -3
  553. package/src/util/__tests__/language-subtag.test.ts +23 -1
  554. package/src/util/ca-bundle.ts +13 -0
  555. package/src/util/language-subtag.ts +16 -0
  556. package/src/util/platform.ts +8 -0
  557. package/src/util/unicode.ts +15 -1
  558. package/src/watch/watch-retro.ts +6 -8
  559. package/src/watch/watch-timeline.ts +2 -2
  560. package/src/workflows/run-manager.ts +2 -1
  561. package/src/workspace/git-porcelain.ts +66 -0
  562. package/src/workspace/git-service.ts +6 -55
  563. package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +258 -0
  564. package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +78 -0
  565. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +214 -0
  566. package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +102 -0
  567. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +199 -0
  568. package/src/workspace/migrations/registry.ts +6 -0
  569. package/src/__tests__/app-source-watcher.test.ts +0 -218
  570. package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -359
  571. package/src/__tests__/speaker-identification.test.ts +0 -56
  572. package/src/calls/speaker-identification.ts +0 -233
  573. package/src/daemon/app-source-watcher.ts +0 -218
  574. package/src/messaging/providers/whatsapp/client.ts +0 -29
  575. package/src/runtime/routes/debug-bash-routes.ts +0 -173
  576. package/src/util/fs-watcher-error.ts +0 -36
  577. /package/src/{live-voice → calls}/progress-phrases.ts +0 -0
@@ -26,32 +26,8 @@ const CallsDisclosureConfigSchema = z
26
26
  "Controls whether and how the assistant discloses its nature at the start of a phone call",
27
27
  );
28
28
 
29
- const CallsSafetyConfigSchema = z
30
- .object({
31
- denyCategories: z
32
- .array(
33
- z.string({
34
- error: "calls.safety.denyCategories values must be strings",
35
- }),
36
- )
37
- .default([])
38
- .describe(
39
- "Categories of calls that should be denied (e.g. for safety or compliance reasons)",
40
- ),
41
- })
42
- .describe("Safety guardrails for phone calls");
43
-
44
29
  const CallsVoiceConfigSchema = z
45
30
  .object({
46
- interruptSensitivity: z
47
- .enum(["low", "medium", "high"], {
48
- error:
49
- "calls.voice.interruptSensitivity must be one of: low, medium, high",
50
- })
51
- .default("low")
52
- .describe(
53
- "How aggressively the STT provider detects the start of caller speech — low reduces false interrupts from background noise",
54
- ),
55
31
  telephonyStreaming: z
56
32
  .boolean({
57
33
  error: "calls.voice.telephonyStreaming must be a boolean",
@@ -227,7 +203,6 @@ export const CallsConfigSchema = z
227
203
  disclosure: CallsDisclosureConfigSchema.default(
228
204
  CallsDisclosureConfigSchema.parse({}),
229
205
  ),
230
- safety: CallsSafetyConfigSchema.default(CallsSafetyConfigSchema.parse({})),
231
206
  voice: CallsVoiceConfigSchema.default(CallsVoiceConfigSchema.parse({})),
232
207
  callerIdentity: CallerIdentityConfigSchema.default(
233
208
  CallerIdentityConfigSchema.parse({}),
@@ -236,6 +211,4 @@ export const CallsConfigSchema = z
236
211
  CallsVerificationConfigSchema.parse({}),
237
212
  ),
238
213
  })
239
- .describe(
240
- "Phone call configuration — controls telephony, voice, safety, and call behavior",
241
- );
214
+ .describe("Phone call configuration: telephony, voice, and call behavior");
@@ -1,7 +1,5 @@
1
1
  import { z } from "zod";
2
2
 
3
- export const VALID_LIVE_VOICE_MODES = ["ptt", "open-mic"] as const;
4
-
5
3
  export const LiveVoiceVadConfigSchema = z
6
4
  .object({
7
5
  speechEnergyThreshold: z
@@ -79,149 +77,6 @@ export const LiveVoiceVadConfigSchema = z
79
77
  "Voice-activity-detection tuning for live voice sessions (open-mic turn segmentation)",
80
78
  );
81
79
 
82
- export const LiveVoiceProgressConfigSchema = z
83
- .object({
84
- enabled: z
85
- .boolean({
86
- error: "liveVoice.frontModel.progress.enabled must be a boolean",
87
- })
88
- .default(true)
89
- .describe(
90
- "Speak short progress updates during long-running tool-heavy turns; the opt-out for progress narration",
91
- ),
92
- opsThreshold: z
93
- .number({
94
- error: "liveVoice.frontModel.progress.opsThreshold must be a number",
95
- })
96
- .int("liveVoice.frontModel.progress.opsThreshold must be an integer")
97
- .positive(
98
- "liveVoice.frontModel.progress.opsThreshold must be a positive integer",
99
- )
100
- .default(3)
101
- .describe(
102
- "Narrate after this many tool operations since the last narration",
103
- ),
104
- idleIntervalMs: z
105
- .number({
106
- error: "liveVoice.frontModel.progress.idleIntervalMs must be a number",
107
- })
108
- .int("liveVoice.frontModel.progress.idleIntervalMs must be an integer")
109
- .positive(
110
- "liveVoice.frontModel.progress.idleIntervalMs must be a positive integer",
111
- )
112
- .default(5_000)
113
- .describe(
114
- "How often (ms) a running turn's silence is checked, and so the soonest new tool activity is narrated",
115
- ),
116
- maxSilenceMs: z
117
- .number({
118
- error: "liveVoice.frontModel.progress.maxSilenceMs must be a number",
119
- })
120
- .int("liveVoice.frontModel.progress.maxSilenceMs must be an integer")
121
- .positive(
122
- "liveVoice.frontModel.progress.maxSilenceMs must be a positive integer",
123
- )
124
- .default(35_000)
125
- .describe(
126
- "Heartbeat ceiling (ms): narrate after this much unbroken silence even when nothing new has happened. Evaluated on the idle tick, so its resolution is idleIntervalMs and it must be at least that long",
127
- ),
128
- longOpMs: z
129
- .number({
130
- error: "liveVoice.frontModel.progress.longOpMs must be a number",
131
- })
132
- .int("liveVoice.frontModel.progress.longOpMs must be an integer")
133
- .positive(
134
- "liveVoice.frontModel.progress.longOpMs must be a positive integer",
135
- )
136
- .default(15_000)
137
- .describe(
138
- "A tool operation that ran at least this long (ms) narrates the moment it completes, without waiting for opsThreshold",
139
- ),
140
- minGapMs: z
141
- .number({
142
- error: "liveVoice.frontModel.progress.minGapMs must be a number",
143
- })
144
- .int("liveVoice.frontModel.progress.minGapMs must be an integer")
145
- .positive(
146
- "liveVoice.frontModel.progress.minGapMs must be a positive integer",
147
- )
148
- .default(6_000)
149
- .describe(
150
- "Minimum spacing (ms) from any spoken floor-holder — ack or narration",
151
- ),
152
- generationTimeoutMs: z
153
- .number({
154
- error:
155
- "liveVoice.frontModel.progress.generationTimeoutMs must be a number",
156
- })
157
- .int(
158
- "liveVoice.frontModel.progress.generationTimeoutMs must be an integer",
159
- )
160
- .positive(
161
- "liveVoice.frontModel.progress.generationTimeoutMs must be a positive integer",
162
- )
163
- .default(1_500)
164
- .describe(
165
- "Budget (ms) for LLM-generated progress text — not latency-critical: it speaks into dead air",
166
- ),
167
- })
168
- // The heartbeat is checked when the idle tick finds the turn silent, so a
169
- // ceiling shorter than the tick interval would be missed by up to a full
170
- // interval — a promise the cadence cannot keep. Rejecting the combination
171
- // beats silently overshooting it.
172
- .refine((progress) => progress.maxSilenceMs >= progress.idleIntervalMs, {
173
- error:
174
- "liveVoice.frontModel.progress.maxSilenceMs must be at least idleIntervalMs — the heartbeat is evaluated on the idle tick",
175
- })
176
- .describe(
177
- "Progress-narration tuning for live voice sessions (spoken updates during long-running turns)",
178
- );
179
-
180
- export const LiveVoiceFrontModelConfigSchema = z
181
- .object({
182
- endpointDecisionTimeoutMs: z
183
- .number({
184
- error:
185
- "liveVoice.frontModel.endpointDecisionTimeoutMs must be a number",
186
- })
187
- .int("liveVoice.frontModel.endpointDecisionTimeoutMs must be an integer")
188
- .positive(
189
- "liveVoice.frontModel.endpointDecisionTimeoutMs must be a positive integer",
190
- )
191
- .default(1200)
192
- .describe(
193
- "Hard budget (ms) for the endpoint decision LLM call. This adds to end-of-turn latency when semantic endpointing is on, so keep it as tight as the decider model's real roundtrip allows — measured Haiku roundtrips through the managed proxy run ~670-1130ms (dev), so tighter budgets turn the feature into a fail-open no-op.",
194
- ),
195
- endpointExtensionMs: z
196
- .number({
197
- error: "liveVoice.frontModel.endpointExtensionMs must be a number",
198
- })
199
- .int("liveVoice.frontModel.endpointExtensionMs must be an integer")
200
- .positive(
201
- "liveVoice.frontModel.endpointExtensionMs must be a positive integer",
202
- )
203
- .default(1500)
204
- .describe(
205
- "How long (ms) a 'hold' decision keeps the turn open before turn-end replays",
206
- ),
207
- endpointMaxExtensions: z
208
- .number({
209
- error: "liveVoice.frontModel.endpointMaxExtensions must be a number",
210
- })
211
- .int("liveVoice.frontModel.endpointMaxExtensions must be an integer")
212
- .nonnegative(
213
- "liveVoice.frontModel.endpointMaxExtensions must be a nonnegative integer",
214
- )
215
- .default(2)
216
- .describe("Cap on consecutive 'hold' extensions per utterance"),
217
- progress: LiveVoiceProgressConfigSchema.default(
218
- LiveVoiceProgressConfigSchema.parse({}),
219
- ),
220
- })
221
- .describe(
222
- "Voice front-door endpointing and long-turn progress narration tuning",
223
- );
224
-
225
80
  const LiveVoiceFluxTurnEndConfigSchema = z
226
81
  .object({
227
82
  enabled: z
@@ -285,31 +140,10 @@ export const LiveVoiceFluxConfigSchema = z
285
140
 
286
141
  export const LiveVoiceConfigSchema = z
287
142
  .object({
288
- mode: z
289
- .enum(VALID_LIVE_VOICE_MODES, {
290
- error: `liveVoice.mode must be one of: ${VALID_LIVE_VOICE_MODES.join(", ")}`,
291
- })
292
- .default("open-mic")
293
- .describe(
294
- "Default microphone mode for live voice sessions — hands-free (open-mic) or push-to-talk (ptt)",
295
- ),
296
143
  vad: LiveVoiceVadConfigSchema.default(LiveVoiceVadConfigSchema.parse({})),
297
- frontModel: LiveVoiceFrontModelConfigSchema.default(
298
- LiveVoiceFrontModelConfigSchema.parse({}),
299
- ),
300
144
  flux: LiveVoiceFluxConfigSchema.default(
301
145
  LiveVoiceFluxConfigSchema.parse({}),
302
146
  ),
303
- maxSessionDurationSeconds: z
304
- .number({
305
- error: "liveVoice.maxSessionDurationSeconds must be a number",
306
- })
307
- .int("liveVoice.maxSessionDurationSeconds must be an integer")
308
- .positive(
309
- "liveVoice.maxSessionDurationSeconds must be a positive integer",
310
- )
311
- .default(1800)
312
- .describe("Maximum duration of a single live voice session in seconds"),
313
147
  archiveAudio: z
314
148
  .boolean({ error: "liveVoice.archiveAudio must be a boolean" })
315
149
  .default(false)
@@ -318,15 +152,9 @@ export const LiveVoiceConfigSchema = z
318
152
  ),
319
153
  })
320
154
  .describe(
321
- "Live voice (in-app duplex audio) configuration mic mode, VAD tuning, and session limits",
155
+ "Live voice (in-app duplex audio) configuration: VAD tuning, Flux turn detection, and audio archiving",
322
156
  );
323
157
 
324
158
  export type LiveVoiceConfig = z.infer<typeof LiveVoiceConfigSchema>;
325
159
  export type LiveVoiceVadConfig = z.infer<typeof LiveVoiceVadConfigSchema>;
326
- export type LiveVoiceFrontModelConfig = z.infer<
327
- typeof LiveVoiceFrontModelConfigSchema
328
- >;
329
- export type LiveVoiceProgressConfig = z.infer<
330
- typeof LiveVoiceProgressConfigSchema
331
- >;
332
160
  export type LiveVoiceFluxConfig = z.infer<typeof LiveVoiceFluxConfigSchema>;
@@ -102,7 +102,7 @@ export type McpServerConfig = z.infer<typeof McpServerConfigSchema>;
102
102
  export type McpConfig = z.infer<typeof McpConfigSchema>;
103
103
 
104
104
  /**
105
- * Who declared a server: the workspace `config.json`, which the user owns,
105
+ * Who declared a server: the workspace `mcp.json`, which the user owns,
106
106
  * or a plugin's `mcp.json`, which its author owns.
107
107
  *
108
108
  * Deliberately not a schema field. It is resolved from where the entry was
@@ -9,6 +9,16 @@ export const MemoryRetrospectiveConfigSchema = z
9
9
  "Whether the memory-retrospective background pass runs. When false, no retrospective is enqueued by any trigger (interval, message count, pre-compaction, scheduled sweep), the scheduled sweep job stops being queued, and any row already queued completes as a no-op. The rest of the memory system (extraction, retrieval, embeddings, `<memory>` injection) is unaffected. Use `memory.enabled` to disable memory as a whole.",
10
10
  ),
11
11
 
12
+ skillImprovement: z
13
+ .boolean({
14
+ error:
15
+ "memory.retrospective.skillImprovement must be a boolean",
16
+ })
17
+ .default(true)
18
+ .describe(
19
+ "Whether retrospectives may discover, refine, and create managed skills from observed procedures. When false, retrospectives still capture ordinary memories through `remember`, but cannot load skill management, search for similar skills, or scaffold managed skills.",
20
+ ),
21
+
12
22
  timeThresholdMs: z
13
23
  .number({
14
24
  error: "memory.retrospective.timeThresholdMs must be a number",
@@ -140,6 +140,11 @@ const MondayOAuthServiceSchema = BaseServiceSchema.extend({
140
140
  mode: ServiceModeSchema.default("your-own"),
141
141
  });
142
142
 
143
+ export const ShopifyOAuthServiceSchema = BaseServiceSchema.extend({
144
+ mode: ServiceModeSchema.default("your-own"),
145
+ });
146
+ export type ShopifyOAuthService = z.infer<typeof ShopifyOAuthServiceSchema>;
147
+
143
148
  export const StripeLinkOAuthServiceSchema = BaseServiceSchema.extend({
144
149
  mode: ServiceModeSchema.default("your-own"),
145
150
  });
@@ -152,6 +157,13 @@ export const FigmaOAuthServiceSchema = BaseServiceSchema.extend({
152
157
  });
153
158
  export type FigmaOAuthService = z.infer<typeof FigmaOAuthServiceSchema>;
154
159
 
160
+ export const QuickBooksOAuthServiceSchema = BaseServiceSchema.extend({
161
+ mode: ServiceModeSchema.default("your-own"),
162
+ });
163
+ export type QuickBooksOAuthService = z.infer<
164
+ typeof QuickBooksOAuthServiceSchema
165
+ >;
166
+
155
167
  export const EventbriteOAuthServiceSchema = BaseServiceSchema.extend({
156
168
  mode: ServiceModeSchema.default("your-own"),
157
169
  });
@@ -214,12 +226,18 @@ export const ServicesSchema = z.object({
214
226
  "monday-oauth": MondayOAuthServiceSchema.default(
215
227
  MondayOAuthServiceSchema.parse({}),
216
228
  ),
229
+ "shopify-oauth": ShopifyOAuthServiceSchema.default(
230
+ ShopifyOAuthServiceSchema.parse({}),
231
+ ),
217
232
  "stripe-link-oauth": StripeLinkOAuthServiceSchema.default(
218
233
  StripeLinkOAuthServiceSchema.parse({}),
219
234
  ),
220
235
  "figma-oauth": FigmaOAuthServiceSchema.default(
221
236
  FigmaOAuthServiceSchema.parse({}),
222
237
  ),
238
+ "quickbooks-oauth": QuickBooksOAuthServiceSchema.default(
239
+ QuickBooksOAuthServiceSchema.parse({}),
240
+ ),
223
241
  "eventbrite-oauth": EventbriteOAuthServiceSchema.default(
224
242
  EventbriteOAuthServiceSchema.parse({}),
225
243
  ),
@@ -32,20 +32,6 @@ const SkillsLoadConfigSchema = z
32
32
  )
33
33
  .default([])
34
34
  .describe("Additional directories to search for skill definitions"),
35
- watch: z
36
- .boolean({ error: "skills.load.watch must be a boolean" })
37
- .default(true)
38
- .describe(
39
- "Whether to watch skill directories for changes and auto-reload",
40
- ),
41
- watchDebounceMs: z
42
- .number({ error: "skills.load.watchDebounceMs must be a number" })
43
- .int()
44
- .positive()
45
- .default(250)
46
- .describe(
47
- "Debounce delay in milliseconds for skill file change detection",
48
- ),
49
35
  })
50
36
  .describe("Controls how skills are discovered and loaded");
51
37
 
@@ -0,0 +1,150 @@
1
+ import { z } from "zod";
2
+
3
+ export const VoiceProgressConfigSchema = z
4
+ .object({
5
+ enabled: z
6
+ .boolean({
7
+ error: "voice.frontModel.progress.enabled must be a boolean",
8
+ })
9
+ .default(true)
10
+ .describe(
11
+ "Speak short progress updates during long-running tool-heavy turns; the opt-out for progress narration",
12
+ ),
13
+ opsThreshold: z
14
+ .number({
15
+ error: "voice.frontModel.progress.opsThreshold must be a number",
16
+ })
17
+ .int("voice.frontModel.progress.opsThreshold must be an integer")
18
+ .positive(
19
+ "voice.frontModel.progress.opsThreshold must be a positive integer",
20
+ )
21
+ .default(3)
22
+ .describe(
23
+ "Narrate after this many tool operations since the last narration",
24
+ ),
25
+ idleIntervalMs: z
26
+ .number({
27
+ error: "voice.frontModel.progress.idleIntervalMs must be a number",
28
+ })
29
+ .int("voice.frontModel.progress.idleIntervalMs must be an integer")
30
+ .positive(
31
+ "voice.frontModel.progress.idleIntervalMs must be a positive integer",
32
+ )
33
+ .default(5_000)
34
+ .describe(
35
+ "How often (ms) a running turn's silence is checked, and so the soonest new tool activity is narrated",
36
+ ),
37
+ maxSilenceMs: z
38
+ .number({
39
+ error: "voice.frontModel.progress.maxSilenceMs must be a number",
40
+ })
41
+ .int("voice.frontModel.progress.maxSilenceMs must be an integer")
42
+ .positive(
43
+ "voice.frontModel.progress.maxSilenceMs must be a positive integer",
44
+ )
45
+ .default(35_000)
46
+ .describe(
47
+ "Heartbeat ceiling (ms): narrate after this much unbroken silence even when nothing new has happened. Evaluated on the idle tick, so its resolution is idleIntervalMs and it must be at least that long",
48
+ ),
49
+ longOpMs: z
50
+ .number({
51
+ error: "voice.frontModel.progress.longOpMs must be a number",
52
+ })
53
+ .int("voice.frontModel.progress.longOpMs must be an integer")
54
+ .positive("voice.frontModel.progress.longOpMs must be a positive integer")
55
+ .default(15_000)
56
+ .describe(
57
+ "A tool operation that ran at least this long (ms) narrates the moment it completes, without waiting for opsThreshold",
58
+ ),
59
+ minGapMs: z
60
+ .number({
61
+ error: "voice.frontModel.progress.minGapMs must be a number",
62
+ })
63
+ .int("voice.frontModel.progress.minGapMs must be an integer")
64
+ .positive("voice.frontModel.progress.minGapMs must be a positive integer")
65
+ .default(6_000)
66
+ .describe(
67
+ "Minimum spacing (ms) from any spoken floor-holder (ack or narration)",
68
+ ),
69
+ generationTimeoutMs: z
70
+ .number({
71
+ error: "voice.frontModel.progress.generationTimeoutMs must be a number",
72
+ })
73
+ .int("voice.frontModel.progress.generationTimeoutMs must be an integer")
74
+ .positive(
75
+ "voice.frontModel.progress.generationTimeoutMs must be a positive integer",
76
+ )
77
+ .default(1_500)
78
+ .describe(
79
+ "Budget (ms) for LLM-generated progress text. Not latency-critical: it speaks into dead air",
80
+ ),
81
+ })
82
+ // The heartbeat is checked when the idle tick finds the turn silent, so a
83
+ // ceiling shorter than the tick interval would be missed by up to a full
84
+ // interval, a promise the cadence cannot keep. Rejecting the combination
85
+ // beats silently overshooting it.
86
+ .refine((progress) => progress.maxSilenceMs >= progress.idleIntervalMs, {
87
+ error:
88
+ "voice.frontModel.progress.maxSilenceMs must be at least idleIntervalMs: the heartbeat is evaluated on the idle tick",
89
+ })
90
+ .describe(
91
+ "Progress-narration tuning for live voice sessions (spoken updates during long-running turns)",
92
+ );
93
+
94
+ export const VoiceFrontModelConfigSchema = z
95
+ .object({
96
+ endpointDecisionTimeoutMs: z
97
+ .number({
98
+ error: "voice.frontModel.endpointDecisionTimeoutMs must be a number",
99
+ })
100
+ .int("voice.frontModel.endpointDecisionTimeoutMs must be an integer")
101
+ .positive(
102
+ "voice.frontModel.endpointDecisionTimeoutMs must be a positive integer",
103
+ )
104
+ .default(1200)
105
+ .describe(
106
+ "Hard budget (ms) for the endpoint decision LLM call. This adds to end-of-turn latency when semantic endpointing is on, so keep it as tight as the decider model's real roundtrip allows. Measured Haiku roundtrips through the managed proxy run ~670-1130ms (dev), so tighter budgets turn the feature into a fail-open no-op.",
107
+ ),
108
+ endpointExtensionMs: z
109
+ .number({
110
+ error: "voice.frontModel.endpointExtensionMs must be a number",
111
+ })
112
+ .int("voice.frontModel.endpointExtensionMs must be an integer")
113
+ .positive(
114
+ "voice.frontModel.endpointExtensionMs must be a positive integer",
115
+ )
116
+ .default(1500)
117
+ .describe(
118
+ "How long (ms) a 'hold' decision keeps the turn open before turn-end replays",
119
+ ),
120
+ endpointMaxExtensions: z
121
+ .number({
122
+ error: "voice.frontModel.endpointMaxExtensions must be a number",
123
+ })
124
+ .int("voice.frontModel.endpointMaxExtensions must be an integer")
125
+ .nonnegative(
126
+ "voice.frontModel.endpointMaxExtensions must be a nonnegative integer",
127
+ )
128
+ .default(2)
129
+ .describe("Cap on consecutive 'hold' extensions per utterance"),
130
+ progress: VoiceProgressConfigSchema.default(
131
+ VoiceProgressConfigSchema.parse({}),
132
+ ),
133
+ })
134
+ .describe(
135
+ "Voice front-door endpointing and long-turn progress narration tuning, shared by live voice and phone calls",
136
+ );
137
+
138
+ export const VoiceConfigSchema = z
139
+ .object({
140
+ frontModel: VoiceFrontModelConfigSchema.default(
141
+ VoiceFrontModelConfigSchema.parse({}),
142
+ ),
143
+ })
144
+ .describe(
145
+ "Transport-agnostic voice configuration shared by live voice and phone calls: front-door routing and progress narration tuning",
146
+ );
147
+
148
+ export type VoiceConfig = z.infer<typeof VoiceConfigSchema>;
149
+ export type VoiceFrontModelConfig = z.infer<typeof VoiceFrontModelConfigSchema>;
150
+ export type VoiceProgressConfig = z.infer<typeof VoiceProgressConfigSchema>;
@@ -12,8 +12,15 @@ import {
12
12
  test,
13
13
  } from "bun:test";
14
14
 
15
+ import { waitFor } from "../__tests__/helpers/wait-for.js";
15
16
  import { createCesProcessManager } from "./process-manager.js";
16
17
 
18
+ const untilClosed = (predicate: () => boolean) =>
19
+ waitFor(predicate, {
20
+ timeoutMs: 2000,
21
+ message: "socket close never propagated to the transport",
22
+ });
23
+
17
24
  // ---------------------------------------------------------------------------
18
25
  // onTransportClose tests
19
26
  // ---------------------------------------------------------------------------
@@ -79,10 +86,7 @@ describe("CesProcessManager.onTransportClose", () => {
79
86
  sock.destroy();
80
87
  }
81
88
 
82
- // Give the close event a tick to propagate.
83
- await new Promise((resolve) => setTimeout(resolve, 50));
84
-
85
- expect(closeFired).toBe(true);
89
+ await untilClosed(() => closeFired);
86
90
  expect(transport.isAlive()).toBe(false);
87
91
 
88
92
  await pm.stop();
@@ -112,8 +116,7 @@ describe("CesProcessManager.onTransportClose", () => {
112
116
  for (const sock of connections) {
113
117
  sock.destroy();
114
118
  }
115
- await new Promise((resolve) => setTimeout(resolve, 50));
116
- expect(transport.isAlive()).toBe(false);
119
+ await untilClosed(() => !transport.isAlive());
117
120
 
118
121
  // Register handler AFTER transport is already dead.
119
122
  let closeFired = false;
@@ -190,14 +193,12 @@ describe("CesProcessManager transport-death logging", () => {
190
193
  for (const sock of connections) {
191
194
  sock.destroy();
192
195
  }
193
- await new Promise((resolve) => setTimeout(resolve, 50));
194
- expect(transport.isAlive()).toBe(false);
195
-
196
- expect(
196
+ await untilClosed(() =>
197
197
  calls.some(
198
198
  (c) => c.level === "warn" && c.msg.includes("died unexpectedly"),
199
199
  ),
200
- ).toBe(true);
200
+ );
201
+ expect(transport.isAlive()).toBe(false);
201
202
 
202
203
  await pm.stop();
203
204
  });
@@ -208,19 +209,17 @@ describe("CesProcessManager transport-death logging", () => {
208
209
  await pm.start();
209
210
 
210
211
  await pm.stop();
211
- // Let the socket close event propagate after destroy().
212
- await new Promise((resolve) => setTimeout(resolve, 50));
212
+ await untilClosed(() =>
213
+ calls.some(
214
+ (c) =>
215
+ c.level === "debug" && c.msg.includes("CES socket transport closed"),
216
+ ),
217
+ );
213
218
 
214
219
  expect(
215
220
  calls.some(
216
221
  (c) => c.level === "warn" && c.msg.includes("died unexpectedly"),
217
222
  ),
218
223
  ).toBe(false);
219
- expect(
220
- calls.some(
221
- (c) =>
222
- c.level === "debug" && c.msg.includes("CES socket transport closed"),
223
- ),
224
- ).toBe(true);
225
224
  });
226
225
  });
@@ -34,10 +34,7 @@ import {
34
34
  type OAuthConnectionRow,
35
35
  type OAuthProviderRow,
36
36
  } from "../oauth/oauth-store.js";
37
- import {
38
- expectedScopesForStoredToken,
39
- scopeDifference,
40
- } from "../oauth/scope-utils.js";
37
+ import { missingScopesForStoredToken } from "../oauth/scope-utils.js";
41
38
  import { credentialKey } from "../security/credential-key.js";
42
39
  import {
43
40
  getSecureKeyAsync,
@@ -294,26 +291,23 @@ async function checkConnection(
294
291
  // token rather than the provider's bot-side `scope` parameter. A provider
295
292
  // asking for user scopes as well stores the user token and records that
296
293
  // token's grant, so the bot request names scopes that grant can never hold.
297
- const grantedScopes = safeJsonParse<string[]>(grantedScopesRaw, []);
298
- const expectedScopes = expectedScopesForStoredToken(
294
+ const missing = missingScopesForStoredToken(
299
295
  safeJsonParse<string[]>(defaultScopesRaw, []),
300
296
  safeJsonParse<Record<string, string> | undefined>(
301
297
  authorizeParamsRaw,
302
298
  undefined,
303
299
  ),
304
300
  scopeSeparator ?? undefined,
301
+ safeJsonParse<string[]>(grantedScopesRaw, []),
305
302
  );
306
- if (expectedScopes.length > 0 && grantedScopes.length > 0) {
307
- const missing = scopeDifference(expectedScopes, grantedScopes);
308
- if (missing.length > 0) {
309
- return {
310
- ...base,
311
- status: "missing_scopes",
312
- details: `${provider} is missing required scopes: ${missing.join(", ")}. Features may not work correctly.`,
313
- missingScopes: missing,
314
- canAutoRecover: false,
315
- };
316
- }
303
+ if (missing.length > 0) {
304
+ return {
305
+ ...base,
306
+ status: "missing_scopes",
307
+ details: `${provider} is missing required scopes: ${missing.join(", ")}. Features may not work correctly.`,
308
+ missingScopes: missing,
309
+ canAutoRecover: false,
310
+ };
317
311
  }
318
312
 
319
313
  // 4. Liveness ping