@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
@@ -13,8 +13,14 @@ import type { MessageQueuedDeletedEvent } from "../../api/events/message-queued-
13
13
  import type { MessageRequestCompleteEvent } from "../../api/events/message-request-complete.js";
14
14
  import type { QuestionRequestEvent } from "../../api/events/question-request.js";
15
15
  import type { SecretRequestEvent } from "../../api/events/secret-request.js";
16
+ import type { ToolOutputChunkEvent } from "../../api/events/tool-output-chunk.js";
16
17
  import type { ToolResultEvent } from "../../api/events/tool-result.js";
18
+ import type { ToolUsePreviewStartEvent } from "../../api/events/tool-use-preview-start.js";
17
19
  import type { ToolUseStartEvent } from "../../api/events/tool-use-start.js";
20
+ import type {
21
+ TraceEvent,
22
+ TraceEventKind,
23
+ } from "../../api/events/trace-event.js";
18
24
  import type { TurnProfileAutoRoutedEvent } from "../../api/events/turn-profile-auto-routed.js";
19
25
  import type { UserMessageEchoEvent } from "../../api/events/user-message-echo.js";
20
26
  import type { ChannelId, InterfaceId } from "../../channels/types.js";
@@ -79,31 +85,6 @@ export interface AssistantThinkingDelta {
79
85
  messageId?: string;
80
86
  }
81
87
 
82
- export interface ToolOutputChunk {
83
- type: "tool_output_chunk";
84
- chunk: string;
85
- conversationId?: string;
86
- toolUseId?: string;
87
- subType?: "tool_start" | "tool_complete" | "status";
88
- subToolName?: string;
89
- subToolInput?: string;
90
- subToolIsError?: boolean;
91
- subToolId?: string;
92
- /** Database ID of the assistant message that owns the parent tool_use
93
- * block. Same semantics as `AssistantTextDeltaEvent.messageId`. */
94
- messageId?: string;
95
- }
96
-
97
- export interface ToolUsePreviewStart {
98
- type: "tool_use_preview_start";
99
- toolUseId: string;
100
- toolName: string;
101
- conversationId?: string;
102
- /** Database ID of the assistant message that owns this tool_use block.
103
- * Same semantics as `AssistantTextDeltaEvent.messageId`. */
104
- messageId?: string;
105
- }
106
-
107
88
  export interface ToolInputDelta {
108
89
  type: "tool_input_delta";
109
90
  toolName: string;
@@ -165,36 +146,7 @@ export interface ConversationInferenceProfileUpdated {
165
146
  expiresAt?: number | null;
166
147
  }
167
148
 
168
- export type TraceEventKind =
169
- | "request_received"
170
- | "request_queued"
171
- | "request_dequeued"
172
- | "llm_call_started"
173
- | "llm_call_finished"
174
- | "assistant_message"
175
- | "tool_started"
176
- | "tool_permission_requested"
177
- | "tool_permission_decided"
178
- | "tool_finished"
179
- | "tool_failed"
180
- | "generation_handoff"
181
- | "message_complete"
182
- | "generation_cancelled"
183
- | "request_error"
184
- | "tool_profiling_summary";
185
-
186
- export interface TraceEvent {
187
- type: "trace_event";
188
- eventId: string;
189
- conversationId: string;
190
- requestId?: string;
191
- timestampMs: number;
192
- sequence: number;
193
- kind: TraceEventKind;
194
- status?: "info" | "success" | "warning" | "error";
195
- summary: string;
196
- attributes?: Record<string, string | number | boolean | null>;
197
- }
149
+ export type { TraceEvent, TraceEventKind };
198
150
 
199
151
  // --- Domain-level union aliases (consumed by the barrel file) ---
200
152
 
@@ -210,8 +162,8 @@ export type _MessagesServerMessages =
210
162
  | AssistantTextDeltaEvent
211
163
  | AssistantThinkingDelta
212
164
  | ToolUseStartEvent
213
- | ToolUsePreviewStart
214
- | ToolOutputChunk
165
+ | ToolUsePreviewStartEvent
166
+ | ToolOutputChunkEvent
215
167
  | ToolInputDelta
216
168
  | ToolResultEvent
217
169
  | ConfirmationRequestEvent
@@ -86,6 +86,7 @@ interface SlimSkillBase {
86
86
  id: string;
87
87
  name: string;
88
88
  description: string;
89
+ icon?: string;
89
90
  emoji?: string;
90
91
  kind: "bundled" | "installed" | "catalog";
91
92
  status: "enabled" | "disabled" | "available";
@@ -157,6 +158,7 @@ interface SkillDetailBase {
157
158
  id: string;
158
159
  name: string;
159
160
  description: string;
161
+ icon?: string;
160
162
  emoji?: string;
161
163
  kind: "bundled" | "installed" | "catalog";
162
164
  status: "enabled" | "disabled" | "available";
@@ -4,6 +4,9 @@
4
4
 
5
5
  export type SurfaceType =
6
6
  | "card"
7
+ | "choice"
8
+ | "copy_block"
9
+ | "oauth_connect"
7
10
  | "form"
8
11
  | "list"
9
12
  | "table"
@@ -11,9 +14,12 @@ export type SurfaceType =
11
14
  | "dynamic_page"
12
15
  | "file_upload"
13
16
  | "document_preview"
14
- | "task_preferences";
17
+ | "task_preferences"
18
+ | "work_result";
15
19
 
16
20
  export const INTERACTIVE_SURFACE_TYPES: SurfaceType[] = [
21
+ "choice",
22
+ "oauth_connect",
17
23
  "form",
18
24
  "confirmation",
19
25
  "dynamic_page",
@@ -40,6 +46,45 @@ export interface CardSurfaceData {
40
46
  templateData?: Record<string, unknown>;
41
47
  }
42
48
 
49
+ export interface ChoiceOption {
50
+ id: string;
51
+ title: string;
52
+ description?: string;
53
+ /** Visually highlight this option as the assistant's recommendation. */
54
+ recommended?: boolean;
55
+ /** Optional structured payload returned with this choice. */
56
+ data?: Record<string, unknown>;
57
+ }
58
+
59
+ export interface ChoiceSurfaceData {
60
+ description?: string;
61
+ options: ChoiceOption[];
62
+ selectionMode?: "single" | "multiple";
63
+ /**
64
+ * When true, clicking an option submits it immediately. Defaults to true for
65
+ * single-select choice surfaces.
66
+ */
67
+ commitOnSelect?: boolean;
68
+ submitLabel?: string;
69
+ }
70
+
71
+ export interface CopyBlockSurfaceData {
72
+ text: string;
73
+ label?: string;
74
+ language?: string;
75
+ }
76
+
77
+ export interface OAuthConnectSurfaceData {
78
+ /** OAuth provider key from the managed provider catalog, e.g. "google". */
79
+ providerKey: string;
80
+ /** Optional display label. The client falls back to the provider catalog. */
81
+ displayName?: string;
82
+ /** Optional helper text. The client falls back to the provider catalog. */
83
+ description?: string;
84
+ /** Optional provider logo URL. The client falls back to the provider catalog. */
85
+ logoUrl?: string | null;
86
+ }
87
+
43
88
  export interface FormField {
44
89
  id: string;
45
90
  type: "text" | "textarea" | "select" | "toggle" | "number" | "password";
@@ -148,15 +193,79 @@ export interface DocumentPreviewSurfaceData {
148
193
  subtitle?: string;
149
194
  }
150
195
 
196
+ export type WorkResultStatus =
197
+ | "completed"
198
+ | "partial"
199
+ | "failed"
200
+ | "in_progress";
201
+
202
+ export type WorkResultTone = "neutral" | "positive" | "warning" | "negative";
203
+
204
+ export type WorkResultSectionType =
205
+ | "items"
206
+ | "timeline"
207
+ | "diff"
208
+ | "artifacts"
209
+ | "warnings";
210
+
211
+ export interface WorkResultMetric {
212
+ label: string;
213
+ value: string | number;
214
+ detail?: string;
215
+ tone?: WorkResultTone;
216
+ }
217
+
218
+ export interface WorkResultMetadata {
219
+ label: string;
220
+ value: string | number;
221
+ }
222
+
223
+ export interface WorkResultItem {
224
+ id?: string;
225
+ title: string;
226
+ description?: string;
227
+ status?: string;
228
+ tone?: WorkResultTone;
229
+ metadata?: WorkResultMetadata[];
230
+ href?: string;
231
+ }
232
+
233
+ export interface WorkResultDiff {
234
+ label?: string;
235
+ before?: string;
236
+ after?: string;
237
+ }
238
+
239
+ export interface WorkResultSection {
240
+ id?: string;
241
+ title: string;
242
+ description?: string;
243
+ type?: WorkResultSectionType;
244
+ items?: WorkResultItem[];
245
+ diffs?: WorkResultDiff[];
246
+ }
247
+
248
+ export interface WorkResultSurfaceData {
249
+ eyebrow?: string;
250
+ status?: WorkResultStatus;
251
+ summary?: string;
252
+ metrics?: WorkResultMetric[];
253
+ sections?: WorkResultSection[];
254
+ }
255
+
151
256
  export type SurfaceData =
152
257
  | CardSurfaceData
258
+ | ChoiceSurfaceData
259
+ | CopyBlockSurfaceData
260
+ | OAuthConnectSurfaceData
153
261
  | FormSurfaceData
154
262
  | ListSurfaceData
155
263
  | TableSurfaceData
156
264
  | ConfirmationSurfaceData
157
265
  | DynamicPageSurfaceData
158
266
  | FileUploadSurfaceData
159
- | DocumentPreviewSurfaceData;
267
+ | DocumentPreviewSurfaceData
268
+ | WorkResultSurfaceData;
160
269
 
161
270
  // === Client → Server ===
162
271
 
@@ -197,6 +306,21 @@ export interface UiSurfaceShowCard extends UiSurfaceShowBase {
197
306
  data: CardSurfaceData;
198
307
  }
199
308
 
309
+ export interface UiSurfaceShowChoice extends UiSurfaceShowBase {
310
+ surfaceType: "choice";
311
+ data: ChoiceSurfaceData;
312
+ }
313
+
314
+ export interface UiSurfaceShowCopyBlock extends UiSurfaceShowBase {
315
+ surfaceType: "copy_block";
316
+ data: CopyBlockSurfaceData;
317
+ }
318
+
319
+ export interface UiSurfaceShowOAuthConnect extends UiSurfaceShowBase {
320
+ surfaceType: "oauth_connect";
321
+ data: OAuthConnectSurfaceData;
322
+ }
323
+
200
324
  export interface UiSurfaceShowForm extends UiSurfaceShowBase {
201
325
  surfaceType: "form";
202
326
  data: FormSurfaceData;
@@ -232,15 +356,24 @@ export interface UiSurfaceShowDocumentPreview extends UiSurfaceShowBase {
232
356
  data: DocumentPreviewSurfaceData;
233
357
  }
234
358
 
359
+ export interface UiSurfaceShowWorkResult extends UiSurfaceShowBase {
360
+ surfaceType: "work_result";
361
+ data: WorkResultSurfaceData;
362
+ }
363
+
235
364
  export type UiSurfaceShow =
236
365
  | UiSurfaceShowCard
366
+ | UiSurfaceShowChoice
367
+ | UiSurfaceShowCopyBlock
368
+ | UiSurfaceShowOAuthConnect
237
369
  | UiSurfaceShowForm
238
370
  | UiSurfaceShowList
239
371
  | UiSurfaceShowTable
240
372
  | UiSurfaceShowConfirmation
241
373
  | UiSurfaceShowDynamicPage
242
374
  | UiSurfaceShowFileUpload
243
- | UiSurfaceShowDocumentPreview;
375
+ | UiSurfaceShowDocumentPreview
376
+ | UiSurfaceShowWorkResult;
244
377
 
245
378
  export interface UiSurfaceUpdate {
246
379
  type: "ui_surface_update";
@@ -0,0 +1,21 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+
3
+ import { getWorkspacePromptPath } from "../util/platform.js";
4
+ import { stripCommentLines } from "../util/strip-comment-lines.js";
5
+
6
+ /**
7
+ * Read the NOW.md scratchpad from the workspace prompt directory.
8
+ *
9
+ * Returns the trimmed content with `_`-prefixed comment lines stripped,
10
+ * or `null` if the file is missing, empty, or unreadable.
11
+ */
12
+ export function readNowScratchpad(): string | null {
13
+ const nowPath = getWorkspacePromptPath("NOW.md");
14
+ if (!existsSync(nowPath)) return null;
15
+ try {
16
+ const stripped = stripCommentLines(readFileSync(nowPath, "utf-8")).trim();
17
+ return stripped.length > 0 ? stripped : null;
18
+ } catch {
19
+ return null;
20
+ }
21
+ }
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Tests for the orphan subprocess reaper.
3
+ *
4
+ * - `parseProcStat` must read state/ppid correctly even when the executable
5
+ * name (`comm`) contains spaces and parentheses.
6
+ * - `selectReapable` must defer a zombie for one full scan interval (so libuv
7
+ * reaps its own tracked children first) and reap it on the next scan.
8
+ * - An integration test makes the test process a child subreaper via
9
+ * `PR_SET_CHILD_SUBREAPER`, orphans a grandchild, and verifies the
10
+ * exported logic defers-then-reaps the real `<defunct>` entry while libuv
11
+ * independently reaps the directly-spawned (tracked) child.
12
+ */
13
+ import { spawn } from "node:child_process";
14
+ import { readdirSync, readFileSync } from "node:fs";
15
+ import { dlopen, FFIType, ptr } from "bun:ffi";
16
+ import { afterAll, describe, expect, mock, test } from "bun:test";
17
+
18
+ mock.module("../util/logger.js", () => ({
19
+ getLogger: () =>
20
+ new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
21
+ }));
22
+
23
+ const { parseProcStat, selectReapable } = await import("./orphan-reaper.js");
24
+ const { DaemonConfigSchema } = await import("../config/schemas/platform.js");
25
+
26
+ describe("parseProcStat", () => {
27
+ test("parses a normal stat line", () => {
28
+ // GIVEN a well-formed /proc/<pid>/stat line for a zombie
29
+ const line = "1234 (bash) Z 1 1234 1234 0 -1 ...";
30
+ // WHEN it is parsed
31
+ const parsed = parseProcStat(line);
32
+ // THEN comm, state, and ppid are extracted
33
+ expect(parsed).toEqual({ comm: "bash", state: "Z", ppid: 1 });
34
+ });
35
+
36
+ test("handles comm containing spaces and parentheses", () => {
37
+ // GIVEN a stat line whose comm field itself contains spaces and parens
38
+ const line = "42 (weird (name) x) Z 1 42 42 0 -1 4194560";
39
+ // WHEN it is parsed
40
+ const parsed = parseProcStat(line);
41
+ // THEN fields are read relative to the final ')', not naive splitting
42
+ expect(parsed).toEqual({ comm: "weird (name) x", state: "Z", ppid: 1 });
43
+ });
44
+
45
+ test("reads a non-zombie running state", () => {
46
+ // GIVEN a running (non-zombie) process line
47
+ const line = "77 (node) R 12 77 77";
48
+ // WHEN it is parsed
49
+ const parsed = parseProcStat(line);
50
+ // THEN the running state and parent pid are reported
51
+ expect(parsed?.state).toBe("R");
52
+ expect(parsed?.ppid).toBe(12);
53
+ });
54
+
55
+ test("returns null for malformed lines", () => {
56
+ // GIVEN malformed or truncated stat content
57
+ // WHEN each is parsed
58
+ // THEN null is returned rather than a bogus record
59
+ expect(parseProcStat("")).toBeNull();
60
+ expect(parseProcStat("no parens here")).toBeNull();
61
+ expect(parseProcStat("123 (proc)")).toBeNull();
62
+ });
63
+ });
64
+
65
+ describe("selectReapable", () => {
66
+ test("defers a newly-seen zombie for one interval", () => {
67
+ // GIVEN zombies never seen on a previous scan
68
+ // WHEN deciding what to reap with an empty seen set
69
+ const { reap, nextSeen } = selectReapable([100, 101], new Set());
70
+ // THEN nothing is reaped yet, but both are carried into the next scan
71
+ expect(reap).toEqual([]);
72
+ expect([...nextSeen].sort()).toEqual([100, 101]);
73
+ });
74
+
75
+ test("reaps a zombie that survived the previous scan", () => {
76
+ // GIVEN pid 100 was already seen on the prior scan and 101 is new
77
+ // WHEN deciding what to reap
78
+ const { reap } = selectReapable([100, 101], new Set([100]));
79
+ // THEN only the survivor (100) is reaped; the newcomer is deferred
80
+ expect(reap).toEqual([100]);
81
+ });
82
+
83
+ test("drops PIDs that have disappeared from the next seen set", () => {
84
+ // GIVEN pid 100 was seen before but is gone now
85
+ // WHEN computing the next seen set
86
+ const { nextSeen } = selectReapable([101], new Set([100, 101]));
87
+ // THEN only currently-present pids are retained
88
+ expect([...nextSeen]).toEqual([101]);
89
+ });
90
+ });
91
+
92
+ describe("daemon.reapOrphanedSubprocesses gate", () => {
93
+ test("defaults to off so the reaper is opt-in", () => {
94
+ // GIVEN a daemon config with the reaper flag unspecified
95
+ // WHEN it is parsed with schema defaults
96
+ const parsed = DaemonConfigSchema.parse({});
97
+ // THEN the reaper is disabled unless explicitly turned on
98
+ expect(parsed.reapOrphanedSubprocesses).toBe(false);
99
+ });
100
+
101
+ test("honors an explicit opt-in", () => {
102
+ // GIVEN a daemon config that explicitly enables the reaper
103
+ // WHEN it is parsed
104
+ const parsed = DaemonConfigSchema.parse({ reapOrphanedSubprocesses: true });
105
+ // THEN the flag is respected
106
+ expect(parsed.reapOrphanedSubprocesses).toBe(true);
107
+ });
108
+ });
109
+
110
+ // ── Integration: real reparented orphan on Linux ────────────────────────────
111
+ const itLinux = process.platform === "linux" ? test : test.skip;
112
+
113
+ // Bind libc only on Linux — "libc.so.6" does not exist on macOS, so binding it
114
+ // unconditionally would throw at import and break the pure-function tests too.
115
+ const lib =
116
+ process.platform === "linux"
117
+ ? dlopen("libc.so.6", {
118
+ waitpid: {
119
+ args: [FFIType.i32, FFIType.ptr, FFIType.i32],
120
+ returns: FFIType.i32,
121
+ },
122
+ prctl: {
123
+ args: [
124
+ FFIType.i32,
125
+ FFIType.u64,
126
+ FFIType.u64,
127
+ FFIType.u64,
128
+ FFIType.u64,
129
+ ],
130
+ returns: FFIType.i32,
131
+ },
132
+ })
133
+ : null;
134
+ const WNOHANG = 1;
135
+ const PR_SET_CHILD_SUBREAPER = 36;
136
+ const statusBuf = new Int32Array(1);
137
+
138
+ function zombieChildPids(): number[] {
139
+ const self = process.pid;
140
+ const out: number[] = [];
141
+ for (const entry of readdirSync("/proc")) {
142
+ const pid = Number(entry);
143
+ if (!Number.isInteger(pid) || pid <= 1) continue;
144
+ let stat: string;
145
+ try {
146
+ stat = readFileSync(`/proc/${pid}/stat`, "utf8");
147
+ } catch {
148
+ continue;
149
+ }
150
+ const parsed = parseProcStat(stat);
151
+ if (parsed && parsed.state === "Z" && parsed.ppid === self) out.push(pid);
152
+ }
153
+ return out;
154
+ }
155
+
156
+ const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
157
+
158
+ afterAll(() => {
159
+ if (!lib) return;
160
+ // Reap anything still lingering so the test process leaves no zombies.
161
+ for (const pid of zombieChildPids())
162
+ lib.symbols.waitpid(pid, ptr(statusBuf), WNOHANG);
163
+ });
164
+
165
+ itLinux(
166
+ "defers then reaps a reparented orphan while libuv reaps the tracked child",
167
+ async () => {
168
+ if (!lib) return;
169
+ // GIVEN this process is a child subreaper, so orphaned grandchildren
170
+ // reparent here exactly as they reparent to a PID-1 daemon
171
+ expect(lib.symbols.prctl(PR_SET_CHILD_SUBREAPER, 1n, 0n, 0n, 0n)).toBe(0);
172
+
173
+ // AND a libuv-tracked child (A) that detaches a grandchild (B) into its
174
+ // own session and exits immediately; B reparents to us and, once it
175
+ // exits, becomes a zombie with our pid as its parent
176
+ let trackedChildExited = false;
177
+ const a = spawn("bash", ["-c", "setsid -f sleep 0.4; exit 0"], {
178
+ stdio: "ignore",
179
+ });
180
+ a.on("exit", () => {
181
+ trackedChildExited = true;
182
+ });
183
+
184
+ // AND we wait for that orphan to surface as our zombie child
185
+ let zombies: number[] = [];
186
+ for (let i = 0; i < 40 && zombies.length === 0; i++) {
187
+ await sleep(50);
188
+ zombies = zombieChildPids();
189
+ }
190
+ expect(zombies.length).toBeGreaterThan(0);
191
+ expect(trackedChildExited).toBe(true); // libuv reaped A independently
192
+
193
+ // WHEN we run the deferred-reap algorithm across two scans
194
+ // (scan #1 is the grace pass, scan #2 reaps the survivor)
195
+ const scan1 = selectReapable(zombieChildPids(), new Set<number>());
196
+ const scan2 = selectReapable(zombieChildPids(), scan1.nextSeen);
197
+ let reaped = 0;
198
+ for (const pid of scan2.reap) {
199
+ if (lib.symbols.waitpid(pid, ptr(statusBuf), WNOHANG) > 0) reaped++;
200
+ }
201
+ await sleep(50);
202
+
203
+ // THEN nothing is reaped on the grace pass, the survivor is reaped on the
204
+ // second pass, and no defunct child remains
205
+ expect(scan1.reap).toEqual([]);
206
+ expect(scan2.reap.length).toBeGreaterThan(0);
207
+ expect(reaped).toBeGreaterThan(0);
208
+ expect(zombieChildPids()).toEqual([]);
209
+ },
210
+ );