@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
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Periodic reaper for orphaned subprocesses that reparent to the daemon.
3
+ *
4
+ * Tools run commands in their own process group (`detached: true`) and, on
5
+ * timeout/abort, group-kill with `process.kill(-pgid, SIGKILL)` (the bash and
6
+ * host_bash tools, the skill sandbox runner, and the debug-bash route). The
7
+ * immediate child is reaped by Bun/libuv, but its descendants — e.g. git's
8
+ * transport helpers or a skill runner's `bun` process — were never spawned by
9
+ * the daemon, so when the group dies they reparent to PID 1. When the daemon
10
+ * runs as PID 1 in a container, Bun is not an init: it never calls `waitpid()`
11
+ * on those reparented orphans, so they accumulate as `<defunct>` entries that
12
+ * consume PID slots until the container is recycled.
13
+ *
14
+ * This reaper scans `/proc` for zombie children of the daemon and reaps each
15
+ * by **specific PID** with `WNOHANG`. It deliberately does NOT use
16
+ * `waitpid(-1)`: libuv reaps the children it spawned by specific PID on
17
+ * `SIGCHLD`, and a blanket `waitpid(-1)` would race libuv and could swallow a
18
+ * tracked child's exit status — libuv's own source handles the lost race by
19
+ * dropping the exit callback ("someone else stole the waitpid from us. Handle
20
+ * this by not handling it at all."). To stay clear of that race we only reap a
21
+ * zombie after it has survived at least one scan interval: libuv reaps its own
22
+ * within milliseconds of `SIGCHLD`, so anything still defunct a full interval
23
+ * later is a genuine orphan libuv is not tracking.
24
+ *
25
+ * The reaper is a no-op unless the daemon is PID 1 on Linux. Off PID 1 (local
26
+ * macOS dev, or if an init such as tini is ever placed above the daemon),
27
+ * orphans reparent to that init and are reaped there, so there is nothing for
28
+ * this to do. Because the daemon is PID 1, orphans already reparent to it and
29
+ * `PR_SET_CHILD_SUBREAPER` is unnecessary. It is additionally gated behind the
30
+ * `daemon.reapOrphanedSubprocesses` config flag (default off) so the behavior
31
+ * can be enabled per workspace for validation before becoming the default.
32
+ *
33
+ * References:
34
+ * - libuv reaps its own children by pid on SIGCHLD (`uv__wait_children`):
35
+ * https://github.com/nodejs/node/blob/main/deps/uv/src/unix/process.c
36
+ * - Subreaper reaping pattern for runtimes embedding libuv (specific-pid +
37
+ * WNOHANG, never `waitpid(-1)`, grace window for libuv co-existence):
38
+ * https://github.com/coopergwrenn/prctl-subreaper
39
+ * - waitpid(2): https://man7.org/linux/man-pages/man2/waitpid.2.html
40
+ */
41
+
42
+ import { readdirSync, readFileSync } from "node:fs";
43
+ import { dlopen, FFIType, ptr } from "bun:ffi";
44
+
45
+ import { getConfigReadOnly } from "../config/loader.js";
46
+ import { getLogger } from "../util/logger.js";
47
+
48
+ const log = getLogger("orphan-reaper");
49
+
50
+ /** Linux `WNOHANG` — return immediately if no child has changed state. */
51
+ const WNOHANG = 1;
52
+
53
+ const SCAN_INTERVAL_MS = 60_000;
54
+
55
+ let scanTimer: ReturnType<typeof setInterval> | null = null;
56
+
57
+ /** Zombie child PIDs observed on the previous scan (the grace set). */
58
+ let seenLastScan: Set<number> = new Set();
59
+
60
+ type WaitpidFn = (pid: number, statusPtr: unknown, options: number) => number;
61
+
62
+ let waitpid: WaitpidFn | null = null;
63
+ // Held at module scope so the backing buffer is not GC'd while `waitStatusPtr`
64
+ // keeps only a raw pointer into it (waitpid writes the exit status here).
65
+ let waitStatusBuf: Int32Array | null = null;
66
+ let waitStatusPtr: unknown = null;
67
+
68
+ /**
69
+ * Bind libc `waitpid` via FFI. Returns false (and disables the reaper) if FFI
70
+ * is unavailable so daemon startup never fails on this subsystem.
71
+ */
72
+ function initWaitpid(): boolean {
73
+ if (waitpid) return true;
74
+ try {
75
+ const lib = dlopen("libc.so.6", {
76
+ waitpid: {
77
+ args: [FFIType.i32, FFIType.ptr, FFIType.i32],
78
+ returns: FFIType.i32,
79
+ },
80
+ });
81
+ // Reusable out-param buffer for the wstatus we don't inspect.
82
+ waitStatusBuf = new Int32Array(1);
83
+ waitStatusPtr = ptr(waitStatusBuf);
84
+ waitpid = lib.symbols.waitpid as unknown as WaitpidFn;
85
+ return true;
86
+ } catch (err) {
87
+ log.warn(
88
+ { err },
89
+ "Orphan reaper unavailable: failed to bind libc waitpid via FFI",
90
+ );
91
+ return false;
92
+ }
93
+ }
94
+
95
+ export interface ZombieChild {
96
+ pid: number;
97
+ comm: string;
98
+ }
99
+
100
+ /**
101
+ * Parse a `/proc/<pid>/stat` line into its leading fields. `comm` (the
102
+ * executable name) may itself contain spaces and parentheses, so the fixed
103
+ * fields are read relative to the final `)` rather than by naive splitting.
104
+ * Returns null if the line is malformed.
105
+ */
106
+ export function parseProcStat(
107
+ content: string,
108
+ ): { comm: string; state: string; ppid: number } | null {
109
+ const lparen = content.indexOf("(");
110
+ const rparen = content.lastIndexOf(")");
111
+ if (lparen === -1 || rparen === -1 || rparen < lparen) return null;
112
+ const comm = content.slice(lparen + 1, rparen);
113
+ const rest = content.slice(rparen + 2).split(" ");
114
+ const state = rest[0];
115
+ const ppid = Number(rest[1]);
116
+ if (!state || !Number.isInteger(ppid)) return null;
117
+ return { comm, state, ppid };
118
+ }
119
+
120
+ /**
121
+ * Given the zombie child PIDs seen this scan and those seen on the previous
122
+ * scan, decide which to reap now. A zombie is only reaped once it has
123
+ * survived a full interval (present in `seenLast`), leaving newly-defunct
124
+ * children for libuv to reap first. Returns the PIDs to reap and the set to
125
+ * carry into the next scan.
126
+ */
127
+ export function selectReapable(
128
+ current: number[],
129
+ seenLast: Set<number>,
130
+ ): { reap: number[]; nextSeen: Set<number> } {
131
+ const reap = current.filter((pid) => seenLast.has(pid));
132
+ return { reap, nextSeen: new Set(current) };
133
+ }
134
+
135
+ /**
136
+ * Scan `/proc` for zombie (`Z`) processes whose parent is this daemon.
137
+ * Reparented orphans keep their original process group but their parent
138
+ * becomes PID 1 (the daemon), so they appear here once defunct.
139
+ */
140
+ function findZombieChildren(): ZombieChild[] {
141
+ const selfPid = process.pid;
142
+ const zombies: ZombieChild[] = [];
143
+ let entries: string[];
144
+ try {
145
+ entries = readdirSync("/proc");
146
+ } catch {
147
+ return zombies;
148
+ }
149
+ for (const entry of entries) {
150
+ const pid = Number(entry);
151
+ if (!Number.isInteger(pid) || pid <= 1) continue;
152
+ let stat: string;
153
+ try {
154
+ stat = readFileSync(`/proc/${pid}/stat`, "utf8");
155
+ } catch {
156
+ // Process exited between readdir and read — skip.
157
+ continue;
158
+ }
159
+ const parsed = parseProcStat(stat);
160
+ if (parsed && parsed.state === "Z" && parsed.ppid === selfPid) {
161
+ zombies.push({ pid, comm: parsed.comm });
162
+ }
163
+ }
164
+ return zombies;
165
+ }
166
+
167
+ /**
168
+ * Reap zombie children that have persisted for at least one scan interval,
169
+ * leaving newly-defunct children for libuv to reap first.
170
+ */
171
+ function reapScan(): void {
172
+ if (!waitpid) return;
173
+ const zombies = findZombieChildren();
174
+ const byPid = new Map(zombies.map((z) => [z.pid, z]));
175
+ const { reap, nextSeen } = selectReapable([...byPid.keys()], seenLastScan);
176
+ const reaped: ZombieChild[] = [];
177
+ for (const pid of reap) {
178
+ const rc = waitpid(pid, waitStatusPtr, WNOHANG);
179
+ // rc > 0: reaped. rc <= 0 (0 = not yet, -1 = ECHILD/raced): leave it.
180
+ if (rc > 0) reaped.push(byPid.get(pid)!);
181
+ }
182
+ seenLastScan = nextSeen;
183
+ if (reaped.length > 0) {
184
+ log.info(
185
+ {
186
+ count: reaped.length,
187
+ pids: reaped.map((z) => z.pid),
188
+ comms: reaped.map((z) => z.comm),
189
+ },
190
+ "Reaped orphaned subprocesses reparented to the daemon (PID 1)",
191
+ );
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Read the opt-in gate from workspace config (`daemon.reapOrphanedSubprocesses`),
197
+ * tolerating a missing or malformed config so startup never fails on it.
198
+ */
199
+ function isReaperEnabled(): boolean {
200
+ try {
201
+ return getConfigReadOnly().daemon.reapOrphanedSubprocesses;
202
+ } catch {
203
+ return false;
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Start the periodic orphan reaper. No-op unless the daemon is PID 1 on Linux
209
+ * (otherwise reparented orphans are reaped by the real init) and the
210
+ * `daemon.reapOrphanedSubprocesses` config gate is enabled.
211
+ */
212
+ export function startOrphanReaper(): void {
213
+ if (scanTimer) return;
214
+ if (process.platform !== "linux" || process.pid !== 1) {
215
+ log.info(
216
+ { platform: process.platform, pid: process.pid },
217
+ "Orphan reaper not started: daemon is not PID 1 on Linux",
218
+ );
219
+ return;
220
+ }
221
+ if (!isReaperEnabled()) {
222
+ log.info(
223
+ "Orphan reaper not started: daemon.reapOrphanedSubprocesses is disabled",
224
+ );
225
+ return;
226
+ }
227
+ if (!initWaitpid()) return;
228
+ seenLastScan = new Set();
229
+ scanTimer = setInterval(reapScan, SCAN_INTERVAL_MS);
230
+ scanTimer.unref?.();
231
+ log.info({ intervalMs: SCAN_INTERVAL_MS }, "Orphan reaper started");
232
+ }
233
+
234
+ export function stopOrphanReaper(): void {
235
+ if (scanTimer) {
236
+ clearInterval(scanTimer);
237
+ scanTimer = null;
238
+ }
239
+ seenLastScan = new Set();
240
+ }
@@ -0,0 +1,230 @@
1
+ import type { ContextWindowConfig } from "../config/schemas/inference.js";
2
+ import type {
3
+ ContextWindowCompactOptions,
4
+ ContextWindowResult,
5
+ } from "../context/window-manager.js";
6
+ import type { Message } from "../providers/types.js";
7
+ import {
8
+ createInitialReducerState,
9
+ reduceContextOverflow,
10
+ type ReducerState,
11
+ } from "./context-overflow-reducer.js";
12
+ import type { InjectionMode } from "./conversation-runtime-assembly.js";
13
+
14
+ /**
15
+ * Input to the overflow-reduction loop. Captures everything the reducer
16
+ * tier loop needs, including the message history, reducer configuration,
17
+ * and side-effect callbacks that bridge the loop back to the orchestrator's
18
+ * mutable per-turn state (context-window manager, activity emitter, runtime
19
+ * injection reassembly, memory reinjection).
20
+ *
21
+ * The callbacks are supplied by the orchestrator because the reducer loop
22
+ * needs to coordinate with state that lives on the `AgentLoopConversationContext`
23
+ * (message mutation, compaction event emission, circuit breaker tracking,
24
+ * injection block reassembly). Keeping them as explicit callbacks keeps the
25
+ * loop free of any dependency on the agent-loop context object.
26
+ */
27
+ export interface OverflowReduceArgs {
28
+ /** Bare persisted message history (the reducer applies results to a copy
29
+ * of this array). */
30
+ readonly messages: Message[];
31
+ /** Current run-time message array with runtime injections applied. */
32
+ readonly runMessages: Message[];
33
+ /** System prompt used for post-step token estimation. */
34
+ readonly systemPrompt: string;
35
+ /** Provider name used for token estimation (calibration provider key). */
36
+ readonly providerName: string;
37
+ /** Context window config (drives compaction behavior). */
38
+ readonly contextWindow: ContextWindowConfig;
39
+ /** Token budget the reducer must get below (preflight budget). */
40
+ readonly preflightBudget: number;
41
+ /** Tool-token overhead included in every estimation call. */
42
+ readonly toolTokenBudget?: number;
43
+ /** Maximum reducer iterations before the loop exits unconditionally. */
44
+ readonly maxAttempts: number;
45
+ /** Abort signal threaded through compaction calls. */
46
+ readonly abortSignal?: AbortSignal;
47
+ /**
48
+ * Compaction callback — the loop never owns the ContextWindowManager
49
+ * instance. The orchestrator supplies this closure so the loop can
50
+ * delegate the forced-compaction tier without crossing the infra
51
+ * boundary on its own.
52
+ */
53
+ readonly compactFn: (
54
+ messages: Message[],
55
+ signal: AbortSignal | undefined,
56
+ options: unknown,
57
+ ) => Promise<ContextWindowResult>;
58
+ /**
59
+ * Invoked before each reducer iteration to emit the `context_compacting`
60
+ * activity state. The orchestrator owns activity emission because the
61
+ * signal is trust/channel aware.
62
+ */
63
+ readonly emitActivityState: () => void;
64
+ /**
65
+ * Invoked after each reducer step that produced a successful compaction.
66
+ * Handles circuit-breaker tracking, event emission, and context mutation.
67
+ */
68
+ readonly onCompactionResult: (
69
+ result: ContextWindowResult,
70
+ compactedBasis?: Message[],
71
+ ) => void | Promise<void>;
72
+ /**
73
+ * Invoked after each step to rebuild `runMessages` from the step's
74
+ * reduced history with the requested injection mode. The orchestrator
75
+ * owns this helper so the full per-turn injection options object doesn't
76
+ * leak into the loop. The current reduced messages array is passed
77
+ * explicitly so the orchestrator doesn't need to read mutable shared
78
+ * state. Returns the new `runMessages`.
79
+ *
80
+ * Two distinct "did compact" signals are passed so the orchestrator can
81
+ * apply the correct per-iteration vs sticky gating:
82
+ * - `stepCompacted` — whether THIS iteration's reducer step produced a
83
+ * fresh compaction. Gates PKB / NOW re-injection: compaction strips the
84
+ * existing blocks, so only iterations that just compacted need the
85
+ * content re-threaded. Iterations that only truncated tool results or
86
+ * downgraded injections must NOT force a re-injection or the token
87
+ * count grows each round.
88
+ * - `accumulatedCompacted` — whether ANY iteration in this invocation has
89
+ * compacted. Gates `slackChronologicalMessages` suppression: once
90
+ * compaction has run, the captured Slack transcript snapshot would
91
+ * overwrite the compacted history, so it must stay suppressed for every
92
+ * subsequent iteration even if that iteration didn't re-compact.
93
+ */
94
+ readonly reinjectForMode: (
95
+ messages: Message[],
96
+ mode: InjectionMode,
97
+ stepCompacted: boolean,
98
+ accumulatedCompacted: boolean,
99
+ ) => Promise<Message[]>;
100
+ /**
101
+ * Invoked after each step to post-estimate the rebuilt `runMessages`.
102
+ * Pulled out so the orchestrator controls how estimation is performed
103
+ * (and which fields feed it) without the loop reimplementing it.
104
+ */
105
+ readonly estimatePostInjection: (runMessages: Message[]) => number;
106
+ }
107
+
108
+ /** Output of the overflow-reduction loop. */
109
+ export interface OverflowReduceResult {
110
+ /** Final reduced `ctx.messages` value. */
111
+ readonly messages: Message[];
112
+ /** Final `runMessages` with re-applied runtime injections. */
113
+ readonly runMessages: Message[];
114
+ /** Final injection mode (may be `"minimal"` if the downgrade tier fired). */
115
+ readonly injectionMode: InjectionMode;
116
+ /** Accumulated reducer state at exit. */
117
+ readonly reducerState: ReducerState;
118
+ /** True if any step successfully compacted history. */
119
+ readonly reducerCompacted: boolean;
120
+ /** How many iterations of the tier loop executed. */
121
+ readonly attempts: number;
122
+ }
123
+
124
+ /**
125
+ * Run the context-overflow reducer tier loop — forced compaction, tool-result
126
+ * truncation, media stubbing, injection downgrade — plus the post-step
127
+ * re-injection / re-estimation convergence check.
128
+ *
129
+ * The forced-compaction tier is delegated through `args.compactFn`; the other
130
+ * tiers mutate the message array directly. After each step the orchestrator
131
+ * rebuilds `runMessages` via `args.reinjectForMode` and the loop re-estimates
132
+ * the post-injection token count, exiting once it fits the preflight budget,
133
+ * the reducer is exhausted, or `maxAttempts` is reached.
134
+ */
135
+ export async function runOverflowReductionLoop(
136
+ args: OverflowReduceArgs,
137
+ ): Promise<OverflowReduceResult> {
138
+ let messages = args.messages;
139
+ let runMessages = args.runMessages;
140
+ let injectionMode: "full" | "minimal" = "full";
141
+ let reducerState: ReducerState = createInitialReducerState();
142
+ let reducerCompacted = false;
143
+ let attempts = 0;
144
+
145
+ while (attempts < args.maxAttempts && !reducerState.exhausted) {
146
+ // Abort check at the top of every iteration. When the caller aborts
147
+ // externally, this check lets us bail out BETWEEN iterations rather
148
+ // than letting another round of compaction / re-injection mutate
149
+ // `ctx.messages` after the turn has already failed. Individual
150
+ // `reduceContextOverflow` calls also honor the signal, but without this
151
+ // gate a fresh iteration could still start after the signal fires,
152
+ // since the previous one returned normally before the abort propagated.
153
+ args.abortSignal?.throwIfAborted();
154
+
155
+ attempts++;
156
+ args.emitActivityState();
157
+
158
+ const basisMessages = messages;
159
+ const step = await reduceContextOverflow(
160
+ basisMessages,
161
+ {
162
+ providerName: args.providerName,
163
+ systemPrompt: args.systemPrompt,
164
+ contextWindow: args.contextWindow,
165
+ targetTokens: args.preflightBudget,
166
+ toolTokenBudget: args.toolTokenBudget,
167
+ },
168
+ reducerState,
169
+ (msgs, signal, opts: ContextWindowCompactOptions) =>
170
+ args.compactFn(msgs, signal, opts),
171
+ args.abortSignal,
172
+ );
173
+
174
+ reducerState = step.state;
175
+ messages = step.messages;
176
+ injectionMode = step.state.injectionMode;
177
+
178
+ // Per-iteration compaction flag: whether THIS step just produced a
179
+ // fresh compaction. PKB / NOW re-injection is gated on this — see the
180
+ // reinjectForMode JSDoc for why the two signals differ.
181
+ const stepCompacted = step.compactionResult?.compacted === true;
182
+
183
+ // Let the orchestrator apply compaction side effects (circuit-breaker
184
+ // tracking, event emission, ctx mutation) before we re-inject.
185
+ if (step.compactionResult) {
186
+ await args.onCompactionResult(step.compactionResult, basisMessages);
187
+ if (stepCompacted) {
188
+ reducerCompacted = true;
189
+ }
190
+ }
191
+
192
+ // Second abort gate — if the side effects or the step itself took us
193
+ // past the deadline, don't rebuild runMessages or iterate again.
194
+ args.abortSignal?.throwIfAborted();
195
+
196
+ // Rebuild runMessages via the orchestrator-supplied helper (which
197
+ // re-runs `applyRuntimeInjections` with potentially downgraded mode
198
+ // and freshly re-hydrated PKB/NOW blocks after compaction). We pass
199
+ // the current reduced `messages` explicitly so the orchestrator never
200
+ // has to read from mutable shared state to rebuild runMessages — a
201
+ // tier that doesn't trigger compaction (tool-result truncation, media
202
+ // stubbing) won't update `ctx.messages` on its own.
203
+ //
204
+ // `stepCompacted` and `reducerCompacted` are both passed so the
205
+ // orchestrator can gate PKB / NOW re-injection per-iteration while
206
+ // keeping `slackChronologicalMessages` suppressed once any iteration
207
+ // has compacted.
208
+ runMessages = await args.reinjectForMode(
209
+ messages,
210
+ injectionMode,
211
+ stepCompacted,
212
+ reducerCompacted,
213
+ );
214
+
215
+ // Re-estimate with injections included — `step.estimatedTokens` was
216
+ // computed on bare history and doesn't account for tokens added by
217
+ // runtime injections.
218
+ const postInjectionTokens = args.estimatePostInjection(runMessages);
219
+ if (postInjectionTokens <= args.preflightBudget) break;
220
+ }
221
+
222
+ return {
223
+ messages,
224
+ runMessages,
225
+ injectionMode,
226
+ reducerState,
227
+ reducerCompacted,
228
+ attempts,
229
+ };
230
+ }
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Persistence for the image-too-large recovery path.
3
+ *
4
+ * When the provider rejects a turn because an attached image exceeds its
5
+ * limits, the agent loop downgrades the offending image blocks in memory and
6
+ * retries. That transformation is transient — the stored message row keeps the
7
+ * full-size image block, so the rejected image is rehydrated on every later
8
+ * turn and keeps re-entering the model's context. This module makes the
9
+ * downgrade durable for images that can *never* be transmitted, so a rejected
10
+ * upload cannot resurface after the user re-uploads a smaller version.
11
+ */
12
+
13
+ import { optimizeImageForTransport } from "../agent/image-optimize.js";
14
+ import { parseImageDimensions } from "../context/image-dimensions.js";
15
+ import {
16
+ getMessages,
17
+ updateMessageContent,
18
+ } from "../memory/conversation-crud.js";
19
+ import type { ContentBlock } from "../providers/types.js";
20
+ import { getLogger } from "../util/logger.js";
21
+
22
+ const log = getLogger("persist-unsendable-image");
23
+
24
+ // Anthropic rejects any image whose longest side exceeds this many pixels,
25
+ // regardless of payload size. Mirrors the user-facing message surfaced by
26
+ // `classifyConversationError` for the IMAGE_TOO_LARGE code.
27
+ // https://docs.anthropic.com/en/docs/build-with-claude/vision#image-size
28
+ const PROVIDER_MAX_IMAGE_DIMENSION = 8000;
29
+
30
+ // Anthropic rejects any single image whose base64 payload exceeds 5 MB.
31
+ // https://docs.anthropic.com/en/docs/build-with-claude/vision#image-size
32
+ const PROVIDER_MAX_IMAGE_PAYLOAD_BYTES = 5 * 1024 * 1024;
33
+
34
+ /**
35
+ * Note left in place of an image that cannot be sent to the provider. Shared
36
+ * with the in-memory recovery path so the persisted history matches what the
37
+ * model saw on the turn the image was rejected.
38
+ */
39
+ export const UNSENDABLE_IMAGE_NOTE =
40
+ "(An image was attached but could not be sent — its dimensions exceed the provider limit and automatic resize was not available. Please resize the image and try again.)";
41
+
42
+ /**
43
+ * True when a stored image block can never be transmitted to the provider: it
44
+ * violates a provider hard limit (per-side pixel cap or payload size) and
45
+ * cannot be shrunk to fit (re-optimization is a no-op).
46
+ *
47
+ * Stored blocks are already post-optimization, so a block that is still
48
+ * oversized here only stays oversized because resizing is unavailable on this
49
+ * host (e.g. `sips` is absent off macOS, or the format is unsupported). A
50
+ * downscalable image would have been reduced at upload time and would not reach
51
+ * this predicate, so it is left untouched.
52
+ */
53
+ function isImagePermanentlyUnsendable(
54
+ block: Extract<ContentBlock, { type: "image" }>,
55
+ ): boolean {
56
+ const payloadBytes = block.source.data.length;
57
+ const dims = parseImageDimensions(block.source.data, block.source.media_type);
58
+ const exceedsDimensionCap =
59
+ dims != null &&
60
+ (dims.width > PROVIDER_MAX_IMAGE_DIMENSION ||
61
+ dims.height > PROVIDER_MAX_IMAGE_DIMENSION);
62
+ const exceedsPayloadCap = payloadBytes > PROVIDER_MAX_IMAGE_PAYLOAD_BYTES;
63
+ if (!exceedsDimensionCap && !exceedsPayloadCap) return false;
64
+
65
+ const optimized = optimizeImageForTransport(
66
+ block.source.data,
67
+ block.source.media_type,
68
+ );
69
+ return optimized.data === block.source.data;
70
+ }
71
+
72
+ /**
73
+ * Rewrite every stored message in a conversation that holds a permanently
74
+ * unsendable image, replacing those image blocks with {@link
75
+ * UNSENDABLE_IMAGE_NOTE}. Reads stored content directly (not the in-memory,
76
+ * injection-enriched copy) so injected prefixes and hydrated source paths are
77
+ * never written back.
78
+ *
79
+ * Idempotent: once an image is replaced by the note there is no image block
80
+ * left to match, so re-running is a no-op. Returns the number of rewritten
81
+ * messages.
82
+ */
83
+ export function persistUnsendableImageDowngrades(
84
+ conversationId: string,
85
+ ): number {
86
+ let rewritten = 0;
87
+ for (const row of getMessages(conversationId)) {
88
+ // Cheap prefilter — JSON.stringify emits no spaces, so an image block
89
+ // always serializes with this exact substring.
90
+ if (!row.content.includes('"type":"image"')) continue;
91
+
92
+ let parsed: unknown;
93
+ try {
94
+ parsed = JSON.parse(row.content);
95
+ } catch {
96
+ continue;
97
+ }
98
+ if (!Array.isArray(parsed)) continue;
99
+
100
+ let changed = false;
101
+ const next = (parsed as ContentBlock[]).map((block): ContentBlock => {
102
+ if (block.type !== "image") return block;
103
+ if (!isImagePermanentlyUnsendable(block)) return block;
104
+ changed = true;
105
+ return { type: "text", text: UNSENDABLE_IMAGE_NOTE };
106
+ });
107
+ if (!changed) continue;
108
+
109
+ updateMessageContent(row.id, JSON.stringify(next));
110
+ rewritten++;
111
+ log.info(
112
+ { conversationId, messageId: row.id },
113
+ "Persisted unsendable-image downgrade so it cannot resurface on later turns",
114
+ );
115
+ }
116
+ return rewritten;
117
+ }
@@ -437,9 +437,7 @@ export async function processMessage(
437
437
  conversation.getMessages().push(cleanMsg);
438
438
 
439
439
  conversation.emitActivityState("thinking", "context_compacting");
440
- const result = await conversation.forceCompact({
441
- targetInputTokensOverride: slashResult.targetInputTokensOverride,
442
- });
440
+ const result = await conversation.forceCompact();
443
441
  const responseText = formatCompactResult(result);
444
442
  const assistantMsg = createAssistantMessage(responseText);
445
443
  const persistedAssistant = await addMessage(
@@ -39,6 +39,8 @@ import {
39
39
  conversationEntries,
40
40
  deleteConversation,
41
41
  getConversationMap,
42
+ } from "./conversation-registry.js";
43
+ import {
42
44
  getOrCreateConversation as getOrCreateActiveConversation,
43
45
  initConversationLifecycle,
44
46
  setCesClientPromise,
@@ -1,14 +1,16 @@
1
1
  import { v4 as uuid } from "uuid";
2
2
 
3
+ import type {
4
+ TraceEvent,
5
+ TraceEventKind,
6
+ TraceEventStatus,
7
+ } from "../api/events/trace-event.js";
3
8
  import {
4
9
  getMaxSequence,
5
10
  persistTraceEvent,
6
11
  } from "../memory/trace-event-store.js";
7
12
  import { getLogger } from "../util/logger.js";
8
- import type { ServerMessage, TraceEventKind } from "./message-protocol.js";
9
- import type { TraceEvent } from "./message-types/messages.js";
10
-
11
- export type TraceEventStatus = "info" | "success" | "warning" | "error";
13
+ import type { ServerMessage } from "./message-protocol.js";
12
14
 
13
15
  const log = getLogger("trace-emitter");
14
16
 
@@ -5,6 +5,8 @@
5
5
  * imports (memory/conversation-crud → daemon/conversation-runtime-assembly).
6
6
  */
7
7
  import type { ChannelId } from "../channels/types.js";
8
+ import { isHttpAuthDisabled } from "../config/env.js";
9
+ import type { TrustClass } from "../runtime/actor-trust-resolver.js";
8
10
 
9
11
  export interface TrustContext {
10
12
  /** Channel through which the inbound message arrived. */
@@ -62,3 +64,20 @@ export const FALLBACK_TURN_TRUST: TrustContext = {
62
64
  sourceChannel: "vellum",
63
65
  trustClass: "unknown",
64
66
  };
67
+
68
+ /**
69
+ * Resolve the effective trust class for an actor.
70
+ *
71
+ * When HTTP auth is disabled (dev bypass), always returns `'guardian'`
72
+ * so that control-plane gates don't block local development.
73
+ *
74
+ * When no trust context is available (e.g. desktop-only conversations that
75
+ * don't go through channel trust resolution), defaults to `'unknown'`
76
+ * to fail-closed.
77
+ */
78
+ export function resolveTrustClass(
79
+ trustContext: TrustContext | undefined,
80
+ ): TrustClass {
81
+ if (isHttpAuthDisabled()) return "guardian";
82
+ return trustContext?.trustClass ?? "unknown";
83
+ }
@@ -140,6 +140,8 @@ function translateAgentEventToServerMessage(
140
140
  case "context_compacting":
141
141
  case "compaction_circuit_open":
142
142
  case "compaction_circuit_closed":
143
+ case "compaction_completed":
144
+ case "history_stripped":
143
145
  case "agent_loop_exit":
144
146
  return null;
145
147
  case "llm_call_started":
@@ -192,7 +194,7 @@ export function conversationToWakeTarget(
192
194
  },
193
195
  isProcessing: () => conversation.isProcessing(),
194
196
  markProcessing: (on) => {
195
- conversation.processing = on;
197
+ conversation.setProcessing(on);
196
198
  },
197
199
  setTrustContext: (ctx) => conversation.setTrustContext(ctx),
198
200
  setWakeAllowedTools: (tools) => {