@vellumai/assistant 0.8.6 → 0.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (891) hide show
  1. package/AGENTS.md +4 -4
  2. package/Dockerfile +1 -0
  3. package/bun.lock +11 -2
  4. package/docker-entrypoint.sh +8 -6
  5. package/docs/plugins.md +63 -28
  6. package/examples/plugins/echo/register.ts +4 -7
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/environments/bun.lock +24 -0
  9. package/node_modules/@vellumai/environments/package.json +18 -0
  10. package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +95 -0
  11. package/node_modules/@vellumai/environments/src/index.ts +11 -0
  12. package/node_modules/@vellumai/environments/src/seeds.ts +73 -0
  13. package/node_modules/@vellumai/environments/src/types.ts +70 -0
  14. package/node_modules/@vellumai/environments/tsconfig.json +20 -0
  15. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +11 -0
  16. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +3 -4
  17. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +6 -2
  18. package/openapi.yaml +3735 -353
  19. package/package.json +7 -3
  20. package/scripts/generate-openapi.ts +20 -13
  21. package/src/__tests__/agent-loop-callsite-precedence.test.ts +42 -80
  22. package/src/__tests__/agent-loop-exit-reason.test.ts +240 -39
  23. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +141 -0
  24. package/src/__tests__/agent-loop-override-profile.test.ts +19 -32
  25. package/src/__tests__/agent-loop-provider-error-recording.test.ts +6 -4
  26. package/src/__tests__/agent-loop-thinking.test.ts +17 -12
  27. package/src/__tests__/agent-loop.test.ts +207 -341
  28. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +4 -2
  29. package/src/__tests__/agent-wake-override-profile.test.ts +22 -40
  30. package/src/__tests__/anthropic-provider.test.ts +201 -55
  31. package/src/__tests__/app-builder-skill-instructions.test.ts +22 -0
  32. package/src/__tests__/app-control-flow.test.ts +5 -0
  33. package/src/__tests__/approval-cascade.test.ts +4 -11
  34. package/src/__tests__/approval-routes-http.test.ts +4 -2
  35. package/src/__tests__/assistant-event.test.ts +15 -0
  36. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
  37. package/src/__tests__/avatar-e2e.test.ts +7 -37
  38. package/src/__tests__/avatar-generator.test.ts +12 -42
  39. package/src/__tests__/avatar-identity-sync.test.ts +28 -3
  40. package/src/__tests__/background-shell-bash.test.ts +3 -7
  41. package/src/__tests__/btw-routes.test.ts +7 -12
  42. package/src/__tests__/call-pointer-messages.test.ts +5 -3
  43. package/src/__tests__/call-site-routing-provider.test.ts +22 -40
  44. package/src/__tests__/catalog-files.test.ts +1 -0
  45. package/src/__tests__/channel-approval-routes.test.ts +48 -20
  46. package/src/__tests__/channel-approvals.test.ts +3 -1
  47. package/src/__tests__/channel-invite-transport.test.ts +1 -5
  48. package/src/__tests__/channel-readiness-routes.test.ts +0 -4
  49. package/src/__tests__/channel-readiness-slack-remote.test.ts +2 -7
  50. package/src/__tests__/channel-retry-sweep.test.ts +71 -79
  51. package/src/__tests__/circuit-breaker-pipeline.test.ts +3 -3
  52. package/src/__tests__/clawhub-files.test.ts +1 -0
  53. package/src/__tests__/compaction-events.test.ts +5 -17
  54. package/src/__tests__/compaction-pipeline.test.ts +1 -1
  55. package/src/__tests__/compaction-timeout-recovery.test.ts +37 -48
  56. package/src/__tests__/compaction-trail-store.test.ts +1 -79
  57. package/src/__tests__/compactor-image-manifest-trust.test.ts +112 -0
  58. package/src/__tests__/computer-use-tools.test.ts +2 -2
  59. package/src/__tests__/config-watcher.test.ts +28 -0
  60. package/src/__tests__/context-search-agent-runner.test.ts +6 -3
  61. package/src/__tests__/context-token-estimator.test.ts +34 -0
  62. package/src/__tests__/context-window-manager-compact-retry.test.ts +291 -0
  63. package/src/__tests__/conversation-abort-tool-results.test.ts +14 -7
  64. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -2
  65. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +12 -27
  66. package/src/__tests__/conversation-agent-loop-overflow.test.ts +430 -90
  67. package/src/__tests__/conversation-agent-loop.test.ts +581 -62
  68. package/src/__tests__/conversation-analysis-routes.test.ts +1 -3
  69. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
  70. package/src/__tests__/conversation-clear-safety.test.ts +20 -10
  71. package/src/__tests__/conversation-confirmation-signals.test.ts +15 -45
  72. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  73. package/src/__tests__/conversation-disk-view.test.ts +10 -17
  74. package/src/__tests__/conversation-fork-crud.test.ts +86 -172
  75. package/src/__tests__/conversation-fork-route.test.ts +16 -14
  76. package/src/__tests__/conversation-init.benchmark.test.ts +6 -6
  77. package/src/__tests__/conversation-lifecycle.test.ts +3 -2
  78. package/src/__tests__/conversation-load-history-repair.test.ts +3 -2
  79. package/src/__tests__/conversation-load-history-stripped.test.ts +1 -1
  80. package/src/__tests__/conversation-message-sync-tags.test.ts +3 -4
  81. package/src/__tests__/conversation-pairing.test.ts +34 -4
  82. package/src/__tests__/conversation-pre-run-repair.test.ts +1 -1
  83. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -0
  84. package/src/__tests__/conversation-process-callsite.test.ts +27 -30
  85. package/src/__tests__/conversation-provider-retry-repair.test.ts +53 -44
  86. package/src/__tests__/conversation-queue.test.ts +270 -164
  87. package/src/__tests__/conversation-routes-disk-view.test.ts +3 -2
  88. package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
  89. package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -2
  90. package/src/__tests__/conversation-runtime-assembly.test.ts +20 -22
  91. package/src/__tests__/conversation-runtime-workspace.test.ts +19 -1
  92. package/src/__tests__/conversation-slash-queue.test.ts +37 -31
  93. package/src/__tests__/conversation-slash-unknown.test.ts +13 -15
  94. package/src/__tests__/conversation-speed-override.test.ts +8 -22
  95. package/src/__tests__/conversation-stream-state.test.ts +484 -0
  96. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +6 -15
  97. package/src/__tests__/conversation-surfaces-app-control.test.ts +32 -4
  98. package/src/__tests__/conversation-surfaces-state-update.test.ts +5 -2
  99. package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -15
  100. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +23 -11
  101. package/src/__tests__/conversation-unread-route.test.ts +14 -2
  102. package/src/__tests__/conversation-usage.test.ts +0 -2
  103. package/src/__tests__/conversation-wipe.test.ts +1 -1
  104. package/src/__tests__/conversation-workspace-cache-state.test.ts +3 -1
  105. package/src/__tests__/conversation-workspace-injection.test.ts +48 -22
  106. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +27 -7
  107. package/src/__tests__/credential-execution-tools.test.ts +1 -2
  108. package/src/__tests__/credential-security-invariants.test.ts +0 -1
  109. package/src/__tests__/cross-provider-web-search.test.ts +6 -2
  110. package/src/__tests__/cu-unified-flow.test.ts +26 -1
  111. package/src/__tests__/db-schedule-syntax-migration.test.ts +11 -0
  112. package/src/__tests__/disk-pressure-guard.test.ts +66 -0
  113. package/src/__tests__/disk-pressure-routes.test.ts +9 -2
  114. package/src/__tests__/dm-persistence.test.ts +7 -2
  115. package/src/__tests__/dynamic-page-surface.test.ts +68 -0
  116. package/src/__tests__/edit-propagation.test.ts +1 -2
  117. package/src/__tests__/empty-response-pipeline.test.ts +127 -5
  118. package/src/__tests__/filing-service.test.ts +2 -2
  119. package/src/__tests__/first-greeting.test.ts +55 -14
  120. package/src/__tests__/gemini-inline-media.test.ts +78 -0
  121. package/src/__tests__/gemini-provider.test.ts +351 -28
  122. package/src/__tests__/guardian-routing-state.test.ts +60 -71
  123. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +9 -7
  124. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  125. package/src/__tests__/heartbeat-service.test.ts +2 -1
  126. package/src/__tests__/history-repair-hook.test.ts +161 -0
  127. package/src/__tests__/history-repair-observability.test.ts +1 -1
  128. package/src/__tests__/history-repair.test.ts +2 -1
  129. package/src/__tests__/host-app-control-proxy.test.ts +2 -0
  130. package/src/__tests__/host-cu-proxy.test.ts +2 -0
  131. package/src/__tests__/host-file-edit-tool.test.ts +4 -2
  132. package/src/__tests__/host-file-proxy.test.ts +31 -0
  133. package/src/__tests__/host-file-read-tool.test.ts +4 -2
  134. package/src/__tests__/host-file-write-tool.test.ts +9 -3
  135. package/src/__tests__/host-proxy-preactivation.test.ts +53 -14
  136. package/src/__tests__/host-shell-tool.test.ts +9 -4
  137. package/src/__tests__/http-user-message-parity.test.ts +2 -2
  138. package/src/__tests__/identity-intro-cache.test.ts +35 -14
  139. package/src/__tests__/inbound-slack-persistence.test.ts +7 -2
  140. package/src/__tests__/injector-background-turn.test.ts +1 -1
  141. package/src/__tests__/injector-chain.test.ts +1 -1
  142. package/src/__tests__/injector-disk-pressure.test.ts +1 -1
  143. package/src/__tests__/injector-document-comments.test.ts +1 -1
  144. package/src/__tests__/injector-pkb-v2-silenced.test.ts +1 -1
  145. package/src/__tests__/injector-v3-suppression.test.ts +220 -0
  146. package/src/__tests__/list-messages-attachments.test.ts +7 -8
  147. package/src/__tests__/list-messages-hidden-metadata.test.ts +17 -15
  148. package/src/__tests__/list-messages-page-latest.test.ts +0 -1
  149. package/src/__tests__/list-messages-tool-merge.test.ts +36 -6
  150. package/src/__tests__/llm-call-pipeline.test.ts +21 -15
  151. package/src/__tests__/llm-request-log-turn-query.test.ts +42 -86
  152. package/src/__tests__/llm-resolver.test.ts +23 -47
  153. package/src/__tests__/llm-usage-store.test.ts +45 -0
  154. package/src/__tests__/log-export-routes.test.ts +59 -0
  155. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -8
  156. package/src/__tests__/mcp-auth-routes.test.ts +15 -10
  157. package/src/__tests__/mcp-health-check.test.ts +18 -13
  158. package/src/__tests__/memory-retrieval-pipeline.test.ts +1 -1
  159. package/src/__tests__/memory-v2-static-injector.test.ts +1 -1
  160. package/src/__tests__/messaging-send-tool.test.ts +8 -4
  161. package/src/__tests__/migration-export-http.test.ts +12 -12
  162. package/src/__tests__/migration-import-commit-http.test.ts +8 -8
  163. package/src/__tests__/migration-import-preflight-http.test.ts +7 -7
  164. package/src/__tests__/migration-validate-http.test.ts +3 -3
  165. package/src/__tests__/native-web-search.test.ts +14 -20
  166. package/src/__tests__/notification-decision-identity.test.ts +9 -18
  167. package/src/__tests__/notification-decision-recipient-context.test.ts +3 -6
  168. package/src/__tests__/oauth-commands-routes.test.ts +1 -1
  169. package/src/__tests__/onboarding-template-contract.test.ts +10 -0
  170. package/src/__tests__/openai-provider.test.ts +66 -70
  171. package/src/__tests__/openai-responses-provider.test.ts +21 -77
  172. package/src/__tests__/outbound-slack-persistence.test.ts +2 -1
  173. package/src/__tests__/overflow-reduce-pipeline.test.ts +2 -4
  174. package/src/__tests__/parallel-tool.benchmark.test.ts +24 -36
  175. package/src/__tests__/persistence-pipeline.test.ts +15 -26
  176. package/src/__tests__/persistence-secret-redaction.test.ts +2 -1
  177. package/src/__tests__/pipeline-runner.test.ts +2 -3
  178. package/src/__tests__/plugin-bootstrap.test.ts +51 -25
  179. package/src/__tests__/plugin-route-contribution.test.ts +6 -16
  180. package/src/__tests__/plugin-skill-contribution.test.ts +7 -17
  181. package/src/__tests__/plugin-tool-contribution.test.ts +10 -26
  182. package/src/__tests__/plugin-types.test.ts +7 -14
  183. package/src/__tests__/prechat-onboarding-contract.test.ts +23 -0
  184. package/src/__tests__/process-message-background-slack.test.ts +17 -16
  185. package/src/__tests__/process-message-display-content.test.ts +30 -42
  186. package/src/__tests__/provider-commit-message-generator.test.ts +19 -14
  187. package/src/__tests__/provider-error-scenarios.test.ts +7 -6
  188. package/src/__tests__/provider-platform-proxy-integration.test.ts +3 -8
  189. package/src/__tests__/provider-send-message-override-profile.test.ts +9 -25
  190. package/src/__tests__/provider-streaming.benchmark.test.ts +12 -22
  191. package/src/__tests__/provider-usage-tracking.test.ts +0 -6
  192. package/src/__tests__/ratelimit.test.ts +9 -4
  193. package/src/__tests__/relay-server.test.ts +20 -13
  194. package/src/__tests__/retry-openrouter-only-normalization.test.ts +5 -8
  195. package/src/__tests__/retry-thinking-tool-choice.test.ts +10 -13
  196. package/src/__tests__/retry-verbosity-normalization.test.ts +5 -8
  197. package/src/__tests__/runtime-events-sse-reconnect.test.ts +353 -0
  198. package/src/__tests__/schedule-routes.test.ts +80 -10
  199. package/src/__tests__/schedule-store.test.ts +67 -0
  200. package/src/__tests__/schedule-tools.test.ts +125 -0
  201. package/src/__tests__/secret-ingress-http.test.ts +2 -2
  202. package/src/__tests__/secret-prompt-log-hygiene.test.ts +11 -7
  203. package/src/__tests__/secret-prompter-channel-fallback.test.ts +11 -9
  204. package/src/__tests__/secret-response-routing.test.ts +13 -11
  205. package/src/__tests__/send-endpoint-busy.test.ts +2 -1
  206. package/src/__tests__/shell-observability.test.ts +249 -0
  207. package/src/__tests__/skill-feature-flags-integration.test.ts +11 -11
  208. package/src/__tests__/skill-feature-flags.test.ts +6 -6
  209. package/src/__tests__/skill-load-feature-flag.test.ts +10 -10
  210. package/src/__tests__/skills-files-catalog-fallback.test.ts +10 -0
  211. package/src/__tests__/skillssh-files.test.ts +1 -0
  212. package/src/__tests__/starter-task-flow.test.ts +6 -6
  213. package/src/__tests__/strip-memory-injections.test.ts +102 -14
  214. package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
  215. package/src/__tests__/suggestion-routes.test.ts +3 -3
  216. package/src/__tests__/sync-message-contract.test.ts +19 -16
  217. package/src/__tests__/system-prompt.test.ts +54 -0
  218. package/src/__tests__/terminal-tools.test.ts +3 -24
  219. package/src/__tests__/thread-backfill.test.ts +4 -9
  220. package/src/__tests__/title-generate-pipeline.test.ts +1 -1
  221. package/src/__tests__/token-estimate-pipeline.test.ts +2 -4
  222. package/src/__tests__/tool-error-pipeline.test.ts +2 -2
  223. package/src/__tests__/tool-execute-pipeline.test.ts +1 -1
  224. package/src/__tests__/tool-preview-lifecycle.test.ts +13 -11
  225. package/src/__tests__/tool-result-truncate-pipeline.test.ts +9 -12
  226. package/src/__tests__/tool-result-truncation.test.ts +3 -1
  227. package/src/__tests__/tools-audio-read.test.ts +113 -0
  228. package/src/__tests__/turn-boundary-resolution.test.ts +44 -84
  229. package/src/__tests__/turn-events-store.test.ts +11 -7
  230. package/src/__tests__/voice-scoped-grant-consumer.test.ts +8 -6
  231. package/src/__tests__/voice-session-bridge.test.ts +13 -7
  232. package/src/acp/__tests__/prepare-agent-env.test.ts +143 -31
  233. package/src/acp/prepare-agent-env.ts +52 -11
  234. package/src/agent/compaction-circuit.ts +140 -0
  235. package/src/agent/loop.ts +409 -85
  236. package/src/api/README.md +19 -17
  237. package/src/api/constants/tool-execution.ts +21 -0
  238. package/src/api/events/assistant-activity-state.ts +75 -0
  239. package/src/api/events/assistant-outbound-attachment.ts +25 -27
  240. package/src/api/events/assistant-text-delta.ts +6 -8
  241. package/src/api/events/assistant-turn-start.ts +5 -7
  242. package/src/api/events/avatar-updated.ts +24 -0
  243. package/src/api/events/compaction-circuit-closed.ts +26 -0
  244. package/src/api/events/compaction-circuit-open.ts +28 -0
  245. package/src/api/events/confirmation-request.ts +114 -0
  246. package/src/api/events/contact-request.ts +33 -0
  247. package/src/api/events/conversation-error.ts +77 -0
  248. package/src/api/events/conversation-list-invalidated.ts +38 -0
  249. package/src/api/events/conversation-title-updated.ts +24 -0
  250. package/src/api/events/disk-pressure-status-changed.ts +61 -0
  251. package/src/api/events/document-comment-created.ts +24 -28
  252. package/src/api/events/document-comment-deleted.ts +6 -8
  253. package/src/api/events/document-comment-reopened.ts +6 -8
  254. package/src/api/events/document-comment-resolved.ts +8 -10
  255. package/src/api/events/document-editor-update.ts +27 -0
  256. package/src/api/events/error.ts +32 -0
  257. package/src/api/events/generation-cancelled.ts +4 -6
  258. package/src/api/events/generation-handoff.ts +13 -15
  259. package/src/api/events/home-feed-updated.ts +26 -0
  260. package/src/api/events/identity-changed.ts +32 -0
  261. package/src/api/events/interaction-resolved.ts +50 -0
  262. package/src/api/events/message-complete.ts +10 -12
  263. package/src/api/events/message-dequeued.ts +21 -0
  264. package/src/api/events/message-queued-deleted.ts +23 -0
  265. package/src/api/events/message-queued.ts +22 -0
  266. package/src/api/events/message-request-complete.ts +29 -0
  267. package/src/api/events/navigate-settings.ts +20 -0
  268. package/src/api/events/notification-intent.ts +33 -0
  269. package/src/api/events/open-url.ts +6 -8
  270. package/src/api/events/question-request.ts +67 -0
  271. package/src/api/events/relationship-state-updated.ts +4 -6
  272. package/src/api/events/secret-request.ts +42 -0
  273. package/src/api/events/subagent-event.ts +79 -0
  274. package/src/api/events/subagent-spawned.ts +40 -0
  275. package/src/api/events/subagent-status-changed.ts +65 -0
  276. package/src/api/events/sync-changed.ts +29 -0
  277. package/src/api/events/tool-result.ts +129 -0
  278. package/src/api/events/tool-use-start.ts +8 -10
  279. package/src/api/events/turn-profile-auto-routed.ts +28 -0
  280. package/src/api/events/ui-surface-complete.ts +30 -0
  281. package/src/api/events/ui-surface-dismiss.ts +22 -0
  282. package/src/api/events/ui-surface-show.ts +67 -0
  283. package/src/api/events/ui-surface-update.ts +26 -0
  284. package/src/api/events/usage-update.ts +34 -0
  285. package/src/api/events/user-message-echo.ts +35 -0
  286. package/src/api/index.ts +354 -0
  287. package/src/api/requests/dictation.ts +45 -0
  288. package/src/api/responses/disk-pressure-status.ts +26 -0
  289. package/src/api/responses/home.ts +217 -0
  290. package/src/api/responses/llm-context-response.ts +2 -0
  291. package/src/api/responses/memory-v3-selection-log.ts +50 -0
  292. package/src/api/responses/subagent-detail.ts +48 -0
  293. package/src/approvals/guardian-decision-primitive.ts +7 -15
  294. package/src/approvals/guardian-request-resolvers.ts +6 -9
  295. package/src/avatar/__tests__/avatar-manifest.test.ts +236 -0
  296. package/src/avatar/__tests__/avatar-store.test.ts +193 -0
  297. package/src/avatar/avatar-manifest.ts +195 -0
  298. package/src/avatar/avatar-store.ts +113 -0
  299. package/src/avatar/traits-png-sync.ts +8 -2
  300. package/src/background-wake/next-wake.test.ts +31 -1
  301. package/src/background-wake/next-wake.ts +4 -1
  302. package/src/calls/call-conversation-messages.ts +6 -4
  303. package/src/calls/guardian-action-sweep.ts +6 -4
  304. package/src/calls/relay-server.ts +12 -8
  305. package/src/calls/voice-session-bridge.ts +13 -27
  306. package/src/cli/commands/__tests__/memory-v3.test.ts +245 -0
  307. package/src/cli/commands/avatar.ts +17 -11
  308. package/src/cli/commands/conversations.ts +15 -1
  309. package/src/cli/commands/db/__tests__/repair.test.ts +540 -0
  310. package/src/cli/commands/db/__tests__/status.test.ts +253 -0
  311. package/src/cli/commands/db/format.ts +48 -0
  312. package/src/cli/commands/db/index.ts +29 -0
  313. package/src/cli/commands/db/repair-step-conversation-backfill.ts +345 -0
  314. package/src/cli/commands/db/repair-step-integrity.ts +146 -0
  315. package/src/cli/commands/db/repair-steps.ts +164 -0
  316. package/src/cli/commands/db/repair.ts +141 -0
  317. package/src/cli/commands/db/status.ts +366 -0
  318. package/src/cli/commands/memory-v3.ts +159 -445
  319. package/src/cli/lib/cli-colors.ts +24 -6
  320. package/src/cli/program.ts +4 -5
  321. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  322. package/src/config/assistant-feature-flags.ts +2 -2
  323. package/src/config/bundled-skills/app-builder/SKILL.md +14 -3
  324. package/src/config/bundled-skills/media-processing/services/reduce.ts +6 -9
  325. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +7 -2
  326. package/src/config/bundled-skills/schedule/SKILL.md +1 -1
  327. package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
  328. package/src/config/call-site-defaults.ts +2 -7
  329. package/src/config/feature-flag-registry.json +25 -9
  330. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -226
  331. package/src/config/schemas/call-site-catalog.ts +8 -15
  332. package/src/config/schemas/llm.ts +2 -3
  333. package/src/config/schemas/memory-lifecycle.ts +24 -0
  334. package/src/config/schemas/memory-v2.ts +0 -253
  335. package/src/config/schemas/memory-v3.ts +39 -0
  336. package/src/config/schemas/memory.ts +6 -1
  337. package/src/config/schemas/timeouts.ts +3 -1
  338. package/src/context/compactor.ts +54 -31
  339. package/src/context/token-estimator.ts +19 -0
  340. package/src/context/tool-result-truncation.ts +1 -43
  341. package/src/context/window-manager.ts +138 -20
  342. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +2 -2
  343. package/src/daemon/__tests__/web-search-status-text.test.ts +10 -6
  344. package/src/daemon/approval-generators.ts +4 -4
  345. package/src/daemon/config-watcher.ts +7 -1
  346. package/src/daemon/conversation-agent-loop-handlers.ts +225 -88
  347. package/src/daemon/conversation-agent-loop.ts +284 -584
  348. package/src/daemon/conversation-error.ts +7 -7
  349. package/src/daemon/conversation-history.ts +22 -6
  350. package/src/daemon/conversation-launch.ts +4 -8
  351. package/src/daemon/conversation-lifecycle.ts +10 -38
  352. package/src/daemon/conversation-messaging.ts +1 -3
  353. package/src/daemon/conversation-notifiers.ts +7 -5
  354. package/src/daemon/conversation-process.ts +100 -79
  355. package/src/daemon/conversation-runtime-assembly.ts +47 -21
  356. package/src/daemon/conversation-store.ts +6 -5
  357. package/src/daemon/conversation-surfaces.ts +55 -69
  358. package/src/daemon/conversation-tool-setup.ts +3 -0
  359. package/src/daemon/conversation.ts +91 -126
  360. package/src/daemon/daemon-skill-host.ts +2 -6
  361. package/src/daemon/disk-pressure-guard.ts +35 -29
  362. package/src/daemon/external-plugins-bootstrap.ts +46 -24
  363. package/src/daemon/first-greeting.ts +26 -4
  364. package/src/daemon/guardian-action-generators.ts +2 -2
  365. package/src/daemon/handlers/conversations.ts +6 -22
  366. package/src/daemon/handlers/shared.ts +4 -0
  367. package/src/daemon/handlers/skills.ts +15 -14
  368. package/src/daemon/host-app-control-proxy.ts +54 -1
  369. package/src/daemon/host-cu-proxy.ts +46 -22
  370. package/src/daemon/host-file-proxy.ts +25 -1
  371. package/src/daemon/host-proxy-preactivation.ts +25 -6
  372. package/src/daemon/lifecycle.ts +28 -55
  373. package/src/daemon/message-protocol.ts +2 -3
  374. package/src/daemon/message-provenance.ts +49 -0
  375. package/src/daemon/message-types/contacts.ts +3 -20
  376. package/src/daemon/message-types/conversations.ts +13 -111
  377. package/src/daemon/message-types/documents.ts +3 -9
  378. package/src/daemon/message-types/home.ts +4 -17
  379. package/src/daemon/message-types/integrations.ts +2 -6
  380. package/src/daemon/message-types/messages.ts +28 -343
  381. package/src/daemon/message-types/notifications.ts +2 -32
  382. package/src/daemon/message-types/settings.ts +3 -8
  383. package/src/daemon/message-types/skills.ts +2 -0
  384. package/src/daemon/message-types/surfaces.ts +2 -0
  385. package/src/daemon/message-types/sync.ts +12 -25
  386. package/src/daemon/message-types/workspace.ts +3 -11
  387. package/src/daemon/process-message.ts +49 -46
  388. package/src/daemon/server.ts +12 -0
  389. package/src/daemon/tool-side-effects.ts +10 -7
  390. package/src/daemon/trust-context.ts +13 -0
  391. package/src/daemon/wake-target-adapter.ts +11 -1
  392. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -1
  393. package/src/heartbeat/heartbeat-run-store.ts +31 -0
  394. package/src/heartbeat/heartbeat-service.ts +16 -0
  395. package/src/home/feature-gate.ts +22 -0
  396. package/src/home/feed-types.ts +36 -221
  397. package/src/ipc/__tests__/email-ipc.test.ts +0 -9
  398. package/src/ipc/routes/__tests__/route-adapter.test.ts +244 -0
  399. package/src/ipc/routes/route-adapter.ts +45 -6
  400. package/src/ipc/skill-routes/__tests__/memory.test.ts +18 -9
  401. package/src/ipc/skill-routes/__tests__/providers.test.ts +10 -10
  402. package/src/ipc/skill-routes/__tests__/registries.test.ts +28 -18
  403. package/src/ipc/skill-routes/memory.ts +26 -13
  404. package/src/ipc/skill-routes/providers.ts +5 -6
  405. package/src/ipc/skill-routes/registries.ts +13 -61
  406. package/src/live-voice/__tests__/live-voice-archive.test.ts +24 -11
  407. package/src/memory/__tests__/conversation-queries.test.ts +192 -8
  408. package/src/memory/__tests__/db-maintenance.test.ts +128 -0
  409. package/src/memory/__tests__/jobs-store-job-classes.test.ts +5 -4
  410. package/src/memory/__tests__/memory-retrospective-job.test.ts +10 -6
  411. package/src/memory/__tests__/memory-v3-selections-migration.test.ts +103 -0
  412. package/src/memory/context-search/agent-runner.ts +2 -4
  413. package/src/memory/conversation-crud.ts +39 -8
  414. package/src/memory/conversation-queries.ts +78 -22
  415. package/src/memory/db-init.ts +8 -0
  416. package/src/memory/db-maintenance.ts +18 -2
  417. package/src/memory/graph/consolidation.ts +8 -11
  418. package/src/memory/graph/conversation-graph-memory.ts +41 -8
  419. package/src/memory/graph/extraction.ts +6 -9
  420. package/src/memory/graph/narrative.ts +2 -2
  421. package/src/memory/graph/pattern-scan.ts +2 -2
  422. package/src/memory/graph/retriever.ts +20 -26
  423. package/src/memory/graph/tools.ts +4 -4
  424. package/src/memory/job-handlers/conversation-starters.ts +32 -32
  425. package/src/memory/job-handlers/summarization.ts +1 -2
  426. package/src/memory/jobs-store.ts +3 -1
  427. package/src/memory/jobs-worker.ts +51 -39
  428. package/src/memory/llm-request-log-source-clickhouse.ts +5 -31
  429. package/src/memory/llm-request-log-source-local.ts +0 -11
  430. package/src/memory/llm-request-log-source.ts +9 -25
  431. package/src/memory/llm-request-log-store.ts +0 -41
  432. package/src/memory/llm-usage-store.ts +10 -0
  433. package/src/memory/memory-marker.ts +17 -0
  434. package/src/memory/memory-retrospective-job.ts +6 -2
  435. package/src/memory/memory-v2-activation-log-store.ts +1 -83
  436. package/src/memory/migrations/267-llm-usage-events-add-assistant-version.ts +46 -0
  437. package/src/memory/migrations/268-add-memory-v3-selections.ts +28 -0
  438. package/src/memory/migrations/269-schedule-script-timeout.ts +11 -0
  439. package/src/memory/migrations/270-messages-role-created-at-index.ts +18 -0
  440. package/src/memory/migrations/__tests__/267-llm-usage-events-add-assistant-version.test.ts +117 -0
  441. package/src/memory/migrations/index.ts +4 -0
  442. package/src/memory/schema/infrastructure.ts +11 -0
  443. package/src/memory/v2/__tests__/consolidation-job.test.ts +124 -0
  444. package/src/memory/v2/__tests__/migration.test.ts +11 -3
  445. package/src/memory/v2/__tests__/page-index.test.ts +37 -1
  446. package/src/memory/v2/__tests__/router.test.ts +14 -4
  447. package/src/memory/v2/__tests__/sweep-job.test.ts +6 -5
  448. package/src/memory/v2/backfill-jobs.ts +6 -0
  449. package/src/memory/v2/consolidation-job.ts +89 -9
  450. package/src/memory/v2/migration.ts +5 -3
  451. package/src/memory/v2/page-index.ts +11 -0
  452. package/src/memory/v2/router.ts +8 -11
  453. package/src/memory/v2/sweep-job.ts +8 -11
  454. package/src/memory/v2/types.ts +1 -0
  455. package/src/memory/v3/__tests__/assign.test.ts +242 -0
  456. package/src/memory/v3/__tests__/capabilities.test.ts +118 -0
  457. package/src/memory/v3/__tests__/core.test.ts +39 -0
  458. package/src/memory/v3/__tests__/fixtures/eval-turns.json +36 -0
  459. package/src/memory/v3/__tests__/fixtures/live-turns.json +37 -0
  460. package/src/memory/v3/__tests__/health.test.ts +203 -0
  461. package/src/memory/v3/__tests__/live-integration.test.ts +330 -0
  462. package/src/memory/v3/__tests__/maintain-job.test.ts +288 -0
  463. package/src/memory/v3/__tests__/needle.test.ts +107 -0
  464. package/src/memory/v3/__tests__/orchestrate.test.ts +400 -0
  465. package/src/memory/v3/__tests__/reconcile.test.ts +274 -0
  466. package/src/memory/v3/__tests__/render-injection.test.ts +61 -0
  467. package/src/memory/v3/__tests__/router.test.ts +260 -0
  468. package/src/memory/v3/__tests__/selection-log-store.test.ts +179 -0
  469. package/src/memory/v3/__tests__/selector.test.ts +404 -0
  470. package/src/memory/v3/__tests__/shadow-plugin.test.ts +414 -0
  471. package/src/memory/v3/__tests__/snapshot.test.ts +168 -0
  472. package/src/memory/v3/__tests__/tree.test.ts +192 -0
  473. package/src/memory/v3/__tests__/types.test.ts +54 -0
  474. package/src/memory/v3/__tests__/working-set-eviction.test.ts +106 -0
  475. package/src/memory/v3/__tests__/working-set-skeleton.test.ts +44 -0
  476. package/src/memory/v3/assign.ts +268 -0
  477. package/src/memory/v3/capabilities.ts +124 -0
  478. package/src/memory/v3/core.ts +26 -0
  479. package/src/memory/v3/data/README.md +84 -0
  480. package/src/memory/v3/data/assignments.json +5 -0
  481. package/src/memory/v3/data/core.json +1 -0
  482. package/src/memory/v3/data/leaves/domain-a/topic-x.md +9 -0
  483. package/src/memory/v3/data/leaves/domain-a/topic-y.md +9 -0
  484. package/src/memory/v3/data/leaves/domain-b/topic-z.md +9 -0
  485. package/src/memory/v3/health.ts +0 -0
  486. package/src/memory/v3/maintain-job.ts +314 -0
  487. package/src/memory/v3/needle.ts +115 -0
  488. package/src/memory/v3/orchestrate.ts +114 -0
  489. package/src/memory/v3/page-content.ts +34 -0
  490. package/src/memory/v3/provider-blocks.ts +16 -0
  491. package/src/memory/v3/reconcile.ts +523 -0
  492. package/src/memory/v3/render-injection.ts +32 -0
  493. package/src/memory/v3/router.ts +184 -0
  494. package/src/memory/v3/selection-log-store.ts +84 -0
  495. package/src/memory/v3/selector.ts +211 -0
  496. package/src/memory/v3/shadow-plugin.ts +379 -0
  497. package/src/memory/v3/snapshot.ts +209 -0
  498. package/src/memory/v3/tree.ts +174 -0
  499. package/src/memory/v3/types.ts +46 -60
  500. package/src/memory/v3/working-set.ts +88 -0
  501. package/src/messaging/providers/slack/render-transcript.test.ts +1 -1
  502. package/src/messaging/providers/slack/render-transcript.ts +2 -2
  503. package/src/messaging/style-analyzer.ts +8 -11
  504. package/src/notifications/conversation-pairing.ts +8 -6
  505. package/src/notifications/decision-engine.ts +10 -13
  506. package/src/notifications/preference-extractor.ts +11 -14
  507. package/src/permissions/prompter.ts +42 -36
  508. package/src/permissions/question-prompter.test.ts +35 -26
  509. package/src/permissions/question-prompter.ts +6 -10
  510. package/src/plugin-api/index.ts +2 -0
  511. package/src/plugin-api/types.ts +25 -3
  512. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +93 -0
  513. package/src/plugins/defaults/circuit-breaker/package.json +15 -0
  514. package/src/plugins/defaults/circuit-breaker/register.ts +39 -0
  515. package/src/plugins/defaults/compaction/middlewares/compaction.ts +25 -0
  516. package/src/plugins/defaults/compaction/package.json +15 -0
  517. package/src/plugins/defaults/compaction/register.ts +35 -0
  518. package/src/plugins/defaults/compaction/terminal.ts +73 -0
  519. package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +22 -0
  520. package/src/plugins/defaults/empty-response/package.json +15 -0
  521. package/src/plugins/defaults/empty-response/register.ts +28 -0
  522. package/src/plugins/defaults/empty-response/terminal.ts +106 -0
  523. package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +35 -0
  524. package/src/plugins/defaults/history-repair/package.json +15 -0
  525. package/src/plugins/defaults/history-repair/register.ts +24 -0
  526. package/src/{daemon/history-repair.ts → plugins/defaults/history-repair/terminal.ts} +48 -35
  527. package/src/plugins/defaults/index.ts +29 -40
  528. package/src/plugins/defaults/injectors/package.json +15 -0
  529. package/src/plugins/defaults/{injectors.ts → injectors/register.ts} +14 -38
  530. package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +17 -0
  531. package/src/plugins/defaults/llm-call/package.json +15 -0
  532. package/src/plugins/defaults/{llm-call.ts → llm-call/register.ts} +6 -38
  533. package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +17 -0
  534. package/src/plugins/defaults/memory-retrieval/package.json +15 -0
  535. package/src/plugins/defaults/{memory-retrieval.ts → memory-retrieval/register.ts} +10 -48
  536. package/src/plugins/defaults/{overflow-reduce.ts → overflow-reduce/middlewares/overflowReduce.ts} +18 -77
  537. package/src/plugins/defaults/overflow-reduce/package.json +15 -0
  538. package/src/plugins/defaults/overflow-reduce/register.ts +42 -0
  539. package/src/plugins/defaults/persistence/middlewares/persistence.ts +19 -0
  540. package/src/plugins/defaults/persistence/package.json +15 -0
  541. package/src/plugins/defaults/persistence/register.ts +38 -0
  542. package/src/plugins/defaults/persistence/terminal.ts +83 -0
  543. package/src/plugins/defaults/title-generate/package.json +15 -0
  544. package/src/plugins/defaults/title-generate/register.ts +35 -0
  545. package/src/plugins/defaults/title-generate/terminal.ts +31 -0
  546. package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +23 -0
  547. package/src/plugins/defaults/token-estimate/package.json +15 -0
  548. package/src/plugins/defaults/token-estimate/register.ts +34 -0
  549. package/src/plugins/defaults/token-estimate/terminal.ts +40 -0
  550. package/src/plugins/defaults/tool-error/middlewares/toolError.ts +21 -0
  551. package/src/plugins/defaults/tool-error/package.json +15 -0
  552. package/src/plugins/defaults/tool-error/register.ts +35 -0
  553. package/src/plugins/defaults/tool-error/terminal.ts +47 -0
  554. package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +23 -0
  555. package/src/plugins/defaults/tool-execute/package.json +15 -0
  556. package/src/plugins/defaults/{tool-execute.ts → tool-execute/register.ts} +8 -46
  557. package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +23 -0
  558. package/src/plugins/defaults/tool-result-truncate/package.json +15 -0
  559. package/src/plugins/defaults/tool-result-truncate/register.ts +35 -0
  560. package/src/plugins/defaults/tool-result-truncate/terminal.ts +113 -0
  561. package/src/plugins/defaults/tool-result-truncate/types.ts +22 -0
  562. package/src/plugins/external-plugin-loader.ts +2 -2
  563. package/src/plugins/pipeline.ts +0 -12
  564. package/src/plugins/types.ts +51 -90
  565. package/src/plugins/user-loader.ts +4 -3
  566. package/src/proactive-artifact/aux-message-injector.ts +0 -1
  567. package/src/proactive-artifact/job.test.ts +20 -8
  568. package/src/proactive-artifact/job.ts +3 -1
  569. package/src/prompts/sections.ts +20 -7
  570. package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +2 -2
  571. package/src/prompts/templates/BOOTSTRAP.md +5 -1
  572. package/src/prompts/templates/system-sections.ts +6 -0
  573. package/src/providers/__tests__/retry-callsite.test.ts +25 -25
  574. package/src/providers/__tests__/satellite-connection-routing.test.ts +7 -21
  575. package/src/providers/anthropic/client.ts +24 -5
  576. package/src/providers/call-site-routing.ts +1 -9
  577. package/src/providers/gemini/client.ts +152 -34
  578. package/src/providers/gemini/inline-media.ts +74 -0
  579. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +0 -2
  580. package/src/providers/openai/chat-completions-provider.ts +1 -4
  581. package/src/providers/openai/responses-provider.ts +1 -4
  582. package/src/providers/openrouter/client.ts +1 -6
  583. package/src/providers/provider-send-message.ts +6 -6
  584. package/src/providers/ratelimit.ts +1 -9
  585. package/src/providers/retry.ts +0 -5
  586. package/src/providers/types.ts +11 -2
  587. package/src/providers/usage-tracking.ts +1 -9
  588. package/src/runtime/__tests__/agent-wake.test.ts +131 -26
  589. package/src/runtime/__tests__/background-job-runner.test.ts +1 -3
  590. package/src/runtime/agent-wake.ts +93 -18
  591. package/src/runtime/assistant-event-hub.ts +2 -2
  592. package/src/runtime/auth/__tests__/guard-tests.test.ts +75 -109
  593. package/src/runtime/auth/__tests__/route-policy.test.ts +153 -170
  594. package/src/runtime/auth/route-policy.ts +42 -1079
  595. package/src/runtime/background-job-runner.ts +1 -4
  596. package/src/runtime/btw-sidechain.ts +3 -1
  597. package/src/runtime/channel-approvals.ts +3 -14
  598. package/src/runtime/channel-invite-transport.ts +5 -6
  599. package/src/runtime/channel-readiness-service.ts +2 -5
  600. package/src/runtime/channel-retry-sweep.ts +12 -16
  601. package/src/runtime/conversation-stream-state.ts +294 -0
  602. package/src/runtime/http-router.ts +19 -22
  603. package/src/runtime/http-types.ts +12 -6
  604. package/src/runtime/invite-instruction-generator.ts +3 -3
  605. package/src/runtime/pending-interactions.ts +2 -2
  606. package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +565 -0
  607. package/src/runtime/routes/__tests__/content-source-routes.test.ts +4 -4
  608. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +62 -32
  609. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +237 -0
  610. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -22
  611. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +7 -2
  612. package/src/runtime/routes/__tests__/sanity-routes.test.ts +6 -6
  613. package/src/runtime/routes/__tests__/stt-routes.test.ts +3 -3
  614. package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +5 -2
  615. package/src/runtime/routes/__tests__/tts-routes.test.ts +3 -3
  616. package/src/runtime/routes/acp-routes.test.ts +97 -75
  617. package/src/runtime/routes/acp-routes.ts +29 -6
  618. package/src/runtime/routes/app-management-routes.ts +97 -24
  619. package/src/runtime/routes/app-routes.ts +25 -5
  620. package/src/runtime/routes/approval-routes.ts +16 -4
  621. package/src/runtime/routes/attachment-routes.ts +25 -1
  622. package/src/runtime/routes/audio-routes.ts +1 -0
  623. package/src/runtime/routes/audit-routes.ts +5 -0
  624. package/src/runtime/routes/auth-routes.ts +5 -0
  625. package/src/runtime/routes/avatar-routes.ts +238 -59
  626. package/src/runtime/routes/background-tool-routes.ts +9 -0
  627. package/src/runtime/routes/background-wake-routes.ts +13 -3
  628. package/src/runtime/routes/backup-routes.ts +45 -0
  629. package/src/runtime/routes/bookmark-routes.ts +13 -0
  630. package/src/runtime/routes/brain-graph-routes.ts +9 -0
  631. package/src/runtime/routes/browser-routes.ts +5 -0
  632. package/src/runtime/routes/browser-tabs-routes.ts +5 -0
  633. package/src/runtime/routes/btw-routes.ts +5 -1
  634. package/src/runtime/routes/cache-routes.ts +13 -0
  635. package/src/runtime/routes/call-routes.ts +21 -10
  636. package/src/runtime/routes/channel-availability-routes.ts +5 -1
  637. package/src/runtime/routes/channel-readiness-routes.ts +37 -4
  638. package/src/runtime/routes/channel-route-definitions.ts +21 -0
  639. package/src/runtime/routes/channel-verification-routes.ts +21 -0
  640. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +9 -2
  641. package/src/runtime/routes/client-routes.ts +9 -0
  642. package/src/runtime/routes/consolidation-routes.ts +13 -5
  643. package/src/runtime/routes/contact-prompt-routes.ts +9 -0
  644. package/src/runtime/routes/contact-routes.ts +90 -23
  645. package/src/runtime/routes/content-source-routes.ts +5 -1
  646. package/src/runtime/routes/conversation-analysis-routes.ts +5 -1
  647. package/src/runtime/routes/conversation-attention-routes.ts +5 -0
  648. package/src/runtime/routes/conversation-cli-routes.ts +54 -7
  649. package/src/runtime/routes/conversation-compaction-routes.ts +54 -25
  650. package/src/runtime/routes/conversation-list-routes.ts +81 -12
  651. package/src/runtime/routes/conversation-management-routes.ts +57 -14
  652. package/src/runtime/routes/conversation-query-routes.ts +88 -41
  653. package/src/runtime/routes/conversation-routes.ts +74 -19
  654. package/src/runtime/routes/conversation-starter-routes.ts +22 -13
  655. package/src/runtime/routes/conversations-import-routes.ts +6 -1
  656. package/src/runtime/routes/credential-prompt-routes.ts +5 -0
  657. package/src/runtime/routes/credential-routes.ts +25 -6
  658. package/src/runtime/routes/debug-bash-routes.ts +5 -0
  659. package/src/runtime/routes/debug-routes.ts +11 -2
  660. package/src/runtime/routes/defer-routes.ts +13 -0
  661. package/src/runtime/routes/diagnostics-routes.ts +37 -46
  662. package/src/runtime/routes/disk-pressure-routes.ts +17 -31
  663. package/src/runtime/routes/document-comments-routes.ts +46 -27
  664. package/src/runtime/routes/documents-routes.ts +21 -10
  665. package/src/runtime/routes/domain-routes.ts +61 -28
  666. package/src/runtime/routes/email-routes.ts +33 -0
  667. package/src/runtime/routes/events-routes.ts +114 -9
  668. package/src/runtime/routes/filing-routes.ts +9 -4
  669. package/src/runtime/routes/gateway-log-routes.ts +5 -0
  670. package/src/runtime/routes/global-search-routes.ts +53 -50
  671. package/src/runtime/routes/group-routes.ts +21 -5
  672. package/src/runtime/routes/guardian-action-routes.ts +9 -0
  673. package/src/runtime/routes/guardian-approval-interception.ts +0 -31
  674. package/src/runtime/routes/heartbeat-routes.ts +25 -9
  675. package/src/runtime/routes/home-feed-routes.ts +23 -19
  676. package/src/runtime/routes/home-state-routes.ts +8 -40
  677. package/src/runtime/routes/host-app-control-routes.ts +5 -0
  678. package/src/runtime/routes/host-bash-routes.ts +5 -0
  679. package/src/runtime/routes/host-browser-routes.ts +13 -0
  680. package/src/runtime/routes/host-cu-routes.ts +5 -0
  681. package/src/runtime/routes/host-file-routes.ts +26 -6
  682. package/src/runtime/routes/host-transfer-routes.ts +13 -2
  683. package/src/runtime/routes/http-adapter.ts +1 -2
  684. package/src/runtime/routes/identity-intro-cache.ts +17 -6
  685. package/src/runtime/routes/identity-routes.ts +12 -2
  686. package/src/runtime/routes/image-generation-routes.ts +5 -0
  687. package/src/runtime/routes/inbound-message-handler.ts +15 -11
  688. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -12
  689. package/src/runtime/routes/inbound-stages/background-dispatch.ts +15 -19
  690. package/src/runtime/routes/inference-profile-session-routes.ts +13 -3
  691. package/src/runtime/routes/inference-provider-connection-routes.ts +21 -5
  692. package/src/runtime/routes/inference-send-routes.ts +11 -11
  693. package/src/runtime/routes/integrations/a2a.ts +30 -7
  694. package/src/runtime/routes/integrations/slack/channel.ts +19 -3
  695. package/src/runtime/routes/integrations/slack/share.ts +9 -2
  696. package/src/runtime/routes/integrations/telegram.ts +28 -9
  697. package/src/runtime/routes/integrations/twilio.ts +35 -7
  698. package/src/runtime/routes/integrations/vercel.ts +3 -3
  699. package/src/runtime/routes/internal-oauth-routes.ts +5 -0
  700. package/src/runtime/routes/internal-twilio-routes.ts +13 -0
  701. package/src/runtime/routes/llm-call-sites-routes.ts +39 -4
  702. package/src/runtime/routes/log-export-routes.ts +28 -10
  703. package/src/runtime/routes/mcp-auth-routes.ts +25 -0
  704. package/src/runtime/routes/memory-item-routes.ts +21 -10
  705. package/src/runtime/routes/memory-v2-routes.ts +90 -36
  706. package/src/runtime/routes/memory-v3-routes.ts +273 -407
  707. package/src/runtime/routes/migration-rollback-routes.ts +5 -1
  708. package/src/runtime/routes/migration-routes.ts +29 -0
  709. package/src/runtime/routes/notification-routes.ts +17 -1
  710. package/src/runtime/routes/oauth-apps.ts +33 -11
  711. package/src/runtime/routes/oauth-commands-routes.ts +37 -14
  712. package/src/runtime/routes/oauth-connect-routes.ts +9 -0
  713. package/src/runtime/routes/oauth-lifecycle-routes.ts +5 -1
  714. package/src/runtime/routes/oauth-providers.ts +35 -10
  715. package/src/runtime/routes/platform-routes.ts +21 -0
  716. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +3 -2
  717. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +37 -16
  718. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +7 -3
  719. package/src/runtime/routes/playground/__tests__/state.test.ts +10 -3
  720. package/src/runtime/routes/playground/force-compact.ts +1 -1
  721. package/src/runtime/routes/playground/helpers.ts +0 -1
  722. package/src/runtime/routes/playground/inject-failures.ts +13 -8
  723. package/src/runtime/routes/playground/reset-circuit.ts +14 -9
  724. package/src/runtime/routes/playground/seed-conversation.ts +1 -1
  725. package/src/runtime/routes/playground/seeded-conversations.ts +3 -3
  726. package/src/runtime/routes/playground/state.ts +4 -3
  727. package/src/runtime/routes/plugins-routes.ts +22 -19
  728. package/src/runtime/routes/profiler-routes.ts +17 -4
  729. package/src/runtime/routes/ps-routes.ts +5 -0
  730. package/src/runtime/routes/publish-routes.ts +13 -3
  731. package/src/runtime/routes/question-routes.ts +5 -0
  732. package/src/runtime/routes/recording-routes.ts +25 -12
  733. package/src/runtime/routes/rename-conversation-routes.ts +5 -0
  734. package/src/runtime/routes/sanity-routes.ts +9 -2
  735. package/src/runtime/routes/schedule-routes.ts +137 -47
  736. package/src/runtime/routes/secret-routes.ts +17 -4
  737. package/src/runtime/routes/sequence-routes.ts +33 -0
  738. package/src/runtime/routes/settings-routes.ts +65 -19
  739. package/src/runtime/routes/skills-routes.ts +133 -69
  740. package/src/runtime/routes/slack-channel-routes.ts +5 -0
  741. package/src/runtime/routes/stt-routes.ts +13 -6
  742. package/src/runtime/routes/subagents-routes.ts +24 -18
  743. package/src/runtime/routes/suggest-trust-rule-routes.ts +7 -2
  744. package/src/runtime/routes/surface-action-routes.ts +9 -0
  745. package/src/runtime/routes/surface-content-routes.ts +10 -2
  746. package/src/runtime/routes/task-routes.ts +37 -0
  747. package/src/runtime/routes/telemetry-routes.ts +9 -0
  748. package/src/runtime/routes/trace-event-routes.ts +42 -1
  749. package/src/runtime/routes/trust-rules-routes.ts +5 -0
  750. package/src/runtime/routes/tts-routes.ts +13 -6
  751. package/src/runtime/routes/types.ts +17 -8
  752. package/src/runtime/routes/ui-request-routes.ts +5 -0
  753. package/src/runtime/routes/upgrade-broadcast-routes.ts +5 -0
  754. package/src/runtime/routes/usage-routes.ts +71 -3
  755. package/src/runtime/routes/user-routes-cli.ts +9 -0
  756. package/src/runtime/routes/user-routes.ts +5 -1
  757. package/src/runtime/routes/wake-conversation-routes.ts +5 -0
  758. package/src/runtime/routes/watcher-routes.ts +21 -0
  759. package/src/runtime/routes/webhook-routes.ts +9 -0
  760. package/src/runtime/routes/wipe-conversation-routes.ts +5 -0
  761. package/src/runtime/routes/work-items-routes.ts +47 -19
  762. package/src/runtime/routes/workspace-commit-routes.ts +5 -0
  763. package/src/runtime/routes/workspace-routes.test.ts +42 -0
  764. package/src/runtime/routes/workspace-routes.ts +120 -9
  765. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -4
  766. package/src/runtime/services/analyze-conversation.ts +3 -6
  767. package/src/runtime/services/conversation-serializer.ts +24 -2
  768. package/src/runtime/sync/resource-sync-events.ts +16 -2
  769. package/src/runtime/sync/sync-publisher.ts +2 -2
  770. package/src/schedule/run-script.ts +28 -3
  771. package/src/schedule/schedule-store.ts +8 -0
  772. package/src/schedule/scheduler.ts +3 -1
  773. package/src/signals/user-message.ts +5 -8
  774. package/src/skills/catalog-files.ts +4 -1
  775. package/src/skills/clawhub-files.ts +2 -0
  776. package/src/skills/skillssh-files.ts +2 -0
  777. package/src/subagent/manager.ts +3 -6
  778. package/src/telemetry/types.ts +26 -0
  779. package/src/telemetry/usage-telemetry-reporter.test.ts +138 -1
  780. package/src/telemetry/usage-telemetry-reporter.ts +31 -0
  781. package/src/tools/acp/spawn.test.ts +88 -38
  782. package/src/tools/apps/definitions.ts +8 -4
  783. package/src/tools/ask-question/ask-question-tool.test.ts +120 -105
  784. package/src/tools/ask-question/ask-question-tool.ts +85 -90
  785. package/src/tools/computer-use/definitions.ts +28 -24
  786. package/src/tools/credential-execution/make-authenticated-request.ts +56 -51
  787. package/src/tools/credential-execution/manage-secure-command-tool.ts +2 -2
  788. package/src/tools/credential-execution/run-authenticated-command.ts +82 -77
  789. package/src/tools/credentials/vault.ts +112 -111
  790. package/src/tools/execution-target.ts +1 -1
  791. package/src/tools/execution-timeout.ts +3 -4
  792. package/src/tools/filesystem/edit.ts +45 -42
  793. package/src/tools/filesystem/list.ts +33 -30
  794. package/src/tools/filesystem/read.ts +54 -35
  795. package/src/tools/filesystem/write.ts +34 -31
  796. package/src/tools/host-filesystem/edit.ts +44 -42
  797. package/src/tools/host-filesystem/read.ts +49 -35
  798. package/src/tools/host-filesystem/transfer.ts +121 -108
  799. package/src/tools/host-filesystem/write.ts +33 -31
  800. package/src/tools/host-terminal/host-shell.ts +50 -48
  801. package/src/tools/memory/register.ts +23 -24
  802. package/src/tools/network/web-fetch.ts +49 -46
  803. package/src/tools/network/web-search.ts +16 -13
  804. package/src/tools/registry.ts +39 -16
  805. package/src/tools/schedule/create.ts +11 -0
  806. package/src/tools/schedule/update.ts +16 -0
  807. package/src/tools/shared/filesystem/audio-read.ts +122 -0
  808. package/src/tools/shared/filesystem/image-read.ts +1 -1
  809. package/src/tools/skills/execute.ts +34 -31
  810. package/src/tools/skills/load.ts +29 -23
  811. package/src/tools/subagent/notify-parent.ts +35 -32
  812. package/src/tools/system/avatar-generator.ts +13 -22
  813. package/src/tools/system/request-permission.ts +30 -27
  814. package/src/tools/terminal/shell.ts +190 -61
  815. package/src/tools/tool-defaults.ts +20 -9
  816. package/src/tools/tool-manifest.ts +4 -4
  817. package/src/tools/types.ts +74 -23
  818. package/src/tools/ui-surface/definitions.ts +69 -9
  819. package/src/usage/types.ts +10 -0
  820. package/src/util/errors.ts +2 -2
  821. package/src/util/map-limit.ts +27 -0
  822. package/src/util/platform.ts +15 -12
  823. package/src/work-items/work-item-runner.ts +7 -2
  824. package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +7 -20
  825. package/src/workspace/migrations/092-backfill-v3-leaves.ts +169 -0
  826. package/src/workspace/migrations/093-backfill-leaf-ids.ts +144 -0
  827. package/src/workspace/migrations/094-seed-avatar-manifest.ts +155 -0
  828. package/src/workspace/migrations/__tests__/094-seed-avatar-manifest.test.ts +136 -0
  829. package/src/workspace/migrations/__tests__/backfill-leaf-ids.test.ts +175 -0
  830. package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +124 -0
  831. package/src/workspace/migrations/registry.ts +6 -0
  832. package/src/workspace/provider-commit-message-generator.ts +15 -17
  833. package/tsconfig.json +4 -1
  834. package/src/__tests__/history-repair-pipeline.test.ts +0 -396
  835. package/src/cli/commands/__tests__/memory-v3-render.test.ts +0 -340
  836. package/src/cli/commands/memory-v3-render.ts +0 -491
  837. package/src/daemon/message-types/disk-pressure.ts +0 -9
  838. package/src/email/feature-gate.ts +0 -23
  839. package/src/memory/v3/__tests__/coactivation-store.test.ts +0 -422
  840. package/src/memory/v3/__tests__/consolidation-job.test.ts +0 -466
  841. package/src/memory/v3/__tests__/coretrieval-seed.test.ts +0 -270
  842. package/src/memory/v3/__tests__/edge-learning-job.test.ts +0 -324
  843. package/src/memory/v3/__tests__/edges.test.ts +0 -706
  844. package/src/memory/v3/__tests__/filter.test.ts +0 -560
  845. package/src/memory/v3/__tests__/gate.test.ts +0 -637
  846. package/src/memory/v3/__tests__/index-composition.test.ts +0 -291
  847. package/src/memory/v3/__tests__/loop.test.ts +0 -775
  848. package/src/memory/v3/__tests__/retriever.test.ts +0 -226
  849. package/src/memory/v3/__tests__/scouts.test.ts +0 -489
  850. package/src/memory/v3/__tests__/shadow-diff.test.ts +0 -225
  851. package/src/memory/v3/__tests__/shadow-middleware.test.ts +0 -398
  852. package/src/memory/v3/__tests__/system-prompts.test.ts +0 -154
  853. package/src/memory/v3/__tests__/traversal.test.ts +0 -508
  854. package/src/memory/v3/__tests__/tree-index.test.ts +0 -280
  855. package/src/memory/v3/__tests__/tree-store.test.ts +0 -529
  856. package/src/memory/v3/__tests__/tree-walk.test.ts +0 -784
  857. package/src/memory/v3/__tests__/validate.test.ts +0 -277
  858. package/src/memory/v3/auto-edges.ts +0 -223
  859. package/src/memory/v3/coactivation-store.ts +0 -124
  860. package/src/memory/v3/consolidation-job.ts +0 -323
  861. package/src/memory/v3/coretrieval-seed.ts +0 -240
  862. package/src/memory/v3/edge-learning-job.ts +0 -160
  863. package/src/memory/v3/edges.ts +0 -286
  864. package/src/memory/v3/filter.ts +0 -286
  865. package/src/memory/v3/gate.ts +0 -349
  866. package/src/memory/v3/index-composition.ts +0 -126
  867. package/src/memory/v3/llm-capture.ts +0 -46
  868. package/src/memory/v3/loop.ts +0 -430
  869. package/src/memory/v3/maintenance.ts +0 -144
  870. package/src/memory/v3/prompt-context.ts +0 -33
  871. package/src/memory/v3/prompts/consolidation.ts +0 -458
  872. package/src/memory/v3/prompts/system-prompts.ts +0 -196
  873. package/src/memory/v3/retriever.ts +0 -33
  874. package/src/memory/v3/scouts.ts +0 -431
  875. package/src/memory/v3/shadow-diff.ts +0 -287
  876. package/src/memory/v3/shadow-middleware.ts +0 -347
  877. package/src/memory/v3/traversal.ts +0 -211
  878. package/src/memory/v3/tree-index.ts +0 -237
  879. package/src/memory/v3/tree-store.ts +0 -394
  880. package/src/memory/v3/tree-walk.ts +0 -356
  881. package/src/memory/v3/validate.ts +0 -323
  882. package/src/plugins/defaults/circuit-breaker.ts +0 -141
  883. package/src/plugins/defaults/compaction.ts +0 -141
  884. package/src/plugins/defaults/empty-response.ts +0 -124
  885. package/src/plugins/defaults/history-repair.ts +0 -83
  886. package/src/plugins/defaults/persistence.ts +0 -146
  887. package/src/plugins/defaults/title-generate.ts +0 -90
  888. package/src/plugins/defaults/token-estimate.ts +0 -101
  889. package/src/plugins/defaults/tool-error.ts +0 -119
  890. package/src/plugins/defaults/tool-result-truncate.ts +0 -84
  891. package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +0 -35
@@ -1,6 +1,10 @@
1
1
  import type * as genai from "@google/genai";
2
2
  import { ApiError, GoogleGenAI, ThinkingLevel } from "@google/genai";
3
3
 
4
+ import {
5
+ THINKING_LEVELS,
6
+ type ThinkingLevel as ThinkingLevelName,
7
+ } from "../../config/schemas/llm.js";
4
8
  import { isAbortReason } from "../../util/abort-reasons.js";
5
9
  import { ProviderError } from "../../util/errors.js";
6
10
  import { getLogger } from "../../util/logger.js";
@@ -12,12 +16,16 @@ import type {
12
16
  Provider,
13
17
  ProviderResponse,
14
18
  SendMessageOptions,
15
- ToolDefinition,
16
19
  } from "../types.js";
17
20
  import {
18
21
  ContextOverflowError,
19
22
  extractOverflowTokensFromMessage,
20
23
  } from "../types.js";
24
+ import {
25
+ base64ByteLength,
26
+ GEMINI_MAX_INLINE_AUDIO_BYTES,
27
+ normalizeGeminiAudioMime,
28
+ } from "./inline-media.js";
21
29
 
22
30
  /**
23
31
  * Token/context-specific phrases that reliably indicate context-overflow
@@ -34,40 +42,100 @@ function isGemini3Model(model: string): boolean {
34
42
  return model.startsWith("gemini-3") || model.startsWith("models/gemini-3");
35
43
  }
36
44
 
37
- const THINKING_LEVEL_BY_NAME: Record<string, ThinkingLevel> = {
45
+ const THINKING_LEVEL_BY_NAME: Record<ThinkingLevelName, ThinkingLevel> = {
38
46
  minimal: ThinkingLevel.MINIMAL,
39
47
  low: ThinkingLevel.LOW,
40
48
  medium: ThinkingLevel.MEDIUM,
41
49
  high: ThinkingLevel.HIGH,
42
50
  };
43
51
 
52
+ /**
53
+ * Default thinking level for Gemini Pro models when the profile doesn't pin
54
+ * one. Pro rejects `"minimal"` and an absent level resolves to `"minimal"`
55
+ * upstream, so we pin Google's documented Pro default (`"high"`) — always a
56
+ * supported value.
57
+ */
58
+ const GEMINI_PRO_DEFAULT_THINKING_LEVEL: ThinkingLevelName = "high";
59
+
60
+ /**
61
+ * Gemini 3.x Pro family accepts only `low`/`medium`/`high` (no `"minimal"`) and
62
+ * cannot fully disable thinking. Matches `gemini-3.1-pro-preview`,
63
+ * `gemini-3.1-pro-preview-customtools`, and future `gemini-3*pro*`.
64
+ */
65
+ function isGeminiProModel(model: string): boolean {
66
+ const normalized = model.startsWith("models/")
67
+ ? model.slice("models/".length)
68
+ : model;
69
+ return /^gemini-3.*pro/.test(normalized);
70
+ }
71
+
72
+ /**
73
+ * Lowest thinking level the model accepts. Pro's floor is `"low"`; every other
74
+ * thinking-capable Gemini model accepts `"minimal"`.
75
+ */
76
+ function geminiThinkingFloor(model: string): ThinkingLevelName {
77
+ return isGeminiProModel(model) ? "low" : "minimal";
78
+ }
79
+
80
+ /**
81
+ * Raise `level` to `floor` when it sits below it, so we never send a level the
82
+ * model rejects (e.g. `"minimal"` to a Pro model).
83
+ */
84
+ function clampThinkingLevelToFloor(
85
+ level: ThinkingLevelName,
86
+ floor: ThinkingLevelName,
87
+ ): ThinkingLevelName {
88
+ return THINKING_LEVELS.indexOf(level) < THINKING_LEVELS.indexOf(floor)
89
+ ? floor
90
+ : level;
91
+ }
92
+
44
93
  /**
45
94
  * Translate the resolved wire-shape `thinking` config into Gemini's
46
- * `thinkingConfig`. Returns `undefined` when no thinking config was supplied,
47
- * which lets Google's per-model default apply (e.g. `gemini-3.5-flash`
48
- * defaults to dynamic medium-level thinking).
95
+ * `thinkingConfig`, guaranteeing the emitted `thinkingLevel` is one the model
96
+ * accepts. Returns `undefined` when nothing needs to be set, which lets
97
+ * Google's per-model default apply (e.g. `gemini-3.5-flash` defaults to
98
+ * dynamic medium-level thinking).
99
+ *
100
+ * - `enabled: false` maps to the model's floor — the most "off" state it
101
+ * allows (`"minimal"` for most models, `"low"` for Pro, which can't disable
102
+ * thinking).
103
+ * - An explicit `level` below the floor is raised to the floor.
104
+ * - When no `level` is pinned, Pro models get the documented default (`"high"`)
105
+ * because an absent level resolves to the unsupported `"minimal"` upstream;
106
+ * other models keep Google's per-model default by leaving the level unset.
49
107
  *
50
- * `enabled: false` maps to `thinkingLevel: MINIMAL` because Gemini 3.x cannot
51
- * fully disable thinking `"minimal"` is the floor. `includeThoughts` is
52
- * gated on `streamThinking` so callers that opted out of streaming thoughts
53
- * don't pay for thought tokens in the response.
108
+ * `includeThoughts` is gated on `streamThinking` so callers that opted out of
109
+ * streaming thoughts don't pay for thought tokens in the response.
54
110
  */
55
111
  function buildThinkingConfig(
56
112
  thinking: Record<string, unknown> | undefined,
113
+ model: string,
57
114
  ): genai.ThinkingConfig | undefined {
58
115
  if (!thinking) return undefined;
116
+ const floor = geminiThinkingFloor(model);
117
+
59
118
  if (thinking.type === "disabled") {
60
119
  return {
61
- thinkingLevel: ThinkingLevel.MINIMAL,
120
+ thinkingLevel: THINKING_LEVEL_BY_NAME[floor],
62
121
  includeThoughts: false,
63
122
  };
64
123
  }
65
124
  if (thinking.type !== "adaptive") return undefined;
66
125
 
67
126
  const result: genai.ThinkingConfig = {};
68
- if (typeof thinking.level === "string") {
69
- const mapped = THINKING_LEVEL_BY_NAME[thinking.level];
70
- if (mapped) result.thinkingLevel = mapped;
127
+ if (
128
+ typeof thinking.level === "string" &&
129
+ thinking.level in THINKING_LEVEL_BY_NAME
130
+ ) {
131
+ const clamped = clampThinkingLevelToFloor(
132
+ thinking.level as ThinkingLevelName,
133
+ floor,
134
+ );
135
+ result.thinkingLevel = THINKING_LEVEL_BY_NAME[clamped];
136
+ } else if (isGeminiProModel(model)) {
137
+ result.thinkingLevel =
138
+ THINKING_LEVEL_BY_NAME[GEMINI_PRO_DEFAULT_THINKING_LEVEL];
71
139
  }
72
140
  if (typeof thinking.streamThinking === "boolean") {
73
141
  result.includeThoughts = thinking.streamThinking;
@@ -223,11 +291,9 @@ export class GeminiProvider implements Provider {
223
291
 
224
292
  async sendMessage(
225
293
  messages: Message[],
226
- tools?: ToolDefinition[],
227
- systemPrompt?: string,
228
294
  options?: SendMessageOptions,
229
295
  ): Promise<ProviderResponse> {
230
- const { config, onEvent, signal } = options ?? {};
296
+ const { tools, systemPrompt, config, onEvent, signal } = options ?? {};
231
297
  const configObj = config as Record<string, unknown> | undefined;
232
298
  const maxTokens = configObj?.max_tokens as number | undefined;
233
299
  const modelOverride = configObj?.model as string | undefined;
@@ -238,6 +304,7 @@ export class GeminiProvider implements Provider {
238
304
  const thinkingConfig = geminiModelSupportsThinking(activeModel)
239
305
  ? buildThinkingConfig(
240
306
  configObj?.thinking as Record<string, unknown> | undefined,
307
+ activeModel,
241
308
  )
242
309
  : undefined;
243
310
 
@@ -296,6 +363,7 @@ export class GeminiProvider implements Provider {
296
363
  let finishReason = "unknown";
297
364
  let promptTokens = 0;
298
365
  let outputTokens = 0;
366
+ let cachedTokens = 0;
299
367
  let responseModel = activeModel;
300
368
 
301
369
  try {
@@ -343,6 +411,11 @@ export class GeminiProvider implements Provider {
343
411
  if (chunk.usageMetadata) {
344
412
  promptTokens = chunk.usageMetadata.promptTokenCount ?? 0;
345
413
  outputTokens = chunk.usageMetadata.candidatesTokenCount ?? 0;
414
+ // Gemini 2.5+/3.x cache a stable request prefix implicitly (on by
415
+ // default). promptTokenCount already includes these cached tokens,
416
+ // so cachedContentTokenCount is the read subset — surface it so the
417
+ // pricing layer applies the discounted cache-read rate.
418
+ cachedTokens = chunk.usageMetadata.cachedContentTokenCount ?? 0;
346
419
  }
347
420
 
348
421
  if (chunk.modelVersion) {
@@ -386,13 +459,18 @@ export class GeminiProvider implements Provider {
386
459
  usageMetadata: {
387
460
  promptTokenCount: promptTokens,
388
461
  candidatesTokenCount: outputTokens,
462
+ cachedContentTokenCount: cachedTokens,
389
463
  },
390
464
  };
391
465
 
392
466
  return {
393
467
  content,
394
468
  model: responseModel,
395
- usage: { inputTokens: promptTokens, outputTokens },
469
+ usage: {
470
+ inputTokens: promptTokens,
471
+ outputTokens,
472
+ ...(cachedTokens > 0 ? { cacheReadInputTokens: cachedTokens } : {}),
473
+ },
396
474
  stopReason: finishReason,
397
475
  rawRequest,
398
476
  rawResponse,
@@ -456,7 +534,7 @@ export class GeminiProvider implements Provider {
456
534
 
457
535
  for (const msg of messages) {
458
536
  const role = msg.role === "assistant" ? "model" : "user";
459
- const { parts, toolResultImageParts } = this.toGeminiParts(
537
+ const { parts, toolResultMediaParts } = this.toGeminiParts(
460
538
  msg.content,
461
539
  toolCallNames,
462
540
  model,
@@ -468,8 +546,8 @@ export class GeminiProvider implements Provider {
468
546
  // Gemini requires that a Content with functionResponse parts must not
469
547
  // contain non-functionResponse parts. Emit tool-result images in a
470
548
  // separate user Content entry.
471
- if (toolResultImageParts.length > 0) {
472
- result.push({ role: "user", parts: toolResultImageParts });
549
+ if (toolResultMediaParts.length > 0) {
550
+ result.push({ role: "user", parts: toolResultMediaParts });
473
551
  }
474
552
  }
475
553
 
@@ -482,9 +560,9 @@ export class GeminiProvider implements Provider {
482
560
  toolCallNames: Map<string, string>,
483
561
  model: string,
484
562
  role: "model" | "user",
485
- ): { parts: genai.Part[]; toolResultImageParts: genai.Part[] } {
563
+ ): { parts: genai.Part[]; toolResultMediaParts: genai.Part[] } {
486
564
  const parts: genai.Part[] = [];
487
- const toolResultImageParts: genai.Part[] = [];
565
+ const toolResultMediaParts: genai.Part[] = [];
488
566
 
489
567
  for (const block of blocks) {
490
568
  switch (block.type) {
@@ -499,14 +577,27 @@ export class GeminiProvider implements Provider {
499
577
  },
500
578
  });
501
579
  break;
502
- case "file":
580
+ case "file": {
503
581
  if (this.supportsGeminiInlineFile(block.source.media_type)) {
504
- parts.push({
505
- inlineData: {
506
- mimeType: block.source.media_type,
507
- data: block.source.data,
508
- },
509
- });
582
+ // Normalize audio MIME onto Gemini's spelling (e.g. audio/mpeg →
583
+ // audio/mp3); PDFs pass through unchanged. Guard the 20 MB inline
584
+ // request limit for audio so an oversize clip degrades to a text
585
+ // note rather than 400ing the whole request.
586
+ const audioMime = normalizeGeminiAudioMime(block.source.media_type);
587
+ const rawBytes = base64ByteLength(block.source.data);
588
+ if (audioMime && rawBytes > GEMINI_MAX_INLINE_AUDIO_BYTES) {
589
+ const approxMb = Math.round(rawBytes / (1024 * 1024));
590
+ parts.push({
591
+ text: `[Audio file too large to send inline: ${block.source.filename} (${block.source.media_type}, ~${approxMb}MB). Gemini's inline request limit is 20MB; this file was omitted. Ask the user for a shorter clip.]`,
592
+ });
593
+ } else {
594
+ parts.push({
595
+ inlineData: {
596
+ mimeType: audioMime ?? block.source.media_type,
597
+ data: block.source.data,
598
+ },
599
+ });
600
+ }
510
601
  } else {
511
602
  const fallback = block.extracted_text?.trim()
512
603
  ? `[Attached file: ${block.source.filename} (${block.source.media_type})]\n${block.extracted_text}`
@@ -514,6 +605,7 @@ export class GeminiProvider implements Provider {
514
605
  parts.push({ text: fallback });
515
606
  }
516
607
  break;
608
+ }
517
609
  case "tool_use":
518
610
  {
519
611
  const functionCallPart: genai.Part = {
@@ -542,16 +634,39 @@ export class GeminiProvider implements Provider {
542
634
  if (extraText.length > 0) {
543
635
  outputText = outputText + "\n" + extraText.join("\n");
544
636
  }
545
- // Collect images separately — Gemini rejects mixing inlineData
546
- // with functionResponse in the same Content entry.
637
+ // Collect images and inline-able audio separately — Gemini rejects
638
+ // mixing inlineData with functionResponse in the same Content entry.
547
639
  for (const cb of block.contentBlocks) {
548
640
  if (cb.type === "image") {
549
- toolResultImageParts.push({
641
+ toolResultMediaParts.push({
550
642
  inlineData: {
551
643
  mimeType: cb.source.media_type,
552
644
  data: cb.source.data,
553
645
  },
554
646
  });
647
+ } else if (cb.type === "file") {
648
+ const audioMime = normalizeGeminiAudioMime(
649
+ cb.source.media_type,
650
+ );
651
+ if (
652
+ audioMime &&
653
+ base64ByteLength(cb.source.data) <=
654
+ GEMINI_MAX_INLINE_AUDIO_BYTES
655
+ ) {
656
+ toolResultMediaParts.push({
657
+ inlineData: { mimeType: audioMime, data: cb.source.data },
658
+ });
659
+ } else if (audioMime) {
660
+ // Oversize audio: note it in the functionResponse output
661
+ // rather than a media part (a text part can't ride the
662
+ // separate media Content, and inline audio would blow
663
+ // Gemini's request-size limit).
664
+ outputText =
665
+ outputText +
666
+ `\n[Audio too large to send inline: ${cb.source.filename}. Ask for a shorter clip.]`;
667
+ }
668
+ // Non-inline-able file sub-blocks (m4a/opus/pdf) are skipped
669
+ // here; the tool's text output already conveys the file.
555
670
  }
556
671
  }
557
672
  }
@@ -577,7 +692,7 @@ export class GeminiProvider implements Provider {
577
692
  this.addGemini3UnsignedToolCallFallback(parts, model);
578
693
  }
579
694
 
580
- return { parts, toolResultImageParts };
695
+ return { parts, toolResultMediaParts };
581
696
  }
582
697
 
583
698
  private addGemini3UnsignedToolCallFallback(
@@ -601,6 +716,9 @@ export class GeminiProvider implements Provider {
601
716
  }
602
717
 
603
718
  private supportsGeminiInlineFile(mimeType: string): boolean {
604
- return mimeType === "application/pdf";
719
+ return (
720
+ mimeType === "application/pdf" ||
721
+ normalizeGeminiAudioMime(mimeType) !== null
722
+ );
605
723
  }
606
724
  }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Shared source of truth for how Gemini ingests inline audio: which MIME types
3
+ * it accepts, how our stored MIME types normalize onto Gemini's spelling, the
4
+ * inline-request size ceiling, and the token cost.
5
+ *
6
+ * Imported by both the Gemini serializer (`client.ts`) and the token estimator
7
+ * (`context/token-estimator.ts`) so the two cannot drift — if they disagreed on
8
+ * which audio is sent inline, the context budgeter would mis-count what
9
+ * actually goes on the wire.
10
+ *
11
+ * Ref: https://ai.google.dev/gemini-api/docs/audio
12
+ * - Inline-accepted audio: wav, mp3, aiff, aac, ogg, flac
13
+ * - Inline request size limit: 20 MB total (prompt + system + inline files)
14
+ * - Audio is billed at ~32 tokens/second
15
+ */
16
+
17
+ /**
18
+ * Audio MIME types Gemini accepts as inline data, in Gemini's own spelling
19
+ * (the values we emit on the wire). Our upload allowlist stores mp3 as
20
+ * `audio/mpeg`; {@link normalizeGeminiAudioMime} maps that onto `audio/mp3`.
21
+ */
22
+ export const GEMINI_INLINE_AUDIO_MIME_TYPES = new Set([
23
+ "audio/wav",
24
+ "audio/mp3",
25
+ "audio/aiff",
26
+ "audio/aac",
27
+ "audio/ogg",
28
+ "audio/flac",
29
+ ]);
30
+
31
+ /**
32
+ * Map a stored attachment MIME type onto Gemini's inline-audio spelling, or
33
+ * `null` when Gemini cannot take it inline.
34
+ *
35
+ * m4a (`audio/x-m4a`, `audio/mp4`) and opus are intentionally unsupported:
36
+ * m4a bytes are an MP4 container, not raw AAC, so we must not relabel them as
37
+ * `audio/aac` — they fall through to a text placeholder instead.
38
+ */
39
+ export function normalizeGeminiAudioMime(mimeType: string): string | null {
40
+ const normalized = mimeType.toLowerCase().split(";")[0]?.trim() ?? "";
41
+ const remapped = normalized === "audio/mpeg" ? "audio/mp3" : normalized;
42
+ return GEMINI_INLINE_AUDIO_MIME_TYPES.has(remapped) ? remapped : null;
43
+ }
44
+
45
+ /** Raw byte length backing a base64 string (4 base64 chars → 3 bytes). */
46
+ export function base64ByteLength(base64Data: string): number {
47
+ return Math.floor((base64Data.length * 3) / 4);
48
+ }
49
+
50
+ /**
51
+ * Max raw bytes of audio we send inline to Gemini. Gemini's total inline
52
+ * request limit is 20 MB and base64 inflates payloads ~33%, so we cap raw
53
+ * audio at ~12 MB (≈16 MB encoded) to leave headroom for the prompt, system
54
+ * instruction, and conversation history. Larger files degrade to a text
55
+ * placeholder (the Gemini Files API is a future enhancement).
56
+ */
57
+ export const GEMINI_MAX_INLINE_AUDIO_BYTES = 12 * 1024 * 1024;
58
+
59
+ /**
60
+ * Gemini bills audio at ~32 tokens/second, NOT by payload size. We don't have
61
+ * the decoded duration at estimate time, so approximate it from byte size
62
+ * assuming ~128 kbps (~16 KB/s) typical compressed audio. This keeps the
63
+ * context budgeter within range instead of the ~170x over-count that treating
64
+ * the base64 payload as text produces. (Uncompressed WAV is under-counted, but
65
+ * the inline size guard caps it at {@link GEMINI_MAX_INLINE_AUDIO_BYTES}.)
66
+ */
67
+ const GEMINI_AUDIO_TOKENS_PER_SECOND = 32;
68
+ const APPROX_AUDIO_BYTES_PER_SECOND = 16_000;
69
+
70
+ export function estimateGeminiAudioTokens(base64Data: string): number {
71
+ const approxSeconds =
72
+ base64ByteLength(base64Data) / APPROX_AUDIO_BYTES_PER_SECOND;
73
+ return Math.ceil(approxSeconds * GEMINI_AUDIO_TOKENS_PER_SECOND);
74
+ }
@@ -74,8 +74,6 @@ async function runStream(
74
74
  }> {
75
75
  const response = await provider.sendMessage(
76
76
  [{ role: "user", content: [{ type: "text", text: "hi" }] }],
77
- undefined,
78
- undefined,
79
77
  {
80
78
  onEvent: (e) => {
81
79
  events.push(e as { type: string; thinking?: string; text?: string });
@@ -11,7 +11,6 @@ import type {
11
11
  Provider,
12
12
  ProviderResponse,
13
13
  SendMessageOptions,
14
- ToolDefinition,
15
14
  } from "../types.js";
16
15
  import {
17
16
  ContextOverflowError,
@@ -256,11 +255,9 @@ export class OpenAIChatCompletionsProvider implements Provider {
256
255
 
257
256
  async sendMessage(
258
257
  messages: Message[],
259
- tools?: ToolDefinition[],
260
- systemPrompt?: string,
261
258
  options?: SendMessageOptions,
262
259
  ): Promise<ProviderResponse> {
263
- const { config, onEvent, signal } = options ?? {};
260
+ const { tools, systemPrompt, config, onEvent, signal } = options ?? {};
264
261
  const configObj = config as Record<string, unknown> | undefined;
265
262
  const maxTokens = configObj?.max_tokens as number | undefined;
266
263
  const modelOverride = configObj?.model as string | undefined;
@@ -12,7 +12,6 @@ import type {
12
12
  Provider,
13
13
  ProviderResponse,
14
14
  SendMessageOptions,
15
- ToolDefinition,
16
15
  } from "../types.js";
17
16
  import { ContextOverflowError } from "../types.js";
18
17
  import { detectOpenAICompatibleContextOverflow } from "./chat-completions-provider.js";
@@ -160,11 +159,9 @@ export class OpenAIResponsesProvider implements Provider {
160
159
 
161
160
  async sendMessage(
162
161
  messages: Message[],
163
- tools?: ToolDefinition[],
164
- systemPrompt?: string,
165
162
  options?: SendMessageOptions,
166
163
  ): Promise<ProviderResponse> {
167
- const { config, onEvent, signal } = options ?? {};
164
+ const { tools, systemPrompt, config, onEvent, signal } = options ?? {};
168
165
  const configObj = config as Record<string, unknown> | undefined;
169
166
  const maxTokens = configObj?.max_tokens as number | undefined;
170
167
  const modelOverride = configObj?.model as string | undefined;
@@ -10,7 +10,6 @@ import type {
10
10
  Message,
11
11
  ProviderResponse,
12
12
  SendMessageOptions,
13
- ToolDefinition,
14
13
  } from "../types.js";
15
14
  import { ContextOverflowError, isContextOverflowError } from "../types.js";
16
15
 
@@ -142,8 +141,6 @@ export class OpenRouterProvider extends OpenAIChatCompletionsProvider {
142
141
 
143
142
  override async sendMessage(
144
143
  messages: Message[],
145
- tools?: ToolDefinition[],
146
- systemPrompt?: string,
147
144
  options?: SendMessageOptions,
148
145
  ): Promise<ProviderResponse> {
149
146
  const effectiveModel = this.resolveEffectiveModel(options);
@@ -151,12 +148,10 @@ export class OpenRouterProvider extends OpenAIChatCompletionsProvider {
151
148
  if (isAnthropicModel(effectiveModel)) {
152
149
  return await this.getAnthropicInner().sendMessage(
153
150
  messages,
154
- tools,
155
- systemPrompt,
156
151
  withOpenRouterBodyExtras(options),
157
152
  );
158
153
  }
159
- return await super.sendMessage(messages, tools, systemPrompt, options);
154
+ return await super.sendMessage(messages, options);
160
155
  } catch (error) {
161
156
  // Re-tag delegate-thrown ContextOverflowError so the outer provider name
162
157
  // matches the configured provider ("openrouter"). This keeps downstream
@@ -22,7 +22,6 @@ import type {
22
22
  Provider,
23
23
  ProviderResponse,
24
24
  SendMessageOptions,
25
- ToolDefinition,
26
25
  ToolUseContent,
27
26
  } from "./types.js";
28
27
 
@@ -56,16 +55,14 @@ export class CallSiteConfiguredProvider implements Provider {
56
55
 
57
56
  sendMessage(
58
57
  messages: Message[],
59
- tools?: ToolDefinition[],
60
- systemPrompt?: string,
61
58
  options?: SendMessageOptions,
62
59
  ): Promise<ProviderResponse> {
63
60
  const config = options?.config;
64
61
  if (config?.callSite) {
65
- return this.inner.sendMessage(messages, tools, systemPrompt, options);
62
+ return this.inner.sendMessage(messages, options);
66
63
  }
67
64
 
68
- return this.inner.sendMessage(messages, tools, systemPrompt, {
65
+ return this.inner.sendMessage(messages, {
69
66
  ...options,
70
67
  config: {
71
68
  ...config,
@@ -141,7 +138,10 @@ export async function resolveConfiguredProvider(
141
138
  resolved.model,
142
139
  );
143
140
  if (incompatMsg) {
144
- log.warn({ callSite, inferenceProvider, model: resolved.model }, incompatMsg);
141
+ log.warn(
142
+ { callSite, inferenceProvider, model: resolved.model },
143
+ incompatMsg,
144
+ );
145
145
  }
146
146
  }
147
147
  } catch {
@@ -6,7 +6,6 @@ import type {
6
6
  Provider,
7
7
  ProviderResponse,
8
8
  SendMessageOptions,
9
- ToolDefinition,
10
9
  } from "./types.js";
11
10
 
12
11
  const log = getLogger("rate-limit");
@@ -36,8 +35,6 @@ export class RateLimitProvider implements Provider {
36
35
 
37
36
  async sendMessage(
38
37
  messages: Message[],
39
- tools?: ToolDefinition[],
40
- systemPrompt?: string,
41
38
  options?: SendMessageOptions,
42
39
  ): Promise<ProviderResponse> {
43
40
  this.enforceRequestRate();
@@ -46,12 +43,7 @@ export class RateLimitProvider implements Provider {
46
43
  // calls from bypassing the rate limit during the async gap.
47
44
  this.recordRequest();
48
45
 
49
- const response = await this.inner.sendMessage(
50
- messages,
51
- tools,
52
- systemPrompt,
53
- options,
54
- );
46
+ const response = await this.inner.sendMessage(messages, options);
55
47
 
56
48
  return response;
57
49
  }
@@ -23,7 +23,6 @@ import {
23
23
  type Provider,
24
24
  type ProviderResponse,
25
25
  type SendMessageOptions,
26
- type ToolDefinition,
27
26
  } from "./types.js";
28
27
 
29
28
  const log = getLogger("retry");
@@ -525,8 +524,6 @@ export class RetryProvider implements Provider {
525
524
 
526
525
  async sendMessage(
527
526
  messages: Message[],
528
- tools?: ToolDefinition[],
529
- systemPrompt?: string,
530
527
  options?: SendMessageOptions,
531
528
  ): Promise<ProviderResponse> {
532
529
  let lastError: unknown;
@@ -541,8 +538,6 @@ export class RetryProvider implements Provider {
541
538
  try {
542
539
  const result = await this.inner.sendMessage(
543
540
  messages,
544
- tools,
545
- systemPrompt,
546
541
  normalizedOptions,
547
542
  );
548
543
  return result;
@@ -207,10 +207,21 @@ export interface SendMessageConfig {
207
207
  effort?: "none" | "low" | "medium" | "high" | "xhigh" | "max";
208
208
  speed?: "standard" | "fast";
209
209
  verbosity?: "low" | "medium" | "high";
210
+ /**
211
+ * When true, the most recent user message's content varies across
212
+ * otherwise-identical turns (e.g. a per-turn memory block was injected into
213
+ * it). The provider places the primary long-TTL cache breakpoint on the most
214
+ * recent *stable* user message instead of the volatile latest one, so the
215
+ * cached prefix stays reusable across turns. Default false — existing
216
+ * behavior.
217
+ */
218
+ mutableLatestUserMessage?: boolean;
210
219
  [key: string]: unknown;
211
220
  }
212
221
 
213
222
  export interface SendMessageOptions {
223
+ tools?: ToolDefinition[];
224
+ systemPrompt?: string;
214
225
  config?: SendMessageConfig;
215
226
  onEvent?: (event: ProviderEvent) => void;
216
227
  signal?: AbortSignal;
@@ -229,8 +240,6 @@ export interface Provider {
229
240
  tokenEstimationProvider?: string;
230
241
  sendMessage(
231
242
  messages: Message[],
232
- tools?: ToolDefinition[],
233
- systemPrompt?: string,
234
243
  options?: SendMessageOptions,
235
244
  ): Promise<ProviderResponse>;
236
245
  }
@@ -11,7 +11,6 @@ import type {
11
11
  Provider,
12
12
  ProviderResponse,
13
13
  SendMessageOptions,
14
- ToolDefinition,
15
14
  } from "./types.js";
16
15
 
17
16
  const log = getLogger("provider-usage-tracking");
@@ -27,16 +26,9 @@ export class UsageTrackingProvider implements Provider {
27
26
 
28
27
  async sendMessage(
29
28
  messages: Message[],
30
- tools?: ToolDefinition[],
31
- systemPrompt?: string,
32
29
  options?: SendMessageOptions,
33
30
  ): Promise<ProviderResponse> {
34
- const response = await this.inner.sendMessage(
35
- messages,
36
- tools,
37
- systemPrompt,
38
- options,
39
- );
31
+ const response = await this.inner.sendMessage(messages, options);
40
32
  this.recordUsage(response, options);
41
33
  return response;
42
34
  }