@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
@@ -9,6 +9,7 @@ import { existsSync, readFileSync, statSync } from "node:fs";
9
9
  import { join, resolve } from "node:path";
10
10
 
11
11
  import { type ChannelId, parseInterfaceId } from "../channels/types.js";
12
+ import { getConfig } from "../config/loader.js";
12
13
  import { createContextSummaryMessage } from "../context/window-manager.js";
13
14
  import { getAppDirPath, listAppFiles } from "../memory/app-store.js";
14
15
  import {
@@ -20,15 +21,16 @@ import {
20
21
  extractMemoryPrefixBlocks,
21
22
  } from "../memory/graph/conversation-graph-memory.js";
22
23
  import type { QdrantSparseVector } from "../memory/qdrant-client.js";
23
- import { readSlackMetadata } from "../messaging/providers/slack/message-metadata.js";
24
+ import {
25
+ readSlackMetadata,
26
+ readSlackMetadataFromMessageMetadata,
27
+ } from "../messaging/providers/slack/message-metadata.js";
24
28
  import {
25
29
  compareSlackTs,
26
30
  extractTagLineTexts,
27
- isReactionTagLine,
28
31
  isSlackTsAfter,
29
32
  type RenderableSlackMessage,
30
33
  type RenderedSlackTranscriptMessage,
31
- renderSlackTranscript,
32
34
  renderSlackTranscriptWithProvenance,
33
35
  } from "../messaging/providers/slack/render-transcript.js";
34
36
  import { getInjectors } from "../plugins/registry.js";
@@ -48,6 +50,7 @@ import {
48
50
  import { channelStatusToMemberStatus } from "../runtime/routes/inbound-stages/acl-enforcement.js";
49
51
  import type { SubagentState } from "../subagent/types.js";
50
52
  import { TERMINAL_STATUSES } from "../subagent/types.js";
53
+ import { canonicalizeInboundIdentity } from "../util/canonicalize-identity.js";
51
54
  import { getWorkspaceDir, getWorkspacePromptPath } from "../util/platform.js";
52
55
  import { stripCommentLines } from "../util/strip-comment-lines.js";
53
56
  import { filterMessagesForUntrustedActor } from "./conversation-lifecycle.js";
@@ -680,18 +683,19 @@ export function injectChannelCapabilityContext(
680
683
  "- Do NOT reference the dashboard UI, settings panels, or visual preference pickers.",
681
684
  );
682
685
  if (!caps.supportsDynamicUi) {
683
- lines.push(
684
- "- Do NOT use ui_show, ui_update, or app_create — this channel cannot render them.",
685
- );
686
+ if (caps.channel === "slack") {
687
+ lines.push(
688
+ '- Do NOT use app_create. Only use ui_show/ui_update for card surfaces with template: "task_progress"; present all other information as text.',
689
+ );
690
+ } else {
691
+ lines.push(
692
+ "- Do NOT use ui_show, ui_update, or app_create — this channel cannot render them.",
693
+ );
694
+ }
686
695
  lines.push(
687
696
  "- Present information as well-formatted text instead of dynamic UI.",
688
697
  );
689
698
  }
690
- lines.push(
691
- "- Defer dashboard-specific actions (e.g. accent color selection) by telling the user",
692
- );
693
- lines.push(" they can complete those steps later from the desktop app.");
694
-
695
699
  if (caps.channel === "whatsapp") {
696
700
  lines.push(
697
701
  "- Do NOT use markdown tables — use bullet lists instead. No markdown headers — use **bold** or CAPS for emphasis.",
@@ -699,10 +703,6 @@ export function injectChannelCapabilityContext(
699
703
  }
700
704
  }
701
705
 
702
- if (!caps.supportsVoiceInput) {
703
- lines.push("- Do NOT ask the user to use voice or microphone input.");
704
- }
705
-
706
706
  // Inject group chat etiquette only when the chat type indicates a multi-party
707
707
  // conversation, avoiding misconditioned "stay silent" guidance in 1:1 DMs.
708
708
  if (isGroupChatType(caps.chatType)) {
@@ -798,6 +798,13 @@ export interface UnifiedTurnContextOptions {
798
798
  * the model can acknowledge long absences; otherwise omitted.
799
799
  */
800
800
  timeSinceLastMessage?: string | null;
801
+ /**
802
+ * Human-readable model profile description. Only populated when the active
803
+ * inference profile changed since the last turn (or on the first turn of a
804
+ * conversation) so the model knows which profile/model it is using without
805
+ * paying per-turn token cost.
806
+ */
807
+ modelProfile?: string | null;
801
808
  }
802
809
 
803
810
  /**
@@ -856,6 +863,9 @@ export function buildUnifiedTurnContextBlock(
856
863
  if (options.timeSinceLastMessage) {
857
864
  lines.push(`time_since_last_message: ${options.timeSinceLastMessage}`);
858
865
  }
866
+ if (options.modelProfile) {
867
+ lines.push(`model_profile: ${options.modelProfile}`);
868
+ }
859
869
  if (options.interfaceName) {
860
870
  lines.push(`interface: ${options.interfaceName}`);
861
871
  }
@@ -973,6 +983,9 @@ export function buildUnifiedTurnContextBlock(
973
983
  lines.push(
974
984
  `response_discretion: Not every message in a channel thread requires your response. If a message is clearly not directed at you (e.g. people talking among themselves, acknowledgements, reactions), output exactly <no_response/> as your entire reply to stay silent.`,
975
985
  );
986
+ if (options.channelName === "slack") {
987
+ lines.push("if you are going to do work, use task_progress");
988
+ }
976
989
  }
977
990
 
978
991
  lines.push("</turn_context>");
@@ -1032,17 +1045,6 @@ function injectTransportHints(message: Message, hints: string[]): Message {
1032
1045
  };
1033
1046
  }
1034
1047
 
1035
- function injectSlackRuntimeContextNotice(
1036
- message: Message,
1037
- notice: string,
1038
- ): Message {
1039
- const block = `<slack_context_notice>\n${notice}\n</slack_context_notice>`;
1040
- return {
1041
- ...message,
1042
- content: [{ type: "text", text: block }, ...message.content],
1043
- };
1044
- }
1045
-
1046
1048
  // ---------------------------------------------------------------------------
1047
1049
  // Slack chronological transcript assembly
1048
1050
  // ---------------------------------------------------------------------------
@@ -1111,6 +1113,27 @@ function messageRowsToSlackTranscriptRows(
1111
1113
  }));
1112
1114
  }
1113
1115
 
1116
+ function hasSlackMetadata(row: MessageRow): boolean {
1117
+ return (
1118
+ readSlackMetadataFromMessageMetadata(row.metadata, {
1119
+ allowFlatLegacy: true,
1120
+ }) !== null
1121
+ );
1122
+ }
1123
+
1124
+ function filterSlackConversationRowsForActor(
1125
+ rows: MessageRow[],
1126
+ trustClass: TrustClass | undefined,
1127
+ ): MessageRow[] {
1128
+ if (!isUntrustedTrustClass(trustClass)) return rows;
1129
+ const nonSlackVisibleRows = filterMessagesForUntrustedActor(rows);
1130
+ const nonSlackVisibleIds = new Set(nonSlackVisibleRows.map((row) => row.id));
1131
+ return rows.filter((row) => {
1132
+ if (hasSlackMetadata(row)) return true;
1133
+ return nonSlackVisibleIds.has(row.id);
1134
+ });
1135
+ }
1136
+
1114
1137
  /**
1115
1138
  * Extract the user-facing plain text from an already-parsed `ContentBlock[]`.
1116
1139
  * Only `text` blocks contribute to the rendered transcript line. Tool-use /
@@ -1268,6 +1291,60 @@ function rowToRenderable(row: SlackTranscriptInputRow): RenderableSlackMessage {
1268
1291
  };
1269
1292
  }
1270
1293
 
1294
+ const SLACK_ASSISTANT_THREAD_PLACEHOLDER_TEXT = "New Assistant Thread";
1295
+
1296
+ function isSlackAssistantThreadPlaceholder(
1297
+ message: RenderableSlackMessage,
1298
+ canonicalConfiguredBotUserId: string | null,
1299
+ ): boolean {
1300
+ if (!canonicalConfiguredBotUserId) return false;
1301
+ const metadata = message.metadata;
1302
+ if (!metadata || metadata.eventKind !== "message") return false;
1303
+ const actorExternalUserId = metadata.actorExternalUserId?.trim();
1304
+ if (!actorExternalUserId) return false;
1305
+
1306
+ const canonicalActor =
1307
+ canonicalizeInboundIdentity("slack", actorExternalUserId) ??
1308
+ actorExternalUserId;
1309
+ const isThreadRoot =
1310
+ metadata.threadTs === undefined || metadata.threadTs === metadata.channelTs;
1311
+ const hasSlackFiles =
1312
+ Array.isArray(metadata.slackFiles) && metadata.slackFiles.length > 0;
1313
+
1314
+ return (
1315
+ message.role === "user" &&
1316
+ canonicalActor === canonicalConfiguredBotUserId &&
1317
+ isThreadRoot &&
1318
+ !hasSlackFiles &&
1319
+ message.content.replace(/\s+/g, " ").trim() ===
1320
+ SLACK_ASSISTANT_THREAD_PLACEHOLDER_TEXT
1321
+ );
1322
+ }
1323
+
1324
+ function getCanonicalConfiguredSlackBotUserId(): string | null {
1325
+ const configuredBotUserId = getConfig().slack.botUserId.trim();
1326
+ if (!configuredBotUserId) return null;
1327
+ return (
1328
+ canonicalizeInboundIdentity("slack", configuredBotUserId) ??
1329
+ configuredBotUserId
1330
+ );
1331
+ }
1332
+
1333
+ function rowsToRenderableSlackMessages(
1334
+ rows: SlackTranscriptInputRow[],
1335
+ ): RenderableSlackMessage[] {
1336
+ const canonicalConfiguredBotUserId = getCanonicalConfiguredSlackBotUserId();
1337
+ return rows
1338
+ .map(rowToRenderable)
1339
+ .filter(
1340
+ (message) =>
1341
+ !isSlackAssistantThreadPlaceholder(
1342
+ message,
1343
+ canonicalConfiguredBotUserId,
1344
+ ),
1345
+ );
1346
+ }
1347
+
1271
1348
  /**
1272
1349
  * Compatibility projection for callers that still need the legacy
1273
1350
  * `Message[] | null` shape. New runtime callers should use
@@ -1363,7 +1440,7 @@ function assembleSlackChronologicalContext(
1363
1440
  if (capabilities.channel !== "slack") {
1364
1441
  return null;
1365
1442
  }
1366
- const renderable = rows.map(rowToRenderable);
1443
+ const renderable = rowsToRenderableSlackMessages(rows);
1367
1444
  const rendered = renderSlackTranscriptWithProvenance(renderable);
1368
1445
  const contextSummary = options.contextSummary?.trim();
1369
1446
  const renderedMessages = rendered.renderedMessages;
@@ -1372,6 +1449,7 @@ function assembleSlackChronologicalContext(
1372
1449
  {
1373
1450
  message: createContextSummaryMessage(contextSummary),
1374
1451
  sourceChannelTs: null,
1452
+ tagLineProvenance: "none",
1375
1453
  },
1376
1454
  ...renderedMessages,
1377
1455
  ];
@@ -1392,11 +1470,10 @@ function assembleSlackChronologicalContext(
1392
1470
  * Compatibility wrapper over `loadSlackChronologicalContext` for callers that
1393
1471
  * still need only the legacy `Message[] | null` projection.
1394
1472
  *
1395
- * When `trustClass` identifies an untrusted actor (guardian-scoped rows
1396
- * must not leak into the model context), rows are passed through
1397
- * `filterMessagesForUntrustedActor` before assembly mirroring the
1398
- * filtering applied in `loadFromDb` so the chronological transcript
1399
- * respects the same per-actor scoping as the default history path.
1473
+ * When `trustClass` identifies an untrusted actor, non-Slack/private rows
1474
+ * are passed through the default trust filter. Slack-tagged rows stay visible
1475
+ * because the transcript is scoped to the external Slack chat/thread, which
1476
+ * the inbound actor can already read in Slack.
1400
1477
  *
1401
1478
  * Returns `null` when the channel is not Slack — callers should fall
1402
1479
  * through to the default in-memory message history.
@@ -1445,9 +1522,10 @@ export function loadSlackChronologicalContext(
1445
1522
  }
1446
1523
  const loader = options.loader ?? defaultGetMessages;
1447
1524
  const allRows = loader(conversationId);
1448
- const scopedRows = isUntrustedTrustClass(options.trustClass)
1449
- ? filterMessagesForUntrustedActor(allRows)
1450
- : allRows;
1525
+ const scopedRows = filterSlackConversationRowsForActor(
1526
+ allRows,
1527
+ options.trustClass,
1528
+ );
1451
1529
  const rows = filterRowsAfterSlackCompactionBoundary(
1452
1530
  messageRowsToSlackTranscriptRows(scopedRows),
1453
1531
  options,
@@ -1555,29 +1633,29 @@ function buildActiveThreadBlockFromRenderable(
1555
1633
  if (members.length === 0) return null;
1556
1634
 
1557
1635
  // The active-thread block is flattened to plain text below, which discards
1558
- // `Message.role`. Assistant rows are relabeled in the post-render step:
1559
- // `renderSlackTranscript` emits assistant content with no tag-line wrapper
1560
- // (to prevent the model mimicking `[MM/DD/YY HH:MM]:` prefixes in outbound
1561
- // replies), so we prepend an explicit `@assistant:` label to the flattened
1562
- // line. Unnamed user rows (no real Slack displayName) get a `@user`
1563
- // senderLabel here so their tag line carries attribution through the
1564
- // renderer. Labeled user rows and assistant rows pass through unchanged.
1636
+ // `Message.role`. Assistant rows that render content-only are relabeled in
1637
+ // the post-render step. Timezone-aware assistant rows are already
1638
+ // bracket-tagged by the renderer and must not receive another prefix.
1639
+ // Unnamed user rows (no real Slack displayName) get a `@user` senderLabel
1640
+ // here so their tag line carries attribution through the renderer. Labeled
1641
+ // user rows and assistant rows pass through unchanged.
1565
1642
  const labeledMembers = members.map((m) => {
1566
1643
  if (m.role === "assistant") return m;
1567
1644
  if (m.senderLabel !== null) return m;
1568
1645
  return { ...m, senderLabel: "@user" };
1569
1646
  });
1570
1647
 
1571
- const rendered = renderSlackTranscript(labeledMembers);
1572
- if (rendered.length === 0) return null;
1573
- // Reaction / overflow-trailer lines already embed `@assistant` inline, so
1574
- // `isReactionTagLine` is used to skip those and avoid double-attribution
1575
- // (`@assistant: [... @assistant reacted ...]`). Regular content and the
1576
- // `[deleted]` sentinel get the prefix so attribution survives flattening.
1577
- const lines = rendered
1578
- .map((msg) => {
1579
- const text = extractTagLineTexts([msg])[0] ?? "";
1580
- return msg.role === "assistant" && !isReactionTagLine(text)
1648
+ const rendered = renderSlackTranscriptWithProvenance(labeledMembers);
1649
+ if (rendered.renderedMessages.length === 0) return null;
1650
+ // Reaction / overflow-trailer lines are renderer-owned Slack event lines,
1651
+ // and timezone-aware assistant rows already carry metadata-backed compact
1652
+ // attribution. Regular assistant content and the `[deleted]` sentinel get
1653
+ // the prefix so attribution survives flattening.
1654
+ const lines = rendered.renderedMessages
1655
+ .map((entry) => {
1656
+ const text = extractTagLineTexts([entry.message])[0] ?? "";
1657
+ return entry.message.role === "assistant" &&
1658
+ entry.tagLineProvenance === "none"
1581
1659
  ? `@assistant: ${text}`
1582
1660
  : text;
1583
1661
  })
@@ -1605,7 +1683,7 @@ export function assembleSlackActiveThreadFocusBlock(
1605
1683
  // conversation and omits the field for DMs, so gate the focus block
1606
1684
  // on the positive `"channel"` match.
1607
1685
  if (capabilities.chatType !== "channel") return null;
1608
- const renderable = rows.map(rowToRenderable);
1686
+ const renderable = rowsToRenderableSlackMessages(rows);
1609
1687
  const activeThreadTs = detectActiveThreadTs(renderable);
1610
1688
  if (!activeThreadTs) return null;
1611
1689
  return buildActiveThreadBlockFromRenderable(renderable, activeThreadTs);
@@ -1631,9 +1709,10 @@ export function loadSlackActiveThreadFocusBlock(
1631
1709
  if (capabilities.chatType !== "channel") return null;
1632
1710
  const loader = options.loader ?? defaultGetMessages;
1633
1711
  const allRows = loader(conversationId);
1634
- const scopedRows = isUntrustedTrustClass(options.trustClass)
1635
- ? filterMessagesForUntrustedActor(allRows)
1636
- : allRows;
1712
+ const scopedRows = filterSlackConversationRowsForActor(
1713
+ allRows,
1714
+ options.trustClass,
1715
+ );
1637
1716
  const rows = filterRowsAfterSlackCompactionBoundary(
1638
1717
  messageRowsToSlackTranscriptRows(scopedRows),
1639
1718
  options,
@@ -1655,15 +1734,16 @@ const RUNTIME_INJECTION_PREFIXES = [
1655
1734
  "<background_turn>",
1656
1735
  "<memory_context __injected>",
1657
1736
  "<memory_context>", // backward-compat: strip legacy blocks from pre-__injected history
1658
- // The static `memory-v2-static` block (opens `<memory>\n…`) IS stripped
1659
- // so each compaction re-injects the freshest essentials/threads/recent/
1660
- // buffer view, matching the `<knowledge_base>` cadence. The dynamic
1661
- // activation block (opens `<memory __injected>…`) is intentionally NOT
1662
- // stripped `startsWith("<memory>\n")` does not match it — so per-turn
1663
- // memory activations persist in history. The activation pipeline dedupes
1664
- // via `everInjected`, and compaction handles aggregate growth, so
1665
- // accumulation does not cause unbounded context growth.
1737
+ // The static `memory-v2-static` block (`<info>\n…</info>`) and the
1738
+ // dynamic activation block (`<memory>\n…</memory>`, plus legacy
1739
+ // `<memory __injected>…`) are both stripped so each compaction
1740
+ // re-injects the freshest essentials/threads/recent/buffer view and
1741
+ // re-runs the activation pipeline, matching the `<knowledge_base>`
1742
+ // cadence. The activation pipeline dedupes via `everInjected`, and
1743
+ // compaction handles aggregate growth, so accumulation does not cause
1744
+ // unbounded context growth. Both wrappers may appear in persisted rows.
1666
1745
  "<memory>\n",
1746
+ "<info>\n",
1667
1747
  "<voice_call_control>",
1668
1748
  "<workspace_top_level>", // backward-compat: strip legacy workspace blocks
1669
1749
  // NOTE: <workspace> is intentionally NOT stripped — workspace context
@@ -1681,7 +1761,6 @@ const RUNTIME_INJECTION_PREFIXES = [
1681
1761
  "<pkb>", // backward-compat: strip legacy tag from pre-rename history
1682
1762
  "<system_reminder>",
1683
1763
  "<transport_hints>",
1684
- "<slack_context_notice>",
1685
1764
  // The Slack active-thread focus block is non-persisted and injected on
1686
1765
  // the FINAL user turn only. Strip it here so re-assembly during compaction
1687
1766
  // and overflow recovery does not duplicate it across turns.
@@ -1959,7 +2038,7 @@ export interface RuntimeInjectionOptions {
1959
2038
  /**
1960
2039
  * Pre-rendered v2 static memory content (essentials/threads/recent/buffer
1961
2040
  * concatenated, header-wrapped). When non-null on full-mode turns the
1962
- * `memory-v2-static` injector wraps it in `<memory>` and splices it onto
2041
+ * `memory-v2-static` injector wraps it in `<info>` and splices it onto
1963
2042
  * the user message; subsequent turns leave the prior block cached on its
1964
2043
  * original user message.
1965
2044
  */
@@ -1975,7 +2054,6 @@ export interface RuntimeInjectionOptions {
1975
2054
  */
1976
2055
  isBackgroundConversation?: boolean;
1977
2056
  transportHints?: string[] | null;
1978
- slackRuntimeContextNotice?: string | null;
1979
2057
  /**
1980
2058
  * Pre-rendered Slack chronological transcript that replaces the
1981
2059
  * default `runMessages` history for any Slack conversation (channels
@@ -2316,23 +2394,6 @@ export async function applyRuntimeInjections(
2316
2394
  }
2317
2395
  }
2318
2396
 
2319
- if (
2320
- mode === "full" &&
2321
- slackConversation &&
2322
- options.slackRuntimeContextNotice
2323
- ) {
2324
- const userTail = result[result.length - 1];
2325
- if (userTail && userTail.role === "user") {
2326
- result = [
2327
- ...result.slice(0, -1),
2328
- injectSlackRuntimeContextNotice(
2329
- userTail,
2330
- options.slackRuntimeContextNotice,
2331
- ),
2332
- ];
2333
- }
2334
- }
2335
-
2336
2397
  if (mode === "full" && options.channelCommandContext) {
2337
2398
  const userTail = result[result.length - 1];
2338
2399
  if (userTail && userTail.role === "user") {
@@ -14,7 +14,8 @@ import { getVisibleProviderCatalog } from "../providers/provider-catalog-visibil
14
14
  export type SlashResolution =
15
15
  | { kind: "passthrough"; content: string }
16
16
  | { kind: "unknown"; message: string }
17
- | { kind: "compact"; targetInputTokensOverride?: number };
17
+ | { kind: "compact"; targetInputTokensOverride?: number }
18
+ | { kind: "clean" };
18
19
 
19
20
  const COMPACT_USAGE_HINT =
20
21
  "Usage: `/compact [<tokens>]` (e.g. `/compact 30000`, `/compact 30k`, `/compact 1m`).";
@@ -52,6 +53,23 @@ function parseCompactCommand(trimmed: string): CompactParse | null {
52
53
  return { kind: "compact", targetInputTokensOverride: tokens };
53
54
  }
54
55
 
56
+ type CleanParse = { kind: "clean" } | { kind: "unknown"; message: string };
57
+
58
+ const CLEAN_COMMAND_PATTERN = /^\/clean(?:\s+(.+?))?\s*$/i;
59
+
60
+ function parseCleanCommand(trimmed: string): CleanParse | null {
61
+ const match = trimmed.match(CLEAN_COMMAND_PATTERN);
62
+ if (!match) return null;
63
+ const rest = match[1]?.trim();
64
+ if (rest) {
65
+ return {
66
+ kind: "unknown",
67
+ message: `\`/clean\` does not take arguments. Usage: \`/clean\`.`,
68
+ };
69
+ }
70
+ return { kind: "clean" };
71
+ }
72
+
55
73
  // ── /context and /status commands ────────────────────────────────────
56
74
 
57
75
  export interface SlashContext {
@@ -302,10 +320,14 @@ function resolveStatusCommand(context: SlashContext): SlashResolution {
302
320
  return { kind: "unknown", message: lines.join("\n") };
303
321
  }
304
322
 
323
+ const CLEAN_HELP_LINE =
324
+ "/clean — Strip injected runtime context and reset memory injection state (no summarization)";
325
+
305
326
  function resolveCommandsList(context?: SlashContext): string[] {
306
327
  const fallbackLines = [
307
328
  "/commands — List all available commands",
308
329
  "/compact — Force context compaction immediately",
330
+ CLEAN_HELP_LINE,
309
331
  ];
310
332
  if (context) {
311
333
  fallbackLines.push("/context — Show conversation context usage");
@@ -322,6 +344,7 @@ function resolveCommandsList(context?: SlashContext): string[] {
322
344
  return [
323
345
  "/commands — List all available commands",
324
346
  "/compact — Force context compaction immediately",
347
+ CLEAN_HELP_LINE,
325
348
  "/context — Show conversation context usage",
326
349
  "/model — List or switch inference profile",
327
350
  "/models — List all available models",
@@ -335,6 +358,7 @@ function resolveCommandsList(context?: SlashContext): string[] {
335
358
  return [
336
359
  "/commands — List all available commands",
337
360
  "/compact — Force context compaction immediately",
361
+ CLEAN_HELP_LINE,
338
362
  "/context — Show conversation context usage",
339
363
  "/model — List or switch inference profile",
340
364
  "/models — List all available models",
@@ -347,6 +371,7 @@ function resolveCommandsList(context?: SlashContext): string[] {
347
371
  return [
348
372
  "/commands — List all available commands",
349
373
  "/compact — Force context compaction immediately",
374
+ CLEAN_HELP_LINE,
350
375
  "/context — Show conversation context usage",
351
376
  "/model — List or switch inference profile",
352
377
  "/models — List all available models",
@@ -366,7 +391,7 @@ function resolveCommandsList(context?: SlashContext): string[] {
366
391
  */
367
392
  export function classifySlash(
368
393
  content: string,
369
- ): "passthrough" | "compact" | "unknown" {
394
+ ): "passthrough" | "compact" | "clean" | "unknown" {
370
395
  const trimmed = content.trim();
371
396
  if (parseModelCommand(trimmed) != null) {
372
397
  return "unknown";
@@ -381,6 +406,8 @@ export function classifySlash(
381
406
  if (trimmed === "/models") return "unknown";
382
407
  const compactParse = parseCompactCommand(trimmed);
383
408
  if (compactParse) return compactParse.kind;
409
+ const cleanParse = parseCleanCommand(trimmed);
410
+ if (cleanParse) return cleanParse.kind;
384
411
  if (trimmed === "/context") return "unknown";
385
412
  if (trimmed === "/status") return "unknown";
386
413
  if (trimmed === "/commands") return "unknown";
@@ -388,9 +415,10 @@ export function classifySlash(
388
415
  }
389
416
 
390
417
  /**
391
- * Resolve built-in slash commands (/models, /context, /status, /commands, /compact).
392
- * Returns `unknown` with a deterministic message, `compact` for forced compaction,
393
- * or the (possibly rewritten) content as `passthrough`.
418
+ * Resolve built-in slash commands (/models, /context, /status, /commands,
419
+ * /compact, /clean). Returns `unknown` with a deterministic message,
420
+ * `compact` for forced compaction, `clean` for injection stripping, or the
421
+ * (possibly rewritten) content as `passthrough`.
394
422
  */
395
423
  export async function resolveSlash(
396
424
  content: string,
@@ -424,6 +452,10 @@ export async function resolveSlash(
424
452
  const compactParse = parseCompactCommand(trimmed);
425
453
  if (compactParse) return compactParse;
426
454
 
455
+ // Handle /clean command (strip injections, no summarization).
456
+ const cleanParse = parseCleanCommand(trimmed);
457
+ if (cleanParse) return cleanParse;
458
+
427
459
  // Handle /context and legacy /status commands
428
460
  if (trimmed === "/context" || trimmed === "/status") {
429
461
  if (!context) {
@@ -390,6 +390,40 @@ function normalizeTaskProgressCardPatch(
390
390
  return normalizedPatch;
391
391
  }
392
392
 
393
+ function isTaskProgressCardData(data: SurfaceData | Record<string, unknown>) {
394
+ return (data as Record<string, unknown>).template === "task_progress";
395
+ }
396
+
397
+ function isSlackTaskProgressUiException(
398
+ ctx: SurfaceConversationContext,
399
+ toolName: string,
400
+ input: Record<string, unknown>,
401
+ ): boolean {
402
+ if (ctx.channelCapabilities?.channel !== "slack") return false;
403
+ if (toolName === "ui_show") {
404
+ const surfaceType = input.surface_type as SurfaceType;
405
+ if (surfaceType !== "card") return false;
406
+ const rawData = isPlainObject(input.data) ? input.data : {};
407
+ const data = normalizeCardShowData(input, rawData);
408
+ return isTaskProgressCardData(data);
409
+ }
410
+ if (toolName === "ui_update") {
411
+ const surfaceId = input.surface_id;
412
+ if (typeof surfaceId !== "string") return false;
413
+ const stored = ctx.surfaceState.get(surfaceId);
414
+ if (!stored || stored.surfaceType !== "card") return false;
415
+ if (!isTaskProgressCardData(stored.data)) return false;
416
+ const rawPatch = isPlainObject(input.data) ? input.data : {};
417
+ const patch = normalizeTaskProgressCardPatch(
418
+ stored.data as CardSurfaceData,
419
+ rawPatch,
420
+ );
421
+ const mergedData = { ...stored.data, ...patch } as SurfaceData;
422
+ return isTaskProgressCardData(mergedData);
423
+ }
424
+ return false;
425
+ }
426
+
393
427
  /**
394
428
  * Subset of Conversation state that surface helpers need access to.
395
429
  * The Conversation class implements this interface so its instances can be
@@ -1638,7 +1672,12 @@ export async function handleSurfaceAction(
1638
1672
  // One-shot interactive surfaces — auto-complete now that the message has
1639
1673
  // been accepted. Deferred until after rejection check so the surface stays
1640
1674
  // active and retryable if the queue was full.
1641
- const ONE_SHOT_SURFACE_TYPES = ["form", "confirmation", "file_upload"];
1675
+ const ONE_SHOT_SURFACE_TYPES = [
1676
+ "form",
1677
+ "confirmation",
1678
+ "file_upload",
1679
+ "task_preferences",
1680
+ ];
1642
1681
  if (ONE_SHOT_SURFACE_TYPES.includes(pending.surfaceType)) {
1643
1682
  broadcastMessage({
1644
1683
  type: "ui_surface_complete",
@@ -2135,7 +2174,11 @@ export async function surfaceProxyResolver(
2135
2174
 
2136
2175
  if (toolName === "ui_show" || toolName === "ui_update") {
2137
2176
  const caps = ctx.channelCapabilities;
2138
- if (caps && !caps.supportsDynamicUi) {
2177
+ if (
2178
+ caps &&
2179
+ !caps.supportsDynamicUi &&
2180
+ !isSlackTaskProgressUiException(ctx, toolName, input)
2181
+ ) {
2139
2182
  log.info(
2140
2183
  { toolName, channel: caps.channel, conversationId: ctx.conversationId },
2141
2184
  "Blocked UI surface tool on channel without dynamic UI support",