@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
@@ -43,9 +43,30 @@ const TrustRulesListParams = z
43
43
  })
44
44
  .strict();
45
45
 
46
+ const TrustRuleSchema = z.object({
47
+ id: z.string(),
48
+ tool: z.string(),
49
+ pattern: z.string(),
50
+ risk: z.enum(["low", "medium", "high"]),
51
+ description: z.string(),
52
+ origin: z.enum(["default", "user_defined"]),
53
+ userModified: z.boolean(),
54
+ deleted: z.boolean(),
55
+ createdAt: z.string(),
56
+ updatedAt: z.string(),
57
+ });
58
+
59
+ const TrustRulesListResponseSchema = z.object({
60
+ rules: z.array(TrustRuleSchema),
61
+ });
62
+ type TrustRulesListResponse = z.infer<typeof TrustRulesListResponseSchema>;
63
+
46
64
  // ── Handlers ────────────────────────────────────────────────────────────
47
65
 
48
- async function handleList({ queryParams = {}, body = {} }: RouteHandlerArgs) {
66
+ async function handleList({
67
+ queryParams = {},
68
+ body = {},
69
+ }: RouteHandlerArgs): Promise<TrustRulesListResponse> {
49
70
  // HTTP GET delivers filters via queryParams; CLI IPC puts them in body.
50
71
  const source = Object.keys(queryParams).length > 0 ? queryParams : body;
51
72
  const p = TrustRulesListParams.parse(source);
@@ -54,7 +75,9 @@ async function handleList({ queryParams = {}, body = {} }: RouteHandlerArgs) {
54
75
  if (p.origin) qs.set("origin", p.origin);
55
76
  if (p.include_all) qs.set("include_all", "true");
56
77
  const query = qs.toString();
57
- return gatewayFetch(`/v1/trust-rules${query ? `?${query}` : ""}`);
78
+ return gatewayFetch(
79
+ `/v1/trust-rules${query ? `?${query}` : ""}`,
80
+ ) as Promise<TrustRulesListResponse>;
58
81
  }
59
82
 
60
83
  // ── Route definitions ───────────────────────────────────────────────────
@@ -73,6 +96,7 @@ export const ROUTES: RouteDefinition[] = [
73
96
  description:
74
97
  "List trust rules, optionally filtered by tool, origin, or include_all.",
75
98
  tags: ["trust-rules"],
99
+ responseBody: TrustRulesListResponseSchema,
76
100
  queryParams: [
77
101
  { name: "tool", description: "Filter by tool name" },
78
102
  { name: "origin", description: "Filter by origin" },
@@ -15,6 +15,7 @@ import { sanitizeForTts } from "../../calls/tts-text-sanitizer.js";
15
15
  import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
16
16
  import { getConfig } from "../../config/loader.js";
17
17
  import { getMessageContent } from "../../daemon/handlers/conversation-history.js";
18
+ import { listCatalogProvidersForDisplay } from "../../tts/provider-catalog.js";
18
19
  import {
19
20
  synthesizeText,
20
21
  TtsSynthesisError,
@@ -136,6 +137,10 @@ const ttsResponseHeaders = () => ({
136
137
  // Handlers
137
138
  // ---------------------------------------------------------------------------
138
139
 
140
+ function handleListTtsProviders() {
141
+ return { providers: listCatalogProvidersForDisplay() };
142
+ }
143
+
139
144
  async function handleMessageTts({ pathParams, queryParams }: RouteHandlerArgs) {
140
145
  const config = getConfig();
141
146
 
@@ -226,6 +231,36 @@ async function handleSynthesizeCliTts({ body }: RouteHandlerArgs) {
226
231
  // ---------------------------------------------------------------------------
227
232
 
228
233
  export const ROUTES: RouteDefinition[] = [
234
+ {
235
+ operationId: "tts_providers",
236
+ endpoint: "tts/providers",
237
+ method: "GET",
238
+ policy: {
239
+ requiredScopes: ["settings.read"],
240
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
241
+ },
242
+ summary: "List TTS providers",
243
+ description:
244
+ "Return the catalog of available TTS providers with client-facing metadata.",
245
+ tags: ["tts"],
246
+ responseBody: z.object({
247
+ providers: z.array(
248
+ z.object({
249
+ id: z.string(),
250
+ displayName: z.string(),
251
+ subtitle: z.string(),
252
+ supportsVoiceSelection: z.boolean(),
253
+ apiKeyPlaceholder: z.string(),
254
+ credentialsGuide: z.object({
255
+ description: z.string(),
256
+ url: z.string(),
257
+ linkLabel: z.string(),
258
+ }),
259
+ }),
260
+ ),
261
+ }),
262
+ handler: handleListTtsProviders,
263
+ },
229
264
  {
230
265
  operationId: "messages_tts",
231
266
  endpoint: "messages/:messageId/tts",
@@ -31,6 +31,70 @@ export interface RoutePathParam {
31
31
  description?: string;
32
32
  }
33
33
 
34
+ /**
35
+ * Content types a route can declare a request body for. `application/json`
36
+ * is the implicit default when `requestBody` is a bare Zod schema, so it is
37
+ * only spelled out here for the explicit `{ contentType, schema }` form.
38
+ */
39
+ export type RouteRequestContentType =
40
+ | "application/json"
41
+ | "application/octet-stream"
42
+ | "multipart/form-data";
43
+
44
+ /**
45
+ * A route's request body. Either:
46
+ * - a bare Zod schema, which is advertised as `application/json`, or
47
+ * - an explicit `{ contentType, schema }` pair for non-JSON bodies (e.g. a
48
+ * raw `application/octet-stream` upload). `schema` may be a Zod schema or a
49
+ * plain JSON Schema fragment (e.g. `{ type: "string", format: "binary" }`).
50
+ *
51
+ * The OpenAPI generator turns this into the operation's `requestBody`, so the
52
+ * generated client SDK describes a real body type instead of `never`. The HTTP
53
+ * adapter parses the body off the request `Content-Type` header, so this field
54
+ * is a codegen signal only and does not change runtime request handling.
55
+ */
56
+ export type RouteRequestBody =
57
+ | z.ZodType
58
+ | {
59
+ contentType: RouteRequestContentType;
60
+ schema: z.ZodType | Record<string, unknown>;
61
+ };
62
+
63
+ /**
64
+ * Content types a route can declare a success response body for.
65
+ * `application/json` is the implicit default when `responseBody` is a bare
66
+ * Zod schema, so it is only spelled out here for the explicit
67
+ * `{ contentType, schema }` form (e.g. a binary `application/octet-stream`
68
+ * download or an `application/gzip` archive).
69
+ */
70
+ export type RouteResponseContentType =
71
+ | "application/json"
72
+ | "application/octet-stream"
73
+ | "application/gzip"
74
+ | "application/pdf"
75
+ | "application/zip";
76
+
77
+ /**
78
+ * A route's success response body. Either:
79
+ * - a bare Zod schema, which is advertised as `application/json`, or
80
+ * - an explicit `{ contentType, schema }` pair for non-JSON responses (e.g. a
81
+ * binary download). `schema` may be a Zod schema or a plain JSON Schema
82
+ * fragment (e.g. `{ type: "string", format: "binary" }`, which is not
83
+ * expressible as a bare Zod type).
84
+ *
85
+ * The OpenAPI generator turns this into the operation's success response, so
86
+ * the generated client SDK describes a real response type (e.g. `Blob`)
87
+ * instead of `unknown`. Handlers serialize their own bytes via `RouteResponse`,
88
+ * so this field is a codegen signal only and does not change runtime
89
+ * response handling.
90
+ */
91
+ export type RouteResponseBody =
92
+ | z.ZodType
93
+ | {
94
+ contentType: RouteResponseContentType;
95
+ schema: z.ZodType | Record<string, unknown>;
96
+ };
97
+
34
98
  export interface RouteHandlerArgs {
35
99
  pathParams?: Record<string, string>;
36
100
  queryParams?: Record<string, string>;
@@ -102,8 +166,8 @@ export interface RouteDefinition {
102
166
  tags?: string[];
103
167
  pathParams?: RoutePathParam[];
104
168
  queryParams?: RouteQueryParam[];
105
- requestBody?: z.ZodType;
106
- responseBody?: z.ZodType;
169
+ requestBody?: RouteRequestBody;
170
+ responseBody?: RouteResponseBody;
107
171
  /**
108
172
  * HTTP status code for the success response. Defaults to "200".
109
173
  * Use "201" for resource creation, "204" for no-content responses.
@@ -145,12 +209,6 @@ export interface RouteDefinition {
145
209
  * RouteError subclasses rather than explicit Response objects.
146
210
  */
147
211
  additionalResponses?: Record<string, { description: string }>;
148
- /**
149
- * When true, the route expects a raw binary body (e.g. file uploads).
150
- * The HTTP adapter already reads `rawBody` for non-JSON content types;
151
- * this flag is a declarative signal for documentation and tooling.
152
- */
153
- rawBody?: boolean;
154
212
  /**
155
213
  * Per-route request-log control. Routes that opt in can suppress the
156
214
  * per-request INFO log line after a confirmed run of successful
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Route handlers for usage and cost summary endpoints.
3
3
  *
4
- * GET /v1/usage/totals?from=&to= — aggregate totals for a time range
5
- * GET /v1/usage/daily?from=&to= — per-day buckets for a time range
6
- * GET /v1/usage/breakdown?from=&to=&groupBy= — grouped breakdown
7
- * GET /v1/usage/series?from=&to=&granularity=&groupBy= — grouped time-series buckets
4
+ * GET /v1/usage/totals?from=&to=&scheduleId= — aggregate totals for a time range
5
+ * GET /v1/usage/daily?from=&to=&scheduleId= — per-day buckets for a time range
6
+ * GET /v1/usage/breakdown?from=&to=&groupBy=&scheduleId= — grouped breakdown
7
+ * GET /v1/usage/series?from=&to=&granularity=&groupBy=&scheduleId= — grouped time-series buckets
8
8
  */
9
9
 
10
10
  import { z } from "zod";
@@ -18,10 +18,12 @@ import {
18
18
  type GroupByDimension,
19
19
  USAGE_GROUP_BY_DIMENSIONS,
20
20
  USAGE_SERIES_GROUP_BY_DIMENSIONS,
21
+ type UsageAggregationFilter,
21
22
  type UsageGranularity,
22
23
  } from "../../memory/llm-usage-store.js";
23
24
  import { validateTimezone } from "../../memory/usage-buckets.js";
24
25
  import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
26
+ import { parseEpochMillisRange } from "./epoch-millis-range.js";
25
27
  import { BadRequestError } from "./errors.js";
26
28
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
27
29
 
@@ -29,6 +31,8 @@ const VALID_GROUP_BY = new Set<string>(USAGE_GROUP_BY_DIMENSIONS);
29
31
  const VALID_SERIES_GROUP_BY = new Set<string>(USAGE_SERIES_GROUP_BY_DIMENSIONS);
30
32
  const GROUP_BY_DESCRIPTION = USAGE_GROUP_BY_DIMENSIONS.join(", ");
31
33
  const SERIES_GROUP_BY_DESCRIPTION = USAGE_SERIES_GROUP_BY_DIMENSIONS.join(", ");
34
+ const SCHEDULE_ID_FILTER_DESCRIPTION =
35
+ "Optional schedule id. When set, usage is attributed by cron run windows for that schedule.";
32
36
 
33
37
  const usageTotalsSchema = z.object({
34
38
  totalInputTokens: z.number(),
@@ -86,43 +90,23 @@ function resolveTimezone(queryParams: Record<string, string>): string {
86
90
  return tz;
87
91
  }
88
92
 
89
- function parseTimeRange(queryParams: Record<string, string>): {
90
- from: number;
91
- to: number;
92
- } {
93
- const fromRaw = queryParams.from;
94
- const toRaw = queryParams.to;
95
-
96
- if (!fromRaw || !toRaw) {
97
- throw new BadRequestError(
98
- 'Missing required query parameters: "from" and "to" (epoch milliseconds)',
99
- );
100
- }
101
-
102
- const from = Number(fromRaw);
103
- const to = Number(toRaw);
104
-
105
- if (!Number.isFinite(from) || !Number.isFinite(to)) {
106
- throw new BadRequestError(
107
- '"from" and "to" must be valid numbers (epoch milliseconds)',
108
- );
109
- }
110
-
111
- if (from > to) {
112
- throw new BadRequestError('"from" must be less than or equal to "to"');
113
- }
114
-
115
- return { from, to };
93
+ function parseUsageAggregationFilter(
94
+ queryParams: Record<string, string>,
95
+ ): UsageAggregationFilter {
96
+ const scheduleId = queryParams.scheduleId?.trim();
97
+ return scheduleId ? { scheduleId } : {};
116
98
  }
117
99
 
118
100
  function handleUsageTotals({ queryParams }: RouteHandlerArgs) {
119
- const range = parseTimeRange(queryParams ?? {});
120
- return getUsageTotals(range);
101
+ const qp = queryParams ?? {};
102
+ const range = parseEpochMillisRange(qp);
103
+ const filter = parseUsageAggregationFilter(qp);
104
+ return getUsageTotals(range, filter);
121
105
  }
122
106
 
123
107
  function handleUsageDaily({ queryParams }: RouteHandlerArgs) {
124
108
  const qp = queryParams ?? {};
125
- const range = parseTimeRange(qp);
109
+ const range = parseEpochMillisRange(qp);
126
110
  const granularity = qp.granularity ?? "daily";
127
111
  if (granularity !== "daily" && granularity !== "hourly") {
128
112
  throw new BadRequestError(
@@ -130,16 +114,17 @@ function handleUsageDaily({ queryParams }: RouteHandlerArgs) {
130
114
  );
131
115
  }
132
116
  const tz = resolveTimezone(qp);
117
+ const filter = parseUsageAggregationFilter(qp);
133
118
  const buckets =
134
119
  granularity === "hourly"
135
- ? getUsageHourBuckets(range, tz, { fillEmpty: true })
136
- : getUsageDayBuckets(range, tz, { fillEmpty: true });
120
+ ? getUsageHourBuckets(range, tz, { fillEmpty: true }, filter)
121
+ : getUsageDayBuckets(range, tz, { fillEmpty: true }, filter);
137
122
  return { buckets };
138
123
  }
139
124
 
140
125
  function handleUsageBreakdown({ queryParams }: RouteHandlerArgs) {
141
126
  const qp = queryParams ?? {};
142
- const range = parseTimeRange(qp);
127
+ const range = parseEpochMillisRange(qp);
143
128
 
144
129
  const groupBy = qp.groupBy;
145
130
  if (!groupBy) {
@@ -153,13 +138,18 @@ function handleUsageBreakdown({ queryParams }: RouteHandlerArgs) {
153
138
  );
154
139
  }
155
140
 
156
- const breakdown = getUsageGroupBreakdown(range, groupBy as GroupByDimension);
141
+ const filter = parseUsageAggregationFilter(qp);
142
+ const breakdown = getUsageGroupBreakdown(
143
+ range,
144
+ groupBy as GroupByDimension,
145
+ filter,
146
+ );
157
147
  return { breakdown };
158
148
  }
159
149
 
160
150
  function handleUsageSeries({ queryParams }: RouteHandlerArgs) {
161
151
  const qp = queryParams ?? {};
162
- const range = parseTimeRange(qp);
152
+ const range = parseEpochMillisRange(qp);
163
153
  const granularity = qp.granularity ?? "daily";
164
154
  if (granularity !== "daily" && granularity !== "hourly") {
165
155
  throw new BadRequestError(
@@ -180,12 +170,14 @@ function handleUsageSeries({ queryParams }: RouteHandlerArgs) {
180
170
  }
181
171
 
182
172
  const tz = resolveTimezone(qp);
173
+ const filter = parseUsageAggregationFilter(qp);
183
174
  const buckets = getUsageGroupedSeries(
184
175
  range,
185
176
  groupBy as Exclude<GroupByDimension, "conversation">,
186
177
  granularity as UsageGranularity,
187
178
  tz,
188
179
  { fillEmpty: true },
180
+ filter,
189
181
  );
190
182
  return { buckets };
191
183
  }
@@ -213,6 +205,10 @@ export const ROUTES: RouteDefinition[] = [
213
205
  type: "integer",
214
206
  description: "End epoch millis (required)",
215
207
  },
208
+ {
209
+ name: "scheduleId",
210
+ description: SCHEDULE_ID_FILTER_DESCRIPTION,
211
+ },
216
212
  ],
217
213
  responseBody: usageTotalsSchema,
218
214
  handler: handleUsageTotals,
@@ -249,6 +245,10 @@ export const ROUTES: RouteDefinition[] = [
249
245
  description:
250
246
  'IANA timezone identifier (e.g. "America/Los_Angeles"). Bucket boundaries and display labels are computed in this timezone. Defaults to "UTC" for backwards compatibility.',
251
247
  },
248
+ {
249
+ name: "scheduleId",
250
+ description: SCHEDULE_ID_FILTER_DESCRIPTION,
251
+ },
252
252
  ],
253
253
  responseBody: z.object({
254
254
  buckets: z.array(usageDayBucketSchema).describe("Usage bucket objects"),
@@ -282,6 +282,10 @@ export const ROUTES: RouteDefinition[] = [
282
282
  name: "groupBy",
283
283
  description: `Group by: ${GROUP_BY_DESCRIPTION} (required)`,
284
284
  },
285
+ {
286
+ name: "scheduleId",
287
+ description: SCHEDULE_ID_FILTER_DESCRIPTION,
288
+ },
285
289
  ],
286
290
  responseBody: z.object({
287
291
  breakdown: z
@@ -327,6 +331,10 @@ export const ROUTES: RouteDefinition[] = [
327
331
  description:
328
332
  'IANA timezone identifier (e.g. "America/Los_Angeles"). Bucket boundaries and display labels are computed in this timezone. Defaults to "UTC".',
329
333
  },
334
+ {
335
+ name: "scheduleId",
336
+ description: SCHEDULE_ID_FILTER_DESCRIPTION,
337
+ },
330
338
  ],
331
339
  responseBody: z.object({
332
340
  buckets: z
@@ -10,6 +10,8 @@
10
10
  * with the platform for this assistant.
11
11
  */
12
12
 
13
+ import { z } from "zod";
14
+
13
15
  import { getIsPlatform } from "../../config/env-registry.js";
14
16
  import { getConfig } from "../../config/loader.js";
15
17
  import {
@@ -25,6 +27,38 @@ import {
25
27
  } from "./errors.js";
26
28
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
27
29
 
30
+ // ---------------------------------------------------------------------------
31
+ // Schemas
32
+ // ---------------------------------------------------------------------------
33
+
34
+ const WebhooksRegisterRequestSchema = z.object({
35
+ type: z.string(),
36
+ path: z.string().optional(),
37
+ source: z.string().optional(),
38
+ });
39
+
40
+ const WebhooksRegisterResponseSchema = z.object({
41
+ callbackUrl: z.string(),
42
+ type: z.string(),
43
+ path: z.string(),
44
+ mode: z.enum(["platform", "self-hosted"]),
45
+ });
46
+ type WebhooksRegisterResponse = z.infer<typeof WebhooksRegisterResponseSchema>;
47
+
48
+ const WebhookCallbackRouteSchema = z.object({
49
+ id: z.string(),
50
+ assistant_id: z.string(),
51
+ type: z.string(),
52
+ callback_path: z.string(),
53
+ callback_url: z.string(),
54
+ source_identifier: z.string().nullable(),
55
+ });
56
+
57
+ const WebhooksListResponseSchema = z.object({
58
+ routes: z.array(WebhookCallbackRouteSchema),
59
+ });
60
+ type WebhooksListResponse = z.infer<typeof WebhooksListResponseSchema>;
61
+
28
62
  // ---------------------------------------------------------------------------
29
63
  // Helpers
30
64
  // ---------------------------------------------------------------------------
@@ -49,7 +83,7 @@ function deriveWebhookPath(type: string): string {
49
83
 
50
84
  async function handleWebhooksRegister(
51
85
  args: RouteHandlerArgs,
52
- ): Promise<unknown> {
86
+ ): Promise<WebhooksRegisterResponse> {
53
87
  const { type, path: pathOverride, source } = args.body ?? {};
54
88
 
55
89
  if (!type || typeof type !== "string") {
@@ -93,7 +127,9 @@ async function handleWebhooksRegister(
93
127
  };
94
128
  }
95
129
 
96
- async function handleWebhooksList(_args: RouteHandlerArgs): Promise<unknown> {
130
+ async function handleWebhooksList(
131
+ _args: RouteHandlerArgs,
132
+ ): Promise<WebhooksListResponse> {
97
133
  const context = await resolvePlatformCallbackRegistrationContext();
98
134
 
99
135
  if (!context.platformBaseUrl || !context.authHeader) {
@@ -155,6 +191,8 @@ export const ROUTES: RouteDefinition[] = [
155
191
  description:
156
192
  "Resolves a stable callback URL for a webhook type. On platform-managed assistants, registers the route with the platform gateway. On self-hosted assistants, uses the configured ingress.publicBaseUrl.",
157
193
  tags: ["webhooks"],
194
+ requestBody: WebhooksRegisterRequestSchema,
195
+ responseBody: WebhooksRegisterResponseSchema,
158
196
  handler: handleWebhooksRegister,
159
197
  },
160
198
  {
@@ -169,6 +207,7 @@ export const ROUTES: RouteDefinition[] = [
169
207
  description:
170
208
  "Lists all webhook callback routes registered with the platform for this assistant.",
171
209
  tags: ["webhooks"],
210
+ responseBody: WebhooksListResponseSchema,
172
211
  handler: handleWebhooksList,
173
212
  },
174
213
  ];
@@ -8,10 +8,8 @@
8
8
  import { z } from "zod";
9
9
 
10
10
  import type { Conversation } from "../../daemon/conversation.js";
11
- import {
12
- findConversation,
13
- getOrCreateConversation,
14
- } from "../../daemon/conversation-store.js";
11
+ import { findConversation } from "../../daemon/conversation-registry.js";
12
+ import { getOrCreateConversation } from "../../daemon/conversation-store.js";
15
13
  import type { ServerMessage } from "../../daemon/message-protocol.js";
16
14
  import { getMessages } from "../../memory/conversation-crud.js";
17
15
  import { check, classifyRisk } from "../../permissions/checker.js";
@@ -663,6 +663,10 @@ export const ROUTES: RouteDefinition[] = [
663
663
  description: "Allow hidden files (true/false)",
664
664
  },
665
665
  ],
666
+ responseBody: {
667
+ contentType: "application/octet-stream",
668
+ schema: { type: "string", format: "binary" },
669
+ },
666
670
  responseStatus: ({ headers }) => (headers?.["range"] ? "206" : "200"),
667
671
  additionalResponses: {
668
672
  "416": { description: "Range Not Satisfiable" },
@@ -61,6 +61,12 @@ function makeConversation() {
61
61
  setSubagentAllowedTools: mock(() => {}),
62
62
  updateClient: mock(() => {}),
63
63
  processing: false,
64
+ isProcessing(this: { processing: boolean }) {
65
+ return this.processing;
66
+ },
67
+ setProcessing(this: { processing: boolean }, value: boolean) {
68
+ this.processing = value;
69
+ },
64
70
  abortController: null as AbortController | null,
65
71
  currentRequestId: null as string | null,
66
72
  loadedHistoryTrustClass: undefined as string | undefined,
@@ -198,7 +198,7 @@ export async function analyzeConversation(
198
198
  // `currentRequestId` and let two loops mutate the same Conversation
199
199
  // state. Skip this run instead — the next upstream trigger will
200
200
  // re-enqueue once the in-flight loop finishes.
201
- if (opts.trigger === "auto" && analysisConversation.processing) {
201
+ if (opts.trigger === "auto" && analysisConversation.isProcessing()) {
202
202
  log.info(
203
203
  {
204
204
  sourceConversationId: resolvedId,
@@ -247,7 +247,7 @@ export async function analyzeConversation(
247
247
  analysisConversation.updateClient(broadcastMessage, !hasLiveSubscriber);
248
248
 
249
249
  // k. Set up processing state (required by runAgentLoop guard)
250
- analysisConversation.processing = true;
250
+ analysisConversation.setProcessing(true);
251
251
  analysisConversation.abortController = new AbortController();
252
252
  analysisConversation.currentRequestId = crypto.randomUUID();
253
253
 
@@ -9,7 +9,7 @@
9
9
 
10
10
  import { parseChannelId } from "../../channels/types.js";
11
11
  import { getConfig } from "../../config/loader.js";
12
- import { findConversation } from "../../daemon/conversation-store.js";
12
+ import { findConversation } from "../../daemon/conversation-registry.js";
13
13
  import { normalizeConversationType } from "../../daemon/message-types/shared.js";
14
14
  import {
15
15
  type AttentionState,
@@ -49,6 +49,7 @@ export interface ScheduleJob {
49
49
  retryBackoffMs: number;
50
50
  /** Script-mode execution timeout override (ms); null = use the default. */
51
51
  timeoutMs: number | null;
52
+ createdFromConversationId: string | null;
52
53
  createdBy: string;
53
54
  mode: ScheduleMode;
54
55
  routingIntent: RoutingIntent;
@@ -102,6 +103,7 @@ export function createSchedule(params: {
102
103
  maxRetries?: number;
103
104
  retryBackoffMs?: number;
104
105
  timeoutMs?: number | null;
106
+ createdFromConversationId?: string | null;
105
107
  }): ScheduleJob {
106
108
  const expression = params.expression ?? params.cronExpression ?? null;
107
109
  const isOneShot = expression == null;
@@ -138,6 +140,7 @@ export function createSchedule(params: {
138
140
  const maxRetries = params.maxRetries ?? 3;
139
141
  const retryBackoffMs = params.retryBackoffMs ?? 60000;
140
142
  const timeoutMs = params.timeoutMs ?? null;
143
+ const createdFromConversationId = params.createdFromConversationId ?? null;
141
144
 
142
145
  let nextRunAt: number;
143
146
  if (isOneShot) {
@@ -165,6 +168,7 @@ export function createSchedule(params: {
165
168
  maxRetries,
166
169
  retryBackoffMs,
167
170
  timeoutMs,
171
+ createdFromConversationId,
168
172
  createdBy: params.createdBy ?? "agent",
169
173
  mode,
170
174
  routingIntent,
@@ -264,6 +268,7 @@ export function updateSchedule(
264
268
  maxRetries?: number;
265
269
  retryBackoffMs?: number;
266
270
  timeoutMs?: number | null;
271
+ createdFromConversationId?: string | null;
267
272
  },
268
273
  ): ScheduleJob | null {
269
274
  const db = getDb();
@@ -329,6 +334,8 @@ export function updateSchedule(
329
334
  if (updates.retryBackoffMs !== undefined)
330
335
  set.retryBackoffMs = updates.retryBackoffMs;
331
336
  if (updates.timeoutMs !== undefined) set.timeoutMs = updates.timeoutMs;
337
+ if (updates.createdFromConversationId !== undefined)
338
+ set.createdFromConversationId = updates.createdFromConversationId;
332
339
 
333
340
  // Recompute nextRunAt if schedule timing may have changed (only for recurring)
334
341
  if (
@@ -591,7 +598,7 @@ export function cancelSchedule(id: string): boolean {
591
598
 
592
599
  export function createScheduleRun(
593
600
  jobId: string,
594
- conversationId: string,
601
+ conversationId: string | null,
595
602
  ): string {
596
603
  const db = getDb();
597
604
  const id = uuid();
@@ -613,6 +620,17 @@ export function createScheduleRun(
613
620
  return id;
614
621
  }
615
622
 
623
+ export function setScheduleRunConversationId(
624
+ runId: string,
625
+ conversationId: string,
626
+ ): void {
627
+ const db = getDb();
628
+ db.update(scheduleRuns)
629
+ .set({ conversationId })
630
+ .where(eq(scheduleRuns.id, runId))
631
+ .run();
632
+ }
633
+
616
634
  export function completeScheduleRun(
617
635
  runId: string,
618
636
  result: { status: "ok" | "error"; output?: string; error?: string },
@@ -977,6 +995,7 @@ function parseJobRow(row: typeof scheduleJobs.$inferSelect): ScheduleJob {
977
995
  maxRetries: row.maxRetries ?? 3,
978
996
  retryBackoffMs: row.retryBackoffMs ?? 60000,
979
997
  timeoutMs: row.timeoutMs ?? null,
998
+ createdFromConversationId: row.createdFromConversationId ?? null,
980
999
  createdBy: row.createdBy,
981
1000
  mode: (row.mode ?? "execute") as ScheduleMode,
982
1001
  routingIntent: (row.routingIntent ?? "all_channels") as RoutingIntent,