@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
@@ -38,23 +38,66 @@ mock.module("../config/loader.js", () => ({
38
38
  },
39
39
  }));
40
40
 
41
- const { applyRuntimeInjections, composeInjectorChain } =
42
- await import("../daemon/conversation-runtime-assembly.js");
41
+ // `applyRuntimeInjections` computes the `<turn_context>` `current_time` live
42
+ // via `formatTurnTimestamp`; pin it so the rendered block matches the
43
+ // deterministic `buildUnifiedTurnContextBlock` expectations below. The rest of
44
+ // the module (timezone canonicalization/resolution) keeps its real behavior.
45
+ const FIXED_TURN_TIMESTAMP = "2026-04-22";
46
+ const realDateContext = await import("../daemon/date-context.js");
47
+ mock.module("../daemon/date-context.js", () => ({
48
+ ...realDateContext,
49
+ formatTurnTimestamp: () => FIXED_TURN_TIMESTAMP,
50
+ }));
51
+
52
+ const {
53
+ applyRuntimeInjections,
54
+ buildSubagentStatusBlock,
55
+ composeInjectorChain,
56
+ } = await import("../daemon/conversation-runtime-assembly.js");
43
57
  const { DEFAULT_INJECTOR_ORDER, defaultInjectors } =
44
- await import("../plugins/defaults/injectors/register.js");
58
+ await import("../plugins/defaults/memory-retrieval/injectors.js");
45
59
  const { getInjectorChain } =
46
60
  await import("../plugins/defaults/memory-retrieval/injector-chain.js");
61
+ import { eq } from "drizzle-orm";
62
+
63
+ import {
64
+ clearConversations,
65
+ setConversation,
66
+ } from "../daemon/conversation-registry.js";
47
67
  import { buildPkbReminder } from "../daemon/pkb-reminder-builder.js";
68
+ import { getDb } from "../memory/db-connection.js";
69
+ import { initializeDb } from "../memory/db-init.js";
48
70
  import { getPkbRoot } from "../memory/pkb/types.js";
71
+ import { conversations, messages } from "../memory/schema.js";
72
+ import {
73
+ type SlackMessageMetadata,
74
+ writeSlackMetadata,
75
+ } from "../messaging/providers/slack/message-metadata.js";
76
+ import { buildUnifiedTurnContextBlock } from "../plugins/defaults/memory-retrieval/unified-turn-context.js";
49
77
  import type { TurnContext } from "../plugins/types.js";
50
78
  import type { Message } from "../providers/types.js";
79
+ import { getSubagentManager } from "../subagent/index.js";
80
+ import type { SubagentState } from "../subagent/types.js";
51
81
  import { getWorkspacePromptPath } from "../util/platform.js";
52
82
 
83
+ // `applyRuntimeInjections` self-resolves the Slack active-thread focus block
84
+ // from the persisted message rows, so the schema must exist for Slack-channel
85
+ // turns; with no seeded rows the focus loader resolves to null.
86
+ initializeDb();
87
+
88
+ // `makeTurnContext` and the workspace registry seed share this id so the
89
+ // `workspace-context` injector resolves the seeded block for the turn.
90
+ const TEST_CONVERSATION_ID = "conv-test-1";
91
+ // Conversation id the fallback-context test registers its live conversation
92
+ // under; passed explicitly now that `applyRuntimeInjections` requires the
93
+ // caller to name the conversation it resolves through.
94
+ const FALLBACK_CONVERSATION_ID = "runtime-assembly-fallback";
95
+
53
96
  /** A fake TurnContext sufficient for driving `composeInjectorChain`. */
54
97
  function makeTurnContext(): TurnContext {
55
98
  return {
56
99
  requestId: "req-test-1",
57
- conversationId: "conv-test-1",
100
+ conversationId: TEST_CONVERSATION_ID,
58
101
  turnIndex: 0,
59
102
  trust: {
60
103
  sourceChannel: "vellum",
@@ -94,10 +137,158 @@ function clearNowScratchpad(): void {
94
137
  rmSync(getWorkspacePromptPath("NOW.md"), { force: true });
95
138
  }
96
139
 
140
+ // The workspace-context injector sources its block off the live `Conversation`
141
+ // looked up by `conversationId`. Seed a fake instance carrying a non-dirty
142
+ // workspace cache under the id `makeTurnContext()` uses so the injector emits
143
+ // the block; `clearConversations()` between tests keeps suites that assert the
144
+ // workspace block is absent unaffected.
145
+ function seedWorkspaceContext(
146
+ text: string,
147
+ currentTurnTemporalSnapshot?: {
148
+ clientTimezone: string | null;
149
+ },
150
+ interfaceName?: string,
151
+ ): void {
152
+ setConversation(TEST_CONVERSATION_ID, {
153
+ conversationId: TEST_CONVERSATION_ID,
154
+ workingDir: "/sandbox",
155
+ workspaceTopLevelContext: text,
156
+ workspaceTopLevelDirty: false,
157
+ currentTurnTemporalSnapshot,
158
+ currentTurnInterfaceContext: interfaceName
159
+ ? {
160
+ userMessageInterface: interfaceName,
161
+ assistantMessageInterface: interfaceName,
162
+ }
163
+ : undefined,
164
+ } as never);
165
+ }
166
+
167
+ // `applyRuntimeInjections` gates the `<turn_context>` block on the live
168
+ // conversation's frozen `currentTurnTemporalSnapshot` (computing `current_time`
169
+ // live). Tests that drive the chain without a caller-supplied `turnContext`
170
+ // fall back to the runtime-assembly fallback conversation, so seed the snapshot
171
+ // there.
172
+ function seedFallbackTemporalSnapshot(): void {
173
+ setConversation("runtime-assembly-fallback", {
174
+ conversationId: "runtime-assembly-fallback",
175
+ workingDir: "/sandbox",
176
+ workspaceTopLevelContext: "",
177
+ workspaceTopLevelDirty: false,
178
+ currentTurnTemporalSnapshot: { clientTimezone: null },
179
+ } as never);
180
+ }
181
+
182
+ // Persist Slack-channel rows for the turn conversation so
183
+ // `applyRuntimeInjections` self-resolves the chronological transcript from
184
+ // conversation state, exactly as production does (the slack-messages injector
185
+ // reads the live conversation rather than receiving a pre-built transcript).
186
+ const SLACK_CHANNEL_ID = "C0123CHANNEL";
187
+ function seedSlackChannelRows(
188
+ conversationId: string,
189
+ rows: Array<{
190
+ id: string;
191
+ role: "user" | "assistant";
192
+ text: string;
193
+ channelTs: string;
194
+ displayName: string;
195
+ createdAt: number;
196
+ }>,
197
+ ): void {
198
+ const db = getDb();
199
+ const now = Date.now();
200
+ db.insert(conversations)
201
+ .values({ id: conversationId, createdAt: now, updatedAt: now })
202
+ .onConflictDoNothing()
203
+ .run();
204
+ for (const r of rows) {
205
+ const meta: SlackMessageMetadata = {
206
+ source: "slack",
207
+ channelId: SLACK_CHANNEL_ID,
208
+ channelTs: r.channelTs,
209
+ eventKind: "message",
210
+ displayName: r.displayName,
211
+ } as SlackMessageMetadata;
212
+ db.insert(messages)
213
+ .values({
214
+ id: r.id,
215
+ conversationId,
216
+ role: r.role,
217
+ content: JSON.stringify([{ type: "text", text: r.text }]),
218
+ createdAt: r.createdAt,
219
+ metadata: JSON.stringify({
220
+ provenanceTrustClass: "guardian",
221
+ slackMeta: writeSlackMetadata(meta),
222
+ }),
223
+ })
224
+ .run();
225
+ }
226
+ }
227
+
228
+ // `applyRuntimeInjections` self-resolves the `<active_subagents>` block from the
229
+ // global subagent manager keyed by the conversation, so tests seed children
230
+ // directly into the manager's private maps rather than threading a pre-built
231
+ // block through options.
232
+ interface SubagentManagerTestInternals {
233
+ subagents: Map<string, { state: SubagentState }>;
234
+ parentToChildren: Map<string, Set<string>>;
235
+ }
236
+
237
+ function makeSubagentState(
238
+ id: string,
239
+ label: string,
240
+ status: SubagentState["status"],
241
+ ): SubagentState {
242
+ return {
243
+ config: {
244
+ id,
245
+ parentConversationId: TEST_CONVERSATION_ID,
246
+ label,
247
+ objective: "obj",
248
+ },
249
+ status,
250
+ conversationId: `conv-${id}`,
251
+ isFork: false,
252
+ createdAt: Date.now() - 60_000,
253
+ startedAt: Date.now() - 55_000,
254
+ completedAt: status === "completed" ? Date.now() : undefined,
255
+ usage: { inputTokens: 0, outputTokens: 0, estimatedCost: 0 },
256
+ };
257
+ }
258
+
259
+ function seedSubagentChild(
260
+ parentConversationId: string,
261
+ state: SubagentState,
262
+ ): void {
263
+ const internals =
264
+ getSubagentManager() as unknown as SubagentManagerTestInternals;
265
+ internals.subagents.set(state.config.id, { state });
266
+ const ids =
267
+ internals.parentToChildren.get(parentConversationId) ?? new Set<string>();
268
+ ids.add(state.config.id);
269
+ internals.parentToChildren.set(parentConversationId, ids);
270
+ }
271
+
272
+ function clearSeededSubagents(): void {
273
+ const internals =
274
+ getSubagentManager() as unknown as SubagentManagerTestInternals;
275
+ internals.subagents.clear();
276
+ internals.parentToChildren.clear();
277
+ }
278
+
97
279
  describe("injector chain", () => {
98
280
  beforeEach(() => {
99
281
  clearPkbContent();
100
282
  clearNowScratchpad();
283
+ clearConversations();
284
+ clearSeededSubagents();
285
+ const db = getDb();
286
+ db.delete(messages)
287
+ .where(eq(messages.conversationId, TEST_CONVERSATION_ID))
288
+ .run();
289
+ db.delete(conversations)
290
+ .where(eq(conversations.id, TEST_CONVERSATION_ID))
291
+ .run();
101
292
  });
102
293
 
103
294
  test("defaultInjectors lists the defaults in the documented order", () => {
@@ -188,7 +379,7 @@ describe("injector chain", () => {
188
379
  ];
189
380
 
190
381
  const result = await applyRuntimeInjections(runMessages, {
191
- turnContext: makeTurnContext(),
382
+ ...makeTurnContext(),
192
383
  });
193
384
 
194
385
  expect(result.blocks.injectorChainBlock).toBeUndefined();
@@ -200,22 +391,28 @@ describe("injector chain", () => {
200
391
  test("applyRuntimeInjections without turnContext still runs the chain under a synthesized context", async () => {
201
392
  // The static chain is the canonical injection path, so
202
393
  // `applyRuntimeInjections` must drive it even when the caller doesn't
203
- // pass a `turnContext`. Call sites that rely on option fields to opt
204
- // into injections continue to work because the synthesized fallback
205
- // exposes `injectionInputs` built from `options`.
394
+ // pass a `turnContext`. With no caller-supplied context the assembly
395
+ // falls back to the runtime-assembly fallback conversation id, so the
396
+ // live-sourced unified turn context resolves off that conversation.
206
397
  const runMessages: Message[] = [
207
398
  { role: "user", content: [{ type: "text", text: "hi" }] },
208
399
  ];
209
400
 
401
+ // The fallback conversation has no per-turn or origin interface, so the
402
+ // unified-turn-context injector resolves the interface label to the `web`
403
+ // default.
404
+ const synthesizedBlock = buildUnifiedTurnContextBlock({
405
+ timestamp: FIXED_TURN_TIMESTAMP,
406
+ interfaceName: "web",
407
+ });
408
+ seedFallbackTemporalSnapshot();
210
409
  const result = await applyRuntimeInjections(runMessages, {
211
- unifiedTurnContext: "<turn_context>\nsynthesized\n</turn_context>",
410
+ conversationId: FALLBACK_CONVERSATION_ID,
212
411
  });
213
412
 
214
413
  // The unified-turn-context injector fires even without a caller-supplied
215
414
  // turnContext, proving the chain runs under the synthesized context.
216
- expect(result.blocks.unifiedTurnContext).toBe(
217
- "<turn_context>\nsynthesized\n</turn_context>",
218
- );
415
+ expect(result.blocks.unifiedTurnContext).toBe(synthesizedBlock);
219
416
  });
220
417
 
221
418
  test("golden-path: default chain injects workspace + unified-turn + PKB + NOW + subagent in the correct positions", async () => {
@@ -248,16 +445,21 @@ describe("injector chain", () => {
248
445
 
249
446
  const workspaceText =
250
447
  "<workspace>\nRoot: /sandbox\nDirectories: src, lib\n</workspace>";
251
- const unifiedTurn =
252
- "<turn_context>\ncurrent_time: 2026-04-22\ninterface: macos\n</turn_context>";
253
- const subagentBlock =
254
- '<active_subagents>\n- [running] "worker" (sub-1) | elapsed: 5s\n</active_subagents>';
448
+ // The interface label flows through the options bag; the timestamp is
449
+ // computed live at injection time.
450
+ const unifiedTurn = buildUnifiedTurnContextBlock({
451
+ timestamp: FIXED_TURN_TIMESTAMP,
452
+ interfaceName: "macos",
453
+ });
454
+ // A completed child renders deterministically (no elapsed clock), so the
455
+ // block the injector self-resolves matches `buildSubagentStatusBlock`.
456
+ const subagentChild = makeSubagentState("sub-1", "worker", "completed");
457
+ seedSubagentChild(TEST_CONVERSATION_ID, subagentChild);
458
+ const subagentBlock = buildSubagentStatusBlock([subagentChild])!;
255
459
 
460
+ seedWorkspaceContext(workspaceText, { clientTimezone: null }, "macos");
256
461
  const result = await applyRuntimeInjections(runMessages, {
257
- turnContext: makeTurnContext(),
258
- workspaceTopLevelContext: workspaceText,
259
- unifiedTurnContext: unifiedTurn,
260
- subagentStatusBlock: subagentBlock,
462
+ ...makeTurnContext(),
261
463
  });
262
464
 
263
465
  // Extract the tail user message content as a list of text strings.
@@ -295,13 +497,12 @@ describe("injector chain", () => {
295
497
  );
296
498
  });
297
499
 
298
- test("slack-messages injector replaces runMessages when a chronological transcript is provided", async () => {
299
- // End-to-end verification for the `replace-run-messages` placement:
300
- // a Slack channel turn with a pre-rendered chronological transcript
301
- // swaps the incoming `runMessages` for the transcript before the
302
- // after-memory/append placements run. Memory-prefix blocks from the
303
- // original tail are re-prepended onto the new tail so PKB / NOW
304
- // splices still find them.
500
+ test("slack-messages injector replaces runMessages with the self-resolved transcript", async () => {
501
+ // End-to-end verification for the `replace-run-messages` placement: a
502
+ // Slack channel turn swaps the incoming `runMessages` for the
503
+ // self-resolved chronological transcript before the after-memory/append
504
+ // placements run. Memory-prefix blocks from the original tail are
505
+ // re-prepended onto the new tail so PKB / NOW splices still find them.
305
506
  const originalRun: Message[] = [
306
507
  {
307
508
  role: "user",
@@ -316,19 +517,30 @@ describe("injector chain", () => {
316
517
  ],
317
518
  },
318
519
  ];
319
- const slackTranscript: Message[] = [
520
+ seedSlackChannelRows(TEST_CONVERSATION_ID, [
320
521
  {
522
+ id: "s1",
321
523
  role: "user",
322
- content: [{ type: "text", text: "[12:00 alice]: kickoff" }],
524
+ text: "kickoff",
525
+ channelTs: "1700000000.000001",
526
+ displayName: "alice",
527
+ createdAt: 1700000000_000,
323
528
  },
324
529
  {
530
+ id: "s2",
325
531
  role: "user",
326
- content: [{ type: "text", text: "[12:05 @user]: What's happening?" }],
532
+ text: "What's happening?",
533
+ channelTs: "1700000005.000001",
534
+ displayName: "user",
535
+ createdAt: 1700000005_000,
327
536
  },
328
- ];
329
-
330
- const result = await applyRuntimeInjections(originalRun, {
331
- turnContext: makeTurnContext(),
537
+ ]);
538
+ setConversation(TEST_CONVERSATION_ID, {
539
+ conversationId: TEST_CONVERSATION_ID,
540
+ workingDir: "/sandbox",
541
+ workspaceTopLevelContext: "",
542
+ workspaceTopLevelDirty: false,
543
+ trustContext: { trustClass: "guardian" },
332
544
  channelCapabilities: {
333
545
  channel: "slack",
334
546
  dashboardCapable: false,
@@ -336,7 +548,9 @@ describe("injector chain", () => {
336
548
  supportsVoiceInput: false,
337
549
  chatType: "channel",
338
550
  },
339
- slackChronologicalMessages: slackTranscript,
551
+ } as never);
552
+ const result = await applyRuntimeInjections(originalRun, {
553
+ ...makeTurnContext(),
340
554
  });
341
555
 
342
556
  // The swap replaced the run-messages wholesale but preserved the
@@ -354,7 +568,7 @@ describe("injector chain", () => {
354
568
  true,
355
569
  );
356
570
  expect(texts).toContain("<memory __injected>\nrecalled fact\n</memory>");
357
- expect(texts[texts.length - 1]).toBe("[12:05 @user]: What's happening?");
571
+ expect(texts[texts.length - 1]).toContain("What's happening?");
358
572
  });
359
573
 
360
574
  test("minimal mode: only unified-turn-context survives; workspace/PKB/NOW/subagent are skipped", async () => {
@@ -363,6 +577,21 @@ describe("injector chain", () => {
363
577
  // opts out in minimal mode, so the tail should carry only the turn
364
578
  // context prepend plus any non-injector hardcoded content (none
365
579
  // here).
580
+ // Empty workspace text keeps that injector inert while the unified
581
+ // turn-context timestamp flows through the conversation's frozen temporal
582
+ // snapshot. The interface label is sourced from the live conversation,
583
+ // which has no per-turn or origin interface here and so resolves to the
584
+ // `web` default. A live child subagent is seeded so the subagent-status
585
+ // injector has a block to skip.
586
+ const minimalTurnBlock = buildUnifiedTurnContextBlock({
587
+ timestamp: FIXED_TURN_TIMESTAMP,
588
+ interfaceName: "web",
589
+ });
590
+ seedWorkspaceContext("", { clientTimezone: null });
591
+ seedSubagentChild(
592
+ TEST_CONVERSATION_ID,
593
+ makeSubagentState("sub-1", "worker", "running"),
594
+ );
366
595
  const result = await applyRuntimeInjections(
367
596
  [
368
597
  {
@@ -371,11 +600,8 @@ describe("injector chain", () => {
371
600
  },
372
601
  ],
373
602
  {
374
- turnContext: makeTurnContext(),
603
+ ...makeTurnContext(),
375
604
  mode: "minimal",
376
- workspaceTopLevelContext: "<workspace>...</workspace>",
377
- unifiedTurnContext: "<turn_context>...</turn_context>",
378
- subagentStatusBlock: "<active_subagents>...</active_subagents>",
379
605
  },
380
606
  );
381
607
 
@@ -384,10 +610,8 @@ describe("injector chain", () => {
384
610
  .filter((b): b is { type: "text"; text: string } => b.type === "text")
385
611
  .map((b) => b.text);
386
612
 
387
- expect(texts).toEqual(["<turn_context>...</turn_context>", "hi"]);
388
- expect(result.blocks.unifiedTurnContext).toBe(
389
- "<turn_context>...</turn_context>",
390
- );
613
+ expect(texts).toEqual([minimalTurnBlock, "hi"]);
614
+ expect(result.blocks.unifiedTurnContext).toBe(minimalTurnBlock);
391
615
  expect(result.blocks.workspaceBlock).toBeUndefined();
392
616
  expect(result.blocks.pkbContextBlock).toBeUndefined();
393
617
  expect(result.blocks.nowScratchpadBlock).toBeUndefined();