@vellumai/assistant 0.7.3 → 0.8.1

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 (778) hide show
  1. package/AGENTS.md +11 -0
  2. package/ARCHITECTURE.md +29 -28
  3. package/Dockerfile +6 -4
  4. package/README.md +2 -2
  5. package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
  6. package/bun.lock +3 -0
  7. package/docker-entrypoint.sh +16 -0
  8. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  9. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  10. package/eslint.config.mjs +12 -0
  11. package/knip.json +3 -1
  12. package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
  13. package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
  14. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
  15. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
  16. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
  17. package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
  18. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  19. package/openapi.yaml +4126 -959
  20. package/package.json +5 -1
  21. package/scripts/generate-openapi.ts +52 -4
  22. package/scripts/sync-llm-catalog.ts +165 -0
  23. package/scripts/sync-web-search-catalog.ts +107 -0
  24. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  25. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  26. package/src/__tests__/annotate-risk-options.test.ts +291 -0
  27. package/src/__tests__/anthropic-provider.test.ts +92 -2
  28. package/src/__tests__/app-control-flow.test.ts +7 -0
  29. package/src/__tests__/approval-cascade.test.ts +8 -16
  30. package/src/__tests__/approval-routes-http.test.ts +6 -0
  31. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  32. package/src/__tests__/auto-analysis-end-to-end.test.ts +12 -25
  33. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  34. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  35. package/src/__tests__/btw-routes.test.ts +1 -0
  36. package/src/__tests__/call-constants.test.ts +10 -1
  37. package/src/__tests__/call-controller.test.ts +127 -0
  38. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  39. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  40. package/src/__tests__/channel-policy.test.ts +12 -0
  41. package/src/__tests__/checker.test.ts +89 -0
  42. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +88 -30
  43. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  44. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  45. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  46. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +345 -8
  48. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  49. package/src/__tests__/config-schema.test.ts +14 -3
  50. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  51. package/src/__tests__/config-set-route.test.ts +198 -0
  52. package/src/__tests__/config-watcher.test.ts +6 -0
  53. package/src/__tests__/contacts-tools.test.ts +51 -199
  54. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  55. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  56. package/src/__tests__/context-search-conversations-source.test.ts +42 -16
  57. package/src/__tests__/context-search-fanout.test.ts +20 -157
  58. package/src/__tests__/context-search-memory-source.test.ts +3 -26
  59. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
  60. package/src/__tests__/context-search-types.test.ts +7 -2
  61. package/src/__tests__/context-window-manager.test.ts +389 -1
  62. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -6
  63. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
  64. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
  65. package/src/__tests__/conversation-agent-loop.test.ts +3 -3
  66. package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
  67. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  68. package/src/__tests__/conversation-error.test.ts +38 -0
  69. package/src/__tests__/conversation-fork-crud.test.ts +241 -1
  70. package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
  71. package/src/__tests__/conversation-init.benchmark.test.ts +2 -1
  72. package/src/__tests__/conversation-lifecycle.test.ts +124 -0
  73. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  74. package/src/__tests__/conversation-process-callsite.test.ts +22 -7
  75. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -6
  76. package/src/__tests__/conversation-runtime-assembly.test.ts +19 -10
  77. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  78. package/src/__tests__/conversation-slash-unknown.test.ts +1 -6
  79. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
  80. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  81. package/src/__tests__/conversation-surfaces-data-persist.test.ts +73 -1
  82. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +59 -0
  83. package/src/__tests__/conversation-workspace-injection.test.ts +1 -7
  84. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -7
  85. package/src/__tests__/credential-security-invariants.test.ts +5 -6
  86. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  87. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  88. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  89. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  90. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  91. package/src/__tests__/external-plugin-loader.test.ts +458 -0
  92. package/src/__tests__/filing-service.test.ts +25 -22
  93. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  94. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  95. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  96. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -34
  97. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  98. package/src/__tests__/heartbeat-service.test.ts +50 -233
  99. package/src/__tests__/history-repair.test.ts +89 -0
  100. package/src/__tests__/host-app-control-proxy.test.ts +109 -1
  101. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  102. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  103. package/src/__tests__/host-browser-routes.test.ts +325 -33
  104. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  105. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  106. package/src/__tests__/inference-profile-reaper.test.ts +154 -0
  107. package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
  108. package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
  109. package/src/__tests__/injector-chain.test.ts +24 -16
  110. package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
  111. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  112. package/src/__tests__/install-skill-routing.test.ts +2 -2
  113. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +169 -67
  114. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  115. package/src/__tests__/llm-catalog-parity.test.ts +146 -0
  116. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
  117. package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
  118. package/src/__tests__/llm-resolver.test.ts +46 -0
  119. package/src/__tests__/managed-profile-guard.test.ts +131 -2
  120. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  121. package/src/__tests__/mcp-cli.test.ts +182 -220
  122. package/src/__tests__/mcp-health-check.test.ts +56 -27
  123. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  124. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  125. package/src/__tests__/notification-decision-fallback.test.ts +91 -0
  126. package/src/__tests__/notification-decision-strategy.test.ts +22 -0
  127. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  128. package/src/__tests__/oauth-cli.test.ts +38 -1888
  129. package/src/__tests__/oauth-commands-routes.test.ts +711 -0
  130. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  131. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  132. package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
  133. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  134. package/src/__tests__/plugin-bootstrap.test.ts +31 -2
  135. package/src/__tests__/plugin-route-contribution.test.ts +31 -3
  136. package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
  137. package/src/__tests__/plugin-types.test.ts +13 -11
  138. package/src/__tests__/process-message-background-slack.test.ts +46 -0
  139. package/src/__tests__/profile-entry-status.test.ts +43 -0
  140. package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
  141. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  142. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  143. package/src/__tests__/relay-server.test.ts +164 -2
  144. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  145. package/src/__tests__/schedule-retry.test.ts +56 -4
  146. package/src/__tests__/schedule-routes.test.ts +104 -0
  147. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  148. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  149. package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
  150. package/src/__tests__/scheduler-wake.test.ts +0 -63
  151. package/src/__tests__/secret-allowlist.test.ts +1 -0
  152. package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
  153. package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
  154. package/src/__tests__/secret-response-routing.test.ts +7 -5
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
  156. package/src/__tests__/server-history-render.test.ts +82 -0
  157. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  158. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  159. package/src/__tests__/skill-include-graph.test.ts +31 -0
  160. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  161. package/src/__tests__/skill-load-tool.test.ts +42 -16
  162. package/src/__tests__/skills.test.ts +39 -0
  163. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  164. package/src/__tests__/suggestion-routes.test.ts +3 -3
  165. package/src/__tests__/sync-message-contract.test.ts +63 -0
  166. package/src/__tests__/task-scheduler.test.ts +88 -23
  167. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
  168. package/src/__tests__/tool-executor.test.ts +155 -0
  169. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  170. package/src/__tests__/usage-cli.test.ts +11 -73
  171. package/src/__tests__/user-plugin-loader.test.ts +145 -0
  172. package/src/__tests__/vercel-config.test.ts +168 -0
  173. package/src/__tests__/voice-session-bridge.test.ts +3 -0
  174. package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
  175. package/src/__tests__/web-search.test.ts +303 -2
  176. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  177. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
  178. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +153 -0
  179. package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
  180. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
  181. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  182. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  183. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  184. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  185. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  186. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  187. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +15 -27
  188. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  189. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  190. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  191. package/src/acp/resolve-agent.test.ts +25 -0
  192. package/src/acp/resolve-agent.ts +13 -2
  193. package/src/acp/session-manager.ts +14 -0
  194. package/src/agent/loop.ts +11 -0
  195. package/src/approvals/guardian-decision-primitive.ts +0 -13
  196. package/src/approvals/guardian-request-resolvers.ts +19 -102
  197. package/src/calls/call-constants.ts +5 -8
  198. package/src/calls/call-controller.ts +130 -67
  199. package/src/calls/relay-server.ts +42 -1
  200. package/src/calls/relay-setup-router.ts +36 -0
  201. package/src/calls/types.ts +1 -0
  202. package/src/calls/voice-session-bridge.ts +24 -5
  203. package/src/channels/config.ts +14 -1
  204. package/src/channels/types.ts +1 -0
  205. package/src/cli/AGENTS.md +164 -4
  206. package/src/cli/__tests__/notifications.test.ts +54 -0
  207. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  208. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  209. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  210. package/src/cli/commands/__tests__/changelog.test.ts +593 -0
  211. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  212. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  213. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  214. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  215. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  216. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  217. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  218. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  219. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  220. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  221. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  222. package/src/cli/commands/__tests__/status.test.ts +249 -0
  223. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  224. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  225. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  226. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  227. package/src/cli/commands/attachment.ts +8 -3
  228. package/src/cli/commands/audit.ts +95 -64
  229. package/src/cli/commands/auth.ts +61 -58
  230. package/src/cli/commands/avatar.ts +276 -390
  231. package/src/cli/commands/backup.ts +409 -505
  232. package/src/cli/commands/bash.ts +9 -5
  233. package/src/cli/commands/browser.ts +28 -9
  234. package/src/cli/commands/cache.ts +9 -4
  235. package/src/cli/commands/changelog.ts +414 -0
  236. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  237. package/src/cli/commands/clients.ts +8 -3
  238. package/src/cli/commands/completions.ts +9 -9
  239. package/src/cli/commands/config.ts +102 -72
  240. package/src/cli/commands/contacts.ts +575 -696
  241. package/src/cli/commands/conversations-defer.ts +17 -69
  242. package/src/cli/commands/conversations-import.ts +90 -253
  243. package/src/cli/commands/conversations.ts +346 -436
  244. package/src/cli/commands/credential-execution.ts +9 -6
  245. package/src/cli/commands/credentials.ts +456 -736
  246. package/src/cli/commands/domain.ts +128 -206
  247. package/src/cli/commands/email.ts +606 -794
  248. package/src/cli/commands/gateway.ts +8 -1
  249. package/src/cli/commands/image-generation.ts +157 -205
  250. package/src/cli/commands/inference-providers.ts +352 -0
  251. package/src/cli/commands/inference-session.ts +415 -0
  252. package/src/cli/commands/inference.ts +87 -65
  253. package/src/cli/commands/keys.ts +8 -3
  254. package/src/cli/commands/mcp.ts +103 -287
  255. package/src/cli/commands/memory-v2.ts +163 -517
  256. package/src/cli/commands/notifications.ts +33 -7
  257. package/src/cli/commands/oauth/apps.ts +292 -261
  258. package/src/cli/commands/oauth/connect.ts +182 -345
  259. package/src/cli/commands/oauth/disconnect.ts +16 -215
  260. package/src/cli/commands/oauth/index.ts +49 -45
  261. package/src/cli/commands/oauth/mode.ts +43 -199
  262. package/src/cli/commands/oauth/ping.ts +17 -125
  263. package/src/cli/commands/oauth/providers.ts +732 -921
  264. package/src/cli/commands/oauth/request.ts +60 -350
  265. package/src/cli/commands/oauth/shared.ts +11 -121
  266. package/src/cli/commands/oauth/status.ts +31 -121
  267. package/src/cli/commands/oauth/token.ts +13 -55
  268. package/src/cli/commands/pending.ts +19 -10
  269. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  270. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  271. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  272. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  273. package/src/cli/commands/platform/connect.ts +16 -80
  274. package/src/cli/commands/platform/disconnect.ts +14 -112
  275. package/src/cli/commands/platform/index.ts +177 -246
  276. package/src/cli/commands/routes.ts +153 -336
  277. package/src/cli/commands/sequence.ts +316 -360
  278. package/src/cli/commands/skills.ts +449 -671
  279. package/src/cli/commands/status.ts +58 -37
  280. package/src/cli/commands/stt.ts +94 -262
  281. package/src/cli/commands/task.ts +14 -40
  282. package/src/cli/commands/trust.ts +8 -3
  283. package/src/cli/commands/tts.ts +162 -167
  284. package/src/cli/commands/ui.ts +35 -42
  285. package/src/cli/commands/usage.ts +188 -126
  286. package/src/cli/commands/watchers.ts +8 -3
  287. package/src/cli/commands/webhooks.ts +99 -193
  288. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  289. package/src/cli/lib/daemon-credential-client.ts +4 -5
  290. package/src/cli/lib/nested-value.ts +44 -0
  291. package/src/cli/lib/open-browser.ts +36 -0
  292. package/src/cli/lib/register-command.ts +19 -0
  293. package/src/cli/lib/time-ago.ts +34 -0
  294. package/src/cli/program.ts +2 -4
  295. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  296. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  297. package/src/cli/utils/conversation-id.ts +30 -0
  298. package/src/cli/utils/parse-duration.ts +41 -0
  299. package/src/config/acp-defaults.test.ts +5 -1
  300. package/src/config/acp-defaults.ts +11 -4
  301. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  302. package/src/config/bundled-skills/app-builder/SKILL.md +1 -3
  303. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  304. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  305. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  306. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  307. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  308. package/src/config/bundled-tool-registry.ts +0 -2
  309. package/src/config/feature-flag-registry.json +17 -17
  310. package/src/config/llm-resolver.ts +16 -1
  311. package/src/config/loader.ts +148 -33
  312. package/src/config/raw-config-utils.ts +2 -30
  313. package/src/config/schema.ts +4 -0
  314. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  315. package/src/config/schemas/call-site-catalog.ts +29 -7
  316. package/src/config/schemas/llm-request-logs.ts +57 -0
  317. package/src/config/schemas/llm.ts +52 -2
  318. package/src/config/schemas/memory-retrospective.ts +48 -0
  319. package/src/config/schemas/memory-v2.ts +33 -2
  320. package/src/config/schemas/memory.ts +4 -0
  321. package/src/config/schemas/services.ts +15 -12
  322. package/src/config/seed-inference-profiles.ts +195 -134
  323. package/src/contacts/contact-store.ts +0 -61
  324. package/src/context/window-manager.ts +191 -5
  325. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +111 -0
  326. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
  327. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  328. package/src/daemon/approval-generators.ts +23 -29
  329. package/src/daemon/config-watcher.ts +2 -0
  330. package/src/daemon/conversation-agent-loop-handlers.ts +56 -0
  331. package/src/daemon/conversation-agent-loop.ts +140 -107
  332. package/src/daemon/conversation-error.ts +21 -0
  333. package/src/daemon/conversation-lifecycle.ts +68 -13
  334. package/src/daemon/conversation-process.ts +36 -19
  335. package/src/daemon/conversation-runtime-assembly.ts +14 -5
  336. package/src/daemon/conversation-slash.ts +175 -23
  337. package/src/daemon/conversation-store.ts +17 -10
  338. package/src/daemon/conversation-surfaces.ts +92 -26
  339. package/src/daemon/conversation-tool-setup.ts +33 -19
  340. package/src/daemon/conversation.ts +49 -10
  341. package/src/daemon/external-plugins-bootstrap.ts +18 -8
  342. package/src/daemon/guardian-action-generators.ts +7 -22
  343. package/src/daemon/handlers/config-model.ts +8 -126
  344. package/src/daemon/handlers/config-slack-channel.ts +10 -7
  345. package/src/daemon/handlers/config-vercel.ts +3 -1
  346. package/src/daemon/handlers/shared.ts +26 -0
  347. package/src/daemon/handlers/skills.ts +84 -5
  348. package/src/daemon/history-repair.ts +33 -6
  349. package/src/daemon/host-app-control-proxy.ts +44 -19
  350. package/src/daemon/host-bash-proxy.ts +85 -158
  351. package/src/daemon/host-browser-proxy.ts +97 -36
  352. package/src/daemon/host-cu-proxy.ts +1 -1
  353. package/src/daemon/host-file-proxy.ts +1 -1
  354. package/src/daemon/host-proxy-base.ts +13 -1
  355. package/src/daemon/host-proxy-preactivation.ts +25 -1
  356. package/src/daemon/host-transfer-proxy.ts +2 -2
  357. package/src/daemon/identity-helpers.ts +19 -0
  358. package/src/daemon/lifecycle.ts +128 -114
  359. package/src/daemon/meet-host-supervisor.ts +15 -15
  360. package/src/daemon/memory-v2-startup.ts +62 -14
  361. package/src/daemon/message-protocol.ts +6 -0
  362. package/src/daemon/message-types/bookmarks.ts +18 -0
  363. package/src/daemon/message-types/conversations.ts +12 -9
  364. package/src/daemon/message-types/messages.ts +28 -2
  365. package/src/daemon/message-types/sync.ts +60 -0
  366. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  367. package/src/daemon/pkb-reminder-builder.ts +21 -7
  368. package/src/daemon/process-message.ts +56 -23
  369. package/src/daemon/server.ts +23 -18
  370. package/src/daemon/shutdown-handlers.ts +0 -2
  371. package/src/daemon/tool-setup-types.ts +9 -0
  372. package/src/daemon/tool-side-effects.ts +6 -4
  373. package/src/daemon/wake-target-adapter.ts +11 -0
  374. package/src/documents/document-store.ts +35 -1
  375. package/src/export/transcript-formatter.ts +61 -2
  376. package/src/filing/filing-service.ts +42 -56
  377. package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
  378. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  379. package/src/heartbeat/heartbeat-service.ts +149 -128
  380. package/src/home/__tests__/feed-types.test.ts +63 -131
  381. package/src/home/__tests__/feed-writer.test.ts +77 -278
  382. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  383. package/src/home/feed-types.ts +19 -73
  384. package/src/home/feed-writer.ts +25 -156
  385. package/src/home/post-connect-feed.ts +1 -3
  386. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  387. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  388. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  389. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  390. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  391. package/src/ipc/assistant-server.ts +148 -42
  392. package/src/ipc/cli-client.ts +370 -50
  393. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  394. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  395. package/src/ipc/skill-routes/events.ts +30 -3
  396. package/src/ipc/skill-server.ts +99 -42
  397. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  398. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  399. package/src/live-voice/live-voice-session-manager.ts +11 -4
  400. package/src/live-voice/live-voice-session.ts +14 -6
  401. package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
  402. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  403. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  404. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  405. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +10 -57
  406. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  407. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  408. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
  409. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  410. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  411. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  412. package/src/memory/bookmark-crud.ts +179 -0
  413. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  414. package/src/memory/context-search/agent-protocol.ts +5 -1
  415. package/src/memory/context-search/agent-runner.ts +60 -85
  416. package/src/memory/context-search/limits.ts +1 -4
  417. package/src/memory/context-search/search.ts +23 -113
  418. package/src/memory/context-search/sources/conversations.ts +18 -6
  419. package/src/memory/context-search/sources/memory-v2.ts +40 -31
  420. package/src/memory/context-search/sources/memory.ts +9 -2
  421. package/src/memory/context-search/sources/workspace.ts +13 -10
  422. package/src/memory/context-search/types.ts +1 -1
  423. package/src/memory/conversation-bootstrap.ts +11 -0
  424. package/src/memory/conversation-crud.ts +312 -10
  425. package/src/memory/conversation-queries.ts +9 -5
  426. package/src/memory/conversation-title-service.ts +1 -0
  427. package/src/memory/conversation-types.ts +16 -0
  428. package/src/memory/db-init.ts +14 -0
  429. package/src/memory/embedding-backend.ts +2 -1
  430. package/src/memory/embedding-runtime-manager.ts +1 -2
  431. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +104 -61
  432. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
  433. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  434. package/src/memory/graph/conversation-graph-memory.ts +108 -14
  435. package/src/memory/graph/extraction.ts +4 -0
  436. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  437. package/src/memory/graph/graph-search.test.ts +6 -5
  438. package/src/memory/graph/graph-search.ts +3 -4
  439. package/src/memory/graph/retriever.test.ts +12 -7
  440. package/src/memory/graph/retriever.ts +4 -5
  441. package/src/memory/graph/tool-handlers.ts +20 -11
  442. package/src/memory/graph/tools.ts +48 -9
  443. package/src/memory/indexer.ts +18 -2
  444. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +120 -6
  445. package/src/memory/jobs/embed-concept-page.ts +261 -89
  446. package/src/memory/jobs-store.ts +51 -1
  447. package/src/memory/jobs-worker.ts +60 -7
  448. package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
  449. package/src/memory/llm-request-log-source-local.ts +26 -0
  450. package/src/memory/llm-request-log-source.ts +97 -0
  451. package/src/memory/llm-request-log-store.ts +1 -1
  452. package/src/memory/memory-retrospective-constants.ts +13 -0
  453. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  454. package/src/memory/memory-retrospective-job.ts +351 -0
  455. package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
  456. package/src/memory/memory-retrospective-state.ts +162 -0
  457. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  458. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  459. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  460. package/src/memory/message-content.ts +38 -1
  461. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  462. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  463. package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
  464. package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
  465. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  466. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  467. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  468. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  469. package/src/memory/migrations/243-provider-connections.ts +68 -0
  470. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  471. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  472. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  473. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  474. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  475. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  476. package/src/memory/migrations/index.ts +7 -0
  477. package/src/memory/pkb/pkb-search.test.ts +6 -5
  478. package/src/memory/pkb/pkb-search.ts +4 -5
  479. package/src/memory/published-pages-store.ts +16 -0
  480. package/src/memory/qdrant-client.ts +3 -0
  481. package/src/memory/schema/bookmarks.ts +38 -0
  482. package/src/memory/schema/conversations.ts +2 -0
  483. package/src/memory/schema/index.ts +2 -0
  484. package/src/memory/schema/inference.ts +29 -0
  485. package/src/memory/schema/memory-core.ts +9 -0
  486. package/src/memory/search/semantic.ts +5 -9
  487. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  488. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  489. package/src/memory/v2/__tests__/activation.test.ts +46 -9
  490. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  491. package/src/memory/v2/__tests__/consolidation-job.test.ts +140 -163
  492. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  493. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  494. package/src/memory/v2/__tests__/injection.test.ts +768 -33
  495. package/src/memory/v2/__tests__/migration.test.ts +7 -3
  496. package/src/memory/v2/__tests__/page-index.test.ts +277 -0
  497. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  498. package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
  499. package/src/memory/v2/__tests__/qdrant.test.ts +382 -9
  500. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  501. package/src/memory/v2/__tests__/router.test.ts +516 -0
  502. package/src/memory/v2/__tests__/sim.test.ts +163 -8
  503. package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
  504. package/src/memory/v2/__tests__/static-context.test.ts +8 -35
  505. package/src/memory/v2/__tests__/sweep-job.test.ts +114 -33
  506. package/src/memory/v2/activation-store.ts +34 -5
  507. package/src/memory/v2/activation.ts +40 -27
  508. package/src/memory/v2/backfill-jobs.ts +17 -84
  509. package/src/memory/v2/consolidation-job.ts +92 -86
  510. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  511. package/src/memory/v2/injection.ts +466 -115
  512. package/src/memory/v2/migration.ts +117 -20
  513. package/src/memory/v2/page-index.ts +191 -0
  514. package/src/memory/v2/page-store.ts +42 -0
  515. package/src/memory/v2/prompts/consolidation.ts +14 -7
  516. package/src/memory/v2/prompts/router.ts +192 -0
  517. package/src/memory/v2/qdrant.ts +307 -133
  518. package/src/memory/v2/reranker.ts +14 -7
  519. package/src/memory/v2/router.ts +322 -0
  520. package/src/memory/v2/sim.ts +88 -34
  521. package/src/memory/v2/skill-store.ts +118 -29
  522. package/src/memory/v2/static-context.ts +20 -17
  523. package/src/memory/v2/sweep-job.ts +127 -102
  524. package/src/memory/v2/types.ts +16 -5
  525. package/src/memory/validation.ts +13 -0
  526. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  527. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  528. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  529. package/src/notifications/adapters/platform.ts +171 -0
  530. package/src/notifications/conversation-pairing.ts +2 -2
  531. package/src/notifications/copy-composer.ts +61 -12
  532. package/src/notifications/decision-engine.ts +46 -0
  533. package/src/notifications/destination-resolver.ts +21 -0
  534. package/src/notifications/emit-signal.ts +28 -1
  535. package/src/notifications/home-feed-side-effect.ts +111 -0
  536. package/src/notifications/signal.ts +5 -0
  537. package/src/permissions/checker.ts +12 -0
  538. package/src/permissions/gateway-threshold-reader.ts +116 -8
  539. package/src/permissions/ipc-risk-types.ts +2 -0
  540. package/src/permissions/prompter.ts +86 -96
  541. package/src/permissions/secret-prompter.ts +31 -31
  542. package/src/plugin-api/index.ts +13 -0
  543. package/src/plugin-api/package.json +12 -0
  544. package/src/plugin-api/types.ts +62 -0
  545. package/src/plugins/defaults/injectors.ts +20 -5
  546. package/src/plugins/external-plugin-loader.ts +294 -0
  547. package/src/plugins/types.ts +46 -30
  548. package/src/plugins/user-loader.ts +64 -41
  549. package/src/proactive-artifact/job.test.ts +63 -8
  550. package/src/proactive-artifact/job.ts +20 -2
  551. package/src/proactive-artifact/message-copy.ts +18 -1
  552. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  553. package/src/proactive-artifact/trigger-state.ts +4 -0
  554. package/src/prompts/__tests__/system-prompt.test.ts +105 -0
  555. package/src/prompts/system-prompt.ts +22 -1
  556. package/src/prompts/templates/SOUL.md +13 -28
  557. package/src/prompts/update-bulletin-job.ts +61 -73
  558. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  559. package/src/providers/__tests__/inference.test.ts +288 -0
  560. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  561. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  562. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  563. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  564. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  565. package/src/providers/anthropic/client.ts +95 -26
  566. package/src/providers/call-site-routing.ts +94 -16
  567. package/src/providers/connection-resolution.ts +163 -0
  568. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  569. package/src/providers/inference/adapter-factory.ts +173 -0
  570. package/src/providers/inference/auth.ts +112 -0
  571. package/src/providers/inference/backfill.ts +196 -0
  572. package/src/providers/inference/connections.ts +356 -0
  573. package/src/providers/inference/resolve-auth.ts +65 -0
  574. package/src/providers/model-catalog.ts +104 -6
  575. package/src/providers/openai/responses-provider.ts +4 -2
  576. package/src/providers/provider-env-vars.ts +17 -7
  577. package/src/providers/provider-secret-catalog.ts +49 -30
  578. package/src/providers/provider-send-message.ts +41 -20
  579. package/src/providers/registry.ts +143 -159
  580. package/src/providers/retry.ts +18 -10
  581. package/src/providers/search-provider-catalog.ts +121 -0
  582. package/src/runtime/AGENTS.md +18 -5
  583. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  584. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  585. package/src/runtime/actor-trust-resolver.ts +32 -10
  586. package/src/runtime/agent-wake.ts +35 -6
  587. package/src/runtime/assistant-event-hub.ts +3 -85
  588. package/src/runtime/auth/route-policy.ts +304 -8
  589. package/src/runtime/auth/same-actor.ts +2 -0
  590. package/src/runtime/background-job-runner.ts +339 -0
  591. package/src/runtime/btw-sidechain.ts +1 -0
  592. package/src/runtime/channel-approvals.ts +3 -2
  593. package/src/runtime/guardian-reply-router.ts +0 -10
  594. package/src/runtime/http-router.ts +36 -1
  595. package/src/runtime/http-server.ts +31 -5
  596. package/src/runtime/http-types.ts +2 -0
  597. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  598. package/src/runtime/middleware/request-logger.ts +62 -1
  599. package/src/runtime/pending-interactions.ts +19 -15
  600. package/src/runtime/pre-first-message-gate.ts +83 -0
  601. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  602. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
  603. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  604. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
  605. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
  606. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  607. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  608. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +147 -0
  609. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  610. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  611. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  612. package/src/runtime/routes/acp-routes.ts +10 -8
  613. package/src/runtime/routes/app-management-routes.ts +228 -3
  614. package/src/runtime/routes/approval-routes.ts +7 -21
  615. package/src/runtime/routes/audit-routes.ts +43 -0
  616. package/src/runtime/routes/auth-routes.ts +72 -0
  617. package/src/runtime/routes/avatar-routes.ts +273 -20
  618. package/src/runtime/routes/backup-routes.ts +406 -2
  619. package/src/runtime/routes/bookmark-routes.ts +154 -0
  620. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  621. package/src/runtime/routes/consolidation-routes.ts +8 -9
  622. package/src/runtime/routes/contact-routes.ts +0 -160
  623. package/src/runtime/routes/conversation-cli-routes.ts +192 -0
  624. package/src/runtime/routes/conversation-management-routes.ts +30 -43
  625. package/src/runtime/routes/conversation-query-routes.ts +373 -82
  626. package/src/runtime/routes/conversation-routes.ts +31 -10
  627. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  628. package/src/runtime/routes/credential-routes.ts +540 -0
  629. package/src/runtime/routes/debug-bash-routes.ts +2 -0
  630. package/src/runtime/routes/debug-routes.ts +2 -2
  631. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  632. package/src/runtime/routes/domain-routes.ts +167 -0
  633. package/src/runtime/routes/email-routes.ts +603 -0
  634. package/src/runtime/routes/errors.ts +2 -2
  635. package/src/runtime/routes/events-routes.ts +192 -0
  636. package/src/runtime/routes/filing-routes.ts +2 -3
  637. package/src/runtime/routes/home-feed-routes.ts +6 -78
  638. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  639. package/src/runtime/routes/host-browser-routes.ts +103 -22
  640. package/src/runtime/routes/http-adapter.ts +2 -0
  641. package/src/runtime/routes/identity-routes.ts +5 -0
  642. package/src/runtime/routes/image-generation-routes.ts +99 -0
  643. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
  644. package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
  645. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  646. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -7
  647. package/src/runtime/routes/index.ts +36 -0
  648. package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
  649. package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
  650. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  651. package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
  652. package/src/runtime/routes/inference-send-routes.ts +115 -0
  653. package/src/runtime/routes/integrations/twilio.ts +1 -0
  654. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  655. package/src/runtime/routes/memory-item-routes.test.ts +3 -9
  656. package/src/runtime/routes/memory-item-routes.ts +5 -6
  657. package/src/runtime/routes/memory-v2-routes.ts +105 -404
  658. package/src/runtime/routes/notification-routes.ts +2 -0
  659. package/src/runtime/routes/oauth-apps.ts +112 -7
  660. package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
  661. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  662. package/src/runtime/routes/oauth-providers.ts +298 -8
  663. package/src/runtime/routes/platform-routes.ts +336 -0
  664. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  665. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  666. package/src/runtime/routes/playground/state.ts +2 -1
  667. package/src/runtime/routes/publish-routes.ts +221 -0
  668. package/src/runtime/routes/schedule-routes.ts +82 -0
  669. package/src/runtime/routes/sequence-routes.ts +291 -0
  670. package/src/runtime/routes/settings-routes.ts +2 -10
  671. package/src/runtime/routes/skills-routes.ts +31 -1
  672. package/src/runtime/routes/stt-routes.ts +240 -3
  673. package/src/runtime/routes/surface-action-routes.ts +43 -7
  674. package/src/runtime/routes/tts-routes.ts +67 -0
  675. package/src/runtime/routes/types.ts +32 -0
  676. package/src/runtime/routes/user-routes-cli.ts +243 -0
  677. package/src/runtime/routes/webhook-routes.ts +165 -0
  678. package/src/runtime/sync/resource-sync-events.ts +25 -0
  679. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  680. package/src/runtime/sync/sync-publisher.ts +21 -0
  681. package/src/schedule/scheduler.ts +200 -123
  682. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  683. package/src/security/secret-patterns.ts +3 -0
  684. package/src/sequence/engine.ts +38 -40
  685. package/src/skills/include-graph.ts +35 -13
  686. package/src/subagent/manager.ts +20 -15
  687. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  688. package/src/tools/browser/browser-execution.ts +15 -4
  689. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  690. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  691. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  692. package/src/tools/browser/cdp-client/factory.ts +66 -5
  693. package/src/tools/browser/runtime-check.ts +77 -0
  694. package/src/tools/document/document-tool.ts +20 -0
  695. package/src/tools/executor.ts +18 -2
  696. package/src/tools/memory/register.test.ts +10 -8
  697. package/src/tools/memory/register.ts +9 -1
  698. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  699. package/src/tools/network/web-search.ts +280 -37
  700. package/src/tools/permission-checker.ts +28 -5
  701. package/src/tools/skills/load.ts +24 -20
  702. package/src/tools/subagent/spawn.ts +3 -3
  703. package/src/tools/terminal/shell.ts +44 -0
  704. package/src/tools/tool-name-aliases.ts +19 -0
  705. package/src/tools/types.ts +19 -1
  706. package/src/usage/attribution.ts +3 -2
  707. package/src/util/pricing.ts +86 -160
  708. package/src/watcher/__tests__/engine.test.ts +301 -0
  709. package/src/watcher/constants.ts +7 -0
  710. package/src/watcher/engine.ts +90 -90
  711. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  712. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  713. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
  714. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +4 -62
  715. package/src/workspace/migrations/069-seed-onboarding-threads.ts +34 -0
  716. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
  717. package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
  718. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
  719. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
  720. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  721. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  722. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  723. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  724. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  725. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  726. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  727. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  728. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  729. package/src/workspace/migrations/registry.ts +28 -0
  730. package/src/workspace/migrations/runner.ts +13 -2
  731. package/src/workspace/migrations/types.ts +13 -3
  732. package/src/workspace/provider-commit-message-generator.ts +3 -2
  733. package/src/__tests__/context-search-pkb-source.test.ts +0 -492
  734. package/src/__tests__/credentials-cli.test.ts +0 -1225
  735. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  736. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  737. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  738. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  739. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  740. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  741. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  742. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  743. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  744. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  745. package/src/cli/commands/autonomy.ts +0 -365
  746. package/src/cli/commands/memory.ts +0 -424
  747. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -1201
  748. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  749. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  750. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  751. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  752. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  753. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  754. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  755. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  756. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  757. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  758. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  759. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  760. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  761. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  762. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  763. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  764. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  765. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  766. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  767. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  768. package/src/home/assistant-feed-authoring.ts +0 -135
  769. package/src/home/emit-feed-event.ts +0 -169
  770. package/src/home/feed-scheduler.ts +0 -281
  771. package/src/home/platform-gmail-digest.ts +0 -163
  772. package/src/home/rewrite-command-preview.ts +0 -66
  773. package/src/home/rewrite-feed-title.ts +0 -58
  774. package/src/home/rollup-producer.ts +0 -426
  775. package/src/memory/admin.ts +0 -326
  776. package/src/memory/context-search/sources/pkb.ts +0 -477
  777. package/src/memory/graph/compaction.ts +0 -299
  778. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -118,6 +118,12 @@ export interface EventHandlerState {
118
118
  orderingErrorDetected: boolean;
119
119
  deferredOrderingError: string | null;
120
120
  contextTooLargeDetected: boolean;
121
+ /**
122
+ * Set when the provider rejects with an image-dimension error. The agent
123
+ * loop strips or downscales oversized image blocks from ctx.messages and
124
+ * retries once before surfacing an error to the user.
125
+ */
126
+ imageTooLargeDetected: boolean;
121
127
  /**
122
128
  * The provider error object when context_too_large is detected, preserved
123
129
  * so `parseActualTokensFromError` can prefer the typed
@@ -127,6 +133,11 @@ export interface EventHandlerState {
127
133
  */
128
134
  contextTooLargeError: unknown;
129
135
  providerErrorUserMessage: string | null;
136
+ /**
137
+ * First persisted assistant row in this run; history keeps this id when it
138
+ * merges tool-turn rows into one display bubble.
139
+ */
140
+ firstAssistantMessageId: string | undefined;
130
141
  lastAssistantMessageId: string | undefined;
131
142
  readonly pendingToolResults: Map<string, PendingToolResult>;
132
143
  readonly persistedToolUseIds: Set<string>;
@@ -170,6 +181,16 @@ export interface EventHandlerState {
170
181
  approvalMode?: string;
171
182
  approvalReason?: string;
172
183
  riskThreshold?: string;
184
+ /** Display-only regex ladder for the rule editor (narrowest → broadest). */
185
+ riskScopeOptions?: Array<{ pattern: string; label: string }>;
186
+ /** Minimatch save patterns for the rule editor (narrowest → broadest). */
187
+ riskAllowlistOptions?: Array<{
188
+ label: string;
189
+ description: string;
190
+ pattern: string;
191
+ }>;
192
+ /** Directory scope ladder for the rule editor. */
193
+ riskDirectoryScopeOptions?: Array<{ scope: string; label: string }>;
173
194
  }
174
195
  >;
175
196
  /** tool_use_ids emitted in the current turn (populated in handleToolUse, cleared after annotation). */
@@ -210,8 +231,10 @@ export function createEventHandlerState(): EventHandlerState {
210
231
  orderingErrorDetected: false,
211
232
  deferredOrderingError: null,
212
233
  contextTooLargeDetected: false,
234
+ imageTooLargeDetected: false,
213
235
  contextTooLargeError: null,
214
236
  providerErrorUserMessage: null,
237
+ firstAssistantMessageId: undefined,
215
238
  lastAssistantMessageId: undefined,
216
239
  pendingToolResults: new Map(),
217
240
  persistedToolUseIds: new Set(),
@@ -235,6 +258,12 @@ export function createEventHandlerState(): EventHandlerState {
235
258
  };
236
259
  }
237
260
 
261
+ export function getClientDisplayMessageId(
262
+ state: EventHandlerState,
263
+ ): string | undefined {
264
+ return state.firstAssistantMessageId ?? state.lastAssistantMessageId;
265
+ }
266
+
238
267
  // ── Shared Helper ────────────────────────────────────────────────────
239
268
 
240
269
  // providerNameOverride should be supplied when the caller already knows the
@@ -554,6 +583,14 @@ export function handleToolResult(
554
583
  approvalMode: event.approvalMode,
555
584
  approvalReason: event.approvalReason,
556
585
  riskThreshold: event.riskThreshold,
586
+ // Capture the 3 risk-option arrays so the persisted tool_use block
587
+ // carries the same chip ladder as the live tool_result event. Without
588
+ // these, hydrated chips from chat history fall back to the synthesized
589
+ // `*` allowlist and an empty scope ladder (see the comment on
590
+ // `synthesizeFallbackOption` in web's RuleEditorModal).
591
+ riskScopeOptions: event.riskScopeOptions,
592
+ riskAllowlistOptions: event.riskAllowlistOptions,
593
+ riskDirectoryScopeOptions: event.riskDirectoryScopeOptions,
557
594
  });
558
595
  }
559
596
 
@@ -633,6 +670,7 @@ export function handleToolResult(
633
670
  matchedTrustRuleId: event.matchedTrustRuleId,
634
671
  isContainerized: event.isContainerized,
635
672
  riskScopeOptions: event.riskScopeOptions,
673
+ riskAllowlistOptions: event.riskAllowlistOptions,
636
674
  riskDirectoryScopeOptions: event.riskDirectoryScopeOptions,
637
675
  approvalMode: event.approvalMode,
638
676
  approvalReason: event.approvalReason,
@@ -694,6 +732,19 @@ function annotatePersistedAssistantMessage(
694
732
  if (risk.approvalMode) rec._approvalMode = risk.approvalMode;
695
733
  if (risk.approvalReason) rec._approvalReason = risk.approvalReason;
696
734
  if (risk.riskThreshold) rec._riskThreshold = risk.riskThreshold;
735
+ // Persist the 3 risk-option arrays so the rule editor's chip ladder
736
+ // survives chat-history reload. These mirror the same-named fields
737
+ // on the live `tool_result` event; clients should read them back via
738
+ // `shared.ts` and treat them identically to the live values.
739
+ if (risk.riskScopeOptions && risk.riskScopeOptions.length > 0)
740
+ rec._riskScopeOptions = risk.riskScopeOptions;
741
+ if (risk.riskAllowlistOptions && risk.riskAllowlistOptions.length > 0)
742
+ rec._riskAllowlistOptions = risk.riskAllowlistOptions;
743
+ if (
744
+ risk.riskDirectoryScopeOptions &&
745
+ risk.riskDirectoryScopeOptions.length > 0
746
+ )
747
+ rec._riskDirectoryScopeOptions = risk.riskDirectoryScopeOptions;
697
748
  modified = true;
698
749
  }
699
750
  }
@@ -749,6 +800,10 @@ function handleError(
749
800
  if (classified.code === "CONTEXT_TOO_LARGE") {
750
801
  state.contextTooLargeDetected = true;
751
802
  state.contextTooLargeError = event.error;
803
+ } else if (classified.code === "IMAGE_TOO_LARGE") {
804
+ // Trigger silent recovery: the agent loop will strip/downscale images
805
+ // in ctx.messages and retry once before surfacing an error.
806
+ state.imageTooLargeDetected = true;
752
807
  } else if (
753
808
  classified.code === "PROVIDER_ORDERING" ||
754
809
  classified.code === "PROVIDER_WEB_SEARCH"
@@ -972,6 +1027,7 @@ export async function handleMessageComplete(
972
1027
  DEFAULT_TIMEOUTS.persistence,
973
1028
  )) as PersistAddResult;
974
1029
  const assistantMsg = assistantPersistResult.message;
1030
+ state.firstAssistantMessageId ??= assistantMsg.id;
975
1031
  state.lastAssistantMessageId = assistantMsg.id;
976
1032
 
977
1033
  // Backfill message_id on all LLM request logs from this turn.
@@ -11,6 +11,7 @@ import { join } from "node:path";
11
11
 
12
12
  import { v4 as uuid } from "uuid";
13
13
 
14
+ import { optimizeImageForTransport } from "../agent/image-optimize.js";
14
15
  import type {
15
16
  AgentEvent,
16
17
  AgentLoop,
@@ -28,6 +29,7 @@ import {
28
29
  contextWindowConfigFromEffective,
29
30
  resolveEffectiveContextWindow,
30
31
  } from "../config/llm-context-resolution.js";
32
+ import { resolveCallSiteConfig } from "../config/llm-resolver.js";
31
33
  import { getConfig } from "../config/loader.js";
32
34
  import type { LLMCallSite } from "../config/schemas/llm.js";
33
35
  import type { ContextWindowConfig } from "../config/types.js";
@@ -41,9 +43,7 @@ import {
41
43
  } from "../context/token-estimator.js";
42
44
  import type { ContextWindowManager } from "../context/window-manager.js";
43
45
  import type { ToolProfiler } from "../events/tool-profiling-listener.js";
44
- import { emitFeedEvent } from "../home/emit-feed-event.js";
45
46
  import { writeRelationshipState } from "../home/relationship-state-writer.js";
46
- import { rewriteFeedTitle } from "../home/rewrite-feed-title.js";
47
47
  import {
48
48
  clearSentryConversationContext,
49
49
  setSentryConversationContext,
@@ -71,11 +71,12 @@ import {
71
71
  } from "../memory/conversation-title-service.js";
72
72
  import type { ConversationGraphMemory } from "../memory/graph/conversation-graph-memory.js";
73
73
  import { recordMemoryRecallLog } from "../memory/memory-recall-log-store.js";
74
+ import { enqueueMemoryRetrospectiveOnCompaction } from "../memory/memory-retrospective-enqueue.js";
74
75
  import { PKB_WORKSPACE_SCOPE } from "../memory/pkb/types.js";
75
76
  import type { QdrantSparseVector } from "../memory/qdrant-client.js";
76
77
  import {
77
78
  readMemoryV2StaticContent,
78
- shouldLoadMemoryV2Static,
79
+ shouldExposePersonalMemory,
79
80
  } from "../memory/v2/static-context.js";
80
81
  import type { PermissionPrompter } from "../permissions/prompter.js";
81
82
  import { defaultCompactionTerminal } from "../plugins/defaults/compaction.js";
@@ -147,6 +148,7 @@ import {
147
148
  createEventHandlerState,
148
149
  dispatchAgentEvent,
149
150
  type EventHandlerDeps,
151
+ getClientDisplayMessageId,
150
152
  } from "./conversation-agent-loop-handlers.js";
151
153
  import {
152
154
  approveHostAttachmentRead,
@@ -679,7 +681,9 @@ export async function runAgentLoopImpl(
679
681
  overrideProfile: turnOverrideProfile ?? undefined,
680
682
  });
681
683
  const turnContextWindowConfig = contextWindowConfigFromEffective(
682
- config.llm.default.contextWindow,
684
+ resolveCallSiteConfig(turnCallSite, config.llm, {
685
+ overrideProfile: turnOverrideProfile ?? undefined,
686
+ }).contextWindow,
683
687
  effectiveContextWindow,
684
688
  );
685
689
  (
@@ -986,7 +990,7 @@ export async function runAgentLoopImpl(
986
990
  compactableStartIndex: 1,
987
991
  };
988
992
  };
989
- const applySuccessfulCompaction = (
993
+ const applySuccessfulCompaction = async (
990
994
  result: Awaited<ReturnType<typeof ctx.contextWindowManager.maybeCompact>>,
991
995
  compactedBasis?: Message[],
992
996
  ) => {
@@ -1000,7 +1004,7 @@ export async function runAgentLoopImpl(
1000
1004
  provenanceContext,
1001
1005
  result.compactedMessages,
1002
1006
  );
1003
- applyCompactionResult(ctx, result, onEvent, reqId, {
1007
+ await applyCompactionResult(ctx, result, onEvent, reqId, {
1004
1008
  slackContextCompactionWatermarkTs: slackWatermarkTs,
1005
1009
  });
1006
1010
  currentSlackContextSummary = result.summaryText;
@@ -1087,7 +1091,10 @@ export async function runAgentLoopImpl(
1087
1091
  await trackCompactionOutcome(ctx, compacted.summaryFailed, onEvent);
1088
1092
  }
1089
1093
  if (compacted?.compacted) {
1090
- applySuccessfulCompaction(compacted, messagesForStartOfTurnCompaction);
1094
+ await applySuccessfulCompaction(
1095
+ compacted,
1096
+ messagesForStartOfTurnCompaction,
1097
+ );
1091
1098
  shouldInjectWorkspace = true;
1092
1099
  if (compacted.compactedPersistedMessages > 0) {
1093
1100
  compactedThisTurn = true;
@@ -1408,33 +1415,44 @@ export async function runAgentLoopImpl(
1408
1415
 
1409
1416
  // The `remember` tool handles scratchpad-style memory writes directly to the graph.
1410
1417
 
1418
+ // Personal-memory trust gate: PKB, NOW.md, and v2 static blocks all
1419
+ // hold private user content. Block exposure to non-guardian actors
1420
+ // arriving over a remote channel; internal/local flows pass through.
1421
+ // See `shouldExposePersonalMemory` for the threat model.
1422
+ const personalMemoryAllowed = shouldExposePersonalMemory({
1423
+ sourceChannel: ctx.trustContext?.sourceChannel,
1424
+ isTrustedActor,
1425
+ });
1426
+
1411
1427
  // Inject NOW.md and PKB content only on the first turn (or after
1412
1428
  // compaction re-strips them). Old injections persist in history and
1413
1429
  // are never stripped on normal turns — this preserves the cached prefix.
1414
1430
  // PKB/NOW content is sourced from the `memoryRetrieval` pipeline above
1415
1431
  // so plugins can override either source without touching the agent loop.
1416
- const currentNowContent = memoryResult.nowContent;
1432
+ const currentNowContent = personalMemoryAllowed
1433
+ ? memoryResult.nowContent
1434
+ : null;
1417
1435
  const shouldInjectNowAndPkb = isFirstMessage || compactedThisTurn;
1418
1436
  const nowScratchpad = shouldInjectNowAndPkb ? currentNowContent : null;
1419
1437
 
1420
- const currentPkbContent = memoryResult.pkbContent;
1438
+ const currentPkbContent = personalMemoryAllowed
1439
+ ? memoryResult.pkbContent
1440
+ : null;
1421
1441
  const pkbContext = shouldInjectNowAndPkb ? currentPkbContent : null;
1422
1442
  const pkbActive = currentPkbContent !== null;
1423
1443
 
1424
- // V2 static memory block (essentials/threads/recent/buffer). Same
1425
- // first-turn / post-compaction cadence as PKB. `shouldLoadMemoryV2Static`
1426
- // also blocks remote-channel non-guardian actors from inducing the
1427
- // model to recite private memory; `readMemoryV2StaticContent` self-gates
1428
- // on the v2 flag + config and returns null when v2 is off, so the file
1429
- // reads are skipped on non-injection turns.
1430
- const currentMemoryV2Static = shouldLoadMemoryV2Static({
1431
- shouldInjectNowAndPkb,
1432
- sourceChannel: ctx.trustContext?.sourceChannel,
1433
- isTrustedActor,
1434
- })
1444
+ // V2 static memory block (essentials/threads/recent/buffer).
1445
+ // `currentMemoryV2Static` is the trust-gated content reused by every
1446
+ // re-injection path it stays non-null on non-full-mode turns so
1447
+ // that mid-turn reducer compaction (which strips the prior `<memory>`
1448
+ // block) can restore the freshest content. `memoryV2Static` is the
1449
+ // first-turn / post-compaction cadence-gated value for initial
1450
+ // injection only. `readMemoryV2StaticContent` self-gates on the v2
1451
+ // flag + config and returns null when v2 is off.
1452
+ const currentMemoryV2Static = personalMemoryAllowed
1435
1453
  ? readMemoryV2StaticContent()
1436
1454
  : null;
1437
- const memoryV2Static = currentMemoryV2Static;
1455
+ const memoryV2Static = shouldInjectNowAndPkb ? currentMemoryV2Static : null;
1438
1456
 
1439
1457
  // PKB relevance-hint inputs. Resolved once per turn and reused across
1440
1458
  // re-injections so post-compaction rebuilds pick up fresh hints against
@@ -1572,7 +1590,8 @@ export async function runAgentLoopImpl(
1572
1590
  injection.blocks.pkbSystemReminder ||
1573
1591
  injection.blocks.workspaceBlock ||
1574
1592
  injection.blocks.nowScratchpadBlock ||
1575
- injection.blocks.pkbContextBlock
1593
+ injection.blocks.pkbContextBlock ||
1594
+ injection.blocks.memoryV2StaticBlock
1576
1595
  ) {
1577
1596
  try {
1578
1597
  const metadataUpdates: Record<string, unknown> = {};
@@ -1594,6 +1613,10 @@ export async function runAgentLoopImpl(
1594
1613
  if (injection.blocks.pkbContextBlock) {
1595
1614
  metadataUpdates.pkbContextBlock = injection.blocks.pkbContextBlock;
1596
1615
  }
1616
+ if (injection.blocks.memoryV2StaticBlock) {
1617
+ metadataUpdates.memoryV2StaticBlock =
1618
+ injection.blocks.memoryV2StaticBlock;
1619
+ }
1597
1620
  await runPipeline<PersistArgs, PersistResult>(
1598
1621
  "persistence",
1599
1622
  getMiddlewaresFor("persistence"),
@@ -1790,7 +1813,7 @@ export async function runAgentLoopImpl(
1790
1813
  await trackCompactionOutcome(ctx, result.summaryFailed, onEvent);
1791
1814
  }
1792
1815
  if (result.compacted) {
1793
- applySuccessfulCompaction(result, compactedBasis);
1816
+ await applySuccessfulCompaction(result, compactedBasis);
1794
1817
  shouldInjectWorkspace = true;
1795
1818
  }
1796
1819
  },
@@ -2119,7 +2142,7 @@ export async function runAgentLoopImpl(
2119
2142
  );
2120
2143
  }
2121
2144
  if (midLoopCompact.compacted) {
2122
- applySuccessfulCompaction(midLoopCompact, rawHistory);
2145
+ await applySuccessfulCompaction(midLoopCompact, rawHistory);
2123
2146
  reducerCompacted = true;
2124
2147
  shouldInjectWorkspace = true;
2125
2148
  }
@@ -2237,6 +2260,83 @@ export async function runAgentLoopImpl(
2237
2260
  }
2238
2261
  }
2239
2262
 
2263
+ // ── Image-dimension overflow recovery ──────────────────────────
2264
+ // When the provider rejects because an image block exceeds its pixel
2265
+ // cap, strip every image block from ctx.messages and retry once.
2266
+ // optimizeImageForTransport already ran at upload time; if sips was
2267
+ // unavailable (non-macOS) it returns the same bytes unchanged. In
2268
+ // that case we swap the block for a text note so the model can tell
2269
+ // the user what happened instead of hard-failing with a red banner.
2270
+ if (state.imageTooLargeDetected) {
2271
+ state.imageTooLargeDetected = false;
2272
+ rlog.warn(
2273
+ { phase: "image-recovery" },
2274
+ "Image too large — stripping oversized image blocks and retrying",
2275
+ );
2276
+ ctx.messages = ctx.messages.map((msg) => {
2277
+ if (!Array.isArray(msg.content)) return msg;
2278
+ if (!msg.content.some((b) => b.type === "image")) return msg;
2279
+ return {
2280
+ ...msg,
2281
+ content: msg.content.flatMap((b): ContentBlock[] => {
2282
+ if (b.type !== "image") return [b];
2283
+ const resized = optimizeImageForTransport(
2284
+ b.source.data,
2285
+ b.source.media_type,
2286
+ );
2287
+ if (resized.data !== b.source.data) {
2288
+ // sips managed to downscale — use the smaller version
2289
+ return [
2290
+ {
2291
+ ...b,
2292
+ source: {
2293
+ type: "base64" as const,
2294
+ media_type: resized.mediaType,
2295
+ data: resized.data,
2296
+ },
2297
+ },
2298
+ ];
2299
+ }
2300
+ // Can't resize — replace with a text annotation so the model
2301
+ // can explain the situation rather than silently dropping context
2302
+ return [
2303
+ {
2304
+ type: "text" as const,
2305
+ text: "(An image was attached but could not be sent — its dimensions exceed the provider limit and automatic resize was not available. Please resize the image and try again.)",
2306
+ },
2307
+ ];
2308
+ }),
2309
+ };
2310
+ });
2311
+ runMessages = ctx.messages;
2312
+ updatedHistory = await ctx.agentLoop.run(
2313
+ runMessages,
2314
+ eventHandler,
2315
+ abortController.signal,
2316
+ reqId,
2317
+ onCheckpoint,
2318
+ turnCallSite,
2319
+ loopTurnCtx,
2320
+ turnOverrideProfile,
2321
+ effectiveContextWindow.maxInputTokens,
2322
+ );
2323
+ if (state.imageTooLargeDetected) {
2324
+ rlog.error(
2325
+ { phase: "image-recovery" },
2326
+ "Image-recovery retry also failed — surfacing error to user",
2327
+ );
2328
+ const classified = classifyConversationError(
2329
+ new Error("Image dimensions too large"),
2330
+ { phase: "agent_loop" },
2331
+ );
2332
+ deps.onEvent(
2333
+ buildConversationErrorMessage(deps.ctx.conversationId, classified),
2334
+ );
2335
+ state.providerErrorUserMessage = classified.userMessage;
2336
+ state.imageTooLargeDetected = false;
2337
+ }
2338
+ }
2339
+
2240
2340
  // ── Bounded context overflow convergence loop ──────────────────
2241
2341
  // When the provider rejects with context-too-large, iterate through
2242
2342
  // reducer tiers (forced compaction, tool-result truncation, media
@@ -2371,7 +2471,7 @@ export async function runAgentLoopImpl(
2371
2471
  }
2372
2472
 
2373
2473
  if (step.compactionResult?.compacted) {
2374
- applySuccessfulCompaction(
2474
+ await applySuccessfulCompaction(
2375
2475
  step.compactionResult,
2376
2476
  convergenceCompactionBasis,
2377
2477
  );
@@ -2537,7 +2637,7 @@ export async function runAgentLoopImpl(
2537
2637
  );
2538
2638
  }
2539
2639
  if (emergencyCompact?.compacted) {
2540
- applySuccessfulCompaction(emergencyCompact, ctx.messages);
2640
+ await applySuccessfulCompaction(emergencyCompact, ctx.messages);
2541
2641
  reducerCompacted = true;
2542
2642
  shouldInjectWorkspace = true;
2543
2643
  }
@@ -2831,6 +2931,7 @@ export async function runAgentLoopImpl(
2831
2931
  ctx.lastAssistantAttachments = assistantAttachments;
2832
2932
  ctx.lastAttachmentWarnings = attachmentResult.directiveWarnings;
2833
2933
  syncLastAssistantMessageToDisk();
2934
+ const clientDisplayMessageId = getClientDisplayMessageId(state);
2834
2935
 
2835
2936
  // Re-check: the user may have cancelled during attachment resolution
2836
2937
  if (abortController.signal.aborted) {
@@ -2871,6 +2972,9 @@ export async function runAgentLoopImpl(
2871
2972
  ...(state.lastAssistantMessageId
2872
2973
  ? { messageId: state.lastAssistantMessageId }
2873
2974
  : {}),
2975
+ ...(clientDisplayMessageId
2976
+ ? { displayMessageId: clientDisplayMessageId }
2977
+ : {}),
2874
2978
  });
2875
2979
  } else {
2876
2980
  ctx.emitActivityState("idle", "message_complete", "global", reqId);
@@ -2894,86 +2998,11 @@ export async function runAgentLoopImpl(
2894
2998
  ...(state.lastAssistantMessageId
2895
2999
  ? { messageId: state.lastAssistantMessageId }
2896
3000
  : {}),
3001
+ ...(clientDisplayMessageId
3002
+ ? { displayMessageId: clientDisplayMessageId }
3003
+ : {}),
2897
3004
  });
2898
3005
 
2899
- // Emit a home-feed event for background/scheduled conversation completions.
2900
- // Scoped to message_complete only (not cancelled/handoff), wrapped in
2901
- // try-catch so malformed message content can never propagate errors.
2902
- try {
2903
- const conv = getConversation(ctx.conversationId);
2904
- if (
2905
- conv &&
2906
- (conv.conversationType === "background" ||
2907
- conv.conversationType === "scheduled")
2908
- ) {
2909
- const lastMsg = state.lastAssistantMessageId
2910
- ? getMessageById(state.lastAssistantMessageId, ctx.conversationId)
2911
- : undefined;
2912
- let summary: string;
2913
- if (lastMsg) {
2914
- const parsed: unknown = JSON.parse(lastMsg.content);
2915
- if (typeof parsed === "string") {
2916
- summary = parsed.slice(0, 200);
2917
- } else if (Array.isArray(parsed)) {
2918
- const textBlock = parsed.find(
2919
- (b: { type?: string }) => b.type === "text",
2920
- );
2921
- summary =
2922
- typeof textBlock?.text === "string"
2923
- ? textBlock.text.slice(0, 200)
2924
- : (conv.title ?? "Background task completed.");
2925
- } else {
2926
- summary = conv.title ?? "Background task completed.";
2927
- }
2928
- } else {
2929
- summary = conv.title ?? "Background task completed.";
2930
- }
2931
- const feedTitle =
2932
- conv.title && !isReplaceableTitle(conv.title)
2933
- ? conv.title
2934
- : "Background task";
2935
- const dedupKey = `bg-conv:${ctx.conversationId}`;
2936
- void emitFeedEvent({
2937
- source: "assistant",
2938
- title: feedTitle,
2939
- summary,
2940
- dedupKey,
2941
- conversationId: ctx.conversationId,
2942
- }).catch((err) => {
2943
- log.warn(
2944
- { err, conversationId: ctx.conversationId },
2945
- "Failed to emit background conversation feed event",
2946
- );
2947
- });
2948
-
2949
- if (isReplaceableTitle(conv.title ?? null)) {
2950
- void rewriteFeedTitle(feedTitle)
2951
- .then((prose) => {
2952
- if (prose && prose !== feedTitle) {
2953
- return emitFeedEvent({
2954
- source: "assistant",
2955
- title: prose,
2956
- summary,
2957
- dedupKey,
2958
- conversationId: ctx.conversationId,
2959
- });
2960
- }
2961
- })
2962
- .catch((err) => {
2963
- log.warn(
2964
- { err, conversationId: ctx.conversationId },
2965
- "Failed to update feed event with prose title rewrite",
2966
- );
2967
- });
2968
- }
2969
- }
2970
- } catch (feedErr) {
2971
- log.warn(
2972
- { err: feedErr, conversationId: ctx.conversationId },
2973
- "Failed to build home-feed event for background conversation",
2974
- );
2975
- }
2976
-
2977
3006
  // Proactive artifact: fire once when the processed turn was the 4th user message.
2978
3007
  // Only trigger for real user-authored turns (not subagent/system messages).
2979
3008
  {
@@ -3223,7 +3252,7 @@ export interface CompactionApplyContext {
3223
3252
  * truth for the UI indicator after compaction. Emitting both caused a
3224
3253
  * redundant SwiftUI invalidation on every compaction.
3225
3254
  */
3226
- export function applyCompactionResult(
3255
+ export async function applyCompactionResult(
3227
3256
  ctx: CompactionApplyContext,
3228
3257
  result: {
3229
3258
  messages: Message[];
@@ -3249,12 +3278,12 @@ export function applyCompactionResult(
3249
3278
  options: {
3250
3279
  slackContextCompactionWatermarkTs?: string | null;
3251
3280
  } = {},
3252
- ): void {
3281
+ ): Promise<void> {
3253
3282
  ctx.messages = result.messages;
3254
3283
  ctx.contextCompactedMessageCount += result.compactedPersistedMessages;
3255
3284
  const compactedAt = Date.now();
3256
3285
  ctx.contextCompactedAt = compactedAt;
3257
- ctx.graphMemory.onCompacted(result.compactedPersistedMessages);
3286
+ await ctx.graphMemory.onCompacted(result.compactedPersistedMessages);
3258
3287
  updateConversationContextWindow(
3259
3288
  ctx.conversationId,
3260
3289
  result.summaryText,
@@ -3271,6 +3300,10 @@ export function applyCompactionResult(
3271
3300
  ctx.conversationId,
3272
3301
  ctx.trustContext?.trustClass,
3273
3302
  );
3303
+ enqueueMemoryRetrospectiveOnCompaction(
3304
+ ctx.conversationId,
3305
+ ctx.trustContext?.trustClass,
3306
+ );
3274
3307
  const summarySignals = computeSummaryQualitySignals(result.summaryText);
3275
3308
  onEvent({
3276
3309
  type: "context_compacted",
@@ -120,6 +120,13 @@ const STREAMING_ERROR_PATTERNS = [
120
120
  ];
121
121
 
122
122
  // User-initiated cancellation patterns — these should NOT produce conversation_error
123
+ // Image-input validation patterns — Anthropic 400s with this message when an image
124
+ // block exceeds the per-side pixel cap. Distinct classification matters because
125
+ // retrying with the same oversized image is futile; the user needs to resize.
126
+ const IMAGE_DIMENSIONS_TOO_LARGE_PATTERNS = [
127
+ /image dimensions? exceeds? max allowed size/i,
128
+ ];
129
+
123
130
  const CANCEL_PATTERNS = [/abort/i, /cancel/i];
124
131
 
125
132
  /**
@@ -370,6 +377,15 @@ function classifyCore(
370
377
  errorCategory: "provider_not_configured",
371
378
  };
372
379
  }
380
+ if (isImageDimensionsTooLarge(message)) {
381
+ return {
382
+ code: "IMAGE_TOO_LARGE",
383
+ userMessage:
384
+ "An attached image is too large for the AI provider — image dimensions must be under 8000 pixels per side. Resize the image and try again.",
385
+ retryable: false,
386
+ errorCategory: "image_dimensions_too_large",
387
+ };
388
+ }
373
389
  return {
374
390
  code: "PROVIDER_API",
375
391
  userMessage: "The AI provider rejected the request.",
@@ -388,6 +404,11 @@ export function isContextTooLarge(message: string): boolean {
388
404
  return CONTEXT_TOO_LARGE_PATTERNS.some((p) => p.test(message));
389
405
  }
390
406
 
407
+ /** Check whether an error message indicates an image-input dimension failure. */
408
+ function isImageDimensionsTooLarge(message: string): boolean {
409
+ return IMAGE_DIMENSIONS_TOO_LARGE_PATTERNS.some((p) => p.test(message));
410
+ }
411
+
391
412
  /** Check whether an error message indicates a web-search-specific ordering failure. */
392
413
  function isWebSearchOrderingError(message: string): boolean {
393
414
  return WEB_SEARCH_ORDERING_PATTERNS.some((p) => p.test(message));