@vellumai/assistant 0.12.1-dev.202609141913.5e16607 → 0.12.1-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 (439) 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/docs/guardian-request-flow.md +0 -16
  5. package/openapi.yaml +49 -291
  6. package/package.json +1 -1
  7. package/src/__tests__/always-loaded-tools-guard.test.ts +10 -18
  8. package/src/__tests__/app-compiler.test.ts +0 -6
  9. package/src/__tests__/app-control-tool-schemas.test.ts +2 -5
  10. package/src/__tests__/app-dir-path-guard.test.ts +3 -1
  11. package/src/__tests__/app-source-watcher.test.ts +218 -0
  12. package/src/{calls/__tests__ → __tests__}/call-controller.test.ts +82 -503
  13. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +2 -5
  14. package/src/__tests__/computer-use-tools.test.ts +5 -17
  15. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  16. package/src/__tests__/config-schema.test.ts +29 -28
  17. package/src/__tests__/config-watcher-skill-reseed.test.ts +359 -0
  18. package/src/__tests__/config-watcher.test.ts +8 -23
  19. package/src/__tests__/connection-model-compat.test.ts +2 -2
  20. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  21. package/src/__tests__/conversation-pairing.test.ts +0 -26
  22. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -4
  23. package/src/__tests__/conversation-queue.test.ts +207 -48
  24. package/src/__tests__/conversation-retry-discard.test.ts +1 -54
  25. package/src/__tests__/conversation-skill-tools.test.ts +0 -27
  26. package/src/__tests__/conversation-surfaces-app-control.test.ts +3 -8
  27. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -67
  28. package/src/__tests__/conversation-title-service.test.ts +10 -14
  29. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +5 -3
  30. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -51
  31. package/src/__tests__/credential-record-retire.test.ts +1 -171
  32. package/src/__tests__/credential-routes.test.ts +3 -212
  33. package/src/__tests__/credential-security-invariants.test.ts +2 -4
  34. package/src/__tests__/cu-unified-flow.test.ts +2 -8
  35. package/src/__tests__/document-sync-tags.test.ts +0 -25
  36. package/src/__tests__/drain-kick-guard.test.ts +2 -0
  37. package/src/__tests__/drain-requeue-on-contention.test.ts +6 -0
  38. package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
  39. package/src/__tests__/host-bash-proxy.test.ts +45 -26
  40. package/src/__tests__/host-browser-proxy.test.ts +17 -6
  41. package/src/__tests__/host-file-proxy-targeted.test.ts +0 -23
  42. package/src/__tests__/host-file-proxy.test.ts +23 -11
  43. package/src/__tests__/host-transfer-proxy-targeted.test.ts +9 -30
  44. package/src/__tests__/llm-catalog-parity.test.ts +0 -25
  45. package/src/__tests__/mcp-auth-routes.test.ts +9 -6
  46. package/src/__tests__/mcp-config-secret-boundary.test.ts +136 -78
  47. package/src/__tests__/mcp-health-check.test.ts +11 -8
  48. package/src/__tests__/mcp-list-plugin-servers.test.ts +10 -8
  49. package/src/{calls/__tests__ → __tests__}/media-stream-audio-transcode.test.ts +1 -1
  50. package/src/{calls/__tests__ → __tests__}/media-stream-output.test.ts +8 -37
  51. package/src/{calls/__tests__ → __tests__}/media-stream-parser.test.ts +1 -1
  52. package/src/{calls/__tests__ → __tests__}/media-stream-server-integration.test.ts +57 -150
  53. package/src/{calls/__tests__ → __tests__}/media-stream-stt-session.test.ts +5 -5
  54. package/src/{calls/__tests__ → __tests__}/media-turn-detector.test.ts +1 -1
  55. package/src/__tests__/messages-after-tiebreaker.test.ts +0 -91
  56. package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
  57. package/src/__tests__/messaging-send-tool.test.ts +548 -355
  58. package/src/__tests__/model-intents.test.ts +0 -3
  59. package/src/__tests__/notification-vellum-adapter.test.ts +2 -85
  60. package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
  61. package/src/__tests__/platform-callback-registration.test.ts +16 -8
  62. package/src/__tests__/platform-client-verify-credential.test.ts +0 -2
  63. package/src/__tests__/plugin-import-boundary-guard.test.ts +0 -13
  64. package/src/__tests__/script-proxy-certs.test.ts +0 -35
  65. package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
  66. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  67. package/src/__tests__/speaker-identification.test.ts +56 -0
  68. package/src/__tests__/subagent-tool-gate-mode.test.ts +3 -19
  69. package/src/__tests__/subagent-tools.test.ts +2 -3
  70. package/src/__tests__/telephony-tts-guard.test.ts +3 -38
  71. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -4
  72. package/src/{calls/__tests__/voice-session-bridge-turn-flow.test.ts → __tests__/voice-session-bridge.test.ts} +12 -20
  73. package/src/__tests__/watch-retro-tool-availability.test.ts +17 -8
  74. package/src/__tests__/workspace-git-service.test.ts +0 -26
  75. package/src/acp/__tests__/agent-process.test.ts +4 -258
  76. package/src/acp/__tests__/auth-required.test.ts +0 -96
  77. package/src/acp/__tests__/client-handler.test.ts +2 -90
  78. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -5
  79. package/src/acp/__tests__/session-manager-resume.test.ts +6 -270
  80. package/src/acp/__tests__/session-manager-usage.test.ts +2 -4
  81. package/src/acp/__tests__/session-manager.test.ts +4 -895
  82. package/src/acp/agent-process.test.ts +1 -4
  83. package/src/acp/agent-process.ts +9 -94
  84. package/src/acp/auth-required.ts +1 -50
  85. package/src/acp/auto-install.test.ts +7 -9
  86. package/src/acp/client-handler.ts +3 -16
  87. package/src/acp/resolve-agent.test.ts +6 -220
  88. package/src/acp/resolve-agent.ts +23 -88
  89. package/src/acp/session-manager.test.ts +3 -196
  90. package/src/acp/session-manager.ts +18 -441
  91. package/src/acp/types.ts +5 -50
  92. package/src/api/events/app-files-changed.ts +3 -4
  93. package/src/api/events/notification-intent.ts +0 -2
  94. package/src/api/index.ts +0 -6
  95. package/src/apps/app-store.ts +1 -1
  96. package/src/bundler/app-compiler.ts +0 -15
  97. package/src/calls/__tests__/voice-control-protocol.test.ts +25 -58
  98. package/src/calls/__tests__/voice-session-bridge.test.ts +1 -37
  99. package/src/calls/__tests__/voice-triage-escalate.test.ts +0 -105
  100. package/src/calls/call-constants.ts +4 -24
  101. package/src/calls/call-controller.ts +199 -499
  102. package/src/calls/call-transport.ts +0 -16
  103. package/src/calls/media-stream-output.ts +0 -32
  104. package/src/calls/media-stream-server.ts +30 -82
  105. package/src/calls/media-stream-stt-session.ts +0 -15
  106. package/src/calls/resolve-call-tts-provider.ts +2 -33
  107. package/src/calls/speaker-identification.ts +233 -0
  108. package/src/calls/tts-call-strategy.ts +5 -9
  109. package/src/calls/types.ts +0 -2
  110. package/src/calls/voice-control-protocol.ts +21 -53
  111. package/src/calls/voice-session-bridge.ts +46 -59
  112. package/src/calls/voice-triage-escalate.ts +56 -175
  113. package/src/cli/commands/apps.help.ts +13 -67
  114. package/src/cli/commands/apps.ts +0 -183
  115. package/src/cli/commands/bash.help.ts +13 -8
  116. package/src/cli/commands/bash.ts +25 -7
  117. package/src/cli/commands/channels/index.help.ts +2 -70
  118. package/src/cli/commands/channels/index.ts +3 -16
  119. package/src/cli/commands/credentials.help.ts +2 -6
  120. package/src/cli/commands/credentials.ts +2 -2
  121. package/src/cli/commands/mcp.help.ts +8 -8
  122. package/src/cli/commands/mcp.ts +1 -1
  123. package/src/cli/commands/roadmap.help.ts +1 -5
  124. package/src/cli/commands/roadmap.ts +1 -1
  125. package/src/cli/lib/bundled-marketplace.json +90 -103
  126. package/src/config/__tests__/default-profile-catalog.test.ts +0 -22
  127. package/src/config/__tests__/memory-retrospective-schema.test.ts +1 -15
  128. package/src/config/__tests__/platform-rehydration.test.ts +9 -99
  129. package/src/config/acp-defaults.test.ts +3 -13
  130. package/src/config/acp-defaults.ts +6 -23
  131. package/src/config/acp-schema.ts +2 -30
  132. package/src/config/bundled-skills/acp/SKILL.md +14 -22
  133. package/src/config/bundled-skills/acp/TOOLS.json +1 -5
  134. package/src/config/bundled-skills/app-builder/SKILL.md +9 -12
  135. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
  136. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  137. package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
  138. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +139 -67
  139. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
  140. package/src/config/bundled-skills/schedule/SKILL.md +4 -3
  141. package/src/config/bundled-skills/screen-annotation/SKILL.md +1 -8
  142. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +1 -4
  143. package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
  144. package/src/config/default-profile-catalog.ts +1 -1
  145. package/src/config/env.ts +2 -2
  146. package/src/config/feature-flag-registry.json +12 -24
  147. package/src/config/loader.ts +0 -1
  148. package/src/config/memory-v3-gate.test.ts +0 -31
  149. package/src/config/memory-v3-gate.ts +16 -20
  150. package/src/config/platform-rehydration.ts +27 -11
  151. package/src/config/schema.ts +2 -2
  152. package/src/config/schemas/__tests__/live-voice.test.ts +158 -8
  153. package/src/config/schemas/calls.ts +28 -1
  154. package/src/config/schemas/live-voice.ts +173 -1
  155. package/src/config/schemas/mcp.ts +1 -1
  156. package/src/config/schemas/memory-retrospective.ts +0 -10
  157. package/src/config/schemas/services.ts +0 -8
  158. package/src/config/schemas/skills.ts +14 -0
  159. package/src/credential-execution/process-manager.test.ts +19 -18
  160. package/src/daemon/__tests__/conversation-tool-setup.test.ts +121 -66
  161. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +1 -4
  162. package/src/daemon/app-source-watcher.ts +218 -0
  163. package/src/daemon/config-watcher.ts +194 -13
  164. package/src/daemon/conversation-process.ts +64 -35
  165. package/src/daemon/conversation-skill-tools.ts +31 -13
  166. package/src/daemon/conversation-store.ts +1 -1
  167. package/src/daemon/conversation-surfaces.ts +8 -10
  168. package/src/daemon/conversation-tool-setup.ts +43 -37
  169. package/src/daemon/conversation.ts +3 -0
  170. package/src/daemon/host-bash-proxy.ts +12 -8
  171. package/src/daemon/host-browser-proxy.ts +1 -15
  172. package/src/daemon/host-file-proxy.ts +10 -8
  173. package/src/daemon/host-transfer-proxy.ts +18 -14
  174. package/src/daemon/lifecycle.ts +5 -0
  175. package/src/daemon/mcp-reload-service.ts +5 -5
  176. package/src/daemon/message-types/sync.ts +0 -1
  177. package/src/daemon/orphan-reaper.ts +1 -1
  178. package/src/daemon/providers-setup.ts +1 -1
  179. package/src/daemon/shutdown-handlers.ts +9 -1
  180. package/src/daemon/skill-memory-refresh.ts +0 -64
  181. package/src/daemon/tool-side-effects.ts +18 -7
  182. package/src/home/__tests__/feed-writer.test.ts +0 -22
  183. package/src/home/feed-writer.ts +2 -11
  184. package/src/hooks/types.ts +0 -33
  185. package/src/inbound/platform-callback-registration.ts +5 -4
  186. package/src/live-voice/__tests__/live-voice-metrics.test.ts +3 -0
  187. package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -15
  188. package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
  189. package/src/{calls → live-voice}/__tests__/progress-narration.test.ts +4 -4
  190. package/src/{calls → live-voice}/__tests__/progress-phrases.test.ts +1 -1
  191. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +69 -13
  192. package/src/live-voice/live-voice-session.ts +693 -213
  193. package/src/{calls → live-voice}/progress-narration.ts +2 -2
  194. package/src/live-voice/protocol.ts +2 -0
  195. package/src/mcp/__tests__/effective-config.test.ts +2 -2
  196. package/src/mcp/effective-config.ts +3 -3
  197. package/src/mcp/mcp-header-store.ts +45 -29
  198. package/src/mcp/startup.ts +4 -8
  199. package/src/messaging/provider.ts +3 -10
  200. package/src/messaging/providers/callback-routing.ts +0 -18
  201. package/src/messaging/providers/channel-transport.ts +0 -56
  202. package/src/messaging/providers/discord/transport.ts +0 -17
  203. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +17 -6
  204. package/src/messaging/providers/slack/adapter.ts +44 -7
  205. package/src/messaging/providers/slack/transport.ts +0 -16
  206. package/src/messaging/providers/telegram-bot/adapter.ts +48 -1
  207. package/src/messaging/providers/telegram-bot/client.ts +26 -0
  208. package/src/messaging/providers/telegram-bot/transport.ts +0 -20
  209. package/src/messaging/providers/whatsapp/adapter.ts +48 -1
  210. package/src/messaging/providers/whatsapp/client.ts +29 -0
  211. package/src/messaging/providers/whatsapp/transport.ts +0 -18
  212. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +0 -8
  213. package/src/notifications/__tests__/assistant-reply-producer.test.ts +0 -55
  214. package/src/notifications/__tests__/guardian-feed-projection.test.ts +2 -158
  215. package/src/notifications/__tests__/home-feed-side-effect.test.ts +3 -153
  216. package/src/notifications/__tests__/schedule-result-producer.test.ts +3 -99
  217. package/src/notifications/adapters/macos.ts +0 -3
  218. package/src/notifications/assistant-reply-producer.ts +3 -8
  219. package/src/notifications/conversation-pairing.ts +16 -36
  220. package/src/notifications/delivered-post-record.ts +1 -11
  221. package/src/notifications/guardian-feed-projection.ts +5 -125
  222. package/src/notifications/home-feed-side-effect.ts +7 -55
  223. package/src/notifications/schedule-result-producer.ts +22 -66
  224. package/src/oauth/__tests__/seed-providers-managed.test.ts +0 -54
  225. package/src/oauth/byo-connection.test.ts +0 -45
  226. package/src/oauth/byo-connection.ts +6 -36
  227. package/src/oauth/connection-resolver.test.ts +0 -73
  228. package/src/oauth/connection-resolver.ts +2 -95
  229. package/src/oauth/seed-providers.ts +0 -165
  230. package/src/outbound-proxy/certs.ts +5 -3
  231. package/src/permissions/checker.test.ts +6 -11
  232. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  233. package/src/persistence/conversation-crud.ts +63 -71
  234. package/src/persistence/conversation-lineage.ts +4 -12
  235. package/src/persistence/conversation-title-service.ts +26 -9
  236. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  237. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  238. package/src/persistence/message-reads.ts +0 -30
  239. package/src/persistence/migrations/157-invite-contact-id.ts +6 -18
  240. package/src/persistence/schema/memory-core.ts +0 -5
  241. package/src/platform/client.test.ts +2 -4
  242. package/src/platform/client.ts +10 -2
  243. package/src/plugin-api/constants.ts +0 -2
  244. package/src/plugin-api/index.ts +0 -1
  245. package/src/plugin-api/types.ts +0 -2
  246. package/src/plugins/defaults/index.ts +0 -2
  247. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +0 -46
  248. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +5 -9
  249. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +10 -20
  250. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +0 -219
  251. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +0 -31
  252. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -63
  253. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +0 -4
  254. package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -4
  255. package/src/plugins/defaults/memory/hooks/init.ts +0 -10
  256. package/src/plugins/defaults/memory/hooks/shutdown.ts +0 -2
  257. package/src/plugins/defaults/memory/jobs-worker.ts +0 -13
  258. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +60 -34
  259. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +5 -3
  260. package/src/plugins/defaults/memory/memory-retrospective-job.ts +3 -12
  261. package/src/plugins/defaults/memory/memory-retrospective-state.ts +71 -312
  262. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +1 -2
  263. package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +3 -5
  264. package/src/plugins/defaults/memory/startup.ts +1 -6
  265. package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +9 -7
  266. package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
  267. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +0 -89
  268. package/src/plugins/defaults/memory/worker.ts +0 -6
  269. package/src/plugins/mcp-servers.ts +75 -15
  270. package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
  271. package/src/providers/gemini/client.ts +23 -9
  272. package/src/providers/inference/auth.ts +3 -2
  273. package/src/providers/inference/connection-availability.ts +8 -27
  274. package/src/providers/inference/resolve-auth.ts +4 -22
  275. package/src/providers/model-catalog.ts +0 -34
  276. package/src/providers/model-intents.ts +5 -10
  277. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +18 -146
  278. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +1 -83
  279. package/src/providers/openai/chat-completions-provider.ts +78 -192
  280. package/src/providers/openai/codex-models.ts +4 -0
  281. package/src/runtime/AGENTS.md +0 -2
  282. package/src/runtime/auth/same-actor.ts +3 -38
  283. package/src/runtime/http-server.ts +151 -160
  284. package/src/runtime/routes/__tests__/acp-routes.test.ts +4 -159
  285. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -108
  286. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
  287. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +12 -16
  288. package/src/runtime/routes/acp-routes.test.ts +0 -15
  289. package/src/runtime/routes/acp-routes.ts +9 -72
  290. package/src/runtime/routes/app-management-routes.ts +0 -73
  291. package/src/runtime/routes/app-routes.ts +1 -1
  292. package/src/runtime/routes/conversation-list-routes.ts +3 -14
  293. package/src/runtime/routes/conversation-query-routes.ts +0 -40
  294. package/src/runtime/routes/credential-routes.ts +10 -19
  295. package/src/runtime/routes/debug-bash-routes.ts +173 -0
  296. package/src/runtime/routes/diagnostics-routes.ts +3 -55
  297. package/src/runtime/routes/index.ts +2 -4
  298. package/src/runtime/routes/log-export-routes.ts +0 -2
  299. package/src/runtime/routes/mcp-auth-routes.ts +47 -39
  300. package/src/runtime/routes/migration-routes.ts +20 -6
  301. package/src/runtime/routes/platform-routes.ts +15 -18
  302. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -28
  303. package/src/runtime/services/conversation-serializer.ts +3 -16
  304. package/src/runtime/sync/resource-sync-events.ts +1 -2
  305. package/src/schedule/worker.ts +1 -1
  306. package/src/security/ces-rpc-record-backend.ts +0 -7
  307. package/src/subagent/consult-context.ts +25 -12
  308. package/src/tools/acp/list-agents.test.ts +1 -3
  309. package/src/tools/acp/spawn.test.ts +11 -146
  310. package/src/tools/acp/spawn.ts +3 -21
  311. package/src/tools/acp/status.ts +3 -40
  312. package/src/tools/app-control/skill-proxy-bridge.ts +1 -2
  313. package/src/tools/capability-offer.test.ts +2 -22
  314. package/src/tools/capability-offer.ts +1 -16
  315. package/src/tools/computer-use/definitions.ts +2 -4
  316. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -2
  317. package/src/tools/credentials/metadata-store.ts +0 -100
  318. package/src/tools/host-filesystem/edit.test.ts +1 -2
  319. package/src/tools/host-filesystem/edit.ts +2 -2
  320. package/src/tools/host-filesystem/read.test.ts +1 -2
  321. package/src/tools/host-filesystem/read.ts +2 -2
  322. package/src/tools/host-filesystem/transfer.test.ts +1 -2
  323. package/src/tools/host-filesystem/transfer.ts +2 -2
  324. package/src/tools/host-filesystem/write.test.ts +1 -2
  325. package/src/tools/host-filesystem/write.ts +2 -2
  326. package/src/tools/host-terminal/host-shell.test.ts +0 -16
  327. package/src/tools/host-terminal/host-shell.ts +20 -4
  328. package/src/tools/policy-context.ts +7 -6
  329. package/src/tools/subagent/spawn.ts +8 -5
  330. package/src/tools/watch/watch-retro-report.ts +8 -0
  331. package/src/util/__tests__/language-subtag.test.ts +1 -23
  332. package/src/util/fs-watcher-error.ts +36 -0
  333. package/src/util/language-subtag.ts +0 -16
  334. package/src/util/platform.ts +0 -8
  335. package/src/workspace/git-service.ts +54 -5
  336. package/src/workspace/migrations/registry.ts +0 -6
  337. package/scripts/smoke-desktop-window-theme.ts +0 -186
  338. package/src/__tests__/git-porcelain.test.ts +0 -47
  339. package/src/__tests__/helpers/set-workspace-mcp.ts +0 -11
  340. package/src/__tests__/message-deleted-hook-dispatch.test.ts +0 -119
  341. package/src/__tests__/resolve-app.test.ts +0 -135
  342. package/src/__tests__/service-account-token.test.ts +0 -247
  343. package/src/__tests__/source-fingerprint.test.ts +0 -184
  344. package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +0 -336
  345. package/src/acp/__tests__/helpers/acp-model-option.ts +0 -51
  346. package/src/acp/model-config.test.ts +0 -166
  347. package/src/acp/model-config.ts +0 -138
  348. package/src/api/events/acp-session-model-update.test.ts +0 -88
  349. package/src/api/events/acp-session-model-update.ts +0 -46
  350. package/src/apps/resolve-app.ts +0 -81
  351. package/src/apps/source-fingerprint.ts +0 -266
  352. package/src/calls/__tests__/barge-in-guard.test.ts +0 -81
  353. package/src/calls/__tests__/voice-leg-coordinator.test.ts +0 -229
  354. package/src/calls/__tests__/voice-progress-cadence.test.ts +0 -274
  355. package/src/calls/barge-in-guard.ts +0 -118
  356. package/src/calls/voice-leg-coordinator.ts +0 -189
  357. package/src/calls/voice-progress-cadence.ts +0 -423
  358. package/src/cli/commands/__tests__/apps.test.ts +0 -245
  359. package/src/cli/commands/__tests__/bash.test.ts +0 -53
  360. package/src/cli/commands/__tests__/roadmap.help.test.ts +0 -19
  361. package/src/cli/commands/channels/__tests__/send.test.ts +0 -218
  362. package/src/cli/commands/channels/send.ts +0 -128
  363. package/src/config/__tests__/platform-identity.test.ts +0 -255
  364. package/src/config/acp-agent-write.ts +0 -43
  365. package/src/config/acp-schema.test.ts +0 -81
  366. package/src/config/platform-identity.ts +0 -201
  367. package/src/config/schemas/__tests__/voice.test.ts +0 -148
  368. package/src/config/schemas/voice.ts +0 -150
  369. package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +0 -133
  370. package/src/daemon/app-change-notify.ts +0 -45
  371. package/src/desktop/__tests__/fake-desktop.ts +0 -119
  372. package/src/desktop/desktop-chrome-policy.test.ts +0 -71
  373. package/src/desktop/desktop-chrome-policy.ts +0 -42
  374. package/src/desktop/desktop-dependencies.test.ts +0 -102
  375. package/src/desktop/desktop-dependencies.ts +0 -306
  376. package/src/desktop/desktop-feature.test.ts +0 -18
  377. package/src/desktop/desktop-feature.ts +0 -19
  378. package/src/desktop/desktop-panel-config.test.ts +0 -135
  379. package/src/desktop/desktop-panel-config.ts +0 -149
  380. package/src/desktop/desktop-session-manager.test.ts +0 -627
  381. package/src/desktop/desktop-session-manager.ts +0 -814
  382. package/src/desktop/desktop-stream-bridge.test.ts +0 -395
  383. package/src/desktop/desktop-stream-bridge.ts +0 -214
  384. package/src/desktop/desktop-wallpaper.test.ts +0 -191
  385. package/src/desktop/desktop-wallpaper.ts +0 -113
  386. package/src/desktop/desktop-window-theme.ts +0 -170
  387. package/src/i18n/AGENTS.md +0 -22
  388. package/src/i18n/__tests__/i18n.test.ts +0 -108
  389. package/src/i18n/index.ts +0 -16
  390. package/src/i18n/locales.ts +0 -93
  391. package/src/i18n/messages.ts +0 -61
  392. package/src/i18n/title.ts +0 -25
  393. package/src/mcp/__tests__/workspace-mcp-config.test.ts +0 -135
  394. package/src/mcp/spec-schema.ts +0 -111
  395. package/src/mcp/workspace-mcp-config.ts +0 -188
  396. package/src/messaging/providers/__tests__/proactive-address.test.ts +0 -95
  397. package/src/persistence/conversation-title-placeholders.ts +0 -23
  398. package/src/persistence/message-cursor.ts +0 -78
  399. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +0 -149
  400. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +0 -118
  401. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +0 -83
  402. package/src/plugins/defaults/memory/hooks/message-deleted.ts +0 -21
  403. package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +0 -126
  404. package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +0 -79
  405. package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +0 -28
  406. package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +0 -9
  407. package/src/providers/gemini-thought-signature.test.ts +0 -63
  408. package/src/providers/gemini-thought-signature.ts +0 -44
  409. package/src/providers/inference/service-account-token.ts +0 -248
  410. package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +0 -613
  411. package/src/providers/openai/__tests__/google-thought-signature.test.ts +0 -235
  412. package/src/providers/openai/google-thought-signature.ts +0 -320
  413. package/src/runtime/__tests__/channel-send.test.ts +0 -443
  414. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +0 -89
  415. package/src/runtime/__tests__/live-voice-upgrade.test.ts +0 -58
  416. package/src/runtime/__tests__/runtime-ws-test-utils.ts +0 -72
  417. package/src/runtime/__tests__/watch-stream-upgrade.test.ts +0 -59
  418. package/src/runtime/channel-send.ts +0 -316
  419. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +0 -205
  420. package/src/runtime/routes/__tests__/channel-send-routes.test.ts +0 -127
  421. package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +0 -107
  422. package/src/runtime/routes/channel-send-routes.ts +0 -85
  423. package/src/runtime/routes/desktop-setup-routes.test.ts +0 -74
  424. package/src/runtime/routes/desktop-setup-routes.ts +0 -35
  425. package/src/security/__tests__/ces-http-record-backend.test.ts +0 -137
  426. package/src/security/ces-http-record-backend.ts +0 -120
  427. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +0 -60
  428. package/src/skills/workspace-skill-md-signature.ts +0 -50
  429. package/src/tools/acp/status.test.ts +0 -94
  430. package/src/tools/terminal/__tests__/sanitized-bash.test.ts +0 -57
  431. package/src/tools/terminal/sanitized-bash.ts +0 -105
  432. package/src/util/ca-bundle.ts +0 -13
  433. package/src/workspace/git-porcelain.ts +0 -66
  434. package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +0 -258
  435. package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +0 -78
  436. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +0 -214
  437. package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +0 -102
  438. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +0 -199
  439. /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",
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Tools run commands in their own process group (`detached: true`) and, on
5
5
  * timeout/abort, group-kill with `process.kill(-pgid, SIGKILL)` (the bash and
6
- * host_bash tools, and the skill sandbox runner). The
6
+ * host_bash tools, the skill sandbox runner, and the debug-bash route). The
7
7
  * immediate child is reaped by Bun/libuv, but its descendants — e.g. git's
8
8
  * transport helpers or a skill runner's `bun` process — were never spawned by
9
9
  * the daemon, so when the group dies they reparent to PID 1. When the daemon
@@ -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
@@ -459,28 +459,6 @@ describe("feed-writer", () => {
459
459
  expect(result!.summary).toBe("Fresh summary");
460
460
  });
461
461
 
462
- test("a status value replaces, and a status updater reads write-time state", async () => {
463
- await appendFeedItem(makeItem({ id: "item-1" }));
464
-
465
- const replaced = await patchFeedItemContent("item-1", {
466
- status: "acted_on",
467
- });
468
- expect(replaced!.status).toBe("acted_on");
469
-
470
- // The updater sees the status as of the write, so a conditional
471
- // transition cannot overwrite what another writer just set.
472
- const observed: string[] = [];
473
- const conditional = await patchFeedItemContent("item-1", {
474
- status: (existing) => {
475
- observed.push(existing.status);
476
- return existing.status === "new" ? "seen" : existing.status;
477
- },
478
- });
479
- expect(observed).toEqual(["acted_on"]);
480
- expect(conditional!.status).toBe("acted_on");
481
- expect(readFileJson().items[0]!.status).toBe("acted_on");
482
- });
483
-
484
462
  test("returns null for an unknown id", async () => {
485
463
  await appendFeedItem(makeItem({ id: "known" }));
486
464
  expect(await patchFeedItemContent("unknown", { title: "x" })).toBeNull();
@@ -185,13 +185,7 @@ export interface FeedItemContentPatch {
185
185
  title?: string;
186
186
  summary?: string;
187
187
  urgency?: FeedItemUrgency;
188
- /**
189
- * New status, or an updater applied inside the coalescing queue so it
190
- * reads the item as of write time. Use the updater for a conditional
191
- * transition: a plain value would overwrite a status another writer
192
- * set while the patch sat in the queue.
193
- */
194
- status?: FeedItemStatus | ((existing: FeedItem) => FeedItemStatus);
188
+ status?: FeedItemStatus;
195
189
  /**
196
190
  * Updater for the item's guardian projection, applied inside the
197
191
  * coalescing queue so it reads the projection as of write time (a
@@ -405,10 +399,7 @@ async function runWrite(): Promise<void> {
405
399
  updated.urgency = patch.urgency;
406
400
  }
407
401
  if (patch.status !== undefined) {
408
- updated.status =
409
- typeof patch.status === "function"
410
- ? patch.status(existing)
411
- : patch.status;
402
+ updated.status = patch.status;
412
403
  }
413
404
  if (patch.guardianRequest !== undefined && existing.guardianRequest) {
414
405
  updated.guardianRequest = patch.guardianRequest(existing.guardianRequest);
@@ -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;