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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (475) hide show
  1. package/ARCHITECTURE.md +6 -6
  2. package/bun.lock +2 -2
  3. package/docs/activation-funnel-telemetry.md +310 -0
  4. package/examples/plugins/echo/README.md +61 -60
  5. package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
  6. package/examples/plugins/echo/hooks/stop.ts +16 -0
  7. package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
  8. package/examples/plugins/echo/package.json +1 -2
  9. package/examples/plugins/echo/src/emit.ts +19 -0
  10. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
  11. package/openapi.yaml +263 -121
  12. package/package.json +2 -2
  13. package/src/__tests__/activation-early-marking.test.ts +120 -0
  14. package/src/__tests__/agent-loop-callsite-precedence.test.ts +69 -14
  15. package/src/__tests__/agent-loop-exit-reason.test.ts +204 -144
  16. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +50 -35
  17. package/src/__tests__/agent-loop-output-hooks.test.ts +357 -0
  18. package/src/__tests__/agent-loop-override-profile.test.ts +25 -6
  19. package/src/__tests__/agent-loop-provider-error-recording.test.ts +41 -21
  20. package/src/__tests__/agent-loop-thinking.test.ts +36 -20
  21. package/src/__tests__/agent-loop.test.ts +441 -96
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +14 -14
  23. package/src/__tests__/agent-wake-override-profile.test.ts +17 -21
  24. package/src/__tests__/anthropic-provider.test.ts +23 -8
  25. package/src/__tests__/app-builder-tool-scripts.test.ts +21 -0
  26. package/src/__tests__/app-control-flow.test.ts +1 -1
  27. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  28. package/src/__tests__/app-executors.test.ts +132 -0
  29. package/src/__tests__/approval-cascade.test.ts +6 -5
  30. package/src/__tests__/approval-routes-http.test.ts +4 -1
  31. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  32. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  33. package/src/__tests__/channel-approvals.test.ts +1 -1
  34. package/src/__tests__/compaction-circuit.test.ts +258 -0
  35. package/src/__tests__/compaction-direct.test.ts +146 -0
  36. package/src/__tests__/compaction-events.test.ts +7 -7
  37. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  38. package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
  39. package/src/__tests__/context-overflow-reducer.test.ts +265 -125
  40. package/src/__tests__/context-window-manager-compact-retry.test.ts +121 -15
  41. package/src/__tests__/conversation-abort-tool-results.test.ts +7 -5
  42. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +7 -10
  43. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +78 -119
  44. package/src/__tests__/conversation-agent-loop-overflow.test.ts +158 -234
  45. package/src/__tests__/conversation-agent-loop.test.ts +342 -623
  46. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  47. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -5
  48. package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
  49. package/src/__tests__/conversation-error.test.ts +15 -1
  50. package/src/__tests__/conversation-history-web-search.test.ts +6 -1
  51. package/src/__tests__/conversation-media-retry.test.ts +1 -1
  52. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +44 -4
  53. package/src/__tests__/conversation-process-callsite.test.ts +15 -15
  54. package/src/__tests__/conversation-provider-retry-repair.test.ts +66 -65
  55. package/src/__tests__/conversation-queue.test.ts +10 -10
  56. package/src/__tests__/conversation-runtime-assembly.test.ts +1059 -231
  57. package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
  58. package/src/__tests__/conversation-slash-queue.test.ts +7 -5
  59. package/src/__tests__/conversation-slash-unknown.test.ts +7 -5
  60. package/src/__tests__/conversation-speed-override.test.ts +11 -10
  61. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  62. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +395 -0
  63. package/src/__tests__/conversation-surfaces-app-control.test.ts +48 -1
  64. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +73 -4
  65. package/src/__tests__/conversation-undo.test.ts +2 -2
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +24 -21
  67. package/src/__tests__/conversation-workspace-injection.test.ts +69 -7
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +15 -12
  69. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  70. package/src/__tests__/corrected-target.test.ts +93 -0
  71. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  72. package/src/__tests__/cu-unified-flow.test.ts +36 -0
  73. package/src/__tests__/db-acp-history.test.ts +101 -0
  74. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  75. package/src/__tests__/empty-response-hook.test.ts +1 -1
  76. package/src/__tests__/file-write-tool.test.ts +63 -0
  77. package/src/__tests__/gateway-only-guard.test.ts +17 -2
  78. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  79. package/src/__tests__/guardian-routing-invariants.test.ts +93 -4
  80. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  81. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  82. package/src/__tests__/heartbeat-service.test.ts +1 -0
  83. package/src/__tests__/history-repair-hook.test.ts +5 -1
  84. package/src/__tests__/host-app-control-proxy.test.ts +45 -0
  85. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  86. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  87. package/src/__tests__/inference-profile-reaper.test.ts +62 -0
  88. package/src/__tests__/inference-profile-session-handler.test.ts +86 -0
  89. package/src/__tests__/injector-background-turn.test.ts +13 -23
  90. package/src/__tests__/injector-chain.test.ts +268 -44
  91. package/src/__tests__/injector-disk-pressure.test.ts +210 -52
  92. package/src/__tests__/injector-document-comments.test.ts +97 -114
  93. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  94. package/src/__tests__/injector-v3-suppression.test.ts +4 -4
  95. package/src/__tests__/list-messages-client-message-id.test.ts +91 -0
  96. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  97. package/src/__tests__/llm-resolver.test.ts +73 -0
  98. package/src/__tests__/memory-retrieval-hook.test.ts +156 -38
  99. package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
  100. package/src/__tests__/notification-decision-strategy.test.ts +3 -3
  101. package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
  102. package/src/__tests__/persist-unsendable-image-downscale.test.ts +145 -0
  103. package/src/__tests__/persist-unsendable-image.test.ts +97 -1
  104. package/src/__tests__/plugin-api-shim.test.ts +6 -9
  105. package/src/__tests__/plugin-bootstrap.test.ts +91 -81
  106. package/src/__tests__/plugin-registry.test.ts +3 -49
  107. package/src/__tests__/plugin-skill-contribution.test.ts +15 -14
  108. package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
  109. package/src/__tests__/plugin-types.test.ts +0 -70
  110. package/src/__tests__/post-turn-tool-result-truncation.test.ts +69 -0
  111. package/src/__tests__/pre-model-call-sanitize.test.ts +109 -0
  112. package/src/__tests__/published-app-updater.test.ts +138 -0
  113. package/src/__tests__/reaction-persistence.test.ts +1 -1
  114. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  115. package/src/__tests__/skill-feature-flags-integration.test.ts +31 -0
  116. package/src/__tests__/steer-tool-repair.test.ts +1 -1
  117. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  118. package/src/__tests__/subagent-detail.test.ts +25 -7
  119. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  120. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  121. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  122. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  123. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  124. package/src/__tests__/title-generate-hook.test.ts +5 -1
  125. package/src/__tests__/tool-error-hook.test.ts +1 -1
  126. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -1
  127. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  128. package/src/__tests__/web-fetch.test.ts +45 -0
  129. package/src/acp/__tests__/agent-process.test.ts +161 -0
  130. package/src/acp/__tests__/client-handler.test.ts +40 -0
  131. package/src/acp/__tests__/helpers/acp-config-stub.ts +0 -2
  132. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  133. package/src/acp/__tests__/helpers/exec-file-stub.ts +106 -0
  134. package/src/acp/__tests__/prepare-agent-env.test.ts +97 -0
  135. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  136. package/src/acp/__tests__/session-manager-resume.test.ts +888 -0
  137. package/src/acp/agent-process.ts +61 -1
  138. package/src/acp/auto-install.test.ts +280 -0
  139. package/src/acp/auto-install.ts +232 -0
  140. package/src/acp/client-handler.ts +31 -0
  141. package/src/acp/prepare-agent-env.ts +80 -27
  142. package/src/acp/resolve-agent.test.ts +188 -28
  143. package/src/acp/resolve-agent.ts +119 -42
  144. package/src/acp/resume-hint.ts +23 -0
  145. package/src/acp/session-manager.ts +507 -73
  146. package/src/agent/compaction-circuit.ts +60 -102
  147. package/src/agent/loop.ts +403 -251
  148. package/src/api/responses/conversation-message.ts +22 -2
  149. package/src/api/responses/memory-v3-selection-log.ts +19 -10
  150. package/src/approvals/guardian-request-resolvers.ts +27 -1
  151. package/src/background-wake/next-wake.ts +1 -0
  152. package/src/cli/commands/__tests__/memory-v3.test.ts +191 -210
  153. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  154. package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
  155. package/src/cli/commands/memory-v3.ts +57 -199
  156. package/src/cli/commands/plugins.ts +43 -37
  157. package/src/cli/lib/__tests__/install-from-github.test.ts +790 -111
  158. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
  159. package/src/cli/lib/__tests__/plugin-details.test.ts +381 -0
  160. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +270 -0
  161. package/src/cli/lib/__tests__/search-plugins.test.ts +233 -32
  162. package/src/cli/lib/install-from-github.ts +797 -60
  163. package/src/cli/lib/plugin-catalog-cache.ts +84 -0
  164. package/src/cli/lib/plugin-details.ts +416 -0
  165. package/src/cli/lib/plugin-marketplace.ts +215 -0
  166. package/src/cli/lib/search-plugins.ts +201 -29
  167. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  168. package/src/config/acp-defaults.test.ts +10 -0
  169. package/src/config/acp-defaults.ts +9 -3
  170. package/src/config/acp-schema.ts +1 -7
  171. package/src/config/bundled-skills/acp/SKILL.md +80 -41
  172. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  173. package/src/config/bundled-skills/app-builder/SKILL.md +224 -381
  174. package/src/config/bundled-skills/app-builder/TOOLS.json +72 -2
  175. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  176. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  177. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  178. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  179. package/src/config/bundled-skills/app-builder/tools/app-update.ts +18 -0
  180. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  181. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  182. package/src/config/bundled-tool-registry.ts +4 -0
  183. package/src/config/call-site-defaults.ts +0 -3
  184. package/src/config/feature-flag-registry.json +10 -16
  185. package/src/config/llm-resolver.ts +39 -7
  186. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -9
  187. package/src/config/schemas/call-site-catalog.ts +0 -21
  188. package/src/config/schemas/heartbeat.ts +9 -0
  189. package/src/config/schemas/llm.ts +17 -3
  190. package/src/config/schemas/memory-v3.ts +58 -8
  191. package/src/config/seed-inference-profiles.ts +18 -0
  192. package/src/context/compactor.ts +22 -4
  193. package/src/context/post-turn-tool-result-truncation.ts +39 -1
  194. package/src/context/strip-injections.ts +8 -2
  195. package/src/daemon/conversation-agent-loop-handlers.ts +18 -36
  196. package/src/daemon/conversation-agent-loop.ts +308 -1297
  197. package/src/daemon/conversation-error.ts +31 -4
  198. package/src/daemon/conversation-history.ts +1 -1
  199. package/src/daemon/conversation-lifecycle.ts +11 -255
  200. package/src/daemon/conversation-media-retry.ts +19 -6
  201. package/src/daemon/conversation-messaging.ts +17 -0
  202. package/src/daemon/conversation-process.ts +22 -141
  203. package/src/daemon/conversation-queue-manager.ts +8 -0
  204. package/src/daemon/conversation-registry.ts +159 -0
  205. package/src/daemon/conversation-runtime-assembly.ts +361 -393
  206. package/src/daemon/conversation-store.ts +9 -90
  207. package/src/daemon/conversation-surfaces.ts +165 -11
  208. package/src/daemon/conversation-workspace.ts +17 -0
  209. package/src/daemon/conversation.ts +444 -62
  210. package/src/daemon/disk-pressure-policy.ts +0 -1
  211. package/src/daemon/external-plugins-bootstrap.ts +36 -46
  212. package/src/daemon/handlers/config-channels.ts +11 -2
  213. package/src/daemon/handlers/conversations.ts +3 -1
  214. package/src/daemon/handlers/skills.ts +4 -1
  215. package/src/daemon/host-app-control-proxy.ts +72 -57
  216. package/src/daemon/host-proxy-preactivation.ts +1 -3
  217. package/src/daemon/lifecycle.ts +21 -7
  218. package/src/daemon/persist-unsendable-image.ts +62 -25
  219. package/src/daemon/process-message.ts +1 -1
  220. package/src/daemon/server.ts +2 -0
  221. package/src/daemon/tool-side-effects.ts +15 -0
  222. package/src/daemon/wake-conversation-ops.ts +269 -0
  223. package/src/embedded/plugin-api.ts +2 -2
  224. package/src/export/__tests__/transcript-formatter.test.ts +5 -0
  225. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  226. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  227. package/src/heartbeat/heartbeat-service.ts +26 -0
  228. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  229. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  230. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  231. package/src/ipc/skill-routes/memory.ts +4 -2
  232. package/src/memory/__tests__/activation-session-store.test.ts +41 -0
  233. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +87 -0
  234. package/src/memory/__tests__/onboarding-events-store.test.ts +80 -0
  235. package/src/memory/activation-session-store.ts +43 -0
  236. package/src/memory/conversation-crud.ts +29 -19
  237. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  238. package/src/memory/db-init.ts +6 -0
  239. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  240. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -4
  241. package/src/memory/jobs-worker.ts +25 -1
  242. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  243. package/src/memory/migrations/273-onboarding-events-funnel-columns.ts +46 -0
  244. package/src/memory/migrations/274-create-activation-sessions.ts +15 -0
  245. package/src/memory/migrations/index.ts +3 -0
  246. package/src/memory/onboarding-events-store.ts +66 -18
  247. package/src/memory/schema/acp.ts +4 -0
  248. package/src/memory/schema/infrastructure.ts +13 -0
  249. package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -97
  250. package/src/memory/v2/__tests__/page-store.test.ts +22 -0
  251. package/src/memory/v2/consolidation-job.ts +2 -63
  252. package/src/memory/v2/types.ts +5 -0
  253. package/src/messaging/providers/telegram-bot/api.ts +14 -5
  254. package/src/notifications/__tests__/copy-composer.test.ts +244 -0
  255. package/src/notifications/access-request-copy.ts +298 -0
  256. package/src/notifications/adapters/slack.ts +3 -3
  257. package/src/notifications/adapters/telegram.ts +9 -2
  258. package/src/notifications/copy-composer.ts +49 -267
  259. package/src/notifications/decision-engine.ts +16 -35
  260. package/src/notifications/home-feed-side-effect.ts +1 -6
  261. package/src/plugin-api/constants.ts +4 -0
  262. package/src/plugin-api/index.ts +40 -11
  263. package/src/plugin-api/types.ts +108 -0
  264. package/src/plugins/defaults/compaction/compact.ts +106 -0
  265. package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +250 -42
  266. package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
  267. package/src/plugins/defaults/compaction/manager-store.ts +57 -0
  268. package/src/plugins/defaults/compaction/package.json +1 -2
  269. package/src/{context → plugins/defaults/compaction}/window-manager.ts +95 -25
  270. package/src/plugins/defaults/empty-response/package.json +0 -1
  271. package/src/plugins/defaults/history-repair/package.json +0 -1
  272. package/src/plugins/defaults/index.ts +156 -26
  273. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
  274. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +285 -0
  275. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
  276. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +148 -73
  277. package/src/plugins/defaults/memory-retrieval/package.json +14 -0
  278. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +223 -0
  279. package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +71 -0
  280. package/src/plugins/defaults/memory-v3-shadow/__tests__/dense.test.ts +181 -0
  281. package/src/plugins/defaults/memory-v3-shadow/__tests__/edge.test.ts +247 -0
  282. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +147 -134
  283. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +456 -0
  284. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +662 -0
  285. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +306 -0
  286. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +91 -0
  287. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +402 -0
  288. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-needle.test.ts +135 -0
  289. package/src/plugins/defaults/memory-v3-shadow/__tests__/sections.test.ts +125 -0
  290. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +74 -19
  291. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +446 -0
  292. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +592 -0
  293. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -24
  294. package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +91 -0
  295. package/src/plugins/defaults/memory-v3-shadow/dense.ts +97 -0
  296. package/src/plugins/defaults/memory-v3-shadow/edge.ts +252 -0
  297. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  298. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  299. package/src/plugins/defaults/memory-v3-shadow/injector.ts +76 -0
  300. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +555 -0
  301. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +266 -0
  302. package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
  303. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +71 -0
  304. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +204 -0
  305. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +16 -8
  306. package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +236 -0
  307. package/src/plugins/defaults/memory-v3-shadow/section-needle.ts +200 -0
  308. package/src/plugins/defaults/memory-v3-shadow/sections.ts +115 -0
  309. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +156 -0
  310. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +382 -0
  311. package/src/plugins/defaults/memory-v3-shadow/types.ts +92 -0
  312. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +4 -1
  313. package/src/plugins/defaults/title-generate/package.json +0 -1
  314. package/src/plugins/defaults/tool-error/package.json +0 -1
  315. package/src/plugins/defaults/tool-result-truncate/package.json +0 -1
  316. package/src/plugins/external-api.ts +12 -2
  317. package/src/plugins/pipeline.ts +6 -293
  318. package/src/plugins/registry.ts +9 -37
  319. package/src/plugins/types.ts +76 -381
  320. package/src/plugins/user-loader.ts +30 -127
  321. package/src/prompts/__tests__/system-prompt.test.ts +6 -0
  322. package/src/prompts/system-prompt.ts +61 -10
  323. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +71 -4
  324. package/src/providers/anthropic/client.ts +9 -10
  325. package/src/providers/inference/kimi-cjk-token-ids.ts +493 -0
  326. package/src/providers/inference/logit-bias.ts +55 -0
  327. package/src/providers/model-catalog.ts +34 -0
  328. package/src/providers/openai/__tests__/vision-not-supported.test.ts +75 -0
  329. package/src/providers/openai/chat-completions-provider.ts +44 -1
  330. package/src/providers/retry.ts +22 -0
  331. package/src/providers/types.ts +6 -0
  332. package/src/runtime/__tests__/agent-wake.test.ts +555 -691
  333. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  334. package/src/runtime/agent-wake.ts +108 -209
  335. package/src/runtime/assistant-event-hub.ts +1 -1
  336. package/src/runtime/channel-approvals.ts +1 -1
  337. package/src/runtime/interactive-ui.ts +1 -1
  338. package/src/runtime/routes/__tests__/acp-routes.test.ts +466 -55
  339. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  340. package/src/runtime/routes/__tests__/plugins-routes.test.ts +423 -73
  341. package/src/runtime/routes/__tests__/stt-routes.test.ts +112 -0
  342. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  343. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  344. package/src/runtime/routes/acp-routes.test.ts +185 -32
  345. package/src/runtime/routes/acp-routes.ts +328 -30
  346. package/src/runtime/routes/app-management-routes.ts +3 -0
  347. package/src/runtime/routes/approval-routes.ts +1 -1
  348. package/src/runtime/routes/browser-routes.ts +1 -1
  349. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  350. package/src/runtime/routes/channel-verification-routes.ts +14 -5
  351. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  352. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  353. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  354. package/src/runtime/routes/conversation-routes.ts +30 -2
  355. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  356. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  357. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  358. package/src/runtime/routes/host-cu-routes.ts +1 -1
  359. package/src/runtime/routes/identity-routes.ts +18 -3
  360. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  361. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
  362. package/src/runtime/routes/inference-profile-session-handler.ts +11 -0
  363. package/src/runtime/routes/inference-profile-session-reaper.ts +6 -0
  364. package/src/runtime/routes/memory-v3-routes.ts +65 -305
  365. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +1 -1
  366. package/src/runtime/routes/playground/helpers.ts +1 -1
  367. package/src/runtime/routes/plugins-routes.ts +337 -35
  368. package/src/runtime/routes/stt-routes.ts +45 -12
  369. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  370. package/src/runtime/routes/work-items-routes.ts +2 -4
  371. package/src/runtime/routes/workspace-routes.ts +50 -15
  372. package/src/runtime/services/conversation-serializer.ts +1 -1
  373. package/src/runtime/verification-outbound-actions.ts +147 -2
  374. package/src/runtime/verification-templates.ts +29 -3
  375. package/src/services/published-app-updater.ts +30 -8
  376. package/src/signals/cancel.ts +2 -4
  377. package/src/subagent/manager.ts +21 -5
  378. package/src/telemetry/__tests__/activation-funnel.test.ts +95 -0
  379. package/src/telemetry/activation-funnel.ts +167 -0
  380. package/src/telemetry/types.ts +13 -0
  381. package/src/telemetry/usage-telemetry-reporter.test.ts +154 -0
  382. package/src/telemetry/usage-telemetry-reporter.ts +26 -1
  383. package/src/tools/acp/context.ts +20 -0
  384. package/src/tools/acp/list-agents.test.ts +9 -19
  385. package/src/tools/acp/list-agents.ts +3 -15
  386. package/src/tools/acp/spawn.test.ts +173 -202
  387. package/src/tools/acp/spawn.ts +37 -172
  388. package/src/tools/acp/steer.test.ts +105 -8
  389. package/src/tools/acp/steer.ts +48 -17
  390. package/src/tools/apps/executors.ts +166 -50
  391. package/src/tools/browser/browser-execution.ts +12 -2
  392. package/src/tools/filesystem/write.ts +34 -0
  393. package/src/tools/network/web-fetch.ts +65 -24
  394. package/src/tools/skills/load.ts +1 -1
  395. package/src/tools/subagent/spawn.ts +2 -4
  396. package/src/tools/ui-surface/definitions.ts +32 -5
  397. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  398. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +69 -45
  399. package/docs/plugins.md +0 -832
  400. package/examples/plugins/echo/register.ts +0 -143
  401. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  402. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  403. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  404. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -667
  405. package/src/__tests__/pipeline-runner.test.ts +0 -554
  406. package/src/daemon/wake-target-adapter.ts +0 -253
  407. package/src/memory/v3/__tests__/assign.test.ts +0 -242
  408. package/src/memory/v3/__tests__/capabilities.test.ts +0 -118
  409. package/src/memory/v3/__tests__/core.test.ts +0 -39
  410. package/src/memory/v3/__tests__/health.test.ts +0 -219
  411. package/src/memory/v3/__tests__/maintain-job.test.ts +0 -288
  412. package/src/memory/v3/__tests__/needle.test.ts +0 -107
  413. package/src/memory/v3/__tests__/orchestrate.test.ts +0 -436
  414. package/src/memory/v3/__tests__/provider-blocks.test.ts +0 -13
  415. package/src/memory/v3/__tests__/reconcile.test.ts +0 -274
  416. package/src/memory/v3/__tests__/render-injection.test.ts +0 -61
  417. package/src/memory/v3/__tests__/router.test.ts +0 -332
  418. package/src/memory/v3/__tests__/selector.test.ts +0 -470
  419. package/src/memory/v3/__tests__/shadow-plugin.test.ts +0 -432
  420. package/src/memory/v3/__tests__/snapshot.test.ts +0 -168
  421. package/src/memory/v3/__tests__/tree.test.ts +0 -192
  422. package/src/memory/v3/assign.ts +0 -268
  423. package/src/memory/v3/capabilities.ts +0 -124
  424. package/src/memory/v3/core.ts +0 -26
  425. package/src/memory/v3/health.ts +0 -0
  426. package/src/memory/v3/maintain-job.ts +0 -314
  427. package/src/memory/v3/needle.ts +0 -115
  428. package/src/memory/v3/orchestrate.ts +0 -126
  429. package/src/memory/v3/page-content.ts +0 -34
  430. package/src/memory/v3/provider-blocks.ts +0 -26
  431. package/src/memory/v3/reconcile.ts +0 -523
  432. package/src/memory/v3/router.ts +0 -190
  433. package/src/memory/v3/selection-log-store.ts +0 -84
  434. package/src/memory/v3/selector.ts +0 -226
  435. package/src/memory/v3/shadow-plugin.ts +0 -411
  436. package/src/memory/v3/snapshot.ts +0 -209
  437. package/src/memory/v3/tree.ts +0 -174
  438. package/src/memory/v3/types.ts +0 -59
  439. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
  440. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  441. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  442. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  443. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  444. package/src/plugins/defaults/compaction/register.ts +0 -35
  445. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  446. package/src/plugins/defaults/empty-response/register.ts +0 -23
  447. package/src/plugins/defaults/history-repair/register.ts +0 -24
  448. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +0 -216
  449. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  450. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  451. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  452. package/src/plugins/defaults/title-generate/register.ts +0 -35
  453. package/src/plugins/defaults/tool-error/register.ts +0 -23
  454. package/src/plugins/defaults/tool-result-truncate/register.ts +0 -24
  455. package/src/proactive-artifact/aux-message-injector.ts +0 -97
  456. package/src/proactive-artifact/decision.test.ts +0 -226
  457. package/src/proactive-artifact/decision.ts +0 -165
  458. package/src/proactive-artifact/index.ts +0 -7
  459. package/src/proactive-artifact/job.test.ts +0 -962
  460. package/src/proactive-artifact/job.ts +0 -372
  461. package/src/proactive-artifact/message-copy.ts +0 -58
  462. package/src/proactive-artifact/trigger-state.test.ts +0 -286
  463. package/src/proactive-artifact/trigger-state.ts +0 -123
  464. package/src/util/map-limit.ts +0 -27
  465. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  466. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  467. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  468. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  469. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  470. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  471. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  472. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  473. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  474. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  475. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/llm-retry.ts +0 -0
@@ -7,19 +7,35 @@ describe("MemoryV3ConfigSchema", () => {
7
7
  const parsed = MemoryV3ConfigSchema.parse({});
8
8
  expect(parsed).toEqual({
9
9
  workingSet: { maxPages: 150, evictWindow: 5 },
10
- l2Concurrency: 16,
10
+ needleK: 100,
11
+ denseK: 100,
12
+ edge: { hubDegree: 30, seedCount: 18, perSeed: 6, cap: 45 },
11
13
  });
12
14
  });
13
15
 
14
- test("accepts an explicit l2Concurrency override", () => {
15
- expect(MemoryV3ConfigSchema.parse({ l2Concurrency: 8 }).l2Concurrency).toBe(
16
- 8,
17
- );
16
+ test("accepts explicit lane-K overrides", () => {
17
+ const parsed = MemoryV3ConfigSchema.parse({ needleK: 50, denseK: 75 });
18
+ expect(parsed.needleK).toBe(50);
19
+ expect(parsed.denseK).toBe(75);
18
20
  });
19
21
 
20
- test("rejects a non-positive or non-integer l2Concurrency", () => {
21
- expect(() => MemoryV3ConfigSchema.parse({ l2Concurrency: 0 })).toThrow();
22
- expect(() => MemoryV3ConfigSchema.parse({ l2Concurrency: -4 })).toThrow();
23
- expect(() => MemoryV3ConfigSchema.parse({ l2Concurrency: 1.5 })).toThrow();
22
+ test("accepts a partial edge override, defaulting the rest", () => {
23
+ const parsed = MemoryV3ConfigSchema.parse({ edge: { hubDegree: 10 } });
24
+ expect(parsed.edge).toEqual({
25
+ hubDegree: 10,
26
+ seedCount: 18,
27
+ perSeed: 6,
28
+ cap: 45,
29
+ });
30
+ });
31
+
32
+ test("rejects non-positive or non-integer lane knobs", () => {
33
+ expect(() => MemoryV3ConfigSchema.parse({ needleK: 0 })).toThrow();
34
+ expect(() => MemoryV3ConfigSchema.parse({ denseK: -4 })).toThrow();
35
+ expect(() => MemoryV3ConfigSchema.parse({ needleK: 1.5 })).toThrow();
36
+ expect(() =>
37
+ MemoryV3ConfigSchema.parse({ edge: { perSeed: 0 } }),
38
+ ).toThrow();
39
+ expect(() => MemoryV3ConfigSchema.parse({ edge: { cap: -1 } })).toThrow();
24
40
  });
25
41
  });
@@ -121,13 +121,6 @@ const CATALOG_RECORD: CatalogRecord = {
121
121
  "Selects which concept pages to inject for the next agent turn by routing over a cached page index.",
122
122
  domain: "memory",
123
123
  },
124
- memoryV3RouteL1: {
125
- id: "memoryV3RouteL1",
126
- displayName: "Memory V3 L1 Router",
127
- description:
128
- "Picks which leaves of the topic tree to open for the next agent turn by routing over a cache-warm static leaf block.",
129
- domain: "memory",
130
- },
131
124
  memoryV3SelectL2: {
132
125
  id: "memoryV3SelectL2",
133
126
  displayName: "Memory V3 L2 Selector",
@@ -300,20 +293,6 @@ const CATALOG_RECORD: CatalogRecord = {
300
293
  description: "General-purpose LLM inference call site for skill use.",
301
294
  domain: "skills",
302
295
  },
303
- proactiveArtifactDecision: {
304
- id: "proactiveArtifactDecision",
305
- displayName: "Proactive Artifact Decision",
306
- description:
307
- "Decides what personalized artifact to build for new users based on conversation context.",
308
- domain: "agentLoop",
309
- },
310
- proactiveArtifactBuild: {
311
- id: "proactiveArtifactBuild",
312
- displayName: "Proactive Artifact Build",
313
- description:
314
- "Builds the personalized artifact in a background conversation with tool access.",
315
- domain: "agentLoop",
316
- },
317
296
  homeGreeting: {
318
297
  id: "homeGreeting",
319
298
  displayName: "Home Greeting",
@@ -56,6 +56,15 @@ export const HeartbeatConfigSchema = z
56
56
  .describe(
57
57
  "Maximum heartbeats that can run consecutively without a guardian message. Counter resets when the guardian sends a message. Set to null for unlimited.",
58
58
  ),
59
+ maxDailyRuns: z
60
+ .number({ error: "heartbeat.maxDailyRuns must be a number" })
61
+ .int("heartbeat.maxDailyRuns must be an integer")
62
+ .positive("heartbeat.maxDailyRuns must be a positive integer")
63
+ .nullable()
64
+ .default(2)
65
+ .describe(
66
+ "Maximum heartbeats that can run per calendar day. Resets at midnight local time. Set to null for unlimited.",
67
+ ),
59
68
  disposition: z
60
69
  .string({ error: "heartbeat.disposition must be a string" })
61
70
  .default(
@@ -50,7 +50,6 @@ export const LLMCallSiteEnum = z.enum([
50
50
  "memoryV2Migration",
51
51
  "memoryV2Sweep",
52
52
  "memoryRouter",
53
- "memoryV3RouteL1",
54
53
  "memoryV3SelectL2",
55
54
  "memoryV2Consolidation",
56
55
  "memoryRetrospective",
@@ -77,8 +76,6 @@ export const LLMCallSiteEnum = z.enum([
77
76
  "meetChatOpportunity",
78
77
  "inference",
79
78
  "trustRuleSuggestion",
80
- "proactiveArtifactDecision",
81
- "proactiveArtifactBuild",
82
79
  "homeGreeting",
83
80
  "homeSuggestedPrompts",
84
81
  ]);
@@ -126,6 +123,17 @@ const VerbosityEnum = z.enum(["low", "medium", "high"]);
126
123
  const ModelSchema = z.string().min(1);
127
124
  const MaxTokensSchema = z.number().int().positive();
128
125
  const TemperatureSchema = z.number().min(0).max(2).nullable();
126
+ // Named, code-resolved logit-bias preset a profile may opt into. The value is a
127
+ // preset *name*, not an inline token→bias map, so the workspace config stays
128
+ // small. This is profile-identity metadata, not inheritable config: the resolver
129
+ // strips it from the deep-merge and re-attaches it from the winning profile (see
130
+ // `profileConfigFragment` / `resolveCallSiteConfig`), and `RetryProvider`
131
+ // resolves it to a `logit_bias` map at request time, forwarded only on the
132
+ // Fireworks (OpenAI-compatible) path. Keep these literals in sync with the
133
+ // presets handled by `resolveLogitBiasPreset` in
134
+ // `providers/inference/logit-bias.ts` (kept separate to avoid a schema →
135
+ // provider import cycle).
136
+ const LogitBiasPresetSchema = z.enum(["suppress-cjk"]);
129
137
 
130
138
  // ---------------------------------------------------------------------------
131
139
  // Thinking & ContextWindow
@@ -318,6 +326,11 @@ export const LLMConfigBase = z.object({
318
326
  thinking: ThinkingSchema.default(ThinkingSchema.parse({})),
319
327
  contextWindow: ContextWindowSchema.default(ContextWindowSchema.parse({})),
320
328
  openrouter: OpenRouterSchema.default(OpenRouterSchema.parse({})),
329
+ // Not deep-merged like the other fields: `resolveCallSiteConfig` sets this
330
+ // from the single highest-precedence profile that won resolution (see
331
+ // `profileConfigFragment`, which strips it from the merge), so a preset
332
+ // can't bleed from a lower-precedence profile into one that didn't opt in.
333
+ logitBias: LogitBiasPresetSchema.optional(),
321
334
  });
322
335
  export type LLMConfigBase = z.infer<typeof LLMConfigBase>;
323
336
 
@@ -338,6 +351,7 @@ const LLMConfigFragment = z.object({
338
351
  thinking: ThinkingFragmentSchema.optional(),
339
352
  contextWindow: ContextWindowDeepPartialSchema.optional(),
340
353
  openrouter: OpenRouterDeepPartialSchema.optional(),
354
+ logitBias: LogitBiasPresetSchema.optional(),
341
355
  });
342
356
  type LLMConfigFragment = z.infer<typeof LLMConfigFragment>;
343
357
 
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
 
3
3
  /**
4
- * Memory v3 (topic-tree routing) working-set configuration.
4
+ * Memory v3 (section-grain lane retrieval) working-set configuration.
5
5
  *
6
6
  * The working set is the per-conversation set of concept pages carried
7
7
  * forward across turns. Eviction keeps it bounded: pages unseen for longer
@@ -28,20 +28,70 @@ export const MemoryV3WorkingSetSchema = z
28
28
  })
29
29
  .describe("Memory v3 working-set retention/eviction tuning.");
30
30
 
31
+ /**
32
+ * Edge-lane tuning for the link-graph expansion that folds a turn's lexical and
33
+ * dense seeds outward to their first-class neighbours.
34
+ */
35
+ export const MemoryV3EdgeSchema = z
36
+ .object({
37
+ hubDegree: z
38
+ .number({ error: "memory.v3.edge.hubDegree must be a number" })
39
+ .int("memory.v3.edge.hubDegree must be an integer")
40
+ .positive("memory.v3.edge.hubDegree must be a positive integer")
41
+ .default(30)
42
+ .describe(
43
+ "In-degree above which an article is treated as a hub and excluded from edge expansion (too generic to be a useful surface).",
44
+ ),
45
+ seedCount: z
46
+ .number({ error: "memory.v3.edge.seedCount must be a number" })
47
+ .int("memory.v3.edge.seedCount must be an integer")
48
+ .positive("memory.v3.edge.seedCount must be a positive integer")
49
+ .default(18)
50
+ .describe(
51
+ "Number of top needle+dense seeds (in rank order) expanded by the edge lane.",
52
+ ),
53
+ perSeed: z
54
+ .number({ error: "memory.v3.edge.perSeed must be a number" })
55
+ .int("memory.v3.edge.perSeed must be an integer")
56
+ .positive("memory.v3.edge.perSeed must be a positive integer")
57
+ .default(6)
58
+ .describe("Maximum neighbours surfaced per expanded seed."),
59
+ cap: z
60
+ .number({ error: "memory.v3.edge.cap must be a number" })
61
+ .int("memory.v3.edge.cap must be an integer")
62
+ .positive("memory.v3.edge.cap must be a positive integer")
63
+ .default(45)
64
+ .describe(
65
+ "Hard cap on the total number of distinct articles surfaced by the edge lane.",
66
+ ),
67
+ })
68
+ .describe("Memory v3 edge-lane (link-graph expansion) tuning.");
69
+
31
70
  export const MemoryV3ConfigSchema = z
32
71
  .object({
33
72
  workingSet: MemoryV3WorkingSetSchema.default(
34
73
  MemoryV3WorkingSetSchema.parse({}),
35
74
  ),
36
- l2Concurrency: z
37
- .number({ error: "memory.v3.l2Concurrency must be a number" })
38
- .int("memory.v3.l2Concurrency must be an integer")
39
- .positive("memory.v3.l2Concurrency must be a positive integer")
40
- .default(16)
75
+ needleK: z
76
+ .number({ error: "memory.v3.needleK must be a number" })
77
+ .int("memory.v3.needleK must be an integer")
78
+ .positive("memory.v3.needleK must be a positive integer")
79
+ .default(100)
80
+ .describe(
81
+ "Number of section-grain BM25 needle articles folded into the candidate pool each turn.",
82
+ ),
83
+ denseK: z
84
+ .number({ error: "memory.v3.denseK must be a number" })
85
+ .int("memory.v3.denseK must be an integer")
86
+ .positive("memory.v3.denseK must be a positive integer")
87
+ .default(100)
41
88
  .describe(
42
- "Bounded fan-out for the per-leaf L2 selection (number of leaf selector calls in flight at once).",
89
+ "Number of dense-lane articles folded into the candidate pool each turn.",
43
90
  ),
91
+ edge: MemoryV3EdgeSchema.default(MemoryV3EdgeSchema.parse({})),
44
92
  })
45
- .describe("Memory v3 — topic-tree routing with a carry-forward working set");
93
+ .describe(
94
+ "Memory v3 — section-grain lane retrieval with a carry-forward working set",
95
+ );
46
96
 
47
97
  export type MemoryV3Config = z.infer<typeof MemoryV3ConfigSchema>;
@@ -74,6 +74,24 @@ const MANAGED_PROFILE_TEMPLATES: Record<string, ManagedProfileTemplate> = {
74
74
  thinking: { enabled: false, streamThinking: false },
75
75
  contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
76
76
  },
77
+ // Open-weight economy option: Kimi K2.6 served by Fireworks via managed
78
+ // platform inference. Carries the `suppress-cjk` logit-bias preset to
79
+ // discourage the model from spontaneously emitting Chinese in English
80
+ // output; the preset is profile-scoped and only forwarded on the Fireworks
81
+ // path (see `providers/inference/logit-bias.ts`).
82
+ "balanced-economy": {
83
+ intent: "balanced",
84
+ provider: "fireworks",
85
+ connectionName: "fireworks-managed",
86
+ source: "managed",
87
+ label: "Balanced Economy",
88
+ description: "Strong open model (Kimi K2.6) at a lower price point",
89
+ maxTokens: 16000,
90
+ effort: "high",
91
+ thinking: { enabled: true, streamThinking: true },
92
+ contextWindow: { maxInputTokens: DEFAULT_CONTEXT_WINDOW_MAX_INPUT_TOKENS },
93
+ logitBias: "suppress-cjk",
94
+ },
77
95
  };
78
96
 
79
97
  /**
@@ -22,6 +22,7 @@ import { optimizeImageForTransport } from "../agent/image-optimize.js";
22
22
  import type { CompactionConfig } from "../config/schemas/compaction.js";
23
23
  import type { LLMCallSite } from "../config/schemas/llm.js";
24
24
  import { filterMessagesForUntrustedActor } from "../daemon/message-provenance.js";
25
+ import { stripHistoricalWebSearchResults } from "../daemon/web-search-history.js";
25
26
  import {
26
27
  getAttachmentContent,
27
28
  getAttachmentMetadataForMessage,
@@ -685,6 +686,25 @@ function extractTextFromResponse(content: ContentBlock[]): string {
685
686
  .join("\n");
686
687
  }
687
688
 
689
+ // Build the outbound message list for a compaction provider call: convert
690
+ // historical web_search_tool_result blocks to text, then append the
691
+ // summarization instruction at the tail.
692
+ //
693
+ // Anthropic's opaque `encrypted_content` tokens are route-scoped and expire, so
694
+ // replaying a stale one is rejected with `Invalid encrypted_content in
695
+ // search_result block`. Sanitizing here — the single seam every compaction
696
+ // provider call funnels through — keeps that error away from both the
697
+ // assistant-driven and emergency summarization calls. Only this outbound copy
698
+ // is sanitized; tail resolution and the persisted compaction result read the
699
+ // caller's original messages, so durable history keeps the rich blocks. The
700
+ // instruction stays at the tail so the prefix cache stays warm.
701
+ function buildCompactionRequest(
702
+ history: Message[],
703
+ instruction: Message,
704
+ ): Message[] {
705
+ return [...stripHistoricalWebSearchResults(history).messages, instruction];
706
+ }
707
+
688
708
  export async function runAssistantDrivenCompaction(
689
709
  args: CompactionRunArgs,
690
710
  ): Promise<CompactionRunResult> {
@@ -718,9 +738,7 @@ export async function runAssistantDrivenCompaction(
718
738
  manifestText,
719
739
  );
720
740
 
721
- // Append instruction at the tail — prefix unchanged, so prefix cache
722
- // stays warm.
723
- const requestMessages = [...args.messages, instruction];
741
+ const requestMessages = buildCompactionRequest(args.messages, instruction);
724
742
 
725
743
  let response: ProviderResponse;
726
744
  try {
@@ -1090,7 +1108,7 @@ export async function runEmergencyCompaction(
1090
1108
  role: "user",
1091
1109
  content: [{ type: "text", text: EMERGENCY_COMPACTION_PROMPT }],
1092
1110
  };
1093
- const requestMessages = [...prefix, instruction];
1111
+ const requestMessages = buildCompactionRequest(prefix, instruction);
1094
1112
 
1095
1113
  let response: ProviderResponse;
1096
1114
  try {
@@ -22,6 +22,34 @@ export const TOOL_RESULT_DIR = ".tool-results";
22
22
  /** Marker used to detect already-truncated results (idempotency guard). */
23
23
  export const TRUNCATION_MARKER = "\u2014 full result:";
24
24
 
25
+ /**
26
+ * Tools whose results carry durable operating instructions the model relies on
27
+ * across later turns rather than one-off data it only needs in the moment.
28
+ * Their results must never be middle-truncated: paging out the middle silently
29
+ * strips the workflow (e.g. a `skill_load` body losing its "## Available Tools"
30
+ * section), leaving the model to fall back to generic priors. Skill bodies are
31
+ * bounded and authored to live in context, so exempting them is safe.
32
+ */
33
+ export const TRUNCATION_EXEMPT_TOOLS = new Set<string>(["skill_load"]);
34
+
35
+ /**
36
+ * Build a map of tool_use_id -> originating tool name by walking the tool_use
37
+ * blocks in assistant messages. A tool_result only carries `tool_use_id`, so
38
+ * this is the only way to recover which tool produced a given result.
39
+ */
40
+ function buildToolNameById(messages: Message[]): Map<string, string> {
41
+ const byId = new Map<string, string>();
42
+ for (const msg of messages) {
43
+ if (msg.role !== "assistant") continue;
44
+ for (const block of msg.content) {
45
+ if (block.type !== "tool_use") continue;
46
+ const tu = block as ToolUseContent;
47
+ byId.set(tu.id, tu.name);
48
+ }
49
+ }
50
+ return byId;
51
+ }
52
+
25
53
  /**
26
54
  * Deterministic file path for a tool result's full content on disk.
27
55
  * Uses the first 12 hex chars of the SHA-256 of the tool_use_id.
@@ -59,7 +87,8 @@ export function buildTruncatedContent(
59
87
  * - The in-context content is replaced with a prefix/suffix stub.
60
88
  *
61
89
  * Results are skipped if they are below threshold, are error results,
62
- * or have already been truncated (contain `TRUNCATION_MARKER`).
90
+ * have already been truncated (contain `TRUNCATION_MARKER`), or were produced
91
+ * by a tool in `TRUNCATION_EXEMPT_TOOLS` (durable instructions like skill bodies).
63
92
  *
64
93
  * Returns a shallow-copied messages array (only modified messages are cloned)
65
94
  * and the count of results that were truncated.
@@ -70,6 +99,8 @@ export function postTurnTruncateToolResults(
70
99
  ): { messages: Message[]; truncatedCount: number } {
71
100
  let truncatedCount = 0;
72
101
 
102
+ const toolNameById = buildToolNameById(messages);
103
+
73
104
  const mapped = messages.map((msg) => {
74
105
  let changed = false;
75
106
  const nextContent: ContentBlock[] = msg.content.map((block) => {
@@ -82,6 +113,13 @@ export function postTurnTruncateToolResults(
82
113
  // Skip error results.
83
114
  if (tr.is_error) return block;
84
115
 
116
+ // Skip results from tools whose output is durable operating instructions
117
+ // (e.g. skill_load); middle-truncating them strips the workflow.
118
+ const toolName = toolNameById.get(tr.tool_use_id);
119
+ if (toolName !== undefined && TRUNCATION_EXEMPT_TOOLS.has(toolName)) {
120
+ return block;
121
+ }
122
+
85
123
  // Skip already-truncated results (idempotency).
86
124
  if (tr.content.includes(TRUNCATION_MARKER)) return block;
87
125
 
@@ -87,8 +87,14 @@ const RUNTIME_INJECTION_PREFIXES: InjectionMatcher[] = [
87
87
  { prefix: "<info>\n", suffix: "\n</info>" },
88
88
  "<voice_call_control>",
89
89
  "<workspace_top_level>", // backward-compat: strip legacy workspace blocks
90
- // NOTE: <workspace> is intentionally NOT stripped — workspace context
91
- // persists in history so the assistant retains workspace grounding.
90
+ // The `<workspace>` top-level block is stripped so each compaction re-injects
91
+ // a fresh directory snapshot rather than carrying a stale listing into the
92
+ // summary — matching the `<knowledge_base>`/`<NOW.md>` cadence and keeping the
93
+ // `workspace-context` injector's presence detection in lockstep (the block is
94
+ // present exactly when compaction would strip it). The full `{ prefix, suffix }`
95
+ // wrapper shape ensures user-authored text merely starting with `<workspace>\n`
96
+ // is never mistaken for an injected block.
97
+ { prefix: "<workspace>\n", suffix: "\n</workspace>" },
92
98
  "<temporal_context>\nToday:", // backward-compat: strip legacy temporal blocks
93
99
  "<active_subagents>",
94
100
  "<active_workspace>",
@@ -17,7 +17,6 @@ import type {
17
17
  import { getConfig } from "../config/loader.js";
18
18
  import { recordEstimate } from "../context/estimator-calibration.js";
19
19
  import { getCalibrationProviderKey } from "../context/token-estimator.js";
20
- import type { ContextWindowResult } from "../context/window-manager.js";
21
20
  import { projectAssistantMessage } from "../memory/conversation-attention-store.js";
22
21
  import {
23
22
  deleteMessageById,
@@ -46,6 +45,7 @@ import {
46
45
  type SlackMessageMetadata,
47
46
  writeSlackMetadata,
48
47
  } from "../messaging/providers/slack/message-metadata.js";
48
+ import type { ContextWindowResult } from "../plugins/defaults/compaction/window-manager.js";
49
49
  import type {
50
50
  ContentBlock,
51
51
  ImageContent,
@@ -76,10 +76,8 @@ import {
76
76
  cleanAssistantContent,
77
77
  drainDirectiveDisplayBuffer,
78
78
  } from "./assistant-attachments.js";
79
- import type {
80
- AgentLoopConversationContext,
81
- AssistantSurface,
82
- } from "./conversation-agent-loop.js";
79
+ import type { Conversation } from "./conversation.js";
80
+ import type { AssistantSurface } from "./conversation-agent-loop.js";
83
81
  import {
84
82
  buildConversationErrorMessage,
85
83
  classifyConversationError,
@@ -295,29 +293,11 @@ export interface EventHandlerState {
295
293
  * never claims content a flush has not yet written.
296
294
  */
297
295
  lastPersistedContentSeq: number | undefined;
298
- /**
299
- * Whether the workspace top-level block should be (re)injected on this
300
- * turn. Compaction's prepare phase strips the workspace / NOW.md / PKB
301
- * blocks off the tail, so it is set after any successful compaction to
302
- * force the workspace overview back in. On an ordinary turn the block is
303
- * already present in history, so it defaults `false` to avoid burning
304
- * tokens re-injecting it redundantly.
305
- */
306
- shouldInjectWorkspace: boolean;
307
- /**
308
- * Whether the reducer has compacted `ctx.messages`, gating the Slack
309
- * chronological-transcript override on re-injection. The captured
310
- * transcript is the full persisted history; blindly replaying it after
311
- * compaction would overwrite the reduced messages and undo compaction, so
312
- * once this is `true` the override falls back to the reduced
313
- * `ctx.messages`.
314
- */
315
- reducerCompacted: boolean;
316
296
  }
317
297
 
318
298
  /** Immutable context shared across event handlers within a single agent loop run. */
319
299
  export interface EventHandlerDeps {
320
- readonly ctx: AgentLoopConversationContext;
300
+ readonly ctx: Conversation;
321
301
  readonly onEvent: (msg: ServerMessage) => void;
322
302
  readonly reqId: string;
323
303
  readonly isFirstMessage: boolean;
@@ -392,8 +372,6 @@ export function createEventHandlerState(): EventHandlerState {
392
372
  pendingPartialFlushPromise: undefined,
393
373
  currentMessageContent: [],
394
374
  lastPersistedContentSeq: undefined,
395
- shouldInjectWorkspace: false,
396
- reducerCompacted: false,
397
375
  };
398
376
  }
399
377
 
@@ -655,9 +633,7 @@ function computeToolUseStatusText(
655
633
  return `Running ${friendlyToolName(name)}`;
656
634
  }
657
635
 
658
- function resolveAssistantReplyTimestampTimezone(
659
- ctx: AgentLoopConversationContext,
660
- ): string {
636
+ function resolveAssistantReplyTimestampTimezone(ctx: Conversation): string {
661
637
  const config = getConfig();
662
638
  return resolveTurnTimezoneContext({
663
639
  configuredUserTimeZone: config.ui?.userTimezone ?? null,
@@ -1506,6 +1482,13 @@ function annotatePersistedAssistantMessage(
1506
1482
  display: surface.display,
1507
1483
  ...(surface.persistent ? { persistent: true } : {}),
1508
1484
  ...(surface.toolCallId ? { toolCallId: surface.toolCallId } : {}),
1485
+ // Daemon-only commit-timing activation tag, persisted so
1486
+ // restoreSurfaceStateFromHistory can rehydrate it after a reload. This
1487
+ // block lives only in server-side conversation history, never in the
1488
+ // client `ui_surface_show` message.
1489
+ ...(surface.activationMoment
1490
+ ? { activationMoment: surface.activationMoment }
1491
+ : {}),
1509
1492
  } as unknown as ContentBlock);
1510
1493
  }
1511
1494
  modified = true;
@@ -1659,6 +1642,8 @@ export async function handleMessageComplete(
1659
1642
  deps.ctx.conversationId,
1660
1643
  state.pendingNotifiedInferenceProfile,
1661
1644
  );
1645
+ deps.ctx.lastNotifiedInferenceProfile =
1646
+ state.pendingNotifiedInferenceProfile;
1662
1647
  state.pendingNotifiedInferenceProfile = null;
1663
1648
  }
1664
1649
 
@@ -2302,17 +2287,14 @@ export async function dispatchAgentEvent(
2302
2287
  // so re-injection re-applies onto the stripped history even when the
2303
2288
  // pipeline ran but did not compact. When it did compact, commit the
2304
2289
  // durable result (DB-record fields, Slack provenance, SSE) — which
2305
- // overwrites `ctx.messages` with the compacted history — and flip the
2306
- // per-turn re-injection guards the orchestrator reads. This runs
2290
+ // overwrites `ctx.messages` with the compacted history. This runs
2307
2291
  // before the loop's `reinject` hook (the loop awaits this dispatch),
2308
- // so the guards are set in time. A failed durable commit re-throws
2309
- // below to abort the turn rather than re-injecting against
2310
- // half-applied state.
2292
+ // so the committed history is in place in time. A failed durable
2293
+ // commit re-throws below to abort the turn rather than re-injecting
2294
+ // against half-applied state.
2311
2295
  deps.ctx.messages = event.basis;
2312
2296
  if (event.result.compacted) {
2313
2297
  await deps.applyCompaction(event.result, event.basis);
2314
- state.reducerCompacted = true;
2315
- state.shouldInjectWorkspace = true;
2316
2298
  }
2317
2299
  break;
2318
2300
  case "history_stripped":