@vellumai/assistant 0.8.8 → 0.8.9-dev.202606091853.fbaa2ae

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 (475) hide show
  1. package/ARCHITECTURE.md +6 -6
  2. package/bun.lock +2 -2
  3. package/docs/activation-funnel-telemetry.md +310 -0
  4. package/examples/plugins/echo/README.md +61 -60
  5. package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
  6. package/examples/plugins/echo/hooks/stop.ts +16 -0
  7. package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
  8. package/examples/plugins/echo/package.json +1 -2
  9. package/examples/plugins/echo/src/emit.ts +19 -0
  10. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
  11. package/openapi.yaml +263 -121
  12. package/package.json +2 -2
  13. package/src/__tests__/activation-early-marking.test.ts +120 -0
  14. package/src/__tests__/agent-loop-callsite-precedence.test.ts +69 -14
  15. package/src/__tests__/agent-loop-exit-reason.test.ts +204 -144
  16. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +50 -35
  17. package/src/__tests__/agent-loop-output-hooks.test.ts +357 -0
  18. package/src/__tests__/agent-loop-override-profile.test.ts +25 -6
  19. package/src/__tests__/agent-loop-provider-error-recording.test.ts +41 -21
  20. package/src/__tests__/agent-loop-thinking.test.ts +36 -20
  21. package/src/__tests__/agent-loop.test.ts +441 -96
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +14 -14
  23. package/src/__tests__/agent-wake-override-profile.test.ts +17 -21
  24. package/src/__tests__/anthropic-provider.test.ts +23 -8
  25. package/src/__tests__/app-builder-tool-scripts.test.ts +21 -0
  26. package/src/__tests__/app-control-flow.test.ts +1 -1
  27. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  28. package/src/__tests__/app-executors.test.ts +132 -0
  29. package/src/__tests__/approval-cascade.test.ts +6 -5
  30. package/src/__tests__/approval-routes-http.test.ts +4 -1
  31. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  32. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  33. package/src/__tests__/channel-approvals.test.ts +1 -1
  34. package/src/__tests__/compaction-circuit.test.ts +258 -0
  35. package/src/__tests__/compaction-direct.test.ts +146 -0
  36. package/src/__tests__/compaction-events.test.ts +7 -7
  37. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  38. package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
  39. package/src/__tests__/context-overflow-reducer.test.ts +265 -125
  40. package/src/__tests__/context-window-manager-compact-retry.test.ts +121 -15
  41. package/src/__tests__/conversation-abort-tool-results.test.ts +7 -5
  42. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +7 -10
  43. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +78 -119
  44. package/src/__tests__/conversation-agent-loop-overflow.test.ts +158 -234
  45. package/src/__tests__/conversation-agent-loop.test.ts +342 -623
  46. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  47. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -5
  48. package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
  49. package/src/__tests__/conversation-error.test.ts +15 -1
  50. package/src/__tests__/conversation-history-web-search.test.ts +6 -1
  51. package/src/__tests__/conversation-media-retry.test.ts +1 -1
  52. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +44 -4
  53. package/src/__tests__/conversation-process-callsite.test.ts +15 -15
  54. package/src/__tests__/conversation-provider-retry-repair.test.ts +66 -65
  55. package/src/__tests__/conversation-queue.test.ts +10 -10
  56. package/src/__tests__/conversation-runtime-assembly.test.ts +1059 -231
  57. package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
  58. package/src/__tests__/conversation-slash-queue.test.ts +7 -5
  59. package/src/__tests__/conversation-slash-unknown.test.ts +7 -5
  60. package/src/__tests__/conversation-speed-override.test.ts +11 -10
  61. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  62. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +395 -0
  63. package/src/__tests__/conversation-surfaces-app-control.test.ts +48 -1
  64. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +73 -4
  65. package/src/__tests__/conversation-undo.test.ts +2 -2
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +24 -21
  67. package/src/__tests__/conversation-workspace-injection.test.ts +69 -7
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +15 -12
  69. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  70. package/src/__tests__/corrected-target.test.ts +93 -0
  71. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  72. package/src/__tests__/cu-unified-flow.test.ts +36 -0
  73. package/src/__tests__/db-acp-history.test.ts +101 -0
  74. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  75. package/src/__tests__/empty-response-hook.test.ts +1 -1
  76. package/src/__tests__/file-write-tool.test.ts +63 -0
  77. package/src/__tests__/gateway-only-guard.test.ts +17 -2
  78. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  79. package/src/__tests__/guardian-routing-invariants.test.ts +93 -4
  80. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  81. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  82. package/src/__tests__/heartbeat-service.test.ts +1 -0
  83. package/src/__tests__/history-repair-hook.test.ts +5 -1
  84. package/src/__tests__/host-app-control-proxy.test.ts +45 -0
  85. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  86. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  87. package/src/__tests__/inference-profile-reaper.test.ts +62 -0
  88. package/src/__tests__/inference-profile-session-handler.test.ts +86 -0
  89. package/src/__tests__/injector-background-turn.test.ts +13 -23
  90. package/src/__tests__/injector-chain.test.ts +268 -44
  91. package/src/__tests__/injector-disk-pressure.test.ts +210 -52
  92. package/src/__tests__/injector-document-comments.test.ts +97 -114
  93. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  94. package/src/__tests__/injector-v3-suppression.test.ts +4 -4
  95. package/src/__tests__/list-messages-client-message-id.test.ts +91 -0
  96. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  97. package/src/__tests__/llm-resolver.test.ts +73 -0
  98. package/src/__tests__/memory-retrieval-hook.test.ts +156 -38
  99. package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
  100. package/src/__tests__/notification-decision-strategy.test.ts +3 -3
  101. package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
  102. package/src/__tests__/persist-unsendable-image-downscale.test.ts +145 -0
  103. package/src/__tests__/persist-unsendable-image.test.ts +97 -1
  104. package/src/__tests__/plugin-api-shim.test.ts +6 -9
  105. package/src/__tests__/plugin-bootstrap.test.ts +91 -81
  106. package/src/__tests__/plugin-registry.test.ts +3 -49
  107. package/src/__tests__/plugin-skill-contribution.test.ts +15 -14
  108. package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
  109. package/src/__tests__/plugin-types.test.ts +0 -70
  110. package/src/__tests__/post-turn-tool-result-truncation.test.ts +69 -0
  111. package/src/__tests__/pre-model-call-sanitize.test.ts +109 -0
  112. package/src/__tests__/published-app-updater.test.ts +138 -0
  113. package/src/__tests__/reaction-persistence.test.ts +1 -1
  114. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  115. package/src/__tests__/skill-feature-flags-integration.test.ts +31 -0
  116. package/src/__tests__/steer-tool-repair.test.ts +1 -1
  117. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  118. package/src/__tests__/subagent-detail.test.ts +25 -7
  119. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  120. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  121. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  122. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  123. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  124. package/src/__tests__/title-generate-hook.test.ts +5 -1
  125. package/src/__tests__/tool-error-hook.test.ts +1 -1
  126. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -1
  127. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  128. package/src/__tests__/web-fetch.test.ts +45 -0
  129. package/src/acp/__tests__/agent-process.test.ts +161 -0
  130. package/src/acp/__tests__/client-handler.test.ts +40 -0
  131. package/src/acp/__tests__/helpers/acp-config-stub.ts +0 -2
  132. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  133. package/src/acp/__tests__/helpers/exec-file-stub.ts +106 -0
  134. package/src/acp/__tests__/prepare-agent-env.test.ts +97 -0
  135. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  136. package/src/acp/__tests__/session-manager-resume.test.ts +888 -0
  137. package/src/acp/agent-process.ts +61 -1
  138. package/src/acp/auto-install.test.ts +280 -0
  139. package/src/acp/auto-install.ts +232 -0
  140. package/src/acp/client-handler.ts +31 -0
  141. package/src/acp/prepare-agent-env.ts +80 -27
  142. package/src/acp/resolve-agent.test.ts +188 -28
  143. package/src/acp/resolve-agent.ts +119 -42
  144. package/src/acp/resume-hint.ts +23 -0
  145. package/src/acp/session-manager.ts +507 -73
  146. package/src/agent/compaction-circuit.ts +60 -102
  147. package/src/agent/loop.ts +403 -251
  148. package/src/api/responses/conversation-message.ts +22 -2
  149. package/src/api/responses/memory-v3-selection-log.ts +19 -10
  150. package/src/approvals/guardian-request-resolvers.ts +27 -1
  151. package/src/background-wake/next-wake.ts +1 -0
  152. package/src/cli/commands/__tests__/memory-v3.test.ts +191 -210
  153. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  154. package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
  155. package/src/cli/commands/memory-v3.ts +57 -199
  156. package/src/cli/commands/plugins.ts +43 -37
  157. package/src/cli/lib/__tests__/install-from-github.test.ts +790 -111
  158. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
  159. package/src/cli/lib/__tests__/plugin-details.test.ts +381 -0
  160. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +270 -0
  161. package/src/cli/lib/__tests__/search-plugins.test.ts +233 -32
  162. package/src/cli/lib/install-from-github.ts +797 -60
  163. package/src/cli/lib/plugin-catalog-cache.ts +84 -0
  164. package/src/cli/lib/plugin-details.ts +416 -0
  165. package/src/cli/lib/plugin-marketplace.ts +215 -0
  166. package/src/cli/lib/search-plugins.ts +201 -29
  167. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  168. package/src/config/acp-defaults.test.ts +10 -0
  169. package/src/config/acp-defaults.ts +9 -3
  170. package/src/config/acp-schema.ts +1 -7
  171. package/src/config/bundled-skills/acp/SKILL.md +80 -41
  172. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  173. package/src/config/bundled-skills/app-builder/SKILL.md +224 -381
  174. package/src/config/bundled-skills/app-builder/TOOLS.json +72 -2
  175. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  176. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  177. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  178. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  179. package/src/config/bundled-skills/app-builder/tools/app-update.ts +18 -0
  180. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  181. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  182. package/src/config/bundled-tool-registry.ts +4 -0
  183. package/src/config/call-site-defaults.ts +0 -3
  184. package/src/config/feature-flag-registry.json +10 -16
  185. package/src/config/llm-resolver.ts +39 -7
  186. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -9
  187. package/src/config/schemas/call-site-catalog.ts +0 -21
  188. package/src/config/schemas/heartbeat.ts +9 -0
  189. package/src/config/schemas/llm.ts +17 -3
  190. package/src/config/schemas/memory-v3.ts +58 -8
  191. package/src/config/seed-inference-profiles.ts +18 -0
  192. package/src/context/compactor.ts +22 -4
  193. package/src/context/post-turn-tool-result-truncation.ts +39 -1
  194. package/src/context/strip-injections.ts +8 -2
  195. package/src/daemon/conversation-agent-loop-handlers.ts +18 -36
  196. package/src/daemon/conversation-agent-loop.ts +308 -1297
  197. package/src/daemon/conversation-error.ts +31 -4
  198. package/src/daemon/conversation-history.ts +1 -1
  199. package/src/daemon/conversation-lifecycle.ts +11 -255
  200. package/src/daemon/conversation-media-retry.ts +19 -6
  201. package/src/daemon/conversation-messaging.ts +17 -0
  202. package/src/daemon/conversation-process.ts +22 -141
  203. package/src/daemon/conversation-queue-manager.ts +8 -0
  204. package/src/daemon/conversation-registry.ts +159 -0
  205. package/src/daemon/conversation-runtime-assembly.ts +361 -393
  206. package/src/daemon/conversation-store.ts +9 -90
  207. package/src/daemon/conversation-surfaces.ts +165 -11
  208. package/src/daemon/conversation-workspace.ts +17 -0
  209. package/src/daemon/conversation.ts +444 -62
  210. package/src/daemon/disk-pressure-policy.ts +0 -1
  211. package/src/daemon/external-plugins-bootstrap.ts +36 -46
  212. package/src/daemon/handlers/config-channels.ts +11 -2
  213. package/src/daemon/handlers/conversations.ts +3 -1
  214. package/src/daemon/handlers/skills.ts +4 -1
  215. package/src/daemon/host-app-control-proxy.ts +72 -57
  216. package/src/daemon/host-proxy-preactivation.ts +1 -3
  217. package/src/daemon/lifecycle.ts +21 -7
  218. package/src/daemon/persist-unsendable-image.ts +62 -25
  219. package/src/daemon/process-message.ts +1 -1
  220. package/src/daemon/server.ts +2 -0
  221. package/src/daemon/tool-side-effects.ts +15 -0
  222. package/src/daemon/wake-conversation-ops.ts +269 -0
  223. package/src/embedded/plugin-api.ts +2 -2
  224. package/src/export/__tests__/transcript-formatter.test.ts +5 -0
  225. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  226. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  227. package/src/heartbeat/heartbeat-service.ts +26 -0
  228. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  229. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  230. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  231. package/src/ipc/skill-routes/memory.ts +4 -2
  232. package/src/memory/__tests__/activation-session-store.test.ts +41 -0
  233. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +87 -0
  234. package/src/memory/__tests__/onboarding-events-store.test.ts +80 -0
  235. package/src/memory/activation-session-store.ts +43 -0
  236. package/src/memory/conversation-crud.ts +29 -19
  237. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  238. package/src/memory/db-init.ts +6 -0
  239. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  240. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -4
  241. package/src/memory/jobs-worker.ts +25 -1
  242. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  243. package/src/memory/migrations/273-onboarding-events-funnel-columns.ts +46 -0
  244. package/src/memory/migrations/274-create-activation-sessions.ts +15 -0
  245. package/src/memory/migrations/index.ts +3 -0
  246. package/src/memory/onboarding-events-store.ts +66 -18
  247. package/src/memory/schema/acp.ts +4 -0
  248. package/src/memory/schema/infrastructure.ts +13 -0
  249. package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -97
  250. package/src/memory/v2/__tests__/page-store.test.ts +22 -0
  251. package/src/memory/v2/consolidation-job.ts +2 -63
  252. package/src/memory/v2/types.ts +5 -0
  253. package/src/messaging/providers/telegram-bot/api.ts +14 -5
  254. package/src/notifications/__tests__/copy-composer.test.ts +244 -0
  255. package/src/notifications/access-request-copy.ts +298 -0
  256. package/src/notifications/adapters/slack.ts +3 -3
  257. package/src/notifications/adapters/telegram.ts +9 -2
  258. package/src/notifications/copy-composer.ts +49 -267
  259. package/src/notifications/decision-engine.ts +16 -35
  260. package/src/notifications/home-feed-side-effect.ts +1 -6
  261. package/src/plugin-api/constants.ts +4 -0
  262. package/src/plugin-api/index.ts +40 -11
  263. package/src/plugin-api/types.ts +108 -0
  264. package/src/plugins/defaults/compaction/compact.ts +106 -0
  265. package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +250 -42
  266. package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
  267. package/src/plugins/defaults/compaction/manager-store.ts +57 -0
  268. package/src/plugins/defaults/compaction/package.json +1 -2
  269. package/src/{context → plugins/defaults/compaction}/window-manager.ts +95 -25
  270. package/src/plugins/defaults/empty-response/package.json +0 -1
  271. package/src/plugins/defaults/history-repair/package.json +0 -1
  272. package/src/plugins/defaults/index.ts +156 -26
  273. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
  274. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +285 -0
  275. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
  276. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +148 -73
  277. package/src/plugins/defaults/memory-retrieval/package.json +14 -0
  278. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +223 -0
  279. package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +71 -0
  280. package/src/plugins/defaults/memory-v3-shadow/__tests__/dense.test.ts +181 -0
  281. package/src/plugins/defaults/memory-v3-shadow/__tests__/edge.test.ts +247 -0
  282. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +147 -134
  283. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +456 -0
  284. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +662 -0
  285. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +306 -0
  286. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +91 -0
  287. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +402 -0
  288. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-needle.test.ts +135 -0
  289. package/src/plugins/defaults/memory-v3-shadow/__tests__/sections.test.ts +125 -0
  290. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +74 -19
  291. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +446 -0
  292. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +592 -0
  293. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -24
  294. package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +91 -0
  295. package/src/plugins/defaults/memory-v3-shadow/dense.ts +97 -0
  296. package/src/plugins/defaults/memory-v3-shadow/edge.ts +252 -0
  297. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  298. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  299. package/src/plugins/defaults/memory-v3-shadow/injector.ts +76 -0
  300. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +555 -0
  301. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +266 -0
  302. package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
  303. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +71 -0
  304. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +204 -0
  305. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +16 -8
  306. package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +236 -0
  307. package/src/plugins/defaults/memory-v3-shadow/section-needle.ts +200 -0
  308. package/src/plugins/defaults/memory-v3-shadow/sections.ts +115 -0
  309. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +156 -0
  310. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +382 -0
  311. package/src/plugins/defaults/memory-v3-shadow/types.ts +92 -0
  312. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +4 -1
  313. package/src/plugins/defaults/title-generate/package.json +0 -1
  314. package/src/plugins/defaults/tool-error/package.json +0 -1
  315. package/src/plugins/defaults/tool-result-truncate/package.json +0 -1
  316. package/src/plugins/external-api.ts +12 -2
  317. package/src/plugins/pipeline.ts +6 -293
  318. package/src/plugins/registry.ts +9 -37
  319. package/src/plugins/types.ts +76 -381
  320. package/src/plugins/user-loader.ts +30 -127
  321. package/src/prompts/__tests__/system-prompt.test.ts +6 -0
  322. package/src/prompts/system-prompt.ts +61 -10
  323. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +71 -4
  324. package/src/providers/anthropic/client.ts +9 -10
  325. package/src/providers/inference/kimi-cjk-token-ids.ts +493 -0
  326. package/src/providers/inference/logit-bias.ts +55 -0
  327. package/src/providers/model-catalog.ts +34 -0
  328. package/src/providers/openai/__tests__/vision-not-supported.test.ts +75 -0
  329. package/src/providers/openai/chat-completions-provider.ts +44 -1
  330. package/src/providers/retry.ts +22 -0
  331. package/src/providers/types.ts +6 -0
  332. package/src/runtime/__tests__/agent-wake.test.ts +555 -691
  333. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  334. package/src/runtime/agent-wake.ts +108 -209
  335. package/src/runtime/assistant-event-hub.ts +1 -1
  336. package/src/runtime/channel-approvals.ts +1 -1
  337. package/src/runtime/interactive-ui.ts +1 -1
  338. package/src/runtime/routes/__tests__/acp-routes.test.ts +466 -55
  339. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  340. package/src/runtime/routes/__tests__/plugins-routes.test.ts +423 -73
  341. package/src/runtime/routes/__tests__/stt-routes.test.ts +112 -0
  342. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  343. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  344. package/src/runtime/routes/acp-routes.test.ts +185 -32
  345. package/src/runtime/routes/acp-routes.ts +328 -30
  346. package/src/runtime/routes/app-management-routes.ts +3 -0
  347. package/src/runtime/routes/approval-routes.ts +1 -1
  348. package/src/runtime/routes/browser-routes.ts +1 -1
  349. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  350. package/src/runtime/routes/channel-verification-routes.ts +14 -5
  351. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  352. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  353. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  354. package/src/runtime/routes/conversation-routes.ts +30 -2
  355. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  356. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  357. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  358. package/src/runtime/routes/host-cu-routes.ts +1 -1
  359. package/src/runtime/routes/identity-routes.ts +18 -3
  360. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  361. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
  362. package/src/runtime/routes/inference-profile-session-handler.ts +11 -0
  363. package/src/runtime/routes/inference-profile-session-reaper.ts +6 -0
  364. package/src/runtime/routes/memory-v3-routes.ts +65 -305
  365. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +1 -1
  366. package/src/runtime/routes/playground/helpers.ts +1 -1
  367. package/src/runtime/routes/plugins-routes.ts +337 -35
  368. package/src/runtime/routes/stt-routes.ts +45 -12
  369. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  370. package/src/runtime/routes/work-items-routes.ts +2 -4
  371. package/src/runtime/routes/workspace-routes.ts +50 -15
  372. package/src/runtime/services/conversation-serializer.ts +1 -1
  373. package/src/runtime/verification-outbound-actions.ts +147 -2
  374. package/src/runtime/verification-templates.ts +29 -3
  375. package/src/services/published-app-updater.ts +30 -8
  376. package/src/signals/cancel.ts +2 -4
  377. package/src/subagent/manager.ts +21 -5
  378. package/src/telemetry/__tests__/activation-funnel.test.ts +95 -0
  379. package/src/telemetry/activation-funnel.ts +167 -0
  380. package/src/telemetry/types.ts +13 -0
  381. package/src/telemetry/usage-telemetry-reporter.test.ts +154 -0
  382. package/src/telemetry/usage-telemetry-reporter.ts +26 -1
  383. package/src/tools/acp/context.ts +20 -0
  384. package/src/tools/acp/list-agents.test.ts +9 -19
  385. package/src/tools/acp/list-agents.ts +3 -15
  386. package/src/tools/acp/spawn.test.ts +173 -202
  387. package/src/tools/acp/spawn.ts +37 -172
  388. package/src/tools/acp/steer.test.ts +105 -8
  389. package/src/tools/acp/steer.ts +48 -17
  390. package/src/tools/apps/executors.ts +166 -50
  391. package/src/tools/browser/browser-execution.ts +12 -2
  392. package/src/tools/filesystem/write.ts +34 -0
  393. package/src/tools/network/web-fetch.ts +65 -24
  394. package/src/tools/skills/load.ts +1 -1
  395. package/src/tools/subagent/spawn.ts +2 -4
  396. package/src/tools/ui-surface/definitions.ts +32 -5
  397. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  398. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +69 -45
  399. package/docs/plugins.md +0 -832
  400. package/examples/plugins/echo/register.ts +0 -143
  401. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  402. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  403. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  404. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -667
  405. package/src/__tests__/pipeline-runner.test.ts +0 -554
  406. package/src/daemon/wake-target-adapter.ts +0 -253
  407. package/src/memory/v3/__tests__/assign.test.ts +0 -242
  408. package/src/memory/v3/__tests__/capabilities.test.ts +0 -118
  409. package/src/memory/v3/__tests__/core.test.ts +0 -39
  410. package/src/memory/v3/__tests__/health.test.ts +0 -219
  411. package/src/memory/v3/__tests__/maintain-job.test.ts +0 -288
  412. package/src/memory/v3/__tests__/needle.test.ts +0 -107
  413. package/src/memory/v3/__tests__/orchestrate.test.ts +0 -436
  414. package/src/memory/v3/__tests__/provider-blocks.test.ts +0 -13
  415. package/src/memory/v3/__tests__/reconcile.test.ts +0 -274
  416. package/src/memory/v3/__tests__/render-injection.test.ts +0 -61
  417. package/src/memory/v3/__tests__/router.test.ts +0 -332
  418. package/src/memory/v3/__tests__/selector.test.ts +0 -470
  419. package/src/memory/v3/__tests__/shadow-plugin.test.ts +0 -432
  420. package/src/memory/v3/__tests__/snapshot.test.ts +0 -168
  421. package/src/memory/v3/__tests__/tree.test.ts +0 -192
  422. package/src/memory/v3/assign.ts +0 -268
  423. package/src/memory/v3/capabilities.ts +0 -124
  424. package/src/memory/v3/core.ts +0 -26
  425. package/src/memory/v3/health.ts +0 -0
  426. package/src/memory/v3/maintain-job.ts +0 -314
  427. package/src/memory/v3/needle.ts +0 -115
  428. package/src/memory/v3/orchestrate.ts +0 -126
  429. package/src/memory/v3/page-content.ts +0 -34
  430. package/src/memory/v3/provider-blocks.ts +0 -26
  431. package/src/memory/v3/reconcile.ts +0 -523
  432. package/src/memory/v3/router.ts +0 -190
  433. package/src/memory/v3/selection-log-store.ts +0 -84
  434. package/src/memory/v3/selector.ts +0 -226
  435. package/src/memory/v3/shadow-plugin.ts +0 -411
  436. package/src/memory/v3/snapshot.ts +0 -209
  437. package/src/memory/v3/tree.ts +0 -174
  438. package/src/memory/v3/types.ts +0 -59
  439. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
  440. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  441. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  442. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  443. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  444. package/src/plugins/defaults/compaction/register.ts +0 -35
  445. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  446. package/src/plugins/defaults/empty-response/register.ts +0 -23
  447. package/src/plugins/defaults/history-repair/register.ts +0 -24
  448. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +0 -216
  449. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  450. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  451. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  452. package/src/plugins/defaults/title-generate/register.ts +0 -35
  453. package/src/plugins/defaults/tool-error/register.ts +0 -23
  454. package/src/plugins/defaults/tool-result-truncate/register.ts +0 -24
  455. package/src/proactive-artifact/aux-message-injector.ts +0 -97
  456. package/src/proactive-artifact/decision.test.ts +0 -226
  457. package/src/proactive-artifact/decision.ts +0 -165
  458. package/src/proactive-artifact/index.ts +0 -7
  459. package/src/proactive-artifact/job.test.ts +0 -962
  460. package/src/proactive-artifact/job.ts +0 -372
  461. package/src/proactive-artifact/message-copy.ts +0 -58
  462. package/src/proactive-artifact/trigger-state.test.ts +0 -286
  463. package/src/proactive-artifact/trigger-state.ts +0 -123
  464. package/src/util/map-limit.ts +0 -27
  465. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  466. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  467. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  468. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  469. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  470. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  471. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  472. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  473. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  474. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  475. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/llm-retry.ts +0 -0
@@ -120,7 +120,7 @@ describe("stripInjectionsForCompaction preserves history shape", () => {
120
120
  expect(out[3]).toEqual(messages[3]);
121
121
  });
122
122
 
123
- test("leaves <turn_context>, <workspace>, and <memory __injected> alone", () => {
123
+ test("strips <workspace> but leaves <turn_context> and <memory __injected> alone", () => {
124
124
  const messages: Message[] = [
125
125
  {
126
126
  role: "user",
@@ -132,6 +132,9 @@ describe("stripInjectionsForCompaction preserves history shape", () => {
132
132
  },
133
133
  ];
134
134
  const out = stripInjectionsForCompaction(messages);
135
- expect(out[0].content).toEqual(messages[0].content);
135
+ expect(out[0].content).toEqual([
136
+ { type: "text", text: "<turn_context>\nnow\n</turn_context>" },
137
+ { type: "text", text: "<memory __injected>\nrecent\n</memory>" },
138
+ ]);
136
139
  });
137
140
  });
@@ -164,9 +164,10 @@ mock.module("../memory/retriever.js", () => ({
164
164
  injectMemoryRecallAsUserBlock: (msgs: Message[]) => msgs,
165
165
  }));
166
166
 
167
- mock.module("../context/window-manager.js", () => ({
167
+ mock.module("../plugins/defaults/compaction/window-manager.js", () => ({
168
168
  ContextWindowManager: class {
169
169
  constructor() {}
170
+ updateConfig() {}
170
171
  shouldCompact() {
171
172
  return { needed: false, estimatedTokens: 0 };
172
173
  }
@@ -199,10 +200,10 @@ mock.module("../agent/loop.js", () => ({
199
200
  getActiveModel() {
200
201
  return undefined;
201
202
  }
202
- async run(
203
- _messages: Message[],
204
- _onEvent: (event: AgentEvent) => void,
205
- ): Promise<Message[]> {
203
+ async run(_options: {
204
+ messages: Message[];
205
+ onEvent: (event: AgentEvent) => void;
206
+ }): Promise<Message[]> {
206
207
  return [];
207
208
  }
208
209
  },
@@ -9,7 +9,7 @@ mock.module("../util/logger.js", () => ({
9
9
  import {
10
10
  createConversation,
11
11
  getConversation,
12
- getConversationOverrideProfileFromRow,
12
+ resolveOverrideProfile,
13
13
  setConversationInferenceProfile,
14
14
  setConversationInferenceProfileSession,
15
15
  } from "../memory/conversation-crud.js";
@@ -55,7 +55,7 @@ describe("setConversationInferenceProfile", () => {
55
55
  });
56
56
  });
57
57
 
58
- describe("getConversationOverrideProfileFromRow — lazy expiry check", () => {
58
+ describe("resolveOverrideProfile — lazy expiry check", () => {
59
59
  beforeEach(() => {
60
60
  const db = getDb();
61
61
  db.run(`DELETE FROM messages`);
@@ -73,7 +73,7 @@ describe("getConversationOverrideProfileFromRow — lazy expiry check", () => {
73
73
  );
74
74
  const row = getConversation(conv.id);
75
75
  expect(row).not.toBeNull();
76
- expect(getConversationOverrideProfileFromRow(row)).toBeUndefined();
76
+ expect(resolveOverrideProfile(row)).toBeUndefined();
77
77
  });
78
78
 
79
79
  test("returns the profile when inferenceProfileExpiresAt is in the future", () => {
@@ -86,7 +86,7 @@ describe("getConversationOverrideProfileFromRow — lazy expiry check", () => {
86
86
  );
87
87
  const row = getConversation(conv.id);
88
88
  expect(row).not.toBeNull();
89
- expect(getConversationOverrideProfileFromRow(row)).toBe("balanced");
89
+ expect(resolveOverrideProfile(row)).toBe("balanced");
90
90
  });
91
91
 
92
92
  test("returns undefined at the exact-expiry boundary (expiresAt === now)", () => {
@@ -110,7 +110,7 @@ describe("getConversationOverrideProfileFromRow — lazy expiry check", () => {
110
110
  const realNow = Date.now;
111
111
  Date.now = () => now;
112
112
  try {
113
- expect(getConversationOverrideProfileFromRow(row)).toBeUndefined();
113
+ expect(resolveOverrideProfile(row)).toBeUndefined();
114
114
  } finally {
115
115
  Date.now = realNow;
116
116
  }
@@ -126,9 +126,7 @@ describe("getConversationOverrideProfileFromRow — lazy expiry check", () => {
126
126
  );
127
127
  const row = getConversation(conv.id);
128
128
  expect(row).not.toBeNull();
129
- expect(getConversationOverrideProfileFromRow(row)).toBe(
130
- "quality-optimized",
131
- );
129
+ expect(resolveOverrideProfile(row)).toBe("quality-optimized");
132
130
  });
133
131
 
134
132
  test.each<"background" | "scheduled">(["background", "scheduled"])(
@@ -148,7 +146,7 @@ describe("getConversationOverrideProfileFromRow — lazy expiry check", () => {
148
146
  expect(row).not.toBeNull();
149
147
  expect(row?.conversationType).toBe(conversationType);
150
148
  expect(row?.inferenceProfile).toBe("quality-optimized");
151
- expect(getConversationOverrideProfileFromRow(row)).toBeUndefined();
149
+ expect(resolveOverrideProfile(row)).toBeUndefined();
152
150
  },
153
151
  );
154
152
  });
@@ -319,7 +319,6 @@ describe("classifyConversationError", () => {
319
319
  expect(result.errorCategory).toBe("image_dimensions_too_large");
320
320
  expect(result.retryable).toBe(false);
321
321
  expect(result.userMessage).toContain("image");
322
- expect(result.userMessage).toContain("8000");
323
322
  });
324
323
 
325
324
  it("matches the singular 'image dimension exceeds' phrasing as well", () => {
@@ -333,6 +332,21 @@ describe("classifyConversationError", () => {
333
332
  expect(result.retryable).toBe(false);
334
333
  });
335
334
 
335
+ it("classifies the base64 payload 'exceeds 5 MB maximum' variant as IMAGE_TOO_LARGE (JARVIS-1041)", () => {
336
+ // This is the exact shape that wedged the reporting user: an oversized
337
+ // image nested in a tool_result. It must route to IMAGE_TOO_LARGE so the
338
+ // recovery path fires, not to a retryable PROVIDER_API loop.
339
+ const err = new ProviderError(
340
+ 'Anthropic API error (400): 400 {"type":"error","error":{"type":"invalid_request_error","message":"messages.28.content.1.tool_result.content.1.image.source.base64: image exceeds 5 MB maximum: 7465044 bytes > 5242880 bytes"},"request_id":"req_011CbbFqvxBmDQdhVlqxtAfW"}',
341
+ "anthropic",
342
+ 400,
343
+ );
344
+ const result = classifyConversationError(err, baseCtx);
345
+ expect(result.code).toBe("IMAGE_TOO_LARGE");
346
+ expect(result.errorCategory).toBe("image_dimensions_too_large");
347
+ expect(result.retryable).toBe(false);
348
+ });
349
+
336
350
  it("does not steal generic 400s that happen to mention 'image'", () => {
337
351
  const err = new ProviderError(
338
352
  "invalid request: image source is missing",
@@ -807,7 +807,12 @@ describe("web_search_tool_result structural guard", () => {
807
807
  // Media token counting iterates tool_result.contentBlocks for nested
808
808
  // image/file blocks. web_search_tool_result has opaque content with no
809
809
  // contentBlocks property, so it cannot contain nested media.
810
- "daemon/context-overflow-reducer.ts",
810
+ "plugins/defaults/compaction/context-overflow-reducer.ts",
811
+
812
+ // Downgrades permanently-unsendable images nested in tool_result.contentBlocks
813
+ // (e.g. an oversized browser screenshot). web_search_tool_result has opaque
814
+ // content with no contentBlocks property, so it cannot hold such an image.
815
+ "daemon/persist-unsendable-image.ts",
811
816
 
812
817
  // Final orphan-pair safety pass in the Slack transcript renderer.
813
818
  // Server-side block types (`server_tool_use`, `web_search_tool_result`)
@@ -1,7 +1,7 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
 
3
- import { createContextSummaryMessage } from "../context/window-manager.js";
4
3
  import { stripMediaPayloadsForRetry } from "../daemon/conversation-media-retry.js";
4
+ import { createContextSummaryMessage } from "../plugins/defaults/compaction/window-manager.js";
5
5
  import type { ContentBlock, Message } from "../providers/types.js";
6
6
 
7
7
  // ---------------------------------------------------------------------------
@@ -92,7 +92,7 @@ mock.module("../daemon/conversation-messaging.js", () => ({
92
92
  // ---------------------------------------------------------------------------
93
93
 
94
94
  import type { TurnInterfaceContext } from "../channels/types.js";
95
- import type { ProcessConversationContext } from "../daemon/conversation-process.js";
95
+ import type { Conversation } from "../daemon/conversation.js";
96
96
  import { drainQueue } from "../daemon/conversation-process.js";
97
97
  import {
98
98
  MessageQueue,
@@ -102,7 +102,7 @@ import { TraceEmitter } from "../daemon/trace-emitter.js";
102
102
 
103
103
  // ---------------------------------------------------------------------------
104
104
  // Fake context — captures preactivation calls, satisfies the bare minimum
105
- // of `ProcessConversationContext`. `runAgentLoop` resolves immediately so
105
+ // of `Conversation`. `runAgentLoop` resolves immediately so
106
106
  // the drain-chain does not recurse forever.
107
107
  // ---------------------------------------------------------------------------
108
108
 
@@ -113,7 +113,7 @@ interface FakeRecord {
113
113
  function makeFakeContext(opts: {
114
114
  queue: MessageQueue;
115
115
  turnInterfaceContext?: TurnInterfaceContext;
116
- }): ProcessConversationContext & FakeRecord {
116
+ }): Conversation & FakeRecord {
117
117
  const calls: string[] = [];
118
118
  let preactivatedSkillIds: string[] | undefined = undefined;
119
119
  const ctx = {
@@ -177,7 +177,7 @@ function makeFakeContext(opts: {
177
177
  setTransportHints() {},
178
178
  applyHostEnvFromTransport() {},
179
179
  ensureHostProxiesForTurn() {},
180
- } as unknown as ProcessConversationContext & FakeRecord;
180
+ } as unknown as Conversation & FakeRecord;
181
181
  return ctx;
182
182
  }
183
183
 
@@ -185,6 +185,7 @@ function makeQueuedMessage(opts: {
185
185
  requestId: string;
186
186
  content?: string;
187
187
  turnInterfaceContext?: TurnInterfaceContext;
188
+ sourceActorPrincipalId?: string;
188
189
  }): QueuedMessage {
189
190
  return {
190
191
  content: opts.content ?? "follow up",
@@ -194,6 +195,10 @@ function makeQueuedMessage(opts: {
194
195
  metadata: {},
195
196
  sentAt: Date.now(),
196
197
  turnInterfaceContext: opts.turnInterfaceContext,
198
+ sourceActorPrincipalId: opts.sourceActorPrincipalId,
199
+ authContext: opts.sourceActorPrincipalId
200
+ ? ({ actorPrincipalId: opts.sourceActorPrincipalId } as never)
201
+ : undefined,
197
202
  };
198
203
  }
199
204
 
@@ -332,6 +337,7 @@ describe("drainQueue preactivation re-add for host-proxy interfaces", () => {
332
337
  makeQueuedMessage({
333
338
  requestId: "req-web-1",
334
339
  turnInterfaceContext: ifCtx,
340
+ sourceActorPrincipalId: "user-1",
335
341
  }),
336
342
  );
337
343
  const ctx = makeFakeContext({ queue, turnInterfaceContext: ifCtx });
@@ -346,6 +352,39 @@ describe("drainQueue preactivation re-add for host-proxy interfaces", () => {
346
352
  expect(ctx.preactivatedSkillIdCalls).toContain("computer-use");
347
353
  });
348
354
 
355
+ test("drainSingleMessage filters cross-client preactivation by the queued requester, not guardian owner", async () => {
356
+ mockCapabilityClients = [
357
+ { clientId: "owner-macos-client", actorPrincipalId: "owner-user" },
358
+ ];
359
+ const queue = new MessageQueue();
360
+ const ifCtx: TurnInterfaceContext = {
361
+ userMessageInterface: "web",
362
+ assistantMessageInterface: "web",
363
+ };
364
+ queue.push(
365
+ makeQueuedMessage({
366
+ requestId: "req-web-attacker",
367
+ turnInterfaceContext: ifCtx,
368
+ sourceActorPrincipalId: "trusted-contact-user",
369
+ }),
370
+ );
371
+ const ctx = makeFakeContext({ queue, turnInterfaceContext: ifCtx });
372
+ ctx.trustContext = {
373
+ trustClass: "trusted_contact",
374
+ guardianPrincipalId: "owner-user",
375
+ sourceChannel: "vellum",
376
+ };
377
+
378
+ await drainQueue(ctx);
379
+
380
+ expect(ctx.preactivatedSkillIdCalls).not.toContain("computer-use");
381
+ expect(ctx.preactivatedSkillIdCalls).not.toContain("app-control");
382
+ expect(ctx.currentTurnAuthContext?.actorPrincipalId).toBe(
383
+ "trusted-contact-user",
384
+ );
385
+ expect(ctx.currentTurnSourceActorPrincipalId).toBe("trusted-contact-user");
386
+ });
387
+
349
388
  test("drainSingleMessage does NOT re-add 'app-control' for web-sourced message when no capable client is connected", async () => {
350
389
  // mockCapabilityClients remains [] (reset by afterEach from prior test)
351
390
  const queue = new MessageQueue();
@@ -380,6 +419,7 @@ describe("drainQueue preactivation re-add for host-proxy interfaces", () => {
380
419
  makeQueuedMessage({
381
420
  requestId: "req-web-3",
382
421
  turnInterfaceContext: ifCtx,
422
+ sourceActorPrincipalId: "user-1",
383
423
  }),
384
424
  );
385
425
  const ctx = makeFakeContext({ queue, turnInterfaceContext: ifCtx });
@@ -208,14 +208,12 @@ mock.module("../memory/retriever.js", () => ({
208
208
  mock.module("../agent/loop.js", () => ({
209
209
  AgentLoop: class {
210
210
  compactionCircuit = new CompactionCircuit("test-conv");
211
- constructor(
212
- _provider: unknown,
213
- _systemPrompt: string,
214
- options?: {
215
- config?: Record<string, unknown>;
216
- resolveSystemPrompt?: (history: Message[]) => Record<string, unknown>;
217
- },
218
- ) {
211
+ constructor(options?: {
212
+ provider?: unknown;
213
+ systemPrompt?: string;
214
+ config?: Record<string, unknown>;
215
+ resolveSystemPrompt?: (history: Message[]) => Record<string, unknown>;
216
+ }) {
219
217
  captured.constructorMaxTokens = options?.config?.maxTokens;
220
218
  const resolved = options?.resolveSystemPrompt?.([]);
221
219
  captured.resolvedMaxTokens = resolved?.maxTokens;
@@ -229,12 +227,13 @@ mock.module("../agent/loop.js", () => ({
229
227
  getResolvedTools() {
230
228
  return [];
231
229
  }
232
- async run(
233
- messages: Message[],
234
- onEvent: (event: Record<string, unknown>) => void,
235
- options?: { callSite?: string },
236
- ): Promise<Message[]> {
237
- captured.callSite = options?.callSite;
230
+ async run(options: {
231
+ messages: Message[];
232
+ onEvent: (event: Record<string, unknown>) => void;
233
+ callSite?: string;
234
+ }): Promise<Message[]> {
235
+ const { messages, onEvent } = options;
236
+ captured.callSite = options.callSite;
238
237
  onEvent({
239
238
  type: "usage",
240
239
  inputTokens: 0,
@@ -250,9 +249,10 @@ mock.module("../agent/loop.js", () => ({
250
249
  },
251
250
  }));
252
251
 
253
- mock.module("../context/window-manager.js", () => ({
252
+ mock.module("../plugins/defaults/compaction/window-manager.js", () => ({
254
253
  ContextWindowManager: class {
255
254
  constructor() {}
255
+ updateConfig() {}
256
256
  shouldCompact() {
257
257
  return { needed: false, estimatedTokens: 0 };
258
258
  }
@@ -98,58 +98,57 @@ mock.module("../context/token-estimator.js", () => ({
98
98
 
99
99
  // Overflow recovery module mocks — the convergence loop delegates to these
100
100
  // but these tests exercise the Conversation-level flow, not the reducer internals.
101
- // The reducer mock delegates to the compactFn to simulate a forced compaction
102
- // tier, matching the real reducer's behavior for Tier 1.
103
- mock.module("../daemon/context-overflow-reducer.js", () => ({
104
- createInitialReducerState: () => ({
105
- appliedTiers: [],
106
- injectionMode: "full" as const,
107
- exhausted: false,
108
- }),
109
- reduceContextOverflow: async (
110
- msgs: Message[],
111
- _cfg: unknown,
112
- _state: unknown,
113
- compactFn?: (
114
- m: Message[],
115
- s: AbortSignal | undefined,
116
- o: Record<string, unknown>,
117
- ) => Promise<{
118
- compacted: boolean;
119
- messages: Message[];
120
- compactedPersistedMessages?: number;
121
- summaryText?: string;
122
- [k: string]: unknown;
123
- }>,
124
- signal?: AbortSignal,
125
- ) => {
126
- let resultMessages = msgs;
127
- let compactionResult;
128
- if (compactFn) {
129
- const cr = await compactFn(msgs, signal, { force: true });
101
+ // The reducer mock runs the forced-compaction tier through defaultCompact, which
102
+ // resolves the conversation's ContextWindowManager from the store — mirroring the
103
+ // real reducer's Tier 1.
104
+ mock.module(
105
+ "../plugins/defaults/compaction/context-overflow-reducer.js",
106
+ () => ({
107
+ createInitialReducerState: () => ({
108
+ appliedTiers: [],
109
+ injectionMode: "full" as const,
110
+ exhausted: false,
111
+ }),
112
+ reduceContextOverflow: async (
113
+ msgs: Message[],
114
+ cfg: { conversationId: string },
115
+ _state: unknown,
116
+ signal?: AbortSignal,
117
+ ) => {
118
+ const { defaultCompact } =
119
+ await import("../plugins/defaults/compaction/compact.js");
120
+ const cr = await defaultCompact({
121
+ conversationId: cfg.conversationId,
122
+ messages: msgs,
123
+ signal,
124
+ force: true,
125
+ minKeepRecentUserTurns: 0,
126
+ });
127
+ let resultMessages = msgs;
128
+ let compactionResult;
130
129
  if (cr.compacted) {
131
130
  resultMessages = cr.messages;
132
131
  compactionResult = cr;
133
132
  }
134
- }
135
- return {
136
- messages: resultMessages,
137
- tier: "forced_compaction",
138
- state: {
139
- appliedTiers: [
140
- "forced_compaction",
141
- "tool_result_truncation",
142
- "media_stubbing",
143
- "injection_downgrade",
144
- ],
145
- injectionMode: "full",
146
- exhausted: true,
147
- },
148
- estimatedTokens: 1000,
149
- compactionResult,
150
- };
151
- },
152
- }));
133
+ return {
134
+ messages: resultMessages,
135
+ tier: "forced_compaction",
136
+ state: {
137
+ appliedTiers: [
138
+ "forced_compaction",
139
+ "tool_result_truncation",
140
+ "media_stubbing",
141
+ "injection_downgrade",
142
+ ],
143
+ injectionMode: "full",
144
+ exhausted: true,
145
+ },
146
+ estimatedTokens: 1000,
147
+ compactionResult,
148
+ };
149
+ },
150
+ }),
151
+ );
153
152
 
154
153
  mock.module("../daemon/context-overflow-policy.js", () => ({
155
154
  resolveOverflowAction: () => "fail_gracefully",
@@ -218,9 +217,10 @@ mock.module("../memory/retriever.js", () => ({
218
217
  let maybeCompactCalls: Array<{ force: boolean }> = [];
219
218
  let forceCompactionEnabled = false;
220
219
 
221
- mock.module("../context/window-manager.js", () => ({
220
+ mock.module("../plugins/defaults/compaction/window-manager.js", () => ({
222
221
  ContextWindowManager: class {
223
222
  constructor() {}
223
+ updateConfig() {}
224
224
  shouldCompact() {
225
225
  return { needed: false, estimatedTokens: 0 };
226
226
  }
@@ -280,10 +280,11 @@ mock.module("../agent/loop.js", () => ({
280
280
  getActiveModel() {
281
281
  return undefined;
282
282
  }
283
- async run(
284
- messages: Message[],
285
- onEvent: (event: AgentEvent) => void,
286
- ): Promise<AgentLoopRunResult> {
283
+ async run(options: {
284
+ messages: Message[];
285
+ onEvent: (event: AgentEvent) => void;
286
+ }): Promise<AgentLoopRunResult> {
287
+ const { messages, onEvent } = options;
287
288
  // Prime the assistant row anchor — production code emits this from
288
289
  // `AgentLoop.run` just before `provider.sendMessage`.
289
290
  await onEvent({ type: "llm_call_started" });
@@ -486,11 +487,10 @@ describe("provider ordering error retry", () => {
486
487
  firstRunErrorMode = "ordering";
487
488
  maybeCompactCalls = [];
488
489
  forceCompactionEnabled = false;
489
- // Orchestrator pipelines (`overflowReduce`, `persistence`, …) run through
490
- // the plugin registry; re-register every default so each pipeline has a
491
- // middleware to dispatch to. The `context-overflow-reducer` module itself
492
- // (and other collaborators) are mocked above, so the default plugins'
493
- // delegates go through the mocked implementations.
490
+ // The compaction pipeline runs through the plugin registry; re-register
491
+ // every default so it has a middleware to dispatch to. Collaborators are
492
+ // mocked above, so the default plugins' delegates go through the mocked
493
+ // implementations.
494
494
  resetPluginRegistryAndRegisterDefaults();
495
495
  });
496
496
 
@@ -570,7 +570,7 @@ describe("provider ordering error retry", () => {
570
570
  });
571
571
 
572
572
  expect(agentLoopRunCount).toBe(2);
573
- expect(maybeCompactCalls).toEqual([{ force: false }, { force: true }]);
573
+ expect(maybeCompactCalls).toEqual([{ force: true }]);
574
574
  expect(events.some((e) => e.type === "message_complete")).toBe(true);
575
575
  expect(events.some((e) => e.type === "conversation_error")).toBe(false);
576
576
  });
@@ -595,9 +595,10 @@ describe("provider ordering error retry", () => {
595
595
  // (forceCompactionEnabled=false), the second run also fails with
596
596
  // context_too_large. The overflow policy (fail_gracefully) surfaces error.
597
597
  expect(agentLoopRunCount).toBe(2);
598
- // Two maybeCompact calls: initial auto-compact (force:false),
599
- // reducer's compactFn (force:true).
600
- expect(maybeCompactCalls).toEqual([{ force: false }, { force: true }]);
598
+ // One maybeCompact call: the reducer's compactFn (force:true). The
599
+ // orchestrator's start-of-turn auto-compact no longer runs — the loop's
600
+ // pre-call budget gate owns turn-start compaction and doesn't trip here.
601
+ expect(maybeCompactCalls).toEqual([{ force: true }]);
601
602
 
602
603
  expect(events.some((e) => e.type === "conversation_error")).toBe(true);
603
604
  });
@@ -618,7 +619,7 @@ describe("provider ordering error retry", () => {
618
619
 
619
620
  // Same as above — convergence loop re-runs agent loop, which also fails.
620
621
  expect(agentLoopRunCount).toBe(2);
621
- expect(maybeCompactCalls).toEqual([{ force: false }, { force: true }]);
622
+ expect(maybeCompactCalls).toEqual([{ force: true }]);
622
623
  expect(events.some((e) => e.type === "conversation_error")).toBe(true);
623
624
  });
624
625
 
@@ -637,7 +638,7 @@ describe("provider ordering error retry", () => {
637
638
  });
638
639
 
639
640
  expect(agentLoopRunCount).toBe(2);
640
- expect(maybeCompactCalls).toEqual([{ force: false }, { force: true }]);
641
+ expect(maybeCompactCalls).toEqual([{ force: true }]);
641
642
  expect(events.some((e) => e.type === "message_complete")).toBe(true);
642
643
  expect(events.some((e) => e.type === "conversation_error")).toBe(false);
643
644
  });
@@ -660,7 +661,7 @@ describe("provider ordering error retry", () => {
660
661
  // the regex patterns, but classifyConversationError recognizes statusCode 413
661
662
  // as CONTEXT_TOO_LARGE and sets contextTooLargeDetected = true.
662
663
  expect(agentLoopRunCount).toBe(2);
663
- expect(maybeCompactCalls).toEqual([{ force: false }, { force: true }]);
664
+ expect(maybeCompactCalls).toEqual([{ force: true }]);
664
665
  expect(events.some((e) => e.type === "message_complete")).toBe(true);
665
666
  expect(events.some((e) => e.type === "conversation_error")).toBe(false);
666
667
  });
@@ -262,9 +262,10 @@ mock.module("../memory/retriever.js", () => ({
262
262
  injectMemoryRecallAsUserBlock: (msgs: Message[]) => msgs,
263
263
  }));
264
264
 
265
- mock.module("../context/window-manager.js", () => ({
265
+ mock.module("../plugins/defaults/compaction/window-manager.js", () => ({
266
266
  ContextWindowManager: class {
267
267
  constructor() {}
268
+ updateConfig() {}
268
269
  shouldCompact() {
269
270
  return { needed: false, estimatedTokens: 0 };
270
271
  }
@@ -353,15 +354,14 @@ mock.module("../agent/loop.js", () => ({
353
354
  getActiveModel() {
354
355
  return undefined;
355
356
  }
356
- async run(
357
- messages: Message[],
358
- onEvent: (event: AgentEvent) => void | Promise<void>,
359
- options?: {
360
- onCheckpoint?: (
361
- checkpoint: CheckpointInfo,
362
- ) => CheckpointDecision | Promise<CheckpointDecision>;
363
- },
364
- ): Promise<AgentLoopRunResult> {
357
+ async run(options: {
358
+ messages: Message[];
359
+ onEvent: (event: AgentEvent) => void | Promise<void>;
360
+ onCheckpoint?: (
361
+ checkpoint: CheckpointInfo,
362
+ ) => CheckpointDecision | Promise<CheckpointDecision>;
363
+ }): Promise<AgentLoopRunResult> {
364
+ const { messages, onEvent } = options;
365
365
  return new Promise<AgentLoopRunResult>((resolveResult, reject) => {
366
366
  const pending: PendingRun = {
367
367
  resolve: (history: Message[]) =>