@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
@@ -14,43 +14,24 @@ import { getVisibleProviderCatalog } from "../providers/provider-catalog-visibil
14
14
  export type SlashResolution =
15
15
  | { kind: "passthrough"; content: string }
16
16
  | { kind: "unknown"; message: string }
17
- | { kind: "compact"; targetInputTokensOverride?: number }
17
+ | { kind: "compact" }
18
18
  | { kind: "clean" };
19
19
 
20
- const COMPACT_USAGE_HINT =
21
- "Usage: `/compact [<tokens>]` (e.g. `/compact 30000`, `/compact 30k`, `/compact 1m`).";
20
+ type CompactParse = { kind: "compact" } | { kind: "unknown"; message: string };
22
21
 
23
- type CompactParse =
24
- | { kind: "compact"; targetInputTokensOverride?: number }
25
- | { kind: "unknown"; message: string };
26
-
27
- const TOKEN_COUNT_PATTERN = /^(\d+(?:\.\d+)?)([km])?$/i;
28
22
  const COMPACT_COMMAND_PATTERN = /^\/compact(?:\s+(.+?))?\s*$/i;
29
23
 
30
- function parseTokenCount(input: string): number | null {
31
- const match = input.match(TOKEN_COUNT_PATTERN);
32
- if (!match) return null;
33
- const value = Number.parseFloat(match[1]);
34
- if (!Number.isFinite(value) || value <= 0) return null;
35
- const suffix = match[2]?.toLowerCase();
36
- const multiplier = suffix === "m" ? 1_000_000 : suffix === "k" ? 1_000 : 1;
37
- const tokens = Math.floor(value * multiplier);
38
- return tokens > 0 ? tokens : null;
39
- }
40
-
41
24
  function parseCompactCommand(trimmed: string): CompactParse | null {
42
25
  const match = trimmed.match(COMPACT_COMMAND_PATTERN);
43
26
  if (!match) return null;
44
27
  const rest = match[1]?.trim();
45
- if (!rest) return { kind: "compact" };
46
- const tokens = parseTokenCount(rest);
47
- if (tokens == null) {
28
+ if (rest) {
48
29
  return {
49
30
  kind: "unknown",
50
- message: `Unrecognized argument to \`/compact\`: \`${rest}\`. ${COMPACT_USAGE_HINT}`,
31
+ message: `\`/compact\` does not take arguments. Usage: \`/compact\`.`,
51
32
  };
52
33
  }
53
- return { kind: "compact", targetInputTokensOverride: tokens };
34
+ return { kind: "compact" };
54
35
  }
55
36
 
56
37
  type CleanParse = { kind: "clean" } | { kind: "unknown"; message: string };
@@ -448,7 +429,7 @@ export async function resolveSlash(
448
429
  return await resolveModelList();
449
430
  }
450
431
 
451
- // Handle /compact command (with optional `<tokens>` override).
432
+ // Handle /compact command (summarize history; takes no arguments).
452
433
  const compactParse = parseCompactCommand(trimmed);
453
434
  if (compactParse) return compactParse;
454
435
 
@@ -27,99 +27,18 @@ import { ProviderNotConfiguredError } from "../util/errors.js";
27
27
  import { getSandboxWorkingDir } from "../util/platform.js";
28
28
  import { Conversation } from "./conversation.js";
29
29
  import type { ConversationEvictor } from "./conversation-evictor.js";
30
+ import {
31
+ allConversations,
32
+ clearConversations,
33
+ conversationCount,
34
+ conversationIds,
35
+ deleteConversation,
36
+ findConversation,
37
+ setConversation,
38
+ } from "./conversation-registry.js";
30
39
  import type { ConversationCreateOptions } from "./handlers/shared.js";
31
40
  import { buildTransportHints } from "./transport-hints.js";
32
41
 
33
- // ── Private store ──────────────────────────────────────────────────
34
-
35
- const conversations = new Map<string, Conversation>();
36
-
37
- // ── Read helpers ───────────────────────────────────────────────────
38
-
39
- export function findConversation(
40
- conversationId: string,
41
- ): Conversation | undefined {
42
- return conversations.get(conversationId);
43
- }
44
-
45
- export function findConversationBySurfaceId(
46
- surfaceId: string,
47
- ): Conversation | undefined {
48
- // Fast path: exact surfaceId match in surfaceState
49
- for (const c of conversations.values()) {
50
- if (c.surfaceState.has(surfaceId)) return c;
51
- }
52
-
53
- // Fallback: standalone app surfaces use "app-open-{appId}" IDs that
54
- // were never part of any conversation. Extract the appId and find
55
- // a conversation whose surfaceState has a surface for that app.
56
- const appOpenPrefix = "app-open-";
57
- if (surfaceId.startsWith(appOpenPrefix)) {
58
- const appId = surfaceId.slice(appOpenPrefix.length);
59
- for (const c of conversations.values()) {
60
- for (const [, state] of c.surfaceState.entries()) {
61
- const data = state.data as unknown as Record<string, unknown>;
62
- if (data?.appId === appId) {
63
- // Register this surfaceId so subsequent lookups are O(1)
64
- c.surfaceState.set(surfaceId, state);
65
- return c;
66
- }
67
- }
68
- }
69
- }
70
-
71
- return undefined;
72
- }
73
-
74
- function conversationCount(): number {
75
- return conversations.size;
76
- }
77
-
78
- /** Iterate over all active conversations. */
79
- export function allConversations(): IterableIterator<Conversation> {
80
- return conversations.values();
81
- }
82
-
83
- /** Iterate over all [id, conversation] entries. */
84
- export function conversationEntries(): IterableIterator<
85
- [string, Conversation]
86
- > {
87
- return conversations.entries();
88
- }
89
-
90
- /** Iterate over all active conversation IDs. */
91
- function conversationIds(): IterableIterator<string> {
92
- return conversations.keys();
93
- }
94
-
95
- // ── Write helpers ──────────────────────────────────────────────────
96
-
97
- export function setConversation(
98
- conversationId: string,
99
- conversation: Conversation,
100
- ): void {
101
- conversations.set(conversationId, conversation);
102
- }
103
-
104
- export function deleteConversation(conversationId: string): boolean {
105
- return conversations.delete(conversationId);
106
- }
107
-
108
- export function clearConversations(): void {
109
- conversations.clear();
110
- }
111
-
112
- // ── Underlying Map (for the evictor, which takes a mutable ref) ───
113
-
114
- /**
115
- * Expose the raw Map for the {@link ConversationEvictor}, which needs
116
- * a mutable reference to delete entries during sweeps. No other code
117
- * should use this — prefer the named helpers above.
118
- */
119
- export function getConversationMap(): Map<string, Conversation> {
120
- return conversations;
121
- }
122
-
123
42
  // ── Per-conversation persistent options ────────────────────────────
124
43
 
125
44
  const conversationOptions = new Map<string, ConversationCreateOptions>();
@@ -38,10 +38,13 @@ import type { HostAppControlProxy } from "./host-app-control-proxy.js";
38
38
  import type { HostCuProxy } from "./host-cu-proxy.js";
39
39
  import type {
40
40
  CardSurfaceData,
41
+ ChoiceSurfaceData,
41
42
  ConfirmationSurfaceData,
43
+ CopyBlockSurfaceData,
42
44
  DynamicPageSurfaceData,
43
45
  FormSurfaceData,
44
46
  ListSurfaceData,
47
+ OAuthConnectSurfaceData,
45
48
  ServerMessage,
46
49
  SurfaceData,
47
50
  SurfaceType,
@@ -395,6 +398,107 @@ function normalizeTaskProgressCardPatch(
395
398
  return normalizedPatch;
396
399
  }
397
400
 
401
+ function normalizeChoiceShowData(
402
+ rawData: Record<string, unknown>,
403
+ ): ChoiceSurfaceData {
404
+ const options = Array.isArray(rawData.options)
405
+ ? rawData.options
406
+ .filter((option): option is Record<string, unknown> =>
407
+ isPlainObject(option),
408
+ )
409
+ .map((option) => {
410
+ const id = typeof option.id === "string" ? option.id.trim() : "";
411
+ const title =
412
+ typeof option.title === "string"
413
+ ? option.title.trim()
414
+ : typeof option.label === "string"
415
+ ? option.label.trim()
416
+ : "";
417
+ if (!id || !title) return null;
418
+ return {
419
+ id,
420
+ title,
421
+ ...(typeof option.description === "string"
422
+ ? { description: option.description }
423
+ : {}),
424
+ ...(option.recommended === true ? { recommended: true } : {}),
425
+ ...(isPlainObject(option.data)
426
+ ? { data: option.data as Record<string, unknown> }
427
+ : {}),
428
+ };
429
+ })
430
+ .filter(
431
+ (option): option is NonNullable<typeof option> => option !== null,
432
+ )
433
+ : [];
434
+
435
+ return {
436
+ ...(typeof rawData.description === "string"
437
+ ? { description: rawData.description }
438
+ : {}),
439
+ options,
440
+ selectionMode: rawData.selectionMode === "multiple" ? "multiple" : "single",
441
+ ...(typeof rawData.submitLabel === "string"
442
+ ? { submitLabel: rawData.submitLabel }
443
+ : {}),
444
+ ...(typeof rawData.commitOnSelect === "boolean"
445
+ ? { commitOnSelect: rawData.commitOnSelect }
446
+ : {}),
447
+ };
448
+ }
449
+
450
+ function normalizeCopyBlockShowData(
451
+ rawData: Record<string, unknown>,
452
+ ): CopyBlockSurfaceData {
453
+ return {
454
+ text: typeof rawData.text === "string" ? rawData.text : "",
455
+ ...(typeof rawData.label === "string" ? { label: rawData.label } : {}),
456
+ ...(typeof rawData.language === "string"
457
+ ? { language: rawData.language }
458
+ : {}),
459
+ };
460
+ }
461
+
462
+ function normalizeOAuthConnectShowData(
463
+ rawData: Record<string, unknown>,
464
+ ): OAuthConnectSurfaceData {
465
+ return {
466
+ providerKey:
467
+ typeof rawData.providerKey === "string" ? rawData.providerKey.trim() : "",
468
+ ...(typeof rawData.displayName === "string"
469
+ ? { displayName: rawData.displayName }
470
+ : {}),
471
+ ...(typeof rawData.description === "string"
472
+ ? { description: rawData.description }
473
+ : {}),
474
+ ...(typeof rawData.logoUrl === "string" || rawData.logoUrl === null
475
+ ? { logoUrl: rawData.logoUrl }
476
+ : {}),
477
+ };
478
+ }
479
+
480
+ function buildChoiceActions(data: ChoiceSurfaceData): Array<{
481
+ id: string;
482
+ label: string;
483
+ style?: string;
484
+ data?: Record<string, unknown>;
485
+ }> {
486
+ return data.options.map((option) => ({
487
+ id: option.id,
488
+ label: option.title,
489
+ style: option.recommended ? "primary" : "secondary",
490
+ data: {
491
+ choiceId: option.id,
492
+ choiceTitle: option.title,
493
+ selectedIds: [option.id],
494
+ selectedTitles: [option.title],
495
+ ...(option.description ? { choiceDescription: option.description } : {}),
496
+ ...(option.recommended ? { recommended: true } : {}),
497
+ ...(option.data ?? {}),
498
+ },
499
+ }));
500
+ }
501
+
398
502
  function isTaskProgressCardData(data: SurfaceData | Record<string, unknown>) {
399
503
  return (data as Record<string, unknown>).template === "task_progress";
400
504
  }
@@ -1699,6 +1803,8 @@ export async function handleSurfaceAction(
1699
1803
  // been accepted. Deferred until after rejection check so the surface stays
1700
1804
  // active and retryable if the queue was full.
1701
1805
  const ONE_SHOT_SURFACE_TYPES = [
1806
+ "choice",
1807
+ "oauth_connect",
1702
1808
  "form",
1703
1809
  "confirmation",
1704
1810
  "file_upload",
@@ -1860,6 +1966,12 @@ export function buildCompletionSummary(
1860
1966
  data?: Record<string, unknown>,
1861
1967
  surfaceData?: Record<string, unknown>,
1862
1968
  ): string {
1969
+ const selectedTitles = Array.isArray(data?.selectedTitles)
1970
+ ? data.selectedTitles.filter(
1971
+ (title): title is string => typeof title === "string",
1972
+ )
1973
+ : [];
1974
+
1863
1975
  if (surfaceType === "confirmation") {
1864
1976
  if (actionId === "cancel") {
1865
1977
  const cancelLabel =
@@ -1892,6 +2004,43 @@ export function buildCompletionSummary(
1892
2004
  if (surfaceType === "form") {
1893
2005
  return "Submitted";
1894
2006
  }
2007
+ if (surfaceType === "choice" && data) {
2008
+ const choiceTitle =
2009
+ typeof data.choiceTitle === "string" ? data.choiceTitle : undefined;
2010
+ if (choiceTitle) return `User chose: "${choiceTitle}"`;
2011
+ if (selectedTitles.length === 1)
2012
+ return `User chose: "${selectedTitles[0]}"`;
2013
+ if (selectedTitles.length > 1) {
2014
+ return `User chose ${selectedTitles.length} options: ${selectedTitles
2015
+ .map((title) => `"${title}"`)
2016
+ .join(", ")}`;
2017
+ }
2018
+ return `User chose: ${actionId}`;
2019
+ }
2020
+ if (surfaceType === "oauth_connect") {
2021
+ const providerLabel =
2022
+ typeof data?.providerLabel === "string"
2023
+ ? data.providerLabel
2024
+ : typeof data?.displayName === "string"
2025
+ ? data.displayName
2026
+ : typeof data?.providerKey === "string"
2027
+ ? data.providerKey
2028
+ : "OAuth";
2029
+ const accountLabel =
2030
+ typeof data?.accountLabel === "string" ? data.accountLabel : undefined;
2031
+ if (actionId === "connect" || data?.status === "connected") {
2032
+ return accountLabel
2033
+ ? `Connected ${providerLabel}: ${accountLabel}`
2034
+ : `Connected ${providerLabel}`;
2035
+ }
2036
+ if (actionId === "cancel" || data?.status === "cancelled") {
2037
+ return `Cancelled ${providerLabel} connection`;
2038
+ }
2039
+ if (data?.status === "error") {
2040
+ return `${providerLabel} connection failed`;
2041
+ }
2042
+ return `${providerLabel} connection ${actionId}`;
2043
+ }
1895
2044
  if (surfaceType === "list" && data) {
1896
2045
  const selectedIds = data.selectedIds as string[] | undefined;
1897
2046
  const actionSuffix = actionId ? ` (action: ${actionId})` : "";
@@ -1922,6 +2071,11 @@ function buildUserFacingLabel(
1922
2071
  surfaceData?: Record<string, unknown>,
1923
2072
  ): string {
1924
2073
  const count = (data?.selectedIds as string[] | undefined)?.length;
2074
+ const selectedTitles = Array.isArray(data?.selectedTitles)
2075
+ ? data.selectedTitles.filter(
2076
+ (title): title is string => typeof title === "string",
2077
+ )
2078
+ : [];
1925
2079
 
1926
2080
  if (surfaceType === "confirmation") {
1927
2081
  if (actionId === "cancel") {
@@ -1948,6 +2102,39 @@ function buildUserFacingLabel(
1948
2102
  return `Selected: ${actionId}`;
1949
2103
  }
1950
2104
  if (surfaceType === "form") return "Submitted";
2105
+ if (surfaceType === "choice") {
2106
+ const choiceTitle =
2107
+ typeof data?.choiceTitle === "string" ? data.choiceTitle : undefined;
2108
+ if (choiceTitle) return choiceTitle;
2109
+ if (selectedTitles.length === 1) return selectedTitles[0];
2110
+ if (selectedTitles.length > 1)
2111
+ return `Selected ${selectedTitles.length} options`;
2112
+ return "Selected";
2113
+ }
2114
+ if (surfaceType === "oauth_connect") {
2115
+ const providerLabel =
2116
+ typeof data?.providerLabel === "string"
2117
+ ? data.providerLabel
2118
+ : typeof data?.displayName === "string"
2119
+ ? data.displayName
2120
+ : typeof data?.providerKey === "string"
2121
+ ? data.providerKey
2122
+ : "OAuth";
2123
+ const accountLabel =
2124
+ typeof data?.accountLabel === "string" ? data.accountLabel : undefined;
2125
+ if (actionId === "connect" || data?.status === "connected") {
2126
+ return accountLabel
2127
+ ? `Connected ${providerLabel}: ${accountLabel}`
2128
+ : `Connected ${providerLabel}`;
2129
+ }
2130
+ if (actionId === "cancel" || data?.status === "cancelled") {
2131
+ return "Cancelled";
2132
+ }
2133
+ if (data?.status === "error") {
2134
+ return `${providerLabel} connection failed`;
2135
+ }
2136
+ return `Selected: ${actionId}`;
2137
+ }
1951
2138
 
1952
2139
  // Table / list selection actions
1953
2140
  if (count) {
@@ -2213,11 +2400,17 @@ export async function surfaceProxyResolver(
2213
2400
  const data = (
2214
2401
  surfaceType === "card"
2215
2402
  ? normalizeCardShowData(input, rawData)
2216
- : surfaceType === "dynamic_page"
2217
- ? normalizeDynamicPageShowData(input, rawData)
2218
- : rawData
2403
+ : surfaceType === "choice"
2404
+ ? normalizeChoiceShowData(rawData)
2405
+ : surfaceType === "copy_block"
2406
+ ? normalizeCopyBlockShowData(rawData)
2407
+ : surfaceType === "oauth_connect"
2408
+ ? normalizeOAuthConnectShowData(rawData)
2409
+ : surfaceType === "dynamic_page"
2410
+ ? normalizeDynamicPageShowData(input, rawData)
2411
+ : rawData
2219
2412
  ) as SurfaceData;
2220
- const actions = input.actions as
2413
+ const inputActions = input.actions as
2221
2414
  | Array<{
2222
2415
  id: string;
2223
2416
  label: string;
@@ -2225,8 +2418,33 @@ export async function surfaceProxyResolver(
2225
2418
  data?: Record<string, unknown>;
2226
2419
  }>
2227
2420
  | undefined;
2421
+ const actions =
2422
+ surfaceType === "choice"
2423
+ ? buildChoiceActions(data as ChoiceSurfaceData)
2424
+ : inputActions;
2228
2425
  // Interactive surfaces default to awaiting user action.
2229
2426
  const hasActions = Array.isArray(actions) && actions.length > 0;
2427
+ if (surfaceType === "choice" && !hasActions) {
2428
+ return {
2429
+ content:
2430
+ "choice surfaces require at least one option with both id and title.",
2431
+ isError: true,
2432
+ };
2433
+ }
2434
+ const oauthProviderKey =
2435
+ surfaceType === "oauth_connect"
2436
+ ? (data as unknown as Record<string, unknown>).providerKey
2437
+ : undefined;
2438
+ if (
2439
+ surfaceType === "oauth_connect" &&
2440
+ (typeof oauthProviderKey !== "string" ||
2441
+ oauthProviderKey.trim().length === 0)
2442
+ ) {
2443
+ return {
2444
+ content: "oauth_connect surfaces require data.providerKey.",
2445
+ isError: true,
2446
+ };
2447
+ }
2230
2448
  const isInteractive =
2231
2449
  surfaceType === "card"
2232
2450
  ? hasActions
@@ -11,14 +11,12 @@ import {
11
11
  type InterfaceId,
12
12
  supportsHostProxy,
13
13
  } from "../channels/types.js";
14
- import { isHttpAuthDisabled } from "../config/env.js";
15
14
  import { getIsPlatform } from "../config/env-registry.js";
16
15
  import { getConfig } from "../config/loader.js";
17
16
  import { getBindingByConversation } from "../memory/external-conversation-store.js";
18
17
  import type { PermissionPrompter } from "../permissions/prompter.js";
19
18
  import type { SecretPrompter } from "../permissions/secret-prompter.js";
20
19
  import type { Message, ToolDefinition } from "../providers/types.js";
21
- import type { TrustClass } from "../runtime/actor-trust-resolver.js";
22
20
  import { assistantEventHub } from "../runtime/assistant-event-hub.js";
23
21
  import { registerConversationSender } from "../tools/browser/browser-screencast.js";
24
22
  import type { ToolExecutor } from "../tools/executor.js";
@@ -48,27 +46,10 @@ import {
48
46
  } from "./doordash-steps.js";
49
47
  import type { ServerMessage, UiSurfaceShow } from "./message-protocol.js";
50
48
  import { runPostExecutionSideEffects } from "./tool-side-effects.js";
51
- import type { TrustContext } from "./trust-context.js";
49
+ import { resolveTrustClass } from "./trust-context.js";
52
50
 
53
51
  const log = getLogger("conversation-tool-setup");
54
52
 
55
- /**
56
- * Resolve the effective trust class for tool execution.
57
- *
58
- * When HTTP auth is disabled (dev bypass), always returns `'guardian'`
59
- * so that control-plane gates don't block local development.
60
- *
61
- * When no trust context is available (e.g. desktop-only conversations that
62
- * don't go through channel trust resolution), defaults to `'unknown'`
63
- * to fail-closed.
64
- */
65
- export function resolveTrustClass(
66
- trustContext: TrustContext | undefined,
67
- ): TrustClass {
68
- if (isHttpAuthDisabled()) return "guardian";
69
- return trustContext?.trustClass ?? "unknown";
70
- }
71
-
72
53
  import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
73
54
  import { AUTO_PROFILE_KEY } from "../config/seed-inference-profiles.js";
74
55
  import {
@@ -97,7 +78,6 @@ export function createToolExecutor(
97
78
  input: Record<string, unknown>,
98
79
  onOutput?: (chunk: string) => void,
99
80
  toolUseId?: string,
100
- turnContext?: import("../plugins/types.js").TurnContext,
101
81
  ) => Promise<ToolExecutionResult> {
102
82
  // Register the conversation's sendToClient for browser screencast surface messages
103
83
  registerConversationSender(ctx.conversationId, (msg) =>
@@ -109,7 +89,6 @@ export function createToolExecutor(
109
89
  input: Record<string, unknown>,
110
90
  onOutput?: (chunk: string) => void,
111
91
  toolUseId?: string,
112
- turnContext?: import("../plugins/types.js").TurnContext,
113
92
  ) => {
114
93
  const { name: executionName, input: executionInput } =
115
94
  resolveToolInvocationAlias(name, input, ctx.allowedToolNames);
@@ -257,12 +236,7 @@ export function createToolExecutor(
257
236
  };
258
237
  }
259
238
 
260
- const result = await executor.execute(
261
- toolName,
262
- toolInput,
263
- toolContext,
264
- turnContext,
265
- );
239
+ const result = await executor.execute(toolName, toolInput, toolContext);
266
240
  if (toolContext.approvedViaPrompt) {
267
241
  ctx.approvedViaPromptThisTurn = true;
268
242
  }
@@ -276,7 +250,6 @@ export function createToolExecutor(
276
250
  executionName,
277
251
  executionInput,
278
252
  toolContext,
279
- turnContext,
280
253
  );
281
254
  if (toolContext.approvedViaPrompt) {
282
255
  ctx.approvedViaPromptThisTurn = true;
@@ -4,6 +4,7 @@ import { getConversation } from "../memory/conversation-crud.js";
4
4
  import { resolveConversationDirectoryPaths } from "../memory/conversation-directories.js";
5
5
  import { renderWorkspaceTopLevelContext } from "../workspace/top-level-renderer.js";
6
6
  import { scanTopLevelDirectories } from "../workspace/top-level-scanner.js";
7
+ import { findConversationOrSubagent } from "./conversation-registry.js";
7
8
 
8
9
  /**
9
10
  * Subset of Conversation state that workspace context helpers need.
@@ -25,6 +26,22 @@ export interface WorkspaceConversationContext {
25
26
  hostUsername?: string;
26
27
  }
27
28
 
29
+ /**
30
+ * Resolve the live workspace top-level block for a conversation, refreshing
31
+ * the dirty-guarded cache first so a workspace-mutating tool's
32
+ * `markWorkspaceTopLevelDirty` from the prior turn is picked up. Returns `null`
33
+ * when no live conversation is found (no active conversation, or a context with
34
+ * no conversation id) or when the rendered context is empty.
35
+ */
36
+ export function resolveWorkspaceTopLevelContext(
37
+ conversationId: string | undefined,
38
+ ): string | null {
39
+ const conversation = findConversationOrSubagent(conversationId);
40
+ if (!conversation) return null;
41
+ refreshWorkspaceTopLevelContextIfNeeded(conversation);
42
+ return conversation.workspaceTopLevelContext;
43
+ }
44
+
28
45
  /** Refresh workspace top-level directory context if needed. */
29
46
  export function refreshWorkspaceTopLevelContextIfNeeded(
30
47
  ctx: WorkspaceConversationContext,