@vellumai/assistant 0.8.3 → 0.8.5

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 (665) hide show
  1. package/ARCHITECTURE.md +2 -2
  2. package/docker-entrypoint.sh +0 -1
  3. package/docs/browser-use-architecture-phase2.md +1 -1
  4. package/knip.json +2 -1
  5. package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
  6. package/openapi.yaml +1492 -100
  7. package/package.json +1 -1
  8. package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
  9. package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
  10. package/src/__tests__/agent-loop.test.ts +88 -3
  11. package/src/__tests__/anthropic-provider.test.ts +302 -33
  12. package/src/__tests__/approval-cascade.test.ts +1 -1
  13. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  14. package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
  15. package/src/__tests__/audit-log-rotation.test.ts +70 -16
  16. package/src/__tests__/background-workers-disk-pressure.test.ts +4 -3
  17. package/src/__tests__/btw-routes.test.ts +2 -3
  18. package/src/__tests__/call-controller.test.ts +0 -1
  19. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  20. package/src/__tests__/channel-delivery-store.test.ts +193 -0
  21. package/src/__tests__/channel-guardian.test.ts +3 -3
  22. package/src/__tests__/channel-reply-delivery.test.ts +284 -5
  23. package/src/__tests__/channel-retry-sweep.test.ts +274 -1
  24. package/src/__tests__/checker.test.ts +6 -15
  25. package/src/__tests__/compaction-events.test.ts +2 -1
  26. package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
  27. package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
  28. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
  29. package/src/__tests__/computer-use-tools.test.ts +2 -4
  30. package/src/__tests__/config-watcher.test.ts +1 -1
  31. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  32. package/src/__tests__/context-token-estimator.test.ts +91 -1
  33. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
  34. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
  35. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +55 -4
  36. package/src/__tests__/conversation-agent-loop-overflow.test.ts +228 -8
  37. package/src/__tests__/conversation-agent-loop.test.ts +188 -129
  38. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
  39. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
  40. package/src/__tests__/conversation-clean-command.test.ts +137 -0
  41. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  42. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
  43. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  44. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  45. package/src/__tests__/conversation-error.test.ts +31 -0
  46. package/src/__tests__/conversation-fork-crud.test.ts +324 -0
  47. package/src/__tests__/conversation-lifecycle.test.ts +53 -12
  48. package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
  49. package/src/__tests__/conversation-load-history-stripped.test.ts +279 -0
  50. package/src/__tests__/conversation-pairing.test.ts +2 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +1 -1
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -1
  53. package/src/__tests__/conversation-queue.test.ts +1 -1
  54. package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
  56. package/src/__tests__/conversation-runtime-assembly.test.ts +264 -81
  57. package/src/__tests__/conversation-seed-composer.test.ts +66 -4
  58. package/src/__tests__/conversation-skill-tools.test.ts +2 -5
  59. package/src/__tests__/conversation-slash-commands.test.ts +36 -8
  60. package/src/__tests__/conversation-slash-queue.test.ts +1 -1
  61. package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
  62. package/src/__tests__/conversation-speed-override.test.ts +1 -1
  63. package/src/__tests__/conversation-store.test.ts +1 -1
  64. package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
  65. package/src/__tests__/conversation-sync-tags.test.ts +99 -32
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -1
  67. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  69. package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
  70. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  71. package/src/__tests__/credential-security-invariants.test.ts +7 -0
  72. package/src/__tests__/credential-vault-unit.test.ts +2 -2
  73. package/src/__tests__/cu-unified-flow.test.ts +10 -1
  74. package/src/__tests__/dm-backfill.test.ts +64 -0
  75. package/src/__tests__/dm-persistence.test.ts +33 -0
  76. package/src/__tests__/document-find-replace.test.ts +501 -0
  77. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  78. package/src/__tests__/email-html-renderer.test.ts +12 -0
  79. package/src/__tests__/first-greeting.test.ts +23 -2
  80. package/src/__tests__/gateway-flag-listener.test.ts +237 -0
  81. package/src/__tests__/gemini-provider.test.ts +78 -0
  82. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  83. package/src/__tests__/guardian-outbound-http.test.ts +7 -5
  84. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  85. package/src/__tests__/headless-browser-navigate.test.ts +172 -0
  86. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  87. package/src/__tests__/heartbeat-service.test.ts +4 -0
  88. package/src/__tests__/host-bash-proxy.test.ts +6 -0
  89. package/src/__tests__/host-browser-proxy.test.ts +10 -0
  90. package/src/__tests__/host-cu-proxy.test.ts +8 -1
  91. package/src/__tests__/host-file-proxy.test.ts +8 -1
  92. package/src/__tests__/host-shell-tool.test.ts +1 -1
  93. package/src/__tests__/host-transfer-proxy.test.ts +8 -1
  94. package/src/__tests__/identity-routes.test.ts +57 -0
  95. package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
  96. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  97. package/src/__tests__/injector-chain.test.ts +2 -0
  98. package/src/__tests__/injector-document-comments.test.ts +378 -0
  99. package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
  100. package/src/__tests__/list-messages-attachments.test.ts +21 -17
  101. package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
  102. package/src/__tests__/list-messages-page-latest.test.ts +130 -14
  103. package/src/__tests__/list-messages-tool-merge.test.ts +77 -17
  104. package/src/__tests__/llm-context-normalization.test.ts +0 -2
  105. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  106. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  107. package/src/__tests__/llm-resolver.test.ts +161 -9
  108. package/src/__tests__/llm-usage-store.test.ts +66 -0
  109. package/src/__tests__/log-export-routes.test.ts +99 -2
  110. package/src/__tests__/logger.test.ts +89 -0
  111. package/src/__tests__/mcp-abort-signal.test.ts +2 -2
  112. package/src/__tests__/media-generate-image.test.ts +31 -0
  113. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  114. package/src/__tests__/message-queue-steer.test.ts +114 -0
  115. package/src/__tests__/model-intents.test.ts +2 -4
  116. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  117. package/src/__tests__/onboarding-template-contract.test.ts +1 -1
  118. package/src/__tests__/openai-provider.test.ts +151 -0
  119. package/src/__tests__/openai-responses-provider.test.ts +118 -16
  120. package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
  121. package/src/__tests__/pending-interactions-resolved-event.test.ts +189 -0
  122. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  123. package/src/__tests__/platform.test.ts +2 -5
  124. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  125. package/src/__tests__/plugin-bootstrap.test.ts +2 -2
  126. package/src/__tests__/plugin-source-watcher.test.ts +302 -0
  127. package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
  128. package/src/__tests__/plugin-types.test.ts +3 -2
  129. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  130. package/src/__tests__/pricing.test.ts +12 -0
  131. package/src/__tests__/process-message-background-slack.test.ts +1 -51
  132. package/src/__tests__/process-message-display-content.test.ts +21 -16
  133. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  134. package/src/__tests__/registry.test.ts +2 -8
  135. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  136. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  137. package/src/__tests__/server-history-render.test.ts +83 -4
  138. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  139. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  140. package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
  141. package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
  142. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  143. package/src/__tests__/steer-tool-repair.test.ts +249 -0
  144. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  145. package/src/__tests__/suggestion-routes.test.ts +1 -0
  146. package/src/__tests__/sync-message-contract.test.ts +59 -0
  147. package/src/__tests__/system-prompt.test.ts +161 -124
  148. package/src/__tests__/terminal-tools.test.ts +12 -2
  149. package/src/__tests__/thinking-block-replay.test.ts +113 -0
  150. package/src/__tests__/thread-backfill.test.ts +370 -22
  151. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  152. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  153. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  154. package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
  155. package/src/__tests__/tool-executor.test.ts +89 -53
  156. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  157. package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
  158. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  159. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  160. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  161. package/src/__tests__/twilio-routes.test.ts +1 -1
  162. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  163. package/src/__tests__/usage-routes.test.ts +3 -0
  164. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  165. package/src/__tests__/web-fetch.test.ts +2 -2
  166. package/src/__tests__/workspace-git-service.test.ts +94 -10
  167. package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
  168. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  169. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  170. package/src/acp/prepare-agent-env.ts +78 -0
  171. package/src/acp/session-manager.ts +1 -1
  172. package/src/agent/attachments.ts +1 -0
  173. package/src/agent/loop.ts +65 -20
  174. package/src/api/README.md +5 -0
  175. package/src/api/index.ts +4 -0
  176. package/src/api/package.json +10 -0
  177. package/src/background-wake/background-wake-routes.test.ts +233 -0
  178. package/src/background-wake/next-wake.test.ts +289 -0
  179. package/src/background-wake/next-wake.ts +172 -0
  180. package/src/background-wake/runtime-registry.ts +24 -0
  181. package/src/browser/operations.ts +15 -0
  182. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  183. package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
  184. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  185. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  186. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  187. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  188. package/src/cli/commands/__tests__/memory-v2.test.ts +10 -12
  189. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  190. package/src/cli/commands/browser.ts +247 -0
  191. package/src/cli/commands/conversations.ts +128 -1
  192. package/src/cli/commands/domain.ts +91 -41
  193. package/src/cli/commands/inference-providers.ts +147 -1
  194. package/src/cli/commands/inference.ts +93 -40
  195. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  196. package/src/cli/commands/memory-v2.ts +483 -0
  197. package/src/cli/commands/memory-v3-render.ts +344 -0
  198. package/src/cli/commands/memory-v3.ts +316 -0
  199. package/src/cli/commands/notifications.ts +24 -2
  200. package/src/cli/program.ts +2 -0
  201. package/src/cli/utils/conversation-id.ts +17 -5
  202. package/src/config/assistant-feature-flags.ts +21 -9
  203. package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
  204. package/src/config/bundled-skills/document-editor/SKILL.md +124 -0
  205. package/src/config/bundled-skills/document-editor/TOOLS.json +258 -0
  206. package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
  207. package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
  208. package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
  209. package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
  210. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  211. package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
  212. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  213. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  214. package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
  215. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  216. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  217. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  218. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  219. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  220. package/src/config/bundled-skills/schedule/SKILL.md +8 -0
  221. package/src/config/bundled-tool-registry.ts +24 -12
  222. package/src/config/call-site-defaults.ts +20 -0
  223. package/src/config/feature-flag-registry.json +115 -3
  224. package/src/config/llm-resolver.ts +16 -2
  225. package/src/config/schemas/__tests__/memory-v2.test.ts +217 -1
  226. package/src/config/schemas/call-site-catalog.ts +35 -0
  227. package/src/config/schemas/llm.ts +14 -0
  228. package/src/config/schemas/memory-v2.ts +294 -1
  229. package/src/config/schemas/memory.ts +2 -1
  230. package/src/context/compactor.ts +60 -1
  231. package/src/context/token-estimator.ts +47 -4
  232. package/src/context/window-manager.ts +25 -0
  233. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  234. package/src/conversations/message-consolidation.ts +404 -0
  235. package/src/credential-health/credential-health-service.ts +34 -19
  236. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
  237. package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
  238. package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
  239. package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
  240. package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
  241. package/src/daemon/conversation-agent-loop-handlers.ts +155 -36
  242. package/src/daemon/conversation-agent-loop.ts +307 -88
  243. package/src/daemon/conversation-error.ts +31 -1
  244. package/src/daemon/conversation-lifecycle.ts +149 -118
  245. package/src/daemon/conversation-messaging.ts +3 -0
  246. package/src/daemon/conversation-process.ts +273 -0
  247. package/src/daemon/conversation-queue-manager.ts +14 -0
  248. package/src/daemon/conversation-runtime-assembly.ts +145 -84
  249. package/src/daemon/conversation-slash.ts +37 -5
  250. package/src/daemon/conversation-surfaces.ts +45 -2
  251. package/src/daemon/conversation-tool-setup.ts +70 -3
  252. package/src/daemon/conversation-usage.ts +2 -0
  253. package/src/daemon/conversation.ts +54 -32
  254. package/src/daemon/disk-pressure-guard.ts +14 -2
  255. package/src/daemon/first-greeting.ts +10 -0
  256. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
  257. package/src/daemon/handlers/config-a2a.ts +160 -0
  258. package/src/daemon/handlers/config-model.test.ts +2 -0
  259. package/src/daemon/handlers/conversations.ts +90 -3
  260. package/src/daemon/handlers/shared.ts +92 -29
  261. package/src/daemon/host-bash-proxy.ts +1 -1
  262. package/src/daemon/host-browser-proxy.ts +5 -5
  263. package/src/daemon/host-cu-proxy.ts +5 -5
  264. package/src/daemon/host-file-proxy.ts +5 -5
  265. package/src/daemon/host-proxy-base.ts +4 -4
  266. package/src/daemon/host-transfer-proxy.ts +11 -11
  267. package/src/daemon/lifecycle.ts +40 -23
  268. package/src/daemon/meet-manifest-loader.ts +1 -7
  269. package/src/daemon/message-protocol.ts +4 -0
  270. package/src/daemon/message-types/conversations.ts +14 -9
  271. package/src/daemon/message-types/document-comments.ts +50 -0
  272. package/src/daemon/message-types/home.ts +1 -13
  273. package/src/daemon/message-types/messages.ts +66 -7
  274. package/src/daemon/message-types/surfaces.ts +3 -1
  275. package/src/daemon/message-types/sync.ts +14 -0
  276. package/src/daemon/message-types/web-activity.ts +57 -0
  277. package/src/daemon/plugin-source-watcher.ts +135 -3
  278. package/src/daemon/process-message.ts +69 -12
  279. package/src/daemon/shutdown-handlers.ts +24 -5
  280. package/src/daemon/switch-inference-profile-tool.ts +52 -0
  281. package/src/daemon/tool-setup-types.ts +13 -0
  282. package/src/daemon/trust-context.ts +6 -0
  283. package/src/documents/document-comments-store.test.ts +338 -0
  284. package/src/documents/document-comments-store.ts +237 -0
  285. package/src/documents/document-store.ts +202 -0
  286. package/src/events/relationship-state-updated.ts +25 -0
  287. package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -2
  288. package/src/heartbeat/heartbeat-service.ts +1 -0
  289. package/src/home/__tests__/suggested-prompts.test.ts +33 -2
  290. package/src/home/feed-types.ts +6 -1
  291. package/src/home/home-content-refresh.ts +52 -0
  292. package/src/home/home-greeting-cache.ts +69 -0
  293. package/src/home/home-greeting.ts +85 -0
  294. package/src/home/suggested-prompts.ts +168 -9
  295. package/src/ipc/gateway-flag-listener.ts +123 -0
  296. package/src/ipc/skill-routes/registries.ts +8 -12
  297. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  298. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  299. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
  300. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  301. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
  302. package/src/memory/__tests__/memory-retrospective-job.test.ts +327 -6
  303. package/src/memory/auto-analysis-enqueue.ts +5 -1
  304. package/src/memory/conversation-crud.ts +191 -100
  305. package/src/memory/conversation-starters-cadence.ts +3 -1
  306. package/src/memory/conversation-title-service.ts +19 -3
  307. package/src/memory/db-async-query.ts +214 -0
  308. package/src/memory/db-init.ts +26 -0
  309. package/src/memory/db-maintenance.ts +30 -21
  310. package/src/memory/delivery-crud.ts +41 -0
  311. package/src/memory/delivery-status.ts +141 -15
  312. package/src/memory/external-conversation-store.ts +32 -1
  313. package/src/memory/graph/bootstrap.ts +8 -1
  314. package/src/memory/graph/capability-seed.ts +7 -3
  315. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  316. package/src/memory/graph/extraction.ts +1 -5
  317. package/src/memory/graph/graph-search.ts +7 -1
  318. package/src/memory/indexer.ts +28 -18
  319. package/src/memory/job-handlers/cleanup.ts +76 -18
  320. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  321. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  322. package/src/memory/jobs-store.ts +14 -0
  323. package/src/memory/jobs-worker.ts +68 -15
  324. package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
  325. package/src/memory/llm-request-log-source-local.ts +7 -0
  326. package/src/memory/llm-request-log-source.ts +9 -2
  327. package/src/memory/llm-request-log-store.ts +43 -1
  328. package/src/memory/llm-usage-store.ts +24 -0
  329. package/src/memory/memory-retrospective-constants.ts +28 -0
  330. package/src/memory/memory-retrospective-enqueue.ts +11 -3
  331. package/src/memory/memory-retrospective-job.ts +413 -18
  332. package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
  333. package/src/memory/memory-v2-activation-log-store.ts +41 -14
  334. package/src/memory/migrations/100-core-tables.ts +1 -0
  335. package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
  336. package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
  337. package/src/memory/migrations/253-document-comments.ts +47 -0
  338. package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
  339. package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
  340. package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
  341. package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
  342. package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
  343. package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
  344. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  345. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  346. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  347. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  348. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  349. package/src/memory/migrations/index.ts +34 -0
  350. package/src/memory/migrations/registry.ts +58 -0
  351. package/src/memory/onboarding-events-store.ts +7 -0
  352. package/src/memory/schema/calls.ts +1 -0
  353. package/src/memory/schema/conversations.ts +3 -0
  354. package/src/memory/schema/infrastructure.ts +22 -0
  355. package/src/memory/tool-usage-store.ts +36 -8
  356. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  357. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  358. package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
  359. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  360. package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
  361. package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
  362. package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
  363. package/src/memory/v2/__tests__/injection.test.ts +158 -112
  364. package/src/memory/v2/__tests__/page-index.test.ts +365 -1
  365. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  366. package/src/memory/v2/__tests__/router.test.ts +660 -4
  367. package/src/memory/v2/consolidation-job.ts +14 -0
  368. package/src/memory/v2/harness/compare.ts +57 -0
  369. package/src/memory/v2/harness/metrics.ts +124 -0
  370. package/src/memory/v2/harness/oracle.ts +145 -0
  371. package/src/memory/v2/harness/replay-input.ts +224 -0
  372. package/src/memory/v2/harness/retriever.ts +74 -0
  373. package/src/memory/v2/harness/router-retriever.ts +43 -0
  374. package/src/memory/v2/harness/runner.ts +106 -0
  375. package/src/memory/v2/harness/trace.ts +58 -0
  376. package/src/memory/v2/injection-events.ts +101 -0
  377. package/src/memory/v2/injection.ts +42 -25
  378. package/src/memory/v2/page-index.ts +209 -7
  379. package/src/memory/v2/page-store.ts +18 -0
  380. package/src/memory/v2/prompts/router.ts +26 -1
  381. package/src/memory/v2/qdrant.ts +14 -2
  382. package/src/memory/v2/router.ts +369 -62
  383. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  384. package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
  385. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  386. package/src/memory/v3/__tests__/edges.test.ts +563 -0
  387. package/src/memory/v3/__tests__/filter.test.ts +512 -0
  388. package/src/memory/v3/__tests__/gate.test.ts +574 -0
  389. package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
  390. package/src/memory/v3/__tests__/loop.test.ts +530 -0
  391. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  392. package/src/memory/v3/__tests__/scouts.test.ts +440 -0
  393. package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
  394. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  395. package/src/memory/v3/__tests__/traversal.test.ts +469 -0
  396. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  397. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  398. package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
  399. package/src/memory/v3/__tests__/validate.test.ts +245 -0
  400. package/src/memory/v3/auto-edges.ts +223 -0
  401. package/src/memory/v3/coactivation-store.ts +124 -0
  402. package/src/memory/v3/consolidation-job.ts +323 -0
  403. package/src/memory/v3/edge-learning-job.ts +160 -0
  404. package/src/memory/v3/edges.ts +249 -0
  405. package/src/memory/v3/filter.ts +281 -0
  406. package/src/memory/v3/gate.ts +334 -0
  407. package/src/memory/v3/index-composition.ts +113 -0
  408. package/src/memory/v3/llm-capture.ts +46 -0
  409. package/src/memory/v3/loop.ts +382 -0
  410. package/src/memory/v3/maintenance.ts +144 -0
  411. package/src/memory/v3/prompt-context.ts +33 -0
  412. package/src/memory/v3/prompts/consolidation.ts +458 -0
  413. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  414. package/src/memory/v3/retriever.ts +33 -0
  415. package/src/memory/v3/scouts.ts +420 -0
  416. package/src/memory/v3/shadow-middleware.ts +305 -0
  417. package/src/memory/v3/traversal.ts +206 -0
  418. package/src/memory/v3/tree-index.ts +237 -0
  419. package/src/memory/v3/tree-store.ts +394 -0
  420. package/src/memory/v3/tree-walk.ts +351 -0
  421. package/src/memory/v3/types.ts +65 -0
  422. package/src/memory/v3/validate.ts +300 -0
  423. package/src/messaging/providers/index.ts +7 -1
  424. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
  425. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
  426. package/src/messaging/providers/slack/adapter.ts +178 -25
  427. package/src/messaging/providers/slack/api.test.ts +54 -0
  428. package/src/messaging/providers/slack/api.ts +119 -3
  429. package/src/messaging/providers/slack/client.ts +12 -0
  430. package/src/messaging/providers/slack/deep-link.ts +20 -1
  431. package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
  432. package/src/messaging/providers/slack/message-metadata.ts +156 -0
  433. package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
  434. package/src/messaging/providers/slack/render-transcript.ts +176 -49
  435. package/src/messaging/providers/slack/send.test.ts +77 -0
  436. package/src/messaging/providers/slack/send.ts +8 -2
  437. package/src/messaging/providers/slack/types.ts +14 -0
  438. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
  439. package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
  440. package/src/notifications/adapters/macos.ts +18 -1
  441. package/src/notifications/adapters/platform.ts +1 -1
  442. package/src/notifications/conversation-seed-composer.ts +14 -2
  443. package/src/notifications/decision-engine.ts +1 -4
  444. package/src/notifications/deferred-emit.ts +135 -0
  445. package/src/notifications/emit-signal.ts +38 -50
  446. package/src/notifications/home-feed-side-effect.ts +60 -30
  447. package/src/oauth/connect-orchestrator.ts +3 -0
  448. package/src/oauth/credential-token-resolver.ts +2 -0
  449. package/src/oauth/manual-token-connection.ts +19 -0
  450. package/src/oauth/oauth-store.ts +12 -0
  451. package/src/oauth/seed-providers.ts +22 -0
  452. package/src/permissions/prompter.ts +8 -5
  453. package/src/permissions/question-prompter.ts +5 -2
  454. package/src/permissions/secret-prompter.ts +6 -3
  455. package/src/plugin-api/index.ts +4 -0
  456. package/src/plugin-api/types.ts +7 -33
  457. package/src/plugins/defaults/index.ts +6 -0
  458. package/src/plugins/defaults/injectors.ts +100 -20
  459. package/src/plugins/external-plugin-loader.ts +5 -68
  460. package/src/plugins/types.ts +11 -16
  461. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  462. package/src/prompts/__tests__/system-prompt.test.ts +46 -2
  463. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  464. package/src/prompts/normalize-onboarding.ts +40 -0
  465. package/src/prompts/persona-resolver.ts +36 -21
  466. package/src/prompts/sections.ts +69 -19
  467. package/src/prompts/system-prompt.ts +118 -216
  468. package/src/prompts/template-detection.ts +37 -0
  469. package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
  470. package/src/prompts/templates/BOOTSTRAP.md +10 -2
  471. package/src/prompts/templates/VOICE.md +3 -0
  472. package/src/prompts/templates/system-sections.ts +281 -9
  473. package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
  474. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  475. package/src/providers/anthropic/client.ts +159 -66
  476. package/src/providers/call-site-routing.ts +14 -2
  477. package/src/providers/connection-model-compat.ts +38 -0
  478. package/src/providers/connection-resolution.ts +16 -2
  479. package/src/providers/fireworks/client.ts +20 -2
  480. package/src/providers/gemini/client.ts +49 -6
  481. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
  482. package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
  483. package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
  484. package/src/providers/inference/adapter-factory.ts +18 -1
  485. package/src/providers/inference/auth.ts +3 -3
  486. package/src/providers/inference/codex-token-refresh.ts +128 -0
  487. package/src/providers/inference/resolve-auth.ts +49 -6
  488. package/src/providers/minimax/client.ts +106 -0
  489. package/src/providers/model-catalog.ts +91 -1
  490. package/src/providers/model-intents.ts +1 -1
  491. package/src/providers/openai/chat-completions-provider.ts +63 -23
  492. package/src/providers/openai/codex-models.ts +18 -0
  493. package/src/providers/openai/responses-provider.ts +86 -23
  494. package/src/providers/openrouter/client.ts +5 -1
  495. package/src/providers/provider-send-message.ts +7 -1
  496. package/src/providers/retry.ts +34 -3
  497. package/src/providers/thinking-config.ts +26 -1
  498. package/src/providers/types.ts +25 -0
  499. package/src/providers/usage-tracking.ts +2 -0
  500. package/src/runtime/AGENTS.md +2 -2
  501. package/src/runtime/__tests__/agent-wake.test.ts +214 -0
  502. package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
  503. package/src/runtime/agent-wake.ts +152 -56
  504. package/src/runtime/assistant-event-hub.ts +76 -6
  505. package/src/runtime/auth/route-policy.ts +43 -3
  506. package/src/runtime/background-job-runner.ts +26 -0
  507. package/src/runtime/btw-sidechain.ts +0 -6
  508. package/src/runtime/channel-reply-delivery.ts +182 -47
  509. package/src/runtime/channel-retry-sweep.ts +141 -16
  510. package/src/runtime/http-types.ts +7 -6
  511. package/src/runtime/migrations/vbundle-builder.ts +10 -3
  512. package/src/runtime/pending-interactions.ts +50 -8
  513. package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
  514. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +161 -1
  515. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
  516. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +290 -0
  517. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  518. package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
  519. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
  520. package/src/runtime/routes/acp-routes.test.ts +255 -6
  521. package/src/runtime/routes/acp-routes.ts +8 -1
  522. package/src/runtime/routes/approval-routes.ts +4 -1
  523. package/src/runtime/routes/avatar-routes.ts +10 -10
  524. package/src/runtime/routes/background-wake-routes.ts +188 -0
  525. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  526. package/src/runtime/routes/btw-routes.ts +0 -6
  527. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
  528. package/src/runtime/routes/content-source-routes.ts +78 -0
  529. package/src/runtime/routes/conversation-cli-routes.ts +147 -2
  530. package/src/runtime/routes/conversation-list-routes.ts +12 -4
  531. package/src/runtime/routes/conversation-management-routes.ts +77 -20
  532. package/src/runtime/routes/conversation-query-routes.ts +196 -31
  533. package/src/runtime/routes/conversation-routes.ts +472 -425
  534. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  535. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  536. package/src/runtime/routes/document-comments-routes.ts +287 -0
  537. package/src/runtime/routes/documents-routes.ts +33 -0
  538. package/src/runtime/routes/domain-routes.ts +60 -10
  539. package/src/runtime/routes/email-routes.ts +5 -2
  540. package/src/runtime/routes/events-routes.ts +54 -10
  541. package/src/runtime/routes/group-routes.ts +24 -8
  542. package/src/runtime/routes/home-feed-routes.ts +6 -3
  543. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  544. package/src/runtime/routes/host-browser-routes.ts +17 -2
  545. package/src/runtime/routes/host-cu-routes.ts +2 -2
  546. package/src/runtime/routes/identity-routes.ts +21 -0
  547. package/src/runtime/routes/inbound-message-handler.ts +288 -58
  548. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  549. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
  550. package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
  551. package/src/runtime/routes/index.ts +20 -4
  552. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  553. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  554. package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
  555. package/src/runtime/routes/integrations/a2a.ts +60 -1
  556. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  557. package/src/runtime/routes/log-export-routes.ts +39 -0
  558. package/src/runtime/routes/memory-item-routes.ts +8 -3
  559. package/src/runtime/routes/memory-v2-routes.ts +427 -0
  560. package/src/runtime/routes/memory-v3-routes.ts +316 -0
  561. package/src/runtime/routes/migration-routes.ts +21 -24
  562. package/src/runtime/routes/notification-routes.ts +19 -2
  563. package/src/runtime/routes/plugins-routes.ts +337 -0
  564. package/src/runtime/routes/question-routes.ts +4 -1
  565. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  566. package/src/runtime/routes/sanity-routes.ts +159 -0
  567. package/src/runtime/routes/secret-routes.ts +25 -5
  568. package/src/runtime/routes/settings-routes.ts +12 -11
  569. package/src/runtime/routes/slack-channel-routes.ts +188 -0
  570. package/src/runtime/routes/workspace-routes.ts +25 -10
  571. package/src/runtime/services/conversation-serializer.ts +30 -4
  572. package/src/runtime/sync/resource-sync-events.ts +106 -38
  573. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  574. package/src/runtime/sync/sync-publisher.ts +2 -1
  575. package/src/runtime/verification-outbound-actions.ts +73 -1
  576. package/src/schedule/integration-status.ts +3 -1
  577. package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
  578. package/src/security/oauth2-device-code.ts +307 -0
  579. package/src/security/oauth2.ts +26 -9
  580. package/src/security/secure-keys.ts +5 -0
  581. package/src/skills/catalog-install.ts +6 -2
  582. package/src/telemetry/types.ts +12 -0
  583. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  584. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  585. package/src/tools/acp/spawn.test.ts +119 -0
  586. package/src/tools/acp/spawn.ts +15 -2
  587. package/src/tools/apps/definitions.ts +2 -8
  588. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  589. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  590. package/src/tools/browser/__tests__/pinned-tabs.test.ts +150 -0
  591. package/src/tools/browser/browser-execution.ts +106 -0
  592. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  593. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
  594. package/src/tools/browser/cdp-client/__tests__/types.test.ts +4 -0
  595. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +22 -0
  596. package/src/tools/browser/cdp-client/extension-cdp-client.ts +42 -2
  597. package/src/tools/browser/cdp-client/factory.ts +171 -4
  598. package/src/tools/browser/cdp-client/local-cdp-client.ts +21 -0
  599. package/src/tools/browser/cdp-client/types.ts +101 -0
  600. package/src/tools/browser/pinned-tabs.ts +146 -0
  601. package/src/tools/computer-use/definitions.ts +22 -78
  602. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  603. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  604. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  605. package/src/tools/credentials/vault.ts +3 -9
  606. package/src/tools/document/document-comment-tool.test.ts +379 -0
  607. package/src/tools/document/document-comment-tool.ts +156 -0
  608. package/src/tools/document/document-tool.ts +187 -2
  609. package/src/tools/execution-target.ts +21 -23
  610. package/src/tools/executor.ts +6 -1
  611. package/src/tools/filesystem/edit.ts +3 -9
  612. package/src/tools/filesystem/list.ts +3 -9
  613. package/src/tools/filesystem/read.ts +3 -9
  614. package/src/tools/filesystem/write.ts +3 -9
  615. package/src/tools/host-filesystem/edit.ts +3 -9
  616. package/src/tools/host-filesystem/read.ts +3 -9
  617. package/src/tools/host-filesystem/transfer.ts +3 -9
  618. package/src/tools/host-filesystem/write.ts +3 -9
  619. package/src/tools/host-terminal/host-shell.ts +3 -9
  620. package/src/tools/mcp/mcp-tool-factory.ts +1 -8
  621. package/src/tools/memory/register.test.ts +1 -1
  622. package/src/tools/memory/register.ts +4 -9
  623. package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
  624. package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
  625. package/src/tools/network/domain-normalize.ts +17 -0
  626. package/src/tools/network/web-fetch.ts +216 -73
  627. package/src/tools/network/web-search.ts +216 -98
  628. package/src/tools/registry.ts +7 -23
  629. package/src/tools/schema-transforms.ts +1 -1
  630. package/src/tools/skills/execute.ts +3 -9
  631. package/src/tools/skills/load.ts +3 -9
  632. package/src/tools/skills/skill-tool-factory.ts +1 -8
  633. package/src/tools/subagent/notify-parent.ts +3 -9
  634. package/src/tools/system/request-permission.ts +3 -9
  635. package/src/tools/terminal/safe-env.ts +3 -2
  636. package/src/tools/terminal/shell.ts +3 -9
  637. package/src/tools/tool-approval-handler.ts +19 -12
  638. package/src/tools/tool-defaults.ts +94 -0
  639. package/src/tools/types.ts +31 -98
  640. package/src/tools/ui-surface/definitions.ts +9 -23
  641. package/src/types/onboarding-context.ts +4 -0
  642. package/src/usage/pricing.ts +23 -0
  643. package/src/usage/types.ts +12 -0
  644. package/src/util/__tests__/favicon.test.ts +84 -0
  645. package/src/util/favicon.ts +40 -0
  646. package/src/util/logger.ts +16 -7
  647. package/src/util/platform.ts +7 -7
  648. package/src/util/sqlite3-runtime.ts +65 -0
  649. package/src/workspace/git-service.ts +75 -4
  650. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  651. package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
  652. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  653. package/src/workspace/migrations/registry.ts +4 -0
  654. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  655. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  656. package/src/config/bundled-skills/document/SKILL.md +0 -54
  657. package/src/config/bundled-skills/document/TOOLS.json +0 -106
  658. package/src/daemon/seed-files.ts +0 -18
  659. package/src/prompts/cache-boundary.ts +0 -8
  660. package/src/runtime/routes/interface-routes.ts +0 -43
  661. /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
  662. /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
  663. /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
  664. /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
  665. /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
@@ -0,0 +1,188 @@
1
+ import { z } from "zod";
2
+
3
+ import {
4
+ conversationMetadataSyncTag,
5
+ SYNC_TAGS,
6
+ } from "../../daemon/message-types/sync.js";
7
+ import {
8
+ getBindingByConversation,
9
+ updateExternalChatName,
10
+ } from "../../memory/external-conversation-store.js";
11
+ import {
12
+ getSlackConversationInfo,
13
+ SlackApiError,
14
+ } from "../../messaging/providers/slack/api.js";
15
+ import { publishSyncInvalidation } from "../sync/sync-publisher.js";
16
+ import { NotFoundError } from "./errors.js";
17
+ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
18
+
19
+ type ResolveReason =
20
+ | "auth"
21
+ | "dm"
22
+ | "no_name"
23
+ | "not_found"
24
+ | "permission"
25
+ | "rate_limit"
26
+ | "slack_error";
27
+
28
+ interface SlackChannelResolveResponse {
29
+ channelId: string;
30
+ channelName?: string;
31
+ cached: boolean;
32
+ resolved: boolean;
33
+ reason?: ResolveReason;
34
+ }
35
+
36
+ const SlackChannelResolveResponseSchema = z.object({
37
+ channelId: z.string(),
38
+ channelName: z.string().optional(),
39
+ cached: z.boolean(),
40
+ resolved: z.boolean(),
41
+ reason: z
42
+ .enum([
43
+ "auth",
44
+ "dm",
45
+ "no_name",
46
+ "not_found",
47
+ "permission",
48
+ "rate_limit",
49
+ "slack_error",
50
+ ])
51
+ .optional(),
52
+ });
53
+
54
+ function friendlyCachedName(
55
+ externalChatId: string,
56
+ externalChatName?: string | null,
57
+ ): string | undefined {
58
+ const trimmed = externalChatName?.trim();
59
+ if (!trimmed || trimmed === externalChatId) return undefined;
60
+ return trimmed;
61
+ }
62
+
63
+ function usableResolvedName(
64
+ externalChatId: string,
65
+ name?: string,
66
+ nameNormalized?: string,
67
+ ): string | undefined {
68
+ for (const candidate of [name, nameNormalized]) {
69
+ const trimmed = candidate?.trim();
70
+ if (trimmed && trimmed !== externalChatId) return trimmed;
71
+ }
72
+ return undefined;
73
+ }
74
+
75
+ function reasonForSlackError(err: unknown): ResolveReason {
76
+ if (err instanceof SlackApiError) {
77
+ switch (err.category) {
78
+ case "auth":
79
+ return "auth";
80
+ case "channel_not_found":
81
+ case "not_found":
82
+ return "not_found";
83
+ case "permission":
84
+ return "permission";
85
+ case "rate_limit":
86
+ return "rate_limit";
87
+ default:
88
+ return "slack_error";
89
+ }
90
+ }
91
+ return "slack_error";
92
+ }
93
+
94
+ async function handleSlackChannelNameResolve({
95
+ pathParams = {},
96
+ headers,
97
+ }: RouteHandlerArgs): Promise<SlackChannelResolveResponse> {
98
+ const conversationId = pathParams.conversationId?.trim();
99
+ if (!conversationId) {
100
+ throw new NotFoundError("Conversation not found");
101
+ }
102
+
103
+ const binding = getBindingByConversation(conversationId);
104
+
105
+ if (!binding || binding.sourceChannel !== "slack") {
106
+ throw new NotFoundError("Conversation not found");
107
+ }
108
+
109
+ const channelId = binding.externalChatId;
110
+ const cachedName = friendlyCachedName(channelId, binding.externalChatName);
111
+ if (cachedName) {
112
+ return {
113
+ channelId,
114
+ channelName: cachedName,
115
+ cached: true,
116
+ resolved: true,
117
+ };
118
+ }
119
+
120
+ if (channelId.startsWith("D")) {
121
+ return {
122
+ channelId,
123
+ cached: false,
124
+ resolved: false,
125
+ reason: "dm",
126
+ };
127
+ }
128
+
129
+ let info;
130
+ try {
131
+ info = await getSlackConversationInfo(channelId);
132
+ } catch (err) {
133
+ return {
134
+ channelId,
135
+ cached: false,
136
+ resolved: false,
137
+ reason: reasonForSlackError(err),
138
+ };
139
+ }
140
+
141
+ const channelName = usableResolvedName(
142
+ channelId,
143
+ info?.name,
144
+ info?.nameNormalized,
145
+ );
146
+ if (!channelName) {
147
+ return {
148
+ channelId,
149
+ cached: false,
150
+ resolved: false,
151
+ reason: "no_name",
152
+ };
153
+ }
154
+
155
+ updateExternalChatName(conversationId, channelName);
156
+ await publishSyncInvalidation(
157
+ [SYNC_TAGS.conversationsList, conversationMetadataSyncTag(conversationId)],
158
+ headers?.["x-vellum-client-id"]?.trim() || undefined,
159
+ );
160
+
161
+ return {
162
+ channelId,
163
+ channelName,
164
+ cached: false,
165
+ resolved: true,
166
+ };
167
+ }
168
+
169
+ export const ROUTES: RouteDefinition[] = [
170
+ {
171
+ operationId: "slack_channel_name_resolve",
172
+ endpoint: "conversations/:conversationId/slack-channel/resolve",
173
+ method: "POST",
174
+ handler: handleSlackChannelNameResolve,
175
+ summary: "Resolve Slack channel name",
176
+ description:
177
+ "Resolve and persist a friendly Slack channel name for an external conversation binding.",
178
+ tags: ["conversations", "slack"],
179
+ pathParams: [
180
+ {
181
+ name: "conversationId",
182
+ type: "string",
183
+ description: "Conversation ID whose Slack channel name should resolve.",
184
+ },
185
+ ],
186
+ responseBody: SlackChannelResolveResponseSchema,
187
+ },
188
+ ];
@@ -59,9 +59,12 @@ function isSoundsWorkspacePath(path: string): boolean {
59
59
  );
60
60
  }
61
61
 
62
- function publishSoundsConfigUpdatedForPaths(paths: string[]): void {
62
+ function publishSoundsConfigUpdatedForPaths(
63
+ paths: string[],
64
+ originClientId?: string,
65
+ ): void {
63
66
  if (paths.some(isSoundsWorkspacePath)) {
64
- publishSoundsConfigUpdated();
67
+ publishSoundsConfigUpdated(originClientId);
65
68
  }
66
69
  }
67
70
 
@@ -263,7 +266,7 @@ function handleWorkspaceFileContent({
263
266
  // POST /v1/workspace/write — create or overwrite a file
264
267
  // ---------------------------------------------------------------------------
265
268
 
266
- function handleWorkspaceWrite({ body }: RouteHandlerArgs) {
269
+ function handleWorkspaceWrite({ body, headers }: RouteHandlerArgs) {
267
270
  const path = body?.path as string | undefined;
268
271
  const content = body?.content as string | undefined;
269
272
  const encoding = body?.encoding as string | undefined;
@@ -292,7 +295,10 @@ function handleWorkspaceWrite({ body }: RouteHandlerArgs) {
292
295
 
293
296
  mkdirSync(dirname(resolved), { recursive: true });
294
297
  writeFileSync(resolved, buffer);
295
- publishSoundsConfigUpdatedForPaths([path]);
298
+ publishSoundsConfigUpdatedForPaths(
299
+ [path],
300
+ headers?.["x-vellum-client-id"]?.trim() || undefined,
301
+ );
296
302
 
297
303
  return { path, size: buffer.byteLength };
298
304
  }
@@ -301,7 +307,7 @@ function handleWorkspaceWrite({ body }: RouteHandlerArgs) {
301
307
  // POST /v1/workspace/mkdir — create directories
302
308
  // ---------------------------------------------------------------------------
303
309
 
304
- function handleWorkspaceMkdir({ body }: RouteHandlerArgs) {
310
+ function handleWorkspaceMkdir({ body, headers }: RouteHandlerArgs) {
305
311
  const path = body?.path as string | undefined;
306
312
  if (!path) {
307
313
  throw new BadRequestError("path is required");
@@ -320,7 +326,10 @@ function handleWorkspaceMkdir({ body }: RouteHandlerArgs) {
320
326
  }
321
327
 
322
328
  mkdirSync(resolved, { recursive: true });
323
- publishSoundsConfigUpdatedForPaths([path]);
329
+ publishSoundsConfigUpdatedForPaths(
330
+ [path],
331
+ headers?.["x-vellum-client-id"]?.trim() || undefined,
332
+ );
324
333
  return { path };
325
334
  }
326
335
 
@@ -328,7 +337,7 @@ function handleWorkspaceMkdir({ body }: RouteHandlerArgs) {
328
337
  // POST /v1/workspace/rename — rename/move files and directories
329
338
  // ---------------------------------------------------------------------------
330
339
 
331
- function handleWorkspaceRename({ body }: RouteHandlerArgs) {
340
+ function handleWorkspaceRename({ body, headers }: RouteHandlerArgs) {
332
341
  const oldPath = body?.oldPath as string | undefined;
333
342
  const newPath = body?.newPath as string | undefined;
334
343
  if (!oldPath || !newPath) {
@@ -360,7 +369,10 @@ function handleWorkspaceRename({ body }: RouteHandlerArgs) {
360
369
 
361
370
  mkdirSync(dirname(resolvedNew), { recursive: true });
362
371
  renameSync(resolvedOld, resolvedNew);
363
- publishSoundsConfigUpdatedForPaths([oldPath, newPath]);
372
+ publishSoundsConfigUpdatedForPaths(
373
+ [oldPath, newPath],
374
+ headers?.["x-vellum-client-id"]?.trim() || undefined,
375
+ );
364
376
  return { oldPath, newPath };
365
377
  }
366
378
 
@@ -368,7 +380,7 @@ function handleWorkspaceRename({ body }: RouteHandlerArgs) {
368
380
  // POST /v1/workspace/delete — delete files and directories
369
381
  // ---------------------------------------------------------------------------
370
382
 
371
- function handleWorkspaceDelete({ body }: RouteHandlerArgs) {
383
+ function handleWorkspaceDelete({ body, headers }: RouteHandlerArgs) {
372
384
  const path = body?.path as string | undefined;
373
385
  if (!path) {
374
386
  throw new BadRequestError("path is required");
@@ -388,7 +400,10 @@ function handleWorkspaceDelete({ body }: RouteHandlerArgs) {
388
400
  }
389
401
 
390
402
  rmSync(resolved, { recursive: true, force: true });
391
- publishSoundsConfigUpdatedForPaths([path]);
403
+ publishSoundsConfigUpdatedForPaths(
404
+ [path],
405
+ headers?.["x-vellum-client-id"]?.trim() || undefined,
406
+ );
392
407
  return { success: true };
393
408
  }
394
409
 
@@ -23,7 +23,10 @@ import {
23
23
  } from "../../memory/conversation-crud.js";
24
24
  import type { ExternalConversationBinding } from "../../memory/external-conversation-store.js";
25
25
  import { getBindingsForConversations } from "../../memory/external-conversation-store.js";
26
- import { buildSlackMessageDeepLinks } from "../../messaging/providers/slack/deep-link.js";
26
+ import {
27
+ buildSlackMessageDeepLinks,
28
+ buildSlackWebChannelUrl,
29
+ } from "../../messaging/providers/slack/deep-link.js";
27
30
 
28
31
  // ---------------------------------------------------------------------------
29
32
  // Helpers
@@ -91,10 +94,11 @@ function buildForkParent(
91
94
  }
92
95
 
93
96
  function buildChannelBinding(binding: ExternalConversationBinding) {
97
+ const externalChatName =
98
+ binding.externalChatName?.trim() ||
99
+ (binding.sourceChannel === "slack" ? binding.externalChatId : undefined);
94
100
  const slackConfig =
95
- binding.sourceChannel === "slack" && binding.externalThreadId
96
- ? getConfig().slack
97
- : undefined;
101
+ binding.sourceChannel === "slack" ? getConfig().slack : undefined;
98
102
  const slackThreadLink =
99
103
  slackConfig && binding.externalThreadId
100
104
  ? buildSlackMessageDeepLinks({
@@ -112,10 +116,31 @@ function buildChannelBinding(binding: ExternalConversationBinding) {
112
116
  ...(slackThreadLink ? { link: slackThreadLink } : {}),
113
117
  }
114
118
  : undefined;
119
+ const slackChannelWebUrl = slackConfig
120
+ ? buildSlackWebChannelUrl({
121
+ teamUrl: slackConfig.teamUrl,
122
+ channelId: binding.externalChatId,
123
+ })
124
+ : undefined;
125
+ const slackChannel =
126
+ binding.sourceChannel === "slack"
127
+ ? {
128
+ channelId: binding.externalChatId,
129
+ name: externalChatName,
130
+ ...(slackChannelWebUrl
131
+ ? {
132
+ link: {
133
+ webUrl: slackChannelWebUrl,
134
+ },
135
+ }
136
+ : {}),
137
+ }
138
+ : undefined;
115
139
 
116
140
  return {
117
141
  sourceChannel: binding.sourceChannel,
118
142
  externalChatId: binding.externalChatId,
143
+ ...(externalChatName ? { externalChatName } : {}),
119
144
  ...(binding.externalThreadId
120
145
  ? { externalThreadId: binding.externalThreadId }
121
146
  : {}),
@@ -123,6 +148,7 @@ function buildChannelBinding(binding: ExternalConversationBinding) {
123
148
  displayName: binding.displayName,
124
149
  username: binding.username,
125
150
  ...(slackThread ? { slackThread } : {}),
151
+ ...(slackChannel ? { slackChannel } : {}),
126
152
  };
127
153
  }
128
154
 
@@ -9,15 +9,18 @@ import { getAvatarImagePath } from "../../util/platform.js";
9
9
  import { broadcastMessage } from "../assistant-event-hub.js";
10
10
  import { publishSyncInvalidation } from "./sync-publisher.js";
11
11
 
12
- export function publishAvatarChanged(): void {
12
+ export function publishAvatarChanged(originClientId?: string): void {
13
13
  broadcastMessage({
14
14
  type: "avatar_updated",
15
15
  avatarPath: getAvatarImagePath(),
16
16
  });
17
- void publishSyncInvalidation([SYNC_TAGS.assistantAvatar]);
17
+ void publishSyncInvalidation([SYNC_TAGS.assistantAvatar], originClientId);
18
18
  }
19
19
 
20
- export function publishIdentityChanged(fields: IdentityFields): void {
20
+ export function publishIdentityChanged(
21
+ fields: IdentityFields,
22
+ originClientId?: string,
23
+ ): void {
21
24
  broadcastMessage({
22
25
  type: "identity_changed",
23
26
  name: fields.name,
@@ -26,59 +29,112 @@ export function publishIdentityChanged(fields: IdentityFields): void {
26
29
  emoji: fields.emoji,
27
30
  home: fields.home,
28
31
  });
29
- void publishSyncInvalidation([SYNC_TAGS.assistantIdentity]);
32
+ void publishSyncInvalidation([SYNC_TAGS.assistantIdentity], originClientId);
30
33
  }
31
34
 
32
- export function publishConfigChanged(): void {
35
+ export function publishConfigChanged(originClientId?: string): void {
33
36
  broadcastMessage({ type: "config_changed" });
34
- void publishSyncInvalidation([SYNC_TAGS.assistantConfig]);
37
+ void publishSyncInvalidation([SYNC_TAGS.assistantConfig], originClientId);
35
38
  }
36
39
 
37
- export function publishSoundsConfigUpdated(): void {
40
+ export function publishSoundsConfigUpdated(originClientId?: string): void {
38
41
  broadcastMessage({ type: "sounds_config_updated" });
39
- void publishSyncInvalidation([SYNC_TAGS.assistantSounds]);
42
+ void publishSyncInvalidation([SYNC_TAGS.assistantSounds], originClientId);
40
43
  }
41
44
 
42
- export function publishSchedulesChanged(): void {
43
- void publishSyncInvalidation([SYNC_TAGS.assistantSchedules]);
45
+ export function publishSchedulesChanged(originClientId?: string): void {
46
+ void publishSyncInvalidation([SYNC_TAGS.assistantSchedules], originClientId);
47
+ }
48
+
49
+ /**
50
+ * Reasons that change the *shape* of the conversation list — a row is
51
+ * added, removed, or its position changes. These require web clients to
52
+ * refetch the paginated list because the row patch path (`refreshConversationRow`)
53
+ * only handles a single known id. Reasons not in this set are *content-only*
54
+ * changes to an existing row (e.g. `seen_changed`, `renamed`) and are
55
+ * delivered exclusively via the per-conversation `sync_changed` tag, which
56
+ * web consumes by GET-and-patching the single row.
57
+ */
58
+ const SHAPE_CHANGING_REASONS: ReadonlySet<ConversationListInvalidatedReason> =
59
+ new Set(["created", "deleted", "reordered"]);
60
+
61
+ /**
62
+ * Publish the legacy `conversation_list_invalidated` broadcast to macOS
63
+ * subscribers only.
64
+ *
65
+ * Web consumes `sync_changed` (`conversationsList` for shape changes,
66
+ * `conversation:<id>:metadata` for content changes) directly and patches
67
+ * the cached list in place — see `useAssistantSyncStream` for the consumer
68
+ * side. macOS (`ConversationRestorer.swift`) still listens for the typed
69
+ * broadcast.
70
+ *
71
+ * TODO(electron-cutover): remove this helper and all callers once macOS
72
+ * migrates to the Electron client and consumes `sync_changed` directly.
73
+ * At that point the `conversation_list_invalidated` message type can be
74
+ * retired entirely.
75
+ */
76
+ function broadcastConversationListInvalidatedToMacos(
77
+ reason: ConversationListInvalidatedReason,
78
+ ): void {
79
+ broadcastMessage(
80
+ {
81
+ type: "conversation_list_invalidated",
82
+ reason,
83
+ },
84
+ undefined,
85
+ { targetInterfaceId: "macos" },
86
+ );
44
87
  }
45
88
 
46
89
  export function publishConversationListChanged(
47
90
  reason: ConversationListInvalidatedReason,
91
+ originClientId?: string,
48
92
  ): void {
49
- broadcastMessage({
50
- type: "conversation_list_invalidated",
51
- reason,
52
- });
53
- void publishSyncInvalidation([SYNC_TAGS.conversationsList]);
93
+ broadcastConversationListInvalidatedToMacos(reason);
94
+ void publishSyncInvalidation([SYNC_TAGS.conversationsList], originClientId);
54
95
  }
55
96
 
56
97
  export function publishConversationMessagesChanged(
57
98
  conversationId: string,
99
+ originClientId?: string,
58
100
  ): void {
59
- void publishSyncInvalidation([conversationMessagesSyncTag(conversationId)]);
101
+ void publishSyncInvalidation(
102
+ [conversationMessagesSyncTag(conversationId)],
103
+ originClientId,
104
+ );
60
105
  }
61
106
 
62
107
  export function publishConversationListAndMetadataChanged(
63
108
  reason: ConversationListInvalidatedReason,
64
109
  conversationIds: string | string[],
110
+ originClientId?: string,
65
111
  ): void {
66
112
  const ids = Array.isArray(conversationIds)
67
113
  ? conversationIds
68
114
  : [conversationIds];
69
- broadcastMessage({
70
- type: "conversation_list_invalidated",
71
- reason,
72
- });
73
- void publishSyncInvalidation([
74
- SYNC_TAGS.conversationsList,
75
- ...ids.map((conversationId) => conversationMetadataSyncTag(conversationId)),
76
- ]);
115
+ broadcastConversationListInvalidatedToMacos(reason);
116
+
117
+ // Shape-changing reasons (`created`, `deleted`, `reordered`) add or
118
+ // remove rows or change the order of the paginated window — web must
119
+ // refetch the list, so include the `conversationsList` umbrella tag.
120
+ // Content-only reasons (`renamed`, `seen_changed`) modify an existing
121
+ // row; web consumes the per-conversation metadata tag and GET-and-
122
+ // patches the single row, avoiding the full paginated list drain
123
+ // (`limit=50&offset=0..N` × foreground + background — ~14 requests
124
+ // per write at a few hundred conversations).
125
+ const tags: string[] = ids.map((conversationId) =>
126
+ conversationMetadataSyncTag(conversationId),
127
+ );
128
+ if (SHAPE_CHANGING_REASONS.has(reason)) {
129
+ tags.unshift(SYNC_TAGS.conversationsList);
130
+ }
131
+ void publishSyncInvalidation(tags, originClientId);
77
132
  }
78
133
 
79
134
  export function publishConversationTitleChanged(
80
135
  conversationId: string,
81
136
  title: string,
137
+ originClientId?: string,
82
138
  ): void {
83
139
  broadcastMessage(
84
140
  {
@@ -88,18 +144,27 @@ export function publishConversationTitleChanged(
88
144
  },
89
145
  conversationId,
90
146
  );
91
- void publishSyncInvalidation([
92
- SYNC_TAGS.conversationsList,
93
- conversationMetadataSyncTag(conversationId),
94
- ]);
147
+ // Renames are content-only — the paired typed `conversation_title_updated`
148
+ // event already carries the new title and patches the row in place on
149
+ // web; macOS receives the per-interface `conversation_list_invalidated`
150
+ // emitted from `broadcastMessage` (see `assistant-event-hub.ts`). The
151
+ // `sync_changed` metadata tag is included as a belt-and-suspenders signal
152
+ // for any sibling-tab consumer that missed the typed event.
153
+ void publishSyncInvalidation(
154
+ [conversationMetadataSyncTag(conversationId)],
155
+ originClientId,
156
+ );
95
157
  }
96
158
 
97
- export function publishConversationInferenceProfileChanged(params: {
98
- conversationId: string;
99
- profile: string | null;
100
- sessionId?: string | null;
101
- expiresAt?: number | null;
102
- }): void {
159
+ export function publishConversationInferenceProfileChanged(
160
+ params: {
161
+ conversationId: string;
162
+ profile: string | null;
163
+ sessionId?: string | null;
164
+ expiresAt?: number | null;
165
+ },
166
+ originClientId?: string,
167
+ ): void {
103
168
  broadcastMessage(
104
169
  {
105
170
  type: "conversation_inference_profile_updated",
@@ -110,8 +175,11 @@ export function publishConversationInferenceProfileChanged(params: {
110
175
  },
111
176
  params.conversationId,
112
177
  );
113
- void publishSyncInvalidation([
114
- SYNC_TAGS.conversationsList,
115
- conversationMetadataSyncTag(params.conversationId),
116
- ]);
178
+ void publishSyncInvalidation(
179
+ [
180
+ SYNC_TAGS.conversationsList,
181
+ conversationMetadataSyncTag(params.conversationId),
182
+ ],
183
+ originClientId,
184
+ );
117
185
  }
@@ -102,4 +102,53 @@ describe("sync publisher", () => {
102
102
  subscription.dispose();
103
103
  }
104
104
  });
105
+
106
+ test("forwards originClientId when provided", async () => {
107
+ const received: AssistantEvent[] = [];
108
+ const subscription = assistantEventHub.subscribe({
109
+ type: "process",
110
+ callback: (event) => {
111
+ received.push(event);
112
+ },
113
+ });
114
+
115
+ try {
116
+ const message = await publishSyncInvalidation(
117
+ [SYNC_TAGS.assistantAvatar],
118
+ "client-abc",
119
+ );
120
+
121
+ await waitFor(() => received.length === 1);
122
+
123
+ expect(message).toEqual({
124
+ type: "sync_changed",
125
+ tags: [SYNC_TAGS.assistantAvatar],
126
+ originClientId: "client-abc",
127
+ });
128
+ expect(received[0].message).toEqual(message);
129
+ } finally {
130
+ subscription.dispose();
131
+ }
132
+ });
133
+
134
+ test("omits originClientId when not provided", async () => {
135
+ const received: AssistantEvent[] = [];
136
+ const subscription = assistantEventHub.subscribe({
137
+ type: "process",
138
+ callback: (event) => {
139
+ received.push(event);
140
+ },
141
+ });
142
+
143
+ try {
144
+ const message = await publishSyncInvalidation([SYNC_TAGS.assistantAvatar]);
145
+
146
+ await waitFor(() => received.length === 1);
147
+
148
+ expect("originClientId" in message).toBe(false);
149
+ expect(received[0].message).toEqual(message);
150
+ } finally {
151
+ subscription.dispose();
152
+ }
153
+ });
105
154
  });
@@ -10,8 +10,9 @@ const log = getLogger("sync-publisher");
10
10
 
11
11
  export async function publishSyncInvalidation(
12
12
  tags: SyncInvalidationTag[],
13
+ originClientId?: string,
13
14
  ): Promise<SyncChangedMessage> {
14
- const message = buildSyncChangedMessage(tags);
15
+ const message = buildSyncChangedMessage(tags, originClientId);
15
16
  try {
16
17
  broadcastMessage(message);
17
18
  } catch (err) {