@vellumai/assistant 0.8.6 → 0.8.7

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 (891) hide show
  1. package/AGENTS.md +4 -4
  2. package/Dockerfile +1 -0
  3. package/bun.lock +11 -2
  4. package/docker-entrypoint.sh +8 -6
  5. package/docs/plugins.md +63 -28
  6. package/examples/plugins/echo/register.ts +4 -7
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/environments/bun.lock +24 -0
  9. package/node_modules/@vellumai/environments/package.json +18 -0
  10. package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +95 -0
  11. package/node_modules/@vellumai/environments/src/index.ts +11 -0
  12. package/node_modules/@vellumai/environments/src/seeds.ts +73 -0
  13. package/node_modules/@vellumai/environments/src/types.ts +70 -0
  14. package/node_modules/@vellumai/environments/tsconfig.json +20 -0
  15. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +11 -0
  16. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +3 -4
  17. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +6 -2
  18. package/openapi.yaml +3735 -353
  19. package/package.json +7 -3
  20. package/scripts/generate-openapi.ts +20 -13
  21. package/src/__tests__/agent-loop-callsite-precedence.test.ts +42 -80
  22. package/src/__tests__/agent-loop-exit-reason.test.ts +240 -39
  23. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +141 -0
  24. package/src/__tests__/agent-loop-override-profile.test.ts +19 -32
  25. package/src/__tests__/agent-loop-provider-error-recording.test.ts +6 -4
  26. package/src/__tests__/agent-loop-thinking.test.ts +17 -12
  27. package/src/__tests__/agent-loop.test.ts +207 -341
  28. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +4 -2
  29. package/src/__tests__/agent-wake-override-profile.test.ts +22 -40
  30. package/src/__tests__/anthropic-provider.test.ts +201 -55
  31. package/src/__tests__/app-builder-skill-instructions.test.ts +22 -0
  32. package/src/__tests__/app-control-flow.test.ts +5 -0
  33. package/src/__tests__/approval-cascade.test.ts +4 -11
  34. package/src/__tests__/approval-routes-http.test.ts +4 -2
  35. package/src/__tests__/assistant-event.test.ts +15 -0
  36. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
  37. package/src/__tests__/avatar-e2e.test.ts +7 -37
  38. package/src/__tests__/avatar-generator.test.ts +12 -42
  39. package/src/__tests__/avatar-identity-sync.test.ts +28 -3
  40. package/src/__tests__/background-shell-bash.test.ts +3 -7
  41. package/src/__tests__/btw-routes.test.ts +7 -12
  42. package/src/__tests__/call-pointer-messages.test.ts +5 -3
  43. package/src/__tests__/call-site-routing-provider.test.ts +22 -40
  44. package/src/__tests__/catalog-files.test.ts +1 -0
  45. package/src/__tests__/channel-approval-routes.test.ts +48 -20
  46. package/src/__tests__/channel-approvals.test.ts +3 -1
  47. package/src/__tests__/channel-invite-transport.test.ts +1 -5
  48. package/src/__tests__/channel-readiness-routes.test.ts +0 -4
  49. package/src/__tests__/channel-readiness-slack-remote.test.ts +2 -7
  50. package/src/__tests__/channel-retry-sweep.test.ts +71 -79
  51. package/src/__tests__/circuit-breaker-pipeline.test.ts +3 -3
  52. package/src/__tests__/clawhub-files.test.ts +1 -0
  53. package/src/__tests__/compaction-events.test.ts +5 -17
  54. package/src/__tests__/compaction-pipeline.test.ts +1 -1
  55. package/src/__tests__/compaction-timeout-recovery.test.ts +37 -48
  56. package/src/__tests__/compaction-trail-store.test.ts +1 -79
  57. package/src/__tests__/compactor-image-manifest-trust.test.ts +112 -0
  58. package/src/__tests__/computer-use-tools.test.ts +2 -2
  59. package/src/__tests__/config-watcher.test.ts +28 -0
  60. package/src/__tests__/context-search-agent-runner.test.ts +6 -3
  61. package/src/__tests__/context-token-estimator.test.ts +34 -0
  62. package/src/__tests__/context-window-manager-compact-retry.test.ts +291 -0
  63. package/src/__tests__/conversation-abort-tool-results.test.ts +14 -7
  64. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -2
  65. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +12 -27
  66. package/src/__tests__/conversation-agent-loop-overflow.test.ts +430 -90
  67. package/src/__tests__/conversation-agent-loop.test.ts +581 -62
  68. package/src/__tests__/conversation-analysis-routes.test.ts +1 -3
  69. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
  70. package/src/__tests__/conversation-clear-safety.test.ts +20 -10
  71. package/src/__tests__/conversation-confirmation-signals.test.ts +15 -45
  72. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  73. package/src/__tests__/conversation-disk-view.test.ts +10 -17
  74. package/src/__tests__/conversation-fork-crud.test.ts +86 -172
  75. package/src/__tests__/conversation-fork-route.test.ts +16 -14
  76. package/src/__tests__/conversation-init.benchmark.test.ts +6 -6
  77. package/src/__tests__/conversation-lifecycle.test.ts +3 -2
  78. package/src/__tests__/conversation-load-history-repair.test.ts +3 -2
  79. package/src/__tests__/conversation-load-history-stripped.test.ts +1 -1
  80. package/src/__tests__/conversation-message-sync-tags.test.ts +3 -4
  81. package/src/__tests__/conversation-pairing.test.ts +34 -4
  82. package/src/__tests__/conversation-pre-run-repair.test.ts +1 -1
  83. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -0
  84. package/src/__tests__/conversation-process-callsite.test.ts +27 -30
  85. package/src/__tests__/conversation-provider-retry-repair.test.ts +53 -44
  86. package/src/__tests__/conversation-queue.test.ts +270 -164
  87. package/src/__tests__/conversation-routes-disk-view.test.ts +3 -2
  88. package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
  89. package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -2
  90. package/src/__tests__/conversation-runtime-assembly.test.ts +20 -22
  91. package/src/__tests__/conversation-runtime-workspace.test.ts +19 -1
  92. package/src/__tests__/conversation-slash-queue.test.ts +37 -31
  93. package/src/__tests__/conversation-slash-unknown.test.ts +13 -15
  94. package/src/__tests__/conversation-speed-override.test.ts +8 -22
  95. package/src/__tests__/conversation-stream-state.test.ts +484 -0
  96. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +6 -15
  97. package/src/__tests__/conversation-surfaces-app-control.test.ts +32 -4
  98. package/src/__tests__/conversation-surfaces-state-update.test.ts +5 -2
  99. package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -15
  100. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +23 -11
  101. package/src/__tests__/conversation-unread-route.test.ts +14 -2
  102. package/src/__tests__/conversation-usage.test.ts +0 -2
  103. package/src/__tests__/conversation-wipe.test.ts +1 -1
  104. package/src/__tests__/conversation-workspace-cache-state.test.ts +3 -1
  105. package/src/__tests__/conversation-workspace-injection.test.ts +48 -22
  106. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +27 -7
  107. package/src/__tests__/credential-execution-tools.test.ts +1 -2
  108. package/src/__tests__/credential-security-invariants.test.ts +0 -1
  109. package/src/__tests__/cross-provider-web-search.test.ts +6 -2
  110. package/src/__tests__/cu-unified-flow.test.ts +26 -1
  111. package/src/__tests__/db-schedule-syntax-migration.test.ts +11 -0
  112. package/src/__tests__/disk-pressure-guard.test.ts +66 -0
  113. package/src/__tests__/disk-pressure-routes.test.ts +9 -2
  114. package/src/__tests__/dm-persistence.test.ts +7 -2
  115. package/src/__tests__/dynamic-page-surface.test.ts +68 -0
  116. package/src/__tests__/edit-propagation.test.ts +1 -2
  117. package/src/__tests__/empty-response-pipeline.test.ts +127 -5
  118. package/src/__tests__/filing-service.test.ts +2 -2
  119. package/src/__tests__/first-greeting.test.ts +55 -14
  120. package/src/__tests__/gemini-inline-media.test.ts +78 -0
  121. package/src/__tests__/gemini-provider.test.ts +351 -28
  122. package/src/__tests__/guardian-routing-state.test.ts +60 -71
  123. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +9 -7
  124. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  125. package/src/__tests__/heartbeat-service.test.ts +2 -1
  126. package/src/__tests__/history-repair-hook.test.ts +161 -0
  127. package/src/__tests__/history-repair-observability.test.ts +1 -1
  128. package/src/__tests__/history-repair.test.ts +2 -1
  129. package/src/__tests__/host-app-control-proxy.test.ts +2 -0
  130. package/src/__tests__/host-cu-proxy.test.ts +2 -0
  131. package/src/__tests__/host-file-edit-tool.test.ts +4 -2
  132. package/src/__tests__/host-file-proxy.test.ts +31 -0
  133. package/src/__tests__/host-file-read-tool.test.ts +4 -2
  134. package/src/__tests__/host-file-write-tool.test.ts +9 -3
  135. package/src/__tests__/host-proxy-preactivation.test.ts +53 -14
  136. package/src/__tests__/host-shell-tool.test.ts +9 -4
  137. package/src/__tests__/http-user-message-parity.test.ts +2 -2
  138. package/src/__tests__/identity-intro-cache.test.ts +35 -14
  139. package/src/__tests__/inbound-slack-persistence.test.ts +7 -2
  140. package/src/__tests__/injector-background-turn.test.ts +1 -1
  141. package/src/__tests__/injector-chain.test.ts +1 -1
  142. package/src/__tests__/injector-disk-pressure.test.ts +1 -1
  143. package/src/__tests__/injector-document-comments.test.ts +1 -1
  144. package/src/__tests__/injector-pkb-v2-silenced.test.ts +1 -1
  145. package/src/__tests__/injector-v3-suppression.test.ts +220 -0
  146. package/src/__tests__/list-messages-attachments.test.ts +7 -8
  147. package/src/__tests__/list-messages-hidden-metadata.test.ts +17 -15
  148. package/src/__tests__/list-messages-page-latest.test.ts +0 -1
  149. package/src/__tests__/list-messages-tool-merge.test.ts +36 -6
  150. package/src/__tests__/llm-call-pipeline.test.ts +21 -15
  151. package/src/__tests__/llm-request-log-turn-query.test.ts +42 -86
  152. package/src/__tests__/llm-resolver.test.ts +23 -47
  153. package/src/__tests__/llm-usage-store.test.ts +45 -0
  154. package/src/__tests__/log-export-routes.test.ts +59 -0
  155. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -8
  156. package/src/__tests__/mcp-auth-routes.test.ts +15 -10
  157. package/src/__tests__/mcp-health-check.test.ts +18 -13
  158. package/src/__tests__/memory-retrieval-pipeline.test.ts +1 -1
  159. package/src/__tests__/memory-v2-static-injector.test.ts +1 -1
  160. package/src/__tests__/messaging-send-tool.test.ts +8 -4
  161. package/src/__tests__/migration-export-http.test.ts +12 -12
  162. package/src/__tests__/migration-import-commit-http.test.ts +8 -8
  163. package/src/__tests__/migration-import-preflight-http.test.ts +7 -7
  164. package/src/__tests__/migration-validate-http.test.ts +3 -3
  165. package/src/__tests__/native-web-search.test.ts +14 -20
  166. package/src/__tests__/notification-decision-identity.test.ts +9 -18
  167. package/src/__tests__/notification-decision-recipient-context.test.ts +3 -6
  168. package/src/__tests__/oauth-commands-routes.test.ts +1 -1
  169. package/src/__tests__/onboarding-template-contract.test.ts +10 -0
  170. package/src/__tests__/openai-provider.test.ts +66 -70
  171. package/src/__tests__/openai-responses-provider.test.ts +21 -77
  172. package/src/__tests__/outbound-slack-persistence.test.ts +2 -1
  173. package/src/__tests__/overflow-reduce-pipeline.test.ts +2 -4
  174. package/src/__tests__/parallel-tool.benchmark.test.ts +24 -36
  175. package/src/__tests__/persistence-pipeline.test.ts +15 -26
  176. package/src/__tests__/persistence-secret-redaction.test.ts +2 -1
  177. package/src/__tests__/pipeline-runner.test.ts +2 -3
  178. package/src/__tests__/plugin-bootstrap.test.ts +51 -25
  179. package/src/__tests__/plugin-route-contribution.test.ts +6 -16
  180. package/src/__tests__/plugin-skill-contribution.test.ts +7 -17
  181. package/src/__tests__/plugin-tool-contribution.test.ts +10 -26
  182. package/src/__tests__/plugin-types.test.ts +7 -14
  183. package/src/__tests__/prechat-onboarding-contract.test.ts +23 -0
  184. package/src/__tests__/process-message-background-slack.test.ts +17 -16
  185. package/src/__tests__/process-message-display-content.test.ts +30 -42
  186. package/src/__tests__/provider-commit-message-generator.test.ts +19 -14
  187. package/src/__tests__/provider-error-scenarios.test.ts +7 -6
  188. package/src/__tests__/provider-platform-proxy-integration.test.ts +3 -8
  189. package/src/__tests__/provider-send-message-override-profile.test.ts +9 -25
  190. package/src/__tests__/provider-streaming.benchmark.test.ts +12 -22
  191. package/src/__tests__/provider-usage-tracking.test.ts +0 -6
  192. package/src/__tests__/ratelimit.test.ts +9 -4
  193. package/src/__tests__/relay-server.test.ts +20 -13
  194. package/src/__tests__/retry-openrouter-only-normalization.test.ts +5 -8
  195. package/src/__tests__/retry-thinking-tool-choice.test.ts +10 -13
  196. package/src/__tests__/retry-verbosity-normalization.test.ts +5 -8
  197. package/src/__tests__/runtime-events-sse-reconnect.test.ts +353 -0
  198. package/src/__tests__/schedule-routes.test.ts +80 -10
  199. package/src/__tests__/schedule-store.test.ts +67 -0
  200. package/src/__tests__/schedule-tools.test.ts +125 -0
  201. package/src/__tests__/secret-ingress-http.test.ts +2 -2
  202. package/src/__tests__/secret-prompt-log-hygiene.test.ts +11 -7
  203. package/src/__tests__/secret-prompter-channel-fallback.test.ts +11 -9
  204. package/src/__tests__/secret-response-routing.test.ts +13 -11
  205. package/src/__tests__/send-endpoint-busy.test.ts +2 -1
  206. package/src/__tests__/shell-observability.test.ts +249 -0
  207. package/src/__tests__/skill-feature-flags-integration.test.ts +11 -11
  208. package/src/__tests__/skill-feature-flags.test.ts +6 -6
  209. package/src/__tests__/skill-load-feature-flag.test.ts +10 -10
  210. package/src/__tests__/skills-files-catalog-fallback.test.ts +10 -0
  211. package/src/__tests__/skillssh-files.test.ts +1 -0
  212. package/src/__tests__/starter-task-flow.test.ts +6 -6
  213. package/src/__tests__/strip-memory-injections.test.ts +102 -14
  214. package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
  215. package/src/__tests__/suggestion-routes.test.ts +3 -3
  216. package/src/__tests__/sync-message-contract.test.ts +19 -16
  217. package/src/__tests__/system-prompt.test.ts +54 -0
  218. package/src/__tests__/terminal-tools.test.ts +3 -24
  219. package/src/__tests__/thread-backfill.test.ts +4 -9
  220. package/src/__tests__/title-generate-pipeline.test.ts +1 -1
  221. package/src/__tests__/token-estimate-pipeline.test.ts +2 -4
  222. package/src/__tests__/tool-error-pipeline.test.ts +2 -2
  223. package/src/__tests__/tool-execute-pipeline.test.ts +1 -1
  224. package/src/__tests__/tool-preview-lifecycle.test.ts +13 -11
  225. package/src/__tests__/tool-result-truncate-pipeline.test.ts +9 -12
  226. package/src/__tests__/tool-result-truncation.test.ts +3 -1
  227. package/src/__tests__/tools-audio-read.test.ts +113 -0
  228. package/src/__tests__/turn-boundary-resolution.test.ts +44 -84
  229. package/src/__tests__/turn-events-store.test.ts +11 -7
  230. package/src/__tests__/voice-scoped-grant-consumer.test.ts +8 -6
  231. package/src/__tests__/voice-session-bridge.test.ts +13 -7
  232. package/src/acp/__tests__/prepare-agent-env.test.ts +143 -31
  233. package/src/acp/prepare-agent-env.ts +52 -11
  234. package/src/agent/compaction-circuit.ts +140 -0
  235. package/src/agent/loop.ts +409 -85
  236. package/src/api/README.md +19 -17
  237. package/src/api/constants/tool-execution.ts +21 -0
  238. package/src/api/events/assistant-activity-state.ts +75 -0
  239. package/src/api/events/assistant-outbound-attachment.ts +25 -27
  240. package/src/api/events/assistant-text-delta.ts +6 -8
  241. package/src/api/events/assistant-turn-start.ts +5 -7
  242. package/src/api/events/avatar-updated.ts +24 -0
  243. package/src/api/events/compaction-circuit-closed.ts +26 -0
  244. package/src/api/events/compaction-circuit-open.ts +28 -0
  245. package/src/api/events/confirmation-request.ts +114 -0
  246. package/src/api/events/contact-request.ts +33 -0
  247. package/src/api/events/conversation-error.ts +77 -0
  248. package/src/api/events/conversation-list-invalidated.ts +38 -0
  249. package/src/api/events/conversation-title-updated.ts +24 -0
  250. package/src/api/events/disk-pressure-status-changed.ts +61 -0
  251. package/src/api/events/document-comment-created.ts +24 -28
  252. package/src/api/events/document-comment-deleted.ts +6 -8
  253. package/src/api/events/document-comment-reopened.ts +6 -8
  254. package/src/api/events/document-comment-resolved.ts +8 -10
  255. package/src/api/events/document-editor-update.ts +27 -0
  256. package/src/api/events/error.ts +32 -0
  257. package/src/api/events/generation-cancelled.ts +4 -6
  258. package/src/api/events/generation-handoff.ts +13 -15
  259. package/src/api/events/home-feed-updated.ts +26 -0
  260. package/src/api/events/identity-changed.ts +32 -0
  261. package/src/api/events/interaction-resolved.ts +50 -0
  262. package/src/api/events/message-complete.ts +10 -12
  263. package/src/api/events/message-dequeued.ts +21 -0
  264. package/src/api/events/message-queued-deleted.ts +23 -0
  265. package/src/api/events/message-queued.ts +22 -0
  266. package/src/api/events/message-request-complete.ts +29 -0
  267. package/src/api/events/navigate-settings.ts +20 -0
  268. package/src/api/events/notification-intent.ts +33 -0
  269. package/src/api/events/open-url.ts +6 -8
  270. package/src/api/events/question-request.ts +67 -0
  271. package/src/api/events/relationship-state-updated.ts +4 -6
  272. package/src/api/events/secret-request.ts +42 -0
  273. package/src/api/events/subagent-event.ts +79 -0
  274. package/src/api/events/subagent-spawned.ts +40 -0
  275. package/src/api/events/subagent-status-changed.ts +65 -0
  276. package/src/api/events/sync-changed.ts +29 -0
  277. package/src/api/events/tool-result.ts +129 -0
  278. package/src/api/events/tool-use-start.ts +8 -10
  279. package/src/api/events/turn-profile-auto-routed.ts +28 -0
  280. package/src/api/events/ui-surface-complete.ts +30 -0
  281. package/src/api/events/ui-surface-dismiss.ts +22 -0
  282. package/src/api/events/ui-surface-show.ts +67 -0
  283. package/src/api/events/ui-surface-update.ts +26 -0
  284. package/src/api/events/usage-update.ts +34 -0
  285. package/src/api/events/user-message-echo.ts +35 -0
  286. package/src/api/index.ts +354 -0
  287. package/src/api/requests/dictation.ts +45 -0
  288. package/src/api/responses/disk-pressure-status.ts +26 -0
  289. package/src/api/responses/home.ts +217 -0
  290. package/src/api/responses/llm-context-response.ts +2 -0
  291. package/src/api/responses/memory-v3-selection-log.ts +50 -0
  292. package/src/api/responses/subagent-detail.ts +48 -0
  293. package/src/approvals/guardian-decision-primitive.ts +7 -15
  294. package/src/approvals/guardian-request-resolvers.ts +6 -9
  295. package/src/avatar/__tests__/avatar-manifest.test.ts +236 -0
  296. package/src/avatar/__tests__/avatar-store.test.ts +193 -0
  297. package/src/avatar/avatar-manifest.ts +195 -0
  298. package/src/avatar/avatar-store.ts +113 -0
  299. package/src/avatar/traits-png-sync.ts +8 -2
  300. package/src/background-wake/next-wake.test.ts +31 -1
  301. package/src/background-wake/next-wake.ts +4 -1
  302. package/src/calls/call-conversation-messages.ts +6 -4
  303. package/src/calls/guardian-action-sweep.ts +6 -4
  304. package/src/calls/relay-server.ts +12 -8
  305. package/src/calls/voice-session-bridge.ts +13 -27
  306. package/src/cli/commands/__tests__/memory-v3.test.ts +245 -0
  307. package/src/cli/commands/avatar.ts +17 -11
  308. package/src/cli/commands/conversations.ts +15 -1
  309. package/src/cli/commands/db/__tests__/repair.test.ts +540 -0
  310. package/src/cli/commands/db/__tests__/status.test.ts +253 -0
  311. package/src/cli/commands/db/format.ts +48 -0
  312. package/src/cli/commands/db/index.ts +29 -0
  313. package/src/cli/commands/db/repair-step-conversation-backfill.ts +345 -0
  314. package/src/cli/commands/db/repair-step-integrity.ts +146 -0
  315. package/src/cli/commands/db/repair-steps.ts +164 -0
  316. package/src/cli/commands/db/repair.ts +141 -0
  317. package/src/cli/commands/db/status.ts +366 -0
  318. package/src/cli/commands/memory-v3.ts +159 -445
  319. package/src/cli/lib/cli-colors.ts +24 -6
  320. package/src/cli/program.ts +4 -5
  321. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  322. package/src/config/assistant-feature-flags.ts +2 -2
  323. package/src/config/bundled-skills/app-builder/SKILL.md +14 -3
  324. package/src/config/bundled-skills/media-processing/services/reduce.ts +6 -9
  325. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +7 -2
  326. package/src/config/bundled-skills/schedule/SKILL.md +1 -1
  327. package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
  328. package/src/config/call-site-defaults.ts +2 -7
  329. package/src/config/feature-flag-registry.json +25 -9
  330. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -226
  331. package/src/config/schemas/call-site-catalog.ts +8 -15
  332. package/src/config/schemas/llm.ts +2 -3
  333. package/src/config/schemas/memory-lifecycle.ts +24 -0
  334. package/src/config/schemas/memory-v2.ts +0 -253
  335. package/src/config/schemas/memory-v3.ts +39 -0
  336. package/src/config/schemas/memory.ts +6 -1
  337. package/src/config/schemas/timeouts.ts +3 -1
  338. package/src/context/compactor.ts +54 -31
  339. package/src/context/token-estimator.ts +19 -0
  340. package/src/context/tool-result-truncation.ts +1 -43
  341. package/src/context/window-manager.ts +138 -20
  342. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +2 -2
  343. package/src/daemon/__tests__/web-search-status-text.test.ts +10 -6
  344. package/src/daemon/approval-generators.ts +4 -4
  345. package/src/daemon/config-watcher.ts +7 -1
  346. package/src/daemon/conversation-agent-loop-handlers.ts +225 -88
  347. package/src/daemon/conversation-agent-loop.ts +284 -584
  348. package/src/daemon/conversation-error.ts +7 -7
  349. package/src/daemon/conversation-history.ts +22 -6
  350. package/src/daemon/conversation-launch.ts +4 -8
  351. package/src/daemon/conversation-lifecycle.ts +10 -38
  352. package/src/daemon/conversation-messaging.ts +1 -3
  353. package/src/daemon/conversation-notifiers.ts +7 -5
  354. package/src/daemon/conversation-process.ts +100 -79
  355. package/src/daemon/conversation-runtime-assembly.ts +47 -21
  356. package/src/daemon/conversation-store.ts +6 -5
  357. package/src/daemon/conversation-surfaces.ts +55 -69
  358. package/src/daemon/conversation-tool-setup.ts +3 -0
  359. package/src/daemon/conversation.ts +91 -126
  360. package/src/daemon/daemon-skill-host.ts +2 -6
  361. package/src/daemon/disk-pressure-guard.ts +35 -29
  362. package/src/daemon/external-plugins-bootstrap.ts +46 -24
  363. package/src/daemon/first-greeting.ts +26 -4
  364. package/src/daemon/guardian-action-generators.ts +2 -2
  365. package/src/daemon/handlers/conversations.ts +6 -22
  366. package/src/daemon/handlers/shared.ts +4 -0
  367. package/src/daemon/handlers/skills.ts +15 -14
  368. package/src/daemon/host-app-control-proxy.ts +54 -1
  369. package/src/daemon/host-cu-proxy.ts +46 -22
  370. package/src/daemon/host-file-proxy.ts +25 -1
  371. package/src/daemon/host-proxy-preactivation.ts +25 -6
  372. package/src/daemon/lifecycle.ts +28 -55
  373. package/src/daemon/message-protocol.ts +2 -3
  374. package/src/daemon/message-provenance.ts +49 -0
  375. package/src/daemon/message-types/contacts.ts +3 -20
  376. package/src/daemon/message-types/conversations.ts +13 -111
  377. package/src/daemon/message-types/documents.ts +3 -9
  378. package/src/daemon/message-types/home.ts +4 -17
  379. package/src/daemon/message-types/integrations.ts +2 -6
  380. package/src/daemon/message-types/messages.ts +28 -343
  381. package/src/daemon/message-types/notifications.ts +2 -32
  382. package/src/daemon/message-types/settings.ts +3 -8
  383. package/src/daemon/message-types/skills.ts +2 -0
  384. package/src/daemon/message-types/surfaces.ts +2 -0
  385. package/src/daemon/message-types/sync.ts +12 -25
  386. package/src/daemon/message-types/workspace.ts +3 -11
  387. package/src/daemon/process-message.ts +49 -46
  388. package/src/daemon/server.ts +12 -0
  389. package/src/daemon/tool-side-effects.ts +10 -7
  390. package/src/daemon/trust-context.ts +13 -0
  391. package/src/daemon/wake-target-adapter.ts +11 -1
  392. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -1
  393. package/src/heartbeat/heartbeat-run-store.ts +31 -0
  394. package/src/heartbeat/heartbeat-service.ts +16 -0
  395. package/src/home/feature-gate.ts +22 -0
  396. package/src/home/feed-types.ts +36 -221
  397. package/src/ipc/__tests__/email-ipc.test.ts +0 -9
  398. package/src/ipc/routes/__tests__/route-adapter.test.ts +244 -0
  399. package/src/ipc/routes/route-adapter.ts +45 -6
  400. package/src/ipc/skill-routes/__tests__/memory.test.ts +18 -9
  401. package/src/ipc/skill-routes/__tests__/providers.test.ts +10 -10
  402. package/src/ipc/skill-routes/__tests__/registries.test.ts +28 -18
  403. package/src/ipc/skill-routes/memory.ts +26 -13
  404. package/src/ipc/skill-routes/providers.ts +5 -6
  405. package/src/ipc/skill-routes/registries.ts +13 -61
  406. package/src/live-voice/__tests__/live-voice-archive.test.ts +24 -11
  407. package/src/memory/__tests__/conversation-queries.test.ts +192 -8
  408. package/src/memory/__tests__/db-maintenance.test.ts +128 -0
  409. package/src/memory/__tests__/jobs-store-job-classes.test.ts +5 -4
  410. package/src/memory/__tests__/memory-retrospective-job.test.ts +10 -6
  411. package/src/memory/__tests__/memory-v3-selections-migration.test.ts +103 -0
  412. package/src/memory/context-search/agent-runner.ts +2 -4
  413. package/src/memory/conversation-crud.ts +39 -8
  414. package/src/memory/conversation-queries.ts +78 -22
  415. package/src/memory/db-init.ts +8 -0
  416. package/src/memory/db-maintenance.ts +18 -2
  417. package/src/memory/graph/consolidation.ts +8 -11
  418. package/src/memory/graph/conversation-graph-memory.ts +41 -8
  419. package/src/memory/graph/extraction.ts +6 -9
  420. package/src/memory/graph/narrative.ts +2 -2
  421. package/src/memory/graph/pattern-scan.ts +2 -2
  422. package/src/memory/graph/retriever.ts +20 -26
  423. package/src/memory/graph/tools.ts +4 -4
  424. package/src/memory/job-handlers/conversation-starters.ts +32 -32
  425. package/src/memory/job-handlers/summarization.ts +1 -2
  426. package/src/memory/jobs-store.ts +3 -1
  427. package/src/memory/jobs-worker.ts +51 -39
  428. package/src/memory/llm-request-log-source-clickhouse.ts +5 -31
  429. package/src/memory/llm-request-log-source-local.ts +0 -11
  430. package/src/memory/llm-request-log-source.ts +9 -25
  431. package/src/memory/llm-request-log-store.ts +0 -41
  432. package/src/memory/llm-usage-store.ts +10 -0
  433. package/src/memory/memory-marker.ts +17 -0
  434. package/src/memory/memory-retrospective-job.ts +6 -2
  435. package/src/memory/memory-v2-activation-log-store.ts +1 -83
  436. package/src/memory/migrations/267-llm-usage-events-add-assistant-version.ts +46 -0
  437. package/src/memory/migrations/268-add-memory-v3-selections.ts +28 -0
  438. package/src/memory/migrations/269-schedule-script-timeout.ts +11 -0
  439. package/src/memory/migrations/270-messages-role-created-at-index.ts +18 -0
  440. package/src/memory/migrations/__tests__/267-llm-usage-events-add-assistant-version.test.ts +117 -0
  441. package/src/memory/migrations/index.ts +4 -0
  442. package/src/memory/schema/infrastructure.ts +11 -0
  443. package/src/memory/v2/__tests__/consolidation-job.test.ts +124 -0
  444. package/src/memory/v2/__tests__/migration.test.ts +11 -3
  445. package/src/memory/v2/__tests__/page-index.test.ts +37 -1
  446. package/src/memory/v2/__tests__/router.test.ts +14 -4
  447. package/src/memory/v2/__tests__/sweep-job.test.ts +6 -5
  448. package/src/memory/v2/backfill-jobs.ts +6 -0
  449. package/src/memory/v2/consolidation-job.ts +89 -9
  450. package/src/memory/v2/migration.ts +5 -3
  451. package/src/memory/v2/page-index.ts +11 -0
  452. package/src/memory/v2/router.ts +8 -11
  453. package/src/memory/v2/sweep-job.ts +8 -11
  454. package/src/memory/v2/types.ts +1 -0
  455. package/src/memory/v3/__tests__/assign.test.ts +242 -0
  456. package/src/memory/v3/__tests__/capabilities.test.ts +118 -0
  457. package/src/memory/v3/__tests__/core.test.ts +39 -0
  458. package/src/memory/v3/__tests__/fixtures/eval-turns.json +36 -0
  459. package/src/memory/v3/__tests__/fixtures/live-turns.json +37 -0
  460. package/src/memory/v3/__tests__/health.test.ts +203 -0
  461. package/src/memory/v3/__tests__/live-integration.test.ts +330 -0
  462. package/src/memory/v3/__tests__/maintain-job.test.ts +288 -0
  463. package/src/memory/v3/__tests__/needle.test.ts +107 -0
  464. package/src/memory/v3/__tests__/orchestrate.test.ts +400 -0
  465. package/src/memory/v3/__tests__/reconcile.test.ts +274 -0
  466. package/src/memory/v3/__tests__/render-injection.test.ts +61 -0
  467. package/src/memory/v3/__tests__/router.test.ts +260 -0
  468. package/src/memory/v3/__tests__/selection-log-store.test.ts +179 -0
  469. package/src/memory/v3/__tests__/selector.test.ts +404 -0
  470. package/src/memory/v3/__tests__/shadow-plugin.test.ts +414 -0
  471. package/src/memory/v3/__tests__/snapshot.test.ts +168 -0
  472. package/src/memory/v3/__tests__/tree.test.ts +192 -0
  473. package/src/memory/v3/__tests__/types.test.ts +54 -0
  474. package/src/memory/v3/__tests__/working-set-eviction.test.ts +106 -0
  475. package/src/memory/v3/__tests__/working-set-skeleton.test.ts +44 -0
  476. package/src/memory/v3/assign.ts +268 -0
  477. package/src/memory/v3/capabilities.ts +124 -0
  478. package/src/memory/v3/core.ts +26 -0
  479. package/src/memory/v3/data/README.md +84 -0
  480. package/src/memory/v3/data/assignments.json +5 -0
  481. package/src/memory/v3/data/core.json +1 -0
  482. package/src/memory/v3/data/leaves/domain-a/topic-x.md +9 -0
  483. package/src/memory/v3/data/leaves/domain-a/topic-y.md +9 -0
  484. package/src/memory/v3/data/leaves/domain-b/topic-z.md +9 -0
  485. package/src/memory/v3/health.ts +0 -0
  486. package/src/memory/v3/maintain-job.ts +314 -0
  487. package/src/memory/v3/needle.ts +115 -0
  488. package/src/memory/v3/orchestrate.ts +114 -0
  489. package/src/memory/v3/page-content.ts +34 -0
  490. package/src/memory/v3/provider-blocks.ts +16 -0
  491. package/src/memory/v3/reconcile.ts +523 -0
  492. package/src/memory/v3/render-injection.ts +32 -0
  493. package/src/memory/v3/router.ts +184 -0
  494. package/src/memory/v3/selection-log-store.ts +84 -0
  495. package/src/memory/v3/selector.ts +211 -0
  496. package/src/memory/v3/shadow-plugin.ts +379 -0
  497. package/src/memory/v3/snapshot.ts +209 -0
  498. package/src/memory/v3/tree.ts +174 -0
  499. package/src/memory/v3/types.ts +46 -60
  500. package/src/memory/v3/working-set.ts +88 -0
  501. package/src/messaging/providers/slack/render-transcript.test.ts +1 -1
  502. package/src/messaging/providers/slack/render-transcript.ts +2 -2
  503. package/src/messaging/style-analyzer.ts +8 -11
  504. package/src/notifications/conversation-pairing.ts +8 -6
  505. package/src/notifications/decision-engine.ts +10 -13
  506. package/src/notifications/preference-extractor.ts +11 -14
  507. package/src/permissions/prompter.ts +42 -36
  508. package/src/permissions/question-prompter.test.ts +35 -26
  509. package/src/permissions/question-prompter.ts +6 -10
  510. package/src/plugin-api/index.ts +2 -0
  511. package/src/plugin-api/types.ts +25 -3
  512. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +93 -0
  513. package/src/plugins/defaults/circuit-breaker/package.json +15 -0
  514. package/src/plugins/defaults/circuit-breaker/register.ts +39 -0
  515. package/src/plugins/defaults/compaction/middlewares/compaction.ts +25 -0
  516. package/src/plugins/defaults/compaction/package.json +15 -0
  517. package/src/plugins/defaults/compaction/register.ts +35 -0
  518. package/src/plugins/defaults/compaction/terminal.ts +73 -0
  519. package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +22 -0
  520. package/src/plugins/defaults/empty-response/package.json +15 -0
  521. package/src/plugins/defaults/empty-response/register.ts +28 -0
  522. package/src/plugins/defaults/empty-response/terminal.ts +106 -0
  523. package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +35 -0
  524. package/src/plugins/defaults/history-repair/package.json +15 -0
  525. package/src/plugins/defaults/history-repair/register.ts +24 -0
  526. package/src/{daemon/history-repair.ts → plugins/defaults/history-repair/terminal.ts} +48 -35
  527. package/src/plugins/defaults/index.ts +29 -40
  528. package/src/plugins/defaults/injectors/package.json +15 -0
  529. package/src/plugins/defaults/{injectors.ts → injectors/register.ts} +14 -38
  530. package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +17 -0
  531. package/src/plugins/defaults/llm-call/package.json +15 -0
  532. package/src/plugins/defaults/{llm-call.ts → llm-call/register.ts} +6 -38
  533. package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +17 -0
  534. package/src/plugins/defaults/memory-retrieval/package.json +15 -0
  535. package/src/plugins/defaults/{memory-retrieval.ts → memory-retrieval/register.ts} +10 -48
  536. package/src/plugins/defaults/{overflow-reduce.ts → overflow-reduce/middlewares/overflowReduce.ts} +18 -77
  537. package/src/plugins/defaults/overflow-reduce/package.json +15 -0
  538. package/src/plugins/defaults/overflow-reduce/register.ts +42 -0
  539. package/src/plugins/defaults/persistence/middlewares/persistence.ts +19 -0
  540. package/src/plugins/defaults/persistence/package.json +15 -0
  541. package/src/plugins/defaults/persistence/register.ts +38 -0
  542. package/src/plugins/defaults/persistence/terminal.ts +83 -0
  543. package/src/plugins/defaults/title-generate/package.json +15 -0
  544. package/src/plugins/defaults/title-generate/register.ts +35 -0
  545. package/src/plugins/defaults/title-generate/terminal.ts +31 -0
  546. package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +23 -0
  547. package/src/plugins/defaults/token-estimate/package.json +15 -0
  548. package/src/plugins/defaults/token-estimate/register.ts +34 -0
  549. package/src/plugins/defaults/token-estimate/terminal.ts +40 -0
  550. package/src/plugins/defaults/tool-error/middlewares/toolError.ts +21 -0
  551. package/src/plugins/defaults/tool-error/package.json +15 -0
  552. package/src/plugins/defaults/tool-error/register.ts +35 -0
  553. package/src/plugins/defaults/tool-error/terminal.ts +47 -0
  554. package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +23 -0
  555. package/src/plugins/defaults/tool-execute/package.json +15 -0
  556. package/src/plugins/defaults/{tool-execute.ts → tool-execute/register.ts} +8 -46
  557. package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +23 -0
  558. package/src/plugins/defaults/tool-result-truncate/package.json +15 -0
  559. package/src/plugins/defaults/tool-result-truncate/register.ts +35 -0
  560. package/src/plugins/defaults/tool-result-truncate/terminal.ts +113 -0
  561. package/src/plugins/defaults/tool-result-truncate/types.ts +22 -0
  562. package/src/plugins/external-plugin-loader.ts +2 -2
  563. package/src/plugins/pipeline.ts +0 -12
  564. package/src/plugins/types.ts +51 -90
  565. package/src/plugins/user-loader.ts +4 -3
  566. package/src/proactive-artifact/aux-message-injector.ts +0 -1
  567. package/src/proactive-artifact/job.test.ts +20 -8
  568. package/src/proactive-artifact/job.ts +3 -1
  569. package/src/prompts/sections.ts +20 -7
  570. package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +2 -2
  571. package/src/prompts/templates/BOOTSTRAP.md +5 -1
  572. package/src/prompts/templates/system-sections.ts +6 -0
  573. package/src/providers/__tests__/retry-callsite.test.ts +25 -25
  574. package/src/providers/__tests__/satellite-connection-routing.test.ts +7 -21
  575. package/src/providers/anthropic/client.ts +24 -5
  576. package/src/providers/call-site-routing.ts +1 -9
  577. package/src/providers/gemini/client.ts +152 -34
  578. package/src/providers/gemini/inline-media.ts +74 -0
  579. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +0 -2
  580. package/src/providers/openai/chat-completions-provider.ts +1 -4
  581. package/src/providers/openai/responses-provider.ts +1 -4
  582. package/src/providers/openrouter/client.ts +1 -6
  583. package/src/providers/provider-send-message.ts +6 -6
  584. package/src/providers/ratelimit.ts +1 -9
  585. package/src/providers/retry.ts +0 -5
  586. package/src/providers/types.ts +11 -2
  587. package/src/providers/usage-tracking.ts +1 -9
  588. package/src/runtime/__tests__/agent-wake.test.ts +131 -26
  589. package/src/runtime/__tests__/background-job-runner.test.ts +1 -3
  590. package/src/runtime/agent-wake.ts +93 -18
  591. package/src/runtime/assistant-event-hub.ts +2 -2
  592. package/src/runtime/auth/__tests__/guard-tests.test.ts +75 -109
  593. package/src/runtime/auth/__tests__/route-policy.test.ts +153 -170
  594. package/src/runtime/auth/route-policy.ts +42 -1079
  595. package/src/runtime/background-job-runner.ts +1 -4
  596. package/src/runtime/btw-sidechain.ts +3 -1
  597. package/src/runtime/channel-approvals.ts +3 -14
  598. package/src/runtime/channel-invite-transport.ts +5 -6
  599. package/src/runtime/channel-readiness-service.ts +2 -5
  600. package/src/runtime/channel-retry-sweep.ts +12 -16
  601. package/src/runtime/conversation-stream-state.ts +294 -0
  602. package/src/runtime/http-router.ts +19 -22
  603. package/src/runtime/http-types.ts +12 -6
  604. package/src/runtime/invite-instruction-generator.ts +3 -3
  605. package/src/runtime/pending-interactions.ts +2 -2
  606. package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +565 -0
  607. package/src/runtime/routes/__tests__/content-source-routes.test.ts +4 -4
  608. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +62 -32
  609. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +237 -0
  610. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -22
  611. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +7 -2
  612. package/src/runtime/routes/__tests__/sanity-routes.test.ts +6 -6
  613. package/src/runtime/routes/__tests__/stt-routes.test.ts +3 -3
  614. package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +5 -2
  615. package/src/runtime/routes/__tests__/tts-routes.test.ts +3 -3
  616. package/src/runtime/routes/acp-routes.test.ts +97 -75
  617. package/src/runtime/routes/acp-routes.ts +29 -6
  618. package/src/runtime/routes/app-management-routes.ts +97 -24
  619. package/src/runtime/routes/app-routes.ts +25 -5
  620. package/src/runtime/routes/approval-routes.ts +16 -4
  621. package/src/runtime/routes/attachment-routes.ts +25 -1
  622. package/src/runtime/routes/audio-routes.ts +1 -0
  623. package/src/runtime/routes/audit-routes.ts +5 -0
  624. package/src/runtime/routes/auth-routes.ts +5 -0
  625. package/src/runtime/routes/avatar-routes.ts +238 -59
  626. package/src/runtime/routes/background-tool-routes.ts +9 -0
  627. package/src/runtime/routes/background-wake-routes.ts +13 -3
  628. package/src/runtime/routes/backup-routes.ts +45 -0
  629. package/src/runtime/routes/bookmark-routes.ts +13 -0
  630. package/src/runtime/routes/brain-graph-routes.ts +9 -0
  631. package/src/runtime/routes/browser-routes.ts +5 -0
  632. package/src/runtime/routes/browser-tabs-routes.ts +5 -0
  633. package/src/runtime/routes/btw-routes.ts +5 -1
  634. package/src/runtime/routes/cache-routes.ts +13 -0
  635. package/src/runtime/routes/call-routes.ts +21 -10
  636. package/src/runtime/routes/channel-availability-routes.ts +5 -1
  637. package/src/runtime/routes/channel-readiness-routes.ts +37 -4
  638. package/src/runtime/routes/channel-route-definitions.ts +21 -0
  639. package/src/runtime/routes/channel-verification-routes.ts +21 -0
  640. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +9 -2
  641. package/src/runtime/routes/client-routes.ts +9 -0
  642. package/src/runtime/routes/consolidation-routes.ts +13 -5
  643. package/src/runtime/routes/contact-prompt-routes.ts +9 -0
  644. package/src/runtime/routes/contact-routes.ts +90 -23
  645. package/src/runtime/routes/content-source-routes.ts +5 -1
  646. package/src/runtime/routes/conversation-analysis-routes.ts +5 -1
  647. package/src/runtime/routes/conversation-attention-routes.ts +5 -0
  648. package/src/runtime/routes/conversation-cli-routes.ts +54 -7
  649. package/src/runtime/routes/conversation-compaction-routes.ts +54 -25
  650. package/src/runtime/routes/conversation-list-routes.ts +81 -12
  651. package/src/runtime/routes/conversation-management-routes.ts +57 -14
  652. package/src/runtime/routes/conversation-query-routes.ts +88 -41
  653. package/src/runtime/routes/conversation-routes.ts +74 -19
  654. package/src/runtime/routes/conversation-starter-routes.ts +22 -13
  655. package/src/runtime/routes/conversations-import-routes.ts +6 -1
  656. package/src/runtime/routes/credential-prompt-routes.ts +5 -0
  657. package/src/runtime/routes/credential-routes.ts +25 -6
  658. package/src/runtime/routes/debug-bash-routes.ts +5 -0
  659. package/src/runtime/routes/debug-routes.ts +11 -2
  660. package/src/runtime/routes/defer-routes.ts +13 -0
  661. package/src/runtime/routes/diagnostics-routes.ts +37 -46
  662. package/src/runtime/routes/disk-pressure-routes.ts +17 -31
  663. package/src/runtime/routes/document-comments-routes.ts +46 -27
  664. package/src/runtime/routes/documents-routes.ts +21 -10
  665. package/src/runtime/routes/domain-routes.ts +61 -28
  666. package/src/runtime/routes/email-routes.ts +33 -0
  667. package/src/runtime/routes/events-routes.ts +114 -9
  668. package/src/runtime/routes/filing-routes.ts +9 -4
  669. package/src/runtime/routes/gateway-log-routes.ts +5 -0
  670. package/src/runtime/routes/global-search-routes.ts +53 -50
  671. package/src/runtime/routes/group-routes.ts +21 -5
  672. package/src/runtime/routes/guardian-action-routes.ts +9 -0
  673. package/src/runtime/routes/guardian-approval-interception.ts +0 -31
  674. package/src/runtime/routes/heartbeat-routes.ts +25 -9
  675. package/src/runtime/routes/home-feed-routes.ts +23 -19
  676. package/src/runtime/routes/home-state-routes.ts +8 -40
  677. package/src/runtime/routes/host-app-control-routes.ts +5 -0
  678. package/src/runtime/routes/host-bash-routes.ts +5 -0
  679. package/src/runtime/routes/host-browser-routes.ts +13 -0
  680. package/src/runtime/routes/host-cu-routes.ts +5 -0
  681. package/src/runtime/routes/host-file-routes.ts +26 -6
  682. package/src/runtime/routes/host-transfer-routes.ts +13 -2
  683. package/src/runtime/routes/http-adapter.ts +1 -2
  684. package/src/runtime/routes/identity-intro-cache.ts +17 -6
  685. package/src/runtime/routes/identity-routes.ts +12 -2
  686. package/src/runtime/routes/image-generation-routes.ts +5 -0
  687. package/src/runtime/routes/inbound-message-handler.ts +15 -11
  688. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -12
  689. package/src/runtime/routes/inbound-stages/background-dispatch.ts +15 -19
  690. package/src/runtime/routes/inference-profile-session-routes.ts +13 -3
  691. package/src/runtime/routes/inference-provider-connection-routes.ts +21 -5
  692. package/src/runtime/routes/inference-send-routes.ts +11 -11
  693. package/src/runtime/routes/integrations/a2a.ts +30 -7
  694. package/src/runtime/routes/integrations/slack/channel.ts +19 -3
  695. package/src/runtime/routes/integrations/slack/share.ts +9 -2
  696. package/src/runtime/routes/integrations/telegram.ts +28 -9
  697. package/src/runtime/routes/integrations/twilio.ts +35 -7
  698. package/src/runtime/routes/integrations/vercel.ts +3 -3
  699. package/src/runtime/routes/internal-oauth-routes.ts +5 -0
  700. package/src/runtime/routes/internal-twilio-routes.ts +13 -0
  701. package/src/runtime/routes/llm-call-sites-routes.ts +39 -4
  702. package/src/runtime/routes/log-export-routes.ts +28 -10
  703. package/src/runtime/routes/mcp-auth-routes.ts +25 -0
  704. package/src/runtime/routes/memory-item-routes.ts +21 -10
  705. package/src/runtime/routes/memory-v2-routes.ts +90 -36
  706. package/src/runtime/routes/memory-v3-routes.ts +273 -407
  707. package/src/runtime/routes/migration-rollback-routes.ts +5 -1
  708. package/src/runtime/routes/migration-routes.ts +29 -0
  709. package/src/runtime/routes/notification-routes.ts +17 -1
  710. package/src/runtime/routes/oauth-apps.ts +33 -11
  711. package/src/runtime/routes/oauth-commands-routes.ts +37 -14
  712. package/src/runtime/routes/oauth-connect-routes.ts +9 -0
  713. package/src/runtime/routes/oauth-lifecycle-routes.ts +5 -1
  714. package/src/runtime/routes/oauth-providers.ts +35 -10
  715. package/src/runtime/routes/platform-routes.ts +21 -0
  716. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +3 -2
  717. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +37 -16
  718. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +7 -3
  719. package/src/runtime/routes/playground/__tests__/state.test.ts +10 -3
  720. package/src/runtime/routes/playground/force-compact.ts +1 -1
  721. package/src/runtime/routes/playground/helpers.ts +0 -1
  722. package/src/runtime/routes/playground/inject-failures.ts +13 -8
  723. package/src/runtime/routes/playground/reset-circuit.ts +14 -9
  724. package/src/runtime/routes/playground/seed-conversation.ts +1 -1
  725. package/src/runtime/routes/playground/seeded-conversations.ts +3 -3
  726. package/src/runtime/routes/playground/state.ts +4 -3
  727. package/src/runtime/routes/plugins-routes.ts +22 -19
  728. package/src/runtime/routes/profiler-routes.ts +17 -4
  729. package/src/runtime/routes/ps-routes.ts +5 -0
  730. package/src/runtime/routes/publish-routes.ts +13 -3
  731. package/src/runtime/routes/question-routes.ts +5 -0
  732. package/src/runtime/routes/recording-routes.ts +25 -12
  733. package/src/runtime/routes/rename-conversation-routes.ts +5 -0
  734. package/src/runtime/routes/sanity-routes.ts +9 -2
  735. package/src/runtime/routes/schedule-routes.ts +137 -47
  736. package/src/runtime/routes/secret-routes.ts +17 -4
  737. package/src/runtime/routes/sequence-routes.ts +33 -0
  738. package/src/runtime/routes/settings-routes.ts +65 -19
  739. package/src/runtime/routes/skills-routes.ts +133 -69
  740. package/src/runtime/routes/slack-channel-routes.ts +5 -0
  741. package/src/runtime/routes/stt-routes.ts +13 -6
  742. package/src/runtime/routes/subagents-routes.ts +24 -18
  743. package/src/runtime/routes/suggest-trust-rule-routes.ts +7 -2
  744. package/src/runtime/routes/surface-action-routes.ts +9 -0
  745. package/src/runtime/routes/surface-content-routes.ts +10 -2
  746. package/src/runtime/routes/task-routes.ts +37 -0
  747. package/src/runtime/routes/telemetry-routes.ts +9 -0
  748. package/src/runtime/routes/trace-event-routes.ts +42 -1
  749. package/src/runtime/routes/trust-rules-routes.ts +5 -0
  750. package/src/runtime/routes/tts-routes.ts +13 -6
  751. package/src/runtime/routes/types.ts +17 -8
  752. package/src/runtime/routes/ui-request-routes.ts +5 -0
  753. package/src/runtime/routes/upgrade-broadcast-routes.ts +5 -0
  754. package/src/runtime/routes/usage-routes.ts +71 -3
  755. package/src/runtime/routes/user-routes-cli.ts +9 -0
  756. package/src/runtime/routes/user-routes.ts +5 -1
  757. package/src/runtime/routes/wake-conversation-routes.ts +5 -0
  758. package/src/runtime/routes/watcher-routes.ts +21 -0
  759. package/src/runtime/routes/webhook-routes.ts +9 -0
  760. package/src/runtime/routes/wipe-conversation-routes.ts +5 -0
  761. package/src/runtime/routes/work-items-routes.ts +47 -19
  762. package/src/runtime/routes/workspace-commit-routes.ts +5 -0
  763. package/src/runtime/routes/workspace-routes.test.ts +42 -0
  764. package/src/runtime/routes/workspace-routes.ts +120 -9
  765. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -4
  766. package/src/runtime/services/analyze-conversation.ts +3 -6
  767. package/src/runtime/services/conversation-serializer.ts +24 -2
  768. package/src/runtime/sync/resource-sync-events.ts +16 -2
  769. package/src/runtime/sync/sync-publisher.ts +2 -2
  770. package/src/schedule/run-script.ts +28 -3
  771. package/src/schedule/schedule-store.ts +8 -0
  772. package/src/schedule/scheduler.ts +3 -1
  773. package/src/signals/user-message.ts +5 -8
  774. package/src/skills/catalog-files.ts +4 -1
  775. package/src/skills/clawhub-files.ts +2 -0
  776. package/src/skills/skillssh-files.ts +2 -0
  777. package/src/subagent/manager.ts +3 -6
  778. package/src/telemetry/types.ts +26 -0
  779. package/src/telemetry/usage-telemetry-reporter.test.ts +138 -1
  780. package/src/telemetry/usage-telemetry-reporter.ts +31 -0
  781. package/src/tools/acp/spawn.test.ts +88 -38
  782. package/src/tools/apps/definitions.ts +8 -4
  783. package/src/tools/ask-question/ask-question-tool.test.ts +120 -105
  784. package/src/tools/ask-question/ask-question-tool.ts +85 -90
  785. package/src/tools/computer-use/definitions.ts +28 -24
  786. package/src/tools/credential-execution/make-authenticated-request.ts +56 -51
  787. package/src/tools/credential-execution/manage-secure-command-tool.ts +2 -2
  788. package/src/tools/credential-execution/run-authenticated-command.ts +82 -77
  789. package/src/tools/credentials/vault.ts +112 -111
  790. package/src/tools/execution-target.ts +1 -1
  791. package/src/tools/execution-timeout.ts +3 -4
  792. package/src/tools/filesystem/edit.ts +45 -42
  793. package/src/tools/filesystem/list.ts +33 -30
  794. package/src/tools/filesystem/read.ts +54 -35
  795. package/src/tools/filesystem/write.ts +34 -31
  796. package/src/tools/host-filesystem/edit.ts +44 -42
  797. package/src/tools/host-filesystem/read.ts +49 -35
  798. package/src/tools/host-filesystem/transfer.ts +121 -108
  799. package/src/tools/host-filesystem/write.ts +33 -31
  800. package/src/tools/host-terminal/host-shell.ts +50 -48
  801. package/src/tools/memory/register.ts +23 -24
  802. package/src/tools/network/web-fetch.ts +49 -46
  803. package/src/tools/network/web-search.ts +16 -13
  804. package/src/tools/registry.ts +39 -16
  805. package/src/tools/schedule/create.ts +11 -0
  806. package/src/tools/schedule/update.ts +16 -0
  807. package/src/tools/shared/filesystem/audio-read.ts +122 -0
  808. package/src/tools/shared/filesystem/image-read.ts +1 -1
  809. package/src/tools/skills/execute.ts +34 -31
  810. package/src/tools/skills/load.ts +29 -23
  811. package/src/tools/subagent/notify-parent.ts +35 -32
  812. package/src/tools/system/avatar-generator.ts +13 -22
  813. package/src/tools/system/request-permission.ts +30 -27
  814. package/src/tools/terminal/shell.ts +190 -61
  815. package/src/tools/tool-defaults.ts +20 -9
  816. package/src/tools/tool-manifest.ts +4 -4
  817. package/src/tools/types.ts +74 -23
  818. package/src/tools/ui-surface/definitions.ts +69 -9
  819. package/src/usage/types.ts +10 -0
  820. package/src/util/errors.ts +2 -2
  821. package/src/util/map-limit.ts +27 -0
  822. package/src/util/platform.ts +15 -12
  823. package/src/work-items/work-item-runner.ts +7 -2
  824. package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +7 -20
  825. package/src/workspace/migrations/092-backfill-v3-leaves.ts +169 -0
  826. package/src/workspace/migrations/093-backfill-leaf-ids.ts +144 -0
  827. package/src/workspace/migrations/094-seed-avatar-manifest.ts +155 -0
  828. package/src/workspace/migrations/__tests__/094-seed-avatar-manifest.test.ts +136 -0
  829. package/src/workspace/migrations/__tests__/backfill-leaf-ids.test.ts +175 -0
  830. package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +124 -0
  831. package/src/workspace/migrations/registry.ts +6 -0
  832. package/src/workspace/provider-commit-message-generator.ts +15 -17
  833. package/tsconfig.json +4 -1
  834. package/src/__tests__/history-repair-pipeline.test.ts +0 -396
  835. package/src/cli/commands/__tests__/memory-v3-render.test.ts +0 -340
  836. package/src/cli/commands/memory-v3-render.ts +0 -491
  837. package/src/daemon/message-types/disk-pressure.ts +0 -9
  838. package/src/email/feature-gate.ts +0 -23
  839. package/src/memory/v3/__tests__/coactivation-store.test.ts +0 -422
  840. package/src/memory/v3/__tests__/consolidation-job.test.ts +0 -466
  841. package/src/memory/v3/__tests__/coretrieval-seed.test.ts +0 -270
  842. package/src/memory/v3/__tests__/edge-learning-job.test.ts +0 -324
  843. package/src/memory/v3/__tests__/edges.test.ts +0 -706
  844. package/src/memory/v3/__tests__/filter.test.ts +0 -560
  845. package/src/memory/v3/__tests__/gate.test.ts +0 -637
  846. package/src/memory/v3/__tests__/index-composition.test.ts +0 -291
  847. package/src/memory/v3/__tests__/loop.test.ts +0 -775
  848. package/src/memory/v3/__tests__/retriever.test.ts +0 -226
  849. package/src/memory/v3/__tests__/scouts.test.ts +0 -489
  850. package/src/memory/v3/__tests__/shadow-diff.test.ts +0 -225
  851. package/src/memory/v3/__tests__/shadow-middleware.test.ts +0 -398
  852. package/src/memory/v3/__tests__/system-prompts.test.ts +0 -154
  853. package/src/memory/v3/__tests__/traversal.test.ts +0 -508
  854. package/src/memory/v3/__tests__/tree-index.test.ts +0 -280
  855. package/src/memory/v3/__tests__/tree-store.test.ts +0 -529
  856. package/src/memory/v3/__tests__/tree-walk.test.ts +0 -784
  857. package/src/memory/v3/__tests__/validate.test.ts +0 -277
  858. package/src/memory/v3/auto-edges.ts +0 -223
  859. package/src/memory/v3/coactivation-store.ts +0 -124
  860. package/src/memory/v3/consolidation-job.ts +0 -323
  861. package/src/memory/v3/coretrieval-seed.ts +0 -240
  862. package/src/memory/v3/edge-learning-job.ts +0 -160
  863. package/src/memory/v3/edges.ts +0 -286
  864. package/src/memory/v3/filter.ts +0 -286
  865. package/src/memory/v3/gate.ts +0 -349
  866. package/src/memory/v3/index-composition.ts +0 -126
  867. package/src/memory/v3/llm-capture.ts +0 -46
  868. package/src/memory/v3/loop.ts +0 -430
  869. package/src/memory/v3/maintenance.ts +0 -144
  870. package/src/memory/v3/prompt-context.ts +0 -33
  871. package/src/memory/v3/prompts/consolidation.ts +0 -458
  872. package/src/memory/v3/prompts/system-prompts.ts +0 -196
  873. package/src/memory/v3/retriever.ts +0 -33
  874. package/src/memory/v3/scouts.ts +0 -431
  875. package/src/memory/v3/shadow-diff.ts +0 -287
  876. package/src/memory/v3/shadow-middleware.ts +0 -347
  877. package/src/memory/v3/traversal.ts +0 -211
  878. package/src/memory/v3/tree-index.ts +0 -237
  879. package/src/memory/v3/tree-store.ts +0 -394
  880. package/src/memory/v3/tree-walk.ts +0 -356
  881. package/src/memory/v3/validate.ts +0 -323
  882. package/src/plugins/defaults/circuit-breaker.ts +0 -141
  883. package/src/plugins/defaults/compaction.ts +0 -141
  884. package/src/plugins/defaults/empty-response.ts +0 -124
  885. package/src/plugins/defaults/history-repair.ts +0 -83
  886. package/src/plugins/defaults/persistence.ts +0 -146
  887. package/src/plugins/defaults/title-generate.ts +0 -90
  888. package/src/plugins/defaults/token-estimate.ts +0 -101
  889. package/src/plugins/defaults/tool-error.ts +0 -119
  890. package/src/plugins/defaults/tool-result-truncate.ts +0 -84
  891. package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +0 -35
@@ -1,31 +1,39 @@
1
- import {
2
- copyFileSync,
3
- existsSync,
4
- mkdirSync,
5
- readFileSync,
6
- unlinkSync,
7
- } from "node:fs";
8
- import { dirname, join, resolve } from "node:path";
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
9
3
 
10
4
  import { z } from "zod";
11
5
 
12
6
  import { renderCharacterAscii } from "../../avatar/ascii-renderer.js";
7
+ import {
8
+ type AvatarState,
9
+ deriveStateFromLegacyFiles,
10
+ readManifest,
11
+ writeManifest,
12
+ } from "../../avatar/avatar-manifest.js";
13
+ import {
14
+ clearAvatar,
15
+ setCharacter,
16
+ setImage,
17
+ } from "../../avatar/avatar-store.js";
13
18
  import { getCharacterComponents } from "../../avatar/character-components.js";
14
19
  import { updateIdentityAvatarSection } from "../../avatar/identity-avatar.js";
15
20
  import {
16
21
  type CharacterTraits,
22
+ TRAITS_FILENAME,
17
23
  writeTraitsAndRenderAvatar,
18
24
  } from "../../avatar/traits-png-sync.js";
19
25
  import { setPlatformBaseUrl } from "../../config/env.js";
20
26
  import { credentialKey } from "../../security/credential-key.js";
21
27
  import { getSecureKeyAsync } from "../../security/secure-keys.js";
22
- import { generateAndSaveAvatar } from "../../tools/system/avatar-generator.js";
28
+ import { detectMediaType } from "../../tools/shared/filesystem/image-read.js";
29
+ import { generateAvatarImage } from "../../tools/system/avatar-generator.js";
23
30
  import { getLogger } from "../../util/logger.js";
24
31
  import {
25
32
  getAvatarDir,
26
33
  getAvatarImagePath,
27
34
  getWorkspaceDir,
28
35
  } from "../../util/platform.js";
36
+ import { ACTOR_PRINCIPALS, LOCAL_PRINCIPALS } from "../auth/route-policy.js";
29
37
  import { publishAvatarChanged } from "../sync/resource-sync-events.js";
30
38
  import {
31
39
  BadRequestError,
@@ -40,6 +48,50 @@ function handleGetCharacterComponents() {
40
48
  return getCharacterComponents();
41
49
  }
42
50
 
51
+ /**
52
+ * Reads the manifest, self-healing once if it is absent.
53
+ *
54
+ * The migration (092) seeds `avatar.json` for every workspace, so the manifest
55
+ * is normally present. If it is somehow missing (e.g. a workspace that predates
56
+ * the manifest and skipped the migration), we derive state from the legacy
57
+ * sidecar files. A *real* avatar (character/image) is persisted once so
58
+ * subsequent reads hit the manifest directly; an empty (`none`) result is NOT
59
+ * persisted, so an avatar-less workspace stays manifest-less and a later legacy
60
+ * sidecar write is still picked up by the next self-heal (backward compat).
61
+ */
62
+ function readManifestSelfHealing(): AvatarState {
63
+ const manifest = readManifest();
64
+ if (manifest) {
65
+ return manifest;
66
+ }
67
+ const derived = deriveStateFromLegacyFiles();
68
+ // Only persist a real avatar. Persisting `none` would shadow a later legacy
69
+ // sidecar write behind a stale manifest (see migration 094 + clearAvatar).
70
+ // Persist is best-effort: on a read-only / permission-restricted workspace the
71
+ // write can throw. Swallow it so a GET still returns the derived state instead
72
+ // of turning into a 500 — the next read simply self-heals again.
73
+ if (derived.kind !== "none") {
74
+ try {
75
+ writeManifest(derived);
76
+ } catch (err) {
77
+ log.warn({ err }, "Failed to persist self-healed avatar manifest");
78
+ }
79
+ }
80
+ return derived;
81
+ }
82
+
83
+ /**
84
+ * Return the authoritative avatar render state.
85
+ *
86
+ * Reads the manifest (`avatar.json`). When the manifest is absent it is
87
+ * self-healed once from the legacy sidecar files and persisted. Never 404s —
88
+ * an empty workspace yields `{ kind: "none", traits: null, source: null,
89
+ * image: null }`.
90
+ */
91
+ function handleGetAvatarState() {
92
+ return readManifestSelfHealing();
93
+ }
94
+
43
95
  function handleRenderFromTraits({ body, headers }: RouteHandlerArgs) {
44
96
  const traits = body as CharacterTraits | undefined;
45
97
 
@@ -55,7 +107,7 @@ function handleRenderFromTraits({ body, headers }: RouteHandlerArgs) {
55
107
  );
56
108
  }
57
109
 
58
- const result = writeTraitsAndRenderAvatar(traits);
110
+ const result = setCharacter(traits);
59
111
 
60
112
  if (!result.ok) {
61
113
  switch (result.reason) {
@@ -92,27 +144,69 @@ async function handleGenerateAvatar({ body, headers }: RouteHandlerArgs) {
92
144
  // Non-fatal
93
145
  }
94
146
 
95
- const result = await generateAndSaveAvatar(description);
96
- if (result.isError) {
147
+ const result = await generateAvatarImage(description);
148
+ if (result.isError || !result.pngBuffer) {
97
149
  throw new ServiceUnavailableError(result.content);
98
150
  }
99
151
 
100
- // Remove native character files since AI-generated image takes precedence
101
- const avatarDir = getAvatarDir();
102
- const traitsPath = join(avatarDir, "character-traits.json");
103
- const asciiPath = join(avatarDir, "character-ascii.txt");
104
- try {
105
- if (existsSync(traitsPath)) unlinkSync(traitsPath);
106
- if (existsSync(asciiPath)) unlinkSync(asciiPath);
107
- } catch {
108
- // Best-effort
109
- }
152
+ // Route through the store: atomically writes the PNG, removes the now-stale
153
+ // character sidecars (traits + ASCII), and records an AI-sourced manifest.
154
+ setImage(result.pngBuffer, "ai");
110
155
 
111
156
  updateIdentityAvatarSection(null, log);
112
157
  publishAvatarChanged(headers?.["x-vellum-client-id"]?.trim() || undefined);
113
158
  return { ok: true, message: result.content };
114
159
  }
115
160
 
161
+ /**
162
+ * Accept a base64-encoded image and set it as the avatar. Replaces the web
163
+ * client's prior two-call `workspace/write` + `workspace/delete` dance with a
164
+ * single server-authoritative endpoint: the store atomically writes the PNG,
165
+ * clears the character sidecars, and records an `image` manifest.
166
+ */
167
+ function handleUploadAvatarImage({ body, headers }: RouteHandlerArgs) {
168
+ const payload = body as Record<string, unknown> | undefined;
169
+ const content = payload?.content;
170
+ const encoding = payload?.encoding;
171
+
172
+ if (typeof content !== "string" || content.length === 0) {
173
+ throw new BadRequestError("content (base64 string) is required");
174
+ }
175
+ if (encoding !== undefined && encoding !== "base64") {
176
+ throw new BadRequestError('encoding must be "base64"');
177
+ }
178
+
179
+ // Strictly validate the base64 BEFORE decoding. `Buffer.from(.., "base64")`
180
+ // silently drops characters outside the alphabet, so a valid image prefix
181
+ // followed by garbage would decode to a truncated/corrupt buffer that still
182
+ // passes the magic-byte sniff below — accepting a corrupt avatar. Same strict
183
+ // pattern used by stt-routes / live-voice (tolerating surrounding whitespace).
184
+ const normalized = content.replace(/\s+/g, "");
185
+ if (
186
+ normalized.length === 0 ||
187
+ !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(
188
+ normalized,
189
+ )
190
+ ) {
191
+ throw new BadRequestError("content is not valid base64-encoded image data");
192
+ }
193
+
194
+ const buffer = Buffer.from(normalized, "base64");
195
+ if (detectMediaType(buffer) === null) {
196
+ throw new BadRequestError(
197
+ "content must be a PNG, JPEG, GIF, or WEBP image",
198
+ );
199
+ }
200
+
201
+ // Route through the store: atomically writes the PNG, removes the now-stale
202
+ // character sidecars (traits + ASCII), and records an uploaded-image manifest.
203
+ setImage(buffer, "upload");
204
+
205
+ updateIdentityAvatarSection(null, log);
206
+ publishAvatarChanged(headers?.["x-vellum-client-id"]?.trim() || undefined);
207
+ return { ok: true };
208
+ }
209
+
116
210
  function handleSetAvatar({ body, headers }: RouteHandlerArgs) {
117
211
  const imagePath = (body as Record<string, unknown>)?.imagePath as
118
212
  | string
@@ -137,9 +231,9 @@ function handleSetAvatar({ body, headers }: RouteHandlerArgs) {
137
231
  throw new BadRequestError(`Image file not found: ${normalized}`);
138
232
  }
139
233
 
140
- const avatarPath = getAvatarImagePath();
141
- mkdirSync(dirname(avatarPath), { recursive: true });
142
- copyFileSync(normalized, avatarPath);
234
+ // Route through the store so traits sidecars are cleared and the manifest is
235
+ // recorded as an uploaded image atomically (no more stale both-files state).
236
+ setImage(readFileSync(normalized), "upload");
143
237
 
144
238
  updateIdentityAvatarSection(null, log);
145
239
  publishAvatarChanged(headers?.["x-vellum-client-id"]?.trim() || undefined);
@@ -147,33 +241,26 @@ function handleSetAvatar({ body, headers }: RouteHandlerArgs) {
147
241
  }
148
242
 
149
243
  function handleRemoveAvatar({ headers }: RouteHandlerArgs) {
150
- const avatarPath = getAvatarImagePath();
151
-
152
- if (!existsSync(avatarPath)) {
153
- return { ok: true, hadAvatar: false };
154
- }
155
-
156
- unlinkSync(avatarPath);
157
-
158
- // Regenerate character PNG from traits if available
159
- const traitsPath = join(getAvatarDir(), "character-traits.json");
160
- if (existsSync(traitsPath)) {
161
- try {
162
- const traits = JSON.parse(
163
- readFileSync(traitsPath, "utf-8"),
164
- ) as CharacterTraits;
165
- writeTraitsAndRenderAvatar(traits);
166
- } catch {
167
- // Best-effort
168
- }
169
- }
244
+ // `hadAvatar` must reflect whether *any* avatar was configured before the
245
+ // clear — not just a rendered PNG. A character-only workspace (traits present,
246
+ // no PNG) is still an avatar, and clearAvatar() deletes its traits/ascii too.
247
+ // Derive from the manifest (self-healing on a manifest-miss) and treat any
248
+ // non-"none" kind as hadAvatar.
249
+ const hadAvatar = readManifestSelfHealing().kind !== "none";
250
+
251
+ // Clear everything to a manifest-consistent kind:"none". Semantic change
252
+ // (intentional): traits no longer persist alongside an image, so there is
253
+ // nothing to revert to — the legacy "re-render character from traits" branch
254
+ // has been removed. avatar/remove is now a plain clear, reachable only via
255
+ // CLI/host.
256
+ clearAvatar();
170
257
 
171
258
  updateIdentityAvatarSection(
172
259
  "Default character avatar (no custom image set)",
173
260
  log,
174
261
  );
175
262
  publishAvatarChanged(headers?.["x-vellum-client-id"]?.trim() || undefined);
176
- return { ok: true, hadAvatar: true };
263
+ return { ok: true, hadAvatar };
177
264
  }
178
265
 
179
266
  function handleGetAvatar({ queryParams, body }: RouteHandlerArgs) {
@@ -187,19 +274,27 @@ function handleGetAvatar({ queryParams, body }: RouteHandlerArgs) {
187
274
  );
188
275
  }
189
276
 
277
+ // Resolve precedence from the manifest so this raster accessor (CLI / dock /
278
+ // notifications) agrees with macOS/web rather than picking image-first off
279
+ // file existence. For both `character` and `image` the derived raster is the
280
+ // same on-disk PNG; only the precedence is manifest-driven. Self-heals once
281
+ // on manifest-miss so we never re-infer from legacy files per request.
282
+ const state = readManifestSelfHealing();
283
+
284
+ if (state.kind === "none") {
285
+ return { exists: false };
286
+ }
287
+
190
288
  const avatarPath = getAvatarImagePath();
191
289
 
192
- if (!existsSync(avatarPath)) {
193
- const traitsPath = join(getAvatarDir(), "character-traits.json");
194
- if (existsSync(traitsPath)) {
195
- try {
196
- const traits = JSON.parse(
197
- readFileSync(traitsPath, "utf-8"),
198
- ) as CharacterTraits;
199
- writeTraitsAndRenderAvatar(traits);
200
- } catch {
201
- // Best-effort
202
- }
290
+ // For a character, the rendered PNG normally already exists on disk. Keep the
291
+ // existing safety net: if it's missing, re-render it from the persisted traits
292
+ // so the accessor still returns a raster.
293
+ if (state.kind === "character" && !existsSync(avatarPath) && state.traits) {
294
+ try {
295
+ writeTraitsAndRenderAvatar(state.traits);
296
+ } catch {
297
+ // Best-effort
203
298
  }
204
299
  }
205
300
 
@@ -231,7 +326,7 @@ function handleCharacterAscii({ queryParams, body }: RouteHandlerArgs) {
231
326
  );
232
327
  }
233
328
 
234
- const traitsPath = join(getAvatarDir(), "character-traits.json");
329
+ const traitsPath = join(getAvatarDir(), TRAITS_FILENAME);
235
330
  if (!existsSync(traitsPath)) {
236
331
  throw new BadRequestError(
237
332
  "No native character set. Use 'assistant avatar character update' first.",
@@ -260,15 +355,54 @@ export const ROUTES: RouteDefinition[] = [
260
355
  operationId: "avatar_character_components",
261
356
  endpoint: "avatar/character-components",
262
357
  method: "GET",
358
+ policy: {
359
+ requiredScopes: ["settings.read"],
360
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
361
+ },
263
362
  handler: handleGetCharacterComponents,
264
363
  summary: "Get character components",
265
364
  description: "Return available avatar character components.",
266
365
  tags: ["avatar"],
267
366
  },
367
+ {
368
+ operationId: "avatar_get_state",
369
+ endpoint: "avatar/state",
370
+ method: "GET",
371
+ policy: {
372
+ requiredScopes: ["settings.read"],
373
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
374
+ },
375
+ handler: handleGetAvatarState,
376
+ summary: "Get avatar state",
377
+ description:
378
+ "Return the authoritative avatar render mode (character, image, or none).",
379
+ tags: ["avatar"],
380
+ responseBody: z.object({
381
+ kind: z.enum(["character", "image", "none"]),
382
+ traits: z
383
+ .object({
384
+ bodyShape: z.string(),
385
+ eyeStyle: z.string(),
386
+ color: z.string(),
387
+ })
388
+ .nullable(),
389
+ source: z.enum(["builder", "upload", "ai"]).nullable(),
390
+ image: z
391
+ .object({
392
+ updatedAt: z.string(),
393
+ etag: z.string(),
394
+ })
395
+ .nullable(),
396
+ }),
397
+ },
268
398
  {
269
399
  operationId: "avatar_render_from_traits",
270
400
  endpoint: "avatar/render-from-traits",
271
401
  method: "POST",
402
+ policy: {
403
+ requiredScopes: ["settings.write"],
404
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
405
+ },
272
406
  handler: handleRenderFromTraits,
273
407
  summary: "Render avatar from traits",
274
408
  description: "Write character traits and render an avatar PNG.",
@@ -286,8 +420,14 @@ export const ROUTES: RouteDefinition[] = [
286
420
  operationId: "notify_avatar_updated",
287
421
  endpoint: "avatar/notify-updated",
288
422
  method: "POST",
423
+ policy: {
424
+ requiredScopes: ["settings.write"],
425
+ allowedPrincipalTypes: LOCAL_PRINCIPALS,
426
+ },
289
427
  handler: ({ headers }: RouteHandlerArgs) => {
290
- publishAvatarChanged(headers?.["x-vellum-client-id"]?.trim() || undefined);
428
+ publishAvatarChanged(
429
+ headers?.["x-vellum-client-id"]?.trim() || undefined,
430
+ );
291
431
  return { ok: true };
292
432
  },
293
433
  summary: "Notify avatar updated",
@@ -301,6 +441,10 @@ export const ROUTES: RouteDefinition[] = [
301
441
  operationId: "avatar_generate",
302
442
  endpoint: "avatar/generate",
303
443
  method: "POST",
444
+ policy: {
445
+ requiredScopes: ["settings.write"],
446
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
447
+ },
304
448
  handler: handleGenerateAvatar,
305
449
  summary: "Generate AI avatar",
306
450
  description: "Generate an AI avatar from a text description and save it.",
@@ -312,6 +456,10 @@ export const ROUTES: RouteDefinition[] = [
312
456
  operationId: "avatar_set",
313
457
  endpoint: "avatar/set",
314
458
  method: "POST",
459
+ policy: {
460
+ requiredScopes: ["settings.write"],
461
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
462
+ },
315
463
  handler: handleSetAvatar,
316
464
  summary: "Set avatar from image file",
317
465
  description: "Copy an image file to the avatar location.",
@@ -319,10 +467,33 @@ export const ROUTES: RouteDefinition[] = [
319
467
  requestBody: z.object({ imagePath: z.string() }),
320
468
  responseBody: z.object({ ok: z.boolean() }),
321
469
  },
470
+ {
471
+ operationId: "avatar_upload_image",
472
+ endpoint: "avatar/image",
473
+ method: "POST",
474
+ policy: {
475
+ requiredScopes: ["settings.write"],
476
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
477
+ },
478
+ handler: handleUploadAvatarImage,
479
+ summary: "Upload avatar image",
480
+ description:
481
+ "Upload a base64-encoded image as the avatar; writes the PNG and clears character traits atomically.",
482
+ tags: ["avatar"],
483
+ requestBody: z.object({
484
+ content: z.string(),
485
+ encoding: z.literal("base64").optional(),
486
+ }),
487
+ responseBody: z.object({ ok: z.boolean() }),
488
+ },
322
489
  {
323
490
  operationId: "avatar_remove",
324
491
  endpoint: "avatar/remove",
325
492
  method: "POST",
493
+ policy: {
494
+ requiredScopes: ["settings.write"],
495
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
496
+ },
326
497
  handler: handleRemoveAvatar,
327
498
  summary: "Remove custom avatar",
328
499
  description:
@@ -334,6 +505,10 @@ export const ROUTES: RouteDefinition[] = [
334
505
  operationId: "avatar_get",
335
506
  endpoint: "avatar/get",
336
507
  method: "GET",
508
+ policy: {
509
+ requiredScopes: ["settings.read"],
510
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
511
+ },
337
512
  handler: handleGetAvatar,
338
513
  summary: "Get current avatar",
339
514
  description: "Retrieve the current avatar as a file path or base64 string.",
@@ -350,6 +525,10 @@ export const ROUTES: RouteDefinition[] = [
350
525
  operationId: "avatar_character_ascii",
351
526
  endpoint: "avatar/character/ascii",
352
527
  method: "GET",
528
+ policy: {
529
+ requiredScopes: ["settings.read"],
530
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
531
+ },
353
532
  handler: handleCharacterAscii,
354
533
  summary: "Render character as ASCII art",
355
534
  description: "Render the current native character as ASCII art.",
@@ -12,6 +12,7 @@ import {
12
12
  cancelBackgroundTool,
13
13
  listBackgroundTools,
14
14
  } from "../../tools/background-tool-registry.js";
15
+ import { LOCAL_PRINCIPALS } from "../auth/route-policy.js";
15
16
  import { BadRequestError } from "./errors.js";
16
17
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
17
18
 
@@ -59,6 +60,10 @@ export const ROUTES: RouteDefinition[] = [
59
60
  operationId: "background_tool_list",
60
61
  endpoint: "background-tools",
61
62
  method: "GET",
63
+ policy: {
64
+ requiredScopes: ["settings.read"],
65
+ allowedPrincipalTypes: LOCAL_PRINCIPALS,
66
+ },
62
67
  handler: handleBackgroundToolList,
63
68
  summary: "List active background tools",
64
69
  description:
@@ -80,6 +85,10 @@ export const ROUTES: RouteDefinition[] = [
80
85
  operationId: "background_tool_cancel",
81
86
  endpoint: "background-tools/cancel",
82
87
  method: "POST",
88
+ policy: {
89
+ requiredScopes: ["settings.write"],
90
+ allowedPrincipalTypes: LOCAL_PRINCIPALS,
91
+ },
83
92
  handler: handleBackgroundToolCancel,
84
93
  summary: "Cancel a background tool",
85
94
  description: "Cancel an active background tool execution by ID.",
@@ -7,6 +7,7 @@ import {
7
7
  import type { BackgroundWakeRuntime } from "../../background-wake/runtime-registry.js";
8
8
  import { getBackgroundWakeRuntime } from "../../background-wake/runtime-registry.js";
9
9
  import { getLogger } from "../../util/logger.js";
10
+ import { GATEWAY_PRINCIPALS } from "../auth/route-policy.js";
10
11
  import { BadRequestError, ServiceUnavailableError } from "./errors.js";
11
12
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
12
13
 
@@ -309,7 +310,10 @@ export const ROUTES: RouteDefinition[] = [
309
310
  operationId: "getBackgroundWakeIntent",
310
311
  endpoint: "background-wake/intent",
311
312
  method: "GET",
312
- policyKey: "background-wake",
313
+ policy: {
314
+ requiredScopes: ["internal.write"],
315
+ allowedPrincipalTypes: GATEWAY_PRINCIPALS,
316
+ },
313
317
  summary: "Get background wake intent",
314
318
  description: "Return the current computed background wake intent.",
315
319
  tags: ["background-wake"],
@@ -322,7 +326,10 @@ export const ROUTES: RouteDefinition[] = [
322
326
  operationId: "prepareBackgroundWakeSleep",
323
327
  endpoint: "background-wake/prepare-sleep",
324
328
  method: "POST",
325
- policyKey: "background-wake",
329
+ policy: {
330
+ requiredScopes: ["internal.write"],
331
+ allowedPrincipalTypes: GATEWAY_PRINCIPALS,
332
+ },
326
333
  summary: "Prepare for assistant sleep",
327
334
  description:
328
335
  "Return the current background wake intent and whether sleep should be deferred.",
@@ -337,7 +344,10 @@ export const ROUTES: RouteDefinition[] = [
337
344
  operationId: "drainDueBackgroundWake",
338
345
  endpoint: "background-wake/drain-due",
339
346
  method: "POST",
340
- policyKey: "background-wake",
347
+ policy: {
348
+ requiredScopes: ["internal.write"],
349
+ allowedPrincipalTypes: GATEWAY_PRINCIPALS,
350
+ },
341
351
  summary: "Drain due background wake work",
342
352
  description:
343
353
  "Run due heartbeat and scheduler work for a background wake lease.",
@@ -46,6 +46,7 @@ import type { BackupConfig, BackupDestination } from "../../config/schema.js";
46
46
  import { getMemoryCheckpoint } from "../../memory/checkpoints.js";
47
47
  import { getLogger } from "../../util/logger.js";
48
48
  import { getWorkspaceDir, getWorkspaceHooksDir } from "../../util/platform.js";
49
+ import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
49
50
  import { DefaultPathResolver } from "../migrations/vbundle-import-analyzer.js";
50
51
  import { BadRequestError, RouteError } from "./errors.js";
51
52
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
@@ -493,6 +494,10 @@ export const ROUTES: RouteDefinition[] = [
493
494
  operationId: "backups_list",
494
495
  endpoint: "backups",
495
496
  method: "GET",
497
+ policy: {
498
+ requiredScopes: ["settings.read"],
499
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
500
+ },
496
501
  handler: handleBackupList,
497
502
  summary: "List backup snapshots",
498
503
  description:
@@ -515,6 +520,10 @@ export const ROUTES: RouteDefinition[] = [
515
520
  operationId: "backups_create",
516
521
  endpoint: "backups/create",
517
522
  method: "POST",
523
+ policy: {
524
+ requiredScopes: ["settings.write"],
525
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
526
+ },
518
527
  handler: handleBackupCreate,
519
528
  summary: "Create a backup snapshot immediately",
520
529
  description:
@@ -530,6 +539,10 @@ export const ROUTES: RouteDefinition[] = [
530
539
  operationId: "backups_restore",
531
540
  endpoint: "backups/restore",
532
541
  method: "POST",
542
+ policy: {
543
+ requiredScopes: ["settings.write"],
544
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
545
+ },
533
546
  handler: handleBackupRestore,
534
547
  summary: "Restore from a backup snapshot",
535
548
  description:
@@ -549,6 +562,10 @@ export const ROUTES: RouteDefinition[] = [
549
562
  operationId: "backups_verify",
550
563
  endpoint: "backups/verify",
551
564
  method: "POST",
565
+ policy: {
566
+ requiredScopes: ["settings.read"],
567
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
568
+ },
552
569
  handler: handleBackupVerify,
553
570
  summary: "Verify a backup snapshot",
554
571
  description:
@@ -567,6 +584,10 @@ export const ROUTES: RouteDefinition[] = [
567
584
  operationId: "backup_enable",
568
585
  endpoint: "backup/enable",
569
586
  method: "POST",
587
+ policy: {
588
+ requiredScopes: ["settings.write"],
589
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
590
+ },
570
591
  handler: handleBackupEnable,
571
592
  summary: "Enable automated backups",
572
593
  description:
@@ -583,6 +604,10 @@ export const ROUTES: RouteDefinition[] = [
583
604
  operationId: "backup_disable",
584
605
  endpoint: "backup/disable",
585
606
  method: "POST",
607
+ policy: {
608
+ requiredScopes: ["settings.write"],
609
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
610
+ },
586
611
  handler: handleBackupDisable,
587
612
  summary: "Disable automated backups",
588
613
  description:
@@ -596,6 +621,10 @@ export const ROUTES: RouteDefinition[] = [
596
621
  operationId: "backup_destinations_list",
597
622
  endpoint: "backup/destinations",
598
623
  method: "GET",
624
+ policy: {
625
+ requiredScopes: ["settings.read"],
626
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
627
+ },
599
628
  handler: handleBackupDestinationsList,
600
629
  summary: "List configured offsite backup destinations",
601
630
  description:
@@ -614,6 +643,10 @@ export const ROUTES: RouteDefinition[] = [
614
643
  operationId: "backup_destinations_add",
615
644
  endpoint: "backup/destinations/add",
616
645
  method: "POST",
646
+ policy: {
647
+ requiredScopes: ["settings.write"],
648
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
649
+ },
617
650
  handler: handleBackupDestinationsAdd,
618
651
  summary: "Add an offsite backup destination",
619
652
  description:
@@ -642,6 +675,10 @@ export const ROUTES: RouteDefinition[] = [
642
675
  operationId: "backup_destinations_remove",
643
676
  endpoint: "backup/destinations/remove",
644
677
  method: "POST",
678
+ policy: {
679
+ requiredScopes: ["settings.write"],
680
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
681
+ },
645
682
  handler: handleBackupDestinationsRemove,
646
683
  summary: "Remove an offsite backup destination",
647
684
  description:
@@ -666,6 +703,10 @@ export const ROUTES: RouteDefinition[] = [
666
703
  operationId: "backup_destinations_set_encrypt",
667
704
  endpoint: "backup/destinations/set-encrypt",
668
705
  method: "POST",
706
+ policy: {
707
+ requiredScopes: ["settings.write"],
708
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
709
+ },
669
710
  handler: handleBackupDestinationsSetEncrypt,
670
711
  summary: "Toggle encryption for an existing destination",
671
712
  description:
@@ -691,6 +732,10 @@ export const ROUTES: RouteDefinition[] = [
691
732
  operationId: "backup_status",
692
733
  endpoint: "backup/status",
693
734
  method: "GET",
735
+ policy: {
736
+ requiredScopes: ["settings.read"],
737
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
738
+ },
694
739
  handler: handleBackupStatus,
695
740
  summary: "Show backup status and next-run timing",
696
741
  description:
@@ -23,6 +23,7 @@ import { getDb } from "../../memory/db-connection.js";
23
23
  import { getLogger } from "../../util/logger.js";
24
24
  import { buildAssistantEvent } from "../assistant-event.js";
25
25
  import { assistantEventHub } from "../assistant-event-hub.js";
26
+ import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
26
27
  import { BadRequestError, NotFoundError } from "./errors.js";
27
28
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
28
29
 
@@ -120,6 +121,10 @@ export const ROUTES: RouteDefinition[] = [
120
121
  operationId: "bookmarks_list",
121
122
  endpoint: "bookmarks",
122
123
  method: "GET",
124
+ policy: {
125
+ requiredScopes: ["chat.read"],
126
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
127
+ },
123
128
  summary: "List bookmarks",
124
129
  description:
125
130
  "Return all bookmarks (newest first), joined with their parent message and conversation.",
@@ -131,6 +136,10 @@ export const ROUTES: RouteDefinition[] = [
131
136
  operationId: "bookmarks_create",
132
137
  endpoint: "bookmarks",
133
138
  method: "POST",
139
+ policy: {
140
+ requiredScopes: ["chat.write"],
141
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
142
+ },
134
143
  summary: "Create a bookmark",
135
144
  description:
136
145
  "Bookmark the given message. Idempotent on `messageId` — calling twice returns the same bookmark.",
@@ -146,6 +155,10 @@ export const ROUTES: RouteDefinition[] = [
146
155
  operationId: "bookmarks_delete_by_message",
147
156
  endpoint: "bookmarks/by-message/:messageId",
148
157
  method: "DELETE",
158
+ policy: {
159
+ requiredScopes: ["chat.write"],
160
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
161
+ },
149
162
  summary: "Delete a bookmark by message id",
150
163
  description:
151
164
  "Delete the bookmark (if any) attached to the given message. Succeeds even if no row matched.",