@vellumai/assistant 0.8.7 → 0.8.8-dev.202606052332.17fc8ea

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 (570) hide show
  1. package/Dockerfile +20 -4
  2. package/bun.lock +2 -2
  3. package/docker-entrypoint.sh +4 -2
  4. package/docker-init-apt-root.sh +3 -1
  5. package/docker-kata-apt-env.sh +3 -1
  6. package/docker-kata-runtime-family.sh +12 -0
  7. package/docs/architecture/memory.md +1 -1
  8. package/examples/plugins/echo/README.md +61 -66
  9. package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
  10. package/examples/plugins/echo/hooks/stop.ts +16 -0
  11. package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
  12. package/examples/plugins/echo/package.json +1 -2
  13. package/examples/plugins/echo/src/emit.ts +19 -0
  14. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
  15. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
  16. package/openapi.yaml +3378 -335
  17. package/package.json +2 -2
  18. package/scripts/generate-openapi.ts +68 -41
  19. package/src/__tests__/agent-loop-exit-reason.test.ts +35 -93
  20. package/src/__tests__/agent-loop-provider-error-recording.test.ts +1 -1
  21. package/src/__tests__/agent-loop.test.ts +37 -87
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
  23. package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
  24. package/src/__tests__/annotate-risk-options.test.ts +2 -3
  25. package/src/__tests__/anthropic-provider.test.ts +95 -2
  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__/approval-routes-http.test.ts +4 -1
  29. package/src/__tests__/assistant-event-hub.test.ts +25 -0
  30. package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
  31. package/src/__tests__/{conversation-stream-state.test.ts → assistant-stream-state.test.ts} +252 -91
  32. package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
  33. package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
  34. package/src/__tests__/btw-routes.test.ts +62 -3
  35. package/src/__tests__/build-persisted-content.test.ts +184 -0
  36. package/src/__tests__/catalog-files.test.ts +1 -1
  37. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  38. package/src/__tests__/channel-approvals.test.ts +1 -1
  39. package/src/__tests__/clawhub-files.test.ts +1 -1
  40. package/src/__tests__/compaction-circuit.test.ts +258 -0
  41. package/src/__tests__/compaction-direct.test.ts +132 -0
  42. package/src/__tests__/compaction.benchmark.test.ts +0 -30
  43. package/src/__tests__/config-watcher.test.ts +1 -1
  44. package/src/__tests__/conversation-abort-tool-results.test.ts +57 -19
  45. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +6 -5
  46. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -7
  47. package/src/__tests__/conversation-agent-loop-overflow.test.ts +316 -1143
  48. package/src/__tests__/conversation-agent-loop.test.ts +638 -1655
  49. package/src/__tests__/conversation-analysis-routes.test.ts +6 -0
  50. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  51. package/src/__tests__/conversation-history-web-search.test.ts +11 -1
  52. package/src/__tests__/conversation-pairing.test.ts +4 -31
  53. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +6 -0
  54. package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -10
  55. package/src/__tests__/conversation-queue.test.ts +2 -0
  56. package/src/__tests__/conversation-routes-disk-view.test.ts +3 -0
  57. package/src/__tests__/conversation-routes-slash-commands.test.ts +6 -5
  58. package/src/__tests__/conversation-runtime-assembly.test.ts +310 -300
  59. package/src/__tests__/conversation-runtime-workspace.test.ts +105 -45
  60. package/src/__tests__/conversation-slash-commands.test.ts +8 -42
  61. package/src/__tests__/conversation-slash-queue.test.ts +6 -1
  62. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  63. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +84 -0
  64. package/src/__tests__/conversation-sync-tags.test.ts +27 -15
  65. package/src/__tests__/conversation-title-service.test.ts +135 -2
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +17 -16
  67. package/src/__tests__/conversation-workspace-injection.test.ts +67 -2
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +7 -6
  69. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  70. package/src/__tests__/cross-provider-web-search.test.ts +214 -1
  71. package/src/__tests__/db-acp-history.test.ts +101 -0
  72. package/src/__tests__/db-schedule-syntax-migration.test.ts +5 -0
  73. package/src/__tests__/dm-persistence.test.ts +5 -1
  74. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  75. package/src/__tests__/empty-response-hook.test.ts +304 -0
  76. package/src/__tests__/feature-flag-test-helpers.ts +2 -2
  77. package/src/__tests__/file-write-tool.test.ts +63 -0
  78. package/src/__tests__/gateway-only-guard.test.ts +12 -2
  79. package/src/__tests__/gemini-image-service.test.ts +13 -0
  80. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  81. package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
  82. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  83. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  84. package/src/__tests__/heartbeat-service.test.ts +1 -0
  85. package/src/__tests__/helpers/mock-provider.ts +110 -0
  86. package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
  87. package/src/__tests__/history-repair-hook.test.ts +1 -0
  88. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  89. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  90. package/src/__tests__/identity-intro-cache.test.ts +12 -100
  91. package/src/__tests__/identity-routes.test.ts +248 -7
  92. package/src/__tests__/inbound-slack-persistence.test.ts +5 -1
  93. package/src/__tests__/injector-background-turn.test.ts +3 -9
  94. package/src/__tests__/injector-chain.test.ts +139 -275
  95. package/src/__tests__/injector-disk-pressure.test.ts +75 -41
  96. package/src/__tests__/injector-document-comments.test.ts +3 -3
  97. package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
  98. package/src/__tests__/injector-v3-suppression.test.ts +31 -37
  99. package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
  100. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  101. package/src/__tests__/list-messages-page-latest.test.ts +60 -0
  102. package/src/__tests__/list-messages-tool-merge.test.ts +20 -0
  103. package/src/__tests__/llm-usage-store.test.ts +223 -1
  104. package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
  105. package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
  106. package/src/__tests__/native-web-search.test.ts +191 -0
  107. package/src/__tests__/onboarding-template-contract.test.ts +2 -0
  108. package/src/__tests__/openai-image-service.test.ts +17 -0
  109. package/src/__tests__/openai-provider.test.ts +31 -1
  110. package/src/__tests__/{overflow-reduce-pipeline.test.ts → overflow-reduction-loop.test.ts} +64 -284
  111. package/src/__tests__/persist-unsendable-image.test.ts +215 -0
  112. package/src/__tests__/persistence-secret-redaction.test.ts +1 -0
  113. package/src/__tests__/pkb-autoinject.test.ts +2 -5
  114. package/src/__tests__/plugin-api-shim.test.ts +3 -6
  115. package/src/__tests__/plugin-bootstrap.test.ts +14 -40
  116. package/src/__tests__/plugin-registry.test.ts +3 -76
  117. package/src/__tests__/plugin-types.test.ts +0 -193
  118. package/src/__tests__/process-message-display-content.test.ts +6 -2
  119. package/src/__tests__/reaction-persistence.test.ts +1 -1
  120. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
  121. package/src/__tests__/resolve-trust-class.test.ts +4 -4
  122. package/src/__tests__/runtime-events-sse-reconnect.test.ts +60 -23
  123. package/src/__tests__/schedule-routes.test.ts +603 -2
  124. package/src/__tests__/schedule-store.test.ts +41 -0
  125. package/src/__tests__/schedule-tools.test.ts +35 -0
  126. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  127. package/src/__tests__/server-history-render.test.ts +314 -1
  128. package/src/__tests__/skill-feature-flags-integration.test.ts +33 -0
  129. package/src/__tests__/skillssh-files.test.ts +1 -1
  130. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  131. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  132. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  133. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  134. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  135. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  136. package/src/__tests__/system-prompt.test.ts +20 -0
  137. package/src/__tests__/task-scheduler.test.ts +162 -1
  138. package/src/__tests__/terminal-tools.test.ts +6 -1
  139. package/src/__tests__/title-generate-hook.test.ts +319 -0
  140. package/src/__tests__/tool-error-hook.test.ts +278 -0
  141. package/src/__tests__/tool-preview-lifecycle.test.ts +468 -5
  142. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  143. package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
  144. package/src/__tests__/tool-result-truncation.test.ts +0 -2
  145. package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
  146. package/src/__tests__/ui-work-result-surface.test.ts +159 -0
  147. package/src/__tests__/usage-routes.test.ts +285 -1
  148. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  149. package/src/__tests__/voice-session-bridge.test.ts +6 -3
  150. package/src/__tests__/web-search-backend-failure.test.ts +166 -0
  151. package/src/acp/__tests__/agent-process.test.ts +161 -0
  152. package/src/acp/__tests__/client-handler.test.ts +40 -0
  153. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  154. package/src/acp/__tests__/helpers/exec-file-stub.ts +101 -0
  155. package/src/acp/__tests__/prepare-agent-env.test.ts +137 -0
  156. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  157. package/src/acp/__tests__/session-manager-resume.test.ts +736 -0
  158. package/src/acp/agent-process.ts +61 -1
  159. package/src/acp/auto-install.test.ts +196 -0
  160. package/src/acp/auto-install.ts +177 -0
  161. package/src/acp/client-handler.ts +31 -0
  162. package/src/acp/feature-gate.test.ts +48 -0
  163. package/src/acp/feature-gate.ts +34 -0
  164. package/src/acp/prepare-agent-env.ts +83 -29
  165. package/src/acp/resolve-agent.test.ts +320 -7
  166. package/src/acp/resolve-agent.ts +182 -18
  167. package/src/acp/resume-hint.ts +25 -0
  168. package/src/acp/session-manager.ts +495 -73
  169. package/src/acp/types.ts +8 -0
  170. package/src/agent/compaction-circuit.ts +60 -102
  171. package/src/agent/loop.ts +362 -485
  172. package/src/api/events/assistant-thinking-delta.ts +33 -0
  173. package/src/api/events/tool-output-chunk.ts +45 -0
  174. package/src/api/events/tool-use-preview-start.ts +32 -0
  175. package/src/api/events/trace-event.ts +69 -0
  176. package/src/api/index.ts +48 -13
  177. package/src/api/responses/conversation-message.ts +374 -0
  178. package/src/approvals/guardian-request-resolvers.ts +1 -1
  179. package/src/avatar/__tests__/avatar-store.test.ts +34 -29
  180. package/src/background-wake/next-wake.ts +1 -0
  181. package/src/cli/commands/__tests__/notifications.test.ts +58 -14
  182. package/src/cli/commands/notifications.ts +112 -60
  183. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  184. package/src/config/acp-defaults.test.ts +10 -0
  185. package/src/config/acp-defaults.ts +6 -0
  186. package/src/config/assistant-feature-flags.ts +22 -11
  187. package/src/config/bundled-skills/acp/SKILL.md +83 -31
  188. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  189. package/src/config/bundled-skills/app-builder/SKILL.md +224 -398
  190. package/src/config/bundled-skills/app-builder/TOOLS.json +29 -0
  191. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  192. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  193. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  194. package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
  195. package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
  196. package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
  197. package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
  198. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  199. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  200. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  201. package/src/config/bundled-skills/messaging/SKILL.md +0 -7
  202. package/src/config/bundled-tool-registry.ts +2 -0
  203. package/src/config/feature-flag-cache.ts +3 -3
  204. package/src/config/feature-flag-registry.json +48 -7
  205. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  206. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
  207. package/src/config/schemas/heartbeat.ts +9 -0
  208. package/src/config/schemas/llm.ts +1 -0
  209. package/src/config/schemas/memory-v2.ts +8 -0
  210. package/src/config/schemas/memory-v3.ts +8 -0
  211. package/src/config/schemas/platform.ts +8 -0
  212. package/src/config/seed-inference-profiles.ts +2 -2
  213. package/src/config/skills.ts +13 -0
  214. package/src/context/compactor.ts +1 -1
  215. package/src/context/strip-injections.ts +128 -0
  216. package/src/context/token-estimator.ts +23 -0
  217. package/src/context/tool-result-truncation.ts +0 -23
  218. package/src/context/window-manager.ts +5 -7
  219. package/src/credential-execution/executable-discovery.ts +16 -0
  220. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
  221. package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
  222. package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
  223. package/src/daemon/assistant-attachments.ts +1 -1
  224. package/src/daemon/config-watcher.ts +2 -2
  225. package/src/daemon/context-overflow-reducer.ts +0 -1
  226. package/src/daemon/conversation-agent-loop-handlers.ts +594 -153
  227. package/src/daemon/conversation-agent-loop.ts +301 -997
  228. package/src/daemon/conversation-history.ts +5 -4
  229. package/src/daemon/conversation-lifecycle.ts +3 -4
  230. package/src/daemon/conversation-messaging.ts +7 -6
  231. package/src/daemon/conversation-process.ts +11 -16
  232. package/src/daemon/conversation-registry.ts +159 -0
  233. package/src/daemon/conversation-runtime-assembly.ts +218 -398
  234. package/src/daemon/conversation-slash.ts +6 -25
  235. package/src/daemon/conversation-store.ts +9 -90
  236. package/src/daemon/conversation-surfaces.ts +222 -4
  237. package/src/daemon/conversation-tool-setup.ts +2 -29
  238. package/src/daemon/conversation-workspace.ts +17 -0
  239. package/src/daemon/conversation.ts +32 -20
  240. package/src/daemon/external-plugins-bootstrap.ts +17 -18
  241. package/src/daemon/handlers/config-a2a.ts +51 -36
  242. package/src/daemon/handlers/config-slack-channel.ts +20 -14
  243. package/src/daemon/handlers/config-telegram.ts +16 -2
  244. package/src/daemon/handlers/conversations.ts +3 -1
  245. package/src/daemon/handlers/shared.ts +156 -84
  246. package/src/daemon/handlers/skills.ts +42 -10
  247. package/src/daemon/lifecycle.ts +25 -0
  248. package/src/daemon/message-types/apps.ts +1 -29
  249. package/src/daemon/message-types/messages.ts +9 -57
  250. package/src/daemon/message-types/skills.ts +2 -0
  251. package/src/daemon/message-types/surfaces.ts +136 -3
  252. package/src/daemon/now-scratchpad.ts +21 -0
  253. package/src/daemon/orphan-reaper.test.ts +210 -0
  254. package/src/daemon/orphan-reaper.ts +240 -0
  255. package/src/daemon/overflow-reduction-loop.ts +230 -0
  256. package/src/daemon/persist-unsendable-image.ts +117 -0
  257. package/src/daemon/process-message.ts +1 -3
  258. package/src/daemon/server.ts +2 -0
  259. package/src/daemon/trace-emitter.ts +6 -4
  260. package/src/daemon/trust-context.ts +19 -0
  261. package/src/daemon/wake-target-adapter.ts +3 -1
  262. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  263. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  264. package/src/heartbeat/heartbeat-service.ts +26 -0
  265. package/src/home/home-greeting-cache.ts +24 -1
  266. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  267. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  268. package/src/ipc/gateway-client.test.ts +2 -2
  269. package/src/ipc/gateway-client.ts +3 -3
  270. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  271. package/src/ipc/skill-routes/memory.ts +4 -2
  272. package/src/media/gemini-image-service.ts +15 -0
  273. package/src/media/openai-image-service.ts +14 -0
  274. package/src/media/types.ts +34 -0
  275. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
  276. package/src/memory/auth-fallback-events-store.ts +94 -0
  277. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  278. package/src/memory/conversation-title-service.ts +65 -41
  279. package/src/memory/db-init.ts +6 -0
  280. package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
  281. package/src/memory/graph/conversation-graph-memory.ts +65 -0
  282. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  283. package/src/memory/jobs-store.ts +33 -0
  284. package/src/memory/jobs-worker.ts +32 -5
  285. package/src/memory/llm-usage-store.ts +224 -50
  286. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
  287. package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
  288. package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
  289. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  290. package/src/memory/migrations/index.ts +3 -0
  291. package/src/memory/pkb/autoinject.ts +61 -0
  292. package/src/memory/pkb/context.ts +50 -0
  293. package/src/memory/pkb/types.ts +14 -0
  294. package/src/memory/schedule-attribution-sql.ts +104 -0
  295. package/src/memory/schema/acp.ts +4 -0
  296. package/src/memory/schema/infrastructure.ts +16 -0
  297. package/src/memory/usage-grouped-buckets.ts +6 -1
  298. package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -4
  299. package/src/memory/v2/consolidation-job.ts +14 -5
  300. package/src/notifications/conversation-pairing.ts +8 -15
  301. package/src/notifications/decision-engine.ts +6 -3
  302. package/src/notifications/home-feed-side-effect.ts +12 -1
  303. package/src/permissions/prompter.ts +4 -0
  304. package/src/plugin-api/constants.ts +4 -0
  305. package/src/plugin-api/index.ts +7 -5
  306. package/src/plugin-api/types.ts +151 -1
  307. package/src/plugins/defaults/compaction/compact.ts +59 -0
  308. package/src/plugins/defaults/compaction/package.json +1 -1
  309. package/src/plugins/defaults/compaction/register.ts +8 -19
  310. package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
  311. package/src/plugins/defaults/empty-response/register.ts +8 -13
  312. package/src/plugins/defaults/index.ts +2 -18
  313. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +95 -0
  314. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
  315. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
  316. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +288 -81
  317. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/assign.test.ts +4 -4
  318. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/health.test.ts +16 -0
  319. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +4 -4
  320. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/maintain-job.test.ts +5 -5
  321. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/orchestrate.test.ts +48 -12
  322. package/src/plugins/defaults/memory-v3-shadow/__tests__/provider-blocks.test.ts +13 -0
  323. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/reconcile.test.ts +2 -2
  324. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/render-injection.test.ts +1 -1
  325. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/router.test.ts +104 -32
  326. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +8 -8
  327. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selector.test.ts +96 -30
  328. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/shadow-plugin.test.ts +34 -16
  329. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/assign.ts +5 -5
  330. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/capabilities.ts +2 -2
  331. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/health.ts +0 -0
  332. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  333. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  334. package/src/plugins/defaults/memory-v3-shadow/injector.ts +75 -0
  335. package/src/plugins/defaults/memory-v3-shadow/llm-retry.ts +32 -0
  336. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/maintain-job.ts +8 -8
  337. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/orchestrate.ts +26 -14
  338. package/src/plugins/defaults/{llm-call → memory-v3-shadow}/package.json +2 -2
  339. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/page-content.ts +2 -2
  340. package/src/plugins/defaults/memory-v3-shadow/provider-blocks.ts +26 -0
  341. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/reconcile.ts +3 -3
  342. package/src/plugins/defaults/memory-v3-shadow/register.ts +26 -0
  343. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +1 -1
  344. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/router.ts +51 -45
  345. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selection-log-store.ts +4 -4
  346. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selector.ts +61 -46
  347. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/shadow-plugin.ts +69 -99
  348. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/tree.ts +1 -1
  349. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/types.ts +8 -0
  350. package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
  351. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
  352. package/src/plugins/defaults/title-generate/package.json +1 -1
  353. package/src/plugins/defaults/title-generate/register.ts +18 -18
  354. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
  355. package/src/plugins/defaults/tool-error/package.json +1 -1
  356. package/src/plugins/defaults/tool-error/register.ts +9 -21
  357. package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
  358. package/src/plugins/defaults/tool-result-truncate/register.ts +10 -21
  359. package/src/plugins/defaults/tool-result-truncate/terminal.ts +37 -18
  360. package/src/plugins/external-api.ts +2 -2
  361. package/src/plugins/pipeline.ts +6 -305
  362. package/src/plugins/registry.ts +10 -55
  363. package/src/plugins/types.ts +62 -797
  364. package/src/plugins/user-loader.ts +30 -127
  365. package/src/proactive-artifact/aux-message-injector.ts +4 -4
  366. package/src/proactive-artifact/job.test.ts +8 -13
  367. package/src/prompts/__tests__/system-prompt.test.ts +42 -0
  368. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +64 -0
  369. package/src/prompts/templates/BOOTSTRAP.md +2 -2
  370. package/src/prompts/templates/system-sections.ts +15 -0
  371. package/src/providers/anthropic/client.ts +37 -29
  372. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -0
  373. package/src/providers/openai/chat-completions-provider.ts +44 -0
  374. package/src/providers/openrouter/client.ts +1 -0
  375. package/src/providers/placeholder-sentinels.ts +35 -0
  376. package/src/runtime/__tests__/agent-wake.test.ts +10 -6
  377. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  378. package/src/runtime/agent-wake.ts +2 -5
  379. package/src/runtime/assistant-event-hub.ts +37 -7
  380. package/src/runtime/{conversation-stream-state.ts → assistant-stream-state.ts} +132 -58
  381. package/src/runtime/channel-approvals.ts +1 -1
  382. package/src/runtime/http-router.ts +16 -21
  383. package/src/runtime/http-types.ts +16 -70
  384. package/src/runtime/interactive-ui.ts +1 -1
  385. package/src/runtime/pending-interactions.ts +1 -0
  386. package/src/runtime/routes/__tests__/acp-routes.test.ts +283 -55
  387. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
  388. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  389. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
  390. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
  391. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  392. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  393. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  394. package/src/runtime/routes/acp-routes.test.ts +89 -25
  395. package/src/runtime/routes/acp-routes.ts +81 -29
  396. package/src/runtime/routes/app-management-routes.ts +6 -117
  397. package/src/runtime/routes/app-routes.ts +13 -15
  398. package/src/runtime/routes/approval-routes.ts +1 -1
  399. package/src/runtime/routes/attachment-routes.ts +26 -15
  400. package/src/runtime/routes/avatar-routes.ts +26 -0
  401. package/src/runtime/routes/browser-routes.ts +1 -1
  402. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  403. package/src/runtime/routes/btw-routes.ts +29 -23
  404. package/src/runtime/routes/consolidation-routes.ts +120 -20
  405. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  406. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  407. package/src/runtime/routes/conversation-query-routes.ts +3 -1
  408. package/src/runtime/routes/conversation-routes.ts +372 -185
  409. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  410. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  411. package/src/runtime/routes/documents-routes.ts +4 -0
  412. package/src/runtime/routes/domain-routes.ts +51 -37
  413. package/src/runtime/routes/epoch-millis-range.ts +34 -0
  414. package/src/runtime/routes/events-routes.ts +28 -34
  415. package/src/runtime/routes/gateway-log-routes.ts +26 -4
  416. package/src/runtime/routes/heartbeat-routes.ts +32 -12
  417. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  418. package/src/runtime/routes/host-cu-routes.ts +1 -1
  419. package/src/runtime/routes/identity-intro-cache.ts +11 -34
  420. package/src/runtime/routes/identity-routes.ts +224 -18
  421. package/src/runtime/routes/image-generation-routes.ts +40 -2
  422. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  423. package/src/runtime/routes/index.ts +2 -0
  424. package/src/runtime/routes/integrations/a2a.ts +12 -10
  425. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
  426. package/src/runtime/routes/integrations/slack/channel.ts +4 -0
  427. package/src/runtime/routes/integrations/slack/share.ts +27 -6
  428. package/src/runtime/routes/integrations/telegram.ts +6 -0
  429. package/src/runtime/routes/integrations/twilio.ts +42 -0
  430. package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
  431. package/src/runtime/routes/log-export-routes.ts +8 -0
  432. package/src/runtime/routes/memory-v2-routes.ts +15 -8
  433. package/src/runtime/routes/memory-v3-routes.ts +66 -34
  434. package/src/runtime/routes/oauth-apps.ts +66 -12
  435. package/src/runtime/routes/oauth-providers.ts +44 -5
  436. package/src/runtime/routes/platform-routes.ts +81 -5
  437. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +6 -4
  438. package/src/runtime/routes/playground/force-compact.ts +1 -1
  439. package/src/runtime/routes/playground/helpers.ts +1 -1
  440. package/src/runtime/routes/rename-conversation-routes.ts +5 -0
  441. package/src/runtime/routes/schedule-routes.ts +152 -42
  442. package/src/runtime/routes/secret-routes.ts +14 -2
  443. package/src/runtime/routes/skills-routes.ts +43 -14
  444. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  445. package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
  446. package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
  447. package/src/runtime/routes/trust-rules-routes.ts +26 -2
  448. package/src/runtime/routes/tts-routes.ts +35 -0
  449. package/src/runtime/routes/types.ts +66 -8
  450. package/src/runtime/routes/usage-routes.ts +47 -39
  451. package/src/runtime/routes/webhook-routes.ts +41 -2
  452. package/src/runtime/routes/work-items-routes.ts +2 -4
  453. package/src/runtime/routes/workspace-routes.ts +4 -0
  454. package/src/runtime/services/__tests__/analyze-conversation.test.ts +6 -0
  455. package/src/runtime/services/analyze-conversation.ts +2 -2
  456. package/src/runtime/services/conversation-serializer.ts +1 -1
  457. package/src/schedule/schedule-store.ts +20 -1
  458. package/src/schedule/schedule-usage-store.ts +83 -0
  459. package/src/schedule/scheduler.ts +12 -5
  460. package/src/signals/cancel.ts +2 -4
  461. package/src/skills/catalog-files.ts +2 -2
  462. package/src/skills/catalog-install.ts +3 -0
  463. package/src/skills/categories-cache.ts +118 -0
  464. package/src/skills/clawhub-files.ts +1 -2
  465. package/src/skills/skillssh-files.ts +1 -2
  466. package/src/subagent/manager.ts +17 -5
  467. package/src/telemetry/types.ts +29 -1
  468. package/src/telemetry/usage-telemetry-reporter.test.ts +112 -3
  469. package/src/telemetry/usage-telemetry-reporter.ts +57 -2
  470. package/src/tools/acp/context.ts +20 -0
  471. package/src/tools/acp/list-agents.test.ts +7 -1
  472. package/src/tools/acp/spawn.test.ts +158 -55
  473. package/src/tools/acp/spawn.ts +47 -72
  474. package/src/tools/acp/steer.test.ts +105 -8
  475. package/src/tools/acp/steer.ts +48 -17
  476. package/src/tools/apps/executors.ts +13 -8
  477. package/src/tools/executor.ts +1 -53
  478. package/src/tools/filesystem/write.ts +34 -0
  479. package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
  480. package/src/tools/network/__tests__/web-search.test.ts +11 -3
  481. package/src/tools/network/web-search-error.test.ts +248 -0
  482. package/src/tools/network/web-search-error.ts +267 -0
  483. package/src/tools/network/web-search.ts +207 -48
  484. package/src/tools/schedule/create.ts +2 -0
  485. package/src/tools/subagent/spawn.ts +2 -4
  486. package/src/tools/terminal/safe-env.ts +10 -1
  487. package/src/tools/ui-surface/definitions.ts +34 -5
  488. package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
  489. package/src/tts/provider-catalog.ts +76 -1
  490. package/src/util/mutex.ts +47 -0
  491. package/src/workspace/git-service.ts +1 -42
  492. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  493. package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
  494. package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
  495. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +117 -0
  496. package/src/workspace/migrations/registry.ts +6 -0
  497. package/docs/plugins.md +0 -836
  498. package/examples/plugins/echo/register.ts +0 -184
  499. package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
  500. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  501. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  502. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  503. package/src/__tests__/empty-response-pipeline.test.ts +0 -423
  504. package/src/__tests__/llm-call-pipeline.test.ts +0 -287
  505. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
  506. package/src/__tests__/persistence-pipeline.test.ts +0 -503
  507. package/src/__tests__/pipeline-runner.test.ts +0 -564
  508. package/src/__tests__/title-generate-pipeline.test.ts +0 -211
  509. package/src/__tests__/token-estimate-pipeline.test.ts +0 -479
  510. package/src/__tests__/tool-error-pipeline.test.ts +0 -241
  511. package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
  512. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -341
  513. package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
  514. package/src/gallery/default-gallery.ts +0 -1359
  515. package/src/gallery/gallery-manifest.ts +0 -28
  516. package/src/home/feature-gate.ts +0 -22
  517. package/src/memory/v3/provider-blocks.ts +0 -16
  518. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  519. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  520. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  521. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  522. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  523. package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +0 -22
  524. package/src/plugins/defaults/empty-response/terminal.ts +0 -106
  525. package/src/plugins/defaults/injectors/package.json +0 -15
  526. package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +0 -17
  527. package/src/plugins/defaults/llm-call/register.ts +0 -45
  528. package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +0 -17
  529. package/src/plugins/defaults/memory-retrieval/package.json +0 -15
  530. package/src/plugins/defaults/memory-retrieval/register.ts +0 -181
  531. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  532. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  533. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  534. package/src/plugins/defaults/persistence/middlewares/persistence.ts +0 -19
  535. package/src/plugins/defaults/persistence/package.json +0 -15
  536. package/src/plugins/defaults/persistence/register.ts +0 -38
  537. package/src/plugins/defaults/persistence/terminal.ts +0 -83
  538. package/src/plugins/defaults/title-generate/terminal.ts +0 -31
  539. package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +0 -23
  540. package/src/plugins/defaults/token-estimate/package.json +0 -15
  541. package/src/plugins/defaults/token-estimate/register.ts +0 -34
  542. package/src/plugins/defaults/token-estimate/terminal.ts +0 -40
  543. package/src/plugins/defaults/tool-error/middlewares/toolError.ts +0 -21
  544. package/src/plugins/defaults/tool-error/terminal.ts +0 -47
  545. package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +0 -23
  546. package/src/plugins/defaults/tool-execute/package.json +0 -15
  547. package/src/plugins/defaults/tool-execute/register.ts +0 -49
  548. package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +0 -23
  549. package/src/plugins/defaults/tool-result-truncate/types.ts +0 -22
  550. package/src/skills/category-inference.ts +0 -111
  551. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/capabilities.test.ts +0 -0
  552. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/core.test.ts +0 -0
  553. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  554. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  555. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/needle.test.ts +0 -0
  556. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/snapshot.test.ts +0 -0
  557. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/tree.test.ts +0 -0
  558. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +0 -0
  559. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  560. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  561. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/core.ts +0 -0
  562. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  563. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  564. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  565. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  566. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  567. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  568. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/needle.ts +0 -0
  569. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/snapshot.ts +0 -0
  570. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +0 -0
@@ -1,55 +1,29 @@
1
1
  /**
2
2
  * Plugin core types.
3
3
  *
4
- * This file is scaffolding only it defines the shape of the plugin system
5
- * without wiring any behavior. Later PRs in the `agent-plugin-system` plan
6
- * refine per-pipeline argument/result types (currently `unknown`-based
7
- * placeholders) and add the pipeline runner, registry, and bootstrap.
8
- *
9
- * The assistant composes behavior around a small set of named pipelines
10
- * (`turn`, `llmCall`, `toolExecute`, ...). Each plugin may contribute one
11
- * {@link Middleware} per pipeline; the registry composes them in onion
12
- * order at runtime. Plugins may also contribute {@link Injector}s that emit
13
- * system-prompt-time content, as well as model-visible capabilities
14
- * (`tools`, `routes`, `skills`).
4
+ * A plugin may contribute lifecycle hooks ({@link PluginHooks}) that the
5
+ * runtime invokes at named events, and model-visible capabilities (`tools`,
6
+ * `routes`, `skills`). The registry tracks every registered plugin in
7
+ * registration order.
15
8
  *
16
9
  * Design doc: `.private/plans/agent-plugin-system.md`.
17
10
  */
18
11
 
19
12
  import type { CompactionCircuitClosedEvent } from "../api/events/compaction-circuit-closed.js";
20
13
  import type { CompactionCircuitOpenEvent } from "../api/events/compaction-circuit-open.js";
21
- import type { ContextWindowConfig } from "../config/schemas/inference.js";
22
- import type {
23
- ContextWindowManager,
24
- ContextWindowResult,
25
- } from "../context/window-manager.js";
26
- import type { ReducerState } from "../daemon/context-overflow-reducer.js";
14
+ import type { LLMCallSite } from "../config/schemas/llm.js";
15
+ import type { ContextWindowManager } from "../context/window-manager.js";
27
16
  import type {
28
- ActiveSurfaceContext,
29
17
  ChannelCapabilities,
30
- ChannelCommandContext,
31
18
  InjectionMode,
32
19
  } from "../daemon/conversation-runtime-assembly.js";
33
- import type { PkbContextConversation } from "../daemon/pkb-context-tracker.js";
34
20
  import type { TrustContext } from "../daemon/trust-context.js";
35
- import type { MessageRole } from "../memory/conversation-crud.js";
36
- import type { QdrantSparseVector } from "../memory/qdrant-client.js";
21
+ import type { ConversationGraphMemory } from "../memory/graph/conversation-graph-memory.js";
37
22
  import type { PluginHookFn } from "../plugin-api/types.js";
38
- import type {
39
- ContentBlock,
40
- Message,
41
- Provider,
42
- ProviderResponse,
43
- SendMessageOptions,
44
- ToolDefinition,
45
- } from "../providers/types.js";
23
+ import type { Message } from "../providers/types.js";
46
24
  import type { SkillRoute } from "../runtime/skill-route-registry.js";
47
- import type { Tool, ToolContext, ToolExecutionResult } from "../tools/types.js";
25
+ import type { Tool } from "../tools/types.js";
48
26
  import { AssistantError, ErrorCode } from "../util/errors.js";
49
- import type {
50
- ToolResultTruncateArgs,
51
- ToolResultTruncateResult,
52
- } from "./defaults/tool-result-truncate/types.js";
53
27
 
54
28
  // ─── Manifest ────────────────────────────────────────────────────────────────
55
29
 
@@ -100,618 +74,20 @@ export type {
100
74
  PluginShutdownContext,
101
75
  } from "../plugin-api/types.js";
102
76
 
103
- // ─── Middleware ──────────────────────────────────────────────────────────────
104
-
105
- /**
106
- * Generic onion-style middleware. Each middleware may observe/modify the
107
- * arguments, decide whether to call `next` (short-circuit) or return a
108
- * synthetic result, and observe/modify the downstream result. `ctx` is the
109
- * immutable per-turn {@link TurnContext}.
110
- */
111
- export type Middleware<A, R> = (
112
- args: A,
113
- next: (args: A) => Promise<R>,
114
- ctx: TurnContext,
115
- ) => Promise<R>;
116
-
117
- // ─── Pipeline names ──────────────────────────────────────────────────────────
118
-
119
- /**
120
- * Exhaustive list of pipeline slot names. New pipelines must be added here
121
- * and in `DEFAULT_TIMEOUTS` (PR 12). The registry only understands these.
122
- */
123
- export type PipelineName =
124
- | "turn"
125
- | "llmCall"
126
- | "toolExecute"
127
- | "memoryRetrieval"
128
- | "tokenEstimate"
129
- | "compaction"
130
- | "overflowReduce"
131
- | "persistence"
132
- | "titleGenerate"
133
- | "toolResultTruncate"
134
- | "emptyResponse"
135
- | "toolError"
136
- | "circuitBreaker";
137
-
138
- // ─── Per-pipeline args / results (placeholder shapes) ────────────────────────
139
- // Concrete field-level types land in M2/M3 PRs as each pipeline is wrapped.
140
- // Until then we expose `unknown`-tagged aliases so downstream code can name
141
- // the types without depending on unstable internal shapes.
142
-
143
- export type TurnArgs = { readonly input: unknown };
144
- export type TurnResult = { readonly output: unknown };
145
-
146
- /**
147
- * Pipeline arguments for `llmCall` — mirrors the inputs to
148
- * {@link Provider.sendMessage}. The terminal handler (the default plugin)
149
- * delegates straight to `args.provider.sendMessage(args.messages, args.options)`;
150
- * middleware may observe or rewrite any field before that call, short-circuit
151
- * with a synthetic {@link LLMCallResult}, or post-process the response on the
152
- * way out.
153
- *
154
- * `provider` is passed in `args` (rather than resolved from the runtime) so
155
- * middleware can swap it deterministically per-call. `options` carries the
156
- * full `SendMessageOptions` bag — `tools`, `systemPrompt`, `config`,
157
- * `onEvent`, and `signal` — so middleware can substitute streaming handlers,
158
- * tool sets, or cancellation signals without reconstructing them.
159
- */
160
- export type LLMCallArgs = {
161
- readonly provider: Provider;
162
- readonly messages: Message[];
163
- readonly options?: SendMessageOptions;
164
- };
165
- export type LLMCallResult = ProviderResponse;
166
-
167
- /**
168
- * Arguments passed to the `toolExecute` pipeline — mirrors the public
169
- * {@link ToolExecutor.execute} signature so middleware can observe (and
170
- * mutate) the tool name, input payload, and the full {@link ToolContext}
171
- * before the terminal runs the actual execution.
172
- */
173
- export interface ToolExecuteArgs {
174
- readonly name: string;
175
- readonly input: Record<string, unknown>;
176
- readonly context: ToolContext;
177
- }
178
-
179
- /**
180
- * Result returned from the `toolExecute` pipeline — identical to
181
- * {@link ToolExecutionResult} so short-circuit middleware can supply a
182
- * synthetic result without invoking the terminal.
183
- */
184
- export type ToolExecuteResult = ToolExecutionResult;
185
-
186
- /**
187
- * A single retrieved memory artifact.
188
- *
189
- * The memory-graph retriever emits complex, tightly-coupled state (content
190
- * blocks, query vectors, metrics, events, etc.) that downstream code in the
191
- * agent loop consumes holistically. Representing each memory-graph output as
192
- * an opaque `MemoryBlock` lets plugins swap in completely different shapes
193
- * (custom retrievers, mocks for testing) without requiring the plugin surface
194
- * to re-declare the graph result schema here. Refined by consumers via
195
- * runtime narrowing — the default retriever attaches a structural marker so
196
- * the agent loop can safely unwrap its own output.
197
- */
198
- export type MemoryBlock = unknown;
199
-
200
- /**
201
- * Inputs to the memory-retrieval pipeline. The pipeline takes only
202
- * identifiers and the trust context — the actual data sources (PKB files,
203
- * NOW.md, memory graph) are side-effectful and read by the terminal.
204
- *
205
- * `signal` is the per-turn abort signal forwarded to the memory graph's
206
- * `prepareMemory` call. Carrying it on `args` (rather than on the
207
- * `DefaultMemoryRetrievalDeps` extra-state bundle) is load-bearing: the
208
- * pipeline runner's `linkAbortSignal` swaps any `AbortSignal`-typed
209
- * property on top-level args for an internal linked signal, so a plugin
210
- * timeout (or external cancel) actually reaches `prepareMemory` and cancels
211
- * the underlying retrieval instead of letting it run to completion after
212
- * the pipeline has already errored.
213
- */
214
- export interface MemoryArgs {
215
- readonly conversationId: string;
216
- readonly trustContext: TrustContext | undefined;
217
- readonly turnIndex: number;
218
- readonly signal: AbortSignal;
219
- }
220
-
221
- /**
222
- * Outputs of the memory-retrieval pipeline.
223
- *
224
- * - `pkbContent` / `nowContent`: trimmed file contents ready for injection,
225
- * or `null` when the file is missing/empty.
226
- * - `memoryGraphBlocks`: zero or one memory-graph retrievals (the default
227
- * retriever yields exactly one when the actor is trusted and the graph
228
- * produced output, zero otherwise). Multi-entry arrays are reserved for
229
- * future multi-source retrievers; the current agent loop consumes only
230
- * the first entry.
231
- */
232
- export interface MemoryResult {
233
- readonly pkbContent: string | null;
234
- readonly nowContent: string | null;
235
- readonly memoryGraphBlocks: ReadonlyArray<MemoryBlock>;
236
- }
237
-
238
- /**
239
- * Inputs to the `tokenEstimate` pipeline. The default middleware delegates
240
- * these straight to {@link estimatePromptTokensRaw}; custom plugins may
241
- * substitute an alternate estimator (e.g. provider-native tokenization) by
242
- * short-circuiting the pipeline with their own {@link EstimateResult}.
243
- *
244
- * Fields:
245
- * - `history` — current message list to estimate over.
246
- * - `systemPrompt` — system prompt string, or `undefined` when absent.
247
- * - `tools` — tool definitions visible on this turn. The default plugin
248
- * sums their token budget via `estimateToolsTokens(tools)` and hands the
249
- * result to the raw estimator via `toolTokenBudget`. Plugins that want to
250
- * ignore tool cost can skip that term.
251
- * - `providerName` — canonical calibration provider key (the value returned
252
- * by `getCalibrationProviderKey(provider)`). Drives provider-specific
253
- * heuristics inside the raw estimator (e.g. Anthropic image sizing).
254
- */
255
- export type EstimateArgs = {
256
- readonly history: Message[];
257
- readonly systemPrompt: string | undefined;
258
- readonly tools: ToolDefinition[];
259
- readonly providerName: string | undefined;
260
- };
261
-
262
- /** Result of the `tokenEstimate` pipeline — total estimated prompt tokens. */
263
- export type EstimateResult = number;
264
-
265
- /** Alias retained for symmetry with the rest of the pipeline-name family. */
266
- export type TokenEstimateArgs = EstimateArgs;
267
- /** Alias retained for symmetry with the rest of the pipeline-name family. */
268
- export type TokenEstimateResult = EstimateResult;
269
-
270
- /**
271
- * Pipeline inputs for the `compaction` slot — the arguments the assistant
272
- * would otherwise have passed to {@link ContextWindowManager.maybeCompact}.
273
- *
274
- * Typed via `unknown`-forwarded aliases to keep this module free of runtime
275
- * imports from `context/window-manager.ts` (which would pull the full
276
- * compaction machinery into anything that merely imports plugin types).
277
- * The default compaction plugin re-casts back to the concrete types before
278
- * delegating to the manager.
279
- */
280
- export type CompactionArgs = {
281
- /** The message history to consider for compaction. */
282
- readonly messages: unknown;
283
- /** Abort signal forwarded to the compaction summary call. */
284
- readonly signal?: AbortSignal;
285
- /** `ContextWindowCompactOptions` — options block forwarded verbatim. */
286
- readonly options?: unknown;
287
- };
288
- /**
289
- * Pipeline result for the `compaction` slot — the full
290
- * {@link import("../context/window-manager.js").ContextWindowResult}
291
- * object returned by `maybeCompact()`. Kept as `unknown` here for the
292
- * same decoupling reason as {@link CompactionArgs}; consumers in
293
- * `daemon/conversation-agent-loop.ts` cast back to the concrete shape.
294
- */
295
- export type CompactionResult = unknown;
296
-
297
- /**
298
- * Input to the `overflowReduce` pipeline. Captures everything the reducer
299
- * tier loop needs, including the message history, reducer configuration,
300
- * and side-effect callbacks that bridge the pipeline back to the orchestrator's
301
- * mutable per-turn state (context-window manager, activity emitter, runtime
302
- * injection reassembly, memory reinjection).
303
- *
304
- * The callbacks are supplied by the orchestrator because the reducer loop
305
- * needs to coordinate with state that lives on the `AgentLoopConversationContext`
306
- * (message mutation, compaction event emission, circuit breaker tracking,
307
- * injection block reassembly). Keeping them as explicit callbacks — rather
308
- * than pulling the whole context into the pipeline — preserves the rule that
309
- * `TurnContext` stays minimal and pipeline-agnostic.
310
- */
311
- export interface OverflowReduceArgs {
312
- /** Bare persisted message history (mutable copy — the default middleware
313
- * applies reducer results in-place via the `applyMessages` callback). */
314
- readonly messages: Message[];
315
- /** Current run-time message array with runtime injections applied. */
316
- readonly runMessages: Message[];
317
- /** System prompt used for post-step token estimation. */
318
- readonly systemPrompt: string;
319
- /** Provider name used for token estimation (calibration provider key). */
320
- readonly providerName: string;
321
- /** Context window config (drives compaction behavior). */
322
- readonly contextWindow: ContextWindowConfig;
323
- /** Token budget the reducer must get below (preflight budget). */
324
- readonly preflightBudget: number;
325
- /** Tool-token overhead included in every estimation call. */
326
- readonly toolTokenBudget?: number;
327
- /** Maximum reducer iterations before the loop exits unconditionally. */
328
- readonly maxAttempts: number;
329
- /** Abort signal threaded through compaction calls. */
330
- readonly abortSignal?: AbortSignal;
331
- /**
332
- * Compaction callback — the reducer never owns the ContextWindowManager
333
- * instance. The orchestrator supplies this closure so the default plugin
334
- * can delegate the forced-compaction tier without crossing the
335
- * pipeline/infra boundary on its own.
336
- */
337
- readonly compactFn: (
338
- messages: Message[],
339
- signal: AbortSignal | undefined,
340
- options: unknown,
341
- ) => Promise<ContextWindowResult>;
342
- /**
343
- * Invoked before each reducer iteration to emit the `context_compacting`
344
- * activity state. The orchestrator owns activity emission because the
345
- * signal is trust/channel aware.
346
- */
347
- readonly emitActivityState: () => void;
348
- /**
349
- * Invoked after each reducer step that produced a successful compaction.
350
- * Handles circuit-breaker tracking, event emission, and context mutation.
351
- * The pipeline passes back `didCompact` so the orchestrator can flip its
352
- * `reducerCompacted` / `shouldInjectWorkspace` flags and the next
353
- * re-injection uses the fresh messages.
354
- */
355
- readonly onCompactionResult: (
356
- result: ContextWindowResult,
357
- compactedBasis?: Message[],
358
- ) => void | Promise<void>;
359
- /**
360
- * Invoked after each step to rebuild `runMessages` from the step's
361
- * reduced history with the requested injection mode. The orchestrator
362
- * owns this helper so the full per-turn injection options object doesn't
363
- * leak into the pipeline surface. The plugin passes the current reduced
364
- * messages array explicitly so the orchestrator doesn't need to read
365
- * mutable shared state. Returns the new `runMessages`.
366
- *
367
- * Two distinct "did compact" signals are passed so the orchestrator can
368
- * apply the correct per-iteration vs sticky gating:
369
- * - `stepCompacted` — whether THIS iteration's reducer step produced a
370
- * fresh compaction. Gates PKB / NOW re-injection: compaction strips the
371
- * existing blocks, so only iterations that just compacted need the
372
- * content re-threaded. Iterations that only truncated tool results or
373
- * downgraded injections must NOT force a re-injection or the token
374
- * count grows each round.
375
- * - `accumulatedCompacted` — whether ANY iteration in this pipeline
376
- * invocation has compacted. Gates `slackChronologicalMessages`
377
- * suppression: once compaction has run, the captured Slack transcript
378
- * snapshot would overwrite the compacted history, so it must stay
379
- * suppressed for every subsequent iteration even if that iteration
380
- * didn't re-compact.
381
- */
382
- readonly reinjectForMode: (
383
- messages: Message[],
384
- mode: InjectionMode,
385
- stepCompacted: boolean,
386
- accumulatedCompacted: boolean,
387
- ) => Promise<Message[]>;
388
- /**
389
- * Invoked after each step to post-estimate the rebuilt `runMessages`.
390
- * Pulled out so the orchestrator controls how estimation is performed
391
- * (and which fields feed it) without the pipeline reimplementing it.
392
- */
393
- readonly estimatePostInjection: (runMessages: Message[]) => number;
394
- }
395
-
396
- /** Output of the `overflowReduce` pipeline. */
397
- export interface OverflowReduceResult {
398
- /** Final reduced `ctx.messages` value (mutated in place by the reducer). */
399
- readonly messages: Message[];
400
- /** Final `runMessages` with re-applied runtime injections. */
401
- readonly runMessages: Message[];
402
- /** Final injection mode (may be `"minimal"` if the downgrade tier fired). */
403
- readonly injectionMode: InjectionMode;
404
- /** Accumulated reducer state at exit. */
405
- readonly reducerState: ReducerState;
406
- /** True if any step successfully compacted history. */
407
- readonly reducerCompacted: boolean;
408
- /** How many iterations of the tier loop executed. */
409
- readonly attempts: number;
410
- }
411
-
412
- /**
413
- * Pipeline arguments for `persistence` — a discriminated union over the
414
- * message-CRUD operations plugins may observe, redirect, or short-circuit:
415
- *
416
- * - `add` — append a new message (`addMessage`). Mirrors
417
- * `addMessage(conversationId, role, content, options?)`.
418
- * When `syncToDisk` is set, the default plugin also runs
419
- * {@link syncMessageToDisk} against the just-persisted row
420
- * so the JSONL disk view stays consistent. The
421
- * `createdAtMs` field carries the conversation's creation
422
- * timestamp — needed to resolve the disk-view directory.
423
- * - `reserve` — pre-allocate an empty assistant anchor row
424
- * (`reserveMessage`) so the agent loop can stamp streaming
425
- * events with stable identity before any content is
426
- * produced. Returns the same row shape as `add`.
427
- * - `updateContent` — overwrite the content of an existing message
428
- * (`updateMessageContent`). Used to finalize a previously
429
- * reserved row, and by consolidation paths.
430
- * - `update` — shallow-merge metadata into an existing message
431
- * (`updateMessageMetadata`). Returns `void`.
432
- * - `delete` — remove a single message (`deleteMessageById`). Returns
433
- * the {@link DeletedMemoryIds}-shaped segment/summary IDs
434
- * the caller must clean up out-of-band.
435
- *
436
- * The discriminated `op` field lets plugin middleware narrow the union and
437
- * tailor behavior per-operation (e.g. "only observe deletes", "redirect
438
- * adds to a mock store").
439
- */
440
- export type PersistAddArgs = {
441
- readonly op: "add";
442
- readonly conversationId: string;
443
- readonly role: MessageRole;
444
- readonly content: string;
445
- readonly metadata?: Record<string, unknown>;
446
- readonly addOptions?: { readonly skipIndexing?: boolean };
447
- /**
448
- * When `true`, the default plugin additionally invokes
449
- * {@link syncMessageToDisk} with the returned message's id. Requires
450
- * {@link createdAtMs} to resolve the conversation's disk-view directory.
451
- */
452
- readonly syncToDisk?: boolean;
453
- /** Conversation creation timestamp — only read when `syncToDisk` is true. */
454
- readonly createdAtMs?: number;
455
- };
456
-
457
- export type PersistReserveArgs = {
458
- readonly op: "reserve";
459
- readonly conversationId: string;
460
- readonly role: MessageRole;
461
- readonly metadata?: Record<string, unknown>;
462
- };
463
-
464
- export type PersistUpdateContentArgs = {
465
- readonly op: "updateContent";
466
- readonly messageId: string;
467
- readonly content: string;
468
- };
469
-
470
- export type PersistUpdateArgs = {
471
- readonly op: "update";
472
- readonly messageId: string;
473
- readonly updates: Record<string, unknown>;
474
- };
475
-
476
- export type PersistDeleteArgs = {
477
- readonly op: "delete";
478
- readonly messageId: string;
479
- };
480
-
481
- export type PersistArgs =
482
- | PersistAddArgs
483
- | PersistReserveArgs
484
- | PersistUpdateContentArgs
485
- | PersistUpdateArgs
486
- | PersistDeleteArgs;
487
-
488
- /**
489
- * Result row returned by an `add` op — matches the shape produced by
490
- * {@link addMessage}. Kept structural (not imported from `memory/`) so the
491
- * plugin types module stays decoupled from the storage layer.
492
- */
493
- export type PersistAddResult = {
494
- readonly op: "add";
495
- readonly message: {
496
- readonly id: string;
497
- readonly conversationId: string;
498
- readonly role: string;
499
- readonly content: string;
500
- readonly createdAt: number;
501
- readonly metadata?: string;
502
- };
503
- };
504
-
505
- /**
506
- * Result row returned by a `reserve` op — same row shape as `add` but with
507
- * empty `content` (`"[]"`) and tagged distinctly so middleware can branch
508
- * on intent.
509
- */
510
- export type PersistReserveResult = {
511
- readonly op: "reserve";
512
- readonly message: {
513
- readonly id: string;
514
- readonly conversationId: string;
515
- readonly role: string;
516
- readonly content: string;
517
- readonly createdAt: number;
518
- readonly metadata?: string;
519
- };
520
- };
521
-
522
- export type PersistUpdateContentResult = { readonly op: "updateContent" };
523
-
524
- export type PersistUpdateResult = { readonly op: "update" };
525
-
526
- /** IDs of segments/summaries the caller must remove from Qdrant. */
527
- export type PersistDeleteResult = {
528
- readonly op: "delete";
529
- readonly segmentIds: string[];
530
- readonly deletedSummaryIds: string[];
531
- };
532
-
533
- export type PersistResult =
534
- | PersistAddResult
535
- | PersistReserveResult
536
- | PersistUpdateContentResult
537
- | PersistUpdateResult
538
- | PersistDeleteResult;
539
-
540
- /**
541
- * Arguments for the `titleGenerate` pipeline. Mirrors the parameters of
542
- * `queueGenerateConversationTitle` in `memory/conversation-title-service.ts`
543
- * so the default plugin can delegate verbatim.
544
- *
545
- * `provider` is optional because the underlying service falls back to
546
- * `getConfiguredProvider("conversationTitle")` when absent. `userMessage`
547
- * carries the first turn's text — the service uses it as LLM context and
548
- * also to derive a deterministic fallback title if the call fails.
549
- *
550
- * `onTitleUpdated` is a fire-and-forget callback the pipeline invokes when
551
- * the title is finally persisted. The default implementation is
552
- * fire-and-forget overall, so the pipeline result (`TitleResult`) carries no
553
- * payload — callers that need the title must use the callback.
554
- */
555
- export type TitleArgs = {
556
- readonly conversationId: string;
557
- readonly provider?: Provider;
558
- readonly userMessage: string;
559
- readonly onTitleUpdated?: (title: string) => void;
560
- };
561
- /**
562
- * Result of the `titleGenerate` pipeline. The default implementation is
563
- * fire-and-forget (it schedules background work and returns immediately),
564
- * so there is nothing meaningful to return. Defined as an empty object so
565
- * custom plugins can opt into richer payloads later.
566
- */
567
- export type TitleResult = Readonly<Record<string, never>>;
77
+ // ─── Memory-graph result ─────────────────────────────────────────────────────
568
78
 
569
79
  /**
570
- * @deprecated Alias kept for the M1 scaffolding era. Prefer {@link TitleArgs}.
571
- */
572
- export type TitleGenerateArgs = TitleArgs;
573
- /**
574
- * @deprecated Alias kept for the M1 scaffolding era. Prefer {@link TitleResult}.
80
+ * Full output of a single memory-graph retrieval the object returned by
81
+ * {@link ConversationGraphMemory.prepareMemory} (injected messages, query
82
+ * vectors, metrics). The agent loop consumes these fields directly to drive
83
+ * PKB hint search and runtime injection.
575
84
  */
576
- export type TitleGenerateResult = TitleResult;
85
+ export type GraphMemoryResult = Awaited<
86
+ ReturnType<ConversationGraphMemory["prepareMemory"]>
87
+ >;
577
88
 
578
89
  /**
579
- * Snapshot of the just-completed assistant turn plus retry/context counters
580
- * the `emptyResponse` pipeline needs to decide whether to nudge, accept, or
581
- * surface an error.
582
- *
583
- * `emptyResponseRetries` is the *current* retry counter — the pipeline may
584
- * compare it to `maxEmptyResponseRetries` to implement a retry cap. The loop
585
- * increments the counter only after a `"nudge"` decision; the pipeline is
586
- * stateless across turns.
587
- *
588
- * `priorAssistantHadVisibleText` signals that an earlier turn in the current
589
- * `run()` invocation already delivered user-visible text. When true, an
590
- * empty follow-up is the model correctly ending its turn and nudging would
591
- * mislead it into resending text the user already saw.
592
- */
593
- export interface EmptyResponseArgs {
594
- /** Content blocks produced by the assistant on this turn. */
595
- readonly responseContent: ReadonlyArray<ContentBlock>;
596
- /**
597
- * Number of `tool_use` blocks in `responseContent`. Mirrors the loop's own
598
- * count so middleware doesn't have to recompute it. When > 0 the turn is
599
- * not empty — the model issued tool calls.
600
- */
601
- readonly toolUseBlocksLength: number;
602
- /** 0-based index of the tool-use turn being evaluated. */
603
- readonly toolUseTurns: number;
604
- /** How many empty-response nudges the loop has already issued this run. */
605
- readonly emptyResponseRetries: number;
606
- /** Upper bound for `emptyResponseRetries`. The default is 1. */
607
- readonly maxEmptyResponseRetries: number;
608
- /**
609
- * Whether ANY prior assistant turn in the current `run()` call carried
610
- * visible text. See `agent/loop.ts` for why the whole-run scan matters.
611
- */
612
- readonly priorAssistantHadVisibleText: boolean;
613
- /**
614
- * Provider-reported stop reason for the assistant turn being evaluated.
615
- * `null`/`undefined` when the provider didn't report one (older
616
- * providers, partial responses). The default terminal uses this to
617
- * distinguish an explicit safety-classifier refusal (Anthropic's
618
- * `"refusal"`) from an organically-empty turn — refusals deserve a
619
- * nudge even on the very first model call of the run, whereas an
620
- * organically-empty first call usually means the model legitimately
621
- * had nothing to say.
622
- */
623
- readonly stopReason: string | null | undefined;
624
- }
625
-
626
- /**
627
- * Decision produced by the `emptyResponse` pipeline.
628
- *
629
- * - `"nudge"` — loop appends `nudgeText` as a `user` message and retries.
630
- * `nudgeText` MUST be present; it is what the model will see.
631
- * - `"accept"` — loop treats the turn as complete (pushes the assistant
632
- * message to history and exits the tool-use chain normally).
633
- * - `"error"` — loop surfaces a clear error. Reserved for middleware that
634
- * wants to escalate an empty response rather than absorb it.
635
- */
636
- export interface EmptyResponseDecision {
637
- readonly action: "nudge" | "accept" | "error";
638
- /** Nudge text the loop will push to history. Required when `action === "nudge"`. */
639
- readonly nudgeText?: string;
640
- }
641
-
642
- /** Alias so the {@link PipelineMiddlewareMap} entry names its own result shape. */
643
- export type EmptyResponseResult = EmptyResponseDecision;
644
-
645
- /**
646
- * Arguments to the `toolError` pipeline — invoked by the agent loop once per
647
- * turn that produced tool results, BEFORE the turn's tool-result user message
648
- * is pushed into history.
649
- *
650
- * `hasToolError` is true when at least one tool in the current turn returned
651
- * `isError: true`. `consecutiveErrorTurns` is the running count of
652
- * back-to-back error turns (reset to 0 on a clean turn, incremented on each
653
- * error turn). `maxConsecutiveErrorNudges` is the default cap the agent loop
654
- * currently applies; plugins receive it so they can match the default
655
- * threshold exactly or compute a relative offset.
656
- */
657
- export type ToolErrorArgs = {
658
- readonly hasToolError: boolean;
659
- readonly consecutiveErrorTurns: number;
660
- readonly maxConsecutiveErrorNudges: number;
661
- };
662
-
663
- /**
664
- * Decision returned by the `toolError` pipeline. When `action` is `"nudge"`,
665
- * the agent loop appends a text block with `nudgeText` to the turn's tool
666
- * results so the next LLM turn sees the nudge. When `action` is `"skip"`, no
667
- * nudge is injected and the tool results pass through unchanged.
668
- */
669
- export type ToolErrorDecision =
670
- | { readonly action: "nudge"; readonly nudgeText: string }
671
- | { readonly action: "skip" };
672
-
673
- /** Alias kept so `PipelineMiddlewareMap.toolError` reads result-shaped. */
674
- export type ToolErrorResult = ToolErrorDecision;
675
-
676
- /**
677
- * Arguments for the `circuitBreaker` pipeline.
678
- *
679
- * A single call pattern handles both querying and updating the breaker:
680
- * - `{ key }` — query-only. Returns the current `{ open, cooldownRemainingMs? }`.
681
- * - `{ key, outcome }` — update state, then return the post-update decision.
682
- *
683
- * `key` identifies the circuit bucket so independent circuits (e.g. per
684
- * conversation, per provider) can coexist. The default compaction plugin
685
- * uses `"compaction:<conversationId>"`.
686
- *
687
- * `state` is a pragmatic extension beyond the minimal `{ key, outcome? }`
688
- * shape: the `Conversation` owns `consecutiveCompactionFailures` and
689
- * `compactionCircuitOpenUntil` because dev-only playground routes read and
690
- * mutate those fields directly. The default plugin reads/updates the same
691
- * container so the pipeline stays a pure wrapper rather than forking state
692
- * ownership.
693
- *
694
- * `onEvent` is optional — when provided, the default plugin emits
695
- * `compaction_circuit_open` / `compaction_circuit_closed` transition events
696
- * through it. Its parameter is narrowed to {@link CompactionCircuitEvent} (the
697
- * only two messages this pipeline ever emits) rather than the full
698
- * `ServerMessage` union, so a caller whose outbound channel can carry just
699
- * these two events can satisfy it. Callers that only want to query without
700
- * emitting can omit it.
701
- */
702
- export type CircuitBreakerArgs = {
703
- readonly key: string;
704
- readonly outcome?: "success" | "failure";
705
- readonly state: {
706
- readonly conversationId: string;
707
- consecutiveCompactionFailures: number;
708
- compactionCircuitOpenUntil: number | null;
709
- };
710
- readonly onEvent?: (msg: CompactionCircuitEvent) => void;
711
- };
712
-
713
- /**
714
- * The complete set of transition events the `circuitBreaker` pipeline emits:
90
+ * The complete set of compaction circuit-breaker transition events:
715
91
  * `compaction_circuit_open` when the breaker trips and `compaction_circuit_closed`
716
92
  * on the open→closed transition. Both are a subset of `ServerMessage`, so any
717
93
  * existing `ServerMessage` sink remains assignable to a
@@ -721,44 +97,6 @@ export type CompactionCircuitEvent =
721
97
  | CompactionCircuitOpenEvent
722
98
  | CompactionCircuitClosedEvent;
723
99
 
724
- /**
725
- * Result of a `circuitBreaker` pipeline invocation.
726
- *
727
- * - `open` — `true` when the breaker is currently tripped (auto paths must
728
- * skip). `false` when closed (auto paths may proceed).
729
- * - `cooldownRemainingMs` — when `open` is `true`, the number of ms until
730
- * the breaker auto-closes (for informational display). Omitted when the
731
- * breaker is closed.
732
- */
733
- export type CircuitBreakerResult = {
734
- readonly open: boolean;
735
- readonly cooldownRemainingMs?: number;
736
- };
737
-
738
- /**
739
- * Mapping from {@link PipelineName} to the middleware signature the registry
740
- * expects for that slot. Used both to shape `Plugin.middleware` and to drive
741
- * `getMiddlewaresFor<P>()` type narrowing in PR 13.
742
- */
743
- export interface PipelineMiddlewareMap {
744
- turn: Middleware<TurnArgs, TurnResult>;
745
- llmCall: Middleware<LLMCallArgs, LLMCallResult>;
746
- toolExecute: Middleware<ToolExecuteArgs, ToolExecuteResult>;
747
- memoryRetrieval: Middleware<MemoryArgs, MemoryResult>;
748
- tokenEstimate: Middleware<TokenEstimateArgs, TokenEstimateResult>;
749
- compaction: Middleware<CompactionArgs, CompactionResult>;
750
- overflowReduce: Middleware<OverflowReduceArgs, OverflowReduceResult>;
751
- persistence: Middleware<PersistArgs, PersistResult>;
752
- titleGenerate: Middleware<TitleArgs, TitleResult>;
753
- toolResultTruncate: Middleware<
754
- ToolResultTruncateArgs,
755
- ToolResultTruncateResult
756
- >;
757
- emptyResponse: Middleware<EmptyResponseArgs, EmptyResponseResult>;
758
- toolError: Middleware<ToolErrorArgs, ToolErrorResult>;
759
- circuitBreaker: Middleware<CircuitBreakerArgs, CircuitBreakerResult>;
760
- }
761
-
762
100
  // ─── TurnContext ─────────────────────────────────────────────────────────────
763
101
 
764
102
  /**
@@ -784,49 +122,8 @@ export interface TurnInjectionInputs {
784
122
  * context (unified turn context, etc.). Drives per-injector gating.
785
123
  */
786
124
  readonly mode?: InjectionMode;
787
- /** Disk-pressure cleanup-mode context or null to skip the warning. */
788
- readonly diskPressureContext?: DiskPressureInjectionContext | null;
789
- /** Workspace top-level context text (`<workspace>...`) or null to skip. */
790
- readonly workspaceTopLevelContext?: string | null;
791
125
  /** Pre-built unified-turn-context text (`<turn_context>...`) or null to skip. */
792
126
  readonly unifiedTurnContext?: string | null;
793
- /** PKB auto-injected content (`<knowledge_base>...`) or null to skip. */
794
- readonly pkbContext?: string | null;
795
- /**
796
- * Whether PKB is active for this turn — drives the `<system_reminder>` /
797
- * hybrid-search relevance-hint branch.
798
- */
799
- readonly pkbActive?: boolean;
800
- /** Dense query vector surfaced from the graph memory retriever for PKB hints. */
801
- readonly pkbQueryVector?: number[];
802
- /** Optional sparse vector accompanying `pkbQueryVector`. */
803
- readonly pkbSparseVector?: QdrantSparseVector;
804
- /** Memory scope id used to filter PKB search results. */
805
- readonly pkbScopeId?: string;
806
- /**
807
- * Live conversation (or a minimal shape containing `messages`) used to
808
- * compute which PKB paths are already "in context" and therefore suppressed
809
- * from hint suggestions.
810
- */
811
- readonly pkbConversation?: PkbContextConversation;
812
- /** Auto-injected PKB filenames resolved relative to `pkbRoot`. */
813
- readonly pkbAutoInjectList?: string[];
814
- /** Absolute path to the PKB directory (e.g. `<workspace>/pkb`). */
815
- readonly pkbRoot?: string;
816
- /**
817
- * Working directory against which relative `file_read` paths resolve.
818
- * Falls back to `pkbRoot` when omitted.
819
- */
820
- readonly pkbWorkingDir?: string;
821
- /**
822
- * Pre-rendered v2 static memory content (essentials/threads/recent/buffer
823
- * concatenated, header-wrapped) or null to skip. The agent loop only
824
- * passes this on full-mode turns; the injector wraps it in `<memory>` for
825
- * the user message.
826
- */
827
- readonly memoryV2Static?: string | null;
828
- /** NOW.md scratchpad content or null to skip. */
829
- readonly nowScratchpad?: string | null;
830
127
  /** Pre-built `<active_subagents>` block or null to skip. */
831
128
  readonly subagentStatusBlock?: string | null;
832
129
  /** Channel capabilities — drives slack gating. */
@@ -843,18 +140,6 @@ export interface TurnInjectionInputs {
843
140
  * no focus block is appended.
844
141
  */
845
142
  readonly slackActiveThreadFocusBlock?: string | null;
846
- /**
847
- * Active dashboard-surface context (read from `<active_workspace>`). Kept
848
- * on the injection inputs bag (not its own injector) because it is
849
- * orchestrator-owned surface state, not a default-chain element.
850
- */
851
- readonly activeSurface?: ActiveSurfaceContext | null;
852
- /** Channel command context (e.g. Telegram /start) or null to skip. */
853
- readonly channelCommandContext?: ChannelCommandContext | null;
854
- /** Voice call-control prompt or null to skip. */
855
- readonly voiceCallControlPrompt?: string | null;
856
- /** Gateway-provided transport hints (e.g. Slack thread context). */
857
- readonly transportHints?: string[] | null;
858
143
  /**
859
144
  * When true, inject the `<non_interactive_context>` block so the model
860
145
  * knows no human is present to answer clarification questions.
@@ -880,18 +165,12 @@ export interface TurnInjectionInputs {
880
165
  }> | null;
881
166
  }
882
167
 
883
- export interface DiskPressureInjectionContext {
884
- /** True when the current turn is allowed to run only for storage cleanup. */
885
- readonly cleanupModeActive: boolean;
886
- }
887
-
888
168
  /**
889
- * Per-turn execution context threaded through every middleware invocation.
169
+ * Per-turn execution context threaded to the injector chain and to hook
170
+ * consumers that need turn-level identity.
890
171
  *
891
172
  * Combines turn-level identifiers (`requestId`, `conversationId`,
892
- * `turnIndex`), the optionally-bound `pluginName` (set by the pipeline
893
- * runner when invoking a specific plugin's middleware, for error
894
- * attribution), and the canonical {@link TrustContext} that carries trust
173
+ * `turnIndex`) with the canonical {@link TrustContext} that carries trust
895
174
  * class and channel identity for the inbound actor.
896
175
  *
897
176
  * `TrustContext` is re-exposed here (rather than redefined) so the plugin
@@ -904,39 +183,44 @@ export interface TurnContext {
904
183
  conversationId: string;
905
184
  /** 0-based turn index within the conversation. */
906
185
  turnIndex: number;
907
- /**
908
- * When the pipeline runner is executing a specific plugin's middleware,
909
- * this is set to that plugin's name so downstream code (error wrapping,
910
- * telemetry) can attribute work accurately.
911
- */
912
- pluginName?: string;
913
186
  /** Trust classification and channel identity for the inbound actor. */
914
187
  trust: TrustContext;
915
188
  /**
916
189
  * Optional handle to the conversation's {@link ContextWindowManager}.
917
190
  *
918
- * Attached by the orchestrator when building the per-turn context for
919
- * pipeline invocations that need to defer to the real compaction machinery
920
- * (notably the default `compaction` plugin). Pipelines that never touch
921
- * compaction can ignore this field; the default compaction plugin throws
922
- * a {@link PluginExecutionError} if it is missing, which keeps the failure
923
- * attributed to the plugin rather than surfacing as a late NPE downstream.
191
+ * Attached by the orchestrator so the default compaction implementation can
192
+ * defer to the real compaction machinery via `context.manager`. Call sites
193
+ * that never touch compaction may omit it.
924
194
  *
925
195
  * Declared as an optional typed field so plugin code can read it without a
926
- * lenient cast. The optional shape is load-bearing: pipeline runner tests,
927
- * synthesized handler contexts, and other non-compaction call sites still
928
- * construct valid `TurnContext` literals without attaching a manager.
196
+ * lenient cast. The optional shape is load-bearing: synthesized handler
197
+ * contexts and other non-compaction call sites still construct valid
198
+ * `TurnContext` literals without attaching a manager.
929
199
  */
930
200
  contextWindowManager?: ContextWindowManager;
931
201
  /**
932
202
  * Per-turn injection inputs consumed by the default injector chain.
933
203
  *
934
- * Omitted for call sites that don't drive runtime injection (pipeline-runner
935
- * tests, synthesized handler contexts, some background jobs). Each default
936
- * injector treats missing/absent fields as "no injection on this turn", so
937
- * a context without `injectionInputs` produces an empty injection chain.
204
+ * Omitted for call sites that don't drive runtime injection (synthesized
205
+ * handler contexts, some background jobs). Each default injector treats
206
+ * missing/absent fields as "no injection on this turn", so a context
207
+ * without `injectionInputs` produces an empty injection chain.
938
208
  */
939
209
  injectionInputs?: TurnInjectionInputs;
210
+ /**
211
+ * The {@link LLMCallSite} this turn belongs to — `"mainAgent"` for the
212
+ * user-facing conversational reply, or the specific background/utility site
213
+ * (`"compactionAgent"`, `"subagentSpawn"`, `"memoryConsolidation"`,
214
+ * `"conversationTitle"`, …) when the agent loop is driving non-main work
215
+ * that happens to share the same `conversationId`.
216
+ *
217
+ * Lets {@link Injector}s scope their behaviour to the main reply and stay
218
+ * out of background turns, which `onEvent` presence alone cannot distinguish
219
+ * (compaction and subagent loops also stream). Omitted by call sites that
220
+ * don't tag a site (synthesized test contexts); consumers should treat
221
+ * absence conservatively.
222
+ */
223
+ callSite?: LLMCallSite;
940
224
  }
941
225
 
942
226
  // ─── Injectors ───────────────────────────────────────────────────────────────
@@ -1016,8 +300,21 @@ export interface Injector {
1016
300
  name: string;
1017
301
  /** Ascending sort key — lower runs first. */
1018
302
  order: number;
1019
- /** Produce a block, or `null` to contribute nothing on this turn. */
1020
- produce(ctx: TurnContext): Promise<InjectionBlock | null>;
303
+ /**
304
+ * Produce a block, or `null` to contribute nothing on this turn.
305
+ *
306
+ * `runMessages` is the turn's working message array — the same array the
307
+ * chain's blocks are spliced onto — passed explicitly so injectors that
308
+ * need the current prompt contents (e.g. the PKB reminder, which scans for
309
+ * already-loaded `file_read` paths) read it from a parameter rather than a
310
+ * field on the shared {@link TurnContext}. Absent for text-only chain
311
+ * consumers ({@link composeInjectorChain}) that drive injectors without a
312
+ * message array.
313
+ */
314
+ produce(
315
+ ctx: TurnContext,
316
+ runMessages?: Message[],
317
+ ): Promise<InjectionBlock | null>;
1021
318
  }
1022
319
 
1023
320
  // ─── Model-visible capability slots ──────────────────────────────────────────
@@ -1104,7 +401,7 @@ export type PluginHooks = Record<string, PluginHookFn<any>>;
1104
401
 
1105
402
  /**
1106
403
  * A registered plugin. Every field besides `manifest` is optional — a plugin
1107
- * may contribute any combination of middleware, injectors, and model-visible
404
+ * may contribute any combination of lifecycle hooks and model-visible
1108
405
  * capabilities. Lifecycle hooks live under `hooks`.
1109
406
  */
1110
407
  export interface Plugin {
@@ -1126,45 +423,13 @@ export interface Plugin {
1126
423
  routes?: PluginRouteRegistration[];
1127
424
  /** Skill registrations loaded at startup. */
1128
425
  skills?: PluginSkillRegistration[];
1129
- /** Prompt-time injectors contributed by this plugin. */
1130
- injectors?: Injector[];
1131
- /**
1132
- * Named middleware slots. At most one middleware per slot per plugin.
1133
- * The registry composes multiple plugins' middleware for a slot in
1134
- * registration order (outermost first).
1135
- */
1136
- middleware?: Partial<PipelineMiddlewareMap>;
1137
426
  }
1138
427
 
1139
428
  // ─── Errors ──────────────────────────────────────────────────────────────────
1140
429
 
1141
- /**
1142
- * Thrown by the pipeline runner when a plugin's middleware exceeds the
1143
- * pipeline's configured timeout. Carries the pipeline name, the offending
1144
- * plugin (if known), and the elapsed-milliseconds budget that was breached.
1145
- */
1146
- export class PluginTimeoutError extends AssistantError {
1147
- constructor(
1148
- public readonly pipeline: PipelineName,
1149
- public readonly pluginName: string | undefined,
1150
- public readonly elapsedMs: number,
1151
- options?: { cause?: unknown },
1152
- ) {
1153
- super(
1154
- `Plugin pipeline '${pipeline}' timed out after ${elapsedMs}ms${
1155
- pluginName ? ` (offending plugin: ${pluginName})` : ""
1156
- }`,
1157
- ErrorCode.INTERNAL_ERROR,
1158
- options,
1159
- );
1160
- this.name = "PluginTimeoutError";
1161
- }
1162
- }
1163
-
1164
430
  /**
1165
431
  * Thrown by registry and bootstrap for plugin lifecycle errors — registration
1166
- * validation failures, API-version mismatches, init throw-outs. Distinct from
1167
- * {@link PluginTimeoutError} so callers can discriminate.
432
+ * validation failures, API-version mismatches, init throw-outs.
1168
433
  */
1169
434
  export class PluginExecutionError extends AssistantError {
1170
435
  constructor(