@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,148 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
-
3
- import { VoiceConfigSchema, VoiceFrontModelConfigSchema } from "../voice.js";
4
-
5
- const PROGRESS_DEFAULTS = {
6
- enabled: true,
7
- opsThreshold: 3,
8
- idleIntervalMs: 5_000,
9
- maxSilenceMs: 35_000,
10
- longOpMs: 15_000,
11
- minGapMs: 6_000,
12
- generationTimeoutMs: 1_500,
13
- };
14
-
15
- const FRONT_MODEL_DEFAULTS = {
16
- endpointDecisionTimeoutMs: 1200,
17
- endpointExtensionMs: 1500,
18
- endpointMaxExtensions: 2,
19
- progress: PROGRESS_DEFAULTS,
20
- };
21
-
22
- describe("VoiceFrontModelConfigSchema", () => {
23
- test("empty object parses to defaults", () => {
24
- const parsed = VoiceFrontModelConfigSchema.parse({});
25
- expect(parsed).toEqual(FRONT_MODEL_DEFAULTS);
26
- });
27
-
28
- test("accepts overrides", () => {
29
- const parsed = VoiceFrontModelConfigSchema.parse({
30
- endpointDecisionTimeoutMs: 400,
31
- endpointMaxExtensions: 0,
32
- });
33
- expect(parsed.endpointDecisionTimeoutMs).toBe(400);
34
- expect(parsed.endpointMaxExtensions).toBe(0);
35
- // Unspecified fields still get defaults
36
- expect(parsed.endpointExtensionMs).toBe(1500);
37
- });
38
-
39
- test("strips retired generated-ack settings", () => {
40
- const parsed = VoiceFrontModelConfigSchema.parse({
41
- ackFirstDeltaTimeoutMs: 2500,
42
- ackGenerationTimeoutMs: 600,
43
- });
44
- expect(parsed).not.toHaveProperty("ackFirstDeltaTimeoutMs");
45
- expect(parsed).not.toHaveProperty("ackGenerationTimeoutMs");
46
- });
47
-
48
- test("rejects non-positive endpointDecisionTimeoutMs", () => {
49
- const result = VoiceFrontModelConfigSchema.safeParse({
50
- endpointDecisionTimeoutMs: 0,
51
- });
52
- expect(result.success).toBe(false);
53
- });
54
-
55
- test("rejects negative endpointMaxExtensions", () => {
56
- const result = VoiceFrontModelConfigSchema.safeParse({
57
- endpointMaxExtensions: -1,
58
- });
59
- expect(result.success).toBe(false);
60
- });
61
-
62
- test("absent progress namespace parses to full progress defaults", () => {
63
- const parsed = VoiceFrontModelConfigSchema.parse({});
64
- expect(parsed.progress).toEqual(PROGRESS_DEFAULTS);
65
- });
66
-
67
- test("partial progress overrides merge with defaults", () => {
68
- const parsed = VoiceFrontModelConfigSchema.parse({
69
- progress: { enabled: false, opsThreshold: 5 },
70
- });
71
- expect(parsed.progress.enabled).toBe(false);
72
- expect(parsed.progress.opsThreshold).toBe(5);
73
- // Unspecified progress fields still get defaults
74
- expect(parsed.progress.idleIntervalMs).toBe(5_000);
75
- expect(parsed.progress.maxSilenceMs).toBe(35_000);
76
- expect(parsed.progress.longOpMs).toBe(15_000);
77
- expect(parsed.progress.minGapMs).toBe(6_000);
78
- expect(parsed.progress.generationTimeoutMs).toBe(1_500);
79
- });
80
-
81
- test("a stale maxPerTurn key is stripped, not rejected", () => {
82
- // The cap was removed; configs written while it existed must still parse.
83
- const parsed = VoiceFrontModelConfigSchema.parse({
84
- progress: { maxPerTurn: 3 },
85
- });
86
- expect("maxPerTurn" in parsed.progress).toBe(false);
87
- });
88
-
89
- test("rejects non-positive progress.opsThreshold", () => {
90
- const result = VoiceFrontModelConfigSchema.safeParse({
91
- progress: { opsThreshold: 0 },
92
- });
93
- expect(result.success).toBe(false);
94
- });
95
-
96
- test("rejects a heartbeat ceiling shorter than the idle tick interval", () => {
97
- // The heartbeat is only checked on the idle tick, so a shorter ceiling
98
- // could be overshot by a full interval.
99
- const result = VoiceFrontModelConfigSchema.safeParse({
100
- progress: { idleIntervalMs: 60_000, maxSilenceMs: 10_000 },
101
- });
102
- expect(result.success).toBe(false);
103
- if (!result.success) {
104
- const msgs = result.error.issues.map((issue) => issue.message);
105
- expect(
106
- msgs.some((msg) =>
107
- msg.includes("voice.frontModel.progress.maxSilenceMs"),
108
- ),
109
- ).toBe(true);
110
- }
111
- // The floor itself is allowed: the tick is exactly on the ceiling.
112
- expect(
113
- VoiceFrontModelConfigSchema.safeParse({
114
- progress: { idleIntervalMs: 60_000, maxSilenceMs: 60_000 },
115
- }).success,
116
- ).toBe(true);
117
- });
118
-
119
- test("rejects a non-boolean progress.enabled", () => {
120
- const result = VoiceFrontModelConfigSchema.safeParse({
121
- progress: { enabled: "yes" },
122
- });
123
- expect(result.success).toBe(false);
124
- if (!result.success) {
125
- const msgs = result.error.issues.map((i) => i.message);
126
- expect(
127
- msgs.some((m) => m.includes("voice.frontModel.progress.enabled")),
128
- ).toBe(true);
129
- }
130
- });
131
- });
132
-
133
- describe("VoiceConfigSchema", () => {
134
- test("empty object parses to front-model defaults", () => {
135
- expect(VoiceConfigSchema.parse({})).toEqual({
136
- frontModel: FRONT_MODEL_DEFAULTS,
137
- });
138
- });
139
-
140
- test("partial frontModel overrides merge with defaults", () => {
141
- const parsed = VoiceConfigSchema.parse({
142
- frontModel: { endpointDecisionTimeoutMs: 300 },
143
- });
144
- expect(parsed.frontModel.endpointDecisionTimeoutMs).toBe(300);
145
- expect(parsed.frontModel.endpointExtensionMs).toBe(1500);
146
- expect(parsed.frontModel.progress).toEqual(PROGRESS_DEFAULTS);
147
- });
148
- });
@@ -1,150 +0,0 @@
1
- import { z } from "zod";
2
-
3
- export const VoiceProgressConfigSchema = z
4
- .object({
5
- enabled: z
6
- .boolean({
7
- error: "voice.frontModel.progress.enabled must be a boolean",
8
- })
9
- .default(true)
10
- .describe(
11
- "Speak short progress updates during long-running tool-heavy turns; the opt-out for progress narration",
12
- ),
13
- opsThreshold: z
14
- .number({
15
- error: "voice.frontModel.progress.opsThreshold must be a number",
16
- })
17
- .int("voice.frontModel.progress.opsThreshold must be an integer")
18
- .positive(
19
- "voice.frontModel.progress.opsThreshold must be a positive integer",
20
- )
21
- .default(3)
22
- .describe(
23
- "Narrate after this many tool operations since the last narration",
24
- ),
25
- idleIntervalMs: z
26
- .number({
27
- error: "voice.frontModel.progress.idleIntervalMs must be a number",
28
- })
29
- .int("voice.frontModel.progress.idleIntervalMs must be an integer")
30
- .positive(
31
- "voice.frontModel.progress.idleIntervalMs must be a positive integer",
32
- )
33
- .default(5_000)
34
- .describe(
35
- "How often (ms) a running turn's silence is checked, and so the soonest new tool activity is narrated",
36
- ),
37
- maxSilenceMs: z
38
- .number({
39
- error: "voice.frontModel.progress.maxSilenceMs must be a number",
40
- })
41
- .int("voice.frontModel.progress.maxSilenceMs must be an integer")
42
- .positive(
43
- "voice.frontModel.progress.maxSilenceMs must be a positive integer",
44
- )
45
- .default(35_000)
46
- .describe(
47
- "Heartbeat ceiling (ms): narrate after this much unbroken silence even when nothing new has happened. Evaluated on the idle tick, so its resolution is idleIntervalMs and it must be at least that long",
48
- ),
49
- longOpMs: z
50
- .number({
51
- error: "voice.frontModel.progress.longOpMs must be a number",
52
- })
53
- .int("voice.frontModel.progress.longOpMs must be an integer")
54
- .positive("voice.frontModel.progress.longOpMs must be a positive integer")
55
- .default(15_000)
56
- .describe(
57
- "A tool operation that ran at least this long (ms) narrates the moment it completes, without waiting for opsThreshold",
58
- ),
59
- minGapMs: z
60
- .number({
61
- error: "voice.frontModel.progress.minGapMs must be a number",
62
- })
63
- .int("voice.frontModel.progress.minGapMs must be an integer")
64
- .positive("voice.frontModel.progress.minGapMs must be a positive integer")
65
- .default(6_000)
66
- .describe(
67
- "Minimum spacing (ms) from any spoken floor-holder (ack or narration)",
68
- ),
69
- generationTimeoutMs: z
70
- .number({
71
- error: "voice.frontModel.progress.generationTimeoutMs must be a number",
72
- })
73
- .int("voice.frontModel.progress.generationTimeoutMs must be an integer")
74
- .positive(
75
- "voice.frontModel.progress.generationTimeoutMs must be a positive integer",
76
- )
77
- .default(1_500)
78
- .describe(
79
- "Budget (ms) for LLM-generated progress text. Not latency-critical: it speaks into dead air",
80
- ),
81
- })
82
- // The heartbeat is checked when the idle tick finds the turn silent, so a
83
- // ceiling shorter than the tick interval would be missed by up to a full
84
- // interval, a promise the cadence cannot keep. Rejecting the combination
85
- // beats silently overshooting it.
86
- .refine((progress) => progress.maxSilenceMs >= progress.idleIntervalMs, {
87
- error:
88
- "voice.frontModel.progress.maxSilenceMs must be at least idleIntervalMs: the heartbeat is evaluated on the idle tick",
89
- })
90
- .describe(
91
- "Progress-narration tuning for live voice sessions (spoken updates during long-running turns)",
92
- );
93
-
94
- export const VoiceFrontModelConfigSchema = z
95
- .object({
96
- endpointDecisionTimeoutMs: z
97
- .number({
98
- error: "voice.frontModel.endpointDecisionTimeoutMs must be a number",
99
- })
100
- .int("voice.frontModel.endpointDecisionTimeoutMs must be an integer")
101
- .positive(
102
- "voice.frontModel.endpointDecisionTimeoutMs must be a positive integer",
103
- )
104
- .default(1200)
105
- .describe(
106
- "Hard budget (ms) for the endpoint decision LLM call. This adds to end-of-turn latency when semantic endpointing is on, so keep it as tight as the decider model's real roundtrip allows. Measured Haiku roundtrips through the managed proxy run ~670-1130ms (dev), so tighter budgets turn the feature into a fail-open no-op.",
107
- ),
108
- endpointExtensionMs: z
109
- .number({
110
- error: "voice.frontModel.endpointExtensionMs must be a number",
111
- })
112
- .int("voice.frontModel.endpointExtensionMs must be an integer")
113
- .positive(
114
- "voice.frontModel.endpointExtensionMs must be a positive integer",
115
- )
116
- .default(1500)
117
- .describe(
118
- "How long (ms) a 'hold' decision keeps the turn open before turn-end replays",
119
- ),
120
- endpointMaxExtensions: z
121
- .number({
122
- error: "voice.frontModel.endpointMaxExtensions must be a number",
123
- })
124
- .int("voice.frontModel.endpointMaxExtensions must be an integer")
125
- .nonnegative(
126
- "voice.frontModel.endpointMaxExtensions must be a nonnegative integer",
127
- )
128
- .default(2)
129
- .describe("Cap on consecutive 'hold' extensions per utterance"),
130
- progress: VoiceProgressConfigSchema.default(
131
- VoiceProgressConfigSchema.parse({}),
132
- ),
133
- })
134
- .describe(
135
- "Voice front-door endpointing and long-turn progress narration tuning, shared by live voice and phone calls",
136
- );
137
-
138
- export const VoiceConfigSchema = z
139
- .object({
140
- frontModel: VoiceFrontModelConfigSchema.default(
141
- VoiceFrontModelConfigSchema.parse({}),
142
- ),
143
- })
144
- .describe(
145
- "Transport-agnostic voice configuration shared by live voice and phone calls: front-door routing and progress narration tuning",
146
- );
147
-
148
- export type VoiceConfig = z.infer<typeof VoiceConfigSchema>;
149
- export type VoiceFrontModelConfig = z.infer<typeof VoiceFrontModelConfigSchema>;
150
- export type VoiceProgressConfig = z.infer<typeof VoiceProgressConfigSchema>;
@@ -1,133 +0,0 @@
1
- import { mkdirSync, mkdtempSync, rmSync, utimesSync, writeFileSync } from "node:fs";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
4
- import {
5
- afterEach,
6
- beforeEach,
7
- describe,
8
- expect,
9
- mock,
10
- test,
11
- } from "bun:test";
12
-
13
- const WORKSPACE_DIR = mkdtempSync(join(tmpdir(), "skill-md-mtime-refresh-"));
14
- process.env.VELLUM_WORKSPACE_DIR = WORKSPACE_DIR;
15
-
16
- const seedGraphCalls: number[] = [];
17
- const seedV2Calls: number[] = [];
18
-
19
- mock.module("../../config/loader.js", () => ({
20
- getConfig: () => ({}),
21
- }));
22
-
23
- mock.module("../../plugins/defaults/memory/graph/capability-seed.js", () => ({
24
- seedSkillGraphNodes: () => {
25
- seedGraphCalls.push(Date.now());
26
- },
27
- seedUninstalledCatalogSkillMemories: async () => {},
28
- }));
29
-
30
- mock.module(
31
- "../../plugins/defaults/memory/substrate/boot-maintenance.js",
32
- () => ({
33
- maybeSeedCapabilitySkills: () => {
34
- seedV2Calls.push(Date.now());
35
- },
36
- maybeSeedCliCommandCards: () => {},
37
- }),
38
- );
39
-
40
- const {
41
- _resetSkillMdMtimeStateForTests,
42
- maybeRefreshSkillCapabilityMemoriesFromMtime,
43
- refreshSkillCapabilityMemories,
44
- startWorkspaceSkillMdMtimePoll,
45
- stopWorkspaceSkillMdMtimePoll,
46
- } = await import("../skill-memory-refresh.js");
47
-
48
- const SKILLS_DIR = join(WORKSPACE_DIR, "skills");
49
-
50
- function writeSkill(id: string): string {
51
- const dir = join(SKILLS_DIR, id);
52
- mkdirSync(dir, { recursive: true });
53
- const skillMd = join(dir, "SKILL.md");
54
- writeFileSync(
55
- skillMd,
56
- `---\nname: ${id}\ndescription: ${id}\n---\nbody\n`,
57
- );
58
- return skillMd;
59
- }
60
-
61
- describe("maybeRefreshSkillCapabilityMemoriesFromMtime", () => {
62
- beforeEach(() => {
63
- rmSync(SKILLS_DIR, { recursive: true, force: true });
64
- mkdirSync(SKILLS_DIR, { recursive: true });
65
- seedGraphCalls.length = 0;
66
- seedV2Calls.length = 0;
67
- _resetSkillMdMtimeStateForTests();
68
- });
69
-
70
- afterEach(() => {
71
- _resetSkillMdMtimeStateForTests();
72
- });
73
-
74
- test("first call reseeds, a second call with unchanged SKILL.md does not", () => {
75
- writeSkill("alpha");
76
- expect(maybeRefreshSkillCapabilityMemoriesFromMtime()).toBe(true);
77
- expect(seedGraphCalls).toHaveLength(1);
78
- expect(seedV2Calls).toHaveLength(1);
79
-
80
- expect(maybeRefreshSkillCapabilityMemoriesFromMtime()).toBe(false);
81
- expect(seedGraphCalls).toHaveLength(1);
82
- });
83
-
84
- test("explicit refresh remembers the signature so the next poll is a no-op", () => {
85
- writeSkill("alpha");
86
- refreshSkillCapabilityMemories();
87
- expect(seedGraphCalls).toHaveLength(1);
88
- expect(maybeRefreshSkillCapabilityMemoriesFromMtime()).toBe(false);
89
- });
90
-
91
- test("SKILL.md mtime change reseeds", () => {
92
- const skillMd = writeSkill("alpha");
93
- expect(maybeRefreshSkillCapabilityMemoriesFromMtime()).toBe(true);
94
-
95
- const later = new Date(Date.now() + 5_000);
96
- utimesSync(skillMd, later, later);
97
- expect(maybeRefreshSkillCapabilityMemoriesFromMtime()).toBe(true);
98
- expect(seedGraphCalls).toHaveLength(2);
99
- });
100
-
101
- test("TOOLS.json change without a SKILL.md mtime change does not reseed", () => {
102
- writeSkill("alpha");
103
- expect(maybeRefreshSkillCapabilityMemoriesFromMtime()).toBe(true);
104
-
105
- writeFileSync(
106
- join(SKILLS_DIR, "alpha", "TOOLS.json"),
107
- JSON.stringify({ version: 1, tools: [] }),
108
- );
109
- expect(maybeRefreshSkillCapabilityMemoriesFromMtime()).toBe(false);
110
- expect(seedGraphCalls).toHaveLength(1);
111
- });
112
-
113
- test("adding or removing a skill directory reseeds", () => {
114
- writeSkill("alpha");
115
- expect(maybeRefreshSkillCapabilityMemoriesFromMtime()).toBe(true);
116
-
117
- writeSkill("bravo");
118
- expect(maybeRefreshSkillCapabilityMemoriesFromMtime()).toBe(true);
119
-
120
- rmSync(join(SKILLS_DIR, "bravo"), { recursive: true, force: true });
121
- expect(maybeRefreshSkillCapabilityMemoriesFromMtime()).toBe(true);
122
- expect(seedGraphCalls).toHaveLength(3);
123
- });
124
-
125
- test("startWorkspaceSkillMdMtimePoll runs once immediately and is idempotent", () => {
126
- writeSkill("alpha");
127
- startWorkspaceSkillMdMtimePoll();
128
- expect(seedGraphCalls).toHaveLength(1);
129
- startWorkspaceSkillMdMtimePoll();
130
- expect(seedGraphCalls).toHaveLength(1);
131
- stopWorkspaceSkillMdMtimePoll();
132
- });
133
- });
@@ -1,45 +0,0 @@
1
- /**
2
- * Fan out an app change to open conversation surfaces, connected clients,
3
- * and the publish pipeline.
4
- *
5
- * Compilation is the caller's responsibility. This module only notifies:
6
- * it must not call `compileApp()` because that begins with `rm -rf dist/`
7
- * and would race a compile already in flight.
8
- */
9
-
10
- import { broadcastMessage } from "../runtime/assistant-event-hub.js";
11
- import { publishAppsChanged } from "../runtime/sync/resource-sync-events.js";
12
- import { updatePublishedAppDeployment } from "../services/published-app-updater.js";
13
- import type { Conversation } from "./conversation.js";
14
- import { allConversations } from "./conversation-registry.js";
15
- import { refreshSurfacesForApp } from "./conversation-surfaces.js";
16
-
17
- export function broadcastAppFilesChanged(appId: string): void {
18
- broadcastMessage({ type: "app_files_changed", appId });
19
- publishAppsChanged();
20
- }
21
-
22
- /**
23
- * Refresh every in-memory conversation that has this app open, then broadcast
24
- * and re-deploy. Pass `alsoRefresh` when the calling conversation might not
25
- * yet be in the registry (tool post-execution hooks).
26
- */
27
- export function notifyAppSurfacesChanged(
28
- appId: string,
29
- opts?: { fileChange?: boolean; status?: string },
30
- alsoRefresh?: Conversation,
31
- ): void {
32
- const seen = new Set<string>();
33
- if (alsoRefresh) {
34
- refreshSurfacesForApp(alsoRefresh, appId, opts);
35
- seen.add(alsoRefresh.conversationId);
36
- }
37
- for (const conversation of allConversations()) {
38
- if (seen.has(conversation.conversationId)) {
39
- continue;
40
- }
41
- refreshSurfacesForApp(conversation, appId, opts);
42
- }
43
- broadcastAppFilesChanged(appId);
44
- void updatePublishedAppDeployment(appId);
45
- }
@@ -1,119 +0,0 @@
1
- import { join } from "node:path";
2
-
3
- import { sleep } from "../../util/retry.js";
4
- import {
5
- type DesktopChild,
6
- type DesktopChildRole,
7
- type DesktopLoss,
8
- DesktopSessionManager,
9
- type DesktopSpawnRequest,
10
- } from "../desktop-session-manager.js";
11
-
12
- /** A child the test exits by hand. */
13
- class FakeChild implements DesktopChild {
14
- private static nextPid = 1000;
15
- readonly pid = FakeChild.nextPid++;
16
- readonly exited: Promise<number>;
17
- private settle!: (code: number) => void;
18
-
19
- constructor(
20
- readonly role: DesktopChildRole,
21
- readonly request: DesktopSpawnRequest,
22
- ) {
23
- this.exited = new Promise((resolve) => {
24
- this.settle = resolve;
25
- });
26
- }
27
-
28
- kill(): void {}
29
-
30
- exit(code = 0): void {
31
- this.settle(code);
32
- }
33
- }
34
-
35
- export const LINGER_MS = 20;
36
- export const KILL_GRACE_MS = 20;
37
-
38
- export interface FakeDesktopOptions {
39
- profileDir: string;
40
- /** Defaults inside `profileDir`, for tests that ignore the dock's config. */
41
- panelConfigDir?: string;
42
- /** Roles whose spawn throws, to exercise a start that fails partway. */
43
- failSpawn?: DesktopChildRole[];
44
- /** Binaries `which` cannot find. */
45
- missingBinaries?: string[];
46
- /** Whether a SIGTERM makes the fake child exit on its own. */
47
- exitOnTerm?: boolean;
48
- /** Whether a SIGKILL does; without either the child survives both. */
49
- exitOnKill?: boolean;
50
- sourceEnv?: NodeJS.ProcessEnv;
51
- renderWallpaper?: (width: number, height: number) => Promise<Buffer | null>;
52
- }
53
-
54
- export function newFakeDesktop(options: FakeDesktopOptions) {
55
- const spawned: FakeChild[] = [];
56
- const killed: { child: FakeChild; signal: string }[] = [];
57
- let vncReady = true;
58
- let chromiumPath: () => Promise<string> = async () => "/fake/chromium";
59
- const manager = new DesktopSessionManager({
60
- spawn: (role, request) => {
61
- if (options.failSpawn?.includes(role)) {
62
- throw new Error(`spawn ${role} failed`);
63
- }
64
- const child = new FakeChild(role, request);
65
- spawned.push(child);
66
- return child;
67
- },
68
- which: (binary) =>
69
- options.missingBinaries?.includes(binary) ? null : `/usr/bin/${binary}`,
70
- probeVncPort: async () => vncReady,
71
- resolveChromePath: () => chromiumPath(),
72
- renderWallpaper: options.renderWallpaper ?? (async () => null),
73
- killProcessGroup: (child, signal) => {
74
- killed.push({ child: child as FakeChild, signal });
75
- const exits =
76
- signal === "SIGTERM" ? options.exitOnTerm : options.exitOnKill;
77
- if (exits) {
78
- (child as FakeChild).exit(0);
79
- }
80
- },
81
- lingerMs: LINGER_MS,
82
- readyDeadlineMs: 30,
83
- killGraceMs: KILL_GRACE_MS,
84
- profileDir: options.profileDir,
85
- panelConfigDir:
86
- options.panelConfigDir ?? join(options.profileDir, "desktop-panel"),
87
- sourceEnv: options.sourceEnv,
88
- });
89
- return {
90
- manager,
91
- spawned,
92
- killed,
93
- /** Children that got a SIGTERM, in order. */
94
- terminated: () =>
95
- killed.filter((k) => k.signal === "SIGTERM").map((k) => k.child),
96
- setVncReady: (ready: boolean) => {
97
- vncReady = ready;
98
- },
99
- setChromiumPath: (resolve: () => Promise<string>) => {
100
- chromiumPath = resolve;
101
- },
102
- child: (role: DesktopChildRole) =>
103
- spawned.filter((c) => c.role === role).at(-1)!,
104
- roles: () => spawned.map((c) => c.role),
105
- count: (role: DesktopChildRole) =>
106
- spawned.filter((c) => c.role === role).length,
107
- };
108
- }
109
-
110
- /** Let one awaited step (a path resolution, an exit callback) land. */
111
- export const settle = (): Promise<void> => sleep(0);
112
-
113
- export function newViewer() {
114
- const lost: DesktopLoss[] = [];
115
- return {
116
- lost,
117
- viewer: { onDesktopLost: (loss: DesktopLoss) => lost.push(loss) },
118
- };
119
- }
@@ -1,71 +0,0 @@
1
- import {
2
- mkdtempSync,
3
- readdirSync,
4
- readFileSync,
5
- rmSync,
6
- statSync,
7
- writeFileSync,
8
- } from "node:fs";
9
- import { tmpdir } from "node:os";
10
- import { join } from "node:path";
11
- import { afterEach, expect, test } from "bun:test";
12
-
13
- import { writeDesktopChromePolicy } from "./desktop-chrome-policy.js";
14
-
15
- const directories: string[] = [];
16
- function policyDirectory(): string {
17
- const path = mkdtempSync(join(tmpdir(), "desktop-chrome-policy-"));
18
- directories.push(path);
19
- return path;
20
- }
21
-
22
- afterEach(() => {
23
- for (const path of directories.splice(0)) {
24
- rmSync(path, { recursive: true, force: true });
25
- }
26
- });
27
-
28
- test("preserves unrelated policies and does not rewrite on repeated startup", () => {
29
- const directory = policyDirectory();
30
- const path = join(directory, "vellum-desktop.json");
31
- const otherPath = join(directory, "organization.json");
32
- const unrelated = '{ "HomepageLocation": "https://example.com" }\n';
33
- writeFileSync(otherPath, unrelated);
34
- writeFileSync(path, JSON.stringify({ DownloadRestrictions: 1 }));
35
-
36
- writeDesktopChromePolicy(directory);
37
- const content = readFileSync(path, "utf8");
38
- expect(JSON.parse(content).DownloadRestrictions).toBe(1);
39
- expect(readFileSync(otherPath, "utf8")).toBe(unrelated);
40
- expect(readdirSync(directory).sort()).toEqual([
41
- "organization.json",
42
- "vellum-desktop.json",
43
- ]);
44
-
45
- const before = statSync(path);
46
- writeDesktopChromePolicy(directory);
47
- expect(readFileSync(path, "utf8")).toBe(content);
48
- expect(statSync(path).ino).toBe(before.ino);
49
- expect(statSync(path).mtimeMs).toBe(before.mtimeMs);
50
- });
51
-
52
- test("creates missing policy directories for a fresh desktop", () => {
53
- const directory = join(policyDirectory(), "policies", "managed");
54
- writeDesktopChromePolicy(directory);
55
- expect(readdirSync(directory)).toEqual(["vellum-desktop.json"]);
56
- expect(statSync(join(directory, "vellum-desktop.json")).mode & 0o777).toBe(
57
- 0o644,
58
- );
59
- });
60
-
61
- test.each(["{broken", "[]", "null", "false"])(
62
- "leaves invalid existing policy content untouched: %s",
63
- (content) => {
64
- const directory = policyDirectory();
65
- const path = join(directory, "vellum-desktop.json");
66
- writeFileSync(path, content);
67
- expect(() => writeDesktopChromePolicy(directory)).toThrow();
68
- expect(readFileSync(path, "utf8")).toBe(content);
69
- expect(readdirSync(directory)).toEqual(["vellum-desktop.json"]);
70
- },
71
- );