@vellumai/assistant 0.12.1-staging.1 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (404) hide show
  1. package/AGENTS.md +0 -4
  2. package/ARCHITECTURE.md +12 -11
  3. package/docs/architecture/turn-actor.md +8 -15
  4. package/openapi.yaml +1 -291
  5. package/package.json +1 -1
  6. package/src/__tests__/always-loaded-tools-guard.test.ts +10 -18
  7. package/src/__tests__/app-compiler.test.ts +0 -6
  8. package/src/__tests__/app-control-tool-schemas.test.ts +2 -5
  9. package/src/__tests__/app-dir-path-guard.test.ts +3 -1
  10. package/src/__tests__/app-source-watcher.test.ts +218 -0
  11. package/src/{calls/__tests__ → __tests__}/call-controller.test.ts +82 -503
  12. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +2 -5
  13. package/src/__tests__/computer-use-tools.test.ts +5 -17
  14. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  15. package/src/__tests__/config-schema.test.ts +29 -28
  16. package/src/__tests__/config-watcher-skill-reseed.test.ts +359 -0
  17. package/src/__tests__/config-watcher.test.ts +8 -23
  18. package/src/__tests__/connection-model-compat.test.ts +2 -2
  19. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  20. package/src/__tests__/conversation-pairing.test.ts +0 -26
  21. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -4
  22. package/src/__tests__/conversation-queue.test.ts +207 -48
  23. package/src/__tests__/conversation-retry-discard.test.ts +1 -54
  24. package/src/__tests__/conversation-skill-tools.test.ts +0 -27
  25. package/src/__tests__/conversation-surfaces-app-control.test.ts +3 -8
  26. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -67
  27. package/src/__tests__/conversation-title-service.test.ts +10 -14
  28. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +5 -3
  29. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -51
  30. package/src/__tests__/credential-record-retire.test.ts +1 -171
  31. package/src/__tests__/credential-routes.test.ts +3 -212
  32. package/src/__tests__/credential-security-invariants.test.ts +1 -2
  33. package/src/__tests__/cu-unified-flow.test.ts +2 -8
  34. package/src/__tests__/drain-kick-guard.test.ts +2 -0
  35. package/src/__tests__/drain-requeue-on-contention.test.ts +6 -0
  36. package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
  37. package/src/__tests__/host-bash-proxy.test.ts +45 -26
  38. package/src/__tests__/host-browser-proxy.test.ts +17 -6
  39. package/src/__tests__/host-file-proxy-targeted.test.ts +0 -23
  40. package/src/__tests__/host-file-proxy.test.ts +23 -11
  41. package/src/__tests__/host-transfer-proxy-targeted.test.ts +9 -30
  42. package/src/__tests__/llm-catalog-parity.test.ts +0 -25
  43. package/src/__tests__/mcp-auth-routes.test.ts +9 -6
  44. package/src/__tests__/mcp-config-secret-boundary.test.ts +136 -78
  45. package/src/__tests__/mcp-health-check.test.ts +11 -8
  46. package/src/__tests__/mcp-list-plugin-servers.test.ts +10 -8
  47. package/src/{calls/__tests__ → __tests__}/media-stream-audio-transcode.test.ts +1 -1
  48. package/src/{calls/__tests__ → __tests__}/media-stream-output.test.ts +8 -37
  49. package/src/{calls/__tests__ → __tests__}/media-stream-parser.test.ts +1 -1
  50. package/src/{calls/__tests__ → __tests__}/media-stream-server-integration.test.ts +57 -150
  51. package/src/{calls/__tests__ → __tests__}/media-stream-stt-session.test.ts +5 -5
  52. package/src/{calls/__tests__ → __tests__}/media-turn-detector.test.ts +1 -1
  53. package/src/__tests__/messages-after-tiebreaker.test.ts +0 -91
  54. package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
  55. package/src/__tests__/messaging-send-tool.test.ts +548 -355
  56. package/src/__tests__/model-intents.test.ts +0 -3
  57. package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
  58. package/src/__tests__/platform-client-verify-credential.test.ts +0 -2
  59. package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -13
  60. package/src/__tests__/script-proxy-certs.test.ts +0 -35
  61. package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
  62. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  63. package/src/__tests__/speaker-identification.test.ts +56 -0
  64. package/src/__tests__/subagent-tool-gate-mode.test.ts +3 -19
  65. package/src/__tests__/subagent-tools.test.ts +2 -3
  66. package/src/__tests__/telephony-tts-guard.test.ts +3 -38
  67. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -4
  68. package/src/{calls/__tests__/voice-session-bridge-turn-flow.test.ts → __tests__/voice-session-bridge.test.ts} +12 -20
  69. package/src/__tests__/watch-retro-tool-availability.test.ts +17 -8
  70. package/src/__tests__/workspace-git-service.test.ts +0 -26
  71. package/src/acp/__tests__/agent-process.test.ts +4 -258
  72. package/src/acp/__tests__/auth-required.test.ts +0 -96
  73. package/src/acp/__tests__/client-handler.test.ts +2 -90
  74. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -5
  75. package/src/acp/__tests__/session-manager-resume.test.ts +6 -270
  76. package/src/acp/__tests__/session-manager-usage.test.ts +2 -4
  77. package/src/acp/__tests__/session-manager.test.ts +4 -895
  78. package/src/acp/agent-process.test.ts +1 -4
  79. package/src/acp/agent-process.ts +9 -94
  80. package/src/acp/auth-required.ts +1 -50
  81. package/src/acp/auto-install.test.ts +7 -9
  82. package/src/acp/client-handler.ts +3 -16
  83. package/src/acp/resolve-agent.test.ts +6 -220
  84. package/src/acp/resolve-agent.ts +23 -88
  85. package/src/acp/session-manager.test.ts +3 -196
  86. package/src/acp/session-manager.ts +18 -441
  87. package/src/acp/types.ts +5 -50
  88. package/src/api/events/app-files-changed.ts +3 -4
  89. package/src/api/index.ts +0 -6
  90. package/src/apps/app-store.ts +1 -1
  91. package/src/bundler/app-compiler.ts +0 -15
  92. package/src/calls/__tests__/voice-control-protocol.test.ts +25 -58
  93. package/src/calls/__tests__/voice-session-bridge.test.ts +1 -37
  94. package/src/calls/__tests__/voice-triage-escalate.test.ts +0 -105
  95. package/src/calls/call-constants.ts +4 -24
  96. package/src/calls/call-controller.ts +199 -499
  97. package/src/calls/call-transport.ts +0 -16
  98. package/src/calls/media-stream-output.ts +0 -32
  99. package/src/calls/media-stream-server.ts +30 -82
  100. package/src/calls/media-stream-stt-session.ts +0 -15
  101. package/src/calls/resolve-call-tts-provider.ts +2 -33
  102. package/src/calls/speaker-identification.ts +233 -0
  103. package/src/calls/tts-call-strategy.ts +5 -9
  104. package/src/calls/types.ts +0 -2
  105. package/src/calls/voice-control-protocol.ts +21 -53
  106. package/src/calls/voice-session-bridge.ts +46 -59
  107. package/src/calls/voice-triage-escalate.ts +56 -175
  108. package/src/cli/commands/apps.help.ts +13 -67
  109. package/src/cli/commands/apps.ts +0 -183
  110. package/src/cli/commands/channels/index.help.ts +2 -70
  111. package/src/cli/commands/channels/index.ts +3 -16
  112. package/src/cli/commands/credentials.help.ts +2 -6
  113. package/src/cli/commands/credentials.ts +2 -2
  114. package/src/cli/commands/mcp.help.ts +8 -8
  115. package/src/cli/commands/mcp.ts +1 -1
  116. package/src/cli/commands/roadmap.help.ts +1 -5
  117. package/src/cli/commands/roadmap.ts +1 -1
  118. package/src/cli/lib/bundled-marketplace.json +90 -103
  119. package/src/config/__tests__/default-profile-catalog.test.ts +0 -22
  120. package/src/config/__tests__/memory-retrospective-schema.test.ts +1 -15
  121. package/src/config/__tests__/platform-rehydration.test.ts +0 -93
  122. package/src/config/acp-defaults.test.ts +3 -13
  123. package/src/config/acp-defaults.ts +6 -23
  124. package/src/config/acp-schema.ts +2 -30
  125. package/src/config/bundled-skills/acp/SKILL.md +14 -22
  126. package/src/config/bundled-skills/acp/TOOLS.json +1 -5
  127. package/src/config/bundled-skills/app-builder/SKILL.md +9 -12
  128. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
  129. package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
  130. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +139 -67
  131. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
  132. package/src/config/bundled-skills/screen-annotation/SKILL.md +1 -8
  133. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +1 -4
  134. package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
  135. package/src/config/default-profile-catalog.ts +1 -1
  136. package/src/config/env.ts +2 -2
  137. package/src/config/feature-flag-registry.json +12 -8
  138. package/src/config/memory-v3-gate.test.ts +0 -31
  139. package/src/config/memory-v3-gate.ts +16 -20
  140. package/src/config/platform-rehydration.ts +21 -75
  141. package/src/config/schema.ts +2 -2
  142. package/src/config/schemas/__tests__/live-voice.test.ts +158 -8
  143. package/src/config/schemas/calls.ts +28 -1
  144. package/src/config/schemas/live-voice.ts +173 -1
  145. package/src/config/schemas/mcp.ts +1 -1
  146. package/src/config/schemas/memory-retrospective.ts +0 -10
  147. package/src/config/schemas/skills.ts +14 -0
  148. package/src/credential-execution/process-manager.test.ts +19 -18
  149. package/src/daemon/__tests__/conversation-tool-setup.test.ts +121 -66
  150. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +1 -4
  151. package/src/daemon/app-source-watcher.ts +218 -0
  152. package/src/daemon/config-watcher.ts +194 -13
  153. package/src/daemon/conversation-process.ts +64 -35
  154. package/src/daemon/conversation-skill-tools.ts +31 -13
  155. package/src/daemon/conversation-store.ts +1 -1
  156. package/src/daemon/conversation-surfaces.ts +8 -10
  157. package/src/daemon/conversation-tool-setup.ts +43 -37
  158. package/src/daemon/conversation.ts +3 -0
  159. package/src/daemon/host-bash-proxy.ts +12 -8
  160. package/src/daemon/host-browser-proxy.ts +1 -15
  161. package/src/daemon/host-file-proxy.ts +10 -8
  162. package/src/daemon/host-transfer-proxy.ts +18 -14
  163. package/src/daemon/lifecycle.ts +5 -0
  164. package/src/daemon/mcp-reload-service.ts +5 -5
  165. package/src/daemon/message-types/sync.ts +0 -1
  166. package/src/daemon/providers-setup.ts +1 -1
  167. package/src/daemon/shutdown-handlers.ts +9 -1
  168. package/src/daemon/skill-memory-refresh.ts +0 -64
  169. package/src/daemon/tool-side-effects.ts +18 -7
  170. package/src/hooks/types.ts +0 -33
  171. package/src/inbound/platform-callback-registration.ts +5 -4
  172. package/src/live-voice/__tests__/live-voice-metrics.test.ts +3 -0
  173. package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -15
  174. package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
  175. package/src/{calls → live-voice}/__tests__/progress-narration.test.ts +4 -4
  176. package/src/{calls → live-voice}/__tests__/progress-phrases.test.ts +1 -1
  177. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +69 -13
  178. package/src/live-voice/live-voice-session.ts +693 -213
  179. package/src/{calls → live-voice}/progress-narration.ts +2 -2
  180. package/src/live-voice/protocol.ts +2 -0
  181. package/src/mcp/__tests__/effective-config.test.ts +2 -2
  182. package/src/mcp/effective-config.ts +3 -3
  183. package/src/mcp/mcp-header-store.ts +45 -29
  184. package/src/mcp/startup.ts +4 -8
  185. package/src/messaging/provider.ts +3 -10
  186. package/src/messaging/providers/callback-routing.ts +0 -18
  187. package/src/messaging/providers/channel-transport.ts +0 -56
  188. package/src/messaging/providers/discord/transport.ts +0 -17
  189. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +17 -6
  190. package/src/messaging/providers/slack/adapter.ts +44 -7
  191. package/src/messaging/providers/slack/transport.ts +0 -16
  192. package/src/messaging/providers/telegram-bot/adapter.ts +48 -1
  193. package/src/messaging/providers/telegram-bot/client.ts +26 -0
  194. package/src/messaging/providers/telegram-bot/transport.ts +0 -20
  195. package/src/messaging/providers/whatsapp/adapter.ts +48 -1
  196. package/src/messaging/providers/whatsapp/client.ts +29 -0
  197. package/src/messaging/providers/whatsapp/transport.ts +0 -18
  198. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +0 -8
  199. package/src/notifications/__tests__/assistant-reply-producer.test.ts +0 -55
  200. package/src/notifications/__tests__/home-feed-side-effect.test.ts +3 -153
  201. package/src/notifications/assistant-reply-producer.ts +3 -8
  202. package/src/notifications/conversation-pairing.ts +16 -36
  203. package/src/notifications/delivered-post-record.ts +1 -11
  204. package/src/notifications/home-feed-side-effect.ts +7 -55
  205. package/src/outbound-proxy/certs.ts +5 -3
  206. package/src/permissions/checker.test.ts +6 -11
  207. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  208. package/src/persistence/conversation-crud.ts +63 -71
  209. package/src/persistence/conversation-lineage.ts +4 -12
  210. package/src/persistence/conversation-title-service.ts +26 -9
  211. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  212. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  213. package/src/persistence/message-reads.ts +0 -30
  214. package/src/persistence/migrations/157-invite-contact-id.ts +6 -18
  215. package/src/persistence/schema/memory-core.ts +0 -5
  216. package/src/platform/client.test.ts +0 -2
  217. package/src/platform/client.ts +10 -2
  218. package/src/plugin-api/constants.ts +0 -2
  219. package/src/plugin-api/index.ts +0 -1
  220. package/src/plugin-api/types.ts +0 -2
  221. package/src/plugins/defaults/index.ts +0 -2
  222. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +0 -46
  223. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +5 -9
  224. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +10 -20
  225. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +0 -219
  226. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +0 -31
  227. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -63
  228. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +0 -4
  229. package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -4
  230. package/src/plugins/defaults/memory/hooks/init.ts +0 -10
  231. package/src/plugins/defaults/memory/hooks/shutdown.ts +0 -2
  232. package/src/plugins/defaults/memory/jobs-worker.ts +0 -13
  233. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +60 -34
  234. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +5 -3
  235. package/src/plugins/defaults/memory/memory-retrospective-job.ts +3 -12
  236. package/src/plugins/defaults/memory/memory-retrospective-state.ts +71 -312
  237. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +1 -2
  238. package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +3 -5
  239. package/src/plugins/defaults/memory/startup.ts +1 -6
  240. package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +9 -7
  241. package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
  242. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +0 -89
  243. package/src/plugins/defaults/memory/worker.ts +0 -6
  244. package/src/plugins/mcp-servers.ts +75 -15
  245. package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
  246. package/src/providers/gemini/client.ts +23 -9
  247. package/src/providers/model-catalog.ts +0 -34
  248. package/src/providers/model-intents.ts +5 -10
  249. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +18 -146
  250. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +1 -83
  251. package/src/providers/openai/chat-completions-provider.ts +78 -192
  252. package/src/providers/openai/codex-models.ts +4 -0
  253. package/src/runtime/AGENTS.md +0 -2
  254. package/src/runtime/auth/same-actor.ts +3 -38
  255. package/src/runtime/http-server.ts +151 -160
  256. package/src/runtime/routes/__tests__/acp-routes.test.ts +4 -159
  257. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -108
  258. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +12 -16
  259. package/src/runtime/routes/acp-routes.test.ts +0 -15
  260. package/src/runtime/routes/acp-routes.ts +9 -72
  261. package/src/runtime/routes/app-management-routes.ts +0 -73
  262. package/src/runtime/routes/app-routes.ts +1 -1
  263. package/src/runtime/routes/conversation-list-routes.ts +3 -14
  264. package/src/runtime/routes/conversation-query-routes.ts +0 -40
  265. package/src/runtime/routes/credential-routes.ts +10 -19
  266. package/src/runtime/routes/diagnostics-routes.ts +3 -55
  267. package/src/runtime/routes/index.ts +0 -4
  268. package/src/runtime/routes/log-export-routes.ts +0 -2
  269. package/src/runtime/routes/mcp-auth-routes.ts +47 -39
  270. package/src/runtime/routes/migration-routes.ts +21 -8
  271. package/src/runtime/routes/platform-routes.ts +15 -18
  272. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -28
  273. package/src/runtime/services/conversation-serializer.ts +3 -16
  274. package/src/runtime/sync/resource-sync-events.ts +1 -2
  275. package/src/schedule/worker.ts +1 -1
  276. package/src/security/ces-rpc-record-backend.ts +0 -7
  277. package/src/subagent/consult-context.ts +25 -12
  278. package/src/tools/acp/list-agents.test.ts +1 -3
  279. package/src/tools/acp/spawn.test.ts +11 -146
  280. package/src/tools/acp/spawn.ts +3 -21
  281. package/src/tools/acp/status.ts +3 -40
  282. package/src/tools/app-control/skill-proxy-bridge.ts +1 -2
  283. package/src/tools/capability-offer.test.ts +2 -22
  284. package/src/tools/capability-offer.ts +1 -16
  285. package/src/tools/computer-use/definitions.ts +2 -4
  286. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -2
  287. package/src/tools/credentials/metadata-store.ts +0 -100
  288. package/src/tools/host-filesystem/edit.test.ts +1 -2
  289. package/src/tools/host-filesystem/edit.ts +2 -2
  290. package/src/tools/host-filesystem/read.test.ts +1 -2
  291. package/src/tools/host-filesystem/read.ts +2 -2
  292. package/src/tools/host-filesystem/transfer.test.ts +1 -2
  293. package/src/tools/host-filesystem/transfer.ts +2 -2
  294. package/src/tools/host-filesystem/write.test.ts +1 -2
  295. package/src/tools/host-filesystem/write.ts +2 -2
  296. package/src/tools/host-terminal/host-shell.test.ts +0 -16
  297. package/src/tools/host-terminal/host-shell.ts +20 -4
  298. package/src/tools/policy-context.ts +7 -6
  299. package/src/tools/subagent/spawn.ts +8 -5
  300. package/src/tools/watch/watch-retro-report.ts +8 -0
  301. package/src/util/__tests__/language-subtag.test.ts +1 -23
  302. package/src/util/fs-watcher-error.ts +36 -0
  303. package/src/util/language-subtag.ts +0 -16
  304. package/src/util/platform.ts +0 -8
  305. package/src/workspace/git-service.ts +54 -5
  306. package/src/workspace/migrations/registry.ts +0 -6
  307. package/scripts/smoke-desktop-window-theme.ts +0 -186
  308. package/src/__tests__/git-porcelain.test.ts +0 -47
  309. package/src/__tests__/helpers/set-workspace-mcp.ts +0 -11
  310. package/src/__tests__/message-deleted-hook-dispatch.test.ts +0 -119
  311. package/src/__tests__/resolve-app.test.ts +0 -135
  312. package/src/__tests__/source-fingerprint.test.ts +0 -184
  313. package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +0 -336
  314. package/src/acp/__tests__/helpers/acp-model-option.ts +0 -51
  315. package/src/acp/model-config.test.ts +0 -166
  316. package/src/acp/model-config.ts +0 -138
  317. package/src/api/events/acp-session-model-update.test.ts +0 -88
  318. package/src/api/events/acp-session-model-update.ts +0 -46
  319. package/src/apps/resolve-app.ts +0 -81
  320. package/src/apps/source-fingerprint.ts +0 -266
  321. package/src/calls/__tests__/barge-in-guard.test.ts +0 -81
  322. package/src/calls/__tests__/voice-leg-coordinator.test.ts +0 -229
  323. package/src/calls/__tests__/voice-progress-cadence.test.ts +0 -274
  324. package/src/calls/barge-in-guard.ts +0 -118
  325. package/src/calls/voice-leg-coordinator.ts +0 -189
  326. package/src/calls/voice-progress-cadence.ts +0 -423
  327. package/src/cli/commands/__tests__/apps.test.ts +0 -245
  328. package/src/cli/commands/__tests__/roadmap.help.test.ts +0 -19
  329. package/src/cli/commands/channels/__tests__/send.test.ts +0 -218
  330. package/src/cli/commands/channels/send.ts +0 -128
  331. package/src/config/__tests__/platform-identity.test.ts +0 -117
  332. package/src/config/acp-agent-write.ts +0 -43
  333. package/src/config/acp-schema.test.ts +0 -81
  334. package/src/config/platform-identity.ts +0 -144
  335. package/src/config/schemas/__tests__/voice.test.ts +0 -148
  336. package/src/config/schemas/voice.ts +0 -150
  337. package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +0 -133
  338. package/src/daemon/app-change-notify.ts +0 -45
  339. package/src/desktop/__tests__/fake-desktop.ts +0 -119
  340. package/src/desktop/desktop-chrome-policy.test.ts +0 -71
  341. package/src/desktop/desktop-chrome-policy.ts +0 -42
  342. package/src/desktop/desktop-dependencies.test.ts +0 -102
  343. package/src/desktop/desktop-dependencies.ts +0 -306
  344. package/src/desktop/desktop-feature.test.ts +0 -18
  345. package/src/desktop/desktop-feature.ts +0 -19
  346. package/src/desktop/desktop-panel-config.test.ts +0 -135
  347. package/src/desktop/desktop-panel-config.ts +0 -149
  348. package/src/desktop/desktop-session-manager.test.ts +0 -627
  349. package/src/desktop/desktop-session-manager.ts +0 -814
  350. package/src/desktop/desktop-stream-bridge.test.ts +0 -395
  351. package/src/desktop/desktop-stream-bridge.ts +0 -214
  352. package/src/desktop/desktop-wallpaper.test.ts +0 -191
  353. package/src/desktop/desktop-wallpaper.ts +0 -113
  354. package/src/desktop/desktop-window-theme.ts +0 -170
  355. package/src/i18n/AGENTS.md +0 -22
  356. package/src/i18n/__tests__/i18n.test.ts +0 -108
  357. package/src/i18n/index.ts +0 -16
  358. package/src/i18n/locales.ts +0 -93
  359. package/src/i18n/messages.ts +0 -61
  360. package/src/i18n/title.ts +0 -25
  361. package/src/mcp/__tests__/workspace-mcp-config.test.ts +0 -135
  362. package/src/mcp/spec-schema.ts +0 -111
  363. package/src/mcp/workspace-mcp-config.ts +0 -188
  364. package/src/messaging/providers/__tests__/proactive-address.test.ts +0 -95
  365. package/src/persistence/conversation-title-placeholders.ts +0 -23
  366. package/src/persistence/message-cursor.ts +0 -78
  367. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +0 -149
  368. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +0 -118
  369. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +0 -83
  370. package/src/plugins/defaults/memory/hooks/message-deleted.ts +0 -21
  371. package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +0 -126
  372. package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +0 -79
  373. package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +0 -28
  374. package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +0 -9
  375. package/src/providers/gemini-thought-signature.test.ts +0 -63
  376. package/src/providers/gemini-thought-signature.ts +0 -44
  377. package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +0 -613
  378. package/src/providers/openai/__tests__/google-thought-signature.test.ts +0 -235
  379. package/src/providers/openai/google-thought-signature.ts +0 -320
  380. package/src/runtime/__tests__/channel-send.test.ts +0 -443
  381. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +0 -89
  382. package/src/runtime/__tests__/live-voice-upgrade.test.ts +0 -58
  383. package/src/runtime/__tests__/runtime-ws-test-utils.ts +0 -72
  384. package/src/runtime/__tests__/watch-stream-upgrade.test.ts +0 -59
  385. package/src/runtime/channel-send.ts +0 -316
  386. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +0 -205
  387. package/src/runtime/routes/__tests__/channel-send-routes.test.ts +0 -127
  388. package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +0 -107
  389. package/src/runtime/routes/channel-send-routes.ts +0 -85
  390. package/src/runtime/routes/desktop-setup-routes.test.ts +0 -74
  391. package/src/runtime/routes/desktop-setup-routes.ts +0 -35
  392. package/src/security/__tests__/ces-http-record-backend.test.ts +0 -137
  393. package/src/security/ces-http-record-backend.ts +0 -120
  394. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +0 -60
  395. package/src/skills/workspace-skill-md-signature.ts +0 -50
  396. package/src/tools/acp/status.test.ts +0 -94
  397. package/src/util/ca-bundle.ts +0 -13
  398. package/src/workspace/git-porcelain.ts +0 -66
  399. package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +0 -258
  400. package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +0 -78
  401. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +0 -214
  402. package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +0 -102
  403. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +0 -199
  404. /package/src/{calls → live-voice}/progress-phrases.ts +0 -0
@@ -1,9 +1,9 @@
1
1
  import { getConfig } from "../config/loader.js";
2
2
  import { assistantEventHub } from "../runtime/assistant-event-hub.js";
3
3
  import {
4
+ ambiguousSameUserError,
4
5
  enforceSameActorOrErrorResult,
5
- pickMostRecentSameUserClient,
6
- unavailableSameUserClientError,
6
+ pickSameUserAutoResolve,
7
7
  } from "../runtime/auth/same-actor.js";
8
8
  import * as pendingInteractions from "../runtime/pending-interactions.js";
9
9
  import { formatShellOutput } from "../tools/shared/shell-output.js";
@@ -93,17 +93,21 @@ export class HostBashProxy extends HostProxyBase<
93
93
  }
94
94
  resolvedTargetClientId = input.targetClientId;
95
95
  } else {
96
- resolvedTargetClientId = pickMostRecentSameUserClient({
96
+ // Auto-resolve to the unique same-user client. Reject (rather than
97
+ // broadcast) when multiple same-user clients are connected so that
98
+ // a single targeted-style request cannot fan out across every one
99
+ // of the user's machines. Zero same-user matches falls through to
100
+ // the existing untargeted code path.
101
+ const resolved = pickSameUserAutoResolve({
97
102
  hub: assistantEventHub,
98
103
  capability: "host_bash",
99
104
  sourceActorPrincipalId,
100
105
  });
101
- if (
102
- resolvedTargetClientId === undefined &&
103
- sourceActorPrincipalId !== undefined
104
- ) {
105
- return unavailableSameUserClientError("host_bash");
106
+ if (resolved.kind === "ambiguous") {
107
+ return ambiguousSameUserError("host_bash");
106
108
  }
109
+ resolvedTargetClientId =
110
+ resolved.kind === "match" ? resolved.clientId : undefined;
107
111
  }
108
112
 
109
113
  // Targeted requests must be bound to the same authenticated user as the
@@ -5,10 +5,7 @@ import {
5
5
  assistantEventHub,
6
6
  broadcastMessage,
7
7
  } from "../runtime/assistant-event-hub.js";
8
- import {
9
- enforceSameActorOrErrorResult,
10
- unavailableSameUserClientError,
11
- } from "../runtime/auth/same-actor.js";
8
+ import { enforceSameActorOrErrorResult } from "../runtime/auth/same-actor.js";
12
9
  import * as pendingInteractions from "../runtime/pending-interactions.js";
13
10
  import type { ToolExecutionResult } from "../tools/types.js";
14
11
  import { AssistantError, ErrorCode } from "../util/errors.js";
@@ -287,17 +284,6 @@ export class HostBrowserProxy {
287
284
  targetClientId,
288
285
  );
289
286
 
290
- if (
291
- preferredClient === undefined &&
292
- sourceActorPrincipalId !== undefined &&
293
- targetClientId === undefined
294
- ) {
295
- if (isExtensionOnlyMethod(input.cdpMethod)) {
296
- return Promise.resolve(extensionRequiredResult(input.cdpMethod));
297
- }
298
- return Promise.resolve(unavailableSameUserClientError("host_browser"));
299
- }
300
-
301
287
  // Same-user enforcement: when the caller's actor is known, refuse to
302
288
  // dispatch to a client owned by a different actor. This covers the
303
289
  // cross-client exposure case where a web/iOS turn for actor A would
@@ -6,10 +6,10 @@ import {
6
6
  broadcastMessage,
7
7
  } from "../runtime/assistant-event-hub.js";
8
8
  import {
9
+ ambiguousSameUserError,
9
10
  enforceSameActorOrErrorResult,
10
- pickMostRecentSameUserClient,
11
+ pickSameUserAutoResolve,
11
12
  snapshotHostProxyActorPrincipalId,
12
- unavailableSameUserClientError,
13
13
  } from "../runtime/auth/same-actor.js";
14
14
  import * as pendingInteractions from "../runtime/pending-interactions.js";
15
15
  import { readAudioBase64 } from "../tools/shared/filesystem/audio-read.js";
@@ -102,17 +102,19 @@ export class HostFileProxy {
102
102
  });
103
103
  }
104
104
  } else {
105
- resolvedTargetClientId = pickMostRecentSameUserClient({
105
+ // Auto-resolve to the unique same-user client. Reject ambiguous
106
+ // (multi-machine) cases so a single targeted-style request cannot
107
+ // fan out across the user's machines.
108
+ const resolved = pickSameUserAutoResolve({
106
109
  hub: assistantEventHub,
107
110
  capability: "host_file",
108
111
  sourceActorPrincipalId,
109
112
  });
110
- if (
111
- resolvedTargetClientId === undefined &&
112
- sourceActorPrincipalId !== undefined
113
- ) {
114
- return Promise.resolve(unavailableSameUserClientError("host_file"));
113
+ if (resolved.kind === "ambiguous") {
114
+ return Promise.resolve(ambiguousSameUserError("host_file"));
115
115
  }
116
+ resolvedTargetClientId =
117
+ resolved.kind === "match" ? resolved.clientId : undefined;
116
118
  }
117
119
 
118
120
  // Same-user check: targeted host_file requests must be bound to the same
@@ -10,10 +10,10 @@ import {
10
10
  broadcastMessage,
11
11
  } from "../runtime/assistant-event-hub.js";
12
12
  import {
13
+ ambiguousSameUserError,
13
14
  enforceSameActorOrErrorResult,
14
- pickMostRecentSameUserClient,
15
+ pickSameUserAutoResolve,
15
16
  snapshotHostProxyActorPrincipalId,
16
- unavailableSameUserClientError,
17
17
  } from "../runtime/auth/same-actor.js";
18
18
  import * as pendingInteractions from "../runtime/pending-interactions.js";
19
19
  import type { ToolExecutionResult } from "../tools/types.js";
@@ -162,17 +162,19 @@ export class HostTransferProxy {
162
162
  });
163
163
  }
164
164
  } else {
165
- resolvedTargetClientId = pickMostRecentSameUserClient({
165
+ // Auto-resolve to the unique same-user client; reject ambiguous
166
+ // (multi-machine) cases so a single targeted-style transfer cannot
167
+ // fan out across the user's machines.
168
+ const resolved = pickSameUserAutoResolve({
166
169
  hub: assistantEventHub,
167
170
  capability: "host_file",
168
171
  sourceActorPrincipalId,
169
172
  });
170
- if (
171
- resolvedTargetClientId === undefined &&
172
- sourceActorPrincipalId !== undefined
173
- ) {
174
- return Promise.resolve(unavailableSameUserClientError("host_file"));
173
+ if (resolved.kind === "ambiguous") {
174
+ return Promise.resolve(ambiguousSameUserError("host_file"));
175
175
  }
176
+ resolvedTargetClientId =
177
+ resolved.kind === "match" ? resolved.clientId : undefined;
176
178
  }
177
179
 
178
180
  if (resolvedTargetClientId != null) {
@@ -362,17 +364,19 @@ export class HostTransferProxy {
362
364
  });
363
365
  }
364
366
  } else {
365
- resolvedTargetClientId = pickMostRecentSameUserClient({
367
+ // Auto-resolve to the unique same-user client; reject ambiguous
368
+ // (multi-machine) cases so a single targeted-style transfer cannot
369
+ // fan out across the user's machines.
370
+ const resolved = pickSameUserAutoResolve({
366
371
  hub: assistantEventHub,
367
372
  capability: "host_file",
368
373
  sourceActorPrincipalId,
369
374
  });
370
- if (
371
- resolvedTargetClientId === undefined &&
372
- sourceActorPrincipalId !== undefined
373
- ) {
374
- return Promise.resolve(unavailableSameUserClientError("host_file"));
375
+ if (resolved.kind === "ambiguous") {
376
+ return Promise.resolve(ambiguousSameUserError("host_file"));
375
377
  }
378
+ resolvedTargetClientId =
379
+ resolved.kind === "match" ? resolved.clientId : undefined;
376
380
  }
377
381
 
378
382
  if (resolvedTargetClientId != null) {
@@ -71,6 +71,7 @@ import { ensureCompleteCustomProfiles } from "../workspace/custom-profile-ensure
71
71
  import { ensureDefaultProvider } from "../workspace/default-provider-ensure.js";
72
72
  import { WORKSPACE_MIGRATIONS } from "../workspace/migrations/registry.js";
73
73
  import { runWorkspaceMigrations } from "../workspace/migrations/runner.js";
74
+ import { startAppSourceWatcher } from "./app-source-watcher.js";
74
75
  import { startConfigWatcher } from "./config-watcher.js";
75
76
  import { startConversationEvictor } from "./conversation-evictor.js";
76
77
  import { writePid } from "./daemon-control.js";
@@ -705,6 +706,10 @@ export async function runDaemon(): Promise<void> {
705
706
  // config, and broadcast the relevant resource-changed events to clients.
706
707
  startConfigWatcher();
707
708
 
709
+ // Watch app source directories so edits recompile + refresh surfaces across
710
+ // all conversations.
711
+ startAppSourceWatcher();
712
+
708
713
  // Start the CLI IPC server. Throws on EADDRINUSE to abort startup when another
709
714
  // daemon already holds the socket, so this process never runs background jobs
710
715
  // against the shared database as an unmanageable duplicate.
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Shared MCP reload business logic.
3
3
  *
4
- * Called by the ConfigWatcher when mcp.json changes or a reload signal
4
+ * Called by the ConfigWatcher when config.json changes or a reload signal
5
5
  * file is detected, so the daemon automatically reconnects MCP servers.
6
6
  */
7
7
 
8
- import { invalidateConfigCache } from "../config/loader.js";
8
+ import { getConfig, invalidateConfigCache } from "../config/loader.js";
9
9
  import {
10
10
  buildEffectiveMcpConfig,
11
11
  pluginMcpServersChangedSinceLastBuild,
@@ -13,7 +13,6 @@ import {
13
13
  import { getMcpServerManager } from "../mcp/manager.js";
14
14
  import { migrateLegacyMcpHeaders } from "../mcp/mcp-header-store.js";
15
15
  import { signalMcpReloaded } from "../mcp/reload-signal.js";
16
- import { loadWorkspaceMcpConfig } from "../mcp/workspace-mcp-config.js";
17
16
  import { createMcpToolsFromServer } from "../tools/mcp/mcp-tool-factory.js";
18
17
  import { registerMcpTools, unregisterAllMcpTools } from "../tools/registry.js";
19
18
  import { getLogger } from "../util/logger.js";
@@ -96,15 +95,16 @@ async function doReload(): Promise<McpReloadResult> {
96
95
  // If the config is broken we abort early, preserving the current
97
96
  // working MCP setup instead of leaving zero servers.
98
97
  invalidateConfigCache();
98
+ const config = getConfig();
99
99
 
100
100
  // 2. Stop existing MCP servers + unregister their tools
101
101
  await manager.stop();
102
102
  unregisterAllMcpTools();
103
103
 
104
104
  // Plugins are re-read here too: installing or removing one changes the
105
- // server set exactly like editing mcp.json does, and both arrive
105
+ // server set exactly like editing config.json does, and both arrive
106
106
  // through this same reload.
107
- const mcpConfig = buildEffectiveMcpConfig(loadWorkspaceMcpConfig());
107
+ const mcpConfig = buildEffectiveMcpConfig(config.mcp);
108
108
  const serverIds = Object.keys(mcpConfig.servers);
109
109
 
110
110
  // 3. Restart MCP servers
@@ -13,7 +13,6 @@ export const SYNC_TAGS = {
13
13
  assistantConfig: "assistant:self:config",
14
14
  assistantSounds: "assistant:self:sounds",
15
15
  assistantSchedules: "assistant:self:schedules",
16
- assistantDesktop: "assistant:self:desktop",
17
16
  assistantTheme: "assistant:self:theme",
18
17
  appsList: "apps:list",
19
18
  documentsList: "documents:list",
@@ -63,7 +63,7 @@ export async function initializeProvidersAndTools(
63
63
  // Start MCP servers — workspace-configured and plugin-declared alike —
64
64
  // and register their tools. Shared with the schedule worker, which hosts
65
65
  // agent turns in its own process and so needs its own connections.
66
- await startConfiguredMcpServers();
66
+ await startConfiguredMcpServers(config.mcp);
67
67
 
68
68
  log.info("Daemon startup: providers and tools initialized");
69
69
  }
@@ -24,7 +24,11 @@ import { browserManager } from "../tools/browser/browser-manager.js";
24
24
  import { getLogger } from "../util/logger.js";
25
25
  import { APP_VERSION } from "../version.js";
26
26
  import { getEnrichmentService } from "../workspace/commit-message-enrichment-service.js";
27
- import { commitAllPendingWorkspaceChanges } from "../workspace/heartbeat-service.js";
27
+ import {
28
+ commitAllPendingWorkspaceChanges,
29
+ stopWorkspaceHeartbeatService,
30
+ } from "../workspace/heartbeat-service.js";
31
+ import { stopAppSourceWatcher } from "./app-source-watcher.js";
28
32
  import { stopConfigWatcher } from "./config-watcher.js";
29
33
  import { stopConversationEvictor } from "./conversation-evictor.js";
30
34
  import { stopConversations } from "./conversation-store.js";
@@ -94,6 +98,9 @@ async function shutdown(): Promise<void> {
94
98
  }, 30_000);
95
99
  forceTimer.unref();
96
100
 
101
+ // Workspace git heartbeat timer lives in the monitor process. This
102
+ // in-process stop is a no-op unless the singleton was started here.
103
+ await stopWorkspaceHeartbeatService();
97
104
  await stopHeartbeatService();
98
105
 
99
106
  // Stop the periodic consent-cache refresh (a daemon-owned interval).
@@ -127,6 +134,7 @@ async function shutdown(): Promise<void> {
127
134
  disposeAcpSessionManager();
128
135
  stopConversationEvictor();
129
136
  stopConfigWatcher();
137
+ stopAppSourceWatcher();
130
138
  stopCliIpcServer();
131
139
  stopConversations();
132
140
  await stopCes();
@@ -8,24 +8,16 @@ import {
8
8
  maybeSeedCapabilitySkills,
9
9
  maybeSeedCliCommandCards,
10
10
  } from "../plugins/defaults/memory/substrate/boot-maintenance.js";
11
- import { readWorkspaceSkillMdSignature } from "../skills/workspace-skill-md-signature.js";
12
11
  import { getLogger } from "../util/logger.js";
13
12
 
14
13
  const log = getLogger("skill-memory-refresh");
15
14
 
16
- /** Poll interval for workspace `SKILL.md` mtimes. Stats only, no tree walk. */
17
- export const SKILL_MD_MTIME_POLL_MS = 1_500;
18
-
19
- let lastSignature: string | undefined;
20
- let pollTimer: ReturnType<typeof setInterval> | undefined;
21
-
22
15
  export function refreshSkillCapabilityMemories(
23
16
  config: AssistantConfig = getConfig(),
24
17
  ): void {
25
18
  seedSkillGraphNodes();
26
19
  maybeSeedCapabilitySkills(config);
27
20
  maybeSeedCliCommandCards(config);
28
- lastSignature = readWorkspaceSkillMdSignature();
29
21
  void seedUninstalledCatalogSkillMemories()
30
22
  .then(() => {
31
23
  // Re-run after the async catalog fetch populates the cache so stale
@@ -39,59 +31,3 @@ export function refreshSkillCapabilityMemories(
39
31
  ),
40
32
  );
41
33
  }
42
-
43
- /**
44
- * Reseed skill capability memories when the workspace `SKILL.md` set or
45
- * mtimes have changed since the last refresh in this process. No-op when the
46
- * signature is unchanged. First call in a process always reseeds so the
47
- * memory worker, whose in-process skill cache starts empty, picks up the
48
- * catalog without waiting for an install path.
49
- */
50
- export function maybeRefreshSkillCapabilityMemoriesFromMtime(): boolean {
51
- const signature = readWorkspaceSkillMdSignature();
52
- if (lastSignature !== undefined && signature === lastSignature) {
53
- return false;
54
- }
55
- if (lastSignature !== undefined) {
56
- log.info("Workspace SKILL.md set changed, reseeding capability memories");
57
- }
58
- refreshSkillCapabilityMemories();
59
- return true;
60
- }
61
-
62
- function pollOnce(): void {
63
- try {
64
- maybeRefreshSkillCapabilityMemoriesFromMtime();
65
- } catch (err) {
66
- log.warn({ err }, "SKILL.md mtime poll failed");
67
- }
68
- }
69
-
70
- /**
71
- * Start a per-process poll of workspace `SKILL.md` mtimes. Idempotent.
72
- * The memory worker and the assistant each run this against their own
73
- * in-process skill caches. Runs once immediately so a worker that has never
74
- * seeded picks up the catalog without waiting a tick.
75
- */
76
- export function startWorkspaceSkillMdMtimePoll(): void {
77
- if (pollTimer !== undefined) {
78
- return;
79
- }
80
- pollOnce();
81
- pollTimer = setInterval(pollOnce, SKILL_MD_MTIME_POLL_MS);
82
- pollTimer.unref?.();
83
- }
84
-
85
- export function stopWorkspaceSkillMdMtimePoll(): void {
86
- if (pollTimer === undefined) {
87
- return;
88
- }
89
- clearInterval(pollTimer);
90
- pollTimer = undefined;
91
- }
92
-
93
- /** @internal Test-only: clear the in-process signature and poll timer. */
94
- export function _resetSkillMdMtimeStateForTests(): void {
95
- lastSignature = undefined;
96
- stopWorkspaceSkillMdMtimePoll();
97
- }
@@ -18,15 +18,17 @@ import { invalidateEdgeIndex } from "../plugins/defaults/memory/substrate/edge-i
18
18
  import { invalidatePageIndex } from "../plugins/defaults/memory/substrate/page-index.js";
19
19
  import { getConceptsDir } from "../plugins/defaults/memory/substrate/page-store.js";
20
20
  import { broadcastMessage } from "../runtime/assistant-event-hub.js";
21
- import { publishDocumentsChanged } from "../runtime/sync/resource-sync-events.js";
21
+ import {
22
+ publishAppsChanged,
23
+ publishDocumentsChanged,
24
+ } from "../runtime/sync/resource-sync-events.js";
25
+ import { updatePublishedAppDeployment } from "../services/published-app-updater.js";
22
26
  import type { ToolExecutionResult } from "../tools/types.js";
23
27
  import { getLogger } from "../util/logger.js";
24
28
  import { getWorkspaceDir } from "../util/platform.js";
25
- import {
26
- broadcastAppFilesChanged,
27
- notifyAppSurfacesChanged,
28
- } from "./app-change-notify.js";
29
+ import { ensureAppSourceWatcher } from "./app-source-watcher.js";
29
30
  import type { Conversation } from "./conversation.js";
31
+ import { refreshSurfacesForApp } from "./conversation-surfaces.js";
30
32
  import { isDoordashCommand, updateDoordashProgress } from "./doordash-steps.js";
31
33
 
32
34
  const log = getLogger("tool-side-effects");
@@ -52,7 +54,7 @@ export type PostExecutionHook = (
52
54
  * Compilation is the responsibility of the tool executor (see
53
55
  * `executeAppCreate`, `executeAppRefresh`): executors own the source→dist
54
56
  * transform and surface `compile_errors` in their result when it fails.
55
- * Post-execution hooks only observe the outcome and notify. They must
57
+ * Post-execution hooks only observe the outcome and notify — they must
56
58
  * not re-run a compile because `compileApp()` begins with `rm -rf dist/`
57
59
  * and would race with the executor's own output (LUM-1153).
58
60
  */
@@ -61,7 +63,14 @@ function notifyAppChanged(
61
63
  appId: string,
62
64
  opts?: { fileChange?: boolean; status?: string },
63
65
  ): void {
64
- notifyAppSurfacesChanged(appId, opts, ctx);
66
+ refreshSurfacesForApp(ctx, appId, opts);
67
+ broadcastAppFilesChanged(appId);
68
+ void updatePublishedAppDeployment(appId);
69
+ }
70
+
71
+ function broadcastAppFilesChanged(appId: string): void {
72
+ broadcastMessage({ type: "app_files_changed", appId });
73
+ publishAppsChanged();
65
74
  }
66
75
 
67
76
  /**
@@ -119,6 +128,8 @@ registerHook("app_create", (_name, _input, result, { ctx }) => {
119
128
  log.warn({ err, appId }, "Failed to track conversation ID on app_create");
120
129
  }
121
130
 
131
+ ensureAppSourceWatcher();
132
+
122
133
  notifyAppChanged(ctx, appId);
123
134
 
124
135
  // Seed background icon generation from the created app's canonical record
@@ -679,36 +679,3 @@ export interface ConversationDeletedContext
679
679
  * {@link BaseHookContext}.
680
680
  */
681
681
  export type ConversationsClearedContext = BaseHookContext;
682
-
683
- // ─── Message-deleted hook context ────────────────────────────────────────────
684
-
685
- /**
686
- * Context passed to the `message-deleted` hook. Fires once per deleted
687
- * message row, from the shared single-message delete primitive, after the row
688
- * is removed. Whole-conversation deletes dispatch `conversation-deleted`
689
- * instead.
690
- *
691
- * Fire-and-forget like `conversation-deleted`: the primitive is synchronous
692
- * and does not wait for the chain. The row is gone by the time a hook runs,
693
- * so the context carries the row's `createdAt` alongside its id. Together
694
- * they are the `(createdAt, id)` position the row held, which is what a hook
695
- * keeping a cursor on that row needs to record once the row can no longer be
696
- * looked up. The default memory plugin contributes a hook here that stamps
697
- * its retrospective cursor.
698
- */
699
- export interface MessageDeletedInputContext {
700
- /** ID of the conversation that owned the row. */
701
- readonly conversationId: string;
702
- /** ID of the deleted message row. */
703
- readonly messageId: string;
704
- /** The deleted row's `createdAt`. */
705
- readonly createdAt: number;
706
- }
707
-
708
- /**
709
- * The full `message-deleted` context a hook receives: the dispatching call
710
- * site's {@link MessageDeletedInputContext} plus the pipeline-stamped
711
- * {@link BaseHookContext} capabilities.
712
- */
713
- export interface MessageDeletedContext
714
- extends MessageDeletedInputContext, BaseHookContext {}
@@ -18,10 +18,9 @@
18
18
  * the platform can register a route that points at this instance.
19
19
  */
20
20
 
21
- import { getPlatformBaseUrl } from "../config/env.js";
21
+ import { getPlatformAssistantId, getPlatformBaseUrl } from "../config/env.js";
22
22
  import { getIsPlatform } from "../config/env-registry.js";
23
23
  import { getConfig } from "../config/loader.js";
24
- import { resolvePlatformAssistantId } from "../config/platform-identity.js";
25
24
  import { ipcRegisterWebhookRoute } from "../ipc/gateway-client.js";
26
25
  import { credentialKey } from "../security/credential-key.js";
27
26
  import { getSecureKeyAsync } from "../security/secure-keys.js";
@@ -46,11 +45,11 @@ export interface PlatformCallbackRegistrationContext {
46
45
 
47
46
  export async function resolvePlatformCallbackRegistrationContext(): Promise<PlatformCallbackRegistrationContext> {
48
47
  const platform = getIsPlatform();
49
- const [storedBaseUrlRaw, storedAssistantApiKeyRaw, assistantId] =
48
+ const [storedBaseUrlRaw, storedAssistantIdRaw, storedAssistantApiKeyRaw] =
50
49
  await Promise.all([
51
50
  getSecureKeyAsync(credentialKey("vellum", "platform_base_url")),
51
+ getSecureKeyAsync(credentialKey("vellum", "platform_assistant_id")),
52
52
  getSecureKeyAsync(credentialKey("vellum", "assistant_api_key")),
53
- resolvePlatformAssistantId(),
54
53
  ]);
55
54
 
56
55
  const storedBaseUrl = storedBaseUrlRaw?.trim();
@@ -58,6 +57,8 @@ export async function resolvePlatformCallbackRegistrationContext(): Promise<Plat
58
57
  /\/+$/,
59
58
  "",
60
59
  );
60
+ const assistantId =
61
+ getPlatformAssistantId().trim() || storedAssistantIdRaw?.trim() || "";
61
62
  const envAssistantCredential = process.env.ASSISTANT_API_KEY?.trim();
62
63
  const assistantCredential =
63
64
  storedAssistantApiKeyRaw?.trim() || envAssistantCredential || undefined;
@@ -329,6 +329,7 @@ describe("LiveVoiceMetricsCollector", () => {
329
329
  endpointHoldCount: 0,
330
330
  endpointDecisionMaxLatencyMs: 95,
331
331
  });
332
+ expect(completed).not.toHaveProperty("ackSpoken");
332
333
  });
333
334
 
334
335
  test("decisions without a source are attributed to the front door", () => {
@@ -434,6 +435,7 @@ describe("LiveVoiceMetricsCollector", () => {
434
435
  expect(completed).not.toHaveProperty("endpointHoldCount");
435
436
  expect(completed).not.toHaveProperty("endpointDecisionMaxLatencyMs");
436
437
  expect(completed).not.toHaveProperty("endpointDecisionSource");
438
+ expect(completed).not.toHaveProperty("ackSpoken");
437
439
  expect(completed).not.toHaveProperty("progressUpdatesSpoken");
438
440
 
439
441
  const aggregateFields = getLiveVoiceMetricsAggregateFields(
@@ -444,6 +446,7 @@ describe("LiveVoiceMetricsCollector", () => {
444
446
  expect(aggregateFields).not.toHaveProperty("endpointHoldCount");
445
447
  expect(aggregateFields).not.toHaveProperty("endpointDecisionMaxLatencyMs");
446
448
  expect(aggregateFields).not.toHaveProperty("endpointDecisionSource");
449
+ expect(aggregateFields).not.toHaveProperty("ackSpoken");
447
450
  expect(aggregateFields).not.toHaveProperty("progressUpdatesSpoken");
448
451
  });
449
452
 
@@ -1,14 +1,5 @@
1
1
  import { describe, expect, mock, test } from "bun:test";
2
2
 
3
- import type {
4
- VoiceProgressNarrator,
5
- VoiceProgressTextInput,
6
- } from "../../calls/progress-narration.js";
7
- import {
8
- pickProgressPhrase,
9
- PROGRESS_FALLBACK_PHRASES,
10
- PROGRESS_FALLBACK_PHRASES_BY_LANGUAGE,
11
- } from "../../calls/progress-phrases.js";
12
3
  import { sanitizeForTts } from "../../calls/tts-text-sanitizer.js";
13
4
  import type {
14
5
  VoiceTurnCallbacks,
@@ -16,9 +7,9 @@ import type {
16
7
  } from "../../calls/voice-session-bridge.js";
17
8
  import { loadRawConfig, saveRawConfig } from "../../config/loader.js";
18
9
  import type {
19
- VoiceFrontModelConfig,
20
- VoiceProgressConfig,
21
- } from "../../config/schemas/voice.js";
10
+ LiveVoiceFrontModelConfig,
11
+ LiveVoiceProgressConfig,
12
+ } from "../../config/schemas/live-voice.js";
22
13
  import type {
23
14
  StreamingTranscriber,
24
15
  SttStreamServerEvent,
@@ -30,6 +21,15 @@ import {
30
21
  } from "../live-voice-session.js";
31
22
  import type { LiveVoiceSessionFactoryContext } from "../live-voice-session-manager.js";
32
23
  import type { LiveVoiceTtsOptions } from "../live-voice-tts.js";
24
+ import type {
25
+ VoiceProgressNarrator,
26
+ VoiceProgressTextInput,
27
+ } from "../progress-narration.js";
28
+ import {
29
+ pickProgressPhrase,
30
+ PROGRESS_FALLBACK_PHRASES,
31
+ PROGRESS_FALLBACK_PHRASES_BY_LANGUAGE,
32
+ } from "../progress-phrases.js";
33
33
  import {
34
34
  createLiveVoiceServerFrameSequencer,
35
35
  type LiveVoiceClientStartFrame,
@@ -142,8 +142,8 @@ function makeProgressNarrator(
142
142
  }
143
143
 
144
144
  function progressConfig(
145
- overrides: Partial<VoiceProgressConfig> = {},
146
- ): Partial<VoiceFrontModelConfig> {
145
+ overrides: Partial<LiveVoiceProgressConfig> = {},
146
+ ): Partial<LiveVoiceFrontModelConfig> {
147
147
  const idleIntervalMs = overrides.idleIntervalMs ?? 60_000;
148
148
  return {
149
149
  progress: {
@@ -163,7 +163,7 @@ function progressConfig(
163
163
  }
164
164
 
165
165
  function createProgressHarness(options: {
166
- frontModelConfig: Partial<VoiceFrontModelConfig>;
166
+ frontModelConfig: Partial<LiveVoiceFrontModelConfig>;
167
167
  progressNarrator: VoiceProgressNarrator;
168
168
  emitMetrics?: boolean;
169
169
  gateTtsText?: (text: string) => Promise<void> | null;
@@ -12,7 +12,7 @@ import {
12
12
  loadRawConfig,
13
13
  saveRawConfig,
14
14
  } from "../../config/loader.js";
15
- import type { VoiceFrontModelConfig } from "../../config/schemas/voice.js";
15
+ import type { LiveVoiceFrontModelConfig } from "../../config/schemas/live-voice.js";
16
16
  import type {
17
17
  StreamingTranscriber,
18
18
  SttStreamServerEvent,
@@ -183,7 +183,7 @@ function createHarness(options: {
183
183
  echoBargeInMargin?: number;
184
184
  echoEmaHalfLifeMs?: number;
185
185
  echoDrainSlackMs?: number;
186
- frontModelConfig?: Partial<VoiceFrontModelConfig>;
186
+ frontModelConfig?: Partial<LiveVoiceFrontModelConfig>;
187
187
  emitMetrics?: boolean;
188
188
  metricsClock?: () => number;
189
189
  // Return a promise to hold a frame's transport write open (a backed-up
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
 
3
- import { VoiceProgressConfigSchema } from "../../config/schemas/voice.js";
3
+ import { LiveVoiceProgressConfigSchema } from "../../config/schemas/live-voice.js";
4
4
  import type { Provider, ProviderResponse } from "../../providers/types.js";
5
5
  import {
6
6
  createVoiceProgressNarrator,
@@ -8,7 +8,7 @@ import {
8
8
  type VoiceProgressTextInput,
9
9
  } from "../progress-narration.js";
10
10
 
11
- const config = VoiceProgressConfigSchema.parse({});
11
+ const config = LiveVoiceProgressConfigSchema.parse({});
12
12
  const progressInput: VoiceProgressTextInput = {
13
13
  transcriptSoFar: "compare flight prices for next month",
14
14
  completedOps: [
@@ -177,7 +177,7 @@ describe("createVoiceProgressNarrator", () => {
177
177
 
178
178
  test("bounds provider resolution by the configured timeout", async () => {
179
179
  const narrator = createVoiceProgressNarrator({
180
- config: VoiceProgressConfigSchema.parse({ generationTimeoutMs: 20 }),
180
+ config: LiveVoiceProgressConfigSchema.parse({ generationTimeoutMs: 20 }),
181
181
  getProvider: () => new Promise<Provider | null>(() => {}),
182
182
  });
183
183
  const startedAt = Date.now();
@@ -187,7 +187,7 @@ describe("createVoiceProgressNarrator", () => {
187
187
 
188
188
  test("a caller abort settles promptly", async () => {
189
189
  const narrator = createVoiceProgressNarrator({
190
- config: VoiceProgressConfigSchema.parse({
190
+ config: LiveVoiceProgressConfigSchema.parse({
191
191
  generationTimeoutMs: 60_000,
192
192
  }),
193
193
  getProvider: async () =>
@@ -8,6 +8,7 @@
8
8
 
9
9
  import { describe, expect, test } from "bun:test";
10
10
 
11
+ import { BRIDGE_SENTENCE_END_REGEX } from "../../calls/voice-triage-escalate.js";
11
12
  import { DEEPGRAM_MULTI_LANGUAGE_CODES } from "../../providers/speech-to-text/deepgram.js";
12
13
  import {
13
14
  APPROVAL_PENDING_PHRASE,
@@ -17,7 +18,6 @@ import {
17
18
  PROGRESS_FALLBACK_PHRASES,
18
19
  PROGRESS_FALLBACK_PHRASES_BY_LANGUAGE,
19
20
  } from "../progress-phrases.js";
20
- import { BRIDGE_SENTENCE_END_REGEX } from "../voice-triage-escalate.js";
21
21
 
22
22
  // Scripts without space-delimited words, where a word budget is
23
23
  // meaningless and length is asserted instead.