@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,245 +0,0 @@
1
- /**
2
- * Tests for `assistant apps inspect` and `assistant apps refresh`.
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, mock, test } from "bun:test";
9
-
10
- import { createApp, getAppDirPath } from "../../../apps/app-store.js";
11
- import { writeAppSourceFingerprint } from "../../../apps/source-fingerprint.js";
12
- import { getWorkspacePluginsDir } from "../../../util/platform.js";
13
- import { runCliCommand } from "./cli-test-harness.js";
14
-
15
- let lastIpcCall: {
16
- method: string;
17
- params?: Record<string, unknown>;
18
- } | null = null;
19
-
20
- let mockIpcResult: {
21
- ok: boolean;
22
- result?: unknown;
23
- error?: string;
24
- statusCode?: number;
25
- } = { ok: true, result: { ok: true, compiled: true } };
26
-
27
- mock.module("../../../ipc/cli-client.js", () => ({
28
- cliIpcCall: async (method: string, params?: Record<string, unknown>) => {
29
- lastIpcCall = { method, params };
30
- return mockIpcResult;
31
- },
32
- exitCodeFromIpcResult: (r: { statusCode?: number }) => {
33
- if (r.statusCode === undefined) {
34
- return 10;
35
- }
36
- if (r.statusCode >= 500) {
37
- return 3;
38
- }
39
- if (r.statusCode >= 400) {
40
- return 2;
41
- }
42
- return 1;
43
- },
44
- }));
45
-
46
- const { registerAppsCommand } = await import("../apps.js");
47
-
48
- let workspaceDir: string;
49
- let previousWorkspaceDir: string | undefined;
50
-
51
- function freshWorkspace(): string {
52
- return join(
53
- tmpdir(),
54
- `vellum-apps-cli-${Date.now()}-${Math.random().toString(36).slice(2)}`,
55
- );
56
- }
57
-
58
- function uniqueAppName(prefix: string): string {
59
- return `${prefix} ${Math.random().toString(36).slice(2, 8)}`;
60
- }
61
-
62
- beforeEach(() => {
63
- previousWorkspaceDir = process.env.VELLUM_WORKSPACE_DIR;
64
- workspaceDir = freshWorkspace();
65
- process.env.VELLUM_WORKSPACE_DIR = workspaceDir;
66
- lastIpcCall = null;
67
- mockIpcResult = {
68
- ok: true,
69
- result: {
70
- ok: true,
71
- appId: "app-1",
72
- name: "Budget",
73
- compiled: true,
74
- compile_duration_ms: 12,
75
- },
76
- };
77
- });
78
-
79
- afterEach(() => {
80
- rmSync(workspaceDir, { recursive: true, force: true });
81
- if (previousWorkspaceDir === undefined) {
82
- delete process.env.VELLUM_WORKSPACE_DIR;
83
- } else {
84
- process.env.VELLUM_WORKSPACE_DIR = previousWorkspaceDir;
85
- }
86
- });
87
-
88
- function parseJson(stdout: string): Record<string, unknown> {
89
- return JSON.parse(stdout.trim()) as Record<string, unknown>;
90
- }
91
-
92
- describe("assistant apps inspect", () => {
93
- test("reports never_compiled for a new workspace app", async () => {
94
- const name = uniqueAppName("Inspect Fresh");
95
- const created = createApp({
96
- name,
97
- schemaJson: "{}",
98
- htmlDefinition: "<h1>Budget</h1>",
99
- });
100
-
101
- const result = await runCliCommand(registerAppsCommand, [
102
- "apps",
103
- "inspect",
104
- created.id,
105
- "--json",
106
- ]);
107
-
108
- expect(result.exitCode).toBe(0);
109
- const body = parseJson(result.stdout);
110
- expect(body.ok).toBe(true);
111
- const compile = body.compile as { status: string };
112
- expect(compile.status).toBe("never_compiled");
113
- });
114
-
115
- test("reports stale after source changes since the last fingerprint", async () => {
116
- const name = uniqueAppName("Inspect Stale");
117
- const created = createApp({
118
- name,
119
- schemaJson: "{}",
120
- htmlDefinition: "<h1>Budget</h1>",
121
- });
122
- const appDir = getAppDirPath(created.id);
123
- expect(appDir.length).toBeGreaterThan(0);
124
- mkdirSync(join(appDir, "src"), { recursive: true });
125
- writeFileSync(join(appDir, "src", "main.tsx"), "export const n = 1;\n");
126
- mkdirSync(join(appDir, "dist"), { recursive: true });
127
- writeFileSync(join(appDir, "dist", "index.html"), "<html></html>");
128
- writeAppSourceFingerprint(appDir, join(appDir, "dist"));
129
- writeFileSync(join(appDir, "src", "main.tsx"), "export const n = 2;\n");
130
-
131
- const result = await runCliCommand(registerAppsCommand, [
132
- "apps",
133
- "inspect",
134
- created.id,
135
- "--json",
136
- ]);
137
-
138
- expect(result.exitCode).toBe(0);
139
- const body = parseJson(result.stdout);
140
- const app = body.app as { id: string; source: string };
141
- expect(app.id).toBe(created.id);
142
- expect(app.source).toBe(appDir);
143
- const compile = body.compile as {
144
- status: string;
145
- modified: string[];
146
- };
147
- expect(compile.status).toBe("stale");
148
- expect(compile.modified).toEqual(["src/main.tsx"]);
149
- });
150
-
151
- test("exits 1 for an unknown app", async () => {
152
- const result = await runCliCommand(registerAppsCommand, [
153
- "apps",
154
- "inspect",
155
- "missing",
156
- "--json",
157
- ]);
158
- expect(result.exitCode).toBe(1);
159
- const body = parseJson(result.stdout);
160
- expect(body.ok).toBe(false);
161
- expect(String(body.error)).toContain("assistant apps list");
162
- });
163
- });
164
-
165
- describe("assistant apps refresh", () => {
166
- test("sends apps_refresh IPC for a workspace app", async () => {
167
- const name = uniqueAppName("Refresh");
168
- const created = createApp({
169
- name,
170
- schemaJson: "{}",
171
- htmlDefinition: "<h1>Budget</h1>",
172
- });
173
-
174
- const result = await runCliCommand(registerAppsCommand, [
175
- "apps",
176
- "refresh",
177
- created.id,
178
- "--json",
179
- ]);
180
-
181
- expect(result.exitCode).toBe(0);
182
- expect(lastIpcCall).toEqual({
183
- method: "apps_refresh",
184
- params: { pathParams: { id: created.id } },
185
- });
186
- const body = parseJson(result.stdout);
187
- expect(body.compiled).toBe(true);
188
- });
189
-
190
- test("sends apps_refresh IPC for a plugin app", async () => {
191
- const pluginName = `charts-${Math.random().toString(36).slice(2, 8)}`;
192
- const pluginDir = join(getWorkspacePluginsDir(), pluginName);
193
- mkdirSync(pluginDir, { recursive: true });
194
- writeFileSync(
195
- join(pluginDir, "package.json"),
196
- JSON.stringify({ name: pluginName, version: "1.0.0" }),
197
- );
198
- mkdirSync(join(pluginDir, "apps", "viewer"), { recursive: true });
199
- writeFileSync(join(pluginDir, "apps", "viewer", "index.html"), "<h1></h1>");
200
-
201
- const result = await runCliCommand(registerAppsCommand, [
202
- "apps",
203
- "refresh",
204
- "viewer",
205
- "--json",
206
- ]);
207
-
208
- expect(result.exitCode).toBe(0);
209
- expect(lastIpcCall).toEqual({
210
- method: "apps_refresh",
211
- params: { pathParams: { id: `plugins~${pluginName}~viewer` } },
212
- });
213
- });
214
-
215
- test("exits 1 when compile fails", async () => {
216
- const name = uniqueAppName("Refresh Fail");
217
- const created = createApp({
218
- name,
219
- schemaJson: "{}",
220
- htmlDefinition: "<h1>Budget</h1>",
221
- });
222
- mockIpcResult = {
223
- ok: true,
224
- result: {
225
- ok: true,
226
- appId: created.id,
227
- name,
228
- compiled: false,
229
- compile_duration_ms: 8,
230
- compile_errors: [{ text: "Could not resolve foo" }],
231
- },
232
- };
233
-
234
- const result = await runCliCommand(registerAppsCommand, [
235
- "apps",
236
- "refresh",
237
- created.id,
238
- "--json",
239
- ]);
240
-
241
- expect(result.exitCode).toBe(1);
242
- const body = parseJson(result.stdout);
243
- expect(body.compiled).toBe(false);
244
- });
245
- });
@@ -1,53 +0,0 @@
1
- /**
2
- * Tests for `assistant bash`: local sanitized spawn, no IPC round-trip.
3
- */
4
-
5
- import { describe, expect, mock, test } from "bun:test";
6
-
7
- import { runCliCommand } from "./cli-test-harness.js";
8
-
9
- const ipcCalls: Array<{ method: string }> = [];
10
-
11
- mock.module("../../../ipc/cli-client.js", () => ({
12
- cliIpcCall: async (method: string) => {
13
- ipcCalls.push({ method });
14
- return { ok: false, error: "IPC should not be used" };
15
- },
16
- }));
17
-
18
- mock.module("../../logger.js", () => ({
19
- log: {
20
- info: () => {},
21
- warn: () => {},
22
- error: (message: string) => {
23
- process.stderr.write(`${message}\n`);
24
- },
25
- debug: () => {},
26
- },
27
- }));
28
-
29
- const { registerBashCommand } = await import("../bash.js");
30
-
31
- describe("assistant bash", () => {
32
- test("spawns locally and prints stdout without IPC", async () => {
33
- ipcCalls.length = 0;
34
- const result = await runCliCommand(registerBashCommand, [
35
- "bash",
36
- "echo hello",
37
- ]);
38
- expect(ipcCalls).toEqual([]);
39
- expect(result.stdout.trim()).toBe("hello");
40
- expect(result.exitCode).toBe(0);
41
- });
42
-
43
- test("rejects a non-positive timeout", async () => {
44
- const result = await runCliCommand(registerBashCommand, [
45
- "bash",
46
- "echo hello",
47
- "--timeout",
48
- "0",
49
- ]);
50
- expect(result.stderr).toContain("Invalid timeout value");
51
- expect(result.exitCode).toBe(1);
52
- });
53
- });
@@ -1,19 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
-
3
- import { roadmapHelp } from "../roadmap.help.js";
4
-
5
- const DISCORD_URL = "https://vellum.ai/community";
6
-
7
- describe("roadmap help is feature-proposal-only", () => {
8
- test("top-level help describes feature proposals and routes bugs to Discord", () => {
9
- const description = roadmapHelp.description;
10
- const helpText = roadmapHelp.helpText ?? "";
11
- const combined = `${description}\n${helpText}`.toLowerCase();
12
-
13
- expect(combined).toMatch(/feature proposals?/);
14
- expect(description.split(DISCORD_URL)).toHaveLength(2);
15
- expect(helpText).toContain(DISCORD_URL);
16
- expect(combined).toContain("instruct the user");
17
- expect(combined).not.toMatch(/support@|github\.com|share feedback/);
18
- });
19
- });
@@ -1,218 +0,0 @@
1
- import { beforeEach, describe, expect, mock, test } from "bun:test";
2
-
3
- // The command is a door onto the daemon's one send implementation, so what
4
- // matters is the request it hands the route and what it does with the
5
- // answer. IPC is stubbed to capture that request; the exit-code helper
6
- // stays real, so the tests assert the mapping that ships.
7
-
8
- const ipcCalls: Array<{
9
- method: string;
10
- params: Record<string, unknown>;
11
- opts?: Record<string, unknown>;
12
- }> = [];
13
- let ipcResult: Record<string, unknown> = {
14
- ok: true,
15
- result: {
16
- channel: "slack",
17
- chatId: "C0123456789",
18
- messageIds: ["1700000000.000100"],
19
- lastMessageId: "1700000000.000100",
20
- recordedIn: "conv-home",
21
- },
22
- };
23
-
24
- const actualCliClient = await import("../../../../ipc/cli-client.js");
25
- mock.module("../../../../ipc/cli-client.js", () => ({
26
- ...actualCliClient,
27
- cliIpcCall: async (
28
- method: string,
29
- params: Record<string, unknown>,
30
- opts?: Record<string, unknown>,
31
- ) => {
32
- ipcCalls.push({ method, params, ...(opts ? { opts } : {}) });
33
- return ipcResult;
34
- },
35
- }));
36
-
37
- // Imported after the mock is installed, so the command module under test
38
- // binds the stubbed IPC call rather than the real one.
39
- const { runCliCommand } = await import("../../__tests__/cli-test-harness.js");
40
- const { registerChannelsCommand } = await import("../index.js");
41
-
42
- beforeEach(() => {
43
- ipcCalls.length = 0;
44
- ipcResult = {
45
- ok: true,
46
- result: {
47
- channel: "slack",
48
- chatId: "C0123456789",
49
- messageIds: ["1700000000.000100"],
50
- lastMessageId: "1700000000.000100",
51
- recordedIn: "conv-home",
52
- },
53
- };
54
- });
55
-
56
- // The shipped registration as-is: `send` declares its own `--json`, which is
57
- // why the program's global leaf-option pass skips it.
58
- function runSend(args: string[]) {
59
- return runCliCommand(registerChannelsCommand, ["channels", "send", ...args]);
60
- }
61
-
62
- /** The body the command handed the route on its one call. */
63
- function sentBody(): Record<string, unknown> {
64
- expect(ipcCalls).toHaveLength(1);
65
- expect(ipcCalls[0]!.method).toBe("channels_send_post");
66
- return ipcCalls[0]!.params.body as Record<string, unknown>;
67
- }
68
-
69
- describe("the request the command makes", () => {
70
- test("names the chat and asks for the channel's rich rendering", async () => {
71
- const r = await runSend([
72
- "slack",
73
- "C0123456789",
74
- "--text",
75
- "deploy is green",
76
- ]);
77
- expect(r.exitCode).toBe(0);
78
- expect(sentBody()).toEqual({
79
- channel: "slack",
80
- target: { kind: "chat", chatId: "C0123456789" },
81
- text: "deploy is green",
82
- renderRichly: true,
83
- });
84
- });
85
-
86
- test("carries a named thread as the target's thread", async () => {
87
- await runSend([
88
- "slack",
89
- "C0123456789",
90
- "--thread",
91
- "1700000000.000001",
92
- "--text",
93
- "and the smoke tests passed",
94
- ]);
95
- expect(sentBody().target).toEqual({
96
- kind: "chat",
97
- chatId: "C0123456789",
98
- threadId: "1700000000.000001",
99
- });
100
- });
101
-
102
- test("--plain asks for the text verbatim", async () => {
103
- await runSend(["telegram", "123456789", "--text", "morning", "--plain"]);
104
- const body = sentBody();
105
- expect(body.renderRichly).toBeUndefined();
106
- expect(body.channel).toBe("telegram");
107
- });
108
-
109
- test("sends the text as the caller wrote it, whitespace included", async () => {
110
- await runSend([
111
- "slack",
112
- "C0123456789",
113
- "--text",
114
- " indented ",
115
- "--plain",
116
- ]);
117
- expect(sentBody().text).toBe(" indented ");
118
- });
119
-
120
- test("waits longer than the IPC default, since the send itself retries", async () => {
121
- await runSend(["slack", "C0123456789", "--text", "hi"]);
122
- expect(ipcCalls[0]!.opts).toMatchObject({ timeoutMs: 120_000 });
123
- });
124
-
125
- test("refuses an empty text before it sends anything", async () => {
126
- for (const args of [
127
- ["slack", "C0123456789"],
128
- ["slack", "C0123456789", "--text", " "],
129
- ]) {
130
- ipcCalls.length = 0;
131
- const r = await runSend(args);
132
- expect(r.exitCode).toBe(1);
133
- expect(r.stderr).toContain("--text is required");
134
- expect(ipcCalls).toEqual([]);
135
- }
136
- });
137
- });
138
-
139
- describe("what the command reports", () => {
140
- test("names where the post landed and the conversation it was recorded in", async () => {
141
- const r = await runSend(["slack", "C0123456789", "--text", "hello"]);
142
- expect(r.stdout).toContain("C0123456789");
143
- expect(r.stdout).toContain("1700000000.000100");
144
- expect(r.stdout).toContain("conv-home");
145
- });
146
-
147
- test("says so when the channel split the text", async () => {
148
- ipcResult = {
149
- ok: true,
150
- result: {
151
- channel: "telegram",
152
- chatId: "123456789",
153
- messageIds: ["10", "11", "12"],
154
- lastMessageId: "12",
155
- },
156
- };
157
- const r = await runSend(["telegram", "123456789", "--text", "a long one"]);
158
- expect(r.stdout).toContain("3 posts");
159
- });
160
-
161
- test("--json answers with the route's own result", async () => {
162
- const r = await runSend([
163
- "slack",
164
- "C0123456789",
165
- "--text",
166
- "hello",
167
- "--json",
168
- ]);
169
- expect(JSON.parse(r.stdout)).toEqual({
170
- channel: "slack",
171
- chatId: "C0123456789",
172
- messageIds: ["1700000000.000100"],
173
- lastMessageId: "1700000000.000100",
174
- recordedIn: "conv-home",
175
- });
176
- });
177
-
178
- test("a refused send reports the route's reason and its exit code", async () => {
179
- ipcResult = {
180
- ok: false,
181
- error: 'Channel "email" is not addressable',
182
- statusCode: 400,
183
- };
184
- const r = await runSend(["email", "someone", "--text", "hello"]);
185
- expect(r.exitCode).toBe(
186
- actualCliClient.exitCodeFromIpcResult({ statusCode: 400 }),
187
- );
188
- expect(r.stderr).toContain("not addressable");
189
- });
190
-
191
- test("a timeout is reported as an unknown outcome, not a failure to retry", async () => {
192
- ipcResult = { ok: false, error: "Request timed out", timedOut: true };
193
- const r = await runSend(["slack", "C0123456789", "--text", "hello"]);
194
- expect(r.stderr).toContain("may still be in flight");
195
- expect(r.stderr).toContain("before sending again");
196
- expect(r.stderr).not.toContain("The send failed");
197
- });
198
-
199
- test("a refusal in --json mode is a JSON error envelope", async () => {
200
- ipcResult = {
201
- ok: false,
202
- error: 'Channel "slack" did not acknowledge the send',
203
- statusCode: 502,
204
- };
205
- const r = await runSend([
206
- "slack",
207
- "C0123456789",
208
- "--text",
209
- "hello",
210
- "--json",
211
- ]);
212
- expect(JSON.parse(r.stdout)).toEqual({
213
- ok: false,
214
- error: 'Channel "slack" did not acknowledge the send',
215
- });
216
- expect(r.exitCode).toBe(3);
217
- });
218
- });
@@ -1,128 +0,0 @@
1
- /**
2
- * `assistant channels send`: post text to a chat on a channel, as the
3
- * assistant's own bot.
4
- *
5
- * The send door. It runs the daemon function the messaging tool runs
6
- * (`sendChannelText`, over `POST /v1/channels/send`), so a send from the
7
- * command line reaches the chat through the channel's transport and leaves
8
- * the same record: threaded where a thread is named, rendered the way the
9
- * channel renders a reply, and written to the chat's conversation only once
10
- * the channel has acknowledged it.
11
- *
12
- * Posting the same text through `channels request` reaches the platform API
13
- * directly and leaves no record of what was said, which is why this command
14
- * exists beside it. Both act as the bot and both carry the same rating: the
15
- * effect is a message either way.
16
- *
17
- * A channel whose transport cannot be addressed from a named chat is
18
- * refused by the route before anything is sent.
19
- */
20
-
21
- import type { Command } from "commander";
22
-
23
- import { cliIpcCall, exitCodeFromIpcResult } from "../../../ipc/cli-client.js";
24
- import { subcommand } from "../../lib/cli-command-help.js";
25
- import { log } from "../../logger.js";
26
- import { shouldOutputJson, writeError, writeOutput } from "../../output.js";
27
-
28
- /** What the channel acknowledged, and where the post was recorded. */
29
- interface ChannelSendResponse {
30
- channel: string;
31
- chatId: string;
32
- threadId?: string;
33
- messageIds: string[];
34
- lastMessageId: string;
35
- recordedIn?: string;
36
- }
37
-
38
- interface ChannelSendOptions {
39
- text?: string;
40
- thread?: string;
41
- plain?: boolean;
42
- }
43
-
44
- /**
45
- * How long to wait for the daemon before giving up on an answer.
46
- *
47
- * Longer than the IPC default because the work behind this call is a
48
- * platform request that retries: a rate-limited Slack send sleeps for the
49
- * `Retry-After` Slack names and tries again up to three times
50
- * (`MAX_RATE_LIMIT_RETRIES`, providers/slack/web-api-transport.ts), and the
51
- * other channels back off similarly. Waiting past that is better than
52
- * abandoning a send that is still being made, because giving up tells the
53
- * caller nothing about whether the message went out.
54
- */
55
- const SEND_CALL_TIMEOUT_MS = 120_000;
56
-
57
- export function registerChannelsSendCommand(channels: Command): void {
58
- subcommand(channels, "send").action(
59
- async (
60
- channel: string,
61
- chatId: string,
62
- opts: ChannelSendOptions,
63
- cmd: Command,
64
- ) => {
65
- // Trimmed only to reject a blank message: the text goes out as the
66
- // caller wrote it, which `--plain` in particular promises.
67
- const text = opts.text;
68
- if (!text?.trim()) {
69
- writeError(cmd, "--text is required and cannot be empty.");
70
- process.exitCode = 1;
71
- return;
72
- }
73
-
74
- const threadId = opts.thread?.trim();
75
- const r = await cliIpcCall<ChannelSendResponse>(
76
- "channels_send_post",
77
- {
78
- body: {
79
- channel,
80
- target: {
81
- kind: "chat",
82
- chatId,
83
- ...(threadId ? { threadId } : {}),
84
- },
85
- text,
86
- // Rich unless asked otherwise, so a send from here reads like
87
- // the assistant's other posts in that chat rather than like a
88
- // different sender.
89
- ...(opts.plain ? {} : { renderRichly: true }),
90
- },
91
- },
92
- { timeoutMs: SEND_CALL_TIMEOUT_MS },
93
- );
94
- if (!r.ok) {
95
- // A timeout is not a failure: closing the client socket does not
96
- // stop the daemon, so the message may still go out. Saying so is
97
- // what keeps a retry from posting it twice.
98
- const message = r.timedOut
99
- ? `The daemon did not answer within ${Math.round(SEND_CALL_TIMEOUT_MS / 1000)}s. The send may still be in flight, so it may or may not have gone out. Check the chat before sending again.`
100
- : (r.error ?? "The send failed.");
101
- // Reported rather than exited, so `--json` gets an error envelope
102
- // like every other answer this command gives.
103
- writeError(cmd, message);
104
- process.exitCode = exitCodeFromIpcResult({
105
- statusCode: r.statusCode,
106
- });
107
- return;
108
- }
109
-
110
- const sent = r.result!;
111
- if (shouldOutputJson(cmd)) {
112
- writeOutput(cmd, sent);
113
- return;
114
- }
115
-
116
- const where = sent.threadId
117
- ? `${sent.chatId}, thread ${sent.threadId}`
118
- : sent.chatId;
119
- log.info(`Sent to ${channel} ${where} (id: ${sent.lastMessageId})`);
120
- if (sent.messageIds.length > 1) {
121
- log.info(`The channel split it into ${sent.messageIds.length} posts`);
122
- }
123
- if (sent.recordedIn) {
124
- log.info(`Recorded in conversation ${sent.recordedIn}`);
125
- }
126
- },
127
- );
128
- }