@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
@@ -150,11 +150,25 @@ const STREAMING_ERROR_PATTERNS = [
150
150
  ];
151
151
 
152
152
  // User-initiated cancellation patterns — these should NOT produce conversation_error
153
- // Image-input validation patterns — Anthropic 400s with this message when an image
154
- // block exceeds the per-side pixel cap. Distinct classification matters because
155
- // retrying with the same oversized image is futile; the user needs to resize.
153
+ // Image-input validation patterns — Anthropic 400s with one of these messages
154
+ // when an image block violates a hard limit. The first matches the per-side
155
+ // pixel cap ("image dimensions exceed max allowed size"); the second matches the
156
+ // base64 payload cap ("image exceeds 5 MB maximum: 7465044 bytes > 5242880
157
+ // bytes"). Distinct classification matters because retrying with the same
158
+ // oversized image is futile — the recovery path must strip or downscale it.
156
159
  const IMAGE_DIMENSIONS_TOO_LARGE_PATTERNS = [
157
160
  /image dimensions? exceeds? max allowed size/i,
161
+ /image exceeds \d+\s*MB maximum/i,
162
+ ];
163
+
164
+ const VISION_NOT_SUPPORTED_PATTERNS = [
165
+ /no endpoints found that support image input/i,
166
+ /does not support image/i,
167
+ /doesn't support image input/i,
168
+ /image input is not supported/i,
169
+ /this model does not support vision/i,
170
+ /vision is not supported/i,
171
+ /multi-?modal.*not.*support/i,
158
172
  ];
159
173
 
160
174
  const CANCEL_PATTERNS = [/abort/i, /cancel/i];
@@ -447,11 +461,20 @@ function classifyCore(
447
461
  return {
448
462
  code: "IMAGE_TOO_LARGE",
449
463
  userMessage:
450
- "An attached image is too large for the AI provider — image dimensions must be under 8000 pixels per side. Resize the image and try again.",
464
+ "An image in this conversation was too large for the AI provider and was automatically reduced. Send your message again to continue.",
451
465
  retryable: false,
452
466
  errorCategory: "image_dimensions_too_large",
453
467
  };
454
468
  }
469
+ if (isVisionNotSupported(message)) {
470
+ return {
471
+ code: "PROVIDER_API",
472
+ userMessage:
473
+ "This model doesn't support image input. Remove the image or switch to a vision-capable model.",
474
+ retryable: false,
475
+ errorCategory: "vision_not_supported",
476
+ };
477
+ }
455
478
  // Extract the provider detail after "API error (NNN): " prefix
456
479
  const detailMatch = message.match(/API error \(\d+\):\s*(.+)/i);
457
480
  const detail = detailMatch?.[1];
@@ -481,6 +504,10 @@ function isImageDimensionsTooLarge(message: string): boolean {
481
504
  return IMAGE_DIMENSIONS_TOO_LARGE_PATTERNS.some((p) => p.test(message));
482
505
  }
483
506
 
507
+ function isVisionNotSupported(message: string): boolean {
508
+ return VISION_NOT_SUPPORTED_PATTERNS.some((p) => p.test(message));
509
+ }
510
+
484
511
  /** Check whether an error message indicates a web-search-specific ordering failure. */
485
512
  function isWebSearchOrderingError(message: string): boolean {
486
513
  return WEB_SEARCH_ORDERING_PATTERNS.some((p) => p.test(message));
@@ -1,6 +1,5 @@
1
1
  import { v4 as uuid } from "uuid";
2
2
 
3
- import { getSummaryFromContextMessage } from "../context/window-manager.js";
4
3
  import {
5
4
  deleteLastExchange,
6
5
  deleteMessageById,
@@ -13,6 +12,7 @@ import { enqueueMemoryJob } from "../memory/jobs-store.js";
13
12
  import { relinkLlmRequestLogs } from "../memory/llm-request-log-store.js";
14
13
  import { withQdrantBreaker } from "../memory/qdrant-circuit-breaker.js";
15
14
  import { getQdrantClient } from "../memory/qdrant-client.js";
15
+ import { getSummaryFromContextMessage } from "../plugins/defaults/compaction/window-manager.js";
16
16
  import type { ContentBlock, Message } from "../providers/types.js";
17
17
  import { getLogger } from "../util/logger.js";
18
18
  import { truncate } from "../util/truncate.js";
@@ -1,23 +1,20 @@
1
1
  /**
2
- * Conversation lifecycle methods extracted from Conversation: loadFromDb, abort,
3
- * and dispose. Each operates on a context interface so the Conversation class
2
+ * Conversation lifecycle helpers extracted from Conversation: abort and
3
+ * dispose. Each operates on a context interface so the Conversation class
4
4
  * can delegate without exposing its full surface.
5
5
  */
6
6
 
7
7
  import { getConfig } from "../config/loader.js";
8
- import { createContextSummaryMessage } from "../context/window-manager.js";
9
8
  import type { EventBus } from "../events/bus.js";
10
9
  import type { AssistantDomainEvents } from "../events/domain-events.js";
11
10
  import type { ToolProfiler } from "../events/tool-profiling-listener.js";
12
11
  import { enqueueAutoAnalysisIfEnabled } from "../memory/auto-analysis-enqueue.js";
13
12
  import { isAutoAnalysisConversation } from "../memory/auto-analysis-guard.js";
14
- import { getConversation, getMessages } from "../memory/conversation-crud.js";
15
13
  import { enqueueMemoryJob, isMemoryEnabled } from "../memory/jobs-store.js";
16
14
  import { enqueueMemoryRetrospectiveIfEnabled } from "../memory/memory-retrospective-enqueue.js";
17
- import { shouldExposePersonalMemory } from "../memory/v2/static-context.js";
18
15
  import type { PermissionPrompter } from "../permissions/prompter.js";
19
16
  import type { SecretPrompter } from "../permissions/secret-prompter.js";
20
- import { repairHistory } from "../plugins/defaults/history-repair/terminal.js";
17
+ import { disposeContextWindowManager } from "../plugins/defaults/compaction/manager-store.js";
21
18
  import type { ContentBlock, Message } from "../providers/types.js";
22
19
  import {
23
20
  isUntrustedTrustClass,
@@ -28,15 +25,8 @@ import { type AbortReason, createAbortReason } from "../util/abort-reasons.js";
28
25
  import { getLogger } from "../util/logger.js";
29
26
  import { unregisterCallNotifiers } from "./conversation-notifiers.js";
30
27
  import type { MessageQueue } from "./conversation-queue-manager.js";
31
- import { stripInjectionsForCompaction } from "./conversation-runtime-assembly.js";
32
28
  import { resetSkillToolProjection } from "./conversation-skill-tools.js";
33
- import type {
34
- SurfaceData,
35
- SurfaceType,
36
- UsageStats,
37
- } from "./message-protocol.js";
38
- import { filterMessagesForUntrustedActor } from "./message-provenance.js";
39
- import { resolveTrustClass, type TrustContext } from "./trust-context.js";
29
+ import type { SurfaceData, SurfaceType } from "./message-protocol.js";
40
30
 
41
31
  const log = getLogger("conversation-lifecycle");
42
32
 
@@ -75,17 +65,6 @@ export function reinjectImageSourcePaths(
75
65
 
76
66
  // ── Context Interfaces ───────────────────────────────────────────────
77
67
 
78
- export interface LoadFromDbContext {
79
- readonly conversationId: string;
80
- messages: Message[];
81
- usageStats: UsageStats;
82
- contextCompactedMessageCount: number;
83
- contextCompactedAt: number | null;
84
- trustContext?: TrustContext;
85
- loadedHistoryTrustClass?: TrustClass;
86
- loadedHistoryPersonalMemoryAllowed?: boolean;
87
- }
88
-
89
68
  export interface AbortContext {
90
69
  readonly conversationId: string;
91
70
  isProcessing(): boolean;
@@ -127,236 +106,6 @@ export interface DisposeContext extends AbortContext {
127
106
  abort(): void;
128
107
  }
129
108
 
130
- // ── loadFromDb ───────────────────────────────────────────────────────
131
-
132
- export async function loadFromDb(ctx: LoadFromDbContext): Promise<void> {
133
- const trustClass = ctx.trustContext?.trustClass;
134
- const allDbMessages = getMessages(ctx.conversationId);
135
- const dbMessages = isUntrustedTrustClass(trustClass)
136
- ? filterMessagesForUntrustedActor(allDbMessages)
137
- : allDbMessages;
138
-
139
- const conv = getConversation(ctx.conversationId);
140
- const contextSummary = !isUntrustedTrustClass(trustClass)
141
- ? conv?.contextSummary?.trim() || null
142
- : null;
143
- if (isUntrustedTrustClass(trustClass)) {
144
- // Compacted summaries may include trusted/guardian-only details, so we
145
- // disable summary-based context for untrusted actor views.
146
- ctx.contextCompactedMessageCount = 0;
147
- ctx.contextCompactedAt = null;
148
- } else {
149
- ctx.contextCompactedMessageCount = Math.max(
150
- 0,
151
- Math.min(conv?.contextCompactedMessageCount ?? 0, dbMessages.length),
152
- );
153
- ctx.contextCompactedAt = conv?.contextCompactedAt ?? null;
154
- }
155
-
156
- // Every injection-strip event (`/clean` or compaction) updates
157
- // `historyStrippedAt`. Messages older than this should skip metadata
158
- // rehydration and have any injection prefixes still embedded in their
159
- // content stripped, so the post-strip view survives reload and forks.
160
- const historyStrippedAt = conv?.historyStrippedAt ?? null;
161
- const slicedDbMessages = dbMessages.slice(ctx.contextCompactedMessageCount);
162
- let preStrippedCount = 0;
163
- if (historyStrippedAt != null) {
164
- const boundary = slicedDbMessages.findIndex(
165
- (m) => m.createdAt >= historyStrippedAt,
166
- );
167
- preStrippedCount = boundary === -1 ? slicedDbMessages.length : boundary;
168
- }
169
-
170
- // Mirror the injection-time gate (`shouldExposePersonalMemory` in
171
- // `conversation-agent-loop.ts`) so background/local conversations
172
- // (sourceChannel `undefined` or `"vellum"`) can rehydrate the persisted
173
- // v2 static memory block. Use `resolveTrustClass` for parity with the
174
- // agent loop — it folds in the HTTP-auth-disabled dev bypass so
175
- // rehydration and injection agree on the effective trust class.
176
- const personalMemoryAllowed = shouldExposePersonalMemory({
177
- sourceChannel: ctx.trustContext?.sourceChannel,
178
- isTrustedActor: resolveTrustClass(ctx.trustContext) === "guardian",
179
- });
180
- const parsedMessages: Message[] = slicedDbMessages.map((m, index, arr) => {
181
- const isPreStripped = index < preStrippedCount;
182
- const role = m.role as "user" | "assistant";
183
- let content: ContentBlock[];
184
- try {
185
- const parsed = JSON.parse(m.content);
186
- content = Array.isArray(parsed)
187
- ? parsed
188
- : [{ type: "text", text: m.content }];
189
- } catch {
190
- log.warn(
191
- { conversationId: ctx.conversationId, messageId: m.id },
192
- "Invalid JSON in persisted message content, replacing with safe text block",
193
- );
194
- content = [{ type: "text", text: m.content }];
195
- }
196
-
197
- content = reinjectImageSourcePaths(content, role, m.metadata);
198
-
199
- // Re-inject persisted injection blocks from metadata so it survives
200
- // conversation reloads (eviction, restart, fork).
201
- if (role === "user" && m.metadata && !isPreStripped) {
202
- try {
203
- const meta = JSON.parse(m.metadata);
204
- const isTail = index === arr.length - 1;
205
-
206
- // Rehydrate in reverse injection order (innermost block first)
207
- // so the resulting layout matches `applyRuntimeInjections`'s
208
- // after-memory-prefix splices in ascending injector order
209
- // (pkb-context 30, pkb-reminder 35, memory-v2-static 38,
210
- // now-md 40 — the v2 static block lands inside the memory
211
- // prefix, so now-md splices *after* it):
212
- // [<workspace>, <turn_context>, <memory>dynamic</memory>,
213
- // <info>v2static</info>, <NOW.md>, <system_reminder>,
214
- // <knowledge_base>, ...original]
215
- // The v2 static block is replayed verbatim from stored metadata,
216
- // so rows may carry either `<info>…</info>` or `<memory>…</memory>`
217
- // depending on when they were persisted.
218
- // Required so Anthropic's prefix cache keeps matching msg[0]
219
- // across daemon restart and conversation eviction. The tail
220
- // row only rehydrates `memoryInjectedBlock` — the next turn
221
- // re-injects the rest fresh.
222
- if (!isTail && typeof meta.pkbContextBlock === "string") {
223
- content = [
224
- { type: "text" as const, text: meta.pkbContextBlock },
225
- ...content,
226
- ];
227
- }
228
-
229
- if (!isTail && typeof meta.pkbSystemReminderBlock === "string") {
230
- content = [
231
- { type: "text" as const, text: meta.pkbSystemReminderBlock },
232
- ...content,
233
- ];
234
- }
235
-
236
- if (!isTail && typeof meta.nowScratchpadBlock === "string") {
237
- content = [
238
- { type: "text" as const, text: meta.nowScratchpadBlock },
239
- ...content,
240
- ];
241
- }
242
-
243
- // The v2 static memory block (essentials/threads/recent/buffer
244
- // wrapped in either `<info>…</info>` or `<memory>…</memory>`)
245
- // carries personal user memory. Trust-gated to mirror
246
- // `shouldExposePersonalMemory` at injection time — untrusted-actor
247
- // views must not read persisted personal memory back through
248
- // metadata. Skipped on the tail row because the next turn
249
- // re-injects fresh content on full-mode turns.
250
- if (
251
- !isTail &&
252
- personalMemoryAllowed &&
253
- typeof meta.memoryV2StaticBlock === "string"
254
- ) {
255
- content = [
256
- { type: "text" as const, text: meta.memoryV2StaticBlock },
257
- ...content,
258
- ];
259
- }
260
-
261
- // Memory remains rehydrated on all rows (existing behavior).
262
- // Strip any pre-existing wrapper before re-wrapping so historical
263
- // rows persisted with the wrapper (v2 path before the
264
- // injectedBlockText contract was unified with v1's unwrapped form)
265
- // don't render double-wrapped after rehydrate. Only unwrap when
266
- // the full <memory>...</memory> pair is present so we don't mutate
267
- // legitimate unwrapped payloads that happen to start with
268
- // "<memory>\n" or end with "\n</memory>".
269
- if (typeof meta.memoryInjectedBlock === "string") {
270
- const block = meta.memoryInjectedBlock;
271
- const inner =
272
- block.startsWith("<memory>\n") && block.endsWith("\n</memory>")
273
- ? block.slice("<memory>\n".length, -"\n</memory>".length)
274
- : block;
275
- content = [
276
- {
277
- type: "text" as const,
278
- text: `<memory>\n${inner}\n</memory>`,
279
- },
280
- ...content,
281
- ];
282
- }
283
-
284
- if (!isTail && typeof meta.turnContextBlock === "string") {
285
- content = [
286
- { type: "text" as const, text: meta.turnContextBlock },
287
- ...content,
288
- ];
289
- }
290
-
291
- if (!isTail && typeof meta.workspaceBlock === "string") {
292
- content = [
293
- { type: "text" as const, text: meta.workspaceBlock },
294
- ...content,
295
- ];
296
- }
297
- } catch {
298
- /* ignore parse errors — metadata may be malformed */
299
- }
300
- }
301
-
302
- return { role, content };
303
- });
304
-
305
- // Strip pre-clean messages only; post-clean messages keep the fresh
306
- // injections they were generated with.
307
- const messagesBeforeRepair =
308
- preStrippedCount === 0
309
- ? parsedMessages
310
- : [
311
- ...stripInjectionsForCompaction(
312
- parsedMessages.slice(0, preStrippedCount),
313
- ),
314
- ...parsedMessages.slice(preStrippedCount),
315
- ];
316
-
317
- // Normalize the canonical persisted history once at load. Every consumer
318
- // of `ctx.messages` outside the agent loop (history edit/undo, PKB context
319
- // tracking, surfaces) reads this list directly, so it must satisfy the
320
- // provider pairing/alternation rules before any of them run. The agent
321
- // loop's pre-run repair only repairs the transient per-turn message list it
322
- // sends to the provider and never writes back here, so this pass is not
323
- // redundant with it.
324
- const { messages: repairedMessages, stats } =
325
- repairHistory(messagesBeforeRepair);
326
- if (
327
- stats.assistantToolResultsMigrated > 0 ||
328
- stats.missingToolResultsInserted > 0 ||
329
- stats.orphanToolResultsDowngraded > 0 ||
330
- stats.consecutiveSameRoleMerged > 0
331
- ) {
332
- log.warn(
333
- { conversationId: ctx.conversationId, phase: "load", ...stats },
334
- "Repaired persisted history",
335
- );
336
- }
337
- ctx.messages = repairedMessages;
338
-
339
- if (contextSummary) {
340
- ctx.messages.unshift(createContextSummaryMessage(contextSummary));
341
- }
342
-
343
- if (conv) {
344
- ctx.usageStats = {
345
- inputTokens: conv.totalInputTokens,
346
- outputTokens: conv.totalOutputTokens,
347
- estimatedCost: conv.totalEstimatedCost,
348
- };
349
- }
350
-
351
- ctx.loadedHistoryTrustClass = trustClass;
352
- ctx.loadedHistoryPersonalMemoryAllowed = personalMemoryAllowed;
353
-
354
- log.info(
355
- { conversationId: ctx.conversationId, count: ctx.messages.length },
356
- "Loaded messages from DB",
357
- );
358
- }
359
-
360
109
  // ── abort ─────────────────────────────────────────────────────────────
361
110
 
362
111
  export function abortConversation(
@@ -493,4 +242,11 @@ export function disposeConversation(ctx: DisposeContext): void {
493
242
  ctx.accumulatedSurfaceState.clear();
494
243
  ctx.lastSurfaceAction.clear();
495
244
  ctx.workspaceTopLevelContext = null;
245
+ // The compaction module owns the per-conversation ContextWindowManager, so
246
+ // teardown releases it directly. Moving this behind a compaction-plugin hook
247
+ // would let the module own disposal end-to-end, but the per-turn `stop` hook
248
+ // would first require relocating the manager's only
249
+ // cross-turn state — `nonPersistedPrefixCount` — off the manager so a
250
+ // per-turn dispose/rebuild stays correct.
251
+ disposeContextWindowManager(ctx.conversationId);
496
252
  }
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import { estimateContentBlockTokens } from "../context/token-estimator.js";
10
- import { getSummaryFromContextMessage } from "../context/window-manager.js";
10
+ import { getSummaryFromContextMessage } from "../plugins/defaults/compaction/window-manager.js";
11
11
  import type { ContentBlock, Message } from "../providers/types.js";
12
12
 
13
13
  export interface StripMediaOptions {
@@ -173,15 +173,28 @@ export function estimateUnconditionalStubTokens(
173
173
  const msg = messages[msgIndex];
174
174
  for (const block of msg.content) {
175
175
  if (block.type === "image" && msgIndex !== latestUserIndex) {
176
- stubTokens += estimateContentBlockTokens(imageBlockToStub(block), options);
176
+ stubTokens += estimateContentBlockTokens(
177
+ imageBlockToStub(block),
178
+ options,
179
+ );
177
180
  } else if (block.type === "file" && msgIndex !== latestUserIndex) {
178
- stubTokens += estimateContentBlockTokens(fileBlockToStub(block), options);
179
- } else if (block.type === "tool_result" && block.contentBlocks) { // guard:allow-tool-result-only — web_search_tool_result has no contentBlocks
181
+ stubTokens += estimateContentBlockTokens(
182
+ fileBlockToStub(block),
183
+ options,
184
+ );
185
+ } else if (block.type === "tool_result" && block.contentBlocks) {
186
+ // guard:allow-tool-result-only — web_search_tool_result has no contentBlocks
180
187
  for (const cb of block.contentBlocks) {
181
188
  if (cb.type === "image") {
182
- stubTokens += estimateContentBlockTokens(imageBlockToStub(cb), options);
189
+ stubTokens += estimateContentBlockTokens(
190
+ imageBlockToStub(cb),
191
+ options,
192
+ );
183
193
  } else if (cb.type === "file") {
184
- stubTokens += estimateContentBlockTokens(fileBlockToStub(cb), options);
194
+ stubTokens += estimateContentBlockTokens(
195
+ fileBlockToStub(cb),
196
+ options,
197
+ );
185
198
  }
186
199
  }
187
200
  }
@@ -43,6 +43,7 @@ import {
43
43
  } from "../messaging/providers/slack/message-metadata.js";
44
44
  import type { SecretPrompter } from "../permissions/secret-prompter.js";
45
45
  import type { Message } from "../providers/types.js";
46
+ import type { AuthContext } from "../runtime/auth/types.js";
46
47
  import { getLogger } from "../util/logger.js";
47
48
  import type { MessageQueue } from "./conversation-queue-manager.js";
48
49
  import type { SlackInboundMessageMetadata } from "./handlers/shared.js";
@@ -193,6 +194,9 @@ export interface MessagingConversationContext {
193
194
  currentRequestId?: string;
194
195
  readonly queue: MessageQueue;
195
196
  trustContext?: TrustContext;
197
+ authContext?: AuthContext;
198
+ currentTurnAuthContext?: AuthContext;
199
+ currentTurnSourceActorPrincipalId?: string;
196
200
  getTurnChannelContext(): TurnChannelContext | null;
197
201
  getTurnInterfaceContext(): TurnInterfaceContext | null;
198
202
  }
@@ -302,6 +306,10 @@ export interface EnqueueMessageOptions {
302
306
  displayContent?: string;
303
307
  transport?: ConversationTransportMetadata;
304
308
  clientMessageId?: string;
309
+ /** JWT-verified requester principal captured for queued host-proxy routing. */
310
+ sourceActorPrincipalId?: string;
311
+ /** Auth context snapshot captured for queued turn-scoped authorization. */
312
+ authContext?: AuthContext;
305
313
  }
306
314
 
307
315
  // ── enqueueMessage ───────────────────────────────────────────────────
@@ -322,7 +330,14 @@ export function enqueueMessage(
322
330
  displayContent,
323
331
  transport,
324
332
  clientMessageId,
333
+ authContext,
325
334
  } = options;
335
+ const queuedAuthContext =
336
+ authContext ?? ctx.currentTurnAuthContext ?? ctx.authContext;
337
+ const sourceActorPrincipalId =
338
+ options.sourceActorPrincipalId ??
339
+ ctx.currentTurnSourceActorPrincipalId ??
340
+ queuedAuthContext?.actorPrincipalId;
326
341
 
327
342
  if (!ctx.isProcessing()) {
328
343
  return { queued: false, requestId };
@@ -347,6 +362,8 @@ export function enqueueMessage(
347
362
  turnChannelContext,
348
363
  turnInterfaceContext,
349
364
  isInteractive,
365
+ sourceActorPrincipalId,
366
+ authContext: queuedAuthContext,
350
367
  transport,
351
368
  displayContent,
352
369
  sentAt: Date.now(),