@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
@@ -17,10 +17,6 @@ import { getLogger } from "../util/logger.js";
17
17
  import { Mutex } from "../util/mutex.js";
18
18
  import { addToPathEnv, getExtraToolPathDirs } from "../util/platform.js";
19
19
  import { PromiseGuard } from "../util/promise-guard.js";
20
- import {
21
- collectDirtyPathsFromPorcelain,
22
- parsePorcelainZ,
23
- } from "./git-porcelain.js";
24
20
 
25
21
  const execFileAsync = promisify(execFile);
26
22
  const log = getLogger("workspace-git");
@@ -230,6 +226,59 @@ done
230
226
  exit 0
231
227
  `;
232
228
 
229
+ /**
230
+ * Parse NUL-terminated `git status --porcelain -z` output into status/path
231
+ * pairs. NUL termination is required so paths with special characters
232
+ * (non-ASCII, quotes, newlines) arrive verbatim instead of C-style quoted.
233
+ * A rename/copy record is followed by a bare origin-path entry, which is
234
+ * skipped.
235
+ */
236
+ function parsePorcelainZ(
237
+ stdout: string,
238
+ ): Array<{ status: string; path: string }> {
239
+ const entries = stdout.split("\0");
240
+ const parsed: Array<{ status: string; path: string }> = [];
241
+ for (let i = 0; i < entries.length; i++) {
242
+ const entry = entries[i] ?? "";
243
+ if (entry.length < 4) {
244
+ continue;
245
+ }
246
+ const status = entry.substring(0, 2);
247
+ parsed.push({ status, path: entry.substring(3) });
248
+ if (status[0] === "R" || status[0] === "C") {
249
+ i++;
250
+ }
251
+ }
252
+ return parsed;
253
+ }
254
+
255
+ /**
256
+ * Every path git status knows about, including rename/copy origins.
257
+ * Origins are skipped by {@link parsePorcelainZ} (they have no status
258
+ * prefix) but still need to be staged so a deletion is not left behind
259
+ * when a rename is split across add batches.
260
+ */
261
+ function collectDirtyPathsFromPorcelain(stdout: string): string[] {
262
+ const entries = stdout.split("\0");
263
+ const paths: string[] = [];
264
+ for (let i = 0; i < entries.length; i++) {
265
+ const entry = entries[i] ?? "";
266
+ if (entry.length < 4) {
267
+ continue;
268
+ }
269
+ const status = entry.substring(0, 2);
270
+ paths.push(entry.substring(3));
271
+ if (status[0] === "R" || status[0] === "C") {
272
+ i++;
273
+ const origin = entries[i];
274
+ if (origin && origin.length > 0) {
275
+ paths.push(origin);
276
+ }
277
+ }
278
+ }
279
+ return paths;
280
+ }
281
+
233
282
  /** Properties added by Node's child_process errors. */
234
283
  interface ExecError extends Error {
235
284
  killed?: boolean;
@@ -384,7 +433,7 @@ export class WorkspaceGitService {
384
433
  *
385
434
  * This method is always called inside the mutex, so no git operation from
386
435
  * our code can be concurrently holding the lock. However, an external git
387
- * git process (user running `git add`, IDE tooling, etc.) could legitimately
436
+ * process (user running `git add`, IDE tooling, etc.) could legitimately
388
437
  * hold the lock. We use `lsof` to check — if any process has the file
389
438
  * open, we leave it alone. If no process holds it, it's stale (crashed
390
439
  * process) and safe to remove.
@@ -151,9 +151,6 @@ import { sttFluxProviderToModelFamilyMigration } from "./150-stt-flux-provider-t
151
151
  import { repairRenamedFireworksDeepseekProModelIdMigration } from "./151-repair-renamed-fireworks-deepseek-pro-model-id.js";
152
152
  import { repairRetiredFireworksMinimaxM2p7ModelIdMigration } from "./152-repair-retired-fireworks-minimax-m2p7-model-id.js";
153
153
  import { stripMcpPolicyFieldsMigration } from "./153-strip-mcp-policy-fields.js";
154
- import { repairRetiredCodexGpt54ModelIdsMigration } from "./154-repair-retired-codex-gpt-5-4-model-ids.js";
155
- import { moveFrontModelConfigToVoiceMigration } from "./155-move-front-model-config-to-voice.js";
156
- import { extractWorkspaceMcpJsonMigration } from "./156-extract-workspace-mcp-json.js";
157
154
  import { migrateToWorkspaceVolumeMigration } from "./migrate-to-workspace-volume.js";
158
155
  import type { WorkspaceMigration } from "./types.js";
159
156
 
@@ -320,7 +317,4 @@ export const WORKSPACE_MIGRATIONS: WorkspaceMigration[] = [
320
317
  repairRenamedFireworksDeepseekProModelIdMigration,
321
318
  repairRetiredFireworksMinimaxM2p7ModelIdMigration,
322
319
  stripMcpPolicyFieldsMigration,
323
- repairRetiredCodexGpt54ModelIdsMigration,
324
- moveFrontModelConfigToVoiceMigration,
325
- extractWorkspaceMcpJsonMigration,
326
320
  ];
@@ -1,186 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
-
6
- import { writeDesktopWindowTheme } from "../src/desktop/desktop-window-theme.js";
7
-
8
- if (process.platform !== "linux") {
9
- throw new Error(
10
- "Run in a disposable Linux environment with Xvfb, Openbox, xterm, xdotool, xwininfo and xmllint installed",
11
- );
12
- }
13
-
14
- const directory = await mkdtemp(join(tmpdir(), "window-theme-smoke-"));
15
- const env = { ...process.env, DISPLAY: ":97" };
16
- const children: ReturnType<typeof Bun.spawn>[] = [];
17
- const start = (cmd: string[]) => {
18
- const child = Bun.spawn(cmd, {
19
- env,
20
- stdout: "ignore",
21
- stderr: "inherit",
22
- windowsHide: true,
23
- });
24
- children.push(child);
25
- return child;
26
- };
27
- const run = (...cmd: string[]) => {
28
- const result = Bun.spawnSync(cmd, {
29
- env,
30
-
31
- windowsHide: true,
32
- });
33
- assert.equal(result.exitCode, 0, result.stderr.toString());
34
- return result.stdout.toString();
35
- };
36
- const waitFor = async (predicate: () => boolean) => {
37
- for (let attempt = 0; attempt < 100; attempt++) {
38
- try {
39
- if (predicate()) {
40
- return;
41
- }
42
- } catch {}
43
- await Bun.sleep(50);
44
- }
45
- throw new Error("Window theme smoke condition timed out");
46
- };
47
- const pointer = async (...args: string[]) => {
48
- run("xdotool", ...args);
49
- await Bun.sleep(200);
50
- };
51
- const geometry = () => {
52
- const info = run("xwininfo", "-name", "Theme smoke");
53
- return [
54
- "Absolute upper-left X",
55
- "Absolute upper-left Y",
56
- "Width",
57
- "Height",
58
- ].map((label) =>
59
- Number(new RegExp(`${label}:\\s+(-?\\d+)`).exec(info)?.[1]),
60
- ) as [number, number, number, number];
61
- };
62
- const state = () => run("xprop", "-name", "Theme smoke", "_NET_WM_STATE");
63
- const button = async (offset: number) => {
64
- const [x, y, width] = geometry();
65
- await pointer(
66
- "mousemove",
67
- String(x + width - offset),
68
- String(y - 16),
69
- "click",
70
- "1",
71
- );
72
- };
73
-
74
- try {
75
- const home = join(directory, "home");
76
- const sourceDir = join(home, ".config", "openbox");
77
- await mkdir(sourceDir, { recursive: true });
78
- const original = await readFile("/etc/xdg/openbox/rc.xml", "utf8");
79
- const mouse = original.match(/<mouse>[^]*?<\/mouse>/)![0];
80
- const keyboard = original.match(/<keyboard>[^]*?<\/keyboard>/)![0];
81
- const source = original
82
- .replace(
83
- mouse,
84
- `<xi:include href="bindings.xml" xpointer="xpointer(/*/*)"/>`,
85
- )
86
- .replace(keyboard, "");
87
- const sourcePath = join(sourceDir, "rc.xml");
88
- await writeFile(sourcePath, source);
89
- await writeFile(
90
- join(sourceDir, "bindings.xml"),
91
- `<bindings xmlns="http://openbox.org/3.4/rc">${mouse}${keyboard}</bindings>`,
92
- );
93
- const configDir = join(directory, "managed & theme");
94
- const config = writeDesktopWindowTheme(configDir, home, "#53b7aa");
95
- const expanded = run("xmllint", "--xinclude", config);
96
- assert(
97
- expanded.includes("NextWindow") && expanded.includes("Move"),
98
- "Relative includes must retain the actual keyboard and mouse bindings",
99
- );
100
- assert.equal(await readFile(sourcePath, "utf8"), source);
101
- writeDesktopWindowTheme(configDir, home, "#bc7799");
102
- writeDesktopWindowTheme(configDir, home, "#53b7aa");
103
- assert.equal(await readFile(sourcePath, "utf8"), source);
104
- const blocked = join(directory, "blocked");
105
- await writeFile(blocked, "not a directory");
106
- assert.throws(() => writeDesktopWindowTheme(blocked, home));
107
- assert.equal(await readFile(sourcePath, "utf8"), source);
108
- const customBase = source.replace(
109
- "<openbox_config",
110
- '<openbox_config xml:base="./custom/"',
111
- );
112
- await writeFile(sourcePath, customBase);
113
- assert.throws(() => writeDesktopWindowTheme(configDir, home));
114
- assert.equal(await readFile(sourcePath, "utf8"), customBase);
115
- await writeFile(sourcePath, source);
116
-
117
- start(["Xvfb", ":97", "-screen", "0", "1100x700x24"]);
118
- await waitFor(
119
- () => run("xdotool", "getdisplaygeometry").trim() === "1100 700",
120
- );
121
- start(["openbox", "--config-file", config]);
122
- await waitFor(() =>
123
- run("xprop", "-root", "_OB_THEME").includes("window-theme"),
124
- );
125
- start([
126
- "xterm",
127
- "-title",
128
- "Theme smoke",
129
- "-geometry",
130
- "48x12+450+250",
131
- "-e",
132
- "sleep",
133
- "60",
134
- ]);
135
- await waitFor(
136
- () => run("xdotool", "search", "--name", "^Theme smoke$").trim().length > 0,
137
- );
138
- await Bun.sleep(300);
139
- const id = run("xdotool", "search", "--name", "^Theme smoke$").trim();
140
- await button(39);
141
- assert(
142
- state().includes("MAXIMIZED_HORZ") && state().includes("MAXIMIZED_VERT"),
143
- );
144
- await button(39);
145
- assert(!state().includes("MAXIMIZED"));
146
- await button(62);
147
- assert(state().includes("HIDDEN"));
148
- await pointer("windowactivate", id);
149
- assert(!state().includes("HIDDEN"));
150
- let [x, y, width, height] = geometry();
151
- await pointer("mousemove", String(x + 100), String(y - 16), "mousedown", "1");
152
- await pointer("mousemove", String(x + 90), String(y - 26));
153
- await pointer("mousemove", String(x + 45), String(y - 65));
154
- await pointer("mouseup", "1");
155
- const [movedX, movedY] = geometry();
156
- assert(Math.abs(movedX - x) >= 30 && Math.abs(movedY - y) >= 30);
157
- [x, y, width, height] = geometry();
158
- await pointer(
159
- "mousemove",
160
- String(x + width - 2),
161
- String(y + height + 2),
162
- "mousedown",
163
- "1",
164
- );
165
- await pointer("mousemove", String(x + width + 10), String(y + height + 10));
166
- await pointer("mousemove", String(x + width + 60), String(y + height + 40));
167
- await pointer("mouseup", "1");
168
- const [, , resizedWidth, resizedHeight] = geometry();
169
- assert(resizedWidth > width && resizedHeight > height);
170
- await pointer("key", "alt+F4");
171
- await waitFor(
172
- () =>
173
- !run("xprop", "-root", "_NET_CLIENT_LIST").includes(
174
- `0x${Number(id).toString(16)}`,
175
- ),
176
- );
177
- console.log(
178
- "PASS: relative includes, preserved source, repeated theme updates, maximize/restore, minimize/activation, dragging, resizing, and keyboard close",
179
- );
180
- } finally {
181
- for (const child of children.reverse()) {
182
- child.kill();
183
- }
184
- await Promise.all(children.map((child) => child.exited));
185
- await rm(directory, { recursive: true, force: true });
186
- }
@@ -1,47 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
-
3
- import {
4
- collectDirtyPathsFromPorcelain,
5
- parsePorcelainZ,
6
- } from "../workspace/git-porcelain.js";
7
-
8
- describe("parsePorcelainZ", () => {
9
- test("parses ordinary modified and untracked records", () => {
10
- expect(parsePorcelainZ("M tracked.txt\0?? new.txt\0")).toEqual([
11
- { status: "M ", path: "tracked.txt" },
12
- { status: "??", path: "new.txt" },
13
- ]);
14
- });
15
-
16
- test("captures rename origin on the same record", () => {
17
- expect(parsePorcelainZ("R dest.txt\0src.txt\0")).toEqual([
18
- { status: "R ", path: "dest.txt", origin: "src.txt" },
19
- ]);
20
- });
21
-
22
- test("captures copy origin on the same record", () => {
23
- expect(parsePorcelainZ("C dest.txt\0src.txt\0")).toEqual([
24
- { status: "C ", path: "dest.txt", origin: "src.txt" },
25
- ]);
26
- });
27
-
28
- test("skips short leftover NUL entries", () => {
29
- expect(parsePorcelainZ("M a.txt\0\0")).toEqual([
30
- { status: "M ", path: "a.txt" },
31
- ]);
32
- });
33
- });
34
-
35
- describe("collectDirtyPathsFromPorcelain", () => {
36
- test("flattens rename origin so both paths are staged", () => {
37
- expect(
38
- collectDirtyPathsFromPorcelain("R dest.txt\0src.txt\0?? extra.txt\0"),
39
- ).toEqual(["dest.txt", "src.txt", "extra.txt"]);
40
- });
41
-
42
- test("dedupes a path that appears as both origin and destination", () => {
43
- expect(collectDirtyPathsFromPorcelain("R same.txt\0same.txt\0")).toEqual([
44
- "same.txt",
45
- ]);
46
- });
47
- });
@@ -1,11 +0,0 @@
1
- /**
2
- * Seed `$VELLUM_WORKSPACE_DIR/mcp.json` for tests that go through the
3
- * real workspace MCP loader.
4
- */
5
-
6
- import type { McpConfig } from "../../config/schemas/mcp.js";
7
- import { saveWorkspaceMcpConfig } from "../../mcp/workspace-mcp-config.js";
8
-
9
- export function setWorkspaceMcp(servers: McpConfig["servers"]): void {
10
- saveWorkspaceMcpConfig({ servers });
11
- }
@@ -1,119 +0,0 @@
1
- /**
2
- * The `message-deleted` hook is dispatched by every primitive that removes
3
- * individual message rows, carrying each row's `(createdAt, id)`, so a plugin
4
- * keeping a cursor on a row learns where it sat once the row is gone.
5
- * DB-backed: exercises the real delete primitives against the test database.
6
- */
7
- import { beforeEach, describe, expect, test } from "bun:test";
8
-
9
- import { registerPluginHooks } from "../hooks/registry.js";
10
- import type { MessageDeletedContext } from "../hooks/types.js";
11
- import {
12
- addMessage,
13
- deleteLastExchange,
14
- deleteMessageById,
15
- getMessages,
16
- } from "../persistence/conversation-crud.js";
17
- import { getDb } from "../persistence/db-connection.js";
18
- import { initializeDb } from "../persistence/db-init.js";
19
- import { conversations, messages } from "../persistence/schema/index.js";
20
- import type { PluginHooks } from "../plugins/types.js";
21
-
22
- await initializeDb();
23
-
24
- const CONV_ID = "conv-message-deleted-hook";
25
-
26
- const received: Array<{
27
- conversationId: string;
28
- messageId: string;
29
- createdAt: number;
30
- }> = [];
31
- registerPluginHooks("test-message-deleted-spy", {
32
- "message-deleted": async (ctx: MessageDeletedContext) => {
33
- received.push({
34
- conversationId: ctx.conversationId,
35
- messageId: ctx.messageId,
36
- createdAt: ctx.createdAt,
37
- });
38
- },
39
- } as PluginHooks);
40
-
41
- /** Poll until the fire-and-forget hook chain has delivered `count` calls. */
42
- async function waitForCalls(count: number): Promise<void> {
43
- const deadline = Date.now() + 2_000;
44
- while (received.length < count && Date.now() < deadline) {
45
- await Bun.sleep(10);
46
- }
47
- }
48
-
49
- const text = (t: string) => JSON.stringify([{ type: "text", text: t }]);
50
-
51
- beforeEach(() => {
52
- received.length = 0;
53
- getDb().delete(messages).run();
54
- getDb().delete(conversations).run();
55
- const now = Date.now();
56
- getDb()
57
- .insert(conversations)
58
- .values({
59
- id: CONV_ID,
60
- title: "message-deleted hook",
61
- createdAt: now,
62
- updatedAt: now,
63
- source: "test",
64
- conversationType: "standard",
65
- })
66
- .run();
67
- });
68
-
69
- describe("message-deleted hook dispatch", () => {
70
- test("deleteMessageById dispatches once with the row's position", async () => {
71
- await addMessage(CONV_ID, "user", text("hello"));
72
- const reply = await addMessage(CONV_ID, "assistant", text("hi"));
73
- const replyCreatedAt = getMessages(CONV_ID).find(
74
- (m) => m.id === reply.id,
75
- )!.createdAt;
76
-
77
- deleteMessageById(reply.id);
78
- await waitForCalls(1);
79
-
80
- expect(received).toEqual([
81
- {
82
- conversationId: CONV_ID,
83
- messageId: reply.id,
84
- createdAt: replyCreatedAt,
85
- },
86
- ]);
87
- });
88
-
89
- test("deleteLastExchange dispatches for every row of the undone tail", async () => {
90
- await addMessage(CONV_ID, "user", text("first"));
91
- await addMessage(CONV_ID, "assistant", text("one"));
92
- const user2 = await addMessage(CONV_ID, "user", text("second"));
93
- const reply2 = await addMessage(CONV_ID, "assistant", text("two"));
94
- const byId = new Map(getMessages(CONV_ID).map((m) => [m.id, m.createdAt]));
95
-
96
- expect(deleteLastExchange(CONV_ID)).toBe(2);
97
- await waitForCalls(2);
98
-
99
- expect([...received].sort((a, b) => a.createdAt - b.createdAt)).toEqual([
100
- {
101
- conversationId: CONV_ID,
102
- messageId: user2.id,
103
- createdAt: byId.get(user2.id)!,
104
- },
105
- {
106
- conversationId: CONV_ID,
107
- messageId: reply2.id,
108
- createdAt: byId.get(reply2.id)!,
109
- },
110
- ]);
111
- });
112
-
113
- test("a delete of a missing row dispatches nothing", async () => {
114
- deleteMessageById("no-such-row");
115
- await Bun.sleep(50);
116
-
117
- expect(received).toEqual([]);
118
- });
119
- });
@@ -1,135 +0,0 @@
1
- /**
2
- * Tests for resolving an app query by name, slug, or id.
3
- */
4
-
5
- import { mkdirSync, rmSync, writeFileSync } from "node:fs";
6
- import { tmpdir } from "node:os";
7
- import { join } from "node:path";
8
- import { afterEach, beforeEach, describe, expect, test } from "bun:test";
9
-
10
- import { createApp } from "../apps/app-store.js";
11
- import { resolveAppQuery } from "../apps/resolve-app.js";
12
- import { getWorkspacePluginsDir } from "../util/platform.js";
13
-
14
- let workspaceDir: string;
15
- let previousWorkspaceDir: string | undefined;
16
-
17
- function freshWorkspace(): string {
18
- return join(
19
- tmpdir(),
20
- `vellum-resolve-app-${Date.now()}-${Math.random().toString(36).slice(2)}`,
21
- );
22
- }
23
-
24
- function installPlugin(name: string): string {
25
- const pluginDir = join(getWorkspacePluginsDir(), name);
26
- mkdirSync(pluginDir, { recursive: true });
27
- writeFileSync(
28
- join(pluginDir, "package.json"),
29
- JSON.stringify({ name, version: "1.0.0" }),
30
- );
31
- return pluginDir;
32
- }
33
-
34
- function bundleApp(pluginDir: string, app: string): void {
35
- const appDir = join(pluginDir, "apps", app);
36
- mkdirSync(appDir, { recursive: true });
37
- writeFileSync(join(appDir, "index.html"), "<h1>Plugin app</h1>");
38
- }
39
-
40
- beforeEach(() => {
41
- previousWorkspaceDir = process.env.VELLUM_WORKSPACE_DIR;
42
- workspaceDir = freshWorkspace();
43
- process.env.VELLUM_WORKSPACE_DIR = workspaceDir;
44
- });
45
-
46
- afterEach(() => {
47
- rmSync(workspaceDir, { recursive: true, force: true });
48
- if (previousWorkspaceDir === undefined) {
49
- delete process.env.VELLUM_WORKSPACE_DIR;
50
- } else {
51
- process.env.VELLUM_WORKSPACE_DIR = previousWorkspaceDir;
52
- }
53
- });
54
-
55
- describe("resolveAppQuery", () => {
56
- test("resolves a workspace app by display name, slug, and id", () => {
57
- const created = createApp({
58
- name: "Budget",
59
- schemaJson: "{}",
60
- htmlDefinition: "<h1>Budget</h1>",
61
- });
62
-
63
- const byName = resolveAppQuery("Budget");
64
- expect(byName.ok).toBe(true);
65
- if (byName.ok) {
66
- expect(byName.app.id).toBe(created.id);
67
- }
68
-
69
- const byNameCase = resolveAppQuery("budget");
70
- expect(byNameCase.ok).toBe(true);
71
- if (byNameCase.ok) {
72
- expect(byNameCase.app.id).toBe(created.id);
73
- }
74
-
75
- const slug = created.dirName ?? "";
76
- expect(slug.length).toBeGreaterThan(0);
77
- const bySlug = resolveAppQuery(slug);
78
- expect(bySlug.ok).toBe(true);
79
- if (bySlug.ok) {
80
- expect(bySlug.app.id).toBe(created.id);
81
- }
82
-
83
- const byId = resolveAppQuery(created.id);
84
- expect(byId.ok).toBe(true);
85
- if (byId.ok) {
86
- expect(byId.app.id).toBe(created.id);
87
- }
88
- });
89
-
90
- test("returns not_found for an unknown name", () => {
91
- const result = resolveAppQuery("missing");
92
- expect(result).toEqual({
93
- ok: false,
94
- reason: "not_found",
95
- query: "missing",
96
- });
97
- });
98
-
99
- test("returns ambiguous when two apps share a display name", () => {
100
- const first = createApp({
101
- name: "Notes",
102
- schemaJson: "{}",
103
- htmlDefinition: "<h1>One</h1>",
104
- });
105
- const second = createApp({
106
- name: "Notes",
107
- schemaJson: "{}",
108
- htmlDefinition: "<h1>Two</h1>",
109
- });
110
-
111
- const result = resolveAppQuery("Notes");
112
- expect(result.ok).toBe(false);
113
- if (!result.ok && result.reason === "ambiguous") {
114
- const ids = result.matches.map((m) => m.id).sort();
115
- expect(ids).toEqual([first.id, second.id].sort());
116
- } else {
117
- throw new Error("expected ambiguous resolution");
118
- }
119
- });
120
-
121
- test("resolves a plugin app by directory name", () => {
122
- const pluginDir = installPlugin("charts");
123
- bundleApp(pluginDir, "viewer");
124
-
125
- const result = resolveAppQuery("viewer");
126
- expect(result.ok).toBe(true);
127
- if (result.ok) {
128
- expect(result.app.origin).toEqual({
129
- kind: "plugin",
130
- pluginName: "charts",
131
- });
132
- expect(result.app.id).toBe("plugins~charts~viewer");
133
- }
134
- });
135
- });