@vellumai/assistant 0.6.4 → 0.6.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 (1008) hide show
  1. package/.prettierignore +5 -0
  2. package/AGENTS.md +9 -1
  3. package/ARCHITECTURE.md +43 -49
  4. package/Dockerfile +17 -3
  5. package/README.md +3 -4
  6. package/__tests__/permissions/gateway-threshold-reader.test.ts +283 -0
  7. package/bun.lock +8 -3
  8. package/docs/architecture/integrations.md +33 -59
  9. package/docs/architecture/memory.md +25 -30
  10. package/docs/architecture/security.md +19 -18
  11. package/docs/browser-use-architecture-phase2.md +63 -20
  12. package/docs/error-handling.md +111 -0
  13. package/docs/plugins.md +761 -0
  14. package/docs/skills.md +10 -10
  15. package/docs/stt-provider-onboarding.md +2 -1
  16. package/examples/plugins/echo/README.md +132 -0
  17. package/examples/plugins/echo/package.json +17 -0
  18. package/examples/plugins/echo/register.ts +187 -0
  19. package/knip.json +9 -2
  20. package/node_modules/@vellumai/ces-contracts/package.json +2 -1
  21. package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
  22. package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
  23. package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
  24. package/node_modules/@vellumai/credential-storage/package.json +2 -2
  25. package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
  26. package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
  27. package/node_modules/@vellumai/egress-proxy/package.json +2 -2
  28. package/node_modules/@vellumai/egress-proxy/src/types.ts +19 -0
  29. package/openapi.yaml +334 -78
  30. package/package.json +6 -3
  31. package/scripts/generate-openapi.ts +50 -11
  32. package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
  33. package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
  34. package/src/__tests__/agent-loop.test.ts +112 -1
  35. package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
  36. package/src/__tests__/anthropic-provider.test.ts +171 -2
  37. package/src/__tests__/app-compiler.test.ts +57 -0
  38. package/src/__tests__/approval-cascade.test.ts +36 -10
  39. package/src/__tests__/approval-routes-http.test.ts +134 -10
  40. package/src/__tests__/assistant-attachments.test.ts +44 -0
  41. package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
  42. package/src/__tests__/auto-analysis-end-to-end.test.ts +1 -0
  43. package/src/__tests__/avatar-generator.test.ts +4 -2
  44. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  45. package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
  46. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
  47. package/src/__tests__/browser-skill-endstate.test.ts +51 -182
  48. package/src/__tests__/btw-routes.test.ts +47 -1
  49. package/src/__tests__/bundled-asset.test.ts +6 -6
  50. package/src/__tests__/call-controller.test.ts +1 -2
  51. package/src/__tests__/call-site-routing-provider.test.ts +214 -0
  52. package/src/__tests__/catalog-cache.test.ts +96 -4
  53. package/src/__tests__/channel-approval-routes.test.ts +4 -4
  54. package/src/__tests__/channel-reply-delivery.test.ts +300 -2
  55. package/src/__tests__/checker.test.ts +870 -655
  56. package/src/__tests__/circuit-breaker-pipeline.test.ts +406 -0
  57. package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
  58. package/src/__tests__/compaction-events.test.ts +501 -0
  59. package/src/__tests__/compaction-pipeline.test.ts +210 -0
  60. package/src/__tests__/compaction-strip-metadata-clear.test.ts +181 -0
  61. package/src/__tests__/compaction-timeout-recovery.test.ts +262 -0
  62. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  63. package/src/__tests__/config-analysis.test.ts +11 -28
  64. package/src/__tests__/config-loader-backfill.test.ts +174 -0
  65. package/src/__tests__/config-loader-corrupt.test.ts +183 -0
  66. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
  67. package/src/__tests__/config-model-image-provider.test.ts +110 -0
  68. package/src/__tests__/config-schema-cmd.test.ts +11 -5
  69. package/src/__tests__/config-schema.test.ts +440 -114
  70. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +0 -4
  71. package/src/__tests__/config-watcher.test.ts +2 -2
  72. package/src/__tests__/contact-store-user-file.test.ts +72 -73
  73. package/src/__tests__/contacts-tools.test.ts +26 -0
  74. package/src/__tests__/contacts-write.test.ts +4 -4
  75. package/src/__tests__/context-overflow-policy.test.ts +7 -7
  76. package/src/__tests__/context-token-estimator.test.ts +191 -1
  77. package/src/__tests__/context-window-manager.test.ts +883 -4
  78. package/src/__tests__/conversation-abort-tool-results.test.ts +32 -15
  79. package/src/__tests__/conversation-agent-loop-overflow.test.ts +86 -46
  80. package/src/__tests__/conversation-agent-loop.test.ts +435 -216
  81. package/src/__tests__/conversation-attachments.test.ts +1 -1
  82. package/src/__tests__/conversation-confirmation-signals.test.ts +36 -10
  83. package/src/__tests__/conversation-error.test.ts +37 -6
  84. package/src/__tests__/conversation-history-web-search.test.ts +7 -0
  85. package/src/__tests__/conversation-init.benchmark.test.ts +34 -12
  86. package/src/__tests__/conversation-lifecycle.test.ts +336 -0
  87. package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
  88. package/src/__tests__/conversation-pairing.test.ts +174 -10
  89. package/src/__tests__/conversation-pre-run-repair.test.ts +32 -15
  90. package/src/__tests__/conversation-process-callsite.test.ts +309 -0
  91. package/src/__tests__/conversation-provider-retry-repair.test.ts +44 -21
  92. package/src/__tests__/conversation-queue.test.ts +68 -38
  93. package/src/__tests__/conversation-routes-disk-view.test.ts +36 -7
  94. package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
  95. package/src/__tests__/conversation-runtime-assembly.test.ts +2877 -152
  96. package/src/__tests__/conversation-runtime-workspace.test.ts +35 -50
  97. package/src/__tests__/conversation-seed-composer.test.ts +2 -2
  98. package/src/__tests__/conversation-skill-tools.test.ts +12 -146
  99. package/src/__tests__/conversation-slash-queue.test.ts +39 -19
  100. package/src/__tests__/conversation-slash-unknown.test.ts +53 -16
  101. package/src/__tests__/conversation-speed-override.test.ts +36 -12
  102. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
  103. package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
  104. package/src/__tests__/conversation-title-service.test.ts +118 -2
  105. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +41 -2
  106. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
  107. package/src/__tests__/conversation-unread-route.test.ts +2 -2
  108. package/src/__tests__/conversation-usage.test.ts +4 -2
  109. package/src/__tests__/conversation-workspace-cache-state.test.ts +33 -9
  110. package/src/__tests__/conversation-workspace-injection.test.ts +46 -15
  111. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +46 -15
  112. package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
  113. package/src/__tests__/credential-health-service.test.ts +78 -9
  114. package/src/__tests__/credential-security-invariants.test.ts +5 -2
  115. package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
  116. package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
  117. package/src/__tests__/credential-vault-unit.test.ts +135 -19
  118. package/src/__tests__/credentials-cli.test.ts +1 -9
  119. package/src/__tests__/cross-provider-web-search.test.ts +84 -0
  120. package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
  121. package/src/__tests__/db-schedule-syntax-migration.test.ts +1 -0
  122. package/src/__tests__/delete-propagation.test.ts +437 -0
  123. package/src/__tests__/dm-backfill.test.ts +417 -0
  124. package/src/__tests__/dm-persistence.test.ts +227 -0
  125. package/src/__tests__/edit-propagation.test.ts +280 -0
  126. package/src/__tests__/empty-response-pipeline.test.ts +305 -0
  127. package/src/__tests__/ephemeral-permissions.test.ts +93 -3
  128. package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
  129. package/src/__tests__/estimator-calibration.test.ts +213 -0
  130. package/src/__tests__/extension-id-sync-guard.test.ts +29 -10
  131. package/src/__tests__/file-write-tool.test.ts +151 -1
  132. package/src/__tests__/filing-service.test.ts +255 -0
  133. package/src/__tests__/first-greeting.test.ts +247 -5
  134. package/src/__tests__/gemini-provider.test.ts +0 -3
  135. package/src/__tests__/guardian-grant-minting.test.ts +8 -0
  136. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  137. package/src/__tests__/headless-browser-mode.test.ts +57 -0
  138. package/src/__tests__/heartbeat-service.test.ts +96 -15
  139. package/src/__tests__/history-repair-pipeline.test.ts +399 -0
  140. package/src/__tests__/host-browser-e2e-cloud.test.ts +307 -0
  141. package/src/__tests__/host-browser-e2e-self-hosted.test.ts +3 -3
  142. package/src/__tests__/host-proxy-interface.test.ts +36 -2
  143. package/src/__tests__/host-shell-tool.test.ts +124 -18
  144. package/src/__tests__/http-user-message-parity.test.ts +29 -1
  145. package/src/__tests__/image-credentials.test.ts +137 -0
  146. package/src/__tests__/image-service-dispatcher.test.ts +186 -0
  147. package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
  148. package/src/__tests__/injector-chain.test.ts +526 -0
  149. package/src/__tests__/intent-routing.test.ts +1 -66
  150. package/src/__tests__/llm-call-pipeline.test.ts +285 -0
  151. package/src/__tests__/llm-catalog-parity.test.ts +174 -0
  152. package/src/__tests__/llm-context-normalization.test.ts +121 -0
  153. package/src/__tests__/llm-resolver.test.ts +214 -0
  154. package/src/__tests__/llm-schema.test.ts +223 -0
  155. package/src/__tests__/managed-proxy-context.test.ts +6 -2
  156. package/src/__tests__/media-generate-image.test.ts +119 -13
  157. package/src/__tests__/memory-retrieval-pipeline.test.ts +401 -0
  158. package/src/__tests__/memory-upsert-concurrency.test.ts +1 -0
  159. package/src/__tests__/messaging-skill-split.test.ts +3 -34
  160. package/src/__tests__/migration-import-from-url.test.ts +621 -0
  161. package/src/__tests__/model-intents.test.ts +11 -83
  162. package/src/__tests__/notification-broadcaster.test.ts +3 -3
  163. package/src/__tests__/notification-decision-fallback.test.ts +0 -10
  164. package/src/__tests__/notification-decision-identity.test.ts +0 -9
  165. package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
  166. package/src/__tests__/notification-decision-strategy.test.ts +0 -11
  167. package/src/__tests__/notification-schedule-notify-dedup.test.ts +108 -0
  168. package/src/__tests__/oauth-apps-routes.test.ts +1 -1
  169. package/src/__tests__/oauth-cli.test.ts +14 -12
  170. package/src/__tests__/oauth-connect-orchestrator.test.ts +4 -13
  171. package/src/__tests__/oauth-provider-serializer.test.ts +6 -4
  172. package/src/__tests__/oauth-provider-visibility.test.ts +3 -5
  173. package/src/__tests__/oauth-providers-routes.test.ts +3 -2
  174. package/src/__tests__/oauth-store.test.ts +46 -78
  175. package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
  176. package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
  177. package/src/__tests__/onboarding-template-contract.test.ts +16 -64
  178. package/src/__tests__/openai-image-service.test.ts +368 -0
  179. package/src/__tests__/openai-provider.test.ts +7 -0
  180. package/src/__tests__/openai-responses-provider.test.ts +396 -0
  181. package/src/__tests__/openrouter-provider-only.test.ts +135 -0
  182. package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
  183. package/src/__tests__/overflow-reduce-pipeline.test.ts +676 -0
  184. package/src/__tests__/permission-checker-host-gate.test.ts +1 -25
  185. package/src/__tests__/permission-mode.test.ts +16 -0
  186. package/src/__tests__/permission-types.test.ts +0 -1
  187. package/src/__tests__/persist-onboarding-artifacts.test.ts +266 -0
  188. package/src/__tests__/persistence-pipeline.test.ts +377 -0
  189. package/src/__tests__/persona-resolver.test.ts +13 -13
  190. package/src/__tests__/pipeline-runner.test.ts +565 -0
  191. package/src/__tests__/pkb-autoinject.test.ts +37 -1
  192. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
  193. package/src/__tests__/platform.test.ts +5 -2
  194. package/src/__tests__/plugin-bootstrap.test.ts +483 -0
  195. package/src/__tests__/plugin-registry.test.ts +273 -0
  196. package/src/__tests__/plugin-route-contribution.test.ts +288 -0
  197. package/src/__tests__/plugin-skill-contribution.test.ts +367 -0
  198. package/src/__tests__/plugin-tool-contribution.test.ts +286 -0
  199. package/src/__tests__/plugin-types.test.ts +320 -0
  200. package/src/__tests__/pricing.test.ts +93 -14
  201. package/src/__tests__/profiler-routes.test.ts +1 -1
  202. package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
  203. package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
  204. package/src/__tests__/provider-error-scenarios.test.ts +135 -6
  205. package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
  206. package/src/__tests__/provider-registry-ollama.test.ts +1 -2
  207. package/src/__tests__/proxy-approval-callback.test.ts +69 -9
  208. package/src/__tests__/reaction-persistence.test.ts +561 -0
  209. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
  210. package/src/__tests__/registry.test.ts +0 -2
  211. package/src/__tests__/relay-server.test.ts +1 -1
  212. package/src/__tests__/require-fresh-approval.test.ts +1 -1
  213. package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
  214. package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
  215. package/src/__tests__/risk-classifier-parity.test.ts +230 -0
  216. package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
  217. package/src/__tests__/schedule-routes.test.ts +131 -1
  218. package/src/__tests__/scheduler-recurrence.test.ts +14 -70
  219. package/src/__tests__/scheduler-reuse-conversation.test.ts +10 -50
  220. package/src/__tests__/secret-detection-handler.test.ts +0 -10
  221. package/src/__tests__/secret-ingress-http.test.ts +28 -0
  222. package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
  223. package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
  224. package/src/__tests__/secret-scanner-executor.test.ts +1 -1
  225. package/src/__tests__/send-endpoint-busy.test.ts +29 -1
  226. package/src/__tests__/server-history-render.test.ts +31 -0
  227. package/src/__tests__/shell-identity.test.ts +0 -134
  228. package/src/__tests__/shell-parser-property.test.ts +13 -13
  229. package/src/__tests__/skill-cache-store.test.ts +182 -0
  230. package/src/__tests__/skills.test.ts +19 -33
  231. package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
  232. package/src/__tests__/slack-skill.test.ts +3 -8
  233. package/src/__tests__/starter-bundle.test.ts +35 -0
  234. package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
  235. package/src/__tests__/suggestion-routes.test.ts +259 -3
  236. package/src/__tests__/system-prompt.test.ts +22 -35
  237. package/src/__tests__/task-memory-cleanup.test.ts +1 -0
  238. package/src/__tests__/task-runner.test.ts +3 -1
  239. package/src/__tests__/task-scheduler.test.ts +3 -15
  240. package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
  241. package/src/__tests__/terminal-tools.test.ts +8 -0
  242. package/src/__tests__/test-preload.ts +11 -0
  243. package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
  244. package/src/__tests__/thread-backfill.test.ts +941 -0
  245. package/src/__tests__/title-generate-pipeline.test.ts +224 -0
  246. package/src/__tests__/token-estimate-pipeline.test.ts +431 -0
  247. package/src/__tests__/tool-error-pipeline.test.ts +244 -0
  248. package/src/__tests__/tool-execute-pipeline.test.ts +431 -0
  249. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -8
  250. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
  251. package/src/__tests__/tool-executor-shell-integration.test.ts +7 -10
  252. package/src/__tests__/tool-executor.test.ts +201 -94
  253. package/src/__tests__/tool-result-truncate-pipeline.test.ts +356 -0
  254. package/src/__tests__/tool-result-truncation.test.ts +0 -110
  255. package/src/__tests__/trust-store.test.ts +442 -109
  256. package/src/__tests__/update-bulletin-job.test.ts +389 -0
  257. package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
  258. package/src/__tests__/user-plugin-loader.test.ts +191 -0
  259. package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
  260. package/src/__tests__/voice-session-bridge.test.ts +39 -0
  261. package/src/__tests__/volume-security-guard.test.ts +3 -2
  262. package/src/__tests__/web-search-history.test.ts +337 -0
  263. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
  264. package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
  265. package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
  266. package/src/__tests__/workspace-migration-046-seed-conversation-starters-callsite.test.ts +185 -0
  267. package/src/__tests__/workspace-migration-049-release-notes-default-sonnet.test.ts +100 -0
  268. package/src/__tests__/workspace-migration-050-seed-main-agent-opus-callsite.test.ts +171 -0
  269. package/src/__tests__/workspace-migration-051-seed-conversation-summarization-callsite.test.ts +252 -0
  270. package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
  271. package/src/__tests__/workspace-migration-remove-hooks.test.ts +99 -0
  272. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
  273. package/src/__tests__/workspace-policy.test.ts +22 -16
  274. package/src/acp/client-handler.ts +1 -2
  275. package/src/agent/loop.ts +545 -115
  276. package/src/approvals/__tests__/guardian-feed-event.test.ts +304 -0
  277. package/src/approvals/guardian-request-resolvers.ts +80 -0
  278. package/src/avatar/resvg-lazy.test.ts +136 -0
  279. package/src/avatar/resvg-lazy.ts +82 -9
  280. package/src/avatar/traits-png-sync.ts +21 -1
  281. package/src/backup/__tests__/backup-worker.test.ts +2 -13
  282. package/src/backup/backup-worker.ts +3 -15
  283. package/src/browser/__tests__/operations.test.ts +163 -0
  284. package/src/browser/identifiers.ts +51 -0
  285. package/src/browser/operations.ts +660 -0
  286. package/src/browser/types.ts +81 -0
  287. package/src/bundler/app-compiler.ts +84 -1
  288. package/src/calls/call-state.ts +2 -2
  289. package/src/calls/guardian-question-copy.ts +2 -2
  290. package/src/calls/telephony-stt-routing.ts +1 -1
  291. package/src/calls/voice-session-bridge.ts +1 -0
  292. package/src/channels/__tests__/types.test.ts +3 -3
  293. package/src/channels/types.ts +6 -4
  294. package/src/cli/AGENTS.md +1 -1
  295. package/src/cli/__tests__/notifications.test.ts +87 -211
  296. package/src/cli/commands/__tests__/attachment.test.ts +438 -0
  297. package/src/cli/commands/__tests__/backup.test.ts +1 -1
  298. package/src/cli/commands/__tests__/browser.test.ts +554 -0
  299. package/src/cli/commands/__tests__/cache.test.ts +623 -0
  300. package/src/cli/commands/__tests__/email-list.test.ts +6 -0
  301. package/src/cli/commands/__tests__/email-send.test.ts +93 -1
  302. package/src/cli/commands/__tests__/image-generation.test.ts +886 -0
  303. package/src/cli/commands/__tests__/inference-send.test.ts +463 -0
  304. package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
  305. package/src/cli/commands/__tests__/task.test.ts +913 -0
  306. package/src/cli/commands/__tests__/tts-synthesize.test.ts +606 -0
  307. package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
  308. package/src/cli/commands/__tests__/ui.test.ts +1215 -0
  309. package/src/cli/commands/__tests__/watchers.test.ts +716 -0
  310. package/src/cli/commands/attachment.ts +182 -0
  311. package/src/cli/commands/backup.ts +2 -2
  312. package/src/cli/commands/browser.ts +350 -0
  313. package/src/cli/commands/cache.ts +341 -0
  314. package/src/cli/commands/clients.ts +138 -0
  315. package/src/cli/commands/completions.ts +2 -12
  316. package/src/cli/commands/config.ts +6 -6
  317. package/src/cli/commands/conversations-import.ts +347 -0
  318. package/src/cli/commands/conversations.ts +69 -8
  319. package/src/cli/commands/email.ts +234 -194
  320. package/src/cli/commands/image-generation.ts +299 -0
  321. package/src/cli/commands/inference.ts +200 -0
  322. package/src/cli/commands/memory.ts +127 -17
  323. package/src/cli/commands/notifications.ts +68 -103
  324. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +1 -1
  325. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +1 -1
  326. package/src/cli/commands/oauth/connect.ts +2 -2
  327. package/src/cli/commands/oauth/providers.ts +176 -8
  328. package/src/cli/commands/oauth/status.ts +46 -36
  329. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
  330. package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
  331. package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
  332. package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
  333. package/src/cli/commands/skills.ts +3 -4
  334. package/src/cli/commands/stt.ts +339 -0
  335. package/src/cli/commands/task.ts +795 -0
  336. package/src/cli/commands/trust.ts +50 -19
  337. package/src/cli/commands/tts.ts +273 -0
  338. package/src/cli/commands/ui.ts +670 -0
  339. package/src/cli/commands/watchers.ts +509 -0
  340. package/src/cli/lib/daemon-credential-client.ts +0 -19
  341. package/src/cli/program.ts +39 -24
  342. package/src/cli.ts +0 -37
  343. package/src/config/__tests__/backup-schema.test.ts +7 -2
  344. package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
  345. package/src/config/bundled-skills/app-builder/references/WIDGETS.md +10 -10
  346. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +66 -87
  347. package/src/config/bundled-skills/contacts/tools/contact-search.ts +28 -51
  348. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +22 -40
  349. package/src/config/bundled-skills/image-studio/SKILL.md +2 -1
  350. package/src/config/bundled-skills/image-studio/TOOLS.json +2 -1
  351. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +23 -39
  352. package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
  353. package/src/config/bundled-skills/messaging/SKILL.md +5 -5
  354. package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
  355. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +207 -0
  356. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +20 -1
  357. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
  358. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
  359. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +69 -12
  360. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
  361. package/src/config/bundled-skills/schedule/SKILL.md +8 -3
  362. package/src/config/bundled-skills/schedule/TOOLS.json +15 -7
  363. package/src/config/bundled-skills/schedule/references/SCRIPT_MODE_PATTERNS.md +59 -0
  364. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  365. package/src/config/bundled-tool-registry.ts +0 -190
  366. package/src/config/env.ts +7 -2
  367. package/src/config/feature-flag-registry.json +42 -10
  368. package/src/config/llm-resolver.ts +128 -0
  369. package/src/config/loader.ts +194 -10
  370. package/src/config/raw-config-utils.ts +30 -2
  371. package/src/config/sanitize-for-transfer.ts +35 -0
  372. package/src/config/schema.ts +49 -41
  373. package/src/config/schemas/analysis.ts +3 -22
  374. package/src/config/schemas/backup.ts +1 -1
  375. package/src/config/schemas/calls.ts +0 -4
  376. package/src/config/schemas/conversations.ts +16 -0
  377. package/src/config/schemas/filing.ts +2 -7
  378. package/src/config/schemas/heartbeat.ts +0 -5
  379. package/src/config/schemas/inference.ts +3 -23
  380. package/src/config/schemas/llm.ts +317 -0
  381. package/src/config/schemas/memory-processing.ts +1 -9
  382. package/src/config/schemas/notifications.ts +4 -11
  383. package/src/config/schemas/platform.ts +3 -9
  384. package/src/config/schemas/security.ts +33 -0
  385. package/src/config/schemas/services.ts +9 -4
  386. package/src/config/schemas/stt.ts +1 -0
  387. package/src/config/schemas/tts.ts +64 -0
  388. package/src/config/schemas/updates.ts +1 -1
  389. package/src/config/schemas/workspace-git.ts +3 -40
  390. package/src/config/skill-state.ts +6 -2
  391. package/src/config/skills.ts +96 -7
  392. package/src/context/__tests__/compact-prompt.test.ts +63 -0
  393. package/src/context/__tests__/microcompact.test.ts +805 -0
  394. package/src/context/estimator-calibration.ts +136 -0
  395. package/src/context/microcompact.ts +443 -0
  396. package/src/context/prompts/compact.md +26 -0
  397. package/src/context/token-estimator.ts +61 -3
  398. package/src/context/tool-result-truncation.ts +3 -63
  399. package/src/context/window-manager.ts +417 -39
  400. package/src/credential-execution/approval-bridge.ts +0 -1
  401. package/src/credential-execution/executable-discovery.ts +19 -8
  402. package/src/credential-execution/process-manager.test.ts +109 -0
  403. package/src/credential-execution/process-manager.ts +65 -2
  404. package/src/credential-health/credential-health-service.ts +19 -6
  405. package/src/daemon/__tests__/conversation-feed-event.test.ts +317 -0
  406. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +4 -12
  407. package/src/daemon/__tests__/conversation-tool-setup.test.ts +14 -15
  408. package/src/daemon/approval-generators.ts +29 -4
  409. package/src/daemon/assistant-attachments.ts +24 -13
  410. package/src/daemon/classifier.ts +2 -2
  411. package/src/daemon/config-watcher.ts +0 -3
  412. package/src/daemon/context-overflow-policy.ts +4 -13
  413. package/src/daemon/context-overflow-reducer.ts +4 -1
  414. package/src/daemon/conversation-agent-loop-handlers.ts +162 -34
  415. package/src/daemon/conversation-agent-loop.ts +1282 -599
  416. package/src/daemon/conversation-attachments.ts +2 -6
  417. package/src/daemon/conversation-error.ts +36 -1
  418. package/src/daemon/conversation-history.ts +10 -19
  419. package/src/daemon/conversation-lifecycle.ts +59 -17
  420. package/src/daemon/conversation-messaging.ts +73 -4
  421. package/src/daemon/conversation-notifiers.ts +2 -110
  422. package/src/daemon/conversation-process.ts +24 -11
  423. package/src/daemon/conversation-queue-manager.ts +3 -0
  424. package/src/daemon/conversation-runtime-assembly.ts +1063 -211
  425. package/src/daemon/conversation-slash.ts +2 -2
  426. package/src/daemon/conversation-surfaces.ts +389 -1
  427. package/src/daemon/conversation-tool-setup.ts +51 -9
  428. package/src/daemon/conversation-usage.ts +1 -1
  429. package/src/daemon/conversation.ts +197 -64
  430. package/src/daemon/external-plugins-bootstrap.ts +478 -0
  431. package/src/daemon/external-skills-bootstrap.ts +41 -0
  432. package/src/daemon/first-greeting.ts +191 -14
  433. package/src/daemon/guardian-action-generators.ts +34 -14
  434. package/src/daemon/handlers/config-model.test.ts +86 -0
  435. package/src/daemon/handlers/config-model.ts +65 -12
  436. package/src/daemon/handlers/conversations.ts +9 -2
  437. package/src/daemon/handlers/shared.ts +39 -11
  438. package/src/daemon/handlers/skills.ts +7 -3
  439. package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
  440. package/src/daemon/lifecycle.ts +109 -82
  441. package/src/daemon/message-types/computer-use.ts +2 -34
  442. package/src/daemon/message-types/conversations.ts +63 -0
  443. package/src/daemon/message-types/messages.ts +21 -1
  444. package/src/daemon/message-types/trust.ts +0 -2
  445. package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
  446. package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
  447. package/src/daemon/pkb-context-tracker.test.ts +169 -0
  448. package/src/daemon/pkb-context-tracker.ts +125 -0
  449. package/src/daemon/pkb-reminder-builder.test.ts +70 -0
  450. package/src/daemon/pkb-reminder-builder.ts +31 -0
  451. package/src/daemon/providers-setup.ts +6 -0
  452. package/src/daemon/server.ts +122 -12
  453. package/src/daemon/shutdown-handlers.ts +2 -12
  454. package/src/daemon/tool-side-effects.ts +14 -65
  455. package/src/daemon/web-search-history.ts +126 -0
  456. package/src/events/domain-events.ts +0 -1
  457. package/src/filing/filing-service.ts +9 -10
  458. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +160 -0
  459. package/src/heartbeat/heartbeat-service.ts +99 -28
  460. package/src/home/__tests__/feed-population-integration.test.ts +312 -0
  461. package/src/home/__tests__/feed-scheduler.test.ts +39 -11
  462. package/src/home/__tests__/rollup-producer.test.ts +44 -0
  463. package/src/home/assistant-feed-authoring.ts +4 -0
  464. package/src/home/emit-feed-event.ts +11 -0
  465. package/src/home/feed-scheduler.ts +20 -4
  466. package/src/home/feed-types.ts +97 -4
  467. package/src/home/relationship-state-writer.ts +2 -2
  468. package/src/home/rewrite-command-preview.ts +66 -0
  469. package/src/home/rollup-producer.ts +34 -5
  470. package/src/home/suggested-prompts.ts +101 -0
  471. package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
  472. package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
  473. package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
  474. package/src/ipc/__tests__/socket-path.test.ts +34 -0
  475. package/src/ipc/__tests__/task-ipc.test.ts +577 -0
  476. package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
  477. package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
  478. package/src/ipc/cli-client.ts +2 -1
  479. package/src/ipc/cli-server.ts +26 -8
  480. package/src/ipc/gateway-client.ts +6 -3
  481. package/src/ipc/routes/attachment.ts +114 -0
  482. package/src/ipc/routes/browser-context.ts +63 -0
  483. package/src/ipc/routes/browser.ts +97 -0
  484. package/src/ipc/routes/cache.ts +96 -0
  485. package/src/ipc/routes/get-contact.ts +16 -0
  486. package/src/ipc/routes/index.ts +31 -1
  487. package/src/ipc/routes/list-clients.ts +31 -0
  488. package/src/ipc/routes/merge-contacts.ts +17 -0
  489. package/src/ipc/routes/notification.ts +133 -0
  490. package/src/ipc/routes/rename-conversation.ts +59 -0
  491. package/src/ipc/routes/search-contacts.ts +19 -0
  492. package/src/ipc/routes/task-queue.ts +226 -0
  493. package/src/ipc/routes/task.ts +173 -0
  494. package/src/ipc/routes/ui-request.ts +50 -0
  495. package/src/ipc/routes/upsert-contact.ts +25 -0
  496. package/src/ipc/routes/watcher.ts +203 -0
  497. package/src/ipc/socket-path.ts +76 -0
  498. package/src/media/app-icon-generator.ts +23 -46
  499. package/src/media/avatar-router.ts +26 -41
  500. package/src/media/gemini-image-service.ts +8 -41
  501. package/src/media/image-credentials.ts +73 -0
  502. package/src/media/image-service.ts +85 -0
  503. package/src/media/openai-image-service.ts +131 -0
  504. package/src/media/types.ts +46 -0
  505. package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
  506. package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
  507. package/src/memory/admin.ts +18 -0
  508. package/src/memory/conversation-analyze-job.ts +14 -13
  509. package/src/memory/conversation-attention-store.ts +13 -6
  510. package/src/memory/conversation-crud.ts +133 -3
  511. package/src/memory/conversation-group-migration.ts +38 -6
  512. package/src/memory/conversation-queries.ts +57 -4
  513. package/src/memory/conversation-title-service.ts +32 -4
  514. package/src/memory/db-init.ts +10 -0
  515. package/src/memory/embedding-backend.ts +1 -1
  516. package/src/memory/embedding-gemini.test.ts +41 -2
  517. package/src/memory/embedding-gemini.ts +6 -1
  518. package/src/memory/graph/bootstrap.test.ts +282 -0
  519. package/src/memory/graph/bootstrap.ts +8 -5
  520. package/src/memory/graph/compaction.ts +299 -0
  521. package/src/memory/graph/consolidation.ts +4 -4
  522. package/src/memory/graph/conversation-graph-memory.ts +89 -29
  523. package/src/memory/graph/extraction.test.ts +272 -2
  524. package/src/memory/graph/extraction.ts +183 -53
  525. package/src/memory/graph/graph-search.test.ts +93 -0
  526. package/src/memory/graph/graph-search.ts +4 -1
  527. package/src/memory/graph/inspect.ts +2 -2
  528. package/src/memory/graph/narrative.ts +2 -2
  529. package/src/memory/graph/pattern-scan.ts +2 -2
  530. package/src/memory/graph/retriever.test.ts +459 -0
  531. package/src/memory/graph/retriever.ts +237 -48
  532. package/src/memory/graph/store.ts +41 -0
  533. package/src/memory/graph/tool-handlers.ts +27 -0
  534. package/src/memory/graph/tools.ts +6 -1
  535. package/src/memory/indexer.ts +5 -5
  536. package/src/memory/job-handlers/conversation-starters.ts +23 -20
  537. package/src/memory/job-handlers/summarization.ts +2 -2
  538. package/src/memory/job-utils.ts +7 -1
  539. package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
  540. package/src/memory/jobs/embed-pkb-file.ts +54 -0
  541. package/src/memory/jobs-store.ts +44 -3
  542. package/src/memory/jobs-worker.ts +4 -0
  543. package/src/memory/migrations/041-approval-prompt-ts-tracker.ts +26 -0
  544. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
  545. package/src/memory/migrations/149-oauth-tables.ts +1 -0
  546. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
  547. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
  548. package/src/memory/migrations/223-schedule-script-column.ts +11 -0
  549. package/src/memory/migrations/224-oauth-providers-managed-service-is-paid.ts +24 -0
  550. package/src/memory/migrations/225-oauth-providers-available-scopes.ts +13 -0
  551. package/src/memory/migrations/index.ts +5 -0
  552. package/src/memory/pkb/pkb-index.test.ts +369 -0
  553. package/src/memory/pkb/pkb-index.ts +255 -0
  554. package/src/memory/pkb/pkb-reconcile.test.ts +252 -0
  555. package/src/memory/pkb/pkb-reconcile.ts +148 -0
  556. package/src/memory/pkb/pkb-search.test.ts +499 -0
  557. package/src/memory/pkb/pkb-search.ts +159 -0
  558. package/src/memory/pkb/types.ts +53 -0
  559. package/src/memory/qdrant-client.test.ts +60 -0
  560. package/src/memory/qdrant-client.ts +147 -1
  561. package/src/memory/schema/infrastructure.ts +1 -0
  562. package/src/memory/schema/oauth.ts +4 -1
  563. package/src/memory/slack-thread-store.ts +37 -0
  564. package/src/messaging/providers/gmail/adapter.ts +6 -16
  565. package/src/messaging/providers/gmail/client.ts +22 -0
  566. package/src/messaging/providers/gmail/types.ts +7 -0
  567. package/src/messaging/providers/slack/adapter.ts +14 -2
  568. package/src/messaging/providers/slack/backfill.test.ts +257 -0
  569. package/src/messaging/providers/slack/backfill.ts +101 -0
  570. package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
  571. package/src/messaging/providers/slack/message-metadata.ts +123 -0
  572. package/src/messaging/providers/slack/render-transcript.test.ts +1421 -0
  573. package/src/messaging/providers/slack/render-transcript.ts +501 -0
  574. package/src/messaging/style-analyzer.ts +5 -2
  575. package/src/notifications/README.md +9 -5
  576. package/src/notifications/conversation-pairing.ts +78 -19
  577. package/src/notifications/copy-composer.ts +0 -5
  578. package/src/notifications/decision-engine.ts +3 -9
  579. package/src/notifications/emit-signal.ts +1 -1
  580. package/src/notifications/preference-extractor.ts +2 -6
  581. package/src/notifications/signal.ts +1 -2
  582. package/src/oauth/AGENTS.md +1 -1
  583. package/src/oauth/__tests__/identity-verifier.test.ts +2 -1
  584. package/src/oauth/connect-orchestrator.ts +8 -34
  585. package/src/oauth/connect-types.ts +6 -10
  586. package/src/oauth/manual-token-connection.ts +23 -0
  587. package/src/oauth/oauth-store.ts +31 -14
  588. package/src/oauth/platform-connection.test.ts +47 -0
  589. package/src/oauth/platform-connection.ts +15 -5
  590. package/src/oauth/provider-serializer.ts +6 -1
  591. package/src/oauth/seed-providers.ts +56 -106
  592. package/src/outbound-proxy/http-forwarder.ts +9 -0
  593. package/src/permissions/approval-policy.test.ts +1223 -0
  594. package/src/permissions/approval-policy.ts +309 -0
  595. package/src/permissions/arg-parser.test.ts +161 -0
  596. package/src/permissions/arg-parser.ts +141 -0
  597. package/src/permissions/bash-risk-classifier.test.ts +1620 -0
  598. package/src/permissions/bash-risk-classifier.ts +950 -0
  599. package/src/permissions/checker.ts +348 -711
  600. package/src/permissions/command-registry.test.ts +774 -0
  601. package/src/permissions/command-registry.ts +1005 -0
  602. package/src/permissions/defaults.ts +28 -79
  603. package/src/permissions/file-risk-classifier.test.ts +535 -0
  604. package/src/permissions/file-risk-classifier.ts +274 -0
  605. package/src/permissions/gateway-threshold-reader.ts +196 -0
  606. package/src/permissions/prompter.ts +4 -0
  607. package/src/permissions/risk-types.ts +262 -0
  608. package/src/permissions/schedule-risk-classifier.test.ts +129 -0
  609. package/src/permissions/schedule-risk-classifier.ts +85 -0
  610. package/src/permissions/secret-prompter.ts +53 -2
  611. package/src/permissions/shell-identity.ts +2 -42
  612. package/src/permissions/skill-risk-classifier.test.ts +311 -0
  613. package/src/permissions/skill-risk-classifier.ts +214 -0
  614. package/src/permissions/trust-client.ts +52 -25
  615. package/src/permissions/trust-store-interface.ts +1 -6
  616. package/src/permissions/trust-store.ts +161 -62
  617. package/src/permissions/types.ts +25 -14
  618. package/src/permissions/web-risk-classifier.test.ts +170 -0
  619. package/src/permissions/web-risk-classifier.ts +89 -0
  620. package/src/permissions/workspace-policy.ts +9 -19
  621. package/src/platform/client.ts +19 -1
  622. package/src/plugins/defaults/circuit-breaker.ts +146 -0
  623. package/src/plugins/defaults/compaction.ts +145 -0
  624. package/src/plugins/defaults/empty-response.ts +126 -0
  625. package/src/plugins/defaults/history-repair.ts +85 -0
  626. package/src/plugins/defaults/index.ts +116 -0
  627. package/src/plugins/defaults/injectors.ts +491 -0
  628. package/src/plugins/defaults/llm-call.ts +82 -0
  629. package/src/plugins/defaults/memory-retrieval.ts +226 -0
  630. package/src/plugins/defaults/overflow-reduce.ts +181 -0
  631. package/src/plugins/defaults/persistence.ts +129 -0
  632. package/src/plugins/defaults/title-generate.ts +95 -0
  633. package/src/plugins/defaults/token-estimate.ts +104 -0
  634. package/src/plugins/defaults/tool-error.ts +126 -0
  635. package/src/plugins/defaults/tool-execute.ts +89 -0
  636. package/src/plugins/defaults/tool-result-truncate.ts +88 -0
  637. package/src/plugins/pipeline.ts +316 -0
  638. package/src/plugins/plugin-skill-contributions.ts +292 -0
  639. package/src/plugins/registry.ts +241 -0
  640. package/src/plugins/types.ts +1134 -0
  641. package/src/plugins/user-loader.ts +177 -0
  642. package/src/prompts/persona-resolver.ts +3 -3
  643. package/src/prompts/system-prompt.ts +19 -20
  644. package/src/prompts/templates/BOOTSTRAP.md +27 -77
  645. package/src/prompts/templates/SOUL.md +2 -2
  646. package/src/prompts/update-bulletin-job.ts +190 -0
  647. package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
  648. package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
  649. package/src/providers/__tests__/retry-callsite.test.ts +424 -0
  650. package/src/providers/anthropic/client.ts +183 -14
  651. package/src/providers/call-site-routing.ts +71 -0
  652. package/src/providers/gemini/client.ts +65 -2
  653. package/src/providers/managed-proxy/constants.ts +2 -1
  654. package/src/providers/model-catalog.ts +524 -33
  655. package/src/providers/model-intents.ts +4 -4
  656. package/src/providers/openai/chat-completions-provider.ts +57 -1
  657. package/src/providers/openai/responses-provider.ts +86 -9
  658. package/src/providers/openrouter/client.ts +80 -9
  659. package/src/providers/provider-env-vars.ts +56 -0
  660. package/src/providers/provider-send-message.ts +22 -5
  661. package/src/providers/ratelimit.ts +4 -0
  662. package/src/providers/registry.ts +19 -8
  663. package/src/providers/retry.ts +174 -39
  664. package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
  665. package/src/providers/speech-to-text/deepgram-realtime.test.ts +61 -0
  666. package/src/providers/speech-to-text/deepgram-realtime.ts +57 -0
  667. package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
  668. package/src/providers/speech-to-text/provider-catalog.ts +17 -0
  669. package/src/providers/speech-to-text/resolve.ts +7 -0
  670. package/src/providers/speech-to-text/xai-realtime.test.ts +646 -0
  671. package/src/providers/speech-to-text/xai-realtime.ts +821 -0
  672. package/src/providers/speech-to-text/xai.test.ts +155 -0
  673. package/src/providers/speech-to-text/xai.ts +97 -0
  674. package/src/providers/types.ts +93 -3
  675. package/src/runtime/AGENTS.md +27 -18
  676. package/src/runtime/__tests__/agent-wake.test.ts +43 -2
  677. package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +3 -3
  678. package/src/runtime/__tests__/client-registry.test.ts +293 -0
  679. package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
  680. package/src/runtime/agent-wake.ts +63 -22
  681. package/src/runtime/auth/route-policy.ts +4 -0
  682. package/src/runtime/btw-sidechain.ts +13 -3
  683. package/src/runtime/channel-reply-delivery.ts +106 -2
  684. package/src/runtime/client-registry.ts +261 -0
  685. package/src/runtime/decision-token.ts +116 -0
  686. package/src/runtime/gateway-client.ts +2 -2
  687. package/src/runtime/http-router.ts +32 -0
  688. package/src/runtime/http-server.ts +129 -9
  689. package/src/runtime/http-types.ts +23 -3
  690. package/src/runtime/interactive-ui.ts +362 -0
  691. package/src/runtime/invite-instruction-generator.ts +2 -2
  692. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
  693. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
  694. package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
  695. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
  696. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
  697. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
  698. package/src/runtime/migrations/gcs-signed-url.ts +162 -0
  699. package/src/runtime/migrations/vbundle-builder.ts +1 -22
  700. package/src/runtime/migrations/vbundle-importer.ts +154 -9
  701. package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
  702. package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
  703. package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
  704. package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
  705. package/src/runtime/migrations/vbundle-validator.ts +15 -6
  706. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
  707. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
  708. package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
  709. package/src/runtime/routes/approval-prompt-ts-tracker.ts +78 -0
  710. package/src/runtime/routes/approval-routes.ts +29 -17
  711. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
  712. package/src/runtime/routes/avatar-routes.ts +20 -4
  713. package/src/runtime/routes/browser-extension-pair-routes.ts +27 -8
  714. package/src/runtime/routes/btw-routes.ts +1 -4
  715. package/src/runtime/routes/conversation-management-routes.ts +20 -2
  716. package/src/runtime/routes/conversation-routes.ts +351 -138
  717. package/src/runtime/routes/debug-routes.ts +1 -1
  718. package/src/runtime/routes/diagnostics-routes.ts +6 -4
  719. package/src/runtime/routes/events-routes.ts +16 -0
  720. package/src/runtime/routes/guardian-approval-interception.ts +33 -3
  721. package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
  722. package/src/runtime/routes/home-feed-routes.ts +120 -2
  723. package/src/runtime/routes/inbound-message-handler.ts +987 -2
  724. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
  725. package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
  726. package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
  727. package/src/runtime/routes/integrations/slack/channel.ts +25 -3
  728. package/src/runtime/routes/llm-context-normalization.ts +23 -1
  729. package/src/runtime/routes/memory-item-routes.test.ts +1 -0
  730. package/src/runtime/routes/migration-routes.ts +720 -127
  731. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +284 -0
  732. package/src/runtime/routes/playground/__tests__/guard.test.ts +80 -0
  733. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +294 -0
  734. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +271 -0
  735. package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +202 -0
  736. package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +309 -0
  737. package/src/runtime/routes/playground/__tests__/state.test.ts +224 -0
  738. package/src/runtime/routes/playground/conversation-not-found.ts +29 -0
  739. package/src/runtime/routes/playground/deps.ts +56 -0
  740. package/src/runtime/routes/playground/force-compact.ts +73 -0
  741. package/src/runtime/routes/playground/guard.ts +37 -0
  742. package/src/runtime/routes/playground/index.ts +28 -0
  743. package/src/runtime/routes/playground/inject-failures.ts +159 -0
  744. package/src/runtime/routes/playground/reset-circuit.ts +115 -0
  745. package/src/runtime/routes/playground/seed-conversation.ts +139 -0
  746. package/src/runtime/routes/playground/seeded-conversations.ts +78 -0
  747. package/src/runtime/routes/playground/state.ts +78 -0
  748. package/src/runtime/routes/schedule-routes.ts +89 -8
  749. package/src/runtime/routes/settings-routes.ts +4 -2
  750. package/src/runtime/routes/trust-rules-routes.ts +30 -14
  751. package/src/runtime/routes/work-items-routes.test.ts +1 -1
  752. package/src/runtime/routes/work-items-routes.ts +3 -2
  753. package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
  754. package/src/runtime/services/analyze-conversation.ts +12 -16
  755. package/src/runtime/skill-route-registry.ts +97 -15
  756. package/src/schedule/run-script.ts +68 -0
  757. package/src/schedule/schedule-store.ts +7 -1
  758. package/src/schedule/scheduler.ts +56 -8
  759. package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
  760. package/src/security/__tests__/untrusted-content.test.ts +109 -0
  761. package/src/security/oauth2.ts +98 -35
  762. package/src/security/secure-keys.ts +7 -8
  763. package/src/security/token-manager.ts +27 -13
  764. package/src/security/untrusted-content.ts +102 -0
  765. package/src/skills/catalog-cache.ts +35 -9
  766. package/src/skills/catalog-install.ts +31 -3
  767. package/src/skills/skill-cache-store.ts +97 -0
  768. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
  769. package/src/stt/daemon-batch-transcriber.ts +33 -0
  770. package/src/stt/stt-stream-session.ts +8 -1
  771. package/src/stt/types.ts +5 -1
  772. package/src/subagent/manager.ts +41 -13
  773. package/src/tasks/ephemeral-permissions.ts +9 -4
  774. package/src/telemetry/usage-telemetry-reporter.ts +27 -5
  775. package/src/tools/browser/__tests__/browser-status.test.ts +234 -2
  776. package/src/tools/browser/browser-execution.ts +150 -54
  777. package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +230 -0
  778. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +146 -3
  779. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
  780. package/src/tools/browser/cdp-client/extension-cdp-client.ts +54 -3
  781. package/src/tools/browser/cdp-client/factory.ts +15 -4
  782. package/src/tools/credentials/tool-policy.ts +39 -5
  783. package/src/tools/credentials/vault.ts +9 -4
  784. package/src/tools/executor.ts +129 -73
  785. package/src/tools/filesystem/write.ts +52 -0
  786. package/src/tools/host-terminal/host-shell.ts +45 -5
  787. package/src/tools/memory/register.test.ts +185 -0
  788. package/src/tools/memory/register.ts +3 -1
  789. package/src/tools/network/script-proxy/session-manager.ts +37 -1
  790. package/src/tools/network/web-fetch.ts +20 -10
  791. package/src/tools/network/web-search.ts +19 -4
  792. package/src/tools/permission-checker.ts +116 -46
  793. package/src/tools/policy-context.ts +29 -8
  794. package/src/tools/registry.ts +195 -6
  795. package/src/tools/schedule/create.ts +23 -8
  796. package/src/tools/schedule/update.ts +3 -1
  797. package/src/tools/secret-detection-handler.ts +0 -51
  798. package/src/tools/side-effects.ts +0 -11
  799. package/src/tools/skills/execute.ts +2 -2
  800. package/src/tools/skills/sandbox-runner.ts +5 -2
  801. package/src/tools/system/avatar-generator.ts +6 -2
  802. package/src/tools/terminal/backends/native.ts +51 -2
  803. package/src/tools/terminal/safe-env.ts +3 -2
  804. package/src/tools/terminal/shell.ts +1 -0
  805. package/src/tools/tool-manifest.ts +6 -21
  806. package/src/tools/types.ts +40 -5
  807. package/src/tools/verification-control-plane-policy.ts +1 -1
  808. package/src/tts/__tests__/provider-adapters.test.ts +240 -13
  809. package/src/tts/provider-catalog.ts +18 -0
  810. package/src/tts/providers/index.ts +2 -0
  811. package/src/tts/providers/xai-provider.ts +224 -0
  812. package/src/tts/types.ts +46 -0
  813. package/src/types/tar-stream.d.ts +66 -0
  814. package/src/util/json.ts +17 -0
  815. package/src/util/platform.ts +9 -4
  816. package/src/util/pricing.ts +41 -8
  817. package/src/watcher/engine.ts +1 -1
  818. package/src/watcher/providers/google-calendar.ts +134 -8
  819. package/src/watcher/providers/outlook-calendar.ts +42 -2
  820. package/src/workspace/git-service.ts +23 -4
  821. package/src/workspace/migrations/006-services-config.ts +2 -4
  822. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +2 -3
  823. package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
  824. package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
  825. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
  826. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +56 -0
  827. package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
  828. package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
  829. package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
  830. package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
  831. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +108 -0
  832. package/src/workspace/migrations/047-remove-watch-callsites.ts +54 -0
  833. package/src/workspace/migrations/048-remove-workspace-hooks.ts +81 -0
  834. package/src/workspace/migrations/049-release-notes-default-sonnet.ts +80 -0
  835. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +86 -0
  836. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +128 -0
  837. package/src/workspace/migrations/AGENTS.md +1 -1
  838. package/src/workspace/migrations/registry.ts +28 -0
  839. package/src/workspace/provider-commit-message-generator.ts +19 -38
  840. package/tsconfig.json +1 -1
  841. package/hook-templates/debug-prompt-logger/hook.json +0 -7
  842. package/hook-templates/debug-prompt-logger/run.sh +0 -66
  843. package/src/__tests__/context-overflow-approval.test.ts +0 -156
  844. package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
  845. package/src/__tests__/gmail-archive-gate.test.ts +0 -246
  846. package/src/__tests__/gmail-preferences.test.ts +0 -117
  847. package/src/__tests__/hooks-blocking.test.ts +0 -178
  848. package/src/__tests__/hooks-cli.test.ts +0 -182
  849. package/src/__tests__/hooks-config.test.ts +0 -108
  850. package/src/__tests__/hooks-discovery.test.ts +0 -211
  851. package/src/__tests__/hooks-integration.test.ts +0 -196
  852. package/src/__tests__/hooks-manager.test.ts +0 -226
  853. package/src/__tests__/hooks-runner.test.ts +0 -175
  854. package/src/__tests__/hooks-settings.test.ts +0 -160
  855. package/src/__tests__/hooks-templates.test.ts +0 -169
  856. package/src/__tests__/hooks-ts-runner.test.ts +0 -170
  857. package/src/__tests__/hooks-watch.test.ts +0 -112
  858. package/src/__tests__/notification-schedule-dedup.test.ts +0 -213
  859. package/src/__tests__/oauth-scope-policy.test.ts +0 -180
  860. package/src/__tests__/outlook-attachments.test.ts +0 -301
  861. package/src/__tests__/outlook-automation-tools.test.ts +0 -425
  862. package/src/__tests__/outlook-categories.test.ts +0 -212
  863. package/src/__tests__/outlook-compose-tools.test.ts +0 -325
  864. package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
  865. package/src/__tests__/outlook-follow-up.test.ts +0 -196
  866. package/src/__tests__/outlook-trash.test.ts +0 -77
  867. package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
  868. package/src/__tests__/send-notification-tool.test.ts +0 -83
  869. package/src/__tests__/update-bulletin-format.test.ts +0 -181
  870. package/src/__tests__/update-bulletin-state.test.ts +0 -135
  871. package/src/__tests__/update-bulletin.test.ts +0 -478
  872. package/src/__tests__/update-template-contract.test.ts +0 -29
  873. package/src/cli/commands/doctor.ts +0 -341
  874. package/src/cli/commands/shotgun.ts +0 -266
  875. package/src/config/bundled-skills/browser/SKILL.md +0 -88
  876. package/src/config/bundled-skills/browser/TOOLS.json +0 -516
  877. package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
  878. package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
  879. package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
  880. package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
  881. package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
  882. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
  883. package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
  884. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
  885. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
  886. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
  887. package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
  888. package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
  889. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
  890. package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
  891. package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
  892. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
  893. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
  894. package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
  895. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
  896. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
  897. package/src/config/bundled-skills/conversations/SKILL.md +0 -20
  898. package/src/config/bundled-skills/conversations/TOOLS.json +0 -23
  899. package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +0 -66
  900. package/src/config/bundled-skills/gmail/SKILL.md +0 -221
  901. package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
  902. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
  903. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
  904. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
  905. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
  906. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
  907. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
  908. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
  909. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
  910. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
  911. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
  912. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
  913. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
  914. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
  915. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
  916. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
  917. package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
  918. package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
  919. package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
  920. package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
  921. package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
  922. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
  923. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
  924. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
  925. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
  926. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
  927. package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
  928. package/src/config/bundled-skills/google-calendar/types.ts +0 -97
  929. package/src/config/bundled-skills/heartbeat/SKILL.md +0 -43
  930. package/src/config/bundled-skills/notifications/SKILL.md +0 -40
  931. package/src/config/bundled-skills/notifications/TOOLS.json +0 -80
  932. package/src/config/bundled-skills/notifications/tools/send-notification.ts +0 -152
  933. package/src/config/bundled-skills/notifications/tools/shared.ts +0 -13
  934. package/src/config/bundled-skills/outlook/SKILL.md +0 -196
  935. package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
  936. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
  937. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
  938. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
  939. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
  940. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
  941. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
  942. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
  943. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
  944. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
  945. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
  946. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
  947. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
  948. package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
  949. package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
  950. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
  951. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
  952. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
  953. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
  954. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
  955. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
  956. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
  957. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
  958. package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
  959. package/src/config/bundled-skills/screen-watch/SKILL.md +0 -27
  960. package/src/config/bundled-skills/screen-watch/TOOLS.json +0 -35
  961. package/src/config/bundled-skills/screen-watch/tools/start-screen-watch.ts +0 -12
  962. package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -84
  963. package/src/config/bundled-skills/slack/SKILL.md +0 -108
  964. package/src/config/bundled-skills/tasks/SKILL.md +0 -37
  965. package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
  966. package/src/config/bundled-skills/tasks/icon.svg +0 -34
  967. package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
  968. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
  969. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
  970. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
  971. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
  972. package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
  973. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
  974. package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
  975. package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
  976. package/src/config/bundled-skills/watcher/SKILL.md +0 -31
  977. package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
  978. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
  979. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
  980. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
  981. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
  982. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
  983. package/src/daemon/context-overflow-approval.ts +0 -52
  984. package/src/daemon/watch-handler.ts +0 -399
  985. package/src/hooks/cli.ts +0 -253
  986. package/src/hooks/config.ts +0 -100
  987. package/src/hooks/discovery.ts +0 -135
  988. package/src/hooks/manager.ts +0 -179
  989. package/src/hooks/runner.ts +0 -117
  990. package/src/hooks/templates.ts +0 -77
  991. package/src/hooks/types.ts +0 -75
  992. package/src/oauth/scope-policy.ts +0 -89
  993. package/src/prompts/templates/UPDATES.md +0 -50
  994. package/src/prompts/update-bulletin-format.ts +0 -85
  995. package/src/prompts/update-bulletin-state.ts +0 -58
  996. package/src/prompts/update-bulletin-template-path.ts +0 -13
  997. package/src/prompts/update-bulletin.ts +0 -139
  998. package/src/runtime/gateway-internal-client.ts +0 -94
  999. package/src/runtime/routes/watch-routes.ts +0 -156
  1000. package/src/shared/provider-env-vars.ts +0 -19
  1001. package/src/signals/shotgun.ts +0 -203
  1002. package/src/tools/watch/screen-watch.ts +0 -144
  1003. package/src/tools/watch/watch-state.ts +0 -142
  1004. package/src/tools/watcher/create.ts +0 -86
  1005. package/src/tools/watcher/delete.ts +0 -36
  1006. package/src/tools/watcher/digest.ts +0 -54
  1007. package/src/tools/watcher/list.ts +0 -83
  1008. package/src/tools/watcher/update.ts +0 -71
@@ -81,9 +81,11 @@ function writeConfig(obj: unknown): void {
81
81
  describe("AssistantConfigSchema", () => {
82
82
  test("parses empty object with full defaults", () => {
83
83
  const result = AssistantConfigSchema.parse({});
84
- expect(result.services.inference.provider).toBe("anthropic");
85
- expect(result.services.inference.model).toBe("claude-opus-4-6");
84
+ // services.inference now carries only `mode`; provider/model live under
85
+ // llm.default.{provider,model} (see PR 19 of unify-llm-callsites).
86
86
  expect(result.services.inference.mode).toBe("your-own");
87
+ expect(result.llm.default.provider).toBe("anthropic");
88
+ expect(result.llm.default.model).toBe("claude-sonnet-4-6");
87
89
  expect(result.services["image-generation"].provider).toBe("gemini");
88
90
  expect(result.services["image-generation"].model).toBe(
89
91
  "gemini-3.1-flash-image-preview",
@@ -93,12 +95,12 @@ describe("AssistantConfigSchema", () => {
93
95
  "inference-provider-native",
94
96
  );
95
97
  expect(result.services["web-search"].mode).toBe("your-own");
96
- expect(result.maxTokens).toBe(64000);
97
- expect(result.thinking).toEqual({
98
+ expect(result.llm.default.maxTokens).toBe(64000);
99
+ expect(result.llm.default.thinking).toEqual({
98
100
  enabled: true,
99
101
  streamThinking: true,
100
102
  });
101
- expect(result.contextWindow).toEqual({
103
+ expect(result.llm.default.contextWindow).toEqual({
102
104
  enabled: true,
103
105
  maxInputTokens: 200000,
104
106
  targetBudgetRatio: 0.3,
@@ -134,11 +136,13 @@ describe("AssistantConfigSchema", () => {
134
136
 
135
137
  test("accepts valid complete config", () => {
136
138
  const input = {
137
- services: {
138
- inference: { provider: "openai", model: "gpt-4" },
139
+ llm: {
140
+ default: {
141
+ provider: "openai" as const,
142
+ model: "gpt-4",
143
+ maxTokens: 4096,
144
+ },
139
145
  },
140
- maxTokens: 4096,
141
- thinking: { enabled: true },
142
146
  timeouts: {
143
147
  shellDefaultTimeoutSec: 30,
144
148
  shellMaxTimeoutSec: 300,
@@ -154,13 +158,186 @@ describe("AssistantConfigSchema", () => {
154
158
  auditLog: { retentionDays: 30 },
155
159
  };
156
160
  const result = AssistantConfigSchema.parse(input);
157
- expect(result.services.inference.provider).toBe("openai");
158
- expect(result.services.inference.model).toBe("gpt-4");
159
- expect(result.maxTokens).toBe(4096);
160
- expect(result.thinking.enabled).toBe(true);
161
+ expect(result.llm.default.provider).toBe("openai");
162
+ expect(result.llm.default.model).toBe("gpt-4");
163
+ expect(result.llm.default.maxTokens).toBe(4096);
164
+ expect(result.llm.default.thinking.enabled).toBe(true);
161
165
  expect(result.secretDetection.action).toBe("block");
162
166
  });
163
167
 
168
+ test("applies llm defaults when llm key is omitted", () => {
169
+ const result = AssistantConfigSchema.parse({});
170
+ expect(result.llm).toBeDefined();
171
+ expect(result.llm.default).toEqual({
172
+ provider: "anthropic",
173
+ model: "claude-sonnet-4-6",
174
+ maxTokens: 64000,
175
+ effort: "max",
176
+ speed: "standard",
177
+ temperature: null,
178
+ thinking: { enabled: true, streamThinking: true },
179
+ contextWindow: {
180
+ enabled: true,
181
+ maxInputTokens: 200000,
182
+ targetBudgetRatio: 0.3,
183
+ compactThreshold: 0.8,
184
+ summaryBudgetRatio: 0.05,
185
+ overflowRecovery: {
186
+ enabled: true,
187
+ safetyMarginRatio: 0.05,
188
+ maxAttempts: 3,
189
+ interactiveLatestTurnCompression: "summarize",
190
+ nonInteractiveLatestTurnCompression: "truncate",
191
+ },
192
+ },
193
+ openrouter: { only: [] },
194
+ });
195
+ expect(result.llm.profiles).toEqual({});
196
+ expect(result.llm.callSites).toEqual({});
197
+ expect(result.llm.pricingOverrides).toEqual([]);
198
+ });
199
+
200
+ test("accepts an explicit llm block with profiles and call sites", () => {
201
+ const input = {
202
+ llm: {
203
+ default: {
204
+ provider: "anthropic" as const,
205
+ model: "claude-opus-4-7",
206
+ maxTokens: 32000,
207
+ effort: "high" as const,
208
+ speed: "fast" as const,
209
+ temperature: null,
210
+ thinking: { enabled: true, streamThinking: false },
211
+ contextWindow: {
212
+ enabled: true,
213
+ maxInputTokens: 200000,
214
+ targetBudgetRatio: 0.3,
215
+ compactThreshold: 0.8,
216
+ summaryBudgetRatio: 0.05,
217
+ overflowRecovery: {
218
+ enabled: true,
219
+ safetyMarginRatio: 0.05,
220
+ maxAttempts: 3,
221
+ interactiveLatestTurnCompression: "summarize" as const,
222
+ nonInteractiveLatestTurnCompression: "truncate" as const,
223
+ },
224
+ },
225
+ },
226
+ profiles: {
227
+ fast: { speed: "fast" as const, effort: "low" as const },
228
+ },
229
+ callSites: {
230
+ mainAgent: { profile: "fast" },
231
+ commitMessage: { maxTokens: 256 },
232
+ },
233
+ pricingOverrides: [],
234
+ },
235
+ };
236
+ const result = AssistantConfigSchema.parse(input);
237
+ expect(result.llm.default.model).toBe("claude-opus-4-7");
238
+ expect(result.llm.default.speed).toBe("fast");
239
+ expect(result.llm.profiles?.fast).toEqual({
240
+ speed: "fast",
241
+ effort: "low",
242
+ });
243
+ expect(result.llm.callSites?.mainAgent).toEqual({ profile: "fast" });
244
+ expect(result.llm.callSites?.commitMessage).toEqual({ maxTokens: 256 });
245
+ });
246
+
247
+ test("rejects an llm.callSites entry that references an undefined profile", () => {
248
+ const input = {
249
+ llm: {
250
+ default: {
251
+ provider: "anthropic" as const,
252
+ model: "claude-opus-4-6",
253
+ maxTokens: 64000,
254
+ effort: "max" as const,
255
+ speed: "standard" as const,
256
+ temperature: null,
257
+ thinking: { enabled: true, streamThinking: true },
258
+ contextWindow: {
259
+ enabled: true,
260
+ maxInputTokens: 200000,
261
+ targetBudgetRatio: 0.3,
262
+ compactThreshold: 0.8,
263
+ summaryBudgetRatio: 0.05,
264
+ overflowRecovery: {
265
+ enabled: true,
266
+ safetyMarginRatio: 0.05,
267
+ maxAttempts: 3,
268
+ interactiveLatestTurnCompression: "summarize" as const,
269
+ nonInteractiveLatestTurnCompression: "truncate" as const,
270
+ },
271
+ },
272
+ },
273
+ callSites: {
274
+ mainAgent: { profile: "missing-profile" },
275
+ },
276
+ },
277
+ };
278
+ expect(() => AssistantConfigSchema.parse(input)).toThrow(/missing-profile/);
279
+ });
280
+
281
+ test("legacy top-level inference keys are ignored after PR 19 cleanup", () => {
282
+ // The legacy keys (top-level maxTokens, effort, speed, thinking,
283
+ // contextWindow, services.inference.{provider,model}) were removed in PR
284
+ // 19. Configs that still carry them parse cleanly because Zod strips
285
+ // unknown fields, and migration 039 erases them from the on-disk file
286
+ // entirely.
287
+ const input = {
288
+ services: {
289
+ inference: { provider: "openai", model: "gpt-4" },
290
+ },
291
+ maxTokens: 8000,
292
+ effort: "medium",
293
+ speed: "fast",
294
+ thinking: { enabled: false, streamThinking: false },
295
+ };
296
+ const result = AssistantConfigSchema.parse(input);
297
+ expect((result as Record<string, unknown>).maxTokens).toBeUndefined();
298
+ expect((result as Record<string, unknown>).effort).toBeUndefined();
299
+ expect((result as Record<string, unknown>).speed).toBeUndefined();
300
+ expect((result as Record<string, unknown>).thinking).toBeUndefined();
301
+ expect(
302
+ (result.services.inference as Record<string, unknown>).provider,
303
+ ).toBeUndefined();
304
+ expect(
305
+ (result.services.inference as Record<string, unknown>).model,
306
+ ).toBeUndefined();
307
+ expect(result.llm.default.provider).toBe("anthropic");
308
+ expect(result.llm.default.model).toBe("claude-sonnet-4-6");
309
+ });
310
+
311
+ test("partial llm config (empty `llm: {}`) doesn't trigger full config reset", () => {
312
+ // Regression guard: previously LLMConfigBase had no schema-level defaults,
313
+ // so any `llm: {}` block would fail validation and the loader's recovery
314
+ // path would fall through to `cloneDefaultConfig()`, discarding unrelated
315
+ // valid settings (like a custom `llm.default.maxTokens`). With leaf-level
316
+ // defaults, `llm: {}` parses cleanly and the user's other settings are
317
+ // preserved.
318
+ const result = AssistantConfigSchema.parse({
319
+ llm: { default: { maxTokens: 32000 } },
320
+ });
321
+ expect(result.llm.default.maxTokens).toBe(32000);
322
+ expect(result.llm.default.provider).toBe("anthropic");
323
+ expect(result.llm.default.model).toBe("claude-sonnet-4-6");
324
+ });
325
+
326
+ test("llm.default with one missing field still parses (defaults applied)", () => {
327
+ // A user can override a single field of `llm.default` without specifying
328
+ // the rest — schema-level defaults fill in everything that wasn't set.
329
+ const result = AssistantConfigSchema.parse({
330
+ llm: { default: { model: "claude-haiku-4-5" } },
331
+ });
332
+ expect(result.llm.default.model).toBe("claude-haiku-4-5");
333
+ expect(result.llm.default.provider).toBe("anthropic");
334
+ expect(result.llm.default.maxTokens).toBe(64000);
335
+ expect(result.llm.default.thinking).toEqual({
336
+ enabled: true,
337
+ streamThinking: true,
338
+ });
339
+ });
340
+
164
341
  test("applies rollout defaults for dynamic budget", () => {
165
342
  const result = AssistantConfigSchema.parse({});
166
343
  expect(result.memory.retrieval.dynamicBudget).toEqual({
@@ -248,13 +425,15 @@ describe("AssistantConfigSchema", () => {
248
425
 
249
426
  test("rejects invalid provider", () => {
250
427
  const result = AssistantConfigSchema.safeParse({
251
- services: { inference: { provider: "invalid" } },
428
+ llm: { default: { provider: "invalid" } },
252
429
  });
253
430
  expect(result.success).toBe(false);
254
431
  });
255
432
 
256
- test("rejects negative maxTokens", () => {
257
- const result = AssistantConfigSchema.safeParse({ maxTokens: -100 });
433
+ test("rejects negative llm.default.maxTokens", () => {
434
+ const result = AssistantConfigSchema.safeParse({
435
+ llm: { default: { maxTokens: -100 } },
436
+ });
258
437
  expect(result.success).toBe(false);
259
438
  if (!result.success) {
260
439
  expect(
@@ -263,8 +442,10 @@ describe("AssistantConfigSchema", () => {
263
442
  }
264
443
  });
265
444
 
266
- test("rejects non-integer maxTokens", () => {
267
- const result = AssistantConfigSchema.safeParse({ maxTokens: 3.14 });
445
+ test("rejects non-integer llm.default.maxTokens", () => {
446
+ const result = AssistantConfigSchema.safeParse({
447
+ llm: { default: { maxTokens: 3.14 } },
448
+ });
268
449
  expect(result.success).toBe(false);
269
450
  if (!result.success) {
270
451
  expect(
@@ -273,9 +454,9 @@ describe("AssistantConfigSchema", () => {
273
454
  }
274
455
  });
275
456
 
276
- test("rejects string maxTokens", () => {
457
+ test("rejects string llm.default.maxTokens", () => {
277
458
  const result = AssistantConfigSchema.safeParse({
278
- maxTokens: "not-a-number",
459
+ llm: { default: { maxTokens: "not-a-number" } },
279
460
  });
280
461
  expect(result.success).toBe(false);
281
462
  if (!result.success) {
@@ -301,7 +482,7 @@ describe("AssistantConfigSchema", () => {
301
482
 
302
483
  test("rejects invalid thinking config", () => {
303
484
  const result = AssistantConfigSchema.safeParse({
304
- thinking: { enabled: "yes" },
485
+ llm: { default: { thinking: { enabled: "yes" } } },
305
486
  });
306
487
  expect(result.success).toBe(false);
307
488
  if (!result.success) {
@@ -311,16 +492,21 @@ describe("AssistantConfigSchema", () => {
311
492
 
312
493
  test("rejects contextWindow targetBudgetRatio >= compactThreshold", () => {
313
494
  const result = AssistantConfigSchema.safeParse({
314
- contextWindow: { targetBudgetRatio: 0.8, compactThreshold: 0.8 },
495
+ llm: {
496
+ default: {
497
+ contextWindow: { targetBudgetRatio: 0.8, compactThreshold: 0.8 },
498
+ },
499
+ },
315
500
  });
316
501
  expect(result.success).toBe(false);
317
502
  if (!result.success) {
318
503
  expect(
319
504
  result.error.issues.some(
320
505
  (issue) =>
321
- issue.path.join(".") === "contextWindow.targetBudgetRatio" &&
506
+ issue.path.join(".") ===
507
+ "llm.default.contextWindow.targetBudgetRatio" &&
322
508
  issue.message.includes(
323
- "must be less than contextWindow.compactThreshold",
509
+ "must be less than llm.default.contextWindow.compactThreshold",
324
510
  ),
325
511
  ),
326
512
  ).toBe(true);
@@ -330,7 +516,11 @@ describe("AssistantConfigSchema", () => {
330
516
  test("rejects overflowRecovery safetyMarginRatio out of (0,1) range", () => {
331
517
  for (const bad of [0, 1, -0.1, 1.5]) {
332
518
  const result = AssistantConfigSchema.safeParse({
333
- contextWindow: { overflowRecovery: { safetyMarginRatio: bad } },
519
+ llm: {
520
+ default: {
521
+ contextWindow: { overflowRecovery: { safetyMarginRatio: bad } },
522
+ },
523
+ },
334
524
  });
335
525
  expect(result.success).toBe(false);
336
526
  if (!result.success) {
@@ -345,8 +535,12 @@ describe("AssistantConfigSchema", () => {
345
535
 
346
536
  test("rejects invalid overflowRecovery interactiveLatestTurnCompression", () => {
347
537
  const result = AssistantConfigSchema.safeParse({
348
- contextWindow: {
349
- overflowRecovery: { interactiveLatestTurnCompression: "explode" },
538
+ llm: {
539
+ default: {
540
+ contextWindow: {
541
+ overflowRecovery: { interactiveLatestTurnCompression: "explode" },
542
+ },
543
+ },
350
544
  },
351
545
  });
352
546
  expect(result.success).toBe(false);
@@ -361,8 +555,12 @@ describe("AssistantConfigSchema", () => {
361
555
 
362
556
  test("rejects invalid overflowRecovery nonInteractiveLatestTurnCompression", () => {
363
557
  const result = AssistantConfigSchema.safeParse({
364
- contextWindow: {
365
- overflowRecovery: { nonInteractiveLatestTurnCompression: "nope" },
558
+ llm: {
559
+ default: {
560
+ contextWindow: {
561
+ overflowRecovery: { nonInteractiveLatestTurnCompression: "nope" },
562
+ },
563
+ },
366
564
  },
367
565
  });
368
566
  expect(result.success).toBe(false);
@@ -433,7 +631,7 @@ describe("AssistantConfigSchema", () => {
433
631
  "ollama",
434
632
  ] as const) {
435
633
  const result = AssistantConfigSchema.safeParse({
436
- services: { inference: { provider } },
634
+ llm: { default: { provider } },
437
635
  });
438
636
  expect(result.success).toBe(true);
439
637
  }
@@ -450,13 +648,19 @@ describe("AssistantConfigSchema", () => {
450
648
 
451
649
  test("provides helpful error messages", () => {
452
650
  const result = AssistantConfigSchema.safeParse({
453
- maxTokens: -1,
651
+ llm: { default: { maxTokens: -1 } },
454
652
  secretDetection: { action: "explode" },
455
653
  });
456
654
  expect(result.success).toBe(false);
457
655
  if (!result.success) {
458
656
  const messages = result.error.issues.map((i) => i.message);
459
- expect(messages.some((m) => m.includes("positive"))).toBe(true);
657
+ // The llm.default.maxTokens validation rejects -1 with a "Too small"
658
+ // / "expected number to be >0" message from Zod's default issue text.
659
+ expect(
660
+ messages.some(
661
+ (m) => m.includes("positive") || /expected number to be >0/i.test(m),
662
+ ),
663
+ ).toBe(true);
460
664
  expect(
461
665
  messages.some(
462
666
  (m) =>
@@ -471,6 +675,11 @@ describe("AssistantConfigSchema", () => {
471
675
  expect(result.permissions).toEqual({
472
676
  mode: "workspace",
473
677
  hostAccess: false,
678
+ autoApproveUpTo: {
679
+ conversation: "low",
680
+ background: "medium",
681
+ headless: "none",
682
+ },
474
683
  });
475
684
  });
476
685
 
@@ -507,6 +716,132 @@ describe("AssistantConfigSchema", () => {
507
716
  }
508
717
  });
509
718
 
719
+ test("defaults autoApproveUpTo to per-context object when not specified", () => {
720
+ const result = AssistantConfigSchema.parse({
721
+ permissions: { mode: "workspace" },
722
+ });
723
+ expect(result.permissions.autoApproveUpTo).toEqual({
724
+ conversation: "low",
725
+ background: "medium",
726
+ headless: "none",
727
+ });
728
+ });
729
+
730
+ test("accepts autoApproveUpTo none", () => {
731
+ const result = AssistantConfigSchema.parse({
732
+ permissions: { autoApproveUpTo: "none" },
733
+ });
734
+ expect(result.permissions.autoApproveUpTo).toBe("none");
735
+ });
736
+
737
+ test("accepts autoApproveUpTo low", () => {
738
+ const result = AssistantConfigSchema.parse({
739
+ permissions: { autoApproveUpTo: "low" },
740
+ });
741
+ expect(result.permissions.autoApproveUpTo).toBe("low");
742
+ });
743
+
744
+ test("accepts autoApproveUpTo medium", () => {
745
+ const result = AssistantConfigSchema.parse({
746
+ permissions: { autoApproveUpTo: "medium" },
747
+ });
748
+ expect(result.permissions.autoApproveUpTo).toBe("medium");
749
+ });
750
+
751
+ test("accepts autoApproveUpTo high", () => {
752
+ const result = AssistantConfigSchema.parse({
753
+ permissions: { autoApproveUpTo: "high" },
754
+ });
755
+ expect(result.permissions.autoApproveUpTo).toBe("high");
756
+ });
757
+
758
+ test("rejects invalid autoApproveUpTo string", () => {
759
+ const result = AssistantConfigSchema.safeParse({
760
+ permissions: { autoApproveUpTo: "everything" },
761
+ });
762
+ expect(result.success).toBe(false);
763
+ });
764
+
765
+ test("autoApproveUpTo round-trips through JSON serialization", () => {
766
+ const original = AssistantConfigSchema.parse({
767
+ permissions: { autoApproveUpTo: "medium" },
768
+ });
769
+ const json = JSON.stringify(original);
770
+ const parsed = AssistantConfigSchema.parse(JSON.parse(json));
771
+ expect(parsed.permissions.autoApproveUpTo).toBe("medium");
772
+ });
773
+
774
+ test("accepts autoApproveUpTo as per-context object", () => {
775
+ const result = AssistantConfigSchema.parse({
776
+ permissions: {
777
+ autoApproveUpTo: {
778
+ conversation: "low",
779
+ background: "medium",
780
+ headless: "none",
781
+ },
782
+ },
783
+ });
784
+ expect(result.permissions.autoApproveUpTo).toEqual({
785
+ conversation: "low",
786
+ background: "medium",
787
+ headless: "none",
788
+ });
789
+ });
790
+
791
+ test("per-context object applies defaults for omitted keys", () => {
792
+ const result = AssistantConfigSchema.parse({
793
+ permissions: {
794
+ autoApproveUpTo: {},
795
+ },
796
+ });
797
+ expect(result.permissions.autoApproveUpTo).toEqual({
798
+ conversation: "low",
799
+ background: "medium",
800
+ headless: "none",
801
+ });
802
+ });
803
+
804
+ test("per-context object rejects invalid enum values", () => {
805
+ const result = AssistantConfigSchema.safeParse({
806
+ permissions: {
807
+ autoApproveUpTo: { conversation: "extreme" },
808
+ },
809
+ });
810
+ expect(result.success).toBe(false);
811
+ });
812
+
813
+ test("per-context object accepts high enum value", () => {
814
+ const result = AssistantConfigSchema.parse({
815
+ permissions: {
816
+ autoApproveUpTo: { conversation: "high" },
817
+ },
818
+ });
819
+ expect(result.permissions.autoApproveUpTo).toEqual({
820
+ conversation: "high",
821
+ background: "medium",
822
+ headless: "none",
823
+ });
824
+ });
825
+
826
+ test("per-context object round-trips through JSON serialization", () => {
827
+ const original = AssistantConfigSchema.parse({
828
+ permissions: {
829
+ autoApproveUpTo: {
830
+ conversation: "none",
831
+ background: "low",
832
+ headless: "medium",
833
+ },
834
+ },
835
+ });
836
+ const json = JSON.stringify(original);
837
+ const parsed = AssistantConfigSchema.parse(JSON.parse(json));
838
+ expect(parsed.permissions.autoApproveUpTo).toEqual({
839
+ conversation: "none",
840
+ background: "low",
841
+ headless: "medium",
842
+ });
843
+ });
844
+
510
845
  test("applies workspaceGit defaults including interactiveGitTimeoutMs", () => {
511
846
  const result = AssistantConfigSchema.parse({});
512
847
  expect(result.workspaceGit).toEqual({
@@ -520,11 +855,7 @@ describe("AssistantConfigSchema", () => {
520
855
  enrichmentMaxRetries: 2,
521
856
  commitMessageLLM: {
522
857
  enabled: false,
523
- useConfiguredProvider: true,
524
- providerFastModelOverrides: {},
525
858
  timeoutMs: 600,
526
- maxTokens: 120,
527
- temperature: 0.2,
528
859
  maxFilesInPrompt: 30,
529
860
  maxDiffBytes: 12000,
530
861
  minRemainingTurnBudgetMs: 1000,
@@ -578,11 +909,7 @@ describe("AssistantConfigSchema", () => {
578
909
  const result = AssistantConfigSchema.parse({});
579
910
  const llm = result.workspaceGit.commitMessageLLM;
580
911
  expect(llm.enabled).toBe(false);
581
- expect(llm.useConfiguredProvider).toBe(true);
582
- expect(llm.providerFastModelOverrides).toEqual({});
583
912
  expect(llm.timeoutMs).toBe(600);
584
- expect(llm.maxTokens).toBe(120);
585
- expect(llm.temperature).toBe(0.2);
586
913
  expect(llm.maxFilesInPrompt).toBe(30);
587
914
  expect(llm.maxDiffBytes).toBe(12000);
588
915
  expect(llm.minRemainingTurnBudgetMs).toBe(1000);
@@ -595,13 +922,6 @@ describe("AssistantConfigSchema", () => {
595
922
  expect(result.success).toBe(false);
596
923
  });
597
924
 
598
- test("rejects commitMessageLLM.temperature > 2", () => {
599
- const result = AssistantConfigSchema.safeParse({
600
- workspaceGit: { commitMessageLLM: { temperature: 2.5 } },
601
- });
602
- expect(result.success).toBe(false);
603
- });
604
-
605
925
  test("breaker settings have correct defaults", () => {
606
926
  const result = AssistantConfigSchema.parse({});
607
927
  const breaker = result.workspaceGit.commitMessageLLM.breaker;
@@ -616,14 +936,12 @@ describe("AssistantConfigSchema", () => {
616
936
  commitMessageLLM: {
617
937
  enabled: true,
618
938
  timeoutMs: 1000,
619
- temperature: 0.5,
620
939
  breaker: { openAfterFailures: 5 },
621
940
  },
622
941
  },
623
942
  });
624
943
  expect(result.workspaceGit.commitMessageLLM.enabled).toBe(true);
625
944
  expect(result.workspaceGit.commitMessageLLM.timeoutMs).toBe(1000);
626
- expect(result.workspaceGit.commitMessageLLM.temperature).toBe(0.5);
627
945
  expect(result.workspaceGit.commitMessageLLM.breaker.openAfterFailures).toBe(
628
946
  5,
629
947
  );
@@ -633,18 +951,18 @@ describe("AssistantConfigSchema", () => {
633
951
  );
634
952
  });
635
953
 
636
- test("rejects commitMessageLLM.temperature < 0", () => {
637
- const result = AssistantConfigSchema.safeParse({
638
- workspaceGit: { commitMessageLLM: { temperature: -0.1 } },
639
- });
640
- expect(result.success).toBe(false);
641
- });
642
-
643
- test("rejects non-integer commitMessageLLM.maxTokens", () => {
644
- const result = AssistantConfigSchema.safeParse({
645
- workspaceGit: { commitMessageLLM: { maxTokens: 3.5 } },
954
+ test("ignores legacy commitMessageLLM.{maxTokens,temperature} keys", () => {
955
+ // PR 19 removed maxTokens/temperature from the schema; Zod silently
956
+ // strips them on parse. Migration 039 erases them from disk so they
957
+ // don't accumulate over time.
958
+ const result = AssistantConfigSchema.parse({
959
+ workspaceGit: {
960
+ commitMessageLLM: { maxTokens: 200, temperature: 0.5 },
961
+ },
646
962
  });
647
- expect(result.success).toBe(false);
963
+ const cm = result.workspaceGit.commitMessageLLM as Record<string, unknown>;
964
+ expect(cm.maxTokens).toBeUndefined();
965
+ expect(cm.temperature).toBeUndefined();
648
966
  });
649
967
 
650
968
  // ── Calls config ────────────────────────────────────────────────────
@@ -803,16 +1121,13 @@ describe("AssistantConfigSchema", () => {
803
1121
  ).toBeUndefined();
804
1122
  });
805
1123
 
806
- test("accepts optional calls.model", () => {
1124
+ test("legacy calls.model key is stripped after PR 19 cleanup", () => {
1125
+ // calls.model moved to llm.callSites.callAgent.model in PR 4 and the
1126
+ // legacy field was removed in PR 19. Zod silently strips unknown keys.
807
1127
  const result = AssistantConfigSchema.parse({
808
1128
  calls: { model: "claude-haiku-4-5-20251001" },
809
1129
  });
810
- expect(result.calls.model).toBe("claude-haiku-4-5-20251001");
811
- });
812
-
813
- test("calls.model is undefined by default", () => {
814
- const result = AssistantConfigSchema.parse({});
815
- expect(result.calls.model).toBeUndefined();
1130
+ expect((result.calls as Record<string, unknown>).model).toBeUndefined();
816
1131
  });
817
1132
 
818
1133
  // ── Caller identity config ────────────────────────────────────────
@@ -1938,28 +2253,27 @@ describe("loadConfig with schema validation", () => {
1938
2253
  // intermittently trigger unhandled ENOENT in CI if the directory is removed.
1939
2254
  test("loads valid config", () => {
1940
2255
  writeConfig({
1941
- services: {
1942
- inference: { provider: "openai", model: "gpt-4" },
2256
+ llm: {
2257
+ default: { provider: "openai", model: "gpt-4", maxTokens: 4096 },
1943
2258
  },
1944
- maxTokens: 4096,
1945
2259
  });
1946
2260
  const config = loadConfig();
1947
- expect(config.services.inference.provider).toBe("openai");
1948
- expect(config.services.inference.model).toBe("gpt-4");
1949
- expect(config.maxTokens).toBe(4096);
2261
+ expect(config.llm.default.provider).toBe("openai");
2262
+ expect(config.llm.default.model).toBe("gpt-4");
2263
+ expect(config.llm.default.maxTokens).toBe(4096);
1950
2264
  });
1951
2265
 
1952
2266
  test("applies defaults for missing fields", () => {
1953
2267
  writeConfig({});
1954
2268
  const config = loadConfig();
1955
- expect(config.services.inference.provider).toBe("anthropic");
1956
- expect(config.services.inference.model).toBe("claude-opus-4-6");
1957
- expect(config.maxTokens).toBe(64000);
1958
- expect(config.thinking).toEqual({
2269
+ expect(config.llm.default.provider).toBe("anthropic");
2270
+ expect(config.llm.default.model).toBe("claude-sonnet-4-6");
2271
+ expect(config.llm.default.maxTokens).toBe(64000);
2272
+ expect(config.llm.default.thinking).toEqual({
1959
2273
  enabled: true,
1960
2274
  streamThinking: true,
1961
2275
  });
1962
- expect(config.contextWindow).toEqual({
2276
+ expect(config.llm.default.contextWindow).toEqual({
1963
2277
  enabled: true,
1964
2278
  maxInputTokens: 200000,
1965
2279
  targetBudgetRatio: 0.3,
@@ -1977,16 +2291,16 @@ describe("loadConfig with schema validation", () => {
1977
2291
 
1978
2292
  test("falls back to default for invalid provider", () => {
1979
2293
  writeConfig({
1980
- services: { inference: { provider: "invalid-provider" } },
2294
+ llm: { default: { provider: "invalid-provider" } },
1981
2295
  });
1982
2296
  const config = loadConfig();
1983
- expect(config.services.inference.provider).toBe("anthropic");
2297
+ expect(config.llm.default.provider).toBe("anthropic");
1984
2298
  });
1985
2299
 
1986
2300
  test("falls back to default for invalid maxTokens", () => {
1987
- writeConfig({ maxTokens: -100 });
2301
+ writeConfig({ llm: { default: { maxTokens: -100 } } });
1988
2302
  const config = loadConfig();
1989
- expect(config.maxTokens).toBe(64000);
2303
+ expect(config.llm.default.maxTokens).toBe(64000);
1990
2304
  });
1991
2305
 
1992
2306
  test("falls back to defaults for invalid nested values", () => {
@@ -2001,23 +2315,26 @@ describe("loadConfig with schema validation", () => {
2001
2315
 
2002
2316
  test("preserves valid fields when other fields are invalid", () => {
2003
2317
  writeConfig({
2004
- services: {
2005
- inference: { provider: "openai", model: "gpt-4" },
2318
+ llm: {
2319
+ default: {
2320
+ provider: "openai",
2321
+ model: "gpt-4",
2322
+ maxTokens: -1,
2323
+ thinking: { enabled: true },
2324
+ },
2006
2325
  },
2007
- maxTokens: -1,
2008
- thinking: { enabled: true },
2009
2326
  });
2010
2327
  const config = loadConfig();
2011
- expect(config.services.inference.provider).toBe("openai");
2012
- expect(config.services.inference.model).toBe("gpt-4");
2013
- expect(config.thinking.enabled).toBe(true);
2014
- expect(config.maxTokens).toBe(64000);
2328
+ expect(config.llm.default.provider).toBe("openai");
2329
+ expect(config.llm.default.model).toBe("gpt-4");
2330
+ expect(config.llm.default.thinking.enabled).toBe(true);
2331
+ expect(config.llm.default.maxTokens).toBe(64000);
2015
2332
  });
2016
2333
 
2017
2334
  test("handles no config file", () => {
2018
2335
  const config = loadConfig();
2019
- expect(config.services.inference.provider).toBe("anthropic");
2020
- expect(config.maxTokens).toBe(64000);
2336
+ expect(config.llm.default.provider).toBe("anthropic");
2337
+ expect(config.llm.default.maxTokens).toBe(64000);
2021
2338
  });
2022
2339
 
2023
2340
  test("partial nested objects get defaults for missing fields", () => {
@@ -2038,11 +2355,15 @@ describe("loadConfig with schema validation", () => {
2038
2355
 
2039
2356
  test("falls back for invalid contextWindow relationship", () => {
2040
2357
  writeConfig({
2041
- contextWindow: { targetBudgetRatio: 0.8, compactThreshold: 0.8 },
2358
+ llm: {
2359
+ default: {
2360
+ contextWindow: { targetBudgetRatio: 0.8, compactThreshold: 0.8 },
2361
+ },
2362
+ },
2042
2363
  });
2043
2364
  const config = loadConfig();
2044
- expect(config.contextWindow.targetBudgetRatio).toBe(0.3);
2045
- expect(config.contextWindow.compactThreshold).toBe(0.8);
2365
+ expect(config.llm.default.contextWindow.targetBudgetRatio).toBe(0.3);
2366
+ expect(config.llm.default.contextWindow.compactThreshold).toBe(0.8);
2046
2367
  });
2047
2368
 
2048
2369
  test("falls back for invalid rateLimit values", () => {
@@ -2065,6 +2386,11 @@ describe("loadConfig with schema validation", () => {
2065
2386
  expect(config.permissions).toEqual({
2066
2387
  mode: "workspace",
2067
2388
  hostAccess: false,
2389
+ autoApproveUpTo: {
2390
+ conversation: "low",
2391
+ background: "medium",
2392
+ headless: "none",
2393
+ },
2068
2394
  });
2069
2395
  });
2070
2396
 
@@ -2103,13 +2429,13 @@ describe("loadConfig with schema validation", () => {
2103
2429
  // Only activeHoursStart is set. The superRefine must emit the issue so
2104
2430
  // the loader's delete-and-retry can strip the set field; otherwise the
2105
2431
  // mismatch persists and the config falls back to full defaults (which
2106
- // would reset maxTokens below to 64000).
2432
+ // would reset llm.default.maxTokens below to 64000).
2107
2433
  writeConfig({
2108
- maxTokens: 4096,
2434
+ llm: { default: { maxTokens: 4096 } },
2109
2435
  filing: { activeHoursStart: 8 },
2110
2436
  });
2111
2437
  const config = loadConfig();
2112
- expect(config.maxTokens).toBe(4096);
2438
+ expect(config.llm.default.maxTokens).toBe(4096);
2113
2439
  expect(config.filing.activeHoursStart).toBeNull();
2114
2440
  expect(config.filing.activeHoursEnd).toBeNull();
2115
2441
  });
@@ -2117,13 +2443,13 @@ describe("loadConfig with schema validation", () => {
2117
2443
  test("recovers from partial heartbeat.activeHours without wiping unrelated fields", () => {
2118
2444
  // activeHoursStart is explicitly nulled while activeHoursEnd defaults to
2119
2445
  // 22 — a mismatch. Dual-emit strips both sides; both defaults restore
2120
- // (8, 22). maxTokens is unaffected.
2446
+ // (8, 22). llm.default.maxTokens is unaffected.
2121
2447
  writeConfig({
2122
- maxTokens: 4096,
2448
+ llm: { default: { maxTokens: 4096 } },
2123
2449
  heartbeat: { activeHoursStart: null },
2124
2450
  });
2125
2451
  const config = loadConfig();
2126
- expect(config.maxTokens).toBe(4096);
2452
+ expect(config.llm.default.maxTokens).toBe(4096);
2127
2453
  expect(config.heartbeat.activeHoursStart).toBe(8);
2128
2454
  expect(config.heartbeat.activeHoursEnd).toBe(22);
2129
2455
  });
@@ -2131,14 +2457,14 @@ describe("loadConfig with schema validation", () => {
2131
2457
  test("recovers from heartbeat.activeHours null-mismatch where explicit value equals opposite default", () => {
2132
2458
  // { start: null, end: 8 } — single-emit on the null side would strip
2133
2459
  // start, the default 8 would restore it, and the equal-hours check would
2134
- // fire, cascading to a full defaults reset that wipes maxTokens.
2460
+ // fire, cascading to a full defaults reset that wipes llm.default.maxTokens.
2135
2461
  // Dual-emit strips both sides in one pass.
2136
2462
  writeConfig({
2137
- maxTokens: 4096,
2463
+ llm: { default: { maxTokens: 4096 } },
2138
2464
  heartbeat: { activeHoursStart: null, activeHoursEnd: 8 },
2139
2465
  });
2140
2466
  const config = loadConfig();
2141
- expect(config.maxTokens).toBe(4096);
2467
+ expect(config.llm.default.maxTokens).toBe(4096);
2142
2468
  expect(config.heartbeat.activeHoursStart).toBe(8);
2143
2469
  expect(config.heartbeat.activeHoursEnd).toBe(22);
2144
2470
  });
@@ -2146,11 +2472,11 @@ describe("loadConfig with schema validation", () => {
2146
2472
  test("recovers from heartbeat.activeHours null-mismatch on the end side", () => {
2147
2473
  // { start: 22, end: null } — same cascade class as above, mirrored.
2148
2474
  writeConfig({
2149
- maxTokens: 4096,
2475
+ llm: { default: { maxTokens: 4096 } },
2150
2476
  heartbeat: { activeHoursStart: 22, activeHoursEnd: null },
2151
2477
  });
2152
2478
  const config = loadConfig();
2153
- expect(config.maxTokens).toBe(4096);
2479
+ expect(config.llm.default.maxTokens).toBe(4096);
2154
2480
  expect(config.heartbeat.activeHoursStart).toBe(8);
2155
2481
  expect(config.heartbeat.activeHoursEnd).toBe(22);
2156
2482
  });
@@ -2159,13 +2485,13 @@ describe("loadConfig with schema validation", () => {
2159
2485
  // { start: 22, end: 22 } — both equal to the default for end. Single-emit
2160
2486
  // on one path would strip one side, the default would recreate the
2161
2487
  // equal-hours mismatch, and the loader would fall back to full defaults,
2162
- // wiping maxTokens. Dual-emit strips both sides at once.
2488
+ // wiping llm.default.maxTokens. Dual-emit strips both sides at once.
2163
2489
  writeConfig({
2164
- maxTokens: 4096,
2490
+ llm: { default: { maxTokens: 4096 } },
2165
2491
  heartbeat: { activeHoursStart: 22, activeHoursEnd: 22 },
2166
2492
  });
2167
2493
  const config = loadConfig();
2168
- expect(config.maxTokens).toBe(4096);
2494
+ expect(config.llm.default.maxTokens).toBe(4096);
2169
2495
  expect(config.heartbeat.activeHoursStart).toBe(8);
2170
2496
  expect(config.heartbeat.activeHoursEnd).toBe(22);
2171
2497
  });
@@ -2174,14 +2500,14 @@ describe("loadConfig with schema validation", () => {
2174
2500
  // activeHoursStart === activeHoursEnd is invalid (empty window). Filing's
2175
2501
  // defaults are null/null, so single-emit on one path would strip one side
2176
2502
  // and the null default would recreate a mismatch — cascading to a full
2177
- // defaults reset that wipes maxTokens. Dual-emit strips both sides so
2178
- // both defaults restore to null.
2503
+ // defaults reset that wipes llm.default.maxTokens. Dual-emit strips both
2504
+ // sides so both defaults restore to null.
2179
2505
  writeConfig({
2180
- maxTokens: 1234,
2506
+ llm: { default: { maxTokens: 1234 } },
2181
2507
  filing: { activeHoursStart: 5, activeHoursEnd: 5 },
2182
2508
  });
2183
2509
  const config = loadConfig();
2184
- expect(config.maxTokens).toBe(1234);
2510
+ expect(config.llm.default.maxTokens).toBe(1234);
2185
2511
  expect(config.filing.activeHoursStart).toBeNull();
2186
2512
  expect(config.filing.activeHoursEnd).toBeNull();
2187
2513
  });
@@ -2201,7 +2527,7 @@ describe("loadConfig with schema validation", () => {
2201
2527
  expect(
2202
2528
  (config.calls.voice as Record<string, unknown>).ttsProvider,
2203
2529
  ).toBeUndefined();
2204
- expect(config.calls.model).toBeUndefined();
2530
+ expect((config.calls as Record<string, unknown>).model).toBeUndefined();
2205
2531
  expect(config.calls.callerIdentity).toEqual({
2206
2532
  allowPerCallOverride: true,
2207
2533
  });