@vellumai/assistant 0.8.8 → 0.8.9-dev.202606091926.ebb2d62

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 (490) 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 +273 -121
  12. package/package.json +2 -2
  13. package/scripts/sync-llm-catalog.ts +2 -0
  14. package/src/__tests__/activation-early-marking.test.ts +120 -0
  15. package/src/__tests__/agent-loop-callsite-precedence.test.ts +69 -14
  16. package/src/__tests__/agent-loop-exit-reason.test.ts +204 -144
  17. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +50 -35
  18. package/src/__tests__/agent-loop-output-hooks.test.ts +357 -0
  19. package/src/__tests__/agent-loop-override-profile.test.ts +25 -6
  20. package/src/__tests__/agent-loop-provider-error-recording.test.ts +41 -21
  21. package/src/__tests__/agent-loop-thinking.test.ts +36 -20
  22. package/src/__tests__/agent-loop.test.ts +441 -96
  23. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +14 -14
  24. package/src/__tests__/agent-wake-override-profile.test.ts +17 -21
  25. package/src/__tests__/anthropic-provider.test.ts +23 -8
  26. package/src/__tests__/app-builder-tool-scripts.test.ts +21 -0
  27. package/src/__tests__/app-control-flow.test.ts +1 -1
  28. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  29. package/src/__tests__/app-executors.test.ts +132 -0
  30. package/src/__tests__/approval-cascade.test.ts +6 -5
  31. package/src/__tests__/approval-routes-http.test.ts +4 -1
  32. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  33. package/src/__tests__/build-persisted-content.test.ts +75 -1
  34. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  35. package/src/__tests__/channel-approvals.test.ts +1 -1
  36. package/src/__tests__/compaction-circuit.test.ts +258 -0
  37. package/src/__tests__/compaction-direct.test.ts +146 -0
  38. package/src/__tests__/compaction-events.test.ts +7 -7
  39. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  40. package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
  41. package/src/__tests__/config-managed-gemini-defaults.test.ts +2 -46
  42. package/src/__tests__/context-overflow-reducer.test.ts +265 -125
  43. package/src/__tests__/context-window-manager-compact-retry.test.ts +121 -15
  44. package/src/__tests__/conversation-abort-tool-results.test.ts +7 -5
  45. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +7 -10
  46. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +78 -119
  47. package/src/__tests__/conversation-agent-loop-overflow.test.ts +158 -234
  48. package/src/__tests__/conversation-agent-loop.test.ts +342 -623
  49. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  50. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -5
  51. package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
  52. package/src/__tests__/conversation-error.test.ts +15 -1
  53. package/src/__tests__/conversation-history-web-search.test.ts +6 -1
  54. package/src/__tests__/conversation-media-retry.test.ts +1 -1
  55. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +44 -4
  56. package/src/__tests__/conversation-process-callsite.test.ts +15 -15
  57. package/src/__tests__/conversation-provider-retry-repair.test.ts +66 -65
  58. package/src/__tests__/conversation-queue.test.ts +10 -10
  59. package/src/__tests__/conversation-runtime-assembly.test.ts +1059 -231
  60. package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
  61. package/src/__tests__/conversation-slash-queue.test.ts +7 -5
  62. package/src/__tests__/conversation-slash-unknown.test.ts +7 -5
  63. package/src/__tests__/conversation-speed-override.test.ts +11 -10
  64. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  65. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +395 -0
  66. package/src/__tests__/conversation-surfaces-app-control.test.ts +48 -1
  67. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +73 -4
  68. package/src/__tests__/conversation-undo.test.ts +2 -2
  69. package/src/__tests__/conversation-workspace-cache-state.test.ts +24 -21
  70. package/src/__tests__/conversation-workspace-injection.test.ts +69 -7
  71. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +15 -12
  72. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  73. package/src/__tests__/corrected-target.test.ts +93 -0
  74. package/src/__tests__/credential-execution-feature-gates.test.ts +5 -4
  75. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  76. package/src/__tests__/cu-unified-flow.test.ts +36 -0
  77. package/src/__tests__/db-acp-history.test.ts +101 -0
  78. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  79. package/src/__tests__/embedding-managed-proxy-selection.test.ts +6 -40
  80. package/src/__tests__/empty-response-hook.test.ts +1 -1
  81. package/src/__tests__/file-write-tool.test.ts +63 -0
  82. package/src/__tests__/gateway-only-guard.test.ts +17 -2
  83. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  84. package/src/__tests__/guardian-routing-invariants.test.ts +93 -4
  85. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  86. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  87. package/src/__tests__/heartbeat-service.test.ts +1 -0
  88. package/src/__tests__/history-repair-hook.test.ts +5 -1
  89. package/src/__tests__/host-app-control-proxy.test.ts +45 -0
  90. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  91. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  92. package/src/__tests__/inference-profile-reaper.test.ts +62 -0
  93. package/src/__tests__/inference-profile-session-handler.test.ts +86 -0
  94. package/src/__tests__/injector-background-turn.test.ts +13 -23
  95. package/src/__tests__/injector-chain.test.ts +268 -44
  96. package/src/__tests__/injector-disk-pressure.test.ts +210 -52
  97. package/src/__tests__/injector-document-comments.test.ts +97 -114
  98. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  99. package/src/__tests__/injector-v3-suppression.test.ts +4 -4
  100. package/src/__tests__/list-messages-client-message-id.test.ts +91 -0
  101. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  102. package/src/__tests__/llm-catalog-parity.test.ts +4 -0
  103. package/src/__tests__/llm-resolver.test.ts +73 -0
  104. package/src/__tests__/memory-retrieval-hook.test.ts +156 -38
  105. package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
  106. package/src/__tests__/notification-decision-strategy.test.ts +3 -3
  107. package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
  108. package/src/__tests__/persist-unsendable-image-downscale.test.ts +145 -0
  109. package/src/__tests__/persist-unsendable-image.test.ts +97 -1
  110. package/src/__tests__/persistence-secret-redaction.test.ts +78 -0
  111. package/src/__tests__/plugin-api-shim.test.ts +6 -9
  112. package/src/__tests__/plugin-bootstrap.test.ts +91 -81
  113. package/src/__tests__/plugin-registry.test.ts +3 -49
  114. package/src/__tests__/plugin-skill-contribution.test.ts +15 -14
  115. package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
  116. package/src/__tests__/plugin-types.test.ts +0 -70
  117. package/src/__tests__/post-turn-tool-result-truncation.test.ts +69 -0
  118. package/src/__tests__/pre-model-call-sanitize.test.ts +109 -0
  119. package/src/__tests__/published-app-updater.test.ts +138 -0
  120. package/src/__tests__/reaction-persistence.test.ts +1 -1
  121. package/src/__tests__/retry-thinking-adaptive-only.test.ts +245 -0
  122. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  123. package/src/__tests__/server-history-render.test.ts +39 -0
  124. package/src/__tests__/skill-feature-flags-integration.test.ts +31 -0
  125. package/src/__tests__/steer-tool-repair.test.ts +1 -1
  126. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  127. package/src/__tests__/subagent-detail.test.ts +25 -7
  128. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  129. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  130. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  131. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  132. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  133. package/src/__tests__/title-generate-hook.test.ts +5 -1
  134. package/src/__tests__/tool-error-hook.test.ts +1 -1
  135. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -1
  136. package/src/__tests__/tool-start-timestamp.test.ts +218 -0
  137. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  138. package/src/__tests__/web-fetch.test.ts +45 -0
  139. package/src/acp/__tests__/agent-process.test.ts +161 -0
  140. package/src/acp/__tests__/client-handler.test.ts +40 -0
  141. package/src/acp/__tests__/helpers/acp-config-stub.ts +0 -2
  142. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  143. package/src/acp/__tests__/helpers/exec-file-stub.ts +106 -0
  144. package/src/acp/__tests__/prepare-agent-env.test.ts +97 -0
  145. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  146. package/src/acp/__tests__/session-manager-resume.test.ts +888 -0
  147. package/src/acp/agent-process.ts +61 -1
  148. package/src/acp/auto-install.test.ts +280 -0
  149. package/src/acp/auto-install.ts +232 -0
  150. package/src/acp/client-handler.ts +31 -0
  151. package/src/acp/prepare-agent-env.ts +80 -27
  152. package/src/acp/resolve-agent.test.ts +188 -28
  153. package/src/acp/resolve-agent.ts +119 -42
  154. package/src/acp/resume-hint.ts +23 -0
  155. package/src/acp/session-manager.ts +507 -73
  156. package/src/agent/compaction-circuit.ts +60 -102
  157. package/src/agent/loop.ts +403 -251
  158. package/src/api/events/tool-result.ts +9 -0
  159. package/src/api/events/tool-use-start.ts +7 -0
  160. package/src/api/responses/conversation-message.ts +72 -13
  161. package/src/api/responses/memory-v3-selection-log.ts +19 -10
  162. package/src/approvals/guardian-request-resolvers.ts +27 -1
  163. package/src/background-wake/next-wake.ts +1 -0
  164. package/src/cli/commands/__tests__/memory-v3.test.ts +191 -210
  165. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  166. package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
  167. package/src/cli/commands/memory-v3.ts +57 -199
  168. package/src/cli/commands/plugins.ts +43 -37
  169. package/src/cli/lib/__tests__/install-from-github.test.ts +790 -111
  170. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
  171. package/src/cli/lib/__tests__/plugin-details.test.ts +381 -0
  172. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +270 -0
  173. package/src/cli/lib/__tests__/search-plugins.test.ts +233 -32
  174. package/src/cli/lib/install-from-github.ts +797 -60
  175. package/src/cli/lib/plugin-catalog-cache.ts +84 -0
  176. package/src/cli/lib/plugin-details.ts +416 -0
  177. package/src/cli/lib/plugin-marketplace.ts +215 -0
  178. package/src/cli/lib/search-plugins.ts +201 -29
  179. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  180. package/src/config/acp-defaults.test.ts +10 -0
  181. package/src/config/acp-defaults.ts +9 -3
  182. package/src/config/acp-schema.ts +1 -7
  183. package/src/config/bundled-skills/acp/SKILL.md +80 -41
  184. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  185. package/src/config/bundled-skills/app-builder/SKILL.md +224 -381
  186. package/src/config/bundled-skills/app-builder/TOOLS.json +72 -2
  187. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  188. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  189. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  190. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  191. package/src/config/bundled-skills/app-builder/tools/app-update.ts +18 -0
  192. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  193. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  194. package/src/config/bundled-tool-registry.ts +4 -0
  195. package/src/config/call-site-defaults.ts +0 -3
  196. package/src/config/feature-flag-registry.json +10 -56
  197. package/src/config/llm-resolver.ts +39 -7
  198. package/src/config/loader.ts +5 -22
  199. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -9
  200. package/src/config/schemas/call-site-catalog.ts +0 -21
  201. package/src/config/schemas/heartbeat.ts +9 -0
  202. package/src/config/schemas/llm.ts +17 -3
  203. package/src/config/schemas/memory-v3.ts +58 -8
  204. package/src/config/seed-inference-profiles.ts +18 -0
  205. package/src/context/compactor.ts +22 -4
  206. package/src/context/post-turn-tool-result-truncation.ts +39 -1
  207. package/src/context/strip-injections.ts +8 -2
  208. package/src/daemon/conversation-agent-loop-handlers.ts +120 -42
  209. package/src/daemon/conversation-agent-loop.ts +308 -1297
  210. package/src/daemon/conversation-error.ts +31 -4
  211. package/src/daemon/conversation-history.ts +1 -1
  212. package/src/daemon/conversation-lifecycle.ts +11 -255
  213. package/src/daemon/conversation-media-retry.ts +19 -6
  214. package/src/daemon/conversation-messaging.ts +17 -0
  215. package/src/daemon/conversation-process.ts +22 -141
  216. package/src/daemon/conversation-queue-manager.ts +8 -0
  217. package/src/daemon/conversation-registry.ts +159 -0
  218. package/src/daemon/conversation-runtime-assembly.ts +361 -393
  219. package/src/daemon/conversation-store.ts +9 -90
  220. package/src/daemon/conversation-surfaces.ts +165 -11
  221. package/src/daemon/conversation-workspace.ts +17 -0
  222. package/src/daemon/conversation.ts +444 -62
  223. package/src/daemon/disk-pressure-policy.ts +0 -1
  224. package/src/daemon/external-plugins-bootstrap.ts +36 -46
  225. package/src/daemon/handlers/config-channels.ts +11 -2
  226. package/src/daemon/handlers/conversations.ts +3 -1
  227. package/src/daemon/handlers/shared.ts +9 -1
  228. package/src/daemon/handlers/skills.ts +4 -1
  229. package/src/daemon/host-app-control-proxy.ts +72 -57
  230. package/src/daemon/host-proxy-preactivation.ts +1 -3
  231. package/src/daemon/lifecycle.ts +21 -7
  232. package/src/daemon/persist-unsendable-image.ts +62 -25
  233. package/src/daemon/process-message.ts +1 -1
  234. package/src/daemon/server.ts +2 -0
  235. package/src/daemon/tool-side-effects.ts +15 -0
  236. package/src/daemon/wake-conversation-ops.ts +269 -0
  237. package/src/embedded/plugin-api.ts +2 -2
  238. package/src/export/__tests__/transcript-formatter.test.ts +5 -0
  239. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  240. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  241. package/src/heartbeat/heartbeat-service.ts +26 -0
  242. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  243. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  244. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  245. package/src/ipc/skill-routes/memory.ts +4 -2
  246. package/src/memory/__tests__/activation-session-store.test.ts +41 -0
  247. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +87 -0
  248. package/src/memory/__tests__/onboarding-events-store.test.ts +80 -0
  249. package/src/memory/activation-session-store.ts +43 -0
  250. package/src/memory/conversation-crud.ts +29 -19
  251. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  252. package/src/memory/db-init.ts +6 -0
  253. package/src/memory/embedding-backend.ts +5 -22
  254. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  255. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -4
  256. package/src/memory/jobs-worker.ts +25 -1
  257. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  258. package/src/memory/migrations/273-onboarding-events-funnel-columns.ts +46 -0
  259. package/src/memory/migrations/274-create-activation-sessions.ts +15 -0
  260. package/src/memory/migrations/index.ts +3 -0
  261. package/src/memory/onboarding-events-store.ts +66 -18
  262. package/src/memory/schema/acp.ts +4 -0
  263. package/src/memory/schema/infrastructure.ts +13 -0
  264. package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -97
  265. package/src/memory/v2/__tests__/page-store.test.ts +22 -0
  266. package/src/memory/v2/consolidation-job.ts +2 -63
  267. package/src/memory/v2/types.ts +5 -0
  268. package/src/messaging/providers/telegram-bot/api.ts +14 -5
  269. package/src/notifications/__tests__/copy-composer.test.ts +244 -0
  270. package/src/notifications/access-request-copy.ts +298 -0
  271. package/src/notifications/adapters/slack.ts +3 -3
  272. package/src/notifications/adapters/telegram.ts +9 -2
  273. package/src/notifications/copy-composer.ts +49 -267
  274. package/src/notifications/decision-engine.ts +16 -35
  275. package/src/notifications/home-feed-side-effect.ts +1 -6
  276. package/src/plugin-api/constants.ts +4 -0
  277. package/src/plugin-api/index.ts +40 -11
  278. package/src/plugin-api/types.ts +108 -0
  279. package/src/plugins/defaults/compaction/compact.ts +106 -0
  280. package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +250 -42
  281. package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
  282. package/src/plugins/defaults/compaction/manager-store.ts +57 -0
  283. package/src/plugins/defaults/compaction/package.json +1 -2
  284. package/src/{context → plugins/defaults/compaction}/window-manager.ts +95 -25
  285. package/src/plugins/defaults/empty-response/package.json +0 -1
  286. package/src/plugins/defaults/history-repair/package.json +0 -1
  287. package/src/plugins/defaults/index.ts +156 -26
  288. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
  289. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +285 -0
  290. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
  291. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +148 -73
  292. package/src/plugins/defaults/memory-retrieval/package.json +14 -0
  293. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +223 -0
  294. package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +71 -0
  295. package/src/plugins/defaults/memory-v3-shadow/__tests__/dense.test.ts +181 -0
  296. package/src/plugins/defaults/memory-v3-shadow/__tests__/edge.test.ts +247 -0
  297. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +147 -134
  298. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +456 -0
  299. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +662 -0
  300. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +306 -0
  301. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +91 -0
  302. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +402 -0
  303. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-needle.test.ts +135 -0
  304. package/src/plugins/defaults/memory-v3-shadow/__tests__/sections.test.ts +125 -0
  305. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +74 -19
  306. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +446 -0
  307. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +592 -0
  308. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -24
  309. package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +91 -0
  310. package/src/plugins/defaults/memory-v3-shadow/dense.ts +97 -0
  311. package/src/plugins/defaults/memory-v3-shadow/edge.ts +252 -0
  312. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  313. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  314. package/src/plugins/defaults/memory-v3-shadow/injector.ts +76 -0
  315. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +555 -0
  316. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +266 -0
  317. package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
  318. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +71 -0
  319. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +204 -0
  320. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +16 -8
  321. package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +236 -0
  322. package/src/plugins/defaults/memory-v3-shadow/section-needle.ts +200 -0
  323. package/src/plugins/defaults/memory-v3-shadow/sections.ts +115 -0
  324. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +156 -0
  325. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +382 -0
  326. package/src/plugins/defaults/memory-v3-shadow/types.ts +92 -0
  327. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +4 -1
  328. package/src/plugins/defaults/title-generate/package.json +0 -1
  329. package/src/plugins/defaults/tool-error/package.json +0 -1
  330. package/src/plugins/defaults/tool-result-truncate/package.json +0 -1
  331. package/src/plugins/external-api.ts +12 -2
  332. package/src/plugins/pipeline.ts +6 -293
  333. package/src/plugins/registry.ts +9 -37
  334. package/src/plugins/types.ts +76 -381
  335. package/src/plugins/user-loader.ts +30 -127
  336. package/src/prompts/__tests__/system-prompt.test.ts +6 -0
  337. package/src/prompts/system-prompt.ts +61 -10
  338. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +71 -4
  339. package/src/providers/anthropic/client.ts +9 -10
  340. package/src/providers/inference/kimi-cjk-token-ids.ts +493 -0
  341. package/src/providers/inference/logit-bias.ts +55 -0
  342. package/src/providers/model-catalog.ts +57 -0
  343. package/src/providers/openai/__tests__/vision-not-supported.test.ts +75 -0
  344. package/src/providers/openai/chat-completions-provider.ts +44 -1
  345. package/src/providers/retry.ts +57 -7
  346. package/src/providers/types.ts +6 -0
  347. package/src/runtime/__tests__/agent-wake.test.ts +555 -691
  348. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  349. package/src/runtime/agent-wake.ts +108 -209
  350. package/src/runtime/assistant-event-hub.ts +1 -1
  351. package/src/runtime/channel-approvals.ts +1 -1
  352. package/src/runtime/interactive-ui.ts +1 -1
  353. package/src/runtime/routes/__tests__/acp-routes.test.ts +466 -55
  354. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  355. package/src/runtime/routes/__tests__/plugins-routes.test.ts +423 -73
  356. package/src/runtime/routes/__tests__/stt-routes.test.ts +112 -0
  357. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  358. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  359. package/src/runtime/routes/acp-routes.test.ts +185 -32
  360. package/src/runtime/routes/acp-routes.ts +328 -30
  361. package/src/runtime/routes/app-management-routes.ts +3 -0
  362. package/src/runtime/routes/approval-routes.ts +1 -1
  363. package/src/runtime/routes/browser-routes.ts +1 -1
  364. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  365. package/src/runtime/routes/channel-verification-routes.ts +14 -5
  366. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  367. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  368. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  369. package/src/runtime/routes/conversation-routes.ts +30 -2
  370. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  371. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  372. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  373. package/src/runtime/routes/host-cu-routes.ts +1 -1
  374. package/src/runtime/routes/identity-routes.ts +18 -3
  375. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  376. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
  377. package/src/runtime/routes/inference-profile-session-handler.ts +11 -0
  378. package/src/runtime/routes/inference-profile-session-reaper.ts +6 -0
  379. package/src/runtime/routes/memory-v3-routes.ts +65 -305
  380. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +1 -1
  381. package/src/runtime/routes/playground/helpers.ts +1 -1
  382. package/src/runtime/routes/plugins-routes.ts +337 -35
  383. package/src/runtime/routes/stt-routes.ts +45 -12
  384. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  385. package/src/runtime/routes/work-items-routes.ts +2 -4
  386. package/src/runtime/routes/workspace-routes.ts +50 -15
  387. package/src/runtime/services/conversation-serializer.ts +1 -1
  388. package/src/runtime/verification-outbound-actions.ts +147 -2
  389. package/src/runtime/verification-templates.ts +29 -3
  390. package/src/services/published-app-updater.ts +30 -8
  391. package/src/signals/cancel.ts +2 -4
  392. package/src/subagent/manager.ts +21 -5
  393. package/src/telemetry/__tests__/activation-funnel.test.ts +95 -0
  394. package/src/telemetry/activation-funnel.ts +167 -0
  395. package/src/telemetry/types.ts +13 -0
  396. package/src/telemetry/usage-telemetry-reporter.test.ts +154 -0
  397. package/src/telemetry/usage-telemetry-reporter.ts +26 -1
  398. package/src/tools/acp/context.ts +20 -0
  399. package/src/tools/acp/list-agents.test.ts +9 -19
  400. package/src/tools/acp/list-agents.ts +3 -15
  401. package/src/tools/acp/spawn.test.ts +173 -202
  402. package/src/tools/acp/spawn.ts +37 -172
  403. package/src/tools/acp/steer.test.ts +105 -8
  404. package/src/tools/acp/steer.ts +48 -17
  405. package/src/tools/apps/executors.ts +166 -50
  406. package/src/tools/browser/browser-execution.ts +12 -2
  407. package/src/tools/filesystem/write.ts +34 -0
  408. package/src/tools/network/web-fetch.ts +65 -24
  409. package/src/tools/skills/load.ts +1 -1
  410. package/src/tools/subagent/spawn.ts +2 -4
  411. package/src/tools/ui-surface/definitions.ts +32 -5
  412. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  413. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +69 -45
  414. package/docs/plugins.md +0 -832
  415. package/examples/plugins/echo/register.ts +0 -143
  416. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  417. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  418. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  419. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -667
  420. package/src/__tests__/pipeline-runner.test.ts +0 -554
  421. package/src/daemon/wake-target-adapter.ts +0 -253
  422. package/src/memory/v3/__tests__/assign.test.ts +0 -242
  423. package/src/memory/v3/__tests__/capabilities.test.ts +0 -118
  424. package/src/memory/v3/__tests__/core.test.ts +0 -39
  425. package/src/memory/v3/__tests__/health.test.ts +0 -219
  426. package/src/memory/v3/__tests__/maintain-job.test.ts +0 -288
  427. package/src/memory/v3/__tests__/needle.test.ts +0 -107
  428. package/src/memory/v3/__tests__/orchestrate.test.ts +0 -436
  429. package/src/memory/v3/__tests__/provider-blocks.test.ts +0 -13
  430. package/src/memory/v3/__tests__/reconcile.test.ts +0 -274
  431. package/src/memory/v3/__tests__/render-injection.test.ts +0 -61
  432. package/src/memory/v3/__tests__/router.test.ts +0 -332
  433. package/src/memory/v3/__tests__/selector.test.ts +0 -470
  434. package/src/memory/v3/__tests__/shadow-plugin.test.ts +0 -432
  435. package/src/memory/v3/__tests__/snapshot.test.ts +0 -168
  436. package/src/memory/v3/__tests__/tree.test.ts +0 -192
  437. package/src/memory/v3/assign.ts +0 -268
  438. package/src/memory/v3/capabilities.ts +0 -124
  439. package/src/memory/v3/core.ts +0 -26
  440. package/src/memory/v3/health.ts +0 -0
  441. package/src/memory/v3/maintain-job.ts +0 -314
  442. package/src/memory/v3/needle.ts +0 -115
  443. package/src/memory/v3/orchestrate.ts +0 -126
  444. package/src/memory/v3/page-content.ts +0 -34
  445. package/src/memory/v3/provider-blocks.ts +0 -26
  446. package/src/memory/v3/reconcile.ts +0 -523
  447. package/src/memory/v3/router.ts +0 -190
  448. package/src/memory/v3/selection-log-store.ts +0 -84
  449. package/src/memory/v3/selector.ts +0 -226
  450. package/src/memory/v3/shadow-plugin.ts +0 -411
  451. package/src/memory/v3/snapshot.ts +0 -209
  452. package/src/memory/v3/tree.ts +0 -174
  453. package/src/memory/v3/types.ts +0 -59
  454. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
  455. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  456. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  457. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  458. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  459. package/src/plugins/defaults/compaction/register.ts +0 -35
  460. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  461. package/src/plugins/defaults/empty-response/register.ts +0 -23
  462. package/src/plugins/defaults/history-repair/register.ts +0 -24
  463. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +0 -216
  464. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  465. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  466. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  467. package/src/plugins/defaults/title-generate/register.ts +0 -35
  468. package/src/plugins/defaults/tool-error/register.ts +0 -23
  469. package/src/plugins/defaults/tool-result-truncate/register.ts +0 -24
  470. package/src/proactive-artifact/aux-message-injector.ts +0 -97
  471. package/src/proactive-artifact/decision.test.ts +0 -226
  472. package/src/proactive-artifact/decision.ts +0 -165
  473. package/src/proactive-artifact/index.ts +0 -7
  474. package/src/proactive-artifact/job.test.ts +0 -962
  475. package/src/proactive-artifact/job.ts +0 -372
  476. package/src/proactive-artifact/message-copy.ts +0 -58
  477. package/src/proactive-artifact/trigger-state.test.ts +0 -286
  478. package/src/proactive-artifact/trigger-state.ts +0 -123
  479. package/src/util/map-limit.ts +0 -27
  480. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  481. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  482. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  483. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  484. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  485. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  486. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  487. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  488. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  489. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  490. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/llm-retry.ts +0 -0
@@ -56,6 +56,11 @@ let runCalls: Array<{
56
56
  let runResults: CompactionRunResult[] = [];
57
57
  const estimateReturns: number[] = [];
58
58
 
59
+ // Captured arguments from each runEmergencyCompaction invocation, so the
60
+ // emergencyCompact tests can assert the manager fills in the fields it owns.
61
+ let emergencyCalls: Record<string, unknown>[] = [];
62
+ let emergencyResult: CompactionRunResult | undefined;
63
+
59
64
  mock.module("../context/token-estimator.js", () => ({
60
65
  estimatePromptTokens: (): number => {
61
66
  const next = estimateReturns.shift();
@@ -92,9 +97,18 @@ mock.module("../context/compactor.js", () => ({
92
97
  }
93
98
  return result;
94
99
  },
100
+ runEmergencyCompaction: async (
101
+ args: Record<string, unknown>,
102
+ ): Promise<CompactionRunResult> => {
103
+ emergencyCalls.push(args);
104
+ if (!emergencyResult) {
105
+ throw new Error("emergencyResult not seeded");
106
+ }
107
+ return emergencyResult;
108
+ },
95
109
  }));
96
110
 
97
- import { ContextWindowManager } from "../context/window-manager.js";
111
+ import { ContextWindowManager } from "../plugins/defaults/compaction/window-manager.js";
98
112
  import type { Message, Provider } from "../providers/types.js";
99
113
 
100
114
  function makeProvider(): Provider {
@@ -142,24 +156,28 @@ function compactResult(
142
156
  };
143
157
  }
144
158
 
159
+ function makeConfig(maxAttempts: number = 3) {
160
+ return {
161
+ enabled: true,
162
+ maxInputTokens: 200_000,
163
+ targetBudgetRatio: 0.3,
164
+ compactThreshold: 0.8,
165
+ summaryBudgetRatio: 0.05,
166
+ overflowRecovery: {
167
+ enabled: true,
168
+ safetyMarginRatio: 0.05,
169
+ maxAttempts,
170
+ interactiveLatestTurnCompression: "summarize" as const,
171
+ nonInteractiveLatestTurnCompression: "summarize" as const,
172
+ },
173
+ };
174
+ }
175
+
145
176
  function buildManager(maxAttempts: number = 3): ContextWindowManager {
146
177
  return new ContextWindowManager({
147
178
  provider: makeProvider(),
148
179
  systemPrompt: "you are a test assistant",
149
- config: {
150
- enabled: true,
151
- maxInputTokens: 200_000,
152
- targetBudgetRatio: 0.3,
153
- compactThreshold: 0.8,
154
- summaryBudgetRatio: 0.05,
155
- overflowRecovery: {
156
- enabled: true,
157
- safetyMarginRatio: 0.05,
158
- maxAttempts,
159
- interactiveLatestTurnCompression: "summarize",
160
- nonInteractiveLatestTurnCompression: "summarize",
161
- },
162
- },
180
+ config: makeConfig(maxAttempts),
163
181
  conversationId: "conv-test",
164
182
  });
165
183
  }
@@ -289,3 +307,91 @@ describe("ContextWindowManager.maybeCompact retry budget", () => {
289
307
  expect(result.estimatedInputTokens).toBe(165_000);
290
308
  });
291
309
  });
310
+
311
+ describe("ContextWindowManager.emergencyCompact", () => {
312
+ beforeEach(() => {
313
+ emergencyCalls = [];
314
+ emergencyResult = undefined;
315
+ estimateReturns.length = 0;
316
+ });
317
+
318
+ test("supplies manager-owned fields and forwards only overflow inputs", async () => {
319
+ /**
320
+ * The manager owns provider, system prompt, token budget, conversation
321
+ * id, compaction config, and non-persisted prefix count; the caller
322
+ * provides only the overflow-specific inputs.
323
+ */
324
+ // GIVEN a manager seeded with a non-persisted prefix and a canned result
325
+ emergencyResult = compactResult({
326
+ compacted: true,
327
+ compactedMessages: 40,
328
+ summaryText: "emergency summary",
329
+ });
330
+ const manager = buildManager();
331
+ manager.seedNonPersistedPrefix(3);
332
+ const messages = makeMessages(8);
333
+ const signal = new AbortController().signal;
334
+
335
+ // WHEN emergency compaction runs
336
+ const result = await manager.emergencyCompact(
337
+ messages,
338
+ { previousEstimatedInputTokens: 242_201, overrideProfile: "fast" },
339
+ signal,
340
+ );
341
+
342
+ // THEN the manager fills its owned fields and forwards the caller inputs
343
+ expect(emergencyCalls.length).toBe(1);
344
+ const args = emergencyCalls[0]!;
345
+ expect(args.conversationId).toBe("conv-test");
346
+ expect(args.systemPrompt).toBe("you are a test assistant");
347
+ expect(args.maxInputTokens).toBe(200_000);
348
+ expect(args.nonPersistedPrefixCount).toBe(3);
349
+ expect(args.tools).toBeUndefined();
350
+ expect(args.force).toBe(true);
351
+ expect(args.signal).toBe(signal);
352
+ expect(args.messages).toBe(messages);
353
+ expect(args.previousEstimatedInputTokens).toBe(242_201);
354
+ expect(args.overrideProfile).toBe("fast");
355
+ expect((args.provider as { name: string }).name).toBe("mock-provider");
356
+ expect(result.summaryText).toBe("emergency summary");
357
+ });
358
+
359
+ test("defaults overrideProfile to null when omitted", async () => {
360
+ /**
361
+ * Callers that don't resolve a per-conversation profile get an explicit
362
+ * null forwarded to the summary call.
363
+ */
364
+ // GIVEN a manager and a canned result
365
+ emergencyResult = compactResult({ compacted: true });
366
+ const manager = buildManager();
367
+
368
+ // WHEN emergency compaction runs without an override profile
369
+ await manager.emergencyCompact(makeMessages(6), {
370
+ previousEstimatedInputTokens: 210_000,
371
+ });
372
+
373
+ // THEN overrideProfile is forwarded as null
374
+ expect(emergencyCalls[0]!.overrideProfile).toBeNull();
375
+ });
376
+
377
+ test("throws when the manager has no conversation id", async () => {
378
+ /**
379
+ * Emergency compaction needs a conversation id for attachment and
380
+ * timestamp lookups; a manager without one cannot run it.
381
+ */
382
+ // GIVEN a manager constructed without a conversation id
383
+ const manager = new ContextWindowManager({
384
+ provider: makeProvider(),
385
+ systemPrompt: "you are a test assistant",
386
+ config: makeConfig(),
387
+ });
388
+
389
+ // WHEN/THEN emergency compaction rejects without invoking the compactor
390
+ await expect(
391
+ manager.emergencyCompact(makeMessages(4), {
392
+ previousEstimatedInputTokens: 210_000,
393
+ }),
394
+ ).rejects.toThrow(/conversationId/);
395
+ expect(emergencyCalls.length).toBe(0);
396
+ });
397
+ });
@@ -167,9 +167,10 @@ mock.module("../memory/retriever.js", () => ({
167
167
  injectMemoryRecallAsUserBlock: (msgs: Message[]) => msgs,
168
168
  }));
169
169
 
170
- mock.module("../context/window-manager.js", () => ({
170
+ mock.module("../plugins/defaults/compaction/window-manager.js", () => ({
171
171
  ContextWindowManager: class {
172
172
  constructor() {}
173
+ updateConfig() {}
173
174
  shouldCompact() {
174
175
  return { needed: false, estimatedTokens: 0 };
175
176
  }
@@ -198,10 +199,11 @@ mock.module("../agent/loop.js", () => ({
198
199
  getActiveModel() {
199
200
  return undefined;
200
201
  }
201
- async run(
202
- messages: Message[],
203
- onEvent: (event: AgentEvent) => void,
204
- ): Promise<AgentLoopRunResult> {
202
+ async run(options: {
203
+ messages: Message[];
204
+ onEvent: (event: AgentEvent) => void;
205
+ }): Promise<AgentLoopRunResult> {
206
+ const { messages, onEvent } = options;
205
207
  // Prime the assistant row anchor — production code emits this from
206
208
  // `AgentLoop.run` just before `provider.sendMessage`.
207
209
  await onEvent({ type: "llm_call_started" });
@@ -2,11 +2,11 @@ import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  import { CompactionCircuit } from "../agent/compaction-circuit.js";
4
4
  import type { AgentLoop } from "../agent/loop.js";
5
- import type { AgentLoopConversationContext } from "../daemon/conversation-agent-loop.js";
5
+ import type { Conversation } from "../daemon/conversation.js";
6
6
  import type { DiskPressureStatus } from "../daemon/disk-pressure-guard.js";
7
7
  import type { ServerMessage } from "../daemon/message-protocol.js";
8
8
 
9
- type Context = AgentLoopConversationContext;
9
+ type Context = Conversation;
10
10
 
11
11
  mock.module("../util/logger.js", () => ({
12
12
  getLogger: () =>
@@ -96,7 +96,7 @@ mock.module("../memory/conversation-crud.js", () => ({
96
96
  getMessageById: () => null,
97
97
  getConversationOriginChannel: () => null,
98
98
  getConversationOriginInterface: () => null,
99
- getConversationOverrideProfileFromRow: () => null,
99
+ resolveOverrideProfile: () => null,
100
100
  provenanceFromTrustContext: () => ({}),
101
101
  setConversationHistoryStrippedAt: () => {},
102
102
  updateConversationContextWindow: () => {},
@@ -106,9 +106,7 @@ mock.module("../memory/conversation-crud.js", () => ({
106
106
 
107
107
  import { runAgentLoopImpl } from "../daemon/conversation-agent-loop.js";
108
108
 
109
- function makeCtx(
110
- overrides: Partial<Context> = {},
111
- ): AgentLoopConversationContext {
109
+ function makeCtx(overrides: Partial<Context> = {}): Conversation {
112
110
  let processing = true;
113
111
  return {
114
112
  conversationId: "conv-123",
@@ -137,6 +135,8 @@ function makeCtx(
137
135
  } as unknown as Context["contextWindowManager"],
138
136
  contextCompactedMessageCount: 0,
139
137
  contextCompactedAt: null,
138
+ conversationType: "background",
139
+ source: "memory",
140
140
  memoryPolicy: { scopeId: "default", includeDefaultFallback: true },
141
141
  currentActiveSurfaceId: undefined,
142
142
  currentPage: undefined,
@@ -145,8 +145,6 @@ function makeCtx(
145
145
  surfaceActionRequestIds: new Set<string>(),
146
146
  currentTurnSurfaces: [],
147
147
  workingDir: "/tmp",
148
- workspaceTopLevelContext: null,
149
- workspaceTopLevelDirty: false,
150
148
  channelCapabilities: undefined,
151
149
  commandIntent: undefined,
152
150
  trustContext: undefined,
@@ -172,7 +170,6 @@ function makeCtx(
172
170
  hasNoClient: false,
173
171
  prompter: {} as Context["prompter"],
174
172
  queue: {} as Context["queue"],
175
- refreshWorkspaceTopLevelContextIfNeeded: () => {},
176
173
  markWorkspaceTopLevelDirty: () => {},
177
174
  emitActivityState: () => {},
178
175
  getQueueDepth: () => 0,
@@ -183,7 +180,7 @@ function makeCtx(
183
180
  getTurnChannelContext: () => null,
184
181
  graphMemory: {} as Context["graphMemory"],
185
182
  ...overrides,
186
- } as AgentLoopConversationContext;
183
+ } as unknown as Conversation;
187
184
  }
188
185
 
189
186
  describe("runAgentLoopImpl disk pressure gate", () => {
@@ -15,7 +15,7 @@ import { createRequire } from "node:module";
15
15
  import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
16
16
 
17
17
  import { CompactionCircuit } from "../agent/compaction-circuit.js";
18
- import type { AgentEvent, AgentLoopRunOptions } from "../agent/loop.js";
18
+ import type { AgentLoopRunOptions } from "../agent/loop.js";
19
19
  import type { LLMCallSite } from "../config/schemas/llm.js";
20
20
  import { resetPluginRegistryAndRegisterDefaults } from "../plugins/defaults/index.js";
21
21
  import type { Message, ToolDefinition } from "../providers/types.js";
@@ -102,23 +102,26 @@ mock.module("../context/token-estimator.js", () => ({
102
102
  estimateToolsTokens: () => 0,
103
103
  }));
104
104
 
105
- mock.module("../daemon/context-overflow-reducer.js", () => ({
106
- createInitialReducerState: () => ({
107
- appliedTiers: [],
108
- injectionMode: "full" as const,
109
- exhausted: false,
110
- }),
111
- reduceContextOverflow: async (msgs: Message[]) => ({
112
- messages: msgs,
113
- tier: "forced_compaction",
114
- state: {
115
- appliedTiers: ["forced_compaction"],
116
- injectionMode: "full",
117
- exhausted: true,
118
- },
119
- estimatedTokens: 1000,
105
+ mock.module(
106
+ "../plugins/defaults/compaction/context-overflow-reducer.js",
107
+ () => ({
108
+ createInitialReducerState: () => ({
109
+ appliedTiers: [],
110
+ injectionMode: "full" as const,
111
+ exhausted: false,
112
+ }),
113
+ reduceContextOverflow: async (msgs: Message[]) => ({
114
+ messages: msgs,
115
+ tier: "forced_compaction",
116
+ state: {
117
+ appliedTiers: ["forced_compaction"],
118
+ injectionMode: "full",
119
+ exhausted: true,
120
+ },
121
+ estimatedTokens: 1000,
122
+ }),
120
123
  }),
121
- }));
124
+ );
122
125
 
123
126
  mock.module("../daemon/context-overflow-policy.js", () => ({
124
127
  resolveOverflowAction: () => "fail_gracefully",
@@ -150,12 +153,26 @@ mock.module("../memory/conversation-crud.js", () => ({
150
153
  updateMessageMetadata: () => {},
151
154
  getMessages: () => [],
152
155
  getConversation: () => mockConversationRow,
153
- getConversationOverrideProfileFromRow: (
154
- row: { conversationType?: string; inferenceProfile?: string | null } | null,
156
+ resolveOverrideProfile: (
157
+ fields: {
158
+ conversationType?: string | null;
159
+ inferenceProfile?: string | null;
160
+ inferenceProfileExpiresAt?: number | null;
161
+ } | null,
155
162
  ) => {
156
- if (row?.conversationType === "background") return undefined;
157
- const profile = row?.inferenceProfile;
158
- return typeof profile === "string" ? profile : undefined;
163
+ if (
164
+ fields?.conversationType === "background" ||
165
+ fields?.conversationType === "scheduled"
166
+ ) {
167
+ return undefined;
168
+ }
169
+ if (
170
+ fields?.inferenceProfileExpiresAt != null &&
171
+ fields.inferenceProfileExpiresAt <= Date.now()
172
+ ) {
173
+ return undefined;
174
+ }
175
+ return fields?.inferenceProfile ?? undefined;
159
176
  },
160
177
  provenanceFromTrustContext: () => ({
161
178
  source: "user",
@@ -343,10 +360,8 @@ mock.module("../memory/llm-request-log-store.js", () => ({
343
360
 
344
361
  // ── Imports (after mocks) ────────────────────────────────────────────
345
362
 
346
- import {
347
- type AgentLoopConversationContext,
348
- runAgentLoopImpl,
349
- } from "../daemon/conversation-agent-loop.js";
363
+ import type { Conversation } from "../daemon/conversation.js";
364
+ import { runAgentLoopImpl } from "../daemon/conversation-agent-loop.js";
350
365
 
351
366
  // ── Test helpers ─────────────────────────────────────────────────────
352
367
 
@@ -362,22 +377,20 @@ let mutateBeforeResolveOverrideProfile: (() => void) | undefined;
362
377
 
363
378
  function makeCtx(
364
379
  captured: CapturedAgentLoopRun[],
365
- overrides?: Partial<AgentLoopConversationContext>,
366
- ): AgentLoopConversationContext {
380
+ overrides?: Partial<Conversation>,
381
+ ): Conversation {
367
382
  const agentLoopRun = async (
368
- messages: Message[],
369
- _onEvent: (event: AgentEvent) => void,
370
- options?: AgentLoopRunOptions,
383
+ options: AgentLoopRunOptions,
371
384
  ): Promise<Message[]> => {
372
385
  mutateBeforeResolveOverrideProfile?.();
373
386
  captured.push({
374
- callSite: options?.callSite,
375
- overrideProfile: options?.overrideProfile,
376
- resolvedOverrideProfile: options?.resolveOverrideProfile?.(),
377
- resolvedMaxInputTokens: options?.resolveContextWindow?.().maxInputTokens,
387
+ callSite: options.callSite,
388
+ overrideProfile: options.overrideProfile,
389
+ resolvedOverrideProfile: options.resolveOverrideProfile?.(),
390
+ resolvedMaxInputTokens: options.resolveContextWindow?.().maxInputTokens,
378
391
  });
379
392
  return [
380
- ...messages,
393
+ ...options.messages,
381
394
  {
382
395
  role: "assistant" as const,
383
396
  content: [{ type: "text" as const, text: "response" }],
@@ -406,7 +419,7 @@ function makeCtx(
406
419
  getResolvedTools: () => [] as ToolDefinition[],
407
420
  getActiveModel: () => undefined,
408
421
  compactionCircuit: new CompactionCircuit("test-conv"),
409
- } as unknown as AgentLoopConversationContext["agentLoop"],
422
+ } as unknown as Conversation["agentLoop"],
410
423
  provider: {
411
424
  name: "mock-provider",
412
425
  sendMessage: async () => ({
@@ -415,13 +428,14 @@ function makeCtx(
415
428
  usage: { inputTokens: 0, outputTokens: 0 },
416
429
  stopReason: "end_turn",
417
430
  }),
418
- } as unknown as AgentLoopConversationContext["provider"],
431
+ } as unknown as Conversation["provider"],
419
432
  systemPrompt: "system prompt",
420
433
 
421
434
  contextWindowManager: {
435
+ updateConfig: () => {},
422
436
  shouldCompact: () => ({ needed: false, estimatedTokens: 0 }),
423
437
  maybeCompact: async () => ({ compacted: false }),
424
- } as unknown as AgentLoopConversationContext["contextWindowManager"],
438
+ } as unknown as Conversation["contextWindowManager"],
425
439
  contextCompactedMessageCount: 0,
426
440
  contextCompactedAt: null,
427
441
 
@@ -435,8 +449,6 @@ function makeCtx(
435
449
  currentTurnSurfaces: [],
436
450
 
437
451
  workingDir: "/tmp",
438
- workspaceTopLevelContext: null,
439
- workspaceTopLevelDirty: false,
440
452
  channelCapabilities: undefined,
441
453
  commandIntent: undefined,
442
454
  trustContext: undefined,
@@ -446,15 +458,15 @@ function makeCtx(
446
458
  preactivatedSkillIds: undefined,
447
459
  skillProjectionState: new Map(),
448
460
  skillProjectionCache:
449
- new Map() as unknown as AgentLoopConversationContext["skillProjectionCache"],
461
+ new Map() as unknown as Conversation["skillProjectionCache"],
450
462
 
451
463
  traceEmitter: {
452
464
  emit: () => {},
453
- } as unknown as AgentLoopConversationContext["traceEmitter"],
465
+ } as unknown as Conversation["traceEmitter"],
454
466
  profiler: {
455
467
  startRequest: () => {},
456
468
  emitSummary: () => {},
457
- } as unknown as AgentLoopConversationContext["profiler"],
469
+ } as unknown as Conversation["profiler"],
458
470
  usageStats: {
459
471
  totalInputTokens: 0,
460
472
  totalOutputTokens: 0,
@@ -467,13 +479,12 @@ function makeCtx(
467
479
  lastAttachmentWarnings: [],
468
480
 
469
481
  hasNoClient: false,
470
- prompter: {} as unknown as AgentLoopConversationContext["prompter"],
471
- queue: {} as unknown as AgentLoopConversationContext["queue"],
482
+ prompter: {} as unknown as Conversation["prompter"],
483
+ queue: {} as unknown as Conversation["queue"],
472
484
 
473
485
  getWorkspaceGitService: () => ({ ensureInitialized: async () => {} }),
474
486
  commitTurnChanges: async () => {},
475
487
 
476
- refreshWorkspaceTopLevelContextIfNeeded: () => {},
477
488
  markWorkspaceTopLevelDirty: () => {},
478
489
  emitActivityState: () => {},
479
490
  getQueueDepth: () => 0,
@@ -500,10 +511,10 @@ function makeCtx(
500
511
  }),
501
512
  retrackCachedNodes: () => {},
502
513
  recordPkbQueryVectors: () => {},
503
- } as unknown as AgentLoopConversationContext["graphMemory"],
514
+ } as unknown as Conversation["graphMemory"],
504
515
 
505
516
  ...overrides,
506
- } as AgentLoopConversationContext;
517
+ } as unknown as Conversation;
507
518
  }
508
519
 
509
520
  // ── Tests ────────────────────────────────────────────────────────────
@@ -541,20 +552,11 @@ afterAll(() => {
541
552
 
542
553
  describe("runAgentLoopImpl — per-conversation inferenceProfile", () => {
543
554
  test("non-background conversation with inferenceProfile threads it through as overrideProfile", async () => {
544
- mockConversationRow = {
545
- id: "conv-1",
555
+ const captured: CapturedAgentLoopRun[] = [];
556
+ const ctx = makeCtx(captured, {
546
557
  conversationType: "standard",
547
558
  inferenceProfile: "quality-optimized",
548
- contextSummary: null,
549
- contextCompactedMessageCount: 0,
550
- totalInputTokens: 0,
551
- totalOutputTokens: 0,
552
- totalEstimatedCost: 0,
553
- title: null,
554
- };
555
-
556
- const captured: CapturedAgentLoopRun[] = [];
557
- const ctx = makeCtx(captured);
559
+ });
558
560
 
559
561
  await runAgentLoopImpl(ctx, "hello", "msg-1", () => {});
560
562
 
@@ -564,21 +566,12 @@ describe("runAgentLoopImpl — per-conversation inferenceProfile", () => {
564
566
  }
565
567
  });
566
568
 
567
- test("background conversation ignores inferenceProfile column", async () => {
568
- mockConversationRow = {
569
- id: "conv-1",
569
+ test("background conversation ignores inferenceProfile", async () => {
570
+ const captured: CapturedAgentLoopRun[] = [];
571
+ const ctx = makeCtx(captured, {
570
572
  conversationType: "background",
571
573
  inferenceProfile: "quality-optimized",
572
- contextSummary: null,
573
- contextCompactedMessageCount: 0,
574
- totalInputTokens: 0,
575
- totalOutputTokens: 0,
576
- totalEstimatedCost: 0,
577
- title: null,
578
- };
579
-
580
- const captured: CapturedAgentLoopRun[] = [];
581
- const ctx = makeCtx(captured);
574
+ });
582
575
 
583
576
  await runAgentLoopImpl(ctx, "hello", "msg-1", () => {});
584
577
 
@@ -588,22 +581,9 @@ describe("runAgentLoopImpl — per-conversation inferenceProfile", () => {
588
581
  }
589
582
  });
590
583
 
591
- test("absence of inferenceProfile column behaves identically to today (no override)", async () => {
592
- // `mockConversationRow` already defaults to inferenceProfile: null.
593
- // Also explicitly cover the case where the column is missing entirely.
594
- mockConversationRow = {
595
- id: "conv-1",
596
- conversationType: "standard",
597
- contextSummary: null,
598
- contextCompactedMessageCount: 0,
599
- totalInputTokens: 0,
600
- totalOutputTokens: 0,
601
- totalEstimatedCost: 0,
602
- title: null,
603
- };
604
-
584
+ test("absence of inferenceProfile behaves identically to today (no override)", async () => {
605
585
  const captured: CapturedAgentLoopRun[] = [];
606
- const ctx = makeCtx(captured);
586
+ const ctx = makeCtx(captured, { conversationType: "standard" });
607
587
 
608
588
  await runAgentLoopImpl(ctx, "hello", "msg-1", () => {});
609
589
 
@@ -613,26 +593,17 @@ describe("runAgentLoopImpl — per-conversation inferenceProfile", () => {
613
593
  }
614
594
  });
615
595
 
616
- test("explicit options.overrideProfile takes precedence over the column read", async () => {
596
+ test("explicit options.overrideProfile takes precedence over the conversation override", async () => {
617
597
  // Subagent path: SubagentManager forwards the parent's pinned profile
618
598
  // into the spawned (background) conversation's runAgentLoop call via
619
599
  // `options.overrideProfile`. The agent loop must respect that even
620
- // though the subagent's own conversation row is `background` (which
600
+ // though the subagent's own conversation is `background` (which
621
601
  // would otherwise zero out the override per the rule above).
622
- mockConversationRow = {
623
- id: "conv-1",
602
+ const captured: CapturedAgentLoopRun[] = [];
603
+ const ctx = makeCtx(captured, {
624
604
  conversationType: "background",
625
605
  inferenceProfile: null,
626
- contextSummary: null,
627
- contextCompactedMessageCount: 0,
628
- totalInputTokens: 0,
629
- totalOutputTokens: 0,
630
- totalEstimatedCost: 0,
631
- title: null,
632
- };
633
-
634
- const captured: CapturedAgentLoopRun[] = [];
635
- const ctx = makeCtx(captured);
606
+ });
636
607
 
637
608
  await runAgentLoopImpl(ctx, "hello", "msg-1", () => {}, {
638
609
  overrideProfile: "fast",
@@ -645,27 +616,15 @@ describe("runAgentLoopImpl — per-conversation inferenceProfile", () => {
645
616
  });
646
617
 
647
618
  test("re-resolves inferenceProfile when a tool changes it mid-turn", async () => {
648
- mockConversationRow = {
649
- id: "conv-1",
619
+ const captured: CapturedAgentLoopRun[] = [];
620
+ const ctx = makeCtx(captured, {
650
621
  conversationType: "standard",
651
622
  inferenceProfile: null,
652
- contextSummary: null,
653
- contextCompactedMessageCount: 0,
654
- totalInputTokens: 0,
655
- totalOutputTokens: 0,
656
- totalEstimatedCost: 0,
657
- title: null,
658
- };
623
+ });
659
624
  mutateBeforeResolveOverrideProfile = () => {
660
- mockConversationRow = {
661
- ...mockConversationRow!,
662
- inferenceProfile: "quality-optimized",
663
- };
625
+ ctx.inferenceProfile = "quality-optimized";
664
626
  };
665
627
 
666
- const captured: CapturedAgentLoopRun[] = [];
667
- const ctx = makeCtx(captured);
668
-
669
628
  await runAgentLoopImpl(ctx, "hello", "msg-1", () => {});
670
629
 
671
630
  expect(captured.length).toBeGreaterThan(0);