@vellumai/assistant 0.8.7 → 0.8.8

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 (387) hide show
  1. package/Dockerfile +20 -4
  2. package/docker-entrypoint.sh +4 -2
  3. package/docker-init-apt-root.sh +3 -1
  4. package/docker-kata-apt-env.sh +3 -1
  5. package/docker-kata-runtime-family.sh +12 -0
  6. package/docs/architecture/memory.md +1 -1
  7. package/docs/plugins.md +75 -79
  8. package/examples/plugins/echo/README.md +6 -12
  9. package/examples/plugins/echo/register.ts +0 -41
  10. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
  11. package/openapi.yaml +3381 -348
  12. package/package.json +1 -1
  13. package/scripts/generate-openapi.ts +68 -41
  14. package/src/__tests__/agent-loop-exit-reason.test.ts +34 -39
  15. package/src/__tests__/agent-loop-provider-error-recording.test.ts +1 -1
  16. package/src/__tests__/agent-loop.test.ts +37 -87
  17. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
  18. package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
  19. package/src/__tests__/annotate-risk-options.test.ts +2 -3
  20. package/src/__tests__/anthropic-provider.test.ts +95 -2
  21. package/src/__tests__/assistant-event-hub.test.ts +25 -0
  22. package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
  23. package/src/__tests__/{conversation-stream-state.test.ts → assistant-stream-state.test.ts} +252 -91
  24. package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
  25. package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
  26. package/src/__tests__/btw-routes.test.ts +62 -3
  27. package/src/__tests__/build-persisted-content.test.ts +184 -0
  28. package/src/__tests__/catalog-files.test.ts +1 -1
  29. package/src/__tests__/clawhub-files.test.ts +1 -1
  30. package/src/__tests__/compaction-pipeline.test.ts +1 -1
  31. package/src/__tests__/compaction.benchmark.test.ts +0 -30
  32. package/src/__tests__/config-watcher.test.ts +1 -1
  33. package/src/__tests__/conversation-abort-tool-results.test.ts +57 -19
  34. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +6 -2
  35. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -4
  36. package/src/__tests__/conversation-agent-loop-overflow.test.ts +313 -1136
  37. package/src/__tests__/conversation-agent-loop.test.ts +596 -1616
  38. package/src/__tests__/conversation-analysis-routes.test.ts +6 -0
  39. package/src/__tests__/conversation-history-web-search.test.ts +11 -1
  40. package/src/__tests__/conversation-pairing.test.ts +4 -31
  41. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +6 -0
  42. package/src/__tests__/conversation-provider-retry-repair.test.ts +26 -5
  43. package/src/__tests__/conversation-queue.test.ts +2 -0
  44. package/src/__tests__/conversation-routes-disk-view.test.ts +3 -0
  45. package/src/__tests__/conversation-routes-slash-commands.test.ts +6 -5
  46. package/src/__tests__/conversation-runtime-assembly.test.ts +170 -229
  47. package/src/__tests__/conversation-runtime-workspace.test.ts +3 -24
  48. package/src/__tests__/conversation-slash-commands.test.ts +8 -42
  49. package/src/__tests__/conversation-slash-queue.test.ts +6 -1
  50. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +84 -0
  51. package/src/__tests__/conversation-sync-tags.test.ts +27 -15
  52. package/src/__tests__/conversation-title-service.test.ts +135 -2
  53. package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
  54. package/src/__tests__/cross-provider-web-search.test.ts +214 -1
  55. package/src/__tests__/db-schedule-syntax-migration.test.ts +5 -0
  56. package/src/__tests__/dm-persistence.test.ts +5 -1
  57. package/src/__tests__/empty-response-hook.test.ts +304 -0
  58. package/src/__tests__/feature-flag-test-helpers.ts +2 -2
  59. package/src/__tests__/gemini-image-service.test.ts +13 -0
  60. package/src/__tests__/helpers/mock-provider.ts +110 -0
  61. package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
  62. package/src/__tests__/history-repair-hook.test.ts +1 -0
  63. package/src/__tests__/identity-intro-cache.test.ts +12 -100
  64. package/src/__tests__/identity-routes.test.ts +248 -7
  65. package/src/__tests__/inbound-slack-persistence.test.ts +5 -1
  66. package/src/__tests__/injector-background-turn.test.ts +2 -8
  67. package/src/__tests__/injector-chain.test.ts +106 -270
  68. package/src/__tests__/injector-disk-pressure.test.ts +3 -12
  69. package/src/__tests__/injector-document-comments.test.ts +2 -2
  70. package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
  71. package/src/__tests__/injector-v3-suppression.test.ts +31 -37
  72. package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
  73. package/src/__tests__/list-messages-page-latest.test.ts +60 -0
  74. package/src/__tests__/list-messages-tool-merge.test.ts +20 -0
  75. package/src/__tests__/llm-usage-store.test.ts +223 -1
  76. package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
  77. package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
  78. package/src/__tests__/native-web-search.test.ts +191 -0
  79. package/src/__tests__/onboarding-template-contract.test.ts +2 -0
  80. package/src/__tests__/openai-image-service.test.ts +17 -0
  81. package/src/__tests__/openai-provider.test.ts +31 -1
  82. package/src/__tests__/persist-unsendable-image.test.ts +215 -0
  83. package/src/__tests__/persistence-secret-redaction.test.ts +1 -0
  84. package/src/__tests__/pipeline-runner.test.ts +29 -39
  85. package/src/__tests__/pkb-autoinject.test.ts +2 -5
  86. package/src/__tests__/plugin-bootstrap.test.ts +13 -28
  87. package/src/__tests__/plugin-registry.test.ts +0 -27
  88. package/src/__tests__/plugin-types.test.ts +2 -125
  89. package/src/__tests__/process-message-display-content.test.ts +6 -2
  90. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
  91. package/src/__tests__/resolve-trust-class.test.ts +4 -4
  92. package/src/__tests__/runtime-events-sse-reconnect.test.ts +60 -23
  93. package/src/__tests__/schedule-routes.test.ts +603 -2
  94. package/src/__tests__/schedule-store.test.ts +41 -0
  95. package/src/__tests__/schedule-tools.test.ts +35 -0
  96. package/src/__tests__/server-history-render.test.ts +314 -1
  97. package/src/__tests__/skillssh-files.test.ts +1 -1
  98. package/src/__tests__/system-prompt.test.ts +20 -0
  99. package/src/__tests__/task-scheduler.test.ts +162 -1
  100. package/src/__tests__/terminal-tools.test.ts +6 -1
  101. package/src/__tests__/title-generate-hook.test.ts +319 -0
  102. package/src/__tests__/tool-error-hook.test.ts +278 -0
  103. package/src/__tests__/tool-preview-lifecycle.test.ts +468 -5
  104. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  105. package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
  106. package/src/__tests__/tool-result-truncation.test.ts +0 -2
  107. package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
  108. package/src/__tests__/ui-work-result-surface.test.ts +159 -0
  109. package/src/__tests__/usage-routes.test.ts +285 -1
  110. package/src/__tests__/user-plugin-loader.test.ts +2 -2
  111. package/src/__tests__/voice-session-bridge.test.ts +6 -3
  112. package/src/__tests__/web-search-backend-failure.test.ts +166 -0
  113. package/src/agent/loop.ts +346 -442
  114. package/src/api/events/assistant-thinking-delta.ts +33 -0
  115. package/src/api/events/tool-output-chunk.ts +45 -0
  116. package/src/api/events/tool-use-preview-start.ts +32 -0
  117. package/src/api/events/trace-event.ts +69 -0
  118. package/src/api/index.ts +48 -13
  119. package/src/api/responses/conversation-message.ts +368 -0
  120. package/src/avatar/__tests__/avatar-store.test.ts +34 -29
  121. package/src/cli/commands/__tests__/notifications.test.ts +58 -14
  122. package/src/cli/commands/notifications.ts +112 -60
  123. package/src/config/assistant-feature-flags.ts +22 -11
  124. package/src/config/bundled-skills/app-builder/SKILL.md +3 -20
  125. package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
  126. package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
  127. package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
  128. package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
  129. package/src/config/bundled-skills/document-editor/SKILL.md +1 -1
  130. package/src/config/bundled-skills/messaging/SKILL.md +0 -7
  131. package/src/config/feature-flag-cache.ts +3 -3
  132. package/src/config/feature-flag-registry.json +35 -3
  133. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  134. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
  135. package/src/config/schemas/llm.ts +1 -0
  136. package/src/config/schemas/memory-v2.ts +8 -0
  137. package/src/config/schemas/memory-v3.ts +8 -0
  138. package/src/config/schemas/platform.ts +8 -0
  139. package/src/config/seed-inference-profiles.ts +2 -2
  140. package/src/config/skills.ts +13 -0
  141. package/src/context/compactor.ts +1 -1
  142. package/src/context/strip-injections.ts +122 -0
  143. package/src/context/token-estimator.ts +23 -0
  144. package/src/context/tool-result-truncation.ts +0 -23
  145. package/src/context/window-manager.ts +3 -6
  146. package/src/credential-execution/executable-discovery.ts +16 -0
  147. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
  148. package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
  149. package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
  150. package/src/daemon/assistant-attachments.ts +1 -1
  151. package/src/daemon/config-watcher.ts +2 -2
  152. package/src/daemon/context-overflow-reducer.ts +0 -1
  153. package/src/daemon/conversation-agent-loop-handlers.ts +605 -153
  154. package/src/daemon/conversation-agent-loop.ts +281 -760
  155. package/src/daemon/conversation-history.ts +5 -4
  156. package/src/daemon/conversation-lifecycle.ts +3 -4
  157. package/src/daemon/conversation-messaging.ts +7 -6
  158. package/src/daemon/conversation-process.ts +11 -16
  159. package/src/daemon/conversation-runtime-assembly.ts +130 -347
  160. package/src/daemon/conversation-slash.ts +6 -25
  161. package/src/daemon/conversation-surfaces.ts +222 -4
  162. package/src/daemon/conversation-tool-setup.ts +2 -29
  163. package/src/daemon/conversation.ts +32 -14
  164. package/src/daemon/external-plugins-bootstrap.ts +9 -10
  165. package/src/daemon/handlers/config-a2a.ts +51 -36
  166. package/src/daemon/handlers/config-slack-channel.ts +20 -14
  167. package/src/daemon/handlers/config-telegram.ts +16 -2
  168. package/src/daemon/handlers/shared.ts +156 -84
  169. package/src/daemon/handlers/skills.ts +39 -10
  170. package/src/daemon/lifecycle.ts +4 -0
  171. package/src/daemon/message-types/apps.ts +1 -29
  172. package/src/daemon/message-types/messages.ts +9 -57
  173. package/src/daemon/message-types/skills.ts +2 -0
  174. package/src/daemon/message-types/surfaces.ts +136 -3
  175. package/src/daemon/now-scratchpad.ts +21 -0
  176. package/src/daemon/orphan-reaper.test.ts +210 -0
  177. package/src/daemon/orphan-reaper.ts +240 -0
  178. package/src/daemon/persist-unsendable-image.ts +117 -0
  179. package/src/daemon/process-message.ts +1 -3
  180. package/src/daemon/trace-emitter.ts +6 -4
  181. package/src/daemon/trust-context.ts +19 -0
  182. package/src/daemon/wake-target-adapter.ts +3 -1
  183. package/src/home/home-greeting-cache.ts +24 -1
  184. package/src/ipc/gateway-client.test.ts +2 -2
  185. package/src/ipc/gateway-client.ts +3 -3
  186. package/src/media/gemini-image-service.ts +15 -0
  187. package/src/media/openai-image-service.ts +14 -0
  188. package/src/media/types.ts +34 -0
  189. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
  190. package/src/memory/auth-fallback-events-store.ts +94 -0
  191. package/src/memory/conversation-title-service.ts +65 -41
  192. package/src/memory/db-init.ts +4 -0
  193. package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
  194. package/src/memory/graph/conversation-graph-memory.ts +65 -0
  195. package/src/memory/jobs-store.ts +33 -0
  196. package/src/memory/jobs-worker.ts +31 -4
  197. package/src/memory/llm-usage-store.ts +224 -50
  198. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
  199. package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
  200. package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
  201. package/src/memory/migrations/index.ts +2 -0
  202. package/src/memory/pkb/autoinject.ts +61 -0
  203. package/src/memory/pkb/context.ts +50 -0
  204. package/src/memory/pkb/types.ts +14 -0
  205. package/src/memory/schedule-attribution-sql.ts +104 -0
  206. package/src/memory/schema/infrastructure.ts +16 -0
  207. package/src/memory/usage-grouped-buckets.ts +6 -1
  208. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -1
  209. package/src/memory/v2/consolidation-job.ts +1 -1
  210. package/src/memory/v3/__tests__/health.test.ts +16 -0
  211. package/src/memory/v3/__tests__/orchestrate.test.ts +45 -9
  212. package/src/memory/v3/__tests__/provider-blocks.test.ts +13 -0
  213. package/src/memory/v3/__tests__/router.test.ts +101 -29
  214. package/src/memory/v3/__tests__/selector.test.ts +93 -27
  215. package/src/memory/v3/__tests__/shadow-plugin.test.ts +23 -5
  216. package/src/memory/v3/health.ts +0 -0
  217. package/src/memory/v3/llm-retry.ts +32 -0
  218. package/src/memory/v3/orchestrate.ts +26 -14
  219. package/src/memory/v3/provider-blocks.ts +15 -5
  220. package/src/memory/v3/router.ts +48 -42
  221. package/src/memory/v3/selector.ts +57 -42
  222. package/src/memory/v3/shadow-plugin.ts +47 -15
  223. package/src/memory/v3/types.ts +8 -0
  224. package/src/notifications/conversation-pairing.ts +8 -15
  225. package/src/notifications/decision-engine.ts +6 -3
  226. package/src/notifications/home-feed-side-effect.ts +12 -1
  227. package/src/permissions/prompter.ts +4 -0
  228. package/src/plugin-api/constants.ts +4 -0
  229. package/src/plugin-api/index.ts +8 -1
  230. package/src/plugin-api/types.ts +151 -1
  231. package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
  232. package/src/plugins/defaults/empty-response/register.ts +8 -13
  233. package/src/plugins/defaults/index.ts +1 -15
  234. package/src/plugins/defaults/injectors/register.ts +243 -74
  235. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +91 -0
  236. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
  237. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
  238. package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
  239. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
  240. package/src/plugins/defaults/title-generate/package.json +1 -1
  241. package/src/plugins/defaults/title-generate/register.ts +18 -18
  242. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
  243. package/src/plugins/defaults/tool-error/package.json +1 -1
  244. package/src/plugins/defaults/tool-error/register.ts +9 -21
  245. package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
  246. package/src/plugins/defaults/tool-result-truncate/register.ts +10 -21
  247. package/src/plugins/defaults/tool-result-truncate/terminal.ts +37 -18
  248. package/src/plugins/pipeline.ts +6 -18
  249. package/src/plugins/registry.ts +8 -25
  250. package/src/plugins/types.ts +43 -474
  251. package/src/proactive-artifact/aux-message-injector.ts +3 -3
  252. package/src/proactive-artifact/job.test.ts +7 -12
  253. package/src/prompts/__tests__/system-prompt.test.ts +36 -0
  254. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +62 -0
  255. package/src/prompts/templates/BOOTSTRAP.md +2 -2
  256. package/src/prompts/templates/system-sections.ts +15 -0
  257. package/src/providers/anthropic/client.ts +37 -29
  258. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -0
  259. package/src/providers/openai/chat-completions-provider.ts +44 -0
  260. package/src/providers/openrouter/client.ts +1 -0
  261. package/src/providers/placeholder-sentinels.ts +35 -0
  262. package/src/runtime/__tests__/agent-wake.test.ts +5 -1
  263. package/src/runtime/agent-wake.ts +2 -2
  264. package/src/runtime/assistant-event-hub.ts +36 -6
  265. package/src/runtime/{conversation-stream-state.ts → assistant-stream-state.ts} +132 -58
  266. package/src/runtime/http-router.ts +16 -21
  267. package/src/runtime/http-types.ts +16 -70
  268. package/src/runtime/pending-interactions.ts +1 -0
  269. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
  270. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
  271. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
  272. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  273. package/src/runtime/routes/app-management-routes.ts +6 -117
  274. package/src/runtime/routes/app-routes.ts +13 -15
  275. package/src/runtime/routes/attachment-routes.ts +26 -15
  276. package/src/runtime/routes/avatar-routes.ts +26 -0
  277. package/src/runtime/routes/btw-routes.ts +29 -23
  278. package/src/runtime/routes/consolidation-routes.ts +120 -20
  279. package/src/runtime/routes/conversation-query-routes.ts +2 -0
  280. package/src/runtime/routes/conversation-routes.ts +358 -184
  281. package/src/runtime/routes/documents-routes.ts +4 -0
  282. package/src/runtime/routes/domain-routes.ts +51 -37
  283. package/src/runtime/routes/epoch-millis-range.ts +34 -0
  284. package/src/runtime/routes/events-routes.ts +28 -34
  285. package/src/runtime/routes/gateway-log-routes.ts +26 -4
  286. package/src/runtime/routes/heartbeat-routes.ts +32 -12
  287. package/src/runtime/routes/identity-intro-cache.ts +11 -34
  288. package/src/runtime/routes/identity-routes.ts +208 -17
  289. package/src/runtime/routes/image-generation-routes.ts +40 -2
  290. package/src/runtime/routes/index.ts +2 -0
  291. package/src/runtime/routes/integrations/a2a.ts +12 -10
  292. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
  293. package/src/runtime/routes/integrations/slack/channel.ts +4 -0
  294. package/src/runtime/routes/integrations/slack/share.ts +27 -6
  295. package/src/runtime/routes/integrations/telegram.ts +6 -0
  296. package/src/runtime/routes/integrations/twilio.ts +42 -0
  297. package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
  298. package/src/runtime/routes/log-export-routes.ts +8 -0
  299. package/src/runtime/routes/memory-v2-routes.ts +15 -8
  300. package/src/runtime/routes/memory-v3-routes.ts +50 -28
  301. package/src/runtime/routes/oauth-apps.ts +66 -12
  302. package/src/runtime/routes/oauth-providers.ts +44 -5
  303. package/src/runtime/routes/platform-routes.ts +81 -5
  304. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +6 -4
  305. package/src/runtime/routes/playground/force-compact.ts +1 -1
  306. package/src/runtime/routes/rename-conversation-routes.ts +5 -0
  307. package/src/runtime/routes/schedule-routes.ts +152 -42
  308. package/src/runtime/routes/secret-routes.ts +14 -2
  309. package/src/runtime/routes/skills-routes.ts +43 -14
  310. package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
  311. package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
  312. package/src/runtime/routes/trust-rules-routes.ts +26 -2
  313. package/src/runtime/routes/tts-routes.ts +35 -0
  314. package/src/runtime/routes/types.ts +66 -8
  315. package/src/runtime/routes/usage-routes.ts +47 -39
  316. package/src/runtime/routes/webhook-routes.ts +41 -2
  317. package/src/runtime/routes/workspace-routes.ts +4 -0
  318. package/src/runtime/services/__tests__/analyze-conversation.test.ts +6 -0
  319. package/src/runtime/services/analyze-conversation.ts +2 -2
  320. package/src/schedule/schedule-store.ts +20 -1
  321. package/src/schedule/schedule-usage-store.ts +83 -0
  322. package/src/schedule/scheduler.ts +12 -5
  323. package/src/skills/catalog-files.ts +2 -2
  324. package/src/skills/catalog-install.ts +3 -0
  325. package/src/skills/categories-cache.ts +118 -0
  326. package/src/skills/clawhub-files.ts +1 -2
  327. package/src/skills/skillssh-files.ts +1 -2
  328. package/src/telemetry/types.ts +29 -1
  329. package/src/telemetry/usage-telemetry-reporter.test.ts +112 -3
  330. package/src/telemetry/usage-telemetry-reporter.ts +57 -2
  331. package/src/tools/executor.ts +1 -53
  332. package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
  333. package/src/tools/network/__tests__/web-search.test.ts +11 -3
  334. package/src/tools/network/web-search-error.test.ts +248 -0
  335. package/src/tools/network/web-search-error.ts +267 -0
  336. package/src/tools/network/web-search.ts +207 -48
  337. package/src/tools/schedule/create.ts +2 -0
  338. package/src/tools/terminal/safe-env.ts +10 -1
  339. package/src/tools/ui-surface/definitions.ts +9 -1
  340. package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
  341. package/src/tts/provider-catalog.ts +76 -1
  342. package/src/util/mutex.ts +47 -0
  343. package/src/workspace/git-service.ts +1 -42
  344. package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
  345. package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
  346. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +93 -0
  347. package/src/workspace/migrations/registry.ts +6 -0
  348. package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
  349. package/src/__tests__/empty-response-pipeline.test.ts +0 -423
  350. package/src/__tests__/llm-call-pipeline.test.ts +0 -287
  351. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
  352. package/src/__tests__/persistence-pipeline.test.ts +0 -503
  353. package/src/__tests__/title-generate-pipeline.test.ts +0 -211
  354. package/src/__tests__/token-estimate-pipeline.test.ts +0 -479
  355. package/src/__tests__/tool-error-pipeline.test.ts +0 -241
  356. package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
  357. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -341
  358. package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
  359. package/src/gallery/default-gallery.ts +0 -1359
  360. package/src/gallery/gallery-manifest.ts +0 -28
  361. package/src/home/feature-gate.ts +0 -22
  362. package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +0 -22
  363. package/src/plugins/defaults/empty-response/terminal.ts +0 -106
  364. package/src/plugins/defaults/injectors/package.json +0 -15
  365. package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +0 -17
  366. package/src/plugins/defaults/llm-call/package.json +0 -15
  367. package/src/plugins/defaults/llm-call/register.ts +0 -45
  368. package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +0 -17
  369. package/src/plugins/defaults/memory-retrieval/package.json +0 -15
  370. package/src/plugins/defaults/memory-retrieval/register.ts +0 -181
  371. package/src/plugins/defaults/persistence/middlewares/persistence.ts +0 -19
  372. package/src/plugins/defaults/persistence/package.json +0 -15
  373. package/src/plugins/defaults/persistence/register.ts +0 -38
  374. package/src/plugins/defaults/persistence/terminal.ts +0 -83
  375. package/src/plugins/defaults/title-generate/terminal.ts +0 -31
  376. package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +0 -23
  377. package/src/plugins/defaults/token-estimate/package.json +0 -15
  378. package/src/plugins/defaults/token-estimate/register.ts +0 -34
  379. package/src/plugins/defaults/token-estimate/terminal.ts +0 -40
  380. package/src/plugins/defaults/tool-error/middlewares/toolError.ts +0 -21
  381. package/src/plugins/defaults/tool-error/terminal.ts +0 -47
  382. package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +0 -23
  383. package/src/plugins/defaults/tool-execute/package.json +0 -15
  384. package/src/plugins/defaults/tool-execute/register.ts +0 -49
  385. package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +0 -23
  386. package/src/plugins/defaults/tool-result-truncate/types.ts +0 -22
  387. package/src/skills/category-inference.ts +0 -111
@@ -0,0 +1,33 @@
1
+ /**
2
+ * `assistant_thinking_delta` SSE event.
3
+ *
4
+ * Streaming reasoning chunk emitted by the daemon as a reasoning-capable
5
+ * model produces its chain of thought. Multiple deltas accumulate into a
6
+ * single assistant message's thinking block, interleaved with
7
+ * `assistant_text_delta` and tool events in emission order; the matching
8
+ * `message_complete` event marks the turn done.
9
+ *
10
+ * `messageId` is the database row id of the assistant message this
11
+ * delta belongs to — same semantics as `AssistantTextDeltaEvent.messageId`.
12
+ * Absent on streams produced by older daemons that pre-date the anchor
13
+ * protocol.
14
+ *
15
+ * Only emitted when thinking streaming is enabled for the turn; turns that
16
+ * suppress reasoning output produce none.
17
+ *
18
+ * Canonical wire-contract source. Daemon code imports the type directly
19
+ * from this file; external consumers import via `@vellumai/assistant-api`.
20
+ */
21
+
22
+ import { z } from "zod";
23
+
24
+ export const AssistantThinkingDeltaEventSchema = z.object({
25
+ type: z.literal("assistant_thinking_delta"),
26
+ thinking: z.string(),
27
+ messageId: z.string().optional(),
28
+ conversationId: z.string().optional(),
29
+ });
30
+
31
+ export type AssistantThinkingDeltaEvent = z.infer<
32
+ typeof AssistantThinkingDeltaEventSchema
33
+ >;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * `tool_output_chunk` SSE event.
3
+ *
4
+ * Streamed by the daemon's agent loop while a tool runs, carrying
5
+ * incremental output (e.g. a bash command's stdout). The `subType` and
6
+ * `subTool*` fields describe nested sub-tool activity for tools that
7
+ * themselves orchestrate other tools, so clients can render sub-steps
8
+ * within the parent tool's output.
9
+ *
10
+ * `messageId` is the database row id of the assistant message that owns
11
+ * the parent tool_use block; absent on streams produced by older daemons
12
+ * that pre-date the anchor protocol. Same semantics as
13
+ * `AssistantTextDeltaEvent.messageId`.
14
+ *
15
+ * Canonical wire-contract source. Daemon code imports the type
16
+ * directly from this file; external consumers import via
17
+ * `@vellumai/assistant-api`.
18
+ */
19
+
20
+ import { z } from "zod";
21
+
22
+ export const ToolOutputChunkSubTypeSchema = z.enum([
23
+ "tool_start",
24
+ "tool_complete",
25
+ "status",
26
+ ]);
27
+
28
+ export type ToolOutputChunkSubType = z.infer<
29
+ typeof ToolOutputChunkSubTypeSchema
30
+ >;
31
+
32
+ export const ToolOutputChunkEventSchema = z.object({
33
+ type: z.literal("tool_output_chunk"),
34
+ chunk: z.string(),
35
+ conversationId: z.string().optional(),
36
+ toolUseId: z.string().optional(),
37
+ subType: ToolOutputChunkSubTypeSchema.optional(),
38
+ subToolName: z.string().optional(),
39
+ subToolInput: z.string().optional(),
40
+ subToolIsError: z.boolean().optional(),
41
+ subToolId: z.string().optional(),
42
+ messageId: z.string().optional(),
43
+ });
44
+
45
+ export type ToolOutputChunkEvent = z.infer<typeof ToolOutputChunkEventSchema>;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `tool_use_preview_start` SSE event.
3
+ *
4
+ * Emitted by the daemon's agent loop the moment a tool_use block is
5
+ * recognized in the model stream, before its input has finished
6
+ * streaming. Clients use it to render a tool affordance optimistically;
7
+ * the structured input arrives later via `tool_input_delta` and the
8
+ * invocation proper via `tool_use_start`.
9
+ *
10
+ * `messageId` is the database row id of the assistant message that owns
11
+ * this tool_use block; absent on streams produced by older daemons that
12
+ * pre-date the anchor protocol. Same semantics as
13
+ * `AssistantTextDeltaEvent.messageId`.
14
+ *
15
+ * Canonical wire-contract source. Daemon code imports the type
16
+ * directly from this file; external consumers import via
17
+ * `@vellumai/assistant-api`.
18
+ */
19
+
20
+ import { z } from "zod";
21
+
22
+ export const ToolUsePreviewStartEventSchema = z.object({
23
+ type: z.literal("tool_use_preview_start"),
24
+ toolUseId: z.string(),
25
+ toolName: z.string(),
26
+ conversationId: z.string().optional(),
27
+ messageId: z.string().optional(),
28
+ });
29
+
30
+ export type ToolUsePreviewStartEvent = z.infer<
31
+ typeof ToolUsePreviewStartEventSchema
32
+ >;
@@ -0,0 +1,69 @@
1
+ /**
2
+ * `trace_event` SSE event.
3
+ *
4
+ * Diagnostic timeline event emitted by the daemon's `TraceEmitter` as a
5
+ * request moves through its lifecycle (received, queued, LLM calls, tool
6
+ * invocations, completion). Each event carries a monotonic per-conversation
7
+ * `sequence` so clients can reconstruct order even when timestamps collide,
8
+ * plus optional structured `attributes` (e.g. token counts, latency, tool
9
+ * name). The daemon normalizes every attribute value to a primitive, so the
10
+ * value type is the `string | number | boolean | null` union below.
11
+ *
12
+ * `kind` and `status` are strict enums because the daemon emits a fixed,
13
+ * known set and clients switch on them (icons, metrics, group status).
14
+ *
15
+ * Canonical wire-contract source. Daemon code imports the type directly
16
+ * from this file; external consumers import via `@vellumai/assistant-api`.
17
+ */
18
+
19
+ import { z } from "zod";
20
+
21
+ export const TraceEventKindSchema = z.enum([
22
+ "request_received",
23
+ "request_queued",
24
+ "request_dequeued",
25
+ "llm_call_started",
26
+ "llm_call_finished",
27
+ "assistant_message",
28
+ "tool_started",
29
+ "tool_permission_requested",
30
+ "tool_permission_decided",
31
+ "tool_finished",
32
+ "tool_failed",
33
+ "generation_handoff",
34
+ "message_complete",
35
+ "generation_cancelled",
36
+ "request_error",
37
+ "tool_profiling_summary",
38
+ ]);
39
+
40
+ export type TraceEventKind = z.infer<typeof TraceEventKindSchema>;
41
+
42
+ export const TraceEventStatusSchema = z.enum([
43
+ "info",
44
+ "success",
45
+ "warning",
46
+ "error",
47
+ ]);
48
+
49
+ export type TraceEventStatus = z.infer<typeof TraceEventStatusSchema>;
50
+
51
+ export const TraceEventSchema = z.object({
52
+ type: z.literal("trace_event"),
53
+ eventId: z.string(),
54
+ conversationId: z.string(),
55
+ requestId: z.string().optional(),
56
+ timestampMs: z.number(),
57
+ sequence: z.number(),
58
+ kind: TraceEventKindSchema,
59
+ status: TraceEventStatusSchema.optional(),
60
+ summary: z.string(),
61
+ attributes: z
62
+ .record(
63
+ z.string(),
64
+ z.union([z.string(), z.number(), z.boolean(), z.null()]),
65
+ )
66
+ .optional(),
67
+ });
68
+
69
+ export type TraceEvent = z.infer<typeof TraceEventSchema>;
package/src/api/index.ts CHANGED
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
 
3
3
  import { AssistantActivityStateEventSchema } from "./events/assistant-activity-state.js";
4
4
  import { AssistantTextDeltaEventSchema } from "./events/assistant-text-delta.js";
5
+ import { AssistantThinkingDeltaEventSchema } from "./events/assistant-thinking-delta.js";
5
6
  import { AssistantTurnStartEventSchema } from "./events/assistant-turn-start.js";
6
7
  import { AvatarUpdatedEventSchema } from "./events/avatar-updated.js";
7
8
  import { CompactionCircuitClosedEventSchema } from "./events/compaction-circuit-closed.js";
@@ -38,8 +39,11 @@ import { SubagentEventEventSchema } from "./events/subagent-event.js";
38
39
  import { SubagentSpawnedEventSchema } from "./events/subagent-spawned.js";
39
40
  import { SubagentStatusChangedEventSchema } from "./events/subagent-status-changed.js";
40
41
  import { SyncChangedEventSchema } from "./events/sync-changed.js";
42
+ import { ToolOutputChunkEventSchema } from "./events/tool-output-chunk.js";
41
43
  import { ToolResultEventSchema } from "./events/tool-result.js";
44
+ import { ToolUsePreviewStartEventSchema } from "./events/tool-use-preview-start.js";
42
45
  import { ToolUseStartEventSchema } from "./events/tool-use-start.js";
46
+ import { TraceEventSchema } from "./events/trace-event.js";
43
47
  import { TurnProfileAutoRoutedEventSchema } from "./events/turn-profile-auto-routed.js";
44
48
  import { UISurfaceCompleteEventSchema } from "./events/ui-surface-complete.js";
45
49
  import { UISurfaceDismissEventSchema } from "./events/ui-surface-dismiss.js";
@@ -68,6 +72,10 @@ export {
68
72
  type AssistantTextDeltaEvent,
69
73
  AssistantTextDeltaEventSchema,
70
74
  } from "./events/assistant-text-delta.js";
75
+ export {
76
+ type AssistantThinkingDeltaEvent,
77
+ AssistantThinkingDeltaEventSchema,
78
+ } from "./events/assistant-thinking-delta.js";
71
79
  export {
72
80
  type AssistantTurnStartEvent,
73
81
  AssistantTurnStartEventSchema,
@@ -242,6 +250,12 @@ export {
242
250
  type SyncChangedEvent,
243
251
  SyncChangedEventSchema,
244
252
  } from "./events/sync-changed.js";
253
+ export {
254
+ type ToolOutputChunkEvent,
255
+ ToolOutputChunkEventSchema,
256
+ type ToolOutputChunkSubType,
257
+ ToolOutputChunkSubTypeSchema,
258
+ } from "./events/tool-output-chunk.js";
245
259
  export {
246
260
  type RiskScopeOption,
247
261
  RiskScopeOptionSchema,
@@ -258,10 +272,22 @@ export {
258
272
  type WebSearchResultItem,
259
273
  WebSearchResultItemSchema,
260
274
  } from "./events/tool-result.js";
275
+ export {
276
+ type ToolUsePreviewStartEvent,
277
+ ToolUsePreviewStartEventSchema,
278
+ } from "./events/tool-use-preview-start.js";
261
279
  export {
262
280
  type ToolUseStartEvent,
263
281
  ToolUseStartEventSchema,
264
282
  } from "./events/tool-use-start.js";
283
+ export {
284
+ type TraceEvent,
285
+ type TraceEventKind,
286
+ TraceEventKindSchema,
287
+ TraceEventSchema,
288
+ type TraceEventStatus,
289
+ TraceEventStatusSchema,
290
+ } from "./events/trace-event.js";
265
291
  export {
266
292
  type TurnProfileAutoRoutedEvent,
267
293
  TurnProfileAutoRoutedEventSchema,
@@ -298,6 +324,24 @@ export {
298
324
  type DictationRequest,
299
325
  DictationRequestSchema,
300
326
  } from "./requests/dictation.js";
327
+ export {
328
+ type ConversationContentBlock,
329
+ ConversationContentBlockSchema,
330
+ type ConversationMessage,
331
+ type ConversationMessageAttachment,
332
+ ConversationMessageAttachmentSchema,
333
+ ConversationMessageSchema,
334
+ type ConversationMessageSurface,
335
+ ConversationMessageSurfaceSchema,
336
+ type ConversationMessageToolCall,
337
+ ConversationMessageToolCallSchema,
338
+ type ConversationSlackMessage,
339
+ ConversationSlackMessageSchema,
340
+ type ConversationSubagentNotification,
341
+ ConversationSubagentNotificationSchema,
342
+ type PendingToolConfirmation,
343
+ PendingToolConfirmationSchema,
344
+ } from "./responses/conversation-message.js";
301
345
  export {
302
346
  type DiskPressureStatusResponse,
303
347
  DiskPressureStatusResponseSchema,
@@ -396,6 +440,7 @@ export {
396
440
  export const AssistantEventSchema = z.discriminatedUnion("type", [
397
441
  AssistantActivityStateEventSchema,
398
442
  AssistantTextDeltaEventSchema,
443
+ AssistantThinkingDeltaEventSchema,
399
444
  AssistantTurnStartEventSchema,
400
445
  AvatarUpdatedEventSchema,
401
446
  CompactionCircuitClosedEventSchema,
@@ -432,8 +477,11 @@ export const AssistantEventSchema = z.discriminatedUnion("type", [
432
477
  SubagentSpawnedEventSchema,
433
478
  SubagentStatusChangedEventSchema,
434
479
  SyncChangedEventSchema,
480
+ ToolOutputChunkEventSchema,
435
481
  ToolResultEventSchema,
482
+ ToolUsePreviewStartEventSchema,
436
483
  ToolUseStartEventSchema,
484
+ TraceEventSchema,
437
485
  TurnProfileAutoRoutedEventSchema,
438
486
  UISurfaceCompleteEventSchema,
439
487
  UISurfaceDismissEventSchema,
@@ -461,19 +509,6 @@ export const AssistantEventEnvelopeSchema = z.object({
461
509
  id: z.string(),
462
510
  conversationId: z.string().optional(),
463
511
  seq: z.number().int().optional(),
464
- /**
465
- * Subscriber-filtered sequence number. Monotonic per conversation per
466
- * SSE subscriber, counting only events the subscriber is eligible to
467
- * receive (i.e. after capability/client/interface targeting is applied).
468
- * Gap-free by construction — clients should prefer `clientSeq` over
469
- * `seq` for gap detection to avoid false positives caused by targeted
470
- * events (host_bash, host_cu, etc.) that increment the global `seq`
471
- * but are filtered out for non-matching subscribers.
472
- *
473
- * Absent on older daemons that predate this field; clients fall back
474
- * to `seq` when `clientSeq` is not present.
475
- */
476
- clientSeq: z.number().int().optional(),
477
512
  emittedAt: z.string(),
478
513
  message: AssistantEventSchema,
479
514
  });
@@ -0,0 +1,368 @@
1
+ /**
2
+ * Wire contract for the conversation history / messages endpoints.
3
+ *
4
+ * - `GET /v1/assistants/:id/messages` → `{ messages: ConversationMessage[] }`
5
+ * - `POST /v1/messages` send acks echo an `assistantMessage: ConversationMessage`
6
+ *
7
+ * Holds the canonical history-row shape produced by the daemon's
8
+ * `renderHistoryContent` + conversation-routes serializer and consumed by
9
+ * every history client (web, CLI, evals). Defining it here — rather than
10
+ * re-declaring it in the daemon's `http-types.ts` and again in the web's
11
+ * `chat/api/messages.ts` — means the producer and all consumers derive from
12
+ * one source and cannot drift.
13
+ *
14
+ * The arrays use a positional encoding:
15
+ * - `contentOrder` entries are `"<type>:<index>"` strings (e.g. `"text:0"`,
16
+ * `"thinking:1"`, `"tool:0"`, `"surface:0"`, `"attachment:0"`). The index
17
+ * points into the matching array below.
18
+ * - `textSegments`, `thinkingSegments` are plain string arrays.
19
+ * - `toolCalls`, `surfaces`, `attachments` are object arrays.
20
+ *
21
+ * Canonical wire-contract source. Assistant code imports the types directly
22
+ * from this file via relative paths; external consumers (web client,
23
+ * gateway, evals) import via `@vellumai/assistant-api`.
24
+ */
25
+
26
+ import { z } from "zod";
27
+
28
+ import {
29
+ AllowlistOptionSchema,
30
+ DirectoryScopeOptionSchema,
31
+ ScopeOptionSchema,
32
+ } from "../events/confirmation-request.js";
33
+ import { ToolActivityMetadataSchema } from "../events/tool-result.js";
34
+
35
+ // ---------------------------------------------------------------------------
36
+ // Attachment metadata
37
+ // ---------------------------------------------------------------------------
38
+
39
+ /** Structured attachment metadata attached to a history row. */
40
+ export const ConversationMessageAttachmentSchema = z.object({
41
+ id: z.string(),
42
+ filename: z.string(),
43
+ mimeType: z.string(),
44
+ sizeBytes: z.number(),
45
+ kind: z.string(),
46
+ /** Base64-encoded file data. Only populated for images on history reload. */
47
+ data: z.string().optional(),
48
+ /** Base64-encoded thumbnail, when one was generated. */
49
+ thumbnailData: z.string().optional(),
50
+ /** True when the attachment bytes are backed by a file on disk. */
51
+ fileBacked: z.boolean().optional(),
52
+ });
53
+ export type ConversationMessageAttachment = z.infer<
54
+ typeof ConversationMessageAttachmentSchema
55
+ >;
56
+
57
+ // ---------------------------------------------------------------------------
58
+ // Tool call
59
+ // ---------------------------------------------------------------------------
60
+
61
+ const RiskScopeOptionSchema = z.object({
62
+ pattern: z.string(),
63
+ label: z.string(),
64
+ });
65
+
66
+ const RiskAllowlistOptionSchema = z.object({
67
+ label: z.string(),
68
+ description: z.string(),
69
+ pattern: z.string(),
70
+ });
71
+
72
+ const RiskDirectoryScopeOptionSchema = z.object({
73
+ scope: z.string(),
74
+ label: z.string(),
75
+ });
76
+
77
+ /**
78
+ * In-flight permission prompt awaiting a user decision, mirrored onto a
79
+ * history tool call so a cold reconnect (or a conversation reopened after the
80
+ * event-buffer window has elapsed) can restore the inline confirmation card
81
+ * without replaying the live `confirmation_request` SSE event.
82
+ *
83
+ * The daemon stamps this at render time by consulting the in-memory
84
+ * `pending-interactions` registry (the authoritative store of unresolved
85
+ * prompts) — it is not persisted to the database, so it appears only while the
86
+ * prompt is genuinely outstanding and disappears once the interaction
87
+ * resolves. The shape mirrors the `confirmation_request` event the live path
88
+ * delivers, so both paths hydrate the same client state.
89
+ */
90
+ export const PendingToolConfirmationSchema = z.object({
91
+ requestId: z.string(),
92
+ title: z.string().optional(),
93
+ description: z.string().optional(),
94
+ toolName: z.string().optional(),
95
+ riskLevel: z.string().optional(),
96
+ riskReason: z.string().optional(),
97
+ input: z.record(z.string(), z.unknown()).optional(),
98
+ allowlistOptions: z.array(AllowlistOptionSchema).optional(),
99
+ scopeOptions: z.array(ScopeOptionSchema).optional(),
100
+ directoryScopeOptions: z.array(DirectoryScopeOptionSchema).optional(),
101
+ persistentDecisionsAllowed: z.boolean().optional(),
102
+ });
103
+ export type PendingToolConfirmation = z.infer<
104
+ typeof PendingToolConfirmationSchema
105
+ >;
106
+
107
+ /**
108
+ * Closed set of confirmation outcomes recorded for a tool call. The daemon
109
+ * only ever persists one of these three values (the outcome map is gated to
110
+ * them in `conversation-agent-loop.ts`), so the wire carries the closed enum
111
+ * rather than a free string and clients consume it without re-narrowing.
112
+ */
113
+ export const ConfirmationDecisionSchema = z.enum([
114
+ "approved",
115
+ "denied",
116
+ "timed_out",
117
+ ]);
118
+ export type ConfirmationDecision = z.infer<typeof ConfirmationDecisionSchema>;
119
+
120
+ /**
121
+ * A single tool call rendered into a history row. Mirrors the object the
122
+ * daemon's `renderHistoryContent` emits; `contentOrder` references it as
123
+ * `tool:N` where `N` indexes into `toolCalls`.
124
+ */
125
+ export const ConversationMessageToolCallSchema = z.object({
126
+ /** Stable tool-call id: the provider `tool_use` id, or a synthesized positional id. Guaranteed present as of daemon v0.8.8; optional for skew with older daemons. */
127
+ id: z.string().optional(),
128
+ name: z.string(),
129
+ input: z.record(z.string(), z.unknown()),
130
+ result: z.string().optional(),
131
+ isError: z.boolean().optional(),
132
+ /** Base64-encoded image data from tool contentBlocks. @deprecated Use imageDataList. */
133
+ imageData: z.string().optional(),
134
+ /** Base64-encoded image data from tool contentBlocks (e.g. browser_screenshot, image generation). */
135
+ imageDataList: z.array(z.string()).optional(),
136
+ /** Unix ms when the tool started executing. */
137
+ startedAt: z.number().optional(),
138
+ /** Unix ms when the tool completed. */
139
+ completedAt: z.number().optional(),
140
+ /**
141
+ * Confirmation outcome for this tool call, when one was recorded. Closed
142
+ * enum: the daemon has only ever emitted these three values since the field
143
+ * was introduced, so every daemon that carries it conforms — no version gate.
144
+ */
145
+ confirmationDecision: ConfirmationDecisionSchema.optional(),
146
+ /** Friendly label for the confirmation (e.g. "Edit File", "Run Command"). */
147
+ confirmationLabel: z.string().optional(),
148
+ /** Risk level classification at invocation time ("low" | "medium" | "high" | "unknown"). */
149
+ riskLevel: z.string().optional(),
150
+ /** Human-readable reason for the risk classification. */
151
+ riskReason: z.string().optional(),
152
+ /** ID of the trust rule that matched this invocation (if any). */
153
+ matchedTrustRuleId: z.string().optional(),
154
+ /** @deprecated Use `approvalMode` and `approvalReason` instead. */
155
+ autoApproved: z.boolean().optional(),
156
+ /** How the approval decision was reached: prompted, auto, blocked, or unknown (legacy). */
157
+ approvalMode: z.string().optional(),
158
+ /** Why the approval decision was reached (stable enum for client display). */
159
+ approvalReason: z.string().optional(),
160
+ /** Snapshot of the auto-approve threshold at execution time. */
161
+ riskThreshold: z.string().optional(),
162
+ /** Display-only regex ladder for the rule editor (narrowest → broadest). */
163
+ riskScopeOptions: z.array(RiskScopeOptionSchema).optional(),
164
+ /** Minimatch save patterns for the rule editor (narrowest → broadest). */
165
+ riskAllowlistOptions: z.array(RiskAllowlistOptionSchema).optional(),
166
+ /** Directory scope ladder for the rule editor. */
167
+ riskDirectoryScopeOptions: z.array(RiskDirectoryScopeOptionSchema).optional(),
168
+ /**
169
+ * Structured tool activity (web_search / web_fetch) for rich client cards.
170
+ * Persisted alongside the tool call so the activity card survives a history
171
+ * reopen instead of degrading to the plain `result` text. Mirrors the live
172
+ * `tool_result` event's `activityMetadata`. Guaranteed present for tool calls
173
+ * that produced activity as of daemon v0.8.8; absent for older history rows.
174
+ */
175
+ activityMetadata: ToolActivityMetadataSchema.optional(),
176
+ /**
177
+ * Confirmation scope ladder (`{label, scope}`) for scope-aware tools
178
+ * (file/bash). Derived at render time via the permission checker's pure
179
+ * `generateScopeOptions(workspaceDir, toolName)`, so it is reconstructed for
180
+ * completed tool calls on history reopen rather than persisted. Feeds the
181
+ * rule editor's trust-rule suggestion fallback. Distinct from the
182
+ * regex-flavored `riskScopeOptions` (`{pattern, label}`). Guaranteed present
183
+ * for scope-aware tools as of daemon v0.8.8; absent for older history rows.
184
+ */
185
+ scopeOptions: z.array(ScopeOptionSchema).optional(),
186
+ /**
187
+ * In-flight permission prompt, present only while the tool call is awaiting
188
+ * a user decision (read from the `pending-interactions` registry at render
189
+ * time). Lets a cold reconnect restore the inline confirmation card.
190
+ * Guaranteed present for outstanding prompts as of daemon v0.8.8.
191
+ */
192
+ pendingConfirmation: PendingToolConfirmationSchema.optional(),
193
+ });
194
+ export type ConversationMessageToolCall = z.infer<
195
+ typeof ConversationMessageToolCallSchema
196
+ >;
197
+
198
+ // ---------------------------------------------------------------------------
199
+ // Surface
200
+ // ---------------------------------------------------------------------------
201
+
202
+ const SurfaceActionSchema = z.object({
203
+ id: z.string(),
204
+ label: z.string(),
205
+ style: z.string().optional(),
206
+ data: z.record(z.string(), z.unknown()).optional(),
207
+ });
208
+
209
+ /**
210
+ * A UI surface (widget) embedded in a history row. `contentOrder` references
211
+ * it as `surface:N` where `N` indexes into `surfaces`.
212
+ */
213
+ export const ConversationMessageSurfaceSchema = z.object({
214
+ surfaceId: z.string(),
215
+ surfaceType: z.string(),
216
+ title: z.string().optional(),
217
+ data: z.record(z.string(), z.unknown()),
218
+ actions: z.array(SurfaceActionSchema).optional(),
219
+ display: z.string().optional(),
220
+ persistent: z.boolean().optional(),
221
+ completed: z.boolean().optional(),
222
+ completionSummary: z.string().optional(),
223
+ /** Id of the tool call that produced this surface (the `ui_show` proxy tool). */
224
+ toolCallId: z.string().optional(),
225
+ });
226
+ export type ConversationMessageSurface = z.infer<
227
+ typeof ConversationMessageSurfaceSchema
228
+ >;
229
+
230
+ // ---------------------------------------------------------------------------
231
+ // Subagent notification
232
+ // ---------------------------------------------------------------------------
233
+
234
+ /** Daemon-injected subagent lifecycle notification attached to a history row. */
235
+ export const ConversationSubagentNotificationSchema = z.object({
236
+ subagentId: z.string(),
237
+ label: z.string(),
238
+ status: z.string(),
239
+ error: z.string().optional(),
240
+ conversationId: z.string().optional(),
241
+ objective: z.string().optional(),
242
+ });
243
+ export type ConversationSubagentNotification = z.infer<
244
+ typeof ConversationSubagentNotificationSchema
245
+ >;
246
+
247
+ // ---------------------------------------------------------------------------
248
+ // Slack message envelope
249
+ // ---------------------------------------------------------------------------
250
+
251
+ const SlackMessageLinkSchema = z.object({
252
+ appUrl: z.string().optional(),
253
+ webUrl: z.string().optional(),
254
+ });
255
+
256
+ /** Slack provenance for a history row that originated from a Slack channel. */
257
+ export const ConversationSlackMessageSchema = z.object({
258
+ channelId: z.string(),
259
+ channelName: z.string().optional(),
260
+ channelTs: z.string(),
261
+ threadTs: z.string().optional(),
262
+ sender: z
263
+ .object({
264
+ displayName: z.string().optional(),
265
+ externalUserId: z.string().optional(),
266
+ })
267
+ .optional(),
268
+ messageLink: SlackMessageLinkSchema.optional(),
269
+ threadLink: SlackMessageLinkSchema.optional(),
270
+ });
271
+ export type ConversationSlackMessage = z.infer<
272
+ typeof ConversationSlackMessageSchema
273
+ >;
274
+
275
+ // ---------------------------------------------------------------------------
276
+ // Content block (unified ordered content)
277
+ // ---------------------------------------------------------------------------
278
+
279
+ /**
280
+ * A single ordered content block. `contentBlocks` is the unified, display-ready
281
+ * projection of a message's model-native content — one ordered tagged array so
282
+ * clients render by mapping a single list instead of cross-referencing the
283
+ * parallel positional arrays.
284
+ *
285
+ * Discriminants and field names mirror the model-loop `ContentBlock` union
286
+ * (`providers/types.ts`) so logic reads the same whether it runs in a
287
+ * plugin/hook (raw provider blocks) or on a client (this cleaned wire form).
288
+ * The wire form differs from the raw provider union in three deliberate ways:
289
+ * - `tool_use` carries its paired result (`toolCall.result`): the daemon
290
+ * merges the separate `tool_result` block at read time so clients never
291
+ * re-pair calls with their results.
292
+ * - internal/sensitive provider fields are dropped (risk/approval scratch
293
+ * fields, raw base64 image bytes, provider thought signatures, opaque
294
+ * server-tool blobs).
295
+ * - vellum projections with no provider analog (`surface`, `attachment`)
296
+ * reuse the existing history schemas.
297
+ *
298
+ * The daemon builds this array directly from the model-native content while
299
+ * rendering history (`renderHistoryContent`); the serializer never reconstructs
300
+ * it from the positional arrays, so it stays correct once those are retired.
301
+ */
302
+ export const ConversationContentBlockSchema = z.discriminatedUnion("type", [
303
+ z.object({ type: z.literal("text"), text: z.string() }),
304
+ z.object({ type: z.literal("thinking"), thinking: z.string() }),
305
+ z.object({
306
+ type: z.literal("tool_use"),
307
+ toolCall: ConversationMessageToolCallSchema,
308
+ }),
309
+ z.object({
310
+ type: z.literal("surface"),
311
+ surface: ConversationMessageSurfaceSchema,
312
+ }),
313
+ z.object({
314
+ type: z.literal("attachment"),
315
+ attachment: ConversationMessageAttachmentSchema,
316
+ }),
317
+ ]);
318
+ export type ConversationContentBlock = z.infer<
319
+ typeof ConversationContentBlockSchema
320
+ >;
321
+
322
+ // ---------------------------------------------------------------------------
323
+ // Conversation message (history row)
324
+ // ---------------------------------------------------------------------------
325
+
326
+ /**
327
+ * A single consolidated history row as returned by the daemon's messages
328
+ * endpoint. Consecutive assistant DB rows are merged into one display row;
329
+ * `mergedMessageIds` records the folded ids.
330
+ */
331
+ export const ConversationMessageSchema = z.object({
332
+ id: z.string(),
333
+ /**
334
+ * Server message ids folded into this display row when consecutive
335
+ * assistant messages were consolidated for history rendering.
336
+ */
337
+ mergedMessageIds: z.array(z.string()).optional(),
338
+ role: z.string(),
339
+ /**
340
+ * Flat plain-text body (joined text segments). Redundant with
341
+ * `textSegments`/`contentOrder` for clients that render from the positional
342
+ * arrays (web, CLI), but the legacy Swift macOS client reads `content`
343
+ * directly and drops any history row missing it (its
344
+ * `HistoryReconstructionService` skips rows with empty text). The serializer
345
+ * always emits it — do not remove without updating that client.
346
+ */
347
+ content: z.string().optional(),
348
+ /** Display timestamp as an ISO-8601 string. */
349
+ timestamp: z.string(),
350
+ attachments: z.array(ConversationMessageAttachmentSchema),
351
+ toolCalls: z.array(ConversationMessageToolCallSchema).optional(),
352
+ surfaces: z.array(ConversationMessageSurfaceSchema).optional(),
353
+ textSegments: z.array(z.string()).optional(),
354
+ thinkingSegments: z.array(z.string()).optional(),
355
+ /** Positional `"<type>:<index>"` content ordering (e.g. `"text:0"`, `"thinking:1"`). */
356
+ contentOrder: z.array(z.string()).optional(),
357
+ /**
358
+ * Unified ordered content blocks — the display-ready projection of the
359
+ * row's model-native content. Ships alongside the positional
360
+ * `contentOrder`/`textSegments`/`thinkingSegments` arrays during the client
361
+ * migration; a client that consumes `contentBlocks` can ignore the
362
+ * positional arrays entirely.
363
+ */
364
+ contentBlocks: z.array(ConversationContentBlockSchema).optional(),
365
+ subagentNotification: ConversationSubagentNotificationSchema.optional(),
366
+ slackMessage: ConversationSlackMessageSchema.optional(),
367
+ });
368
+ export type ConversationMessage = z.infer<typeof ConversationMessageSchema>;