@vellumai/assistant 0.8.6 → 0.8.7-dev.202606052118.34cd356

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 (1078) hide show
  1. package/AGENTS.md +4 -4
  2. package/Dockerfile +21 -4
  3. package/bun.lock +13 -4
  4. package/docker-entrypoint.sh +12 -8
  5. package/docker-init-apt-root.sh +3 -1
  6. package/docker-kata-apt-env.sh +3 -1
  7. package/docker-kata-runtime-family.sh +12 -0
  8. package/docs/architecture/memory.md +1 -1
  9. package/docs/plugins.md +110 -83
  10. package/examples/plugins/echo/README.md +13 -12
  11. package/examples/plugins/echo/register.ts +0 -54
  12. package/knip.json +1 -0
  13. package/node_modules/@vellumai/environments/bun.lock +24 -0
  14. package/node_modules/@vellumai/environments/package.json +18 -0
  15. package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +95 -0
  16. package/node_modules/@vellumai/environments/src/index.ts +11 -0
  17. package/node_modules/@vellumai/environments/src/seeds.ts +73 -0
  18. package/node_modules/@vellumai/environments/src/types.ts +70 -0
  19. package/node_modules/@vellumai/environments/tsconfig.json +20 -0
  20. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +11 -0
  21. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +3 -4
  22. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
  23. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +13 -8
  24. package/openapi.yaml +6964 -539
  25. package/package.json +8 -4
  26. package/scripts/generate-openapi.ts +88 -54
  27. package/src/__tests__/agent-loop-callsite-precedence.test.ts +42 -80
  28. package/src/__tests__/agent-loop-exit-reason.test.ts +188 -45
  29. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +141 -0
  30. package/src/__tests__/agent-loop-override-profile.test.ts +19 -32
  31. package/src/__tests__/agent-loop-provider-error-recording.test.ts +7 -5
  32. package/src/__tests__/agent-loop-thinking.test.ts +17 -12
  33. package/src/__tests__/agent-loop.test.ts +238 -422
  34. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +6 -2
  35. package/src/__tests__/agent-wake-override-profile.test.ts +22 -40
  36. package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
  37. package/src/__tests__/annotate-risk-options.test.ts +2 -3
  38. package/src/__tests__/anthropic-provider.test.ts +296 -57
  39. package/src/__tests__/app-builder-skill-instructions.test.ts +22 -0
  40. package/src/__tests__/app-control-flow.test.ts +6 -1
  41. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  42. package/src/__tests__/approval-cascade.test.ts +4 -11
  43. package/src/__tests__/approval-routes-http.test.ts +8 -3
  44. package/src/__tests__/assistant-event-hub.test.ts +25 -0
  45. package/src/__tests__/assistant-event.test.ts +15 -0
  46. package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
  47. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
  48. package/src/__tests__/assistant-stream-state.test.ts +645 -0
  49. package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
  50. package/src/__tests__/avatar-e2e.test.ts +7 -37
  51. package/src/__tests__/avatar-generator.test.ts +12 -42
  52. package/src/__tests__/avatar-identity-sync.test.ts +28 -3
  53. package/src/__tests__/background-shell-bash.test.ts +3 -7
  54. package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
  55. package/src/__tests__/btw-routes.test.ts +69 -15
  56. package/src/__tests__/build-persisted-content.test.ts +184 -0
  57. package/src/__tests__/call-pointer-messages.test.ts +5 -3
  58. package/src/__tests__/call-site-routing-provider.test.ts +22 -40
  59. package/src/__tests__/catalog-files.test.ts +1 -0
  60. package/src/__tests__/channel-approval-routes.test.ts +49 -21
  61. package/src/__tests__/channel-approvals.test.ts +4 -2
  62. package/src/__tests__/channel-invite-transport.test.ts +1 -5
  63. package/src/__tests__/channel-readiness-routes.test.ts +0 -4
  64. package/src/__tests__/channel-readiness-slack-remote.test.ts +2 -7
  65. package/src/__tests__/channel-retry-sweep.test.ts +71 -79
  66. package/src/__tests__/clawhub-files.test.ts +1 -0
  67. package/src/__tests__/compaction-circuit.test.ts +258 -0
  68. package/src/__tests__/compaction-direct.test.ts +132 -0
  69. package/src/__tests__/compaction-events.test.ts +5 -17
  70. package/src/__tests__/compaction-trail-store.test.ts +1 -79
  71. package/src/__tests__/compaction.benchmark.test.ts +0 -30
  72. package/src/__tests__/compactor-image-manifest-trust.test.ts +112 -0
  73. package/src/__tests__/computer-use-tools.test.ts +2 -2
  74. package/src/__tests__/config-watcher.test.ts +28 -0
  75. package/src/__tests__/context-search-agent-runner.test.ts +6 -3
  76. package/src/__tests__/context-token-estimator.test.ts +34 -0
  77. package/src/__tests__/context-window-manager-compact-retry.test.ts +291 -0
  78. package/src/__tests__/conversation-abort-tool-results.test.ts +70 -25
  79. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +9 -7
  80. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -34
  81. package/src/__tests__/conversation-agent-loop-overflow.test.ts +476 -963
  82. package/src/__tests__/conversation-agent-loop.test.ts +823 -1321
  83. package/src/__tests__/conversation-analysis-routes.test.ts +7 -3
  84. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
  85. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  86. package/src/__tests__/conversation-clear-safety.test.ts +20 -10
  87. package/src/__tests__/conversation-confirmation-signals.test.ts +15 -45
  88. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  89. package/src/__tests__/conversation-disk-view.test.ts +10 -17
  90. package/src/__tests__/conversation-fork-crud.test.ts +86 -172
  91. package/src/__tests__/conversation-fork-route.test.ts +16 -14
  92. package/src/__tests__/conversation-history-web-search.test.ts +11 -1
  93. package/src/__tests__/conversation-init.benchmark.test.ts +6 -6
  94. package/src/__tests__/conversation-lifecycle.test.ts +3 -2
  95. package/src/__tests__/conversation-load-history-repair.test.ts +3 -2
  96. package/src/__tests__/conversation-load-history-stripped.test.ts +1 -1
  97. package/src/__tests__/conversation-message-sync-tags.test.ts +3 -4
  98. package/src/__tests__/conversation-pairing.test.ts +10 -7
  99. package/src/__tests__/conversation-pre-run-repair.test.ts +1 -1
  100. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -0
  101. package/src/__tests__/conversation-process-callsite.test.ts +27 -30
  102. package/src/__tests__/conversation-provider-retry-repair.test.ts +80 -51
  103. package/src/__tests__/conversation-queue.test.ts +272 -164
  104. package/src/__tests__/conversation-routes-disk-view.test.ts +6 -2
  105. package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
  106. package/src/__tests__/conversation-routes-slash-commands.test.ts +8 -7
  107. package/src/__tests__/conversation-runtime-assembly.test.ts +317 -313
  108. package/src/__tests__/conversation-runtime-workspace.test.ts +114 -36
  109. package/src/__tests__/conversation-slash-commands.test.ts +8 -42
  110. package/src/__tests__/conversation-slash-queue.test.ts +42 -31
  111. package/src/__tests__/conversation-slash-unknown.test.ts +13 -15
  112. package/src/__tests__/conversation-speed-override.test.ts +8 -22
  113. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  114. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +90 -15
  115. package/src/__tests__/conversation-surfaces-app-control.test.ts +32 -4
  116. package/src/__tests__/conversation-surfaces-state-update.test.ts +5 -2
  117. package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -15
  118. package/src/__tests__/conversation-sync-tags.test.ts +27 -15
  119. package/src/__tests__/conversation-title-service.test.ts +135 -2
  120. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +23 -11
  121. package/src/__tests__/conversation-unread-route.test.ts +14 -2
  122. package/src/__tests__/conversation-usage.test.ts +0 -2
  123. package/src/__tests__/conversation-wipe.test.ts +1 -1
  124. package/src/__tests__/conversation-workspace-cache-state.test.ts +20 -17
  125. package/src/__tests__/conversation-workspace-injection.test.ts +114 -23
  126. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +34 -13
  127. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  128. package/src/__tests__/credential-execution-tools.test.ts +1 -2
  129. package/src/__tests__/credential-security-invariants.test.ts +0 -1
  130. package/src/__tests__/cross-provider-web-search.test.ts +220 -3
  131. package/src/__tests__/cu-unified-flow.test.ts +26 -1
  132. package/src/__tests__/db-acp-history.test.ts +101 -0
  133. package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -0
  134. package/src/__tests__/disk-pressure-guard.test.ts +66 -0
  135. package/src/__tests__/disk-pressure-routes.test.ts +9 -2
  136. package/src/__tests__/dm-persistence.test.ts +12 -3
  137. package/src/__tests__/dynamic-page-surface.test.ts +99 -0
  138. package/src/__tests__/edit-propagation.test.ts +1 -2
  139. package/src/__tests__/empty-response-hook.test.ts +304 -0
  140. package/src/__tests__/feature-flag-test-helpers.ts +2 -2
  141. package/src/__tests__/file-write-tool.test.ts +63 -0
  142. package/src/__tests__/filing-service.test.ts +2 -2
  143. package/src/__tests__/first-greeting.test.ts +55 -14
  144. package/src/__tests__/gemini-image-service.test.ts +13 -0
  145. package/src/__tests__/gemini-inline-media.test.ts +78 -0
  146. package/src/__tests__/gemini-provider.test.ts +351 -28
  147. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  148. package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
  149. package/src/__tests__/guardian-routing-state.test.ts +60 -71
  150. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +10 -8
  151. package/src/__tests__/heartbeat-disk-pressure.test.ts +2 -0
  152. package/src/__tests__/heartbeat-service.test.ts +3 -1
  153. package/src/__tests__/helpers/mock-provider.ts +110 -0
  154. package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
  155. package/src/__tests__/history-repair-hook.test.ts +162 -0
  156. package/src/__tests__/history-repair-observability.test.ts +1 -1
  157. package/src/__tests__/history-repair.test.ts +2 -1
  158. package/src/__tests__/host-app-control-proxy.test.ts +2 -0
  159. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  160. package/src/__tests__/host-cu-proxy.test.ts +2 -0
  161. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  162. package/src/__tests__/host-file-edit-tool.test.ts +4 -2
  163. package/src/__tests__/host-file-proxy.test.ts +31 -0
  164. package/src/__tests__/host-file-read-tool.test.ts +4 -2
  165. package/src/__tests__/host-file-write-tool.test.ts +9 -3
  166. package/src/__tests__/host-proxy-preactivation.test.ts +53 -14
  167. package/src/__tests__/host-shell-tool.test.ts +9 -4
  168. package/src/__tests__/http-user-message-parity.test.ts +2 -2
  169. package/src/__tests__/identity-intro-cache.test.ts +47 -114
  170. package/src/__tests__/identity-routes.test.ts +248 -7
  171. package/src/__tests__/inbound-slack-persistence.test.ts +12 -3
  172. package/src/__tests__/injector-background-turn.test.ts +3 -9
  173. package/src/__tests__/injector-chain.test.ts +139 -275
  174. package/src/__tests__/injector-disk-pressure.test.ts +75 -41
  175. package/src/__tests__/injector-document-comments.test.ts +3 -3
  176. package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
  177. package/src/__tests__/injector-v3-suppression.test.ts +214 -0
  178. package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
  179. package/src/__tests__/list-messages-attachments.test.ts +7 -8
  180. package/src/__tests__/list-messages-hidden-metadata.test.ts +55 -15
  181. package/src/__tests__/list-messages-page-latest.test.ts +60 -1
  182. package/src/__tests__/list-messages-tool-merge.test.ts +56 -6
  183. package/src/__tests__/llm-request-log-turn-query.test.ts +42 -86
  184. package/src/__tests__/llm-resolver.test.ts +23 -47
  185. package/src/__tests__/llm-usage-store.test.ts +268 -1
  186. package/src/__tests__/log-export-routes.test.ts +59 -0
  187. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -8
  188. package/src/__tests__/mcp-auth-routes.test.ts +15 -10
  189. package/src/__tests__/mcp-health-check.test.ts +18 -13
  190. package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
  191. package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
  192. package/src/__tests__/messaging-send-tool.test.ts +8 -4
  193. package/src/__tests__/migration-export-http.test.ts +12 -12
  194. package/src/__tests__/migration-import-commit-http.test.ts +8 -8
  195. package/src/__tests__/migration-import-preflight-http.test.ts +7 -7
  196. package/src/__tests__/migration-validate-http.test.ts +3 -3
  197. package/src/__tests__/native-web-search.test.ts +205 -20
  198. package/src/__tests__/notification-decision-identity.test.ts +9 -18
  199. package/src/__tests__/notification-decision-recipient-context.test.ts +3 -6
  200. package/src/__tests__/oauth-commands-routes.test.ts +1 -1
  201. package/src/__tests__/onboarding-template-contract.test.ts +12 -0
  202. package/src/__tests__/openai-image-service.test.ts +17 -0
  203. package/src/__tests__/openai-provider.test.ts +97 -71
  204. package/src/__tests__/openai-responses-provider.test.ts +21 -77
  205. package/src/__tests__/outbound-slack-persistence.test.ts +2 -1
  206. package/src/__tests__/{overflow-reduce-pipeline.test.ts → overflow-reduction-loop.test.ts} +64 -286
  207. package/src/__tests__/parallel-tool.benchmark.test.ts +24 -36
  208. package/src/__tests__/persist-unsendable-image.test.ts +215 -0
  209. package/src/__tests__/persistence-secret-redaction.test.ts +3 -1
  210. package/src/__tests__/pipeline-runner.test.ts +31 -43
  211. package/src/__tests__/pkb-autoinject.test.ts +2 -5
  212. package/src/__tests__/plugin-bootstrap.test.ts +62 -51
  213. package/src/__tests__/plugin-registry.test.ts +0 -27
  214. package/src/__tests__/plugin-route-contribution.test.ts +6 -16
  215. package/src/__tests__/plugin-skill-contribution.test.ts +7 -17
  216. package/src/__tests__/plugin-tool-contribution.test.ts +10 -26
  217. package/src/__tests__/plugin-types.test.ts +8 -173
  218. package/src/__tests__/prechat-onboarding-contract.test.ts +23 -0
  219. package/src/__tests__/process-message-background-slack.test.ts +17 -16
  220. package/src/__tests__/process-message-display-content.test.ts +36 -44
  221. package/src/__tests__/provider-commit-message-generator.test.ts +19 -14
  222. package/src/__tests__/provider-error-scenarios.test.ts +7 -6
  223. package/src/__tests__/provider-platform-proxy-integration.test.ts +3 -8
  224. package/src/__tests__/provider-send-message-override-profile.test.ts +9 -25
  225. package/src/__tests__/provider-streaming.benchmark.test.ts +12 -22
  226. package/src/__tests__/provider-usage-tracking.test.ts +0 -6
  227. package/src/__tests__/ratelimit.test.ts +9 -4
  228. package/src/__tests__/reaction-persistence.test.ts +1 -1
  229. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
  230. package/src/__tests__/relay-server.test.ts +20 -13
  231. package/src/__tests__/resolve-trust-class.test.ts +4 -4
  232. package/src/__tests__/retry-openrouter-only-normalization.test.ts +5 -8
  233. package/src/__tests__/retry-thinking-tool-choice.test.ts +10 -13
  234. package/src/__tests__/retry-verbosity-normalization.test.ts +5 -8
  235. package/src/__tests__/runtime-events-sse-reconnect.test.ts +390 -0
  236. package/src/__tests__/schedule-routes.test.ts +683 -12
  237. package/src/__tests__/schedule-store.test.ts +108 -0
  238. package/src/__tests__/schedule-tools.test.ts +160 -0
  239. package/src/__tests__/secret-ingress-http.test.ts +2 -2
  240. package/src/__tests__/secret-prompt-log-hygiene.test.ts +11 -7
  241. package/src/__tests__/secret-prompter-channel-fallback.test.ts +11 -9
  242. package/src/__tests__/secret-response-routing.test.ts +13 -11
  243. package/src/__tests__/send-endpoint-busy.test.ts +6 -2
  244. package/src/__tests__/server-history-render.test.ts +314 -1
  245. package/src/__tests__/shell-observability.test.ts +249 -0
  246. package/src/__tests__/skill-feature-flags-integration.test.ts +44 -11
  247. package/src/__tests__/skill-feature-flags.test.ts +6 -6
  248. package/src/__tests__/skill-load-feature-flag.test.ts +10 -10
  249. package/src/__tests__/skills-files-catalog-fallback.test.ts +10 -0
  250. package/src/__tests__/skillssh-files.test.ts +1 -0
  251. package/src/__tests__/starter-task-flow.test.ts +6 -6
  252. package/src/__tests__/strip-memory-injections.test.ts +102 -14
  253. package/src/__tests__/subagent-call-site-routing.test.ts +3 -3
  254. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  255. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  256. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  257. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  258. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  259. package/src/__tests__/suggestion-routes.test.ts +3 -3
  260. package/src/__tests__/sync-message-contract.test.ts +19 -16
  261. package/src/__tests__/system-prompt.test.ts +74 -0
  262. package/src/__tests__/task-scheduler.test.ts +162 -1
  263. package/src/__tests__/terminal-tools.test.ts +9 -25
  264. package/src/__tests__/thread-backfill.test.ts +4 -9
  265. package/src/__tests__/title-generate-hook.test.ts +319 -0
  266. package/src/__tests__/tool-error-hook.test.ts +278 -0
  267. package/src/__tests__/tool-preview-lifecycle.test.ts +481 -16
  268. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  269. package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
  270. package/src/__tests__/tool-result-truncation.test.ts +1 -1
  271. package/src/__tests__/tools-audio-read.test.ts +113 -0
  272. package/src/__tests__/turn-boundary-resolution.test.ts +44 -84
  273. package/src/__tests__/turn-events-store.test.ts +11 -7
  274. package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
  275. package/src/__tests__/ui-work-result-surface.test.ts +159 -0
  276. package/src/__tests__/usage-routes.test.ts +285 -1
  277. package/src/__tests__/user-plugin-loader.test.ts +2 -2
  278. package/src/__tests__/voice-scoped-grant-consumer.test.ts +8 -6
  279. package/src/__tests__/voice-session-bridge.test.ts +19 -10
  280. package/src/__tests__/web-search-backend-failure.test.ts +166 -0
  281. package/src/acp/__tests__/agent-process.test.ts +161 -0
  282. package/src/acp/__tests__/client-handler.test.ts +40 -0
  283. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  284. package/src/acp/__tests__/helpers/exec-file-stub.ts +101 -0
  285. package/src/acp/__tests__/prepare-agent-env.test.ts +143 -31
  286. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  287. package/src/acp/__tests__/session-manager-resume.test.ts +695 -0
  288. package/src/acp/agent-process.ts +61 -1
  289. package/src/acp/auto-install.test.ts +125 -0
  290. package/src/acp/auto-install.ts +174 -0
  291. package/src/acp/client-handler.ts +31 -0
  292. package/src/acp/feature-gate.test.ts +48 -0
  293. package/src/acp/feature-gate.ts +34 -0
  294. package/src/acp/prepare-agent-env.ts +52 -11
  295. package/src/acp/resolve-agent.test.ts +147 -6
  296. package/src/acp/resolve-agent.ts +81 -7
  297. package/src/acp/resume-hint.ts +22 -0
  298. package/src/acp/session-manager.ts +487 -71
  299. package/src/agent/compaction-circuit.ts +98 -0
  300. package/src/agent/loop.ts +651 -450
  301. package/src/api/README.md +19 -17
  302. package/src/api/constants/tool-execution.ts +21 -0
  303. package/src/api/events/assistant-activity-state.ts +75 -0
  304. package/src/api/events/assistant-outbound-attachment.ts +25 -27
  305. package/src/api/events/assistant-text-delta.ts +6 -8
  306. package/src/api/events/assistant-thinking-delta.ts +33 -0
  307. package/src/api/events/assistant-turn-start.ts +5 -7
  308. package/src/api/events/avatar-updated.ts +24 -0
  309. package/src/api/events/compaction-circuit-closed.ts +26 -0
  310. package/src/api/events/compaction-circuit-open.ts +28 -0
  311. package/src/api/events/confirmation-request.ts +114 -0
  312. package/src/api/events/contact-request.ts +33 -0
  313. package/src/api/events/conversation-error.ts +77 -0
  314. package/src/api/events/conversation-list-invalidated.ts +38 -0
  315. package/src/api/events/conversation-title-updated.ts +24 -0
  316. package/src/api/events/disk-pressure-status-changed.ts +61 -0
  317. package/src/api/events/document-comment-created.ts +24 -28
  318. package/src/api/events/document-comment-deleted.ts +6 -8
  319. package/src/api/events/document-comment-reopened.ts +6 -8
  320. package/src/api/events/document-comment-resolved.ts +8 -10
  321. package/src/api/events/document-editor-update.ts +27 -0
  322. package/src/api/events/error.ts +32 -0
  323. package/src/api/events/generation-cancelled.ts +4 -6
  324. package/src/api/events/generation-handoff.ts +13 -15
  325. package/src/api/events/home-feed-updated.ts +26 -0
  326. package/src/api/events/identity-changed.ts +32 -0
  327. package/src/api/events/interaction-resolved.ts +50 -0
  328. package/src/api/events/message-complete.ts +10 -12
  329. package/src/api/events/message-dequeued.ts +21 -0
  330. package/src/api/events/message-queued-deleted.ts +23 -0
  331. package/src/api/events/message-queued.ts +22 -0
  332. package/src/api/events/message-request-complete.ts +29 -0
  333. package/src/api/events/navigate-settings.ts +20 -0
  334. package/src/api/events/notification-intent.ts +33 -0
  335. package/src/api/events/open-url.ts +6 -8
  336. package/src/api/events/question-request.ts +67 -0
  337. package/src/api/events/relationship-state-updated.ts +4 -6
  338. package/src/api/events/secret-request.ts +42 -0
  339. package/src/api/events/subagent-event.ts +79 -0
  340. package/src/api/events/subagent-spawned.ts +40 -0
  341. package/src/api/events/subagent-status-changed.ts +65 -0
  342. package/src/api/events/sync-changed.ts +29 -0
  343. package/src/api/events/tool-output-chunk.ts +45 -0
  344. package/src/api/events/tool-result.ts +129 -0
  345. package/src/api/events/tool-use-preview-start.ts +32 -0
  346. package/src/api/events/tool-use-start.ts +8 -10
  347. package/src/api/events/trace-event.ts +69 -0
  348. package/src/api/events/turn-profile-auto-routed.ts +28 -0
  349. package/src/api/events/ui-surface-complete.ts +30 -0
  350. package/src/api/events/ui-surface-dismiss.ts +22 -0
  351. package/src/api/events/ui-surface-show.ts +67 -0
  352. package/src/api/events/ui-surface-update.ts +26 -0
  353. package/src/api/events/usage-update.ts +34 -0
  354. package/src/api/events/user-message-echo.ts +35 -0
  355. package/src/api/index.ts +389 -0
  356. package/src/api/requests/dictation.ts +45 -0
  357. package/src/api/responses/conversation-message.ts +374 -0
  358. package/src/api/responses/disk-pressure-status.ts +26 -0
  359. package/src/api/responses/home.ts +217 -0
  360. package/src/api/responses/llm-context-response.ts +2 -0
  361. package/src/api/responses/memory-v3-selection-log.ts +50 -0
  362. package/src/api/responses/subagent-detail.ts +48 -0
  363. package/src/approvals/guardian-decision-primitive.ts +7 -15
  364. package/src/approvals/guardian-request-resolvers.ts +7 -10
  365. package/src/avatar/__tests__/avatar-manifest.test.ts +236 -0
  366. package/src/avatar/__tests__/avatar-store.test.ts +198 -0
  367. package/src/avatar/avatar-manifest.ts +195 -0
  368. package/src/avatar/avatar-store.ts +113 -0
  369. package/src/avatar/traits-png-sync.ts +8 -2
  370. package/src/background-wake/next-wake.test.ts +31 -1
  371. package/src/background-wake/next-wake.ts +5 -1
  372. package/src/calls/call-conversation-messages.ts +6 -4
  373. package/src/calls/guardian-action-sweep.ts +6 -4
  374. package/src/calls/relay-server.ts +12 -8
  375. package/src/calls/voice-session-bridge.ts +13 -27
  376. package/src/cli/commands/__tests__/memory-v3.test.ts +245 -0
  377. package/src/cli/commands/__tests__/notifications.test.ts +58 -14
  378. package/src/cli/commands/avatar.ts +17 -11
  379. package/src/cli/commands/conversations.ts +15 -1
  380. package/src/cli/commands/db/__tests__/repair.test.ts +540 -0
  381. package/src/cli/commands/db/__tests__/status.test.ts +253 -0
  382. package/src/cli/commands/db/format.ts +48 -0
  383. package/src/cli/commands/db/index.ts +29 -0
  384. package/src/cli/commands/db/repair-step-conversation-backfill.ts +345 -0
  385. package/src/cli/commands/db/repair-step-integrity.ts +146 -0
  386. package/src/cli/commands/db/repair-steps.ts +164 -0
  387. package/src/cli/commands/db/repair.ts +141 -0
  388. package/src/cli/commands/db/status.ts +366 -0
  389. package/src/cli/commands/memory-v3.ts +159 -445
  390. package/src/cli/commands/notifications.ts +112 -60
  391. package/src/cli/lib/cli-colors.ts +24 -6
  392. package/src/cli/program.ts +4 -5
  393. package/src/config/__tests__/feature-flag-registry-guard.test.ts +4 -4
  394. package/src/config/acp-defaults.test.ts +10 -0
  395. package/src/config/acp-defaults.ts +6 -0
  396. package/src/config/assistant-feature-flags.ts +24 -13
  397. package/src/config/bundled-skills/acp/SKILL.md +64 -30
  398. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  399. package/src/config/bundled-skills/app-builder/SKILL.md +224 -387
  400. package/src/config/bundled-skills/app-builder/TOOLS.json +29 -0
  401. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  402. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  403. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  404. package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
  405. package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
  406. package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
  407. package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
  408. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  409. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  410. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  411. package/src/config/bundled-skills/media-processing/services/reduce.ts +6 -9
  412. package/src/config/bundled-skills/messaging/SKILL.md +0 -7
  413. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +7 -2
  414. package/src/config/bundled-skills/schedule/SKILL.md +1 -1
  415. package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
  416. package/src/config/bundled-tool-registry.ts +2 -0
  417. package/src/config/call-site-defaults.ts +2 -7
  418. package/src/config/feature-flag-cache.ts +3 -3
  419. package/src/config/feature-flag-registry.json +68 -12
  420. package/src/config/schemas/__tests__/memory-v2.test.ts +2 -226
  421. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
  422. package/src/config/schemas/call-site-catalog.ts +8 -15
  423. package/src/config/schemas/heartbeat.ts +9 -0
  424. package/src/config/schemas/llm.ts +3 -3
  425. package/src/config/schemas/memory-lifecycle.ts +24 -0
  426. package/src/config/schemas/memory-v2.ts +8 -253
  427. package/src/config/schemas/memory-v3.ts +47 -0
  428. package/src/config/schemas/memory.ts +6 -1
  429. package/src/config/schemas/platform.ts +8 -0
  430. package/src/config/schemas/timeouts.ts +3 -1
  431. package/src/config/seed-inference-profiles.ts +2 -2
  432. package/src/config/skills.ts +13 -0
  433. package/src/context/compactor.ts +55 -32
  434. package/src/context/strip-injections.ts +128 -0
  435. package/src/context/token-estimator.ts +42 -0
  436. package/src/context/tool-result-truncation.ts +1 -66
  437. package/src/context/window-manager.ts +141 -26
  438. package/src/credential-execution/executable-discovery.ts +16 -0
  439. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
  440. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +2 -2
  441. package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
  442. package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
  443. package/src/daemon/__tests__/web-search-status-text.test.ts +10 -6
  444. package/src/daemon/approval-generators.ts +4 -4
  445. package/src/daemon/assistant-attachments.ts +1 -1
  446. package/src/daemon/config-watcher.ts +7 -1
  447. package/src/daemon/context-overflow-reducer.ts +0 -1
  448. package/src/daemon/conversation-agent-loop-handlers.ts +793 -215
  449. package/src/daemon/conversation-agent-loop.ts +487 -1478
  450. package/src/daemon/conversation-error.ts +7 -7
  451. package/src/daemon/conversation-history.ts +27 -10
  452. package/src/daemon/conversation-launch.ts +4 -8
  453. package/src/daemon/conversation-lifecycle.ts +13 -42
  454. package/src/daemon/conversation-messaging.ts +8 -9
  455. package/src/daemon/conversation-notifiers.ts +7 -5
  456. package/src/daemon/conversation-process.ts +109 -93
  457. package/src/daemon/conversation-registry.ts +159 -0
  458. package/src/daemon/conversation-runtime-assembly.ts +209 -382
  459. package/src/daemon/conversation-slash.ts +6 -25
  460. package/src/daemon/conversation-store.ts +15 -95
  461. package/src/daemon/conversation-surfaces.ts +277 -73
  462. package/src/daemon/conversation-tool-setup.ts +5 -29
  463. package/src/daemon/conversation-workspace.ts +17 -0
  464. package/src/daemon/conversation.ts +123 -146
  465. package/src/daemon/daemon-skill-host.ts +2 -6
  466. package/src/daemon/disk-pressure-guard.ts +35 -29
  467. package/src/daemon/external-plugins-bootstrap.ts +53 -32
  468. package/src/daemon/first-greeting.ts +26 -4
  469. package/src/daemon/guardian-action-generators.ts +2 -2
  470. package/src/daemon/handlers/config-a2a.ts +51 -36
  471. package/src/daemon/handlers/config-slack-channel.ts +20 -14
  472. package/src/daemon/handlers/config-telegram.ts +16 -2
  473. package/src/daemon/handlers/conversations.ts +9 -23
  474. package/src/daemon/handlers/shared.ts +158 -82
  475. package/src/daemon/handlers/skills.ts +53 -20
  476. package/src/daemon/host-app-control-proxy.ts +54 -1
  477. package/src/daemon/host-cu-proxy.ts +46 -22
  478. package/src/daemon/host-file-proxy.ts +25 -1
  479. package/src/daemon/host-proxy-preactivation.ts +25 -6
  480. package/src/daemon/lifecycle.ts +53 -55
  481. package/src/daemon/message-protocol.ts +2 -3
  482. package/src/daemon/message-provenance.ts +49 -0
  483. package/src/daemon/message-types/apps.ts +1 -29
  484. package/src/daemon/message-types/contacts.ts +3 -20
  485. package/src/daemon/message-types/conversations.ts +13 -111
  486. package/src/daemon/message-types/documents.ts +3 -9
  487. package/src/daemon/message-types/home.ts +4 -17
  488. package/src/daemon/message-types/integrations.ts +2 -6
  489. package/src/daemon/message-types/messages.ts +37 -400
  490. package/src/daemon/message-types/notifications.ts +2 -32
  491. package/src/daemon/message-types/settings.ts +3 -8
  492. package/src/daemon/message-types/skills.ts +4 -0
  493. package/src/daemon/message-types/surfaces.ts +138 -3
  494. package/src/daemon/message-types/sync.ts +12 -25
  495. package/src/daemon/message-types/workspace.ts +3 -11
  496. package/src/daemon/now-scratchpad.ts +21 -0
  497. package/src/daemon/orphan-reaper.test.ts +210 -0
  498. package/src/daemon/orphan-reaper.ts +240 -0
  499. package/src/daemon/overflow-reduction-loop.ts +230 -0
  500. package/src/daemon/persist-unsendable-image.ts +117 -0
  501. package/src/daemon/process-message.ts +50 -49
  502. package/src/daemon/server.ts +14 -0
  503. package/src/daemon/tool-side-effects.ts +10 -7
  504. package/src/daemon/trace-emitter.ts +6 -4
  505. package/src/daemon/trust-context.ts +32 -0
  506. package/src/daemon/wake-target-adapter.ts +14 -2
  507. package/src/heartbeat/__tests__/heartbeat-service.test.ts +6 -1
  508. package/src/heartbeat/heartbeat-run-store.ts +54 -1
  509. package/src/heartbeat/heartbeat-service.ts +42 -0
  510. package/src/home/feed-types.ts +36 -221
  511. package/src/home/home-greeting-cache.ts +24 -1
  512. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  513. package/src/ipc/__tests__/email-ipc.test.ts +0 -9
  514. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  515. package/src/ipc/gateway-client.test.ts +2 -2
  516. package/src/ipc/gateway-client.ts +3 -3
  517. package/src/ipc/routes/__tests__/route-adapter.test.ts +244 -0
  518. package/src/ipc/routes/route-adapter.ts +45 -6
  519. package/src/ipc/skill-routes/__tests__/memory.test.ts +33 -9
  520. package/src/ipc/skill-routes/__tests__/providers.test.ts +10 -10
  521. package/src/ipc/skill-routes/__tests__/registries.test.ts +28 -18
  522. package/src/ipc/skill-routes/memory.ts +29 -14
  523. package/src/ipc/skill-routes/providers.ts +5 -6
  524. package/src/ipc/skill-routes/registries.ts +13 -61
  525. package/src/live-voice/__tests__/live-voice-archive.test.ts +24 -11
  526. package/src/media/gemini-image-service.ts +15 -0
  527. package/src/media/openai-image-service.ts +14 -0
  528. package/src/media/types.ts +34 -0
  529. package/src/memory/__tests__/conversation-queries.test.ts +192 -8
  530. package/src/memory/__tests__/db-maintenance.test.ts +128 -0
  531. package/src/memory/__tests__/jobs-store-job-classes.test.ts +5 -4
  532. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
  533. package/src/memory/__tests__/memory-retrospective-job.test.ts +10 -6
  534. package/src/memory/__tests__/memory-v3-selections-migration.test.ts +103 -0
  535. package/src/memory/auth-fallback-events-store.ts +94 -0
  536. package/src/memory/context-search/agent-runner.ts +2 -4
  537. package/src/memory/conversation-crud.ts +39 -8
  538. package/src/memory/conversation-queries.ts +78 -22
  539. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  540. package/src/memory/conversation-title-service.ts +65 -41
  541. package/src/memory/db-init.ts +14 -0
  542. package/src/memory/db-maintenance.ts +18 -2
  543. package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
  544. package/src/memory/graph/consolidation.ts +8 -11
  545. package/src/memory/graph/conversation-graph-memory.ts +106 -8
  546. package/src/memory/graph/extraction.ts +6 -9
  547. package/src/memory/graph/narrative.ts +2 -2
  548. package/src/memory/graph/pattern-scan.ts +2 -2
  549. package/src/memory/graph/retriever.ts +20 -26
  550. package/src/memory/graph/tools.ts +4 -4
  551. package/src/memory/job-handlers/conversation-starters.ts +45 -34
  552. package/src/memory/job-handlers/summarization.ts +1 -2
  553. package/src/memory/jobs-store.ts +36 -1
  554. package/src/memory/jobs-worker.ts +82 -43
  555. package/src/memory/llm-request-log-source-clickhouse.ts +5 -31
  556. package/src/memory/llm-request-log-source-local.ts +0 -11
  557. package/src/memory/llm-request-log-source.ts +9 -25
  558. package/src/memory/llm-request-log-store.ts +0 -41
  559. package/src/memory/llm-usage-store.ts +234 -50
  560. package/src/memory/memory-marker.ts +17 -0
  561. package/src/memory/memory-retrospective-job.ts +6 -2
  562. package/src/memory/memory-v2-activation-log-store.ts +1 -83
  563. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
  564. package/src/memory/migrations/267-llm-usage-events-add-assistant-version.ts +46 -0
  565. package/src/memory/migrations/268-add-memory-v3-selections.ts +28 -0
  566. package/src/memory/migrations/269-schedule-script-timeout.ts +11 -0
  567. package/src/memory/migrations/270-messages-role-created-at-index.ts +18 -0
  568. package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
  569. package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
  570. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  571. package/src/memory/migrations/__tests__/267-llm-usage-events-add-assistant-version.test.ts +117 -0
  572. package/src/memory/migrations/index.ts +7 -0
  573. package/src/memory/pkb/autoinject.ts +61 -0
  574. package/src/memory/pkb/context.ts +50 -0
  575. package/src/memory/pkb/types.ts +14 -0
  576. package/src/memory/schedule-attribution-sql.ts +104 -0
  577. package/src/memory/schema/acp.ts +4 -0
  578. package/src/memory/schema/infrastructure.ts +27 -0
  579. package/src/memory/usage-grouped-buckets.ts +6 -1
  580. package/src/memory/v2/__tests__/consolidation-job.test.ts +125 -1
  581. package/src/memory/v2/__tests__/migration.test.ts +11 -3
  582. package/src/memory/v2/__tests__/page-index.test.ts +37 -1
  583. package/src/memory/v2/__tests__/router.test.ts +14 -4
  584. package/src/memory/v2/__tests__/sweep-job.test.ts +6 -5
  585. package/src/memory/v2/backfill-jobs.ts +6 -0
  586. package/src/memory/v2/consolidation-job.ts +99 -10
  587. package/src/memory/v2/migration.ts +5 -3
  588. package/src/memory/v2/page-index.ts +11 -0
  589. package/src/memory/v2/router.ts +8 -11
  590. package/src/memory/v2/sweep-job.ts +8 -11
  591. package/src/memory/v2/types.ts +1 -0
  592. package/src/messaging/providers/slack/render-transcript.test.ts +1 -1
  593. package/src/messaging/providers/slack/render-transcript.ts +2 -2
  594. package/src/messaging/style-analyzer.ts +8 -11
  595. package/src/notifications/conversation-pairing.ts +8 -13
  596. package/src/notifications/decision-engine.ts +16 -16
  597. package/src/notifications/home-feed-side-effect.ts +12 -1
  598. package/src/notifications/preference-extractor.ts +11 -14
  599. package/src/permissions/prompter.ts +46 -36
  600. package/src/permissions/question-prompter.test.ts +35 -26
  601. package/src/permissions/question-prompter.ts +6 -10
  602. package/src/plugin-api/constants.ts +4 -0
  603. package/src/plugin-api/index.ts +10 -1
  604. package/src/plugin-api/types.ts +176 -4
  605. package/src/plugins/defaults/compaction/compact.ts +59 -0
  606. package/src/plugins/defaults/compaction/package.json +15 -0
  607. package/src/plugins/defaults/compaction/register.ts +24 -0
  608. package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
  609. package/src/plugins/defaults/empty-response/package.json +15 -0
  610. package/src/plugins/defaults/empty-response/register.ts +23 -0
  611. package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +35 -0
  612. package/src/plugins/defaults/history-repair/package.json +15 -0
  613. package/src/plugins/defaults/history-repair/register.ts +24 -0
  614. package/src/{daemon/history-repair.ts → plugins/defaults/history-repair/terminal.ts} +48 -35
  615. package/src/plugins/defaults/index.ts +22 -49
  616. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +95 -0
  617. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
  618. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
  619. package/src/plugins/defaults/{injectors.ts → memory-retrieval/injectors.ts} +295 -112
  620. package/src/plugins/defaults/memory-v3-shadow/__tests__/assign.test.ts +242 -0
  621. package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +118 -0
  622. package/src/plugins/defaults/memory-v3-shadow/__tests__/core.test.ts +39 -0
  623. package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/eval-turns.json +36 -0
  624. package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/live-turns.json +37 -0
  625. package/src/plugins/defaults/memory-v3-shadow/__tests__/health.test.ts +219 -0
  626. package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +330 -0
  627. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +288 -0
  628. package/src/plugins/defaults/memory-v3-shadow/__tests__/needle.test.ts +107 -0
  629. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +436 -0
  630. package/src/plugins/defaults/memory-v3-shadow/__tests__/provider-blocks.test.ts +13 -0
  631. package/src/plugins/defaults/memory-v3-shadow/__tests__/reconcile.test.ts +274 -0
  632. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +61 -0
  633. package/src/plugins/defaults/memory-v3-shadow/__tests__/router.test.ts +332 -0
  634. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +179 -0
  635. package/src/plugins/defaults/memory-v3-shadow/__tests__/selector.test.ts +470 -0
  636. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +432 -0
  637. package/src/plugins/defaults/memory-v3-shadow/__tests__/snapshot.test.ts +168 -0
  638. package/src/plugins/defaults/memory-v3-shadow/__tests__/tree.test.ts +192 -0
  639. package/src/plugins/defaults/memory-v3-shadow/__tests__/types.test.ts +54 -0
  640. package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-eviction.test.ts +106 -0
  641. package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-skeleton.test.ts +44 -0
  642. package/src/plugins/defaults/memory-v3-shadow/assign.ts +268 -0
  643. package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +124 -0
  644. package/src/plugins/defaults/memory-v3-shadow/core.ts +26 -0
  645. package/src/plugins/defaults/memory-v3-shadow/data/README.md +84 -0
  646. package/src/plugins/defaults/memory-v3-shadow/data/assignments.json +5 -0
  647. package/src/plugins/defaults/memory-v3-shadow/data/core.json +1 -0
  648. package/src/plugins/defaults/memory-v3-shadow/data/leaves/domain-a/topic-x.md +9 -0
  649. package/src/plugins/defaults/memory-v3-shadow/data/leaves/domain-a/topic-y.md +9 -0
  650. package/src/plugins/defaults/memory-v3-shadow/data/leaves/domain-b/topic-z.md +9 -0
  651. package/src/plugins/defaults/memory-v3-shadow/health.ts +0 -0
  652. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  653. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  654. package/src/plugins/defaults/memory-v3-shadow/injector.ts +75 -0
  655. package/src/plugins/defaults/memory-v3-shadow/llm-retry.ts +32 -0
  656. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +314 -0
  657. package/src/plugins/defaults/memory-v3-shadow/needle.ts +115 -0
  658. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +126 -0
  659. package/src/plugins/defaults/memory-v3-shadow/package.json +15 -0
  660. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +34 -0
  661. package/src/plugins/defaults/memory-v3-shadow/provider-blocks.ts +26 -0
  662. package/src/plugins/defaults/memory-v3-shadow/reconcile.ts +523 -0
  663. package/src/plugins/defaults/memory-v3-shadow/register.ts +26 -0
  664. package/src/plugins/defaults/memory-v3-shadow/render-injection.ts +32 -0
  665. package/src/plugins/defaults/memory-v3-shadow/router.ts +190 -0
  666. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +84 -0
  667. package/src/plugins/defaults/memory-v3-shadow/selector.ts +226 -0
  668. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +349 -0
  669. package/src/plugins/defaults/memory-v3-shadow/snapshot.ts +209 -0
  670. package/src/plugins/defaults/memory-v3-shadow/tree.ts +174 -0
  671. package/src/plugins/defaults/memory-v3-shadow/types.ts +59 -0
  672. package/src/plugins/defaults/memory-v3-shadow/working-set.ts +88 -0
  673. package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
  674. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
  675. package/src/plugins/defaults/title-generate/package.json +15 -0
  676. package/src/plugins/defaults/title-generate/register.ts +35 -0
  677. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
  678. package/src/plugins/defaults/tool-error/package.json +15 -0
  679. package/src/plugins/defaults/tool-error/register.ts +23 -0
  680. package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
  681. package/src/plugins/defaults/tool-result-truncate/package.json +15 -0
  682. package/src/plugins/defaults/tool-result-truncate/register.ts +24 -0
  683. package/src/plugins/defaults/tool-result-truncate/terminal.ts +132 -0
  684. package/src/plugins/external-plugin-loader.ts +2 -2
  685. package/src/plugins/pipeline.ts +8 -35
  686. package/src/plugins/registry.ts +8 -25
  687. package/src/plugins/types.ts +62 -721
  688. package/src/plugins/user-loader.ts +4 -3
  689. package/src/proactive-artifact/aux-message-injector.ts +4 -5
  690. package/src/proactive-artifact/job.test.ts +28 -21
  691. package/src/proactive-artifact/job.ts +3 -1
  692. package/src/prompts/__tests__/system-prompt.test.ts +42 -0
  693. package/src/prompts/sections.ts +20 -7
  694. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +64 -0
  695. package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +2 -2
  696. package/src/prompts/templates/BOOTSTRAP.md +7 -3
  697. package/src/prompts/templates/system-sections.ts +21 -0
  698. package/src/providers/__tests__/retry-callsite.test.ts +25 -25
  699. package/src/providers/__tests__/satellite-connection-routing.test.ts +7 -21
  700. package/src/providers/anthropic/client.ts +61 -34
  701. package/src/providers/call-site-routing.ts +1 -9
  702. package/src/providers/gemini/client.ts +152 -34
  703. package/src/providers/gemini/inline-media.ts +74 -0
  704. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -2
  705. package/src/providers/openai/chat-completions-provider.ts +45 -4
  706. package/src/providers/openai/responses-provider.ts +1 -4
  707. package/src/providers/openrouter/client.ts +2 -6
  708. package/src/providers/placeholder-sentinels.ts +35 -0
  709. package/src/providers/provider-send-message.ts +6 -6
  710. package/src/providers/ratelimit.ts +1 -9
  711. package/src/providers/retry.ts +0 -5
  712. package/src/providers/types.ts +11 -2
  713. package/src/providers/usage-tracking.ts +1 -9
  714. package/src/runtime/__tests__/agent-wake.test.ts +141 -32
  715. package/src/runtime/__tests__/background-job-runner.test.ts +1 -3
  716. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  717. package/src/runtime/agent-wake.ts +95 -23
  718. package/src/runtime/assistant-event-hub.ts +38 -8
  719. package/src/runtime/assistant-stream-state.ts +368 -0
  720. package/src/runtime/auth/__tests__/guard-tests.test.ts +75 -109
  721. package/src/runtime/auth/__tests__/route-policy.test.ts +153 -170
  722. package/src/runtime/auth/route-policy.ts +42 -1079
  723. package/src/runtime/background-job-runner.ts +1 -4
  724. package/src/runtime/btw-sidechain.ts +3 -1
  725. package/src/runtime/channel-approvals.ts +4 -15
  726. package/src/runtime/channel-invite-transport.ts +5 -6
  727. package/src/runtime/channel-readiness-service.ts +2 -5
  728. package/src/runtime/channel-retry-sweep.ts +12 -16
  729. package/src/runtime/http-router.ts +35 -43
  730. package/src/runtime/http-types.ts +23 -71
  731. package/src/runtime/interactive-ui.ts +1 -1
  732. package/src/runtime/invite-instruction-generator.ts +3 -3
  733. package/src/runtime/pending-interactions.ts +3 -2
  734. package/src/runtime/routes/__tests__/acp-routes.test.ts +253 -55
  735. package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +565 -0
  736. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
  737. package/src/runtime/routes/__tests__/content-source-routes.test.ts +4 -4
  738. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +62 -32
  739. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +237 -0
  740. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
  741. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -22
  742. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
  743. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +7 -2
  744. package/src/runtime/routes/__tests__/sanity-routes.test.ts +6 -6
  745. package/src/runtime/routes/__tests__/stt-routes.test.ts +3 -3
  746. package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +5 -2
  747. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  748. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  749. package/src/runtime/routes/__tests__/tts-routes.test.ts +9 -5
  750. package/src/runtime/routes/acp-routes.test.ts +186 -100
  751. package/src/runtime/routes/acp-routes.ts +110 -35
  752. package/src/runtime/routes/app-management-routes.ts +93 -131
  753. package/src/runtime/routes/app-routes.ts +38 -20
  754. package/src/runtime/routes/approval-routes.ts +17 -5
  755. package/src/runtime/routes/attachment-routes.ts +51 -16
  756. package/src/runtime/routes/audio-routes.ts +1 -0
  757. package/src/runtime/routes/audit-routes.ts +5 -0
  758. package/src/runtime/routes/auth-routes.ts +5 -0
  759. package/src/runtime/routes/avatar-routes.ts +264 -59
  760. package/src/runtime/routes/background-tool-routes.ts +9 -0
  761. package/src/runtime/routes/background-wake-routes.ts +13 -3
  762. package/src/runtime/routes/backup-routes.ts +45 -0
  763. package/src/runtime/routes/bookmark-routes.ts +13 -0
  764. package/src/runtime/routes/brain-graph-routes.ts +9 -0
  765. package/src/runtime/routes/browser-routes.ts +6 -1
  766. package/src/runtime/routes/browser-tabs-routes.ts +11 -10
  767. package/src/runtime/routes/btw-routes.ts +34 -24
  768. package/src/runtime/routes/cache-routes.ts +13 -0
  769. package/src/runtime/routes/call-routes.ts +21 -10
  770. package/src/runtime/routes/channel-availability-routes.ts +5 -1
  771. package/src/runtime/routes/channel-readiness-routes.ts +37 -4
  772. package/src/runtime/routes/channel-route-definitions.ts +21 -0
  773. package/src/runtime/routes/channel-verification-routes.ts +21 -0
  774. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +9 -2
  775. package/src/runtime/routes/client-routes.ts +9 -0
  776. package/src/runtime/routes/consolidation-routes.ts +133 -25
  777. package/src/runtime/routes/contact-prompt-routes.ts +9 -0
  778. package/src/runtime/routes/contact-routes.ts +90 -23
  779. package/src/runtime/routes/content-source-routes.ts +5 -1
  780. package/src/runtime/routes/conversation-analysis-routes.ts +5 -1
  781. package/src/runtime/routes/conversation-attention-routes.ts +5 -0
  782. package/src/runtime/routes/conversation-cli-routes.ts +54 -7
  783. package/src/runtime/routes/conversation-compaction-routes.ts +54 -25
  784. package/src/runtime/routes/conversation-list-routes.ts +81 -12
  785. package/src/runtime/routes/conversation-management-routes.ts +57 -14
  786. package/src/runtime/routes/conversation-query-routes.ts +90 -41
  787. package/src/runtime/routes/conversation-routes.ts +446 -204
  788. package/src/runtime/routes/conversation-starter-routes.ts +35 -20
  789. package/src/runtime/routes/conversations-import-routes.ts +30 -8
  790. package/src/runtime/routes/credential-prompt-routes.ts +5 -0
  791. package/src/runtime/routes/credential-routes.ts +25 -6
  792. package/src/runtime/routes/debug-bash-routes.ts +5 -0
  793. package/src/runtime/routes/debug-routes.ts +11 -2
  794. package/src/runtime/routes/defer-routes.ts +13 -0
  795. package/src/runtime/routes/diagnostics-routes.ts +37 -46
  796. package/src/runtime/routes/disk-pressure-routes.ts +17 -31
  797. package/src/runtime/routes/document-comments-routes.ts +46 -27
  798. package/src/runtime/routes/documents-routes.ts +25 -10
  799. package/src/runtime/routes/domain-routes.ts +98 -51
  800. package/src/runtime/routes/email-routes.ts +33 -0
  801. package/src/runtime/routes/epoch-millis-range.ts +34 -0
  802. package/src/runtime/routes/events-routes.ts +107 -8
  803. package/src/runtime/routes/filing-routes.ts +9 -4
  804. package/src/runtime/routes/gateway-log-routes.ts +31 -4
  805. package/src/runtime/routes/global-search-routes.ts +53 -50
  806. package/src/runtime/routes/group-routes.ts +21 -5
  807. package/src/runtime/routes/guardian-action-routes.ts +9 -0
  808. package/src/runtime/routes/guardian-approval-interception.ts +0 -31
  809. package/src/runtime/routes/heartbeat-routes.ts +57 -21
  810. package/src/runtime/routes/home-feed-routes.ts +23 -19
  811. package/src/runtime/routes/home-state-routes.ts +8 -40
  812. package/src/runtime/routes/host-app-control-routes.ts +6 -1
  813. package/src/runtime/routes/host-bash-routes.ts +5 -0
  814. package/src/runtime/routes/host-browser-routes.ts +13 -0
  815. package/src/runtime/routes/host-cu-routes.ts +6 -1
  816. package/src/runtime/routes/host-file-routes.ts +26 -6
  817. package/src/runtime/routes/host-transfer-routes.ts +13 -2
  818. package/src/runtime/routes/http-adapter.ts +1 -2
  819. package/src/runtime/routes/identity-intro-cache.ts +28 -40
  820. package/src/runtime/routes/identity-routes.ts +236 -20
  821. package/src/runtime/routes/image-generation-routes.ts +45 -2
  822. package/src/runtime/routes/inbound-message-handler.ts +16 -12
  823. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -12
  824. package/src/runtime/routes/inbound-stages/background-dispatch.ts +15 -19
  825. package/src/runtime/routes/index.ts +2 -0
  826. package/src/runtime/routes/inference-profile-session-routes.ts +13 -3
  827. package/src/runtime/routes/inference-provider-connection-routes.ts +21 -5
  828. package/src/runtime/routes/inference-send-routes.ts +11 -11
  829. package/src/runtime/routes/integrations/a2a.ts +32 -7
  830. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
  831. package/src/runtime/routes/integrations/slack/channel.ts +23 -3
  832. package/src/runtime/routes/integrations/slack/share.ts +36 -8
  833. package/src/runtime/routes/integrations/telegram.ts +34 -9
  834. package/src/runtime/routes/integrations/twilio.ts +77 -7
  835. package/src/runtime/routes/integrations/vercel.ts +3 -3
  836. package/src/runtime/routes/internal-oauth-routes.ts +5 -0
  837. package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
  838. package/src/runtime/routes/internal-twilio-routes.ts +13 -0
  839. package/src/runtime/routes/llm-call-sites-routes.ts +39 -4
  840. package/src/runtime/routes/log-export-routes.ts +36 -10
  841. package/src/runtime/routes/mcp-auth-routes.ts +25 -0
  842. package/src/runtime/routes/memory-item-routes.ts +21 -10
  843. package/src/runtime/routes/memory-v2-routes.ts +105 -44
  844. package/src/runtime/routes/memory-v3-routes.ts +306 -408
  845. package/src/runtime/routes/migration-rollback-routes.ts +5 -1
  846. package/src/runtime/routes/migration-routes.ts +29 -0
  847. package/src/runtime/routes/notification-routes.ts +17 -1
  848. package/src/runtime/routes/oauth-apps.ts +99 -23
  849. package/src/runtime/routes/oauth-commands-routes.ts +37 -14
  850. package/src/runtime/routes/oauth-connect-routes.ts +9 -0
  851. package/src/runtime/routes/oauth-lifecycle-routes.ts +5 -1
  852. package/src/runtime/routes/oauth-providers.ts +79 -15
  853. package/src/runtime/routes/platform-routes.ts +102 -5
  854. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +9 -6
  855. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +37 -16
  856. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +7 -3
  857. package/src/runtime/routes/playground/__tests__/state.test.ts +10 -3
  858. package/src/runtime/routes/playground/force-compact.ts +2 -2
  859. package/src/runtime/routes/playground/helpers.ts +1 -2
  860. package/src/runtime/routes/playground/inject-failures.ts +13 -8
  861. package/src/runtime/routes/playground/reset-circuit.ts +14 -9
  862. package/src/runtime/routes/playground/seed-conversation.ts +1 -1
  863. package/src/runtime/routes/playground/seeded-conversations.ts +3 -3
  864. package/src/runtime/routes/playground/state.ts +4 -3
  865. package/src/runtime/routes/plugins-routes.ts +22 -19
  866. package/src/runtime/routes/profiler-routes.ts +17 -4
  867. package/src/runtime/routes/ps-routes.ts +5 -0
  868. package/src/runtime/routes/publish-routes.ts +13 -3
  869. package/src/runtime/routes/question-routes.ts +5 -0
  870. package/src/runtime/routes/recording-routes.ts +25 -12
  871. package/src/runtime/routes/rename-conversation-routes.ts +10 -0
  872. package/src/runtime/routes/sanity-routes.ts +9 -2
  873. package/src/runtime/routes/schedule-routes.ts +288 -88
  874. package/src/runtime/routes/secret-routes.ts +31 -6
  875. package/src/runtime/routes/sequence-routes.ts +33 -0
  876. package/src/runtime/routes/settings-routes.ts +65 -19
  877. package/src/runtime/routes/skills-routes.ts +166 -73
  878. package/src/runtime/routes/slack-channel-routes.ts +5 -0
  879. package/src/runtime/routes/stt-routes.ts +13 -6
  880. package/src/runtime/routes/subagents-routes.ts +24 -18
  881. package/src/runtime/routes/suggest-trust-rule-routes.ts +7 -2
  882. package/src/runtime/routes/surface-action-routes.ts +9 -0
  883. package/src/runtime/routes/surface-content-routes.ts +10 -2
  884. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  885. package/src/runtime/routes/task-routes.ts +37 -0
  886. package/src/runtime/routes/telemetry-routes.ts +9 -0
  887. package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
  888. package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
  889. package/src/runtime/routes/trace-event-routes.ts +42 -1
  890. package/src/runtime/routes/trust-rules-routes.ts +31 -2
  891. package/src/runtime/routes/tts-routes.ts +48 -6
  892. package/src/runtime/routes/types.ts +83 -16
  893. package/src/runtime/routes/ui-request-routes.ts +5 -0
  894. package/src/runtime/routes/upgrade-broadcast-routes.ts +5 -0
  895. package/src/runtime/routes/usage-routes.ts +118 -42
  896. package/src/runtime/routes/user-routes-cli.ts +9 -0
  897. package/src/runtime/routes/user-routes.ts +5 -1
  898. package/src/runtime/routes/wake-conversation-routes.ts +5 -0
  899. package/src/runtime/routes/watcher-routes.ts +21 -0
  900. package/src/runtime/routes/webhook-routes.ts +50 -2
  901. package/src/runtime/routes/wipe-conversation-routes.ts +5 -0
  902. package/src/runtime/routes/work-items-routes.ts +49 -23
  903. package/src/runtime/routes/workspace-commit-routes.ts +5 -0
  904. package/src/runtime/routes/workspace-routes.test.ts +42 -0
  905. package/src/runtime/routes/workspace-routes.ts +124 -9
  906. package/src/runtime/services/__tests__/analyze-conversation.test.ts +8 -4
  907. package/src/runtime/services/analyze-conversation.ts +5 -8
  908. package/src/runtime/services/conversation-serializer.ts +24 -2
  909. package/src/runtime/sync/resource-sync-events.ts +16 -2
  910. package/src/runtime/sync/sync-publisher.ts +2 -2
  911. package/src/schedule/run-script.ts +28 -3
  912. package/src/schedule/schedule-store.ts +28 -1
  913. package/src/schedule/schedule-usage-store.ts +83 -0
  914. package/src/schedule/scheduler.ts +15 -6
  915. package/src/signals/cancel.ts +2 -4
  916. package/src/signals/user-message.ts +5 -8
  917. package/src/skills/catalog-files.ts +4 -1
  918. package/src/skills/catalog-install.ts +3 -0
  919. package/src/skills/categories-cache.ts +118 -0
  920. package/src/skills/clawhub-files.ts +1 -0
  921. package/src/skills/skillssh-files.ts +1 -0
  922. package/src/subagent/manager.ts +20 -11
  923. package/src/telemetry/types.ts +55 -1
  924. package/src/telemetry/usage-telemetry-reporter.test.ts +250 -4
  925. package/src/telemetry/usage-telemetry-reporter.ts +88 -2
  926. package/src/tools/acp/context.ts +20 -0
  927. package/src/tools/acp/list-agents.test.ts +7 -1
  928. package/src/tools/acp/spawn.test.ts +198 -93
  929. package/src/tools/acp/spawn.ts +32 -70
  930. package/src/tools/acp/steer.test.ts +105 -8
  931. package/src/tools/acp/steer.ts +48 -17
  932. package/src/tools/apps/definitions.ts +8 -4
  933. package/src/tools/apps/executors.ts +13 -8
  934. package/src/tools/ask-question/ask-question-tool.test.ts +120 -105
  935. package/src/tools/ask-question/ask-question-tool.ts +85 -90
  936. package/src/tools/computer-use/definitions.ts +28 -24
  937. package/src/tools/credential-execution/make-authenticated-request.ts +56 -51
  938. package/src/tools/credential-execution/manage-secure-command-tool.ts +2 -2
  939. package/src/tools/credential-execution/run-authenticated-command.ts +82 -77
  940. package/src/tools/credentials/vault.ts +112 -111
  941. package/src/tools/execution-target.ts +1 -1
  942. package/src/tools/execution-timeout.ts +3 -4
  943. package/src/tools/executor.ts +1 -53
  944. package/src/tools/filesystem/edit.ts +45 -42
  945. package/src/tools/filesystem/list.ts +33 -30
  946. package/src/tools/filesystem/read.ts +54 -35
  947. package/src/tools/filesystem/write.ts +69 -32
  948. package/src/tools/host-filesystem/edit.ts +44 -42
  949. package/src/tools/host-filesystem/read.ts +49 -35
  950. package/src/tools/host-filesystem/transfer.ts +121 -108
  951. package/src/tools/host-filesystem/write.ts +33 -31
  952. package/src/tools/host-terminal/host-shell.ts +50 -48
  953. package/src/tools/memory/register.ts +23 -24
  954. package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
  955. package/src/tools/network/__tests__/web-search.test.ts +11 -3
  956. package/src/tools/network/web-fetch.ts +49 -46
  957. package/src/tools/network/web-search-error.test.ts +248 -0
  958. package/src/tools/network/web-search-error.ts +267 -0
  959. package/src/tools/network/web-search.ts +223 -61
  960. package/src/tools/registry.ts +39 -16
  961. package/src/tools/schedule/create.ts +13 -0
  962. package/src/tools/schedule/update.ts +16 -0
  963. package/src/tools/shared/filesystem/audio-read.ts +122 -0
  964. package/src/tools/shared/filesystem/image-read.ts +1 -1
  965. package/src/tools/skills/execute.ts +34 -31
  966. package/src/tools/skills/load.ts +29 -23
  967. package/src/tools/subagent/notify-parent.ts +35 -32
  968. package/src/tools/subagent/spawn.ts +2 -4
  969. package/src/tools/system/avatar-generator.ts +13 -22
  970. package/src/tools/system/request-permission.ts +30 -27
  971. package/src/tools/terminal/safe-env.ts +10 -1
  972. package/src/tools/terminal/shell.ts +190 -61
  973. package/src/tools/tool-defaults.ts +20 -9
  974. package/src/tools/tool-manifest.ts +4 -4
  975. package/src/tools/types.ts +74 -23
  976. package/src/tools/ui-surface/definitions.ts +99 -10
  977. package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
  978. package/src/tts/provider-catalog.ts +76 -1
  979. package/src/usage/types.ts +10 -0
  980. package/src/util/errors.ts +2 -2
  981. package/src/util/map-limit.ts +27 -0
  982. package/src/util/mutex.ts +47 -0
  983. package/src/util/platform.ts +15 -12
  984. package/src/work-items/work-item-runner.ts +7 -2
  985. package/src/workspace/git-service.ts +1 -42
  986. package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +7 -20
  987. package/src/workspace/migrations/092-backfill-v3-leaves.ts +169 -0
  988. package/src/workspace/migrations/093-backfill-leaf-ids.ts +144 -0
  989. package/src/workspace/migrations/094-seed-avatar-manifest.ts +155 -0
  990. package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
  991. package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
  992. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +117 -0
  993. package/src/workspace/migrations/__tests__/094-seed-avatar-manifest.test.ts +136 -0
  994. package/src/workspace/migrations/__tests__/backfill-leaf-ids.test.ts +175 -0
  995. package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +124 -0
  996. package/src/workspace/migrations/registry.ts +12 -0
  997. package/src/workspace/provider-commit-message-generator.ts +15 -17
  998. package/tsconfig.json +4 -1
  999. package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
  1000. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  1001. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  1002. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -262
  1003. package/src/__tests__/empty-response-pipeline.test.ts +0 -301
  1004. package/src/__tests__/history-repair-pipeline.test.ts +0 -396
  1005. package/src/__tests__/llm-call-pipeline.test.ts +0 -281
  1006. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
  1007. package/src/__tests__/persistence-pipeline.test.ts +0 -514
  1008. package/src/__tests__/title-generate-pipeline.test.ts +0 -211
  1009. package/src/__tests__/token-estimate-pipeline.test.ts +0 -481
  1010. package/src/__tests__/tool-error-pipeline.test.ts +0 -241
  1011. package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
  1012. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -344
  1013. package/src/cli/commands/__tests__/memory-v3-render.test.ts +0 -340
  1014. package/src/cli/commands/memory-v3-render.ts +0 -491
  1015. package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
  1016. package/src/daemon/message-types/disk-pressure.ts +0 -9
  1017. package/src/email/feature-gate.ts +0 -23
  1018. package/src/gallery/default-gallery.ts +0 -1359
  1019. package/src/gallery/gallery-manifest.ts +0 -28
  1020. package/src/memory/v3/__tests__/coactivation-store.test.ts +0 -422
  1021. package/src/memory/v3/__tests__/consolidation-job.test.ts +0 -466
  1022. package/src/memory/v3/__tests__/coretrieval-seed.test.ts +0 -270
  1023. package/src/memory/v3/__tests__/edge-learning-job.test.ts +0 -324
  1024. package/src/memory/v3/__tests__/edges.test.ts +0 -706
  1025. package/src/memory/v3/__tests__/filter.test.ts +0 -560
  1026. package/src/memory/v3/__tests__/gate.test.ts +0 -637
  1027. package/src/memory/v3/__tests__/index-composition.test.ts +0 -291
  1028. package/src/memory/v3/__tests__/loop.test.ts +0 -775
  1029. package/src/memory/v3/__tests__/retriever.test.ts +0 -226
  1030. package/src/memory/v3/__tests__/scouts.test.ts +0 -489
  1031. package/src/memory/v3/__tests__/shadow-diff.test.ts +0 -225
  1032. package/src/memory/v3/__tests__/shadow-middleware.test.ts +0 -398
  1033. package/src/memory/v3/__tests__/system-prompts.test.ts +0 -154
  1034. package/src/memory/v3/__tests__/traversal.test.ts +0 -508
  1035. package/src/memory/v3/__tests__/tree-index.test.ts +0 -280
  1036. package/src/memory/v3/__tests__/tree-store.test.ts +0 -529
  1037. package/src/memory/v3/__tests__/tree-walk.test.ts +0 -784
  1038. package/src/memory/v3/__tests__/validate.test.ts +0 -277
  1039. package/src/memory/v3/auto-edges.ts +0 -223
  1040. package/src/memory/v3/coactivation-store.ts +0 -124
  1041. package/src/memory/v3/consolidation-job.ts +0 -323
  1042. package/src/memory/v3/coretrieval-seed.ts +0 -240
  1043. package/src/memory/v3/edge-learning-job.ts +0 -160
  1044. package/src/memory/v3/edges.ts +0 -286
  1045. package/src/memory/v3/filter.ts +0 -286
  1046. package/src/memory/v3/gate.ts +0 -349
  1047. package/src/memory/v3/index-composition.ts +0 -126
  1048. package/src/memory/v3/llm-capture.ts +0 -46
  1049. package/src/memory/v3/loop.ts +0 -430
  1050. package/src/memory/v3/maintenance.ts +0 -144
  1051. package/src/memory/v3/prompt-context.ts +0 -33
  1052. package/src/memory/v3/prompts/consolidation.ts +0 -458
  1053. package/src/memory/v3/prompts/system-prompts.ts +0 -196
  1054. package/src/memory/v3/retriever.ts +0 -33
  1055. package/src/memory/v3/scouts.ts +0 -431
  1056. package/src/memory/v3/shadow-diff.ts +0 -287
  1057. package/src/memory/v3/shadow-middleware.ts +0 -347
  1058. package/src/memory/v3/traversal.ts +0 -211
  1059. package/src/memory/v3/tree-index.ts +0 -237
  1060. package/src/memory/v3/tree-store.ts +0 -394
  1061. package/src/memory/v3/tree-walk.ts +0 -356
  1062. package/src/memory/v3/types.ts +0 -65
  1063. package/src/memory/v3/validate.ts +0 -323
  1064. package/src/plugins/defaults/circuit-breaker.ts +0 -141
  1065. package/src/plugins/defaults/compaction.ts +0 -141
  1066. package/src/plugins/defaults/empty-response.ts +0 -124
  1067. package/src/plugins/defaults/history-repair.ts +0 -83
  1068. package/src/plugins/defaults/llm-call.ts +0 -77
  1069. package/src/plugins/defaults/memory-retrieval.ts +0 -219
  1070. package/src/plugins/defaults/overflow-reduce.ts +0 -185
  1071. package/src/plugins/defaults/persistence.ts +0 -146
  1072. package/src/plugins/defaults/title-generate.ts +0 -90
  1073. package/src/plugins/defaults/token-estimate.ts +0 -101
  1074. package/src/plugins/defaults/tool-error.ts +0 -119
  1075. package/src/plugins/defaults/tool-execute.ts +0 -87
  1076. package/src/plugins/defaults/tool-result-truncate.ts +0 -84
  1077. package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +0 -35
  1078. package/src/skills/category-inference.ts +0 -111
@@ -10,6 +10,7 @@ import {
10
10
  createAssistantMessage,
11
11
  createUserMessage,
12
12
  } from "../../agent/message-types.js";
13
+ import { ConversationMessageSchema } from "../../api/responses/conversation-message.js";
13
14
  import {
14
15
  CHANNEL_IDS,
15
16
  INTERFACE_IDS,
@@ -18,6 +19,7 @@ import {
18
19
  parseInterfaceId,
19
20
  supportsHostProxy,
20
21
  } from "../../channels/types.js";
22
+ import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
21
23
  import { isHttpAuthDisabled } from "../../config/env.js";
22
24
  import { getConfig } from "../../config/loader.js";
23
25
  import {
@@ -41,10 +43,15 @@ import { getOrCreateConversation as getOrCreateConversationInstance } from "../.
41
43
  import { canonicalizeTimeZone } from "../../daemon/date-context.js";
42
44
  import {
43
45
  buildScanFirstMessage,
46
+ buildSelfIntroMessage,
44
47
  getCannedFirstGreeting,
45
48
  isWakeUpGreeting,
46
49
  } from "../../daemon/first-greeting.js";
47
- import { renderHistoryContent } from "../../daemon/handlers/shared.js";
50
+ import {
51
+ collectAttachmentRefs,
52
+ type HistoryAttachmentRef,
53
+ renderHistoryContent,
54
+ } from "../../daemon/handlers/shared.js";
48
55
  import { HostAppControlProxy } from "../../daemon/host-app-control-proxy.js";
49
56
  import { HostCuProxy } from "../../daemon/host-cu-proxy.js";
50
57
  import {
@@ -103,10 +110,15 @@ import type { Provider } from "../../providers/types.js";
103
110
  import { checkIngressForSecrets } from "../../security/secret-ingress.js";
104
111
  import { getSubagentManager } from "../../subagent/index.js";
105
112
  import { getLogger } from "../../util/logger.js";
106
- import { getWorkspacePromptPath } from "../../util/platform.js";
113
+ import {
114
+ getWorkspaceDir,
115
+ getWorkspacePromptPath,
116
+ } from "../../util/platform.js";
107
117
  import { silentlyWithLog } from "../../util/silently.js";
108
118
  import { assistantEventHub, broadcastMessage } from "../assistant-event-hub.js";
109
119
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
120
+ import { getPersistedSeq } from "../assistant-stream-state.js";
121
+ import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
110
122
  import { routeGuardianReply } from "../guardian-reply-router.js";
111
123
  import { healGuardianBindingDrift } from "../guardian-vellum-migration.js";
112
124
  import type {
@@ -131,6 +143,10 @@ import {
131
143
  NotFoundError,
132
144
  RouteError,
133
145
  } from "./errors.js";
146
+ import {
147
+ collectPendingConfirmations,
148
+ enrichToolCallsWithConfirmation,
149
+ } from "./tool-call-confirmation-enrichment.js";
134
150
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
135
151
  import { RouteResponse } from "./types.js";
136
152
 
@@ -140,6 +156,128 @@ const log = getLogger("conversation-routes");
140
156
  const NO_RESPONSE_INLINE_RE = /<no_response\s*\/?>/g;
141
157
  const ATTACHMENT_ENTRY_RE = /^attachment:(\d+)$/;
142
158
 
159
+ /** Rewrites a rendered `contentOrder` to reflect attachment alignment. */
160
+ type ContentOrderRewrite = (contentOrder: string[]) => string[];
161
+
162
+ interface AlignedAttachments {
163
+ /** Hydrated rows, reordered to match the inline file-block order. */
164
+ attachments: RuntimeAttachmentMetadata[];
165
+ /**
166
+ * Resolves a content-walk attachment ref index to its hydrated DB row,
167
+ * mirroring the inline placement `rewriteContentOrder` encodes. Refs with no
168
+ * inline placement (unmatched ids, count mismatch, no DB rows) are absent, so
169
+ * `renderHistoryContent` emits no `attachment` block for them — the row still
170
+ * ships via the flat `attachments` array.
171
+ */
172
+ refIndexToAttachment: Map<number, RuntimeAttachmentMetadata>;
173
+ rewriteContentOrder: ContentOrderRewrite;
174
+ }
175
+
176
+ /**
177
+ * Align DB-hydrated attachment rows with the file-block refs `renderHistoryContent`
178
+ * captured. When a file block was persisted with `_attachmentId` (user-message
179
+ * uploads) we join on that id to position the chip inline; DB rows without a
180
+ * matching ref go to the tail as orphan chips, and unmatched refs drop their
181
+ * `attachment:N` entry. Assistant-authored file blocks carry no `_attachmentId`,
182
+ * so when no ids match we fall back to positional alignment if the ref and row
183
+ * counts agree; otherwise we strip the markers and let chips fall to the tail.
184
+ */
185
+ function alignAttachments(
186
+ attachmentRefs: HistoryAttachmentRef[],
187
+ attachments: RuntimeAttachmentMetadata[],
188
+ ): AlignedAttachments {
189
+ const refIndexToAttachment = new Map<number, RuntimeAttachmentMetadata>();
190
+ const identity: ContentOrderRewrite = (contentOrder) => contentOrder;
191
+ const stripAttachmentEntries: ContentOrderRewrite = (contentOrder) =>
192
+ contentOrder.filter((entry) => !ATTACHMENT_ENTRY_RE.test(entry));
193
+
194
+ if (attachmentRefs.length === 0) {
195
+ return { attachments, refIndexToAttachment, rewriteContentOrder: identity };
196
+ }
197
+ if (attachments.length === 0) {
198
+ // Refs were captured but no DB rows came back — drop the contentOrder
199
+ // entries to avoid out-of-bounds renders.
200
+ return {
201
+ attachments,
202
+ refIndexToAttachment,
203
+ rewriteContentOrder: stripAttachmentEntries,
204
+ };
205
+ }
206
+
207
+ const byId = new Map<string, number>();
208
+ attachments.forEach((att, idx) => {
209
+ if (att.id) byId.set(att.id, idx);
210
+ });
211
+ const consumed = new Set<number>();
212
+ const orderedRowIdx: Array<number | null> = attachmentRefs.map((ref) => {
213
+ if (!ref.attachmentId) return null;
214
+ const idx = byId.get(ref.attachmentId);
215
+ if (idx === undefined || consumed.has(idx)) return null;
216
+ consumed.add(idx);
217
+ return idx;
218
+ });
219
+ const matchedRows = orderedRowIdx.filter(
220
+ (idx): idx is number => idx !== null,
221
+ );
222
+
223
+ if (matchedRows.length > 0) {
224
+ const orphanRows: number[] = [];
225
+ for (let i = 0; i < attachments.length; i++) {
226
+ if (!consumed.has(i)) orphanRows.push(i);
227
+ }
228
+ const reordered = [
229
+ ...matchedRows.map((i) => attachments[i]),
230
+ ...orphanRows.map((i) => attachments[i]),
231
+ ];
232
+ const refToNewIdx = new Map<number, number>();
233
+ let nextIdx = 0;
234
+ orderedRowIdx.forEach((rowIdx, refIdx) => {
235
+ if (rowIdx !== null) {
236
+ refToNewIdx.set(refIdx, nextIdx);
237
+ refIndexToAttachment.set(refIdx, reordered[nextIdx]);
238
+ nextIdx++;
239
+ }
240
+ });
241
+ const rewriteContentOrder: ContentOrderRewrite = (contentOrder) =>
242
+ contentOrder
243
+ .map((entry) => {
244
+ const match = entry.match(ATTACHMENT_ENTRY_RE);
245
+ if (!match) return entry;
246
+ const remapped = refToNewIdx.get(Number(match[1]));
247
+ return remapped !== undefined ? `attachment:${remapped}` : undefined;
248
+ })
249
+ .filter((e): e is string => e !== undefined);
250
+ return {
251
+ attachments: reordered,
252
+ refIndexToAttachment,
253
+ rewriteContentOrder,
254
+ };
255
+ }
256
+
257
+ if (attachmentRefs.length !== attachments.length) {
258
+ // No ref carried an attachmentId we could match and the counts disagree, so
259
+ // positional mapping can't be trusted — strip any attachment:N entries so
260
+ // the client doesn't position attachments inline against a misaligned array
261
+ // (they fall to the tail instead).
262
+ return {
263
+ attachments,
264
+ refIndexToAttachment,
265
+ rewriteContentOrder: stripAttachmentEntries,
266
+ };
267
+ }
268
+
269
+ // No ref matched an id but the counts agree (the assistant-authored case):
270
+ // the Nth marker maps to the Nth row positionally, so the original
271
+ // contentOrder is left untouched.
272
+ attachmentRefs.forEach((_ref, refIdx) => {
273
+ refIndexToAttachment.set(refIdx, attachments[refIdx]);
274
+ });
275
+ return { attachments, refIndexToAttachment, rewriteContentOrder: identity };
276
+ }
277
+
278
+ /** Feature flag gating the self-intro first message (see first-greeting.ts). */
279
+ const SELF_INTRO_GREETING_FLAG = "self-intro-greeting" as const;
280
+
143
281
  const SUGGESTION_CACHE_MAX = 100;
144
282
  const VALID_RISK_THRESHOLDS = ["none", "low", "medium", "high"] as const;
145
283
  type RiskThreshold = (typeof VALID_RISK_THRESHOLDS)[number];
@@ -409,7 +547,7 @@ async function tryConsumeCanonicalGuardianReply(params: {
409
547
  conversationId,
410
548
  "user",
411
549
  JSON.stringify(cleanUserMessage.content),
412
- channelMeta,
550
+ { metadata: channelMeta },
413
551
  );
414
552
  messageId = persistedUser.id;
415
553
 
@@ -423,7 +561,7 @@ async function tryConsumeCanonicalGuardianReply(params: {
423
561
  conversationId,
424
562
  "assistant",
425
563
  JSON.stringify(assistantMessage.content),
426
- channelMeta,
564
+ { metadata: channelMeta },
427
565
  );
428
566
 
429
567
  // Avoid mutating in-memory history / emitting stream deltas while a run is active.
@@ -503,6 +641,7 @@ export function handleListMessages({
503
641
  hasMore: false,
504
642
  oldestTimestamp: null,
505
643
  oldestMessageId: null,
644
+ seq: null,
506
645
  };
507
646
  }
508
647
  return { messages: [] };
@@ -541,7 +680,14 @@ export function handleListMessages({
541
680
  // assistant message has tool_use blocks but its matching user tool_result
542
681
  // is left visible, the result will render as a standalone orphan because
543
682
  // `mergeToolResultsIntoAssistantMessages` has nothing to merge it into.
544
- const visibleFilter = (m: MessageRow) => !isHiddenMessage(m.metadata);
683
+ //
684
+ // Only renderable roles reach this UI-facing transcript. `system` rows (a
685
+ // permitted `MessageRole`, e.g. skill-authored context) are agent-context
686
+ // scaffolding, never a displayed turn, so they are dropped here at the
687
+ // source rather than narrowed away per-client.
688
+ const visibleFilter = (m: MessageRow) =>
689
+ !isHiddenMessage(m.metadata) &&
690
+ (m.role === "user" || m.role === "assistant");
545
691
 
546
692
  if (isPaginated) {
547
693
  const result = getMessagesPaginated(
@@ -575,7 +721,10 @@ export function handleListMessages({
575
721
  mergeConsecutiveAssistantMessages(mergedMessages);
576
722
  const assistantSlackDisplayName = getAssistantName()?.trim() || undefined;
577
723
 
578
- // Parse content blocks and extract text + tool calls
724
+ // Parse each row's stored content and per-message metadata. Rendering is
725
+ // deferred to the serializer pass below so it runs after attachment
726
+ // alignment, letting renderHistoryContent inline `attachment` blocks during
727
+ // its single content walk.
579
728
  const parsed = consolidatedMessages.map((msg) => {
580
729
  let content: unknown;
581
730
  try {
@@ -583,7 +732,6 @@ export function handleListMessages({
583
732
  } catch {
584
733
  content = msg.content;
585
734
  }
586
- const rendered = renderHistoryContent(content);
587
735
 
588
736
  // Extract sentAt from metadata for display timestamps. When a message
589
737
  // was queued or its persistence was delayed (long assistant generation),
@@ -631,94 +779,51 @@ export function handleListMessages({
631
779
  },
632
780
  );
633
781
 
634
- // Strip <no_response/> markers from assistant messages so web/API
635
- // clients never see the raw sentinel. Only assistant messages produce
636
- // this marker; user messages are left untouched.
637
- if (msg.role === "assistant") {
638
- const originalSegments = rendered.textSegments;
639
- const keepIndices: number[] = [];
640
- const filteredSegments: string[] = [];
641
- for (let i = 0; i < originalSegments.length; i++) {
642
- const cleaned = originalSegments[i]
643
- .replace(NO_RESPONSE_INLINE_RE, "")
644
- .trim();
645
- if (cleaned.length > 0) {
646
- keepIndices.push(i);
647
- filteredSegments.push(cleaned);
648
- }
649
- }
650
- // Remap contentOrder text:N indices to account for removed segments
651
- const indexMap = new Map<number, number>();
652
- keepIndices.forEach((oldIdx, newIdx) => indexMap.set(oldIdx, newIdx));
653
- const filteredContentOrder = rendered.contentOrder
654
- .map((entry) => {
655
- const m = entry.match(/^text:(\d+)$/);
656
- if (!m) return entry;
657
- const newIdx = indexMap.get(Number(m[1]));
658
- return newIdx !== undefined ? `text:${newIdx}` : undefined;
659
- })
660
- .filter((e): e is string => e !== undefined);
661
-
662
- return {
663
- role: msg.role,
664
- text: rendered.text.replace(NO_RESPONSE_INLINE_RE, "").trim(),
665
- timestamp: msg.createdAt,
666
- sentAt,
667
- toolCalls: rendered.toolCalls,
668
- toolCallsBeforeText: rendered.toolCallsBeforeText,
669
- textSegments: filteredSegments,
670
- contentOrder: filteredContentOrder,
671
- surfaces: rendered.surfaces,
672
- attachmentRefs: rendered.attachments,
673
- slackMessage,
674
- ...(rendered.thinkingSegments.length > 0
675
- ? { thinkingSegments: rendered.thinkingSegments }
676
- : {}),
677
- id: msg.id,
678
- subagentNotification,
679
- };
680
- }
782
+ // `visibleFilter` has already dropped every non-renderable role, so the
783
+ // only values reaching here are `user` and `assistant`; narrow the raw DB
784
+ // `string` to the wire union.
785
+ const role: "user" | "assistant" =
786
+ msg.role === "assistant" ? "assistant" : "user";
681
787
 
682
788
  return {
683
- role: msg.role,
684
- text: rendered.text,
685
- timestamp: msg.createdAt,
686
- sentAt,
687
- toolCalls: rendered.toolCalls,
688
- toolCallsBeforeText: rendered.toolCallsBeforeText,
689
- textSegments: rendered.textSegments,
690
- contentOrder: rendered.contentOrder,
691
- surfaces: rendered.surfaces,
692
- attachmentRefs: rendered.attachments,
693
- slackMessage,
694
- ...(rendered.thinkingSegments.length > 0
695
- ? { thinkingSegments: rendered.thinkingSegments }
696
- : {}),
697
789
  id: msg.id,
790
+ role,
791
+ content,
792
+ createdAt: msg.createdAt,
793
+ sentAt,
698
794
  subagentNotification,
795
+ slackMessage,
699
796
  };
700
797
  });
701
798
 
799
+ // Confirmation context layered onto rendered tool calls at render time: the
800
+ // derived scope ladder for scope-aware tools, and any in-flight prompt read
801
+ // from the pending-interactions registry. Both are computed once per request
802
+ // and applied per message below.
803
+ const workspaceDir = getWorkspaceDir();
804
+ const pendingConfirmations = collectPendingConfirmations(
805
+ resolvedConversationId,
806
+ );
807
+
702
808
  const messages: RuntimeMessagePayload[] = parsed.map((m) => {
809
+ const mergedMessageIds = m.id ? (mergedIdMap.get(m.id) ?? []) : [];
810
+
811
+ // Hydrate the row's attachments from the DB. A metadata-only query avoids
812
+ // loading large base64 blobs for non-image attachments (documents, audio);
813
+ // full data is fetched only for images so the client can generate
814
+ // thumbnails for inline display on history restore. Merged messages
815
+ // (consecutive assistant merge) are queried too so their attachments
816
+ // aren't lost before DB compaction relinks them.
703
817
  let msgAttachments: RuntimeAttachmentMetadata[] = [];
704
818
  if (m.id) {
705
- // Use metadata-only query first to avoid loading large base64
706
- // blobs for non-image attachments (documents, audio). Then
707
- // selectively fetch full data only for images so the client can
708
- // generate thumbnails for inline display on history restore.
709
- // Also query attachments for any messages that were merged into
710
- // this one (consecutive assistant merge), so their attachments
711
- // aren't lost before DB compaction relinks them.
712
- const idsToQuery = [m.id, ...(mergedIdMap.get(m.id) ?? [])];
819
+ const idsToQuery = [m.id, ...mergedMessageIds];
713
820
  const linked = idsToQuery.flatMap((id) =>
714
821
  getAttachmentMetadataForMessage(id),
715
822
  );
716
823
  if (linked.length > 0) {
717
824
  msgAttachments = linked.map((a) => {
718
825
  if (a.mimeType.startsWith("image/")) {
719
- const full = getAttachmentById(a.id, {
720
- hydrateFileData: true,
721
- });
826
+ const full = getAttachmentById(a.id, { hydrateFileData: true });
722
827
  return {
723
828
  id: a.id,
724
829
  filename: a.originalFilename,
@@ -745,107 +850,101 @@ export function handleListMessages({
745
850
  }
746
851
  }
747
852
 
748
- // Align msgAttachments order with the file-block order captured by
749
- // renderHistoryContent. When a file block was persisted with
750
- // `_attachmentId` (user-message uploads), we join on that id to position
751
- // the chip inline (the `attachment:N` entries in contentOrder index into
752
- // msgAttachments). DB rows without a matching ref go to the tail as orphan
753
- // chips; unmatched refs drop their contentOrder entry and trigger a remap.
754
- // Assistant-authored file blocks carry no `_attachmentId`, so when no ids
755
- // match we fall back to positional alignment if the ref and row counts
756
- // agree; otherwise we strip the markers and let chips fall to the tail.
757
- let alignedContentOrder = m.contentOrder;
758
- if (
759
- m.attachmentRefs.length > 0 &&
760
- msgAttachments.length > 0 &&
761
- m.contentOrder.length > 0
762
- ) {
763
- const byId = new Map<string, number>();
764
- msgAttachments.forEach((att, idx) => {
765
- if (att.id) byId.set(att.id, idx);
766
- });
767
- const consumed = new Set<number>();
768
- const orderedRowIdx: Array<number | null> = m.attachmentRefs.map(
769
- (ref) => {
770
- if (!ref.attachmentId) return null;
771
- const idx = byId.get(ref.attachmentId);
772
- if (idx === undefined || consumed.has(idx)) return null;
773
- consumed.add(idx);
774
- return idx;
775
- },
776
- );
777
- const matchedRows = orderedRowIdx.filter(
778
- (idx): idx is number => idx !== null,
779
- );
780
- if (matchedRows.length > 0) {
781
- const orphanRows: number[] = [];
782
- for (let i = 0; i < msgAttachments.length; i++) {
783
- if (!consumed.has(i)) orphanRows.push(i);
853
+ // Align the hydrated rows with the file-block refs, then render. Rendering
854
+ // after alignment lets renderHistoryContent inline each `attachment` block
855
+ // during its single content walk, so `contentBlocks` comes back ready to
856
+ // ship with no post-processing. The aligned reorder/rewrite keeps the
857
+ // legacy `attachments` array and `contentOrder` positions consistent.
858
+ const attachmentRefs = collectAttachmentRefs(m.content);
859
+ const aligned = alignAttachments(attachmentRefs, msgAttachments);
860
+ msgAttachments = aligned.attachments;
861
+ const attachmentBlocks = attachmentRefs.map(
862
+ (_ref, refIdx) => aligned.refIndexToAttachment.get(refIdx) ?? null,
863
+ );
864
+ const rendered = renderHistoryContent(
865
+ m.content,
866
+ attachmentBlocks,
867
+ m.id ?? undefined,
868
+ );
869
+
870
+ const toolCalls = enrichToolCallsWithConfirmation(rendered.toolCalls, {
871
+ workspaceDir,
872
+ pendingConfirmations,
873
+ });
874
+
875
+ // Strip <no_response/> markers from assistant messages so web/API clients
876
+ // never see the raw sentinel. Only assistant messages produce it; user
877
+ // messages are untouched. The filter is applied consistently to the flat
878
+ // text, the segments, the contentOrder text refs, and the text blocks of
879
+ // contentBlocks.
880
+ let text = rendered.text;
881
+ let textSegments = rendered.textSegments;
882
+ let contentOrder = rendered.contentOrder;
883
+ let contentBlocks = rendered.contentBlocks;
884
+ if (m.role === "assistant") {
885
+ const keepIndices: number[] = [];
886
+ const filteredSegments: string[] = [];
887
+ for (let i = 0; i < rendered.textSegments.length; i++) {
888
+ const cleaned = rendered.textSegments[i]
889
+ .replace(NO_RESPONSE_INLINE_RE, "")
890
+ .trim();
891
+ if (cleaned.length > 0) {
892
+ keepIndices.push(i);
893
+ filteredSegments.push(cleaned);
784
894
  }
785
- msgAttachments = [
786
- ...matchedRows.map((i) => msgAttachments[i]),
787
- ...orphanRows.map((i) => msgAttachments[i]),
788
- ];
789
- const refToNewIdx = new Map<number, number>();
790
- let nextIdx = 0;
791
- orderedRowIdx.forEach((rowIdx, refIdx) => {
792
- if (rowIdx !== null) {
793
- refToNewIdx.set(refIdx, nextIdx);
794
- nextIdx++;
795
- }
796
- });
797
- alignedContentOrder = m.contentOrder
798
- .map((entry) => {
799
- const match = entry.match(ATTACHMENT_ENTRY_RE);
800
- if (!match) return entry;
801
- const remapped = refToNewIdx.get(Number(match[1]));
802
- return remapped !== undefined
803
- ? `attachment:${remapped}`
804
- : undefined;
805
- })
806
- .filter((e): e is string => e !== undefined);
807
- } else if (m.attachmentRefs.length !== msgAttachments.length) {
808
- // No ref carried an attachmentId we could match and the counts
809
- // disagree, so positional mapping can't be trusted — strip any
810
- // attachment:N entries so the client doesn't position attachments
811
- // inline against a misaligned array (they fall to the tail instead).
812
- alignedContentOrder = m.contentOrder.filter(
813
- (entry) => !ATTACHMENT_ENTRY_RE.test(entry),
814
- );
815
895
  }
816
- // Otherwise no ref matched an id but the counts agree (the
817
- // assistant-authored case): the Nth marker maps to the Nth row
818
- // positionally, so the original contentOrder is left untouched.
819
- } else if (m.attachmentRefs.length > 0 && msgAttachments.length === 0) {
820
- // Refs were captured but no DB rows came back — drop the
821
- // contentOrder entries to avoid out-of-bounds renders.
822
- alignedContentOrder = m.contentOrder.filter(
823
- (entry) => !ATTACHMENT_ENTRY_RE.test(entry),
824
- );
896
+ const indexMap = new Map<number, number>();
897
+ keepIndices.forEach((oldIdx, newIdx) => indexMap.set(oldIdx, newIdx));
898
+ contentOrder = rendered.contentOrder
899
+ .map((entry) => {
900
+ const tm = entry.match(/^text:(\d+)$/);
901
+ if (!tm) return entry;
902
+ const newIdx = indexMap.get(Number(tm[1]));
903
+ return newIdx !== undefined ? `text:${newIdx}` : undefined;
904
+ })
905
+ .filter((e): e is string => e !== undefined);
906
+ textSegments = filteredSegments;
907
+ text = rendered.text.replace(NO_RESPONSE_INLINE_RE, "").trim();
908
+ contentBlocks = rendered.contentBlocks
909
+ .map((block) =>
910
+ block.type === "text"
911
+ ? {
912
+ type: "text" as const,
913
+ text: block.text.replace(NO_RESPONSE_INLINE_RE, "").trim(),
914
+ }
915
+ : block,
916
+ )
917
+ .filter((block) => block.type !== "text" || block.text.length > 0);
825
918
  }
826
919
 
827
- // Use sentAt (actual event time) for the display timestamp when
828
- // available, falling back to createdAt (persistence time).
829
- // Note: clients use this display timestamp as their pagination cursor
830
- // after memory-pressure trimming, while server-side pagination filters
831
- // on createdAt. The mismatch is benign it may return slightly extra
832
- // data on a page boundary but never loses messages.
833
- const displayTimestamp = m.sentAt ?? m.timestamp;
920
+ const alignedContentOrder = aligned.rewriteContentOrder(contentOrder);
921
+
922
+ // Use sentAt (actual event time) for the display timestamp when available,
923
+ // falling back to createdAt (persistence time). Clients use this display
924
+ // timestamp as their pagination cursor after memory-pressure trimming,
925
+ // while server-side pagination filters on createdAt. The mismatch is
926
+ // benign it may return slightly extra data on a page boundary but never
927
+ // loses messages.
928
+ const displayTimestamp = m.sentAt ?? m.createdAt;
834
929
  return {
835
930
  id: m.id ?? "",
931
+ ...(mergedMessageIds.length > 0 ? { mergedMessageIds } : {}),
836
932
  role: m.role,
837
- content: m.text,
933
+ // Flat plain-text body the legacy Swift client reads directly; see the
934
+ // `content` field on ConversationMessageSchema for why this must stay.
935
+ content: text,
838
936
  timestamp: new Date(displayTimestamp).toISOString(),
839
937
  attachments: msgAttachments,
840
- ...(m.toolCalls.length > 0 ? { toolCalls: m.toolCalls } : {}),
841
- ...(m.surfaces.length > 0 ? { surfaces: m.surfaces } : {}),
842
- ...(m.textSegments.length > 0 ? { textSegments: m.textSegments } : {}),
843
- ...(m.thinkingSegments?.length
844
- ? { thinkingSegments: m.thinkingSegments }
938
+ ...(toolCalls.length > 0 ? { toolCalls } : {}),
939
+ ...(rendered.surfaces.length > 0 ? { surfaces: rendered.surfaces } : {}),
940
+ ...(textSegments.length > 0 ? { textSegments } : {}),
941
+ ...(rendered.thinkingSegments.length > 0
942
+ ? { thinkingSegments: rendered.thinkingSegments }
845
943
  : {}),
846
944
  ...(alignedContentOrder.length > 0
847
945
  ? { contentOrder: alignedContentOrder }
848
946
  : {}),
947
+ ...(contentBlocks.length > 0 ? { contentBlocks } : {}),
849
948
  ...(m.subagentNotification
850
949
  ? { subagentNotification: m.subagentNotification }
851
950
  : {}),
@@ -853,6 +952,13 @@ export function handleListMessages({
853
952
  };
854
953
  });
855
954
 
955
+ // Snapshot↔stream alignment token: the `seq` of the last event whose
956
+ // content is durably persisted for this conversation in the current
957
+ // daemon process. Returned on every resolved-conversation response so a
958
+ // client can apply only stream events with a higher `seq`. Null when
959
+ // nothing has been persisted in-process (cold/aged-out/post-restart).
960
+ const persistedSeq = getPersistedSeq(resolvedConversationId);
961
+
856
962
  if (isPaginated) {
857
963
  // Prefer the page's oldest visible row (the documented cursor semantic).
858
964
  // When a scan-cap-truncated page comes back empty there's no visible row
@@ -874,6 +980,7 @@ export function handleListMessages({
874
980
  hasMore,
875
981
  oldestTimestamp: oldestTimestamp ?? null,
876
982
  oldestMessageId: oldestMessageId ?? null,
983
+ seq: persistedSeq,
877
984
  };
878
985
  }
879
986
 
@@ -882,10 +989,11 @@ export function handleListMessages({
882
989
  hasMore,
883
990
  ...(oldestTimestamp != null ? { oldestTimestamp } : {}),
884
991
  ...(oldestMessageId != null ? { oldestMessageId } : {}),
992
+ seq: persistedSeq,
885
993
  };
886
994
  }
887
995
 
888
- return { messages };
996
+ return { messages, seq: persistedSeq };
889
997
  }
890
998
 
891
999
  /**
@@ -1330,10 +1438,20 @@ export async function handleSendMessage(
1330
1438
  }
1331
1439
 
1332
1440
  const isInteractive = isInteractiveInterface(sourceInterface);
1441
+ // Use the JWT-verified requester principal — not guardianPrincipalId,
1442
+ // which is the workspace owner and would let a trusted contact's web
1443
+ // turn match against the guardian's macOS client.
1444
+ const sourceActorPrincipalId = actorPrincipalId ?? undefined;
1333
1445
  // Bash/File/Transfer singletons are globally available via isAvailable() —
1334
1446
  // no per-conversation gating needed. CU is per-conversation (owns step
1335
1447
  // count, AX tree history, loop detection).
1336
- if (shouldAttachHostProxyForCapability("host_cu", sourceInterface)) {
1448
+ if (
1449
+ shouldAttachHostProxyForCapability(
1450
+ "host_cu",
1451
+ sourceInterface,
1452
+ sourceActorPrincipalId,
1453
+ )
1454
+ ) {
1337
1455
  if (!conversation.isProcessing() || !conversation.hostCuProxy) {
1338
1456
  conversation.setHostCuProxy(new HostCuProxy());
1339
1457
  }
@@ -1346,7 +1464,13 @@ export async function handleSendMessage(
1346
1464
  // lives in the skill-projection layer (which reads the `feature-flag:
1347
1465
  // app-control` declaration in SKILL.md frontmatter), so an attached proxy
1348
1466
  // is harmless when the flag resolves to off.
1349
- if (shouldAttachHostProxyForCapability("host_app_control", sourceInterface)) {
1467
+ if (
1468
+ shouldAttachHostProxyForCapability(
1469
+ "host_app_control",
1470
+ sourceInterface,
1471
+ sourceActorPrincipalId,
1472
+ )
1473
+ ) {
1350
1474
  if (!conversation.isProcessing() || !conversation.hostAppControlProxy) {
1351
1475
  conversation.setHostAppControlProxy(
1352
1476
  new HostAppControlProxy(mapping.conversationId),
@@ -1359,7 +1483,11 @@ export async function handleSendMessage(
1359
1483
  // this message will be queued and preactivation is deferred to dequeue
1360
1484
  // time in drainQueueImpl to avoid mutating in-flight turn state.
1361
1485
  if (!conversation.isProcessing()) {
1362
- preactivateHostProxySkills(conversation, sourceInterface);
1486
+ preactivateHostProxySkills(
1487
+ conversation,
1488
+ sourceInterface,
1489
+ sourceActorPrincipalId,
1490
+ );
1363
1491
  }
1364
1492
  // Wire sendToClient to the SSE hub so all subsystems can reach the HTTP client.
1365
1493
  // hasNoClient must remain `!isInteractive` so downstream tool gating
@@ -1392,6 +1520,16 @@ export async function handleSendMessage(
1392
1520
  conversation.getMessages().length,
1393
1521
  );
1394
1522
  const isScanPath = !!scanUrl && isWakeUp;
1523
+ // Self-intro path: when we know a name, send a natural introduction on the
1524
+ // user's behalf instead of the canned greeting, so the assistant generates a
1525
+ // real first response. Gated behind the `self-intro-greeting` flag (default
1526
+ // off); `undefined` (flag off or no names) falls back to the canned path.
1527
+ const selfIntroGreetingEnabled =
1528
+ isWakeUp &&
1529
+ isAssistantFeatureFlagEnabled(SELF_INTRO_GREETING_FLAG, getConfig());
1530
+ const selfIntro = selfIntroGreetingEnabled
1531
+ ? buildSelfIntroMessage(body.onboarding ?? undefined)
1532
+ : undefined;
1395
1533
 
1396
1534
  let effectiveContent: string | undefined;
1397
1535
  if (isScanPath) {
@@ -1400,12 +1538,16 @@ export async function handleSendMessage(
1400
1538
  : ("content-source" as const);
1401
1539
  effectiveContent = buildScanFirstMessage(scanUrl, scanVariant);
1402
1540
  // Fall through to normal inference path below
1403
- } else if (isWakeUp && body.onboarding?.initialMessage) {
1541
+ } else if (selfIntroGreetingEnabled && body.onboarding?.initialMessage) {
1404
1542
  effectiveContent = body.onboarding.initialMessage;
1543
+ } else if (isWakeUp && selfIntro) {
1544
+ // Rewrite to the self-introduction and fall through to real inference
1545
+ // (mirrors the scan path above).
1546
+ effectiveContent = selfIntro;
1405
1547
  } else if (isWakeUp) {
1406
1548
  const cannedGreeting = getCannedFirstGreeting(body.onboarding ?? undefined);
1407
1549
 
1408
- conversation.processing = true;
1550
+ conversation.setProcessing(true);
1409
1551
  let cleanupDeferred = false;
1410
1552
  try {
1411
1553
  const rawContent = content ?? "";
@@ -1435,7 +1577,7 @@ export async function handleSendMessage(
1435
1577
  mapping.conversationId,
1436
1578
  "assistant",
1437
1579
  JSON.stringify(assistantMsg.content),
1438
- channelMeta,
1580
+ { metadata: channelMeta },
1439
1581
  );
1440
1582
  conversation.getMessages().push(assistantMsg);
1441
1583
 
@@ -1481,7 +1623,7 @@ export async function handleSendMessage(
1481
1623
  persistedAssistant.id,
1482
1624
  );
1483
1625
  publishConversationMessagesChanged(conversationId, originClientId);
1484
- conversation.processing = false;
1626
+ conversation.setProcessing(false);
1485
1627
  silentlyWithLog(
1486
1628
  conversation.drainQueue(),
1487
1629
  "canned-greeting queue drain",
@@ -1497,8 +1639,8 @@ export async function handleSendMessage(
1497
1639
  cleanupDeferred = true;
1498
1640
  return response;
1499
1641
  } finally {
1500
- if (!cleanupDeferred && conversation.processing) {
1501
- conversation.processing = false;
1642
+ if (!cleanupDeferred && conversation.isProcessing()) {
1643
+ conversation.setProcessing(false);
1502
1644
  silentlyWithLog(conversation.drainQueue(), "error-path queue drain");
1503
1645
  }
1504
1646
  }
@@ -1711,7 +1853,7 @@ export async function handleSendMessage(
1711
1853
  const slashResult = await resolveSlash(rawContent, slashContext);
1712
1854
 
1713
1855
  if (slashResult.kind === "unknown") {
1714
- conversation.processing = true;
1856
+ conversation.setProcessing(true);
1715
1857
  let cleanupDeferred = false;
1716
1858
  try {
1717
1859
  const slashMeta = {
@@ -1744,7 +1886,7 @@ export async function handleSendMessage(
1744
1886
  mapping.conversationId,
1745
1887
  "assistant",
1746
1888
  JSON.stringify(assistantMsg.content),
1747
- channelMeta,
1889
+ { metadata: channelMeta },
1748
1890
  );
1749
1891
  conversation.getMessages().push(assistantMsg);
1750
1892
 
@@ -1792,7 +1934,7 @@ export async function handleSendMessage(
1792
1934
  persistedAssistant.id,
1793
1935
  );
1794
1936
  publishConversationMessagesChanged(conversationId, originClientId);
1795
- conversation.processing = false;
1937
+ conversation.setProcessing(false);
1796
1938
  silentlyWithLog(conversation.drainQueue(), "slash-command queue drain");
1797
1939
  }, 0);
1798
1940
 
@@ -1801,15 +1943,15 @@ export async function handleSendMessage(
1801
1943
  } finally {
1802
1944
  // No-op for the slash-command early-return path (handled inside
1803
1945
  // setTimeout above), but still needed for error paths.
1804
- if (!cleanupDeferred && conversation.processing) {
1805
- conversation.processing = false;
1946
+ if (!cleanupDeferred && conversation.isProcessing()) {
1947
+ conversation.setProcessing(false);
1806
1948
  silentlyWithLog(conversation.drainQueue(), "error-path queue drain");
1807
1949
  }
1808
1950
  }
1809
1951
  }
1810
1952
 
1811
1953
  if (slashResult.kind === "compact") {
1812
- conversation.processing = true;
1954
+ conversation.setProcessing(true);
1813
1955
  const slashMeta = {
1814
1956
  userMessageChannel: sourceChannel,
1815
1957
  assistantMessageChannel: sourceChannel,
@@ -1829,12 +1971,12 @@ export async function handleSendMessage(
1829
1971
  // The fire-and-forget compaction below owns clearing `processing`, but a
1830
1972
  // throw from this initial persist never reaches it — reset here so the
1831
1973
  // conversation isn't stranded in queued mode.
1832
- conversation.processing = false;
1974
+ conversation.setProcessing(false);
1833
1975
  silentlyWithLog(conversation.drainQueue(), "compact-command queue drain");
1834
1976
  throw err;
1835
1977
  }
1836
1978
  if (persisted.deduplicated) {
1837
- conversation.processing = false;
1979
+ conversation.setProcessing(false);
1838
1980
  silentlyWithLog(conversation.drainQueue(), "compact-dedup queue drain");
1839
1981
  return {
1840
1982
  accepted: true,
@@ -1862,14 +2004,8 @@ export async function handleSendMessage(
1862
2004
  clientMessageId,
1863
2005
  });
1864
2006
  publishConversationMessagesChanged(conversationId, originClientId);
1865
- conversation.emitActivityState(
1866
- "thinking",
1867
- "context_compacting",
1868
- "assistant_turn",
1869
- );
1870
- const result = await conversation.forceCompact({
1871
- targetInputTokensOverride: slashResult.targetInputTokensOverride,
1872
- });
2007
+ conversation.emitActivityState("thinking", "context_compacting");
2008
+ const result = await conversation.forceCompact();
1873
2009
  const responseText = formatCompactResult(result);
1874
2010
 
1875
2011
  const assistantMsg = createAssistantMessage(responseText);
@@ -1877,7 +2013,7 @@ export async function handleSendMessage(
1877
2013
  conversationId,
1878
2014
  "assistant",
1879
2015
  JSON.stringify(assistantMsg.content),
1880
- channelMeta,
2016
+ { metadata: channelMeta },
1881
2017
  );
1882
2018
  assistantMessagePersisted = true;
1883
2019
  conversation.getMessages().push(assistantMsg);
@@ -1906,7 +2042,7 @@ export async function handleSendMessage(
1906
2042
  retryable: true,
1907
2043
  });
1908
2044
  } finally {
1909
- conversation.processing = false;
2045
+ conversation.setProcessing(false);
1910
2046
  silentlyWithLog(
1911
2047
  conversation.drainQueue(),
1912
2048
  "compact-command queue drain",
@@ -1922,7 +2058,7 @@ export async function handleSendMessage(
1922
2058
  }
1923
2059
 
1924
2060
  if (slashResult.kind === "clean") {
1925
- conversation.processing = true;
2061
+ conversation.setProcessing(true);
1926
2062
  const conversationId = mapping.conversationId;
1927
2063
  // Outer try/finally guarantees the processing flag is cleared (and the
1928
2064
  // queue drained) on every failure path — including a throw from the
@@ -1972,7 +2108,7 @@ export async function handleSendMessage(
1972
2108
  conversationId,
1973
2109
  "assistant",
1974
2110
  JSON.stringify(assistantMsg.content),
1975
- channelMeta,
2111
+ { metadata: channelMeta },
1976
2112
  );
1977
2113
  assistantMessagePersisted = true;
1978
2114
  conversation.getMessages().push(assistantMsg);
@@ -2008,7 +2144,7 @@ export async function handleSendMessage(
2008
2144
  conversationId,
2009
2145
  };
2010
2146
  } finally {
2011
- conversation.processing = false;
2147
+ conversation.setProcessing(false);
2012
2148
  silentlyWithLog(conversation.drainQueue(), "clean-command queue drain");
2013
2149
  }
2014
2150
  }
@@ -2046,7 +2182,8 @@ export async function handleSendMessage(
2046
2182
 
2047
2183
  // Fire-and-forget the agent loop; events flow to the hub via broadcastMessage.
2048
2184
  conversation
2049
- .runAgentLoop(resolvedContent, messageId, broadcastMessage, {
2185
+ .runAgentLoop(resolvedContent, messageId, {
2186
+ onEvent: broadcastMessage,
2050
2187
  isInteractive,
2051
2188
  isUserMessage: true,
2052
2189
  })
@@ -2124,9 +2261,10 @@ async function generateLlmSuggestion(
2124
2261
  // tokens here would be wasteful.
2125
2262
  const response = await provider.sendMessage(
2126
2263
  [{ role: "user", content: [{ type: "text", text: userPrompt }] }],
2127
- [], // no tools
2128
- systemPrompt,
2129
2264
  {
2265
+ tools: [],
2266
+ // no tools
2267
+ systemPrompt,
2130
2268
  config: {
2131
2269
  callSite: "replySuggestion",
2132
2270
  max_tokens: 60,
@@ -2418,12 +2556,54 @@ export const ROUTES: RouteDefinition[] = [
2418
2556
  operationId: "messages_get",
2419
2557
  endpoint: "messages",
2420
2558
  method: "GET",
2559
+ policy: {
2560
+ requiredScopes: ["chat.read"],
2561
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
2562
+ },
2421
2563
  summary: "List messages",
2422
2564
  description:
2423
2565
  "Return messages for a conversation, including attachments and interface file metadata.",
2424
2566
  tags: ["messages"],
2567
+ queryParams: [
2568
+ {
2569
+ name: "conversationId",
2570
+ type: "string",
2571
+ required: false,
2572
+ description:
2573
+ "Conversation UUID. One of conversationId or conversationKey is required.",
2574
+ },
2575
+ {
2576
+ name: "conversationKey",
2577
+ type: "string",
2578
+ required: false,
2579
+ description:
2580
+ "Channel/external conversation key. One of conversationId or conversationKey is required.",
2581
+ },
2582
+ {
2583
+ name: "page",
2584
+ type: "string",
2585
+ required: false,
2586
+ description:
2587
+ "When set to 'latest', returns the most recent page of messages with pagination metadata.",
2588
+ },
2589
+ {
2590
+ name: "beforeTimestamp",
2591
+ type: "integer",
2592
+ required: false,
2593
+ description:
2594
+ "Return messages older than this timestamp (ms since epoch). Used for paging older history.",
2595
+ },
2596
+ {
2597
+ name: "limit",
2598
+ type: "integer",
2599
+ required: false,
2600
+ description: "Maximum number of messages to return.",
2601
+ },
2602
+ ],
2425
2603
  responseBody: z.object({
2426
- messages: z.array(z.unknown()).describe("Array of message objects"),
2604
+ messages: z
2605
+ .array(ConversationMessageSchema)
2606
+ .describe("Array of message objects"),
2427
2607
  hasMore: z
2428
2608
  .boolean()
2429
2609
  .optional()
@@ -2440,6 +2620,13 @@ export const ROUTES: RouteDefinition[] = [
2440
2620
  .nullable()
2441
2621
  .optional()
2442
2622
  .describe("ID of the oldest message in this page"),
2623
+ seq: z
2624
+ .number()
2625
+ .nullable()
2626
+ .optional()
2627
+ .describe(
2628
+ "Global SSE `seq` of the last event whose content is durably persisted for this conversation in the current daemon process. A client can align this snapshot with the `/events` stream by applying only events with `seq` greater than this value. Null when no events have been persisted in this process (cold conversation, after a daemon restart, or when the conversation has aged out of the in-memory map) — clients should cold-start in that case. Absent on older daemons that predate this field.",
2629
+ ),
2443
2630
  }),
2444
2631
  handler: (args) => handleListMessages(args),
2445
2632
  },
@@ -2447,23 +2634,70 @@ export const ROUTES: RouteDefinition[] = [
2447
2634
  operationId: "messages_post",
2448
2635
  endpoint: "messages",
2449
2636
  method: "POST",
2637
+ policy: {
2638
+ requiredScopes: ["chat.write"],
2639
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
2640
+ },
2450
2641
  summary: "Send a message",
2451
2642
  description:
2452
2643
  "Send a user message to a conversation and trigger the assistant response.",
2453
2644
  tags: ["messages"],
2454
2645
  responseStatus: "202",
2455
2646
  requestBody: z.object({
2456
- conversationKey: z.string().optional(),
2647
+ conversationId: z
2648
+ .string()
2649
+ .nullable()
2650
+ .optional()
2651
+ .describe(
2652
+ "Internal conversation id (0.8.6+ strict lookup). Omit both id and key to mint a new conversation server-side.",
2653
+ ),
2654
+ conversationKey: z.string().nullable().optional(),
2457
2655
  content: z.string().describe("Message text content"),
2458
2656
  attachments: z
2459
2657
  .array(z.unknown())
2460
- .describe("Optional file attachments")
2658
+ .describe("Optional inline file attachments")
2461
2659
  .optional(),
2660
+ attachmentIds: z
2661
+ .array(z.string())
2662
+ .describe("Ids of previously uploaded attachments to attach")
2663
+ .optional(),
2664
+ sourceChannel: z
2665
+ .string()
2666
+ .describe('Originating channel id (e.g. "vellum")'),
2667
+ interface: z
2668
+ .string()
2669
+ .describe('Originating interface id (e.g. "vellum")'),
2462
2670
  conversationType: z.string().optional(),
2463
2671
  slashCommand: z.string().optional(),
2464
2672
  clientTimezone: z.string().optional(),
2465
2673
  inferenceProfile: z.string().nullable().optional(),
2466
2674
  riskThreshold: z.enum(VALID_RISK_THRESHOLDS).optional(),
2675
+ onboarding: z
2676
+ .object({
2677
+ tools: z.array(z.string()),
2678
+ tasks: z.array(z.string()),
2679
+ tone: z.string(),
2680
+ userName: z.string().optional(),
2681
+ assistantName: z.string().optional(),
2682
+ googleConnected: z.boolean().optional(),
2683
+ googleScopes: z.array(z.string()).optional(),
2684
+ priorAssistants: z.array(z.string()).optional(),
2685
+ cohort: z.string().optional(),
2686
+ websiteUrl: z.string().optional(),
2687
+ contentSourceUrl: z.string().optional(),
2688
+ bootstrapTemplate: z.string().optional(),
2689
+ initialMessage: z.string().optional(),
2690
+ skills: z.array(z.string()).optional(),
2691
+ })
2692
+ .describe("PreChat onboarding context, sent on the first message only")
2693
+ .optional(),
2694
+ }),
2695
+ responseBody: z.object({
2696
+ accepted: z.boolean(),
2697
+ conversationId: z.string().optional(),
2698
+ messageId: z.string().optional(),
2699
+ queued: z.boolean().optional(),
2700
+ requestId: z.string().optional(),
2467
2701
  }),
2468
2702
  handler: async (args) =>
2469
2703
  handleSendMessage(args, {
@@ -2479,6 +2713,10 @@ export const ROUTES: RouteDefinition[] = [
2479
2713
  operationId: "search_get",
2480
2714
  endpoint: "search",
2481
2715
  method: "GET",
2716
+ policy: {
2717
+ requiredScopes: ["chat.read"],
2718
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
2719
+ },
2482
2720
  summary: "Search conversations",
2483
2721
  description: "Full-text search across all conversations.",
2484
2722
  tags: ["conversations"],
@@ -2492,6 +2730,10 @@ export const ROUTES: RouteDefinition[] = [
2492
2730
  operationId: "suggestion_get",
2493
2731
  endpoint: "suggestion",
2494
2732
  method: "GET",
2733
+ policy: {
2734
+ requiredScopes: ["chat.read"],
2735
+ allowedPrincipalTypes: ACTOR_PRINCIPALS,
2736
+ },
2495
2737
  summary: "Get reply suggestion",
2496
2738
  description:
2497
2739
  "Return an LLM-generated follow-up suggestion for the most recent assistant message.",