@vellumai/assistant 0.8.4 → 0.8.6

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 (802) hide show
  1. package/AGENTS.md +33 -1
  2. package/ARCHITECTURE.md +3 -3
  3. package/bunfig.toml +6 -1
  4. package/docs/browser-use-architecture-phase2.md +1 -1
  5. package/docs/credential-execution-service.md +6 -6
  6. package/docs/plugins.md +4 -3
  7. package/knip.json +2 -1
  8. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
  9. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
  10. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
  11. package/openapi.yaml +2748 -216
  12. package/package.json +1 -1
  13. package/src/__tests__/actor-token-service.test.ts +3 -2
  14. package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
  15. package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
  16. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
  17. package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
  18. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  19. package/src/__tests__/annotate-risk-options.test.ts +1 -0
  20. package/src/__tests__/anthropic-provider.test.ts +34 -37
  21. package/src/__tests__/approval-cascade.test.ts +1 -0
  22. package/src/__tests__/approval-routes-http.test.ts +9 -13
  23. package/src/__tests__/assert-not-live-db.ts +79 -0
  24. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  25. package/src/__tests__/assistant-feature-flags-integration.test.ts +12 -28
  26. package/src/__tests__/audit-log-rotation.test.ts +72 -18
  27. package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
  28. package/src/__tests__/background-workers-disk-pressure.test.ts +8 -11
  29. package/src/__tests__/browser-skill-endstate.test.ts +3 -3
  30. package/src/__tests__/btw-routes.test.ts +5 -5
  31. package/src/__tests__/call-controller.test.ts +3 -3
  32. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  33. package/src/__tests__/channel-approval-routes.test.ts +3 -2
  34. package/src/__tests__/channel-guardian.test.ts +6 -5
  35. package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
  36. package/src/__tests__/channel-reply-delivery.test.ts +35 -0
  37. package/src/__tests__/channel-retry-sweep.test.ts +320 -3
  38. package/src/__tests__/checker.test.ts +18 -27
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/compaction-trail-store.test.ts +264 -0
  41. package/src/__tests__/compactor-call-site-logging.test.ts +215 -0
  42. package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
  43. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +12 -16
  44. package/src/__tests__/computer-use-tools.test.ts +14 -18
  45. package/src/__tests__/config-loader-backfill.test.ts +13 -28
  46. package/src/__tests__/config-loader-corrupt.test.ts +5 -5
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
  48. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
  49. package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
  50. package/src/__tests__/config-schema.test.ts +10 -10
  51. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  52. package/src/__tests__/connection-model-compat.test.ts +83 -0
  53. package/src/__tests__/contacts-tools.test.ts +3 -2
  54. package/src/__tests__/context-token-estimator.test.ts +22 -0
  55. package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
  56. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -1
  57. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
  58. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -1
  59. package/src/__tests__/conversation-agent-loop-overflow.test.ts +231 -2
  60. package/src/__tests__/conversation-agent-loop.test.ts +581 -54
  61. package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
  62. package/src/__tests__/conversation-app-control-instantiation.test.ts +31 -24
  63. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
  64. package/src/__tests__/conversation-attention-store.test.ts +101 -0
  65. package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
  66. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  67. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
  68. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  69. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  70. package/src/__tests__/conversation-error.test.ts +61 -0
  71. package/src/__tests__/conversation-fork-crud.test.ts +239 -15
  72. package/src/__tests__/conversation-fork-route.test.ts +3 -2
  73. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  74. package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
  75. package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
  76. package/src/__tests__/conversation-lifecycle.test.ts +53 -11
  77. package/src/__tests__/conversation-list-source.test.ts +3 -2
  78. package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
  79. package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +14 -13
  80. package/src/__tests__/conversation-pairing.test.ts +53 -0
  81. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
  82. package/src/__tests__/conversation-process-callsite.test.ts +1 -0
  83. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  84. package/src/__tests__/conversation-queue.test.ts +333 -291
  85. package/src/__tests__/conversation-routes-disk-view.test.ts +112 -18
  86. package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
  87. package/src/__tests__/conversation-routes-slash-commands.test.ts +68 -2
  88. package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
  89. package/src/__tests__/conversation-skill-tools.test.ts +40 -147
  90. package/src/__tests__/conversation-slash-queue.test.ts +84 -32
  91. package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
  92. package/src/__tests__/conversation-speed-override.test.ts +1 -0
  93. package/src/__tests__/conversation-store.test.ts +1 -1
  94. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
  95. package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
  96. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
  97. package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
  98. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
  99. package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
  100. package/src/__tests__/conversation-sync-tags.test.ts +218 -35
  101. package/src/__tests__/conversation-title-service.test.ts +1 -0
  102. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
  103. package/src/__tests__/conversation-usage.test.ts +1 -0
  104. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
  105. package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
  106. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -1
  107. package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
  108. package/src/__tests__/credential-broker-server-use.test.ts +5 -5
  109. package/src/__tests__/credential-execution-client.test.ts +72 -1
  110. package/src/__tests__/credential-execution-feature-gates.test.ts +19 -19
  111. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  112. package/src/__tests__/credential-health-service.test.ts +252 -3
  113. package/src/__tests__/credential-security-invariants.test.ts +6 -5
  114. package/src/__tests__/credential-vault-unit.test.ts +21 -21
  115. package/src/__tests__/credential-vault.test.ts +5 -5
  116. package/src/__tests__/cross-provider-web-search.test.ts +56 -2
  117. package/src/__tests__/db-connection-isolation.test.ts +7 -6
  118. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
  119. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
  120. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
  121. package/src/__tests__/db-test-helpers.ts +58 -0
  122. package/src/__tests__/disk-pressure-guard.test.ts +58 -41
  123. package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
  124. package/src/__tests__/disk-pressure-routes.test.ts +0 -33
  125. package/src/__tests__/disk-pressure-tools.test.ts +0 -4
  126. package/src/__tests__/dm-persistence.test.ts +26 -40
  127. package/src/__tests__/document-create-dedupe.test.ts +189 -0
  128. package/src/__tests__/document-find-replace.test.ts +3 -2
  129. package/src/__tests__/document-tool-security.test.ts +81 -2
  130. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  131. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
  132. package/src/__tests__/email-html-renderer.test.ts +12 -0
  133. package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
  134. package/src/__tests__/encrypted-store.test.ts +11 -9
  135. package/src/__tests__/feature-flag-test-helpers.ts +53 -0
  136. package/src/__tests__/filing-service.test.ts +1 -0
  137. package/src/__tests__/first-greeting.test.ts +62 -12
  138. package/src/__tests__/gateway-flag-listener.test.ts +236 -0
  139. package/src/__tests__/gemini-provider.test.ts +104 -0
  140. package/src/__tests__/guardian-action-sweep.test.ts +3 -2
  141. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  142. package/src/__tests__/guardian-outbound-http.test.ts +10 -7
  143. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
  144. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -1
  145. package/src/__tests__/heartbeat-disk-pressure.test.ts +5 -0
  146. package/src/__tests__/heartbeat-service.test.ts +5 -0
  147. package/src/__tests__/helpers/mock-logger.ts +26 -0
  148. package/src/__tests__/host-bash-routes.test.ts +1 -0
  149. package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
  150. package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
  151. package/src/__tests__/host-shell-tool.test.ts +6 -5
  152. package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
  153. package/src/__tests__/http-conversation-lineage.test.ts +3 -2
  154. package/src/__tests__/http-user-message-parity.test.ts +29 -7
  155. package/src/__tests__/identity-intro-cache.test.ts +133 -22
  156. package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
  157. package/src/__tests__/inference-profile-reaper.test.ts +3 -2
  158. package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
  159. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  160. package/src/__tests__/injector-disk-pressure.test.ts +3 -17
  161. package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
  162. package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
  163. package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
  164. package/src/__tests__/llm-context-normalization.test.ts +42 -0
  165. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  166. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  167. package/src/__tests__/llm-resolver.test.ts +408 -9
  168. package/src/__tests__/llm-schema.test.ts +1 -1
  169. package/src/__tests__/llm-usage-store.test.ts +66 -0
  170. package/src/__tests__/logger.test.ts +89 -0
  171. package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
  172. package/src/__tests__/mcp-abort-signal.test.ts +16 -2
  173. package/src/__tests__/mcp-client-auth.test.ts +14 -0
  174. package/src/__tests__/media-generate-image.test.ts +31 -0
  175. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  176. package/src/__tests__/messaging-send-tool.test.ts +1 -0
  177. package/src/__tests__/migration-import-from-url.test.ts +3 -3
  178. package/src/__tests__/mock-gateway-ipc.ts +18 -2
  179. package/src/__tests__/model-intents.test.ts +4 -6
  180. package/src/__tests__/native-web-search.test.ts +30 -2
  181. package/src/__tests__/notification-deep-link.test.ts +62 -0
  182. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  183. package/src/__tests__/oauth-commands-routes.test.ts +37 -0
  184. package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
  185. package/src/__tests__/oauth-store.test.ts +3 -2
  186. package/src/__tests__/onboarding-template-contract.test.ts +4 -3
  187. package/src/__tests__/openai-provider.test.ts +54 -9
  188. package/src/__tests__/openai-responses-provider.test.ts +176 -14
  189. package/src/__tests__/openrouter-provider-only.test.ts +27 -5
  190. package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
  191. package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
  192. package/src/__tests__/persistence-pipeline.test.ts +139 -1
  193. package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
  194. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  195. package/src/__tests__/platform.test.ts +2 -2
  196. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  197. package/src/__tests__/plugin-bootstrap.test.ts +11 -13
  198. package/src/__tests__/plugin-tool-contribution.test.ts +50 -40
  199. package/src/__tests__/plugin-types.test.ts +3 -2
  200. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  201. package/src/__tests__/pricing.test.ts +12 -0
  202. package/src/__tests__/process-message-background-slack.test.ts +21 -16
  203. package/src/__tests__/process-message-display-content.test.ts +19 -22
  204. package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
  205. package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
  206. package/src/__tests__/provider-registry-ollama.test.ts +45 -22
  207. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  208. package/src/__tests__/recording-handler.test.ts +1 -0
  209. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
  210. package/src/__tests__/registry.test.ts +84 -84
  211. package/src/__tests__/relay-server.test.ts +10 -10
  212. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  213. package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
  214. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  215. package/src/__tests__/schedule-store.test.ts +16 -1
  216. package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
  217. package/src/__tests__/secret-ingress-http.test.ts +5 -1
  218. package/src/__tests__/secure-keys.test.ts +3 -3
  219. package/src/__tests__/send-endpoint-busy.test.ts +81 -42
  220. package/src/__tests__/server-history-render.test.ts +4 -1
  221. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  222. package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
  223. package/src/__tests__/skill-feature-flags.test.ts +16 -18
  224. package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
  225. package/src/__tests__/skill-projection-feature-flag.test.ts +48 -37
  226. package/src/__tests__/skill-projection.benchmark.test.ts +7 -13
  227. package/src/__tests__/skill-tool-factory.test.ts +97 -96
  228. package/src/__tests__/slack-channel-config.test.ts +3 -3
  229. package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
  230. package/src/__tests__/subagent-disposal.test.ts +27 -8
  231. package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
  232. package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
  233. package/src/__tests__/subagent-manager-notify.test.ts +20 -8
  234. package/src/__tests__/subagent-notify-parent.test.ts +6 -5
  235. package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
  236. package/src/__tests__/subagent-tools.test.ts +2 -1
  237. package/src/__tests__/suggestion-routes.test.ts +2 -0
  238. package/src/__tests__/sync-message-contract.test.ts +59 -0
  239. package/src/__tests__/system-prompt.test.ts +183 -131
  240. package/src/__tests__/terminal-tools.test.ts +1 -1
  241. package/src/__tests__/test-preload-verifier.ts +68 -0
  242. package/src/__tests__/test-preload.ts +32 -39
  243. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  244. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  245. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  246. package/src/__tests__/tool-executor-lifecycle-events.test.ts +35 -12
  247. package/src/__tests__/tool-executor.test.ts +64 -72
  248. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  249. package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
  250. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  251. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  252. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  253. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  254. package/src/__tests__/twilio-routes.test.ts +3 -2
  255. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  256. package/src/__tests__/usage-routes.test.ts +3 -0
  257. package/src/__tests__/validate-input.test.ts +381 -0
  258. package/src/__tests__/verification-control-plane-policy.test.ts +3 -2
  259. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
  260. package/src/__tests__/voice-session-bridge.test.ts +37 -28
  261. package/src/__tests__/workspace-git-service.test.ts +6 -5
  262. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  263. package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
  264. package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
  265. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  266. package/src/acp/prepare-agent-env.ts +78 -0
  267. package/src/acp/session-manager.ts +6 -7
  268. package/src/agent/loop.ts +88 -0
  269. package/src/api/README.md +127 -0
  270. package/src/api/constants/call-sites.ts +27 -0
  271. package/src/api/events/assistant-outbound-attachment.ts +51 -0
  272. package/src/api/events/assistant-text-delta.ts +32 -0
  273. package/src/api/events/assistant-turn-start.ts +33 -0
  274. package/src/api/events/document-comment-created.ts +48 -0
  275. package/src/api/events/document-comment-deleted.ts +24 -0
  276. package/src/api/events/document-comment-reopened.ts +25 -0
  277. package/src/api/events/document-comment-resolved.ts +27 -0
  278. package/src/api/events/generation-cancelled.ts +24 -0
  279. package/src/api/events/generation-handoff.ts +41 -0
  280. package/src/api/events/message-complete.ts +42 -0
  281. package/src/api/events/open-url.ts +30 -0
  282. package/src/api/events/relationship-state-updated.ts +25 -0
  283. package/src/api/events/tool-use-start.ts +32 -0
  284. package/src/api/index.ts +129 -0
  285. package/src/api/package.json +10 -0
  286. package/src/api/responses/llm-context-response.ts +39 -0
  287. package/src/api/responses/llm-request-log-entry.ts +93 -0
  288. package/src/api/responses/memory-recall-log.ts +65 -0
  289. package/src/api/responses/memory-v2-activation-log.ts +78 -0
  290. package/src/background-wake/background-wake-routes.test.ts +868 -0
  291. package/src/background-wake/platform-client.test.ts +308 -0
  292. package/src/background-wake/platform-client.ts +167 -0
  293. package/src/background-wake/publisher.ts +91 -0
  294. package/src/background-wake/runtime-registry.ts +24 -0
  295. package/src/background-wake/wake-intent-hooks.test.ts +282 -0
  296. package/src/calls/guardian-dispatch.ts +1 -0
  297. package/src/calls/voice-session-bridge.ts +4 -4
  298. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  299. package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
  300. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  301. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  302. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  303. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  304. package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
  305. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  306. package/src/cli/commands/__tests__/notifications.test.ts +184 -40
  307. package/src/cli/commands/browser.ts +247 -0
  308. package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
  309. package/src/cli/commands/channels/index.ts +229 -0
  310. package/src/cli/commands/domain.ts +91 -41
  311. package/src/cli/commands/inference.ts +93 -40
  312. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  313. package/src/cli/commands/memory-v2.ts +176 -1
  314. package/src/cli/commands/memory-v3-render.ts +491 -0
  315. package/src/cli/commands/memory-v3.ts +567 -0
  316. package/src/cli/commands/notifications.ts +365 -55
  317. package/src/cli/lib/open-browser.ts +7 -2
  318. package/src/cli/program.ts +4 -0
  319. package/src/config/assistant-feature-flags.ts +39 -46
  320. package/src/config/bundled-skills/document-editor/SKILL.md +16 -3
  321. package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
  322. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  323. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  324. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  325. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  326. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  327. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  328. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  329. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  330. package/src/config/bundled-skills/schedule/SKILL.md +1 -1
  331. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  332. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
  333. package/src/config/bundled-tool-registry.ts +2 -0
  334. package/src/config/call-site-defaults.ts +8 -7
  335. package/src/config/feature-flag-cache.ts +86 -0
  336. package/src/config/feature-flag-registry.json +33 -17
  337. package/src/config/llm-context-resolution.ts +10 -1
  338. package/src/config/llm-resolver.ts +121 -15
  339. package/src/config/loader.ts +4 -5
  340. package/src/config/schemas/__tests__/memory-v2.test.ts +228 -1
  341. package/src/config/schemas/call-site-catalog.ts +21 -7
  342. package/src/config/schemas/heartbeat.ts +1 -1
  343. package/src/config/schemas/llm.ts +102 -2
  344. package/src/config/schemas/memory-v2.ts +272 -0
  345. package/src/config/schemas/memory.ts +2 -1
  346. package/src/config/schemas/services.ts +6 -2
  347. package/src/config/seed-inference-profiles.ts +36 -16
  348. package/src/context/compactor.ts +52 -0
  349. package/src/context/token-estimator.ts +10 -5
  350. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  351. package/src/conversations/message-consolidation.ts +404 -0
  352. package/src/credential-execution/executable-discovery.ts +40 -0
  353. package/src/credential-execution/process-manager.ts +6 -2
  354. package/src/credential-health/credential-health-service.ts +125 -40
  355. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
  356. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
  357. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +2 -3
  358. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
  359. package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
  360. package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
  361. package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
  362. package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
  363. package/src/daemon/conversation-agent-loop-handlers.ts +390 -80
  364. package/src/daemon/conversation-agent-loop.ts +244 -90
  365. package/src/daemon/conversation-error.ts +64 -6
  366. package/src/daemon/conversation-lifecycle.ts +27 -22
  367. package/src/daemon/conversation-messaging.ts +84 -43
  368. package/src/daemon/conversation-process.ts +74 -37
  369. package/src/daemon/conversation-runtime-assembly.ts +38 -17
  370. package/src/daemon/conversation-skill-tools.ts +14 -30
  371. package/src/daemon/conversation-surfaces.ts +69 -34
  372. package/src/daemon/conversation-tool-setup.ts +77 -32
  373. package/src/daemon/conversation-usage.ts +2 -0
  374. package/src/daemon/conversation.ts +40 -75
  375. package/src/daemon/daemon-control.ts +1 -1
  376. package/src/daemon/daemon-skill-host.ts +9 -2
  377. package/src/daemon/disk-pressure-guard.ts +39 -29
  378. package/src/daemon/first-greeting.ts +31 -13
  379. package/src/daemon/handlers/config-model.test.ts +1 -0
  380. package/src/daemon/handlers/conversations.ts +11 -3
  381. package/src/daemon/handlers/shared.ts +6 -1
  382. package/src/daemon/host-browser-proxy.ts +5 -5
  383. package/src/daemon/host-cu-proxy.ts +4 -4
  384. package/src/daemon/host-file-proxy.ts +4 -4
  385. package/src/daemon/host-proxy-base.ts +4 -4
  386. package/src/daemon/host-transfer-proxy.ts +10 -10
  387. package/src/daemon/lifecycle.ts +29 -26
  388. package/src/daemon/mcp-reload-service.ts +1 -1
  389. package/src/daemon/meet-manifest-loader.ts +11 -24
  390. package/src/daemon/message-types/conversations.ts +22 -27
  391. package/src/daemon/message-types/document-comments.ts +8 -44
  392. package/src/daemon/message-types/home.ts +2 -14
  393. package/src/daemon/message-types/integrations.ts +2 -7
  394. package/src/daemon/message-types/messages.ts +25 -48
  395. package/src/daemon/message-types/subagents.ts +6 -0
  396. package/src/daemon/message-types/sync.ts +14 -0
  397. package/src/daemon/process-message.ts +9 -9
  398. package/src/daemon/providers-setup.ts +1 -1
  399. package/src/daemon/server.ts +16 -0
  400. package/src/daemon/shutdown-handlers.ts +24 -5
  401. package/src/daemon/switch-inference-profile-tool.ts +62 -0
  402. package/src/daemon/tool-setup-types.ts +7 -0
  403. package/src/daemon/wake-target-adapter.ts +10 -0
  404. package/src/documents/document-store.ts +38 -0
  405. package/src/export/__tests__/transcript-formatter.test.ts +1 -0
  406. package/src/heartbeat/__tests__/heartbeat-service.test.ts +30 -1
  407. package/src/heartbeat/heartbeat-service.ts +63 -0
  408. package/src/home/__tests__/feed-writer.test.ts +161 -0
  409. package/src/home/__tests__/post-connect-feed.test.ts +1 -0
  410. package/src/home/__tests__/suggested-prompts.test.ts +55 -59
  411. package/src/home/feed-writer.ts +146 -7
  412. package/src/home/home-greeting.ts +0 -9
  413. package/src/home/suggested-prompts.ts +27 -154
  414. package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
  415. package/src/ipc/gateway-client.test.ts +4 -1
  416. package/src/ipc/gateway-flag-listener.ts +123 -0
  417. package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
  418. package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
  419. package/src/ipc/skill-routes/memory.ts +4 -3
  420. package/src/ipc/skill-routes/registries.ts +35 -40
  421. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  422. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  423. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +242 -0
  424. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  425. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
  426. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
  427. package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
  428. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
  429. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
  430. package/src/memory/auto-analysis-enqueue.ts +5 -1
  431. package/src/memory/conversation-attention-store.ts +17 -3
  432. package/src/memory/conversation-crud.ts +423 -182
  433. package/src/memory/conversation-starters-cadence.ts +3 -1
  434. package/src/memory/conversation-title-service.ts +19 -3
  435. package/src/memory/db-async-query.ts +214 -0
  436. package/src/memory/db-connection.ts +29 -19
  437. package/src/memory/db-init.ts +14 -0
  438. package/src/memory/db-maintenance.ts +30 -21
  439. package/src/memory/db-singleton.ts +77 -0
  440. package/src/memory/delivery-channels.ts +82 -0
  441. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
  442. package/src/memory/graph/bootstrap.ts +8 -1
  443. package/src/memory/graph/capability-seed.ts +7 -3
  444. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  445. package/src/memory/graph/extraction.ts +1 -5
  446. package/src/memory/graph/graph-search.ts +7 -1
  447. package/src/memory/graph/retriever.test.ts +3 -3
  448. package/src/memory/indexer.ts +28 -18
  449. package/src/memory/job-handlers/cleanup.ts +76 -18
  450. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  451. package/src/memory/job-handlers/embedding.test.ts +3 -2
  452. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
  453. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  454. package/src/memory/jobs-store.ts +14 -0
  455. package/src/memory/jobs-worker.ts +66 -22
  456. package/src/memory/llm-request-log-source-clickhouse.ts +122 -2
  457. package/src/memory/llm-request-log-source-local.ts +31 -0
  458. package/src/memory/llm-request-log-source.ts +40 -2
  459. package/src/memory/llm-request-log-store.ts +228 -1
  460. package/src/memory/llm-usage-store.ts +24 -0
  461. package/src/memory/memory-retrospective-enqueue.ts +8 -1
  462. package/src/memory/memory-retrospective-job.ts +5 -0
  463. package/src/memory/memory-v2-activation-log-store.ts +110 -7
  464. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  465. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  466. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  467. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  468. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  469. package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
  470. package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
  471. package/src/memory/migrations/index.ts +19 -0
  472. package/src/memory/migrations/registry.ts +33 -0
  473. package/src/memory/schema/conversations.ts +10 -2
  474. package/src/memory/schema/inference.ts +0 -1
  475. package/src/memory/schema/infrastructure.ts +21 -0
  476. package/src/memory/tool-usage-store.ts +36 -8
  477. package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
  478. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  479. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  480. package/src/memory/v2/__tests__/harness-metrics.test.ts +83 -0
  481. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  482. package/src/memory/v2/__tests__/harness-replay-input.test.ts +230 -0
  483. package/src/memory/v2/__tests__/harness-runner.test.ts +135 -0
  484. package/src/memory/v2/__tests__/injection.test.ts +127 -98
  485. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  486. package/src/memory/v2/__tests__/router.test.ts +171 -3
  487. package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
  488. package/src/memory/v2/harness/compare.ts +57 -0
  489. package/src/memory/v2/harness/metrics.ts +128 -0
  490. package/src/memory/v2/harness/oracle.ts +145 -0
  491. package/src/memory/v2/harness/replay-input.ts +240 -0
  492. package/src/memory/v2/harness/retriever.ts +74 -0
  493. package/src/memory/v2/harness/router-retriever.ts +43 -0
  494. package/src/memory/v2/harness/runner.ts +112 -0
  495. package/src/memory/v2/harness/trace.ts +64 -0
  496. package/src/memory/v2/injection.ts +21 -15
  497. package/src/memory/v2/prompts/router.ts +26 -1
  498. package/src/memory/v2/qdrant.ts +14 -2
  499. package/src/memory/v2/router.ts +171 -18
  500. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  501. package/src/memory/v3/__tests__/consolidation-job.test.ts +466 -0
  502. package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
  503. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  504. package/src/memory/v3/__tests__/edges.test.ts +706 -0
  505. package/src/memory/v3/__tests__/filter.test.ts +560 -0
  506. package/src/memory/v3/__tests__/gate.test.ts +637 -0
  507. package/src/memory/v3/__tests__/index-composition.test.ts +291 -0
  508. package/src/memory/v3/__tests__/loop.test.ts +775 -0
  509. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  510. package/src/memory/v3/__tests__/scouts.test.ts +489 -0
  511. package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
  512. package/src/memory/v3/__tests__/shadow-middleware.test.ts +398 -0
  513. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  514. package/src/memory/v3/__tests__/traversal.test.ts +508 -0
  515. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  516. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  517. package/src/memory/v3/__tests__/tree-walk.test.ts +784 -0
  518. package/src/memory/v3/__tests__/validate.test.ts +277 -0
  519. package/src/memory/v3/auto-edges.ts +223 -0
  520. package/src/memory/v3/coactivation-store.ts +124 -0
  521. package/src/memory/v3/consolidation-job.ts +323 -0
  522. package/src/memory/v3/coretrieval-seed.ts +240 -0
  523. package/src/memory/v3/edge-learning-job.ts +160 -0
  524. package/src/memory/v3/edges.ts +286 -0
  525. package/src/memory/v3/filter.ts +286 -0
  526. package/src/memory/v3/gate.ts +349 -0
  527. package/src/memory/v3/index-composition.ts +126 -0
  528. package/src/memory/v3/llm-capture.ts +46 -0
  529. package/src/memory/v3/loop.ts +430 -0
  530. package/src/memory/v3/maintenance.ts +144 -0
  531. package/src/memory/v3/prompt-context.ts +33 -0
  532. package/src/memory/v3/prompts/consolidation.ts +458 -0
  533. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  534. package/src/memory/v3/retriever.ts +33 -0
  535. package/src/memory/v3/scouts.ts +431 -0
  536. package/src/memory/v3/shadow-diff.ts +287 -0
  537. package/src/memory/v3/shadow-middleware.ts +347 -0
  538. package/src/memory/v3/traversal.ts +211 -0
  539. package/src/memory/v3/tree-index.ts +237 -0
  540. package/src/memory/v3/tree-store.ts +394 -0
  541. package/src/memory/v3/tree-walk.ts +356 -0
  542. package/src/memory/v3/types.ts +65 -0
  543. package/src/memory/v3/validate.ts +323 -0
  544. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  545. package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
  546. package/src/notifications/adapters/macos.ts +18 -1
  547. package/src/notifications/adapters/platform.ts +1 -1
  548. package/src/notifications/adapters/slack.ts +45 -11
  549. package/src/notifications/broadcaster.ts +114 -63
  550. package/src/notifications/conversation-pairing.ts +23 -3
  551. package/src/notifications/decision-engine.ts +1 -4
  552. package/src/notifications/decisions-store.ts +32 -1
  553. package/src/notifications/deliveries-store.ts +45 -0
  554. package/src/notifications/edit-notification.ts +201 -0
  555. package/src/notifications/emit-signal.ts +40 -50
  556. package/src/notifications/signal.ts +10 -0
  557. package/src/notifications/types.ts +37 -0
  558. package/src/oauth/byo-connection.test.ts +67 -3
  559. package/src/oauth/byo-connection.ts +32 -5
  560. package/src/oauth/connect-orchestrator.ts +9 -0
  561. package/src/oauth/connection-resolver.test.ts +76 -0
  562. package/src/oauth/connection-resolver.ts +49 -10
  563. package/src/oauth/manual-token-connection.ts +51 -3
  564. package/src/oauth/seed-providers.ts +3 -0
  565. package/src/permissions/approval-policy.test.ts +19 -5
  566. package/src/permissions/approval-policy.ts +14 -3
  567. package/src/permissions/checker.ts +21 -8
  568. package/src/permissions/prompter.ts +3 -3
  569. package/src/permissions/question-prompter.ts +5 -2
  570. package/src/permissions/secret-prompter.ts +2 -2
  571. package/src/platform/client.test.ts +24 -1
  572. package/src/platform/client.ts +8 -0
  573. package/src/platform/feature-gate.ts +15 -0
  574. package/src/plugin-api/index.ts +4 -0
  575. package/src/plugin-api/types.ts +7 -33
  576. package/src/plugins/defaults/index.ts +6 -0
  577. package/src/plugins/defaults/injectors.ts +20 -19
  578. package/src/plugins/defaults/persistence.ts +25 -6
  579. package/src/plugins/external-plugin-loader.ts +5 -68
  580. package/src/plugins/types.ts +68 -29
  581. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  582. package/src/proactive-artifact/job.test.ts +1 -0
  583. package/src/prompts/__tests__/system-prompt.test.ts +4 -4
  584. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  585. package/src/prompts/persona-resolver.ts +36 -21
  586. package/src/prompts/sections.ts +39 -7
  587. package/src/prompts/system-prompt.ts +84 -221
  588. package/src/prompts/template-detection.ts +10 -4
  589. package/src/prompts/templates/BOOTSTRAP.md +9 -13
  590. package/src/prompts/templates/IDENTITY.md +0 -2
  591. package/src/prompts/templates/system-sections.ts +230 -8
  592. package/src/providers/__tests__/connection-model-compat.test.ts +233 -0
  593. package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
  594. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  595. package/src/providers/anthropic/client.ts +32 -66
  596. package/src/providers/call-site-routing.ts +42 -6
  597. package/src/providers/connection-model-compat.ts +61 -0
  598. package/src/providers/connection-resolution.ts +47 -14
  599. package/src/providers/fireworks/client.ts +1 -0
  600. package/src/providers/gemini/client.ts +70 -6
  601. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
  602. package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
  603. package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
  604. package/src/providers/inference/adapter-factory.ts +3 -0
  605. package/src/providers/inference/auth.ts +0 -8
  606. package/src/providers/inference/connections.ts +3 -66
  607. package/src/providers/inference/resolve-auth.ts +2 -3
  608. package/src/providers/minimax/client.ts +106 -0
  609. package/src/providers/model-catalog.ts +78 -1
  610. package/src/providers/model-intents.ts +4 -4
  611. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  612. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
  613. package/src/providers/openai/chat-completions-provider.ts +116 -15
  614. package/src/providers/openai/codex-models.ts +20 -0
  615. package/src/providers/openai/responses-provider.ts +87 -30
  616. package/src/providers/openrouter/client.ts +13 -8
  617. package/src/providers/provider-send-message.ts +20 -5
  618. package/src/providers/registry.ts +48 -8
  619. package/src/providers/retry.ts +50 -7
  620. package/src/providers/search-provider-catalog.ts +17 -9
  621. package/src/providers/thinking-config.ts +26 -1
  622. package/src/providers/types.ts +9 -0
  623. package/src/providers/usage-tracking.ts +2 -0
  624. package/src/runtime/AGENTS.md +2 -2
  625. package/src/runtime/__tests__/agent-wake.test.ts +1 -0
  626. package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
  627. package/src/runtime/access-request-helper.ts +1 -0
  628. package/src/runtime/agent-wake.ts +1 -0
  629. package/src/runtime/assistant-event-hub.ts +76 -6
  630. package/src/runtime/auth/route-policy.ts +46 -0
  631. package/src/runtime/btw-sidechain.ts +0 -6
  632. package/src/runtime/channel-readiness-service.ts +68 -0
  633. package/src/runtime/channel-reply-delivery.ts +23 -0
  634. package/src/runtime/channel-retry-sweep.ts +47 -14
  635. package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
  636. package/src/runtime/http-types.ts +0 -2
  637. package/src/runtime/migrations/vbundle-builder.ts +12 -4
  638. package/src/runtime/pending-interactions.ts +0 -1
  639. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
  640. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
  641. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +204 -0
  642. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  643. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
  644. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
  645. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +76 -9
  646. package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
  647. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  648. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
  649. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
  650. package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
  651. package/src/runtime/routes/acp-routes-list.test.ts +3 -0
  652. package/src/runtime/routes/acp-routes.test.ts +255 -6
  653. package/src/runtime/routes/acp-routes.ts +8 -1
  654. package/src/runtime/routes/app-management-routes.ts +111 -4
  655. package/src/runtime/routes/avatar-routes.ts +10 -10
  656. package/src/runtime/routes/background-wake-routes.ts +356 -0
  657. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  658. package/src/runtime/routes/btw-routes.ts +4 -10
  659. package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
  660. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  661. package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
  662. package/src/runtime/routes/conversation-list-routes.ts +159 -4
  663. package/src/runtime/routes/conversation-management-routes.ts +108 -26
  664. package/src/runtime/routes/conversation-query-routes.ts +200 -44
  665. package/src/runtime/routes/conversation-routes.ts +409 -521
  666. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  667. package/src/runtime/routes/conversations-import-routes.ts +19 -6
  668. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  669. package/src/runtime/routes/documents-routes.ts +10 -1
  670. package/src/runtime/routes/domain-routes.ts +60 -10
  671. package/src/runtime/routes/email-routes.ts +5 -2
  672. package/src/runtime/routes/events-routes.ts +54 -10
  673. package/src/runtime/routes/group-routes.ts +35 -8
  674. package/src/runtime/routes/home-feed-routes.ts +129 -0
  675. package/src/runtime/routes/host-browser-routes.ts +10 -2
  676. package/src/runtime/routes/host-cu-routes.ts +2 -2
  677. package/src/runtime/routes/identity-intro-cache.ts +61 -16
  678. package/src/runtime/routes/identity-routes.ts +30 -9
  679. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  680. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
  681. package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
  682. package/src/runtime/routes/index.ts +10 -0
  683. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  684. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  685. package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
  686. package/src/runtime/routes/integrations/vercel.ts +15 -0
  687. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  688. package/src/runtime/routes/llm-context-normalization.ts +7 -2
  689. package/src/runtime/routes/memory-item-routes.ts +8 -3
  690. package/src/runtime/routes/memory-v2-routes.ts +215 -5
  691. package/src/runtime/routes/memory-v3-routes.ts +474 -0
  692. package/src/runtime/routes/migration-routes.ts +32 -28
  693. package/src/runtime/routes/notification-routes.ts +63 -1
  694. package/src/runtime/routes/oauth-commands-routes.ts +6 -1
  695. package/src/runtime/routes/plugins-routes.ts +337 -0
  696. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  697. package/src/runtime/routes/secret-routes.ts +25 -5
  698. package/src/runtime/routes/settings-routes.ts +12 -11
  699. package/src/runtime/routes/slack-channel-routes.ts +5 -4
  700. package/src/runtime/routes/surface-action-routes.ts +1 -38
  701. package/src/runtime/routes/surface-content-routes.ts +12 -5
  702. package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
  703. package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
  704. package/src/runtime/routes/workspace-routes.ts +25 -10
  705. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
  706. package/src/runtime/slack-dm-text-delivery.ts +177 -0
  707. package/src/runtime/sync/resource-sync-events.ts +106 -38
  708. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  709. package/src/runtime/sync/sync-publisher.ts +2 -1
  710. package/src/runtime/tool-grant-request-helper.ts +1 -0
  711. package/src/runtime/verification-outbound-actions.ts +73 -1
  712. package/src/schedule/schedule-store.ts +8 -1
  713. package/src/schedule/scheduler.ts +111 -15
  714. package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
  715. package/src/security/encrypted-store.ts +7 -16
  716. package/src/security/store-path-override.ts +61 -0
  717. package/src/signals/user-message.ts +5 -8
  718. package/src/skills/validate-input.ts +177 -0
  719. package/src/subagent/manager.ts +13 -13
  720. package/src/subagent/types.ts +6 -0
  721. package/src/tasks/tool-sanitizer.ts +2 -2
  722. package/src/telemetry/types.ts +12 -0
  723. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  724. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  725. package/src/tools/acp/spawn.test.ts +119 -0
  726. package/src/tools/acp/spawn.ts +15 -2
  727. package/src/tools/apps/definitions.ts +36 -28
  728. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  729. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  730. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
  731. package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
  732. package/src/tools/browser/browser-execution.ts +16 -3
  733. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  734. package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
  735. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
  736. package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
  737. package/src/tools/browser/cdp-client/factory.ts +100 -17
  738. package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
  739. package/src/tools/browser/cdp-client/types.ts +65 -0
  740. package/src/tools/browser/pinned-tabs.ts +96 -40
  741. package/src/tools/computer-use/definitions.ts +282 -336
  742. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  743. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  744. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  745. package/src/tools/credentials/vault.ts +3 -9
  746. package/src/tools/document/document-tool.ts +189 -7
  747. package/src/tools/execution-target.ts +18 -23
  748. package/src/tools/executor.ts +24 -56
  749. package/src/tools/filesystem/edit.ts +3 -9
  750. package/src/tools/filesystem/list.ts +3 -9
  751. package/src/tools/filesystem/read.ts +3 -9
  752. package/src/tools/filesystem/write.ts +3 -9
  753. package/src/tools/host-filesystem/edit.test.ts +1 -0
  754. package/src/tools/host-filesystem/edit.ts +3 -9
  755. package/src/tools/host-filesystem/read.test.ts +1 -0
  756. package/src/tools/host-filesystem/read.ts +3 -9
  757. package/src/tools/host-filesystem/transfer.test.ts +31 -6
  758. package/src/tools/host-filesystem/transfer.ts +3 -9
  759. package/src/tools/host-filesystem/write.test.ts +1 -0
  760. package/src/tools/host-filesystem/write.ts +3 -9
  761. package/src/tools/host-terminal/host-shell.ts +3 -9
  762. package/src/tools/mcp/mcp-tool-factory.ts +1 -10
  763. package/src/tools/memory/register.test.ts +1 -1
  764. package/src/tools/memory/register.ts +4 -9
  765. package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
  766. package/src/tools/network/__tests__/web-search.test.ts +211 -3
  767. package/src/tools/network/managed-search-proxy.ts +183 -0
  768. package/src/tools/network/web-fetch.ts +3 -9
  769. package/src/tools/network/web-search.ts +224 -76
  770. package/src/tools/policy-context.ts +3 -1
  771. package/src/tools/registry.ts +150 -123
  772. package/src/tools/schedule/create.ts +1 -1
  773. package/src/tools/schema-transforms.ts +1 -1
  774. package/src/tools/skills/execute.ts +3 -9
  775. package/src/tools/skills/load.ts +3 -9
  776. package/src/tools/skills/skill-tool-factory.ts +18 -44
  777. package/src/tools/subagent/notify-parent.ts +3 -9
  778. package/src/tools/subagent/spawn.ts +3 -0
  779. package/src/tools/system/request-permission.ts +3 -9
  780. package/src/tools/terminal/shell.ts +3 -9
  781. package/src/tools/tool-approval-handler.ts +10 -4
  782. package/src/tools/tool-defaults.ts +94 -0
  783. package/src/tools/tool-name-aliases.ts +72 -14
  784. package/src/tools/types.ts +32 -101
  785. package/src/tools/ui-surface/definitions.ts +104 -108
  786. package/src/types/onboarding-context.ts +6 -0
  787. package/src/usage/attribution.ts +32 -1
  788. package/src/usage/pricing.ts +23 -0
  789. package/src/usage/types.ts +12 -0
  790. package/src/util/browser.ts +7 -2
  791. package/src/util/logger.ts +16 -7
  792. package/src/util/platform.ts +7 -2
  793. package/src/util/sqlite3-runtime.ts +65 -0
  794. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  795. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  796. package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
  797. package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
  798. package/src/workspace/migrations/registry.ts +6 -0
  799. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  800. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  801. package/src/daemon/query-complexity-router.ts +0 -75
  802. package/src/prompts/cache-boundary.ts +0 -8
@@ -26,7 +26,6 @@ import type {
26
26
  TurnChannelContext,
27
27
  TurnInterfaceContext,
28
28
  } from "../channels/types.js";
29
- import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
30
29
  import {
31
30
  contextWindowConfigFromEffective,
32
31
  type EffectiveContextWindow,
@@ -60,7 +59,7 @@ import { commitAppTurnChanges } from "../memory/app-git-service.js";
60
59
  import { getApp, listAppFiles, resolveAppDir } from "../memory/app-store.js";
61
60
  import { enqueueAutoAnalysisOnCompaction } from "../memory/auto-analysis-enqueue.js";
62
61
  import {
63
- clearStrippedInjectionMetadataForConversation,
62
+ deleteMessageById,
64
63
  getConversation,
65
64
  getConversationOriginChannel,
66
65
  getConversationOriginInterface,
@@ -68,6 +67,7 @@ import {
68
67
  getLastUserTimestampBefore,
69
68
  getMessageById,
70
69
  provenanceFromTrustContext,
70
+ setConversationHistoryStrippedAt,
71
71
  setLastNotifiedInferenceProfile,
72
72
  updateConversationContextWindow,
73
73
  updateConversationSlackContextWatermark,
@@ -80,7 +80,10 @@ import {
80
80
  } from "../memory/conversation-title-service.js";
81
81
  import { isBackgroundConversationType } from "../memory/conversation-types.js";
82
82
  import type { ConversationGraphMemory } from "../memory/graph/conversation-graph-memory.js";
83
- import { backfillMessageIdOnLogs } from "../memory/llm-request-log-store.js";
83
+ import {
84
+ backfillMessageIdOnLogs,
85
+ recordSyntheticAgentErrorMessageLog,
86
+ } from "../memory/llm-request-log-store.js";
84
87
  import { recordMemoryRecallLog } from "../memory/memory-recall-log-store.js";
85
88
  import { enqueueMemoryRetrospectiveOnCompaction } from "../memory/memory-retrospective-enqueue.js";
86
89
  import { PKB_WORKSPACE_SCOPE } from "../memory/pkb/types.js";
@@ -163,13 +166,13 @@ import {
163
166
  createEventHandlerState,
164
167
  dispatchAgentEvent,
165
168
  type EventHandlerDeps,
166
- getClientDisplayMessageId,
167
169
  } from "./conversation-agent-loop-handlers.js";
168
170
  import {
169
171
  approveHostAttachmentRead,
170
172
  resolveAssistantAttachments,
171
173
  } from "./conversation-attachments.js";
172
174
  import {
175
+ budgetYieldUnrecoveredClassification,
173
176
  buildConversationErrorMessage,
174
177
  classifyConversationError,
175
178
  isUserCancellation,
@@ -217,20 +220,37 @@ import type {
217
220
  } from "./message-protocol.js";
218
221
  import type { MemoryRecalled } from "./message-types/memory.js";
219
222
  import type { ConfirmationStateChanged } from "./message-types/messages.js";
220
- import {
221
- conversationMetadataSyncTag,
222
- SYNC_TAGS,
223
- } from "./message-types/sync.js";
223
+ import { conversationMetadataSyncTag } from "./message-types/sync.js";
224
224
  import { parseActualTokensFromError } from "./parse-actual-tokens-from-error.js";
225
- import {
226
- classifyQueryComplexity,
227
- complexityTierToProfileKey,
228
- } from "./query-complexity-router.js";
229
225
  import type { TraceEmitter } from "./trace-emitter.js";
230
226
  import type { TrustContext } from "./trust-context.js";
231
227
  import { stripHistoricalWebSearchResults } from "./web-search-history.js";
232
228
 
233
229
  const log = getLogger("conversation-agent-loop");
230
+
231
+ /**
232
+ * Best-effort persistence of the history-stripped marker after an
233
+ * injection-strip event (compaction / overflow recovery). The marker is a
234
+ * durability hint, not turn-critical state — a transient SQLite write failure
235
+ * (SQLITE_BUSY, disk-full, read-only FS) must not abort the turn. Logs a
236
+ * warning and continues on failure, preserving the long-standing non-fatal
237
+ * contract for this metadata write.
238
+ */
239
+ function markHistoryStrippedBestEffort(
240
+ conversationId: string,
241
+ strippedAt: number,
242
+ logger: ReturnType<typeof getLogger>,
243
+ ): void {
244
+ try {
245
+ setConversationHistoryStrippedAt(conversationId, strippedAt);
246
+ } catch (err) {
247
+ logger.warn(
248
+ { err },
249
+ "Failed to persist history-stripped marker after compaction strip (non-fatal)",
250
+ );
251
+ }
252
+ }
253
+
234
254
  const DISK_PRESSURE_ERROR_CODE = "DISK_SPACE_CRITICAL" as const;
235
255
  const DISK_PRESSURE_ERROR_CATEGORY = "disk_pressure";
236
256
 
@@ -518,7 +538,12 @@ export interface AgentLoopConversationContext {
518
538
  surfaceType: SurfaceType;
519
539
  title?: string;
520
540
  data: SurfaceData;
521
- actions?: Array<{ id: string; label: string; style?: string }>;
541
+ actions?: Array<{
542
+ id: string;
543
+ label: string;
544
+ style?: string;
545
+ data?: Record<string, unknown>;
546
+ }>;
522
547
  display?: string;
523
548
  persistent?: boolean;
524
549
  }>;
@@ -539,6 +564,13 @@ export interface AgentLoopConversationContext {
539
564
  * is inherited by later tool executions and nested subagents.
540
565
  */
541
566
  currentTurnOverrideProfile?: string;
567
+ /**
568
+ * Set by the `switch_inference_profile` tool when the model self-selects a
569
+ * different profile mid-turn. Read by `readCurrentOverrideProfile` in the
570
+ * agent loop so the next LLM call uses the switched profile. Reset at
571
+ * turn start.
572
+ */
573
+ toolRoutedProfile?: string;
542
574
  commandIntent?: { type: string; payload?: string; languageCode?: string };
543
575
  trustContext?: TrustContext;
544
576
  /** Task-run scope for the current turn. Cleared at turn end so queued/drained turns don't inherit it. */
@@ -681,6 +713,13 @@ export async function runAgentLoopImpl(
681
713
  let yieldedForHandoff = false;
682
714
  let yieldedForBudget = false;
683
715
  let pendingCheckpointYield: "budget" | "handoff" | null = null;
716
+ // Captured when the auto_compress_latest_turn rerun yields at the mid-loop
717
+ // budget checkpoint. SSE emission happens immediately at the detection site;
718
+ // assistant-row persistence is deferred until after the pendingToolResults
719
+ // flush so we don't orphan tool_use/tool_result pairs in the durable history.
720
+ let budgetYieldClassification: ReturnType<
721
+ typeof budgetYieldUnrecoveredClassification
722
+ > | null = null;
684
723
  let emitTerminalExit:
685
724
  | ((reason: AgentLoopExitReason) => Promise<void>)
686
725
  | null = null;
@@ -711,61 +750,32 @@ export async function runAgentLoopImpl(
711
750
 
712
751
  const config = getConfig();
713
752
 
714
- // Query complexity routing: when no explicit user override is set and the
715
- // feature flag is enabled, classify the query and route to the appropriate
716
- // profile for this turn. The override is ephemeral (not persisted).
717
- let turnOverrideProfile = userExplicitOverride;
718
- if (
719
- !userExplicitOverride &&
720
- turnCallSite === "mainAgent" &&
721
- isAssistantFeatureFlagEnabled("query-complexity-routing", config)
722
- ) {
723
- const tier = await classifyQueryComplexity(content);
724
- if (tier && tier !== "balanced") {
725
- const routedProfile = complexityTierToProfileKey(tier);
726
- if (config.llm.profiles?.[routedProfile]) {
727
- turnOverrideProfile = routedProfile;
728
- }
729
- }
730
- }
753
+ // Tool-based auto-routing: the switch_inference_profile tool lets the model
754
+ // self-select a different profile mid-turn. Reset the per-turn slot so a
755
+ // stale selection from a previous turn doesn't leak forward.
756
+ ctx.toolRoutedProfile = undefined;
731
757
 
732
- // Notify clients when the auto-router selected a non-default profile.
733
- if (turnOverrideProfile && turnOverrideProfile !== userExplicitOverride) {
734
- const profileEntry = config.llm.profiles?.[turnOverrideProfile];
735
- const label = profileEntry?.label ?? turnOverrideProfile;
736
- broadcastMessage({
737
- type: "turn_profile_auto_routed",
738
- conversationId: ctx.conversationId,
739
- profile: turnOverrideProfile,
740
- profileLabel: label,
741
- });
742
- }
758
+ const turnOverrideProfile = userExplicitOverride;
743
759
 
744
- // Only use the complexity-routed profile as a fallback — not the initial
745
- // explicit override. If a mid-turn session expiry clears the conversation
746
- // override, the old behavior (return undefined → revert to workspace
747
- // defaults) must be preserved for non-routed turns.
748
- const complexityRoutedProfile =
749
- turnOverrideProfile !== userExplicitOverride
750
- ? turnOverrideProfile
751
- : undefined;
752
760
  const readCurrentOverrideProfile = (): string | undefined =>
753
761
  options?.overrideProfile ??
754
762
  getConversationOverrideProfileFromRow(
755
763
  getConversation(ctx.conversationId),
756
764
  ) ??
757
- complexityRoutedProfile;
765
+ ctx.toolRoutedProfile;
758
766
 
759
767
  const effectiveContextWindow = resolveEffectiveContextWindow({
760
768
  llm: config.llm,
761
769
  callSite: turnCallSite,
762
770
  overrideProfile: turnOverrideProfile ?? undefined,
771
+ selectionSeed: ctx.conversationId,
763
772
  });
764
773
  let currentEffectiveContextWindow: EffectiveContextWindow =
765
774
  effectiveContextWindow;
766
775
  let currentContextWindowConfig = contextWindowConfigFromEffective(
767
776
  resolveCallSiteConfig(turnCallSite, config.llm, {
768
777
  overrideProfile: turnOverrideProfile ?? undefined,
778
+ selectionSeed: ctx.conversationId,
769
779
  }).contextWindow,
770
780
  currentEffectiveContextWindow,
771
781
  );
@@ -776,6 +786,7 @@ export async function runAgentLoopImpl(
776
786
  contextWindowManager.updateConfig?.(currentContextWindowConfig);
777
787
 
778
788
  let appliedOverrideProfile = turnOverrideProfile;
789
+ let emittedToolRoutedProfile: string | undefined;
779
790
  const refreshCurrentProfileState = (): string | undefined => {
780
791
  const currentOverrideProfile = readCurrentOverrideProfile();
781
792
  if (currentOverrideProfile !== appliedOverrideProfile) {
@@ -783,10 +794,12 @@ export async function runAgentLoopImpl(
783
794
  llm: config.llm,
784
795
  callSite: turnCallSite,
785
796
  overrideProfile: currentOverrideProfile,
797
+ selectionSeed: ctx.conversationId,
786
798
  });
787
799
  currentContextWindowConfig = contextWindowConfigFromEffective(
788
800
  resolveCallSiteConfig(turnCallSite, config.llm, {
789
801
  overrideProfile: currentOverrideProfile,
802
+ selectionSeed: ctx.conversationId,
790
803
  }).contextWindow,
791
804
  currentEffectiveContextWindow,
792
805
  );
@@ -797,6 +810,24 @@ export async function runAgentLoopImpl(
797
810
  "Turn inference profile changed mid-loop",
798
811
  );
799
812
  }
813
+
814
+ // Emit turn_profile_auto_routed when the tool-based router selects a
815
+ // new profile. Deduplicated so the event fires at most once per profile.
816
+ if (
817
+ ctx.toolRoutedProfile &&
818
+ ctx.toolRoutedProfile !== emittedToolRoutedProfile
819
+ ) {
820
+ emittedToolRoutedProfile = ctx.toolRoutedProfile;
821
+ const profileEntry = config.llm.profiles?.[ctx.toolRoutedProfile];
822
+ const label = profileEntry?.label ?? ctx.toolRoutedProfile;
823
+ broadcastMessage({
824
+ type: "turn_profile_auto_routed",
825
+ conversationId: ctx.conversationId,
826
+ profile: ctx.toolRoutedProfile,
827
+ profileLabel: label,
828
+ });
829
+ }
830
+
800
831
  ctx.currentTurnOverrideProfile = currentOverrideProfile;
801
832
  return currentOverrideProfile;
802
833
  };
@@ -1023,10 +1054,7 @@ export async function runAgentLoopImpl(
1023
1054
  });
1024
1055
  onEvent({
1025
1056
  type: "sync_changed",
1026
- tags: [
1027
- SYNC_TAGS.conversationsList,
1028
- conversationMetadataSyncTag(ctx.conversationId),
1029
- ],
1057
+ tags: [conversationMetadataSyncTag(ctx.conversationId)],
1030
1058
  });
1031
1059
  },
1032
1060
  };
@@ -1645,7 +1673,7 @@ export async function runAgentLoopImpl(
1645
1673
  // V2 static memory block (essentials/threads/recent/buffer).
1646
1674
  // `currentMemoryV2Static` is the trust-gated content reused by every
1647
1675
  // re-injection path — it stays non-null on non-full-mode turns so
1648
- // that mid-turn reducer compaction (which strips the prior `<memory>`
1676
+ // that mid-turn reducer compaction (which strips the prior `<info>`
1649
1677
  // block) can restore the freshest content. `memoryV2Static` is the
1650
1678
  // first-turn / post-compaction cadence-gated value for initial
1651
1679
  // injection only. `readMemoryV2StaticContent` self-gates on the v2
@@ -2307,14 +2335,7 @@ export async function runAgentLoopImpl(
2307
2335
  // so we compact the "raw" persistent messages.
2308
2336
  const rawHistory = stripInjectionsForCompaction(updatedHistory);
2309
2337
  ctx.messages = rawHistory;
2310
- try {
2311
- clearStrippedInjectionMetadataForConversation(ctx.conversationId);
2312
- } catch (err) {
2313
- rlog.warn(
2314
- { err },
2315
- "Failed to clear stripped-injection metadata after compaction strip (non-fatal)",
2316
- );
2317
- }
2338
+ markHistoryStrippedBestEffort(ctx.conversationId, Date.now(), rlog);
2318
2339
 
2319
2340
  ctx.emitActivityState(
2320
2341
  "thinking",
@@ -2598,14 +2619,7 @@ export async function runAgentLoopImpl(
2598
2619
 
2599
2620
  if (updatedHistory.length > preRunHistoryLength) {
2600
2621
  ctx.messages = stripInjectionsForCompaction(updatedHistory);
2601
- try {
2602
- clearStrippedInjectionMetadataForConversation(ctx.conversationId);
2603
- } catch (err) {
2604
- rlog.warn(
2605
- { err },
2606
- "Failed to clear stripped-injection metadata after compaction strip (non-fatal)",
2607
- );
2608
- }
2622
+ markHistoryStrippedBestEffort(ctx.conversationId, Date.now(), rlog);
2609
2623
  convergenceStripped = true;
2610
2624
  preRepairMessages = updatedHistory;
2611
2625
  preRunHistoryLength = updatedHistory.length;
@@ -2850,14 +2864,7 @@ export async function runAgentLoopImpl(
2850
2864
  // pre-rerun messages.
2851
2865
  if (updatedHistory.length > preRunHistoryLength) {
2852
2866
  ctx.messages = stripInjectionsForCompaction(updatedHistory);
2853
- try {
2854
- clearStrippedInjectionMetadataForConversation(ctx.conversationId);
2855
- } catch (err) {
2856
- rlog.warn(
2857
- { err },
2858
- "Failed to clear stripped-injection metadata after compaction strip (non-fatal)",
2859
- );
2860
- }
2867
+ markHistoryStrippedBestEffort(ctx.conversationId, Date.now(), rlog);
2861
2868
  convergenceStripped = true;
2862
2869
  preRepairMessages = updatedHistory;
2863
2870
  preRunHistoryLength = updatedHistory.length;
@@ -3006,6 +3013,32 @@ export async function runAgentLoopImpl(
3006
3013
  await emitTerminalExit?.("context_too_large");
3007
3014
  pendingCheckpointYield = null;
3008
3015
  onEvent(buildConversationErrorMessage(ctx.conversationId, classified));
3016
+ } else if (yieldedForBudget && !abortController.signal.aborted) {
3017
+ // The auto_compress_latest_turn rerun (action === "auto_compress_latest_turn"
3018
+ // above) reset `contextTooLargeDetected` to false before its final
3019
+ // `agentLoop.run`, so the context-too-large branch above won't fire
3020
+ // even when that rerun yields at the mid-loop budget checkpoint with
3021
+ // no further recovery layer to re-enter. Without surfacing this here,
3022
+ // the turn terminates silently — the inspector sees `agent_loop_exit_reason
3023
+ // = NULL` and the user sees no message at all (just a "ghost" turn).
3024
+ //
3025
+ // Unlike provider-error persistence at L3091 — which only fires when
3026
+ // the loop produced NO assistant output — budget_yield_unrecovered
3027
+ // typically yields AFTER one or more successful tool-use iterations,
3028
+ // so `hasAssistantResponse` is true and that path would skip us. We
3029
+ // capture the classification here so the live SSE event fires
3030
+ // immediately, and persist a dedicated notice row below — after the
3031
+ // pendingToolResults flush — so the transcript reads as: tool-use →
3032
+ // tool results → "I couldn't fit the next step…" notice. Persisting
3033
+ // earlier would orphan an assistant(tool_use) from its user(tool_result),
3034
+ // breaking provider adjacency on replay.
3035
+ budgetYieldClassification = budgetYieldUnrecoveredClassification();
3036
+ onEvent(
3037
+ buildConversationErrorMessage(
3038
+ ctx.conversationId,
3039
+ budgetYieldClassification,
3040
+ ),
3041
+ );
3009
3042
  }
3010
3043
  }
3011
3044
 
@@ -3081,6 +3114,99 @@ export async function runAgentLoopImpl(
3081
3114
  state.pendingToolResults.clear();
3082
3115
  }
3083
3116
 
3117
+ // Persist the budget_yield_unrecovered notice now that any pending
3118
+ // tool_results have flushed. The SSE event already fired upstream; this
3119
+ // makes the row durable in the right position: tool-use → tool-results →
3120
+ // notice. Doing it earlier (e.g. at the detection site) would land the
3121
+ // assistant row between a tool_use and its tool_result and break provider
3122
+ // adjacency on replay.
3123
+ if (budgetYieldClassification && !abortController.signal.aborted) {
3124
+ const yieldNoticeMessage = createAssistantMessage(
3125
+ budgetYieldClassification.userMessage,
3126
+ );
3127
+ const yieldNoticeMetadata = {
3128
+ ...provenanceFromTrustContext(ctx.trustContext),
3129
+ userMessageChannel: capturedTurnChannelContext.userMessageChannel,
3130
+ assistantMessageChannel:
3131
+ capturedTurnChannelContext.assistantMessageChannel,
3132
+ userMessageInterface: capturedTurnInterfaceContext.userMessageInterface,
3133
+ assistantMessageInterface:
3134
+ capturedTurnInterfaceContext.assistantMessageInterface,
3135
+ };
3136
+ let yieldNoticePersistedId: string | null = null;
3137
+ try {
3138
+ const yieldPersistResult = (await runPipeline<
3139
+ PersistArgs,
3140
+ PersistResult
3141
+ >(
3142
+ "persistence",
3143
+ getMiddlewaresFor("persistence"),
3144
+ defaultPersistenceTerminal,
3145
+ {
3146
+ op: "add",
3147
+ conversationId: ctx.conversationId,
3148
+ role: "assistant",
3149
+ content: JSON.stringify(yieldNoticeMessage.content),
3150
+ metadata: yieldNoticeMetadata,
3151
+ },
3152
+ buildPluginTurnContext(ctx, reqId),
3153
+ DEFAULT_TIMEOUTS.persistence,
3154
+ )) as PersistAddResult;
3155
+ yieldNoticePersistedId = yieldPersistResult.message.id;
3156
+ } catch (err) {
3157
+ // Non-fatal — a DB hiccup must not escalate a budget-yield exit into
3158
+ // a turn-level throw. The live SSE event was already emitted, so the
3159
+ // user still sees the notice this turn even if the durable row missed.
3160
+ rlog.warn(
3161
+ { err },
3162
+ "Failed to persist budget_yield_unrecovered notice (non-fatal)",
3163
+ );
3164
+ }
3165
+ // Record a synthetic `llm_request_logs` row for the yield so the
3166
+ // inspector's call rail surfaces a clickable, distinctly-rendered
3167
+ // entry for the failure itself. Without this row, the loop yields
3168
+ // silently — the user sees the notice in chat but the inspector
3169
+ // call list ends at the last actual LLM call with no way to scope
3170
+ // the "what compactions led to this failure?" question to the
3171
+ // yield event.
3172
+ //
3173
+ // Recorded *before* emitTerminalExit so the synthetic row exists
3174
+ // by the time the dispatcher's post-loop hook runs. The row
3175
+ // already carries `agent_loop_exit_reason` at insert time, so
3176
+ // `setAgentLoopExitReasonOnLatestLog`'s IS NULL guard skips it
3177
+ // and stamps the prior real mainAgent call instead — preserving
3178
+ // the existing "latest LLM call carries the exit reason"
3179
+ // invariant other consumers depend on.
3180
+ //
3181
+ // `preparedRequest` snapshots the best-known LLM request state
3182
+ // at yield time — `updatedHistory` (the conversation state the
3183
+ // next call would have been built from) plus the input-token
3184
+ // budget that just failed. Mirrors the role of `request_payload`
3185
+ // on real LLM-call rows; the notice text lives on
3186
+ // `response_payload`.
3187
+ if (yieldNoticePersistedId !== null && budgetYieldClassification) {
3188
+ try {
3189
+ recordSyntheticAgentErrorMessageLog({
3190
+ conversationId: ctx.conversationId,
3191
+ messageId: yieldNoticePersistedId,
3192
+ exitReason: "budget_yield_unrecovered",
3193
+ noticeText: budgetYieldClassification.userMessage,
3194
+ preparedRequest: {
3195
+ messages: updatedHistory,
3196
+ maxInputTokensBudget: resolveCurrentMaxInputTokens() ?? null,
3197
+ },
3198
+ createdAt: Date.now(),
3199
+ });
3200
+ } catch (err) {
3201
+ rlog.warn(
3202
+ { err },
3203
+ "Failed to record budget_yield_unrecovered synthetic call log (non-fatal)",
3204
+ );
3205
+ }
3206
+ }
3207
+ await emitTerminalExit?.("budget_yield_unrecovered");
3208
+ }
3209
+
3084
3210
  // Reconstruct history
3085
3211
  const newMessages = updatedHistory.slice(preRunHistoryLength).map((msg) => {
3086
3212
  if (msg.role !== "assistant") return msg;
@@ -3098,6 +3224,34 @@ export async function runAgentLoopImpl(
3098
3224
  !abortController.signal.aborted &&
3099
3225
  !yieldedForHandoff
3100
3226
  ) {
3227
+ // Drop any reservation stranded by the failed LLM call before
3228
+ // inserting the synthetic error message. The B3 pre-allocation
3229
+ // path reserves an empty assistant row at `llm_call_started`;
3230
+ // when the call exits through the provider-error branch (no
3231
+ // `message_complete`), `assistantRowAwaitingFinalization` stays
3232
+ // true. Without this delete the transcript would carry both the
3233
+ // empty reserved row AND the error message — and downstream sync
3234
+ // (`syncLastAssistantMessageToDisk`) would mis-target the empty
3235
+ // row. After delete we set `lastAssistantMessageId` to the new
3236
+ // error row's id so the post-loop emission paths still point at
3237
+ // a real message.
3238
+ if (
3239
+ state.assistantRowAwaitingFinalization &&
3240
+ state.lastAssistantMessageId
3241
+ ) {
3242
+ // Direct `deleteMessageById` (not via the `persistence` pipeline):
3243
+ // see the same rationale on the matching cleanup in
3244
+ // `handleLlmCallStarted` — an unfinalized reservation has no
3245
+ // observable history for plugins.
3246
+ try {
3247
+ deleteMessageById(state.lastAssistantMessageId);
3248
+ } catch (err) {
3249
+ rlog.warn(
3250
+ { err, messageId: state.lastAssistantMessageId },
3251
+ "Failed to clean up stranded reserved assistant row on provider-error path (non-fatal)",
3252
+ );
3253
+ }
3254
+ }
3101
3255
  const errChannelMeta = {
3102
3256
  ...provenanceFromTrustContext(ctx.trustContext),
3103
3257
  userMessageChannel: capturedTurnChannelContext.userMessageChannel,
@@ -3125,6 +3279,15 @@ export async function runAgentLoopImpl(
3125
3279
  DEFAULT_TIMEOUTS.persistence,
3126
3280
  )) as PersistAddResult;
3127
3281
  persistedErrorAssistantMessage = true;
3282
+ // Repoint `lastAssistantMessageId` at the synthetic error row so the
3283
+ // post-loop sync, attachment resolution, and `message_complete`/
3284
+ // `generation_handoff` emissions all reference a real, persisted
3285
+ // message id. The previous reservation (if any) was already deleted
3286
+ // above. Mark finalization complete so the next LLM call in this run
3287
+ // (or a downstream handler) doesn't try to clean up an id that
3288
+ // already corresponds to a finalized row.
3289
+ state.lastAssistantMessageId = errorPersistResult.message.id;
3290
+ state.assistantRowAwaitingFinalization = false;
3128
3291
  newMessages.push(errorAssistantMessage);
3129
3292
  // Pipe the just-assigned message id into any orphaned LLM request log
3130
3293
  // row(s) for this turn. The success path links rows via
@@ -3263,7 +3426,6 @@ export async function runAgentLoopImpl(
3263
3426
  ctx.lastAssistantAttachments = assistantAttachments;
3264
3427
  ctx.lastAttachmentWarnings = attachmentResult.directiveWarnings;
3265
3428
  syncLastAssistantMessageToDisk();
3266
- const clientDisplayMessageId = getClientDisplayMessageId(state);
3267
3429
 
3268
3430
  // Re-check: the user may have cancelled during attachment resolution
3269
3431
  if (abortController.signal.aborted) {
@@ -3309,9 +3471,6 @@ export async function runAgentLoopImpl(
3309
3471
  ...(state.lastAssistantMessageId
3310
3472
  ? { messageId: state.lastAssistantMessageId }
3311
3473
  : {}),
3312
- ...(clientDisplayMessageId
3313
- ? { displayMessageId: clientDisplayMessageId }
3314
- : {}),
3315
3474
  });
3316
3475
  publishLoopMessagesChanged();
3317
3476
  } else {
@@ -3336,9 +3495,6 @@ export async function runAgentLoopImpl(
3336
3495
  ...(state.lastAssistantMessageId
3337
3496
  ? { messageId: state.lastAssistantMessageId }
3338
3497
  : {}),
3339
- ...(clientDisplayMessageId
3340
- ? { displayMessageId: clientDisplayMessageId }
3341
- : {}),
3342
3498
  });
3343
3499
  publishLoopMessagesChanged();
3344
3500
 
@@ -3397,10 +3553,7 @@ export async function runAgentLoopImpl(
3397
3553
  });
3398
3554
  onEvent({
3399
3555
  type: "sync_changed",
3400
- tags: [
3401
- SYNC_TAGS.conversationsList,
3402
- conversationMetadataSyncTag(ctx.conversationId),
3403
- ],
3556
+ tags: [conversationMetadataSyncTag(ctx.conversationId)],
3404
3557
  });
3405
3558
  },
3406
3559
  signal: abortController.signal,
@@ -3645,6 +3798,7 @@ export async function applyCompactionResult(
3645
3798
  result.summaryText,
3646
3799
  ctx.contextCompactedMessageCount,
3647
3800
  );
3801
+ markHistoryStrippedBestEffort(ctx.conversationId, compactedAt, log);
3648
3802
  if (options.slackContextCompactionWatermarkTs) {
3649
3803
  updateConversationSlackContextWatermark(
3650
3804
  ctx.conversationId,
@@ -1,3 +1,4 @@
1
+ import { ConnectionResolutionError } from "../providers/connection-resolution.js";
1
2
  import { getProviderRoutingSource } from "../providers/registry.js";
2
3
  import { isAbortReason } from "../util/abort-reasons.js";
3
4
  import { ProviderError, ProviderNotConfiguredError } from "../util/errors.js";
@@ -251,14 +252,28 @@ export function classifyConversationError(
251
252
  if (error instanceof ProviderNotConfiguredError) {
252
253
  return {
253
254
  ...providerNotConfiguredClassification({
254
- connectionName:
255
- error.connectionName ?? attribution.connectionName,
255
+ connectionName: error.connectionName ?? attribution.connectionName,
256
256
  profileName: error.profileName ?? attribution.profileName,
257
257
  }),
258
258
  debugDetails,
259
259
  };
260
260
  }
261
261
 
262
+ if (error instanceof ConnectionResolutionError) {
263
+ return {
264
+ code: "PROVIDER_NOT_CONFIGURED",
265
+ userMessage:
266
+ "No compatible provider connection found for this profile. Check your provider connections in Settings.",
267
+ retryable: true,
268
+ debugDetails,
269
+ errorCategory: "provider_not_configured",
270
+ ...(error.connectionName ? { connectionName: error.connectionName } : {}),
271
+ ...(attribution.profileName
272
+ ? { profileName: attribution.profileName }
273
+ : {}),
274
+ };
275
+ }
276
+
262
277
  // Phase-specific overrides
263
278
  if (ctx.phase === "regenerate") {
264
279
  const base = classifyCore(error, message, attribution);
@@ -437,9 +452,15 @@ function classifyCore(
437
452
  errorCategory: "image_dimensions_too_large",
438
453
  };
439
454
  }
455
+ // Extract the provider detail after "API error (NNN): " prefix
456
+ const detailMatch = message.match(/API error \(\d+\):\s*(.+)/i);
457
+ const detail = detailMatch?.[1];
458
+ const suffix = detail
459
+ ? `: ${detail.length > 200 ? detail.slice(0, 200) + "…" : detail}`
460
+ : "";
440
461
  return {
441
462
  code: "PROVIDER_API",
442
- userMessage: "The AI provider rejected the request.",
463
+ userMessage: `The AI provider rejected the request (HTTP ${error.statusCode})${suffix}`,
443
464
  retryable: true,
444
465
  errorCategory: "provider_api_error",
445
466
  };
@@ -760,6 +781,45 @@ function classifyByMessage(
760
781
  };
761
782
  }
762
783
 
784
+ /**
785
+ * Classify a `budget_yield_unrecovered` terminal exit.
786
+ *
787
+ * Emitted when the agent loop's `auto_compress_latest_turn` rerun
788
+ * (the last layer of the overflow-recovery ladder) still yields at
789
+ * the mid-loop preflight budget checkpoint. The turn cannot proceed,
790
+ * but it is not a provider rejection — every compaction the loop ran
791
+ * has already been applied to the conversation, so the user's next
792
+ * message starts from the compacted history and typically succeeds.
793
+ *
794
+ * The returned `userMessage` is persisted as a `role="assistant"` row
795
+ * by the same path that already persists `PROVIDER_BILLING` etc., so
796
+ * the notice is durable across reload (not just a transient banner).
797
+ */
798
+ export function budgetYieldUnrecoveredClassification(): ClassifiedConversationError {
799
+ return {
800
+ code: "BUDGET_YIELD_UNRECOVERED",
801
+ userMessage:
802
+ "I tried to compact this conversation but couldn't fit the next step into the model's context window. Send another message to continue — the compaction I did run has been saved, so your next turn starts from a smaller history.",
803
+ retryable: true,
804
+ errorCategory: "budget_yield_unrecovered",
805
+ };
806
+ }
807
+
808
+ /**
809
+ * Classify a model response that stopped because the output-token limit was
810
+ * reached. The turn may have produced useful partial text, so the recovery is
811
+ * a follow-up user turn rather than a retry of the same request.
812
+ */
813
+ export function maxTokensReachedClassification(): ClassifiedConversationError {
814
+ return {
815
+ code: "MAX_TOKENS_REACHED",
816
+ userMessage:
817
+ "I hit the response limit before I could finish. Continue and I'll pick up from where I stopped.",
818
+ retryable: true,
819
+ errorCategory: "max_tokens_reached",
820
+ };
821
+ }
822
+
763
823
  /**
764
824
  * Build a `conversation_error` server message from a classified error.
765
825
  */
@@ -781,8 +841,6 @@ export function buildConversationErrorMessage(
781
841
  ...(classified.connectionName
782
842
  ? { connectionName: classified.connectionName }
783
843
  : {}),
784
- ...(classified.profileName
785
- ? { profileName: classified.profileName }
786
- : {}),
844
+ ...(classified.profileName ? { profileName: classified.profileName } : {}),
787
845
  };
788
846
  }