@vellumai/assistant 0.8.1 → 0.8.3

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 (630) hide show
  1. package/ARCHITECTURE.md +13 -19
  2. package/Dockerfile +75 -1
  3. package/bun.lock +11 -1
  4. package/docker-entrypoint.sh +17 -0
  5. package/docker-init-apt-root.sh +167 -0
  6. package/docker-kata-apt-env.sh +39 -0
  7. package/docs/plugins.md +88 -47
  8. package/docs/skills.md +9 -7
  9. package/examples/plugins/echo/README.md +27 -27
  10. package/examples/plugins/echo/package.json +3 -0
  11. package/examples/plugins/echo/register.ts +31 -31
  12. package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
  13. package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
  14. package/openapi.yaml +642 -5
  15. package/package.json +3 -1
  16. package/scripts/generate-openapi.ts +83 -10
  17. package/scripts/sync-llm-catalog.ts +2 -2
  18. package/scripts/sync-web-search-catalog.ts +47 -25
  19. package/src/__tests__/agent-image-optimize.test.ts +11 -3
  20. package/src/__tests__/agent-loop-exit-reason.test.ts +272 -0
  21. package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
  23. package/src/__tests__/anthropic-provider.test.ts +45 -0
  24. package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
  25. package/src/__tests__/app-executors.test.ts +220 -4
  26. package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
  27. package/src/__tests__/bundled-asset.test.ts +6 -6
  28. package/src/__tests__/channel-availability-routes.test.ts +206 -0
  29. package/src/__tests__/channel-delivery-store.test.ts +289 -1
  30. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
  31. package/src/__tests__/clawhub.test.ts +75 -16
  32. package/src/__tests__/compactor-tail-resolution.test.ts +147 -0
  33. package/src/__tests__/config-get-vision-flag.test.ts +136 -0
  34. package/src/__tests__/config-loader-backfill.test.ts +115 -18
  35. package/src/__tests__/config-schema.test.ts +21 -0
  36. package/src/__tests__/config-set-route.test.ts +80 -0
  37. package/src/__tests__/config-sounds-sync.test.ts +97 -0
  38. package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
  39. package/src/__tests__/context-search-conversations-source.test.ts +117 -2
  40. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
  41. package/src/__tests__/context-search-workspace-source.test.ts +7 -0
  42. package/src/__tests__/context-token-estimator.test.ts +31 -65
  43. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  44. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  45. package/src/__tests__/conversation-agent-loop-overflow.test.ts +92 -92
  46. package/src/__tests__/conversation-agent-loop.test.ts +59 -1
  47. package/src/__tests__/conversation-error.test.ts +42 -3
  48. package/src/__tests__/conversation-fork-crud.test.ts +82 -0
  49. package/src/__tests__/conversation-inference-profile-route.test.ts +40 -4
  50. package/src/__tests__/conversation-lifecycle.test.ts +173 -0
  51. package/src/__tests__/conversation-media-retry.test.ts +19 -8
  52. package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
  53. package/src/__tests__/conversation-pairing.test.ts +54 -0
  54. package/src/__tests__/conversation-process-callsite.test.ts +4 -1
  55. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
  56. package/src/__tests__/conversation-queue.test.ts +4 -1
  57. package/src/__tests__/conversation-runtime-assembly.test.ts +102 -13
  58. package/src/__tests__/conversation-slash-queue.test.ts +59 -1
  59. package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
  60. package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
  61. package/src/__tests__/conversation-sync-tags.test.ts +235 -0
  62. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  63. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  64. package/src/__tests__/credential-security-invariants.test.ts +3 -2
  65. package/src/__tests__/date-context.test.ts +45 -0
  66. package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
  67. package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
  68. package/src/__tests__/disk-pressure-tools.test.ts +1 -0
  69. package/src/__tests__/dm-backfill.test.ts +121 -10
  70. package/src/__tests__/document-tool-security.test.ts +258 -0
  71. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  72. package/src/__tests__/edit-propagation.test.ts +33 -0
  73. package/src/__tests__/empty-response-pipeline.test.ts +0 -4
  74. package/src/__tests__/external-plugin-loader.test.ts +151 -55
  75. package/src/__tests__/filing-service.test.ts +140 -0
  76. package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
  77. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
  78. package/src/__tests__/guardian-dispatch.test.ts +1 -0
  79. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
  80. package/src/__tests__/heartbeat-service.test.ts +24 -164
  81. package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
  82. package/src/__tests__/helpers/tar-fixtures.ts +39 -0
  83. package/src/__tests__/helpers/wait-for.ts +21 -0
  84. package/src/__tests__/history-repair-pipeline.test.ts +0 -3
  85. package/src/__tests__/history-repair.test.ts +73 -0
  86. package/src/__tests__/host-app-control-proxy.test.ts +507 -10
  87. package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
  88. package/src/__tests__/image-credentials.test.ts +1 -1
  89. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  90. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +1 -1
  91. package/src/__tests__/inference-profile-reaper.test.ts +4 -2
  92. package/src/__tests__/inference-profile-session-handler.test.ts +18 -6
  93. package/src/__tests__/inference-profile-session-ipc.test.ts +17 -5
  94. package/src/__tests__/injector-background-turn.test.ts +153 -0
  95. package/src/__tests__/injector-chain.test.ts +15 -8
  96. package/src/__tests__/install-skill-routing.test.ts +155 -37
  97. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +99 -3
  98. package/src/__tests__/list-messages-page-latest.test.ts +55 -0
  99. package/src/__tests__/llm-call-pipeline.test.ts +0 -3
  100. package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
  101. package/src/__tests__/llm-catalog-parity.test.ts +58 -13
  102. package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
  103. package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
  104. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +36 -0
  105. package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
  106. package/src/__tests__/llm-resolver.test.ts +255 -2
  107. package/src/__tests__/llm-usage-store.test.ts +114 -0
  108. package/src/__tests__/managed-profile-guard.test.ts +41 -29
  109. package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
  110. package/src/__tests__/managed-store.test.ts +84 -192
  111. package/src/__tests__/media-generate-image.test.ts +1 -1
  112. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
  113. package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
  114. package/src/__tests__/notification-decision-fallback.test.ts +0 -91
  115. package/src/__tests__/notification-decision-strategy.test.ts +14 -31
  116. package/src/__tests__/notification-deep-link.test.ts +15 -0
  117. package/src/__tests__/notification-guardian-path.test.ts +1 -2
  118. package/src/__tests__/notification-platform-adapter.test.ts +5 -4
  119. package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
  120. package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
  121. package/src/__tests__/oauth-commands-routes.test.ts +168 -16
  122. package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
  123. package/src/__tests__/openai-provider.test.ts +242 -3
  124. package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
  125. package/src/__tests__/openrouter-provider-only.test.ts +51 -3
  126. package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
  127. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
  128. package/src/__tests__/persistence-pipeline.test.ts +0 -2
  129. package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +7 -2
  130. package/src/__tests__/platform.test.ts +2 -0
  131. package/src/__tests__/plugin-api-shim.test.ts +125 -0
  132. package/src/__tests__/plugin-bootstrap.test.ts +10 -36
  133. package/src/__tests__/plugin-external-api.test.ts +68 -0
  134. package/src/__tests__/plugin-registry.test.ts +0 -77
  135. package/src/__tests__/plugin-route-contribution.test.ts +0 -1
  136. package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
  137. package/src/__tests__/plugin-tool-contribution.test.ts +16 -15
  138. package/src/__tests__/plugin-types.test.ts +3 -13
  139. package/src/__tests__/process-message-background-slack.test.ts +8 -1
  140. package/src/__tests__/process-message-display-content.test.ts +421 -0
  141. package/src/__tests__/provider-catalog-visibility.test.ts +158 -0
  142. package/src/__tests__/provider-error-scenarios.test.ts +111 -0
  143. package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +33 -31
  144. package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
  145. package/src/__tests__/schedule-routes.test.ts +50 -3
  146. package/src/__tests__/schedule-store.test.ts +94 -0
  147. package/src/__tests__/scheduler-reuse-conversation.test.ts +54 -7
  148. package/src/__tests__/schema-transforms.test.ts +20 -0
  149. package/src/__tests__/search-skills-unified.test.ts +0 -5
  150. package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +1 -1
  151. package/src/__tests__/server-history-render.test.ts +43 -0
  152. package/src/__tests__/skill-load-feature-flag.test.ts +0 -12
  153. package/src/__tests__/skill-load-tool.test.ts +27 -89
  154. package/src/__tests__/skill-memory.test.ts +23 -3
  155. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
  156. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
  157. package/src/__tests__/skills-install-extract.test.ts +49 -38
  158. package/src/__tests__/skills-install-staging.test.ts +159 -0
  159. package/src/__tests__/skills-uninstall.test.ts +9 -41
  160. package/src/__tests__/skills.test.ts +51 -58
  161. package/src/__tests__/slack-channel-config.test.ts +9 -0
  162. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  163. package/src/__tests__/system-prompt.test.ts +670 -63
  164. package/src/__tests__/terminal-tools.test.ts +28 -1
  165. package/src/__tests__/thread-backfill.test.ts +557 -27
  166. package/src/__tests__/title-generate-pipeline.test.ts +0 -13
  167. package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
  168. package/src/__tests__/tool-error-pipeline.test.ts +0 -3
  169. package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
  170. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  171. package/src/__tests__/tool-executor.test.ts +16 -4
  172. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
  173. package/src/__tests__/turn-events-store.test.ts +256 -0
  174. package/src/__tests__/twilio-routes.test.ts +4 -0
  175. package/src/__tests__/user-plugin-loader.test.ts +0 -7
  176. package/src/__tests__/voice-session-bridge.test.ts +198 -0
  177. package/src/__tests__/web-search-catalog-parity.test.ts +32 -10
  178. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +115 -3
  179. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +50 -0
  180. package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
  181. package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
  182. package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
  183. package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
  184. package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
  185. package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
  186. package/src/a2a/__tests__/agent-card.test.ts +98 -0
  187. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
  188. package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
  189. package/src/a2a/__tests__/task-store.test.ts +246 -0
  190. package/src/a2a/agent-card.ts +58 -0
  191. package/src/a2a/feature-gate.ts +8 -0
  192. package/src/a2a/protocol-constants.ts +21 -0
  193. package/src/a2a/protocol-errors.ts +50 -0
  194. package/src/a2a/protocol-types.ts +162 -0
  195. package/src/a2a/task-store.ts +168 -0
  196. package/src/acp/resolve-agent.ts +1 -1
  197. package/src/agent/image-optimize.ts +13 -5
  198. package/src/agent/loop.ts +167 -18
  199. package/src/calls/voice-session-bridge.ts +61 -42
  200. package/src/channels/config.ts +9 -0
  201. package/src/channels/types.ts +122 -0
  202. package/src/cli/__tests__/unknown-command.test.ts +24 -0
  203. package/src/cli/commands/__tests__/changelog.test.ts +304 -319
  204. package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
  205. package/src/cli/commands/__tests__/schedules.test.ts +960 -0
  206. package/src/cli/commands/changelog.ts +106 -42
  207. package/src/cli/commands/conversations.ts +102 -17
  208. package/src/cli/commands/default-action.ts +10 -53
  209. package/src/cli/commands/notifications.ts +388 -346
  210. package/src/cli/commands/plugins.ts +252 -0
  211. package/src/cli/commands/schedules.ts +683 -0
  212. package/src/cli/commands/telemetry.ts +40 -0
  213. package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
  214. package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
  215. package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
  216. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
  217. package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
  218. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
  219. package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
  220. package/src/cli/lib/cli-colors.ts +12 -0
  221. package/src/cli/lib/confirm-prompt.ts +79 -0
  222. package/src/cli/lib/install-from-github.ts +303 -0
  223. package/src/cli/lib/list-installed-plugins.ts +137 -0
  224. package/src/cli/lib/search-plugins.ts +163 -0
  225. package/src/cli/lib/uninstall-plugin.ts +82 -0
  226. package/src/cli/lib/unknown-command.ts +111 -0
  227. package/src/cli/program.ts +52 -2
  228. package/src/config/assistant-feature-flags.ts +24 -54
  229. package/src/config/bundled-skills/app-builder/SKILL.md +140 -22
  230. package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
  231. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
  232. package/src/config/bundled-skills/document/SKILL.md +23 -3
  233. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  234. package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
  235. package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
  236. package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
  237. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
  238. package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
  239. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  240. package/src/config/bundled-tool-registry.ts +6 -0
  241. package/src/config/call-site-defaults.ts +105 -0
  242. package/src/config/feature-flag-registry.json +41 -9
  243. package/src/config/llm-resolver.ts +52 -1
  244. package/src/config/loader.ts +64 -38
  245. package/src/config/schema.ts +9 -10
  246. package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
  247. package/src/config/schemas/__tests__/memory-v2.test.ts +3 -3
  248. package/src/config/schemas/channels.ts +17 -0
  249. package/src/config/schemas/compaction.ts +28 -0
  250. package/src/config/schemas/conversations.ts +10 -0
  251. package/src/config/schemas/heartbeat.ts +23 -0
  252. package/src/config/schemas/llm-request-logs.ts +31 -7
  253. package/src/config/schemas/llm.ts +1 -0
  254. package/src/config/schemas/memory-retrieval.ts +18 -0
  255. package/src/config/schemas/memory-retrospective.ts +1 -1
  256. package/src/config/schemas/memory-v2.ts +4 -4
  257. package/src/config/schemas/memory.ts +3 -1
  258. package/src/config/schemas/tools.ts +14 -0
  259. package/src/config/seed-inference-profiles.ts +99 -29
  260. package/src/config/skills.ts +3 -96
  261. package/src/context/compactor.ts +1107 -0
  262. package/src/context/token-estimator.ts +34 -36
  263. package/src/context/window-manager.ts +197 -1520
  264. package/src/credential-execution/managed-catalog.ts +37 -0
  265. package/src/credential-health/credential-health-service.ts +280 -19
  266. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +33 -18
  267. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
  268. package/src/daemon/__tests__/conversation-tool-setup.test.ts +74 -0
  269. package/src/daemon/approval-generators.ts +8 -6
  270. package/src/daemon/config-watcher.ts +94 -31
  271. package/src/daemon/conversation-agent-loop-handlers.ts +78 -0
  272. package/src/daemon/conversation-agent-loop.ts +198 -11
  273. package/src/daemon/conversation-error.ts +171 -37
  274. package/src/daemon/conversation-lifecycle.ts +53 -40
  275. package/src/daemon/conversation-messaging.ts +25 -6
  276. package/src/daemon/conversation-process.ts +49 -12
  277. package/src/daemon/conversation-runtime-assembly.ts +25 -1
  278. package/src/daemon/conversation-slash.ts +12 -5
  279. package/src/daemon/conversation-store.ts +11 -4
  280. package/src/daemon/conversation-tool-setup.ts +39 -7
  281. package/src/daemon/conversation.ts +33 -8
  282. package/src/daemon/date-context.ts +40 -0
  283. package/src/daemon/external-plugins-bootstrap.ts +217 -181
  284. package/src/daemon/first-greeting.ts +22 -2
  285. package/src/daemon/guardian-action-generators.ts +1 -125
  286. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
  287. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
  288. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
  289. package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
  290. package/src/daemon/handlers/config-a2a.ts +289 -0
  291. package/src/daemon/handlers/config-model.ts +6 -5
  292. package/src/daemon/handlers/config-slack-channel.ts +15 -3
  293. package/src/daemon/handlers/conversations.ts +1 -0
  294. package/src/daemon/handlers/shared.ts +14 -5
  295. package/src/daemon/handlers/skills.ts +111 -108
  296. package/src/daemon/history-repair.ts +28 -1
  297. package/src/daemon/host-app-control-proxy.ts +153 -27
  298. package/src/daemon/host-proxy-preactivation.ts +85 -18
  299. package/src/daemon/lifecycle.ts +89 -91
  300. package/src/daemon/meet-host-supervisor.ts +5 -4
  301. package/src/daemon/memory-v2-startup.ts +85 -0
  302. package/src/daemon/message-protocol.ts +1 -0
  303. package/src/daemon/message-types/conversations.ts +25 -0
  304. package/src/daemon/message-types/messages.ts +61 -0
  305. package/src/daemon/message-types/notifications.ts +21 -0
  306. package/src/daemon/message-types/subagents.ts +1 -0
  307. package/src/daemon/message-types/sync.ts +1 -0
  308. package/src/daemon/pkb-reminder-builder.test.ts +11 -54
  309. package/src/daemon/pkb-reminder-builder.ts +5 -20
  310. package/src/daemon/plugin-source-watcher.ts +146 -0
  311. package/src/daemon/process-message.ts +24 -3
  312. package/src/daemon/server.ts +11 -2
  313. package/src/daemon/skill-memory-refresh.ts +33 -0
  314. package/src/daemon/wake-target-adapter.ts +2 -0
  315. package/src/documents/document-store.ts +221 -3
  316. package/src/embedded/plugin-api.ts +40 -0
  317. package/src/export/__tests__/transcript-formatter.test.ts +121 -0
  318. package/src/export/transcript-formatter.ts +54 -20
  319. package/src/filing/filing-service.ts +39 -0
  320. package/src/heartbeat/__tests__/heartbeat-service.test.ts +135 -6
  321. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  322. package/src/heartbeat/heartbeat-service.ts +73 -189
  323. package/src/home/__tests__/feed-types.test.ts +80 -0
  324. package/src/home/feed-types.ts +36 -2
  325. package/src/home/post-connect-feed.ts +1 -0
  326. package/src/index.ts +18 -1
  327. package/src/ipc/cli-client.ts +147 -45
  328. package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
  329. package/src/mcp/client.ts +20 -4
  330. package/src/media/image-credentials.ts +3 -3
  331. package/src/memory/__tests__/bookmark-crud.test.ts +33 -27
  332. package/src/memory/__tests__/conversation-queries.test.ts +483 -0
  333. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
  334. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
  335. package/src/memory/__tests__/memory-retrospective-job.test.ts +87 -4
  336. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +119 -14
  337. package/src/memory/__tests__/message-content.test.ts +35 -0
  338. package/src/memory/bookmark-crud.ts +42 -10
  339. package/src/memory/context-search/sources/conversations.ts +62 -2
  340. package/src/memory/context-search/sources/workspace.ts +4 -0
  341. package/src/memory/conversation-crud.ts +63 -19
  342. package/src/memory/conversation-queries.ts +197 -11
  343. package/src/memory/conversation-title-service.ts +26 -4
  344. package/src/memory/db-init.ts +12 -0
  345. package/src/memory/delivery-crud.ts +152 -5
  346. package/src/memory/embedding-backend.ts +4 -4
  347. package/src/memory/external-conversation-store.ts +66 -5
  348. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +150 -12
  349. package/src/memory/graph/conversation-graph-memory.ts +49 -21
  350. package/src/memory/graph/tools.ts +9 -40
  351. package/src/memory/indexer.ts +34 -29
  352. package/src/memory/invite-store.ts +53 -0
  353. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +73 -0
  354. package/src/memory/jobs/embed-concept-page.ts +20 -11
  355. package/src/memory/jobs-worker.ts +6 -1
  356. package/src/memory/llm-request-log-source-clickhouse.ts +24 -12
  357. package/src/memory/llm-request-log-source.ts +19 -52
  358. package/src/memory/llm-request-log-store.ts +92 -1
  359. package/src/memory/llm-usage-store.ts +125 -5
  360. package/src/memory/memory-retrospective-enqueue.ts +1 -20
  361. package/src/memory/memory-retrospective-job.ts +33 -6
  362. package/src/memory/memory-retrospective-startup-cleanup.ts +72 -5
  363. package/src/memory/message-content.ts +1 -1
  364. package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
  365. package/src/memory/migrations/229-delete-private-conversations.test.ts +38 -1
  366. package/src/memory/migrations/229-delete-private-conversations.ts +7 -0
  367. package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
  368. package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
  369. package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
  370. package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
  371. package/src/memory/migrations/251-a2a-tasks.ts +49 -0
  372. package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
  373. package/src/memory/migrations/index.ts +9 -0
  374. package/src/memory/migrations/registry.ts +16 -0
  375. package/src/memory/onboarding-events-store.ts +106 -0
  376. package/src/memory/schema/a2a.ts +15 -0
  377. package/src/memory/schema/bookmarks.ts +0 -2
  378. package/src/memory/schema/calls.ts +1 -0
  379. package/src/memory/schema/index.ts +1 -0
  380. package/src/memory/schema/inference.ts +3 -3
  381. package/src/memory/schema/infrastructure.ts +13 -0
  382. package/src/memory/turn-events-store.ts +127 -2
  383. package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
  384. package/src/memory/v2/__tests__/activation.test.ts +0 -8
  385. package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
  386. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
  387. package/src/memory/v2/__tests__/injection.test.ts +288 -11
  388. package/src/memory/v2/__tests__/migration.test.ts +87 -0
  389. package/src/memory/v2/__tests__/page-index.test.ts +83 -0
  390. package/src/memory/v2/__tests__/prompts-router.test.ts +58 -6
  391. package/src/memory/v2/__tests__/qdrant.test.ts +66 -3
  392. package/src/memory/v2/__tests__/router.test.ts +15 -0
  393. package/src/memory/v2/__tests__/skill-store.test.ts +387 -8
  394. package/src/memory/v2/__tests__/static-context.test.ts +12 -1
  395. package/src/memory/v2/activation-store.ts +14 -16
  396. package/src/memory/v2/cli-command-content.ts +19 -0
  397. package/src/memory/v2/cli-command-store.ts +304 -0
  398. package/src/memory/v2/frontmatter-sweep.ts +7 -1
  399. package/src/memory/v2/injection.ts +81 -26
  400. package/src/memory/v2/migration.ts +49 -19
  401. package/src/memory/v2/page-index.ts +63 -8
  402. package/src/memory/v2/prompts/router.ts +11 -8
  403. package/src/memory/v2/prompts/sweep.ts +2 -2
  404. package/src/memory/v2/qdrant.ts +135 -7
  405. package/src/memory/v2/router.ts +9 -8
  406. package/src/memory/v2/skill-store.ts +120 -35
  407. package/src/memory/v2/static-context.ts +4 -4
  408. package/src/memory/v2/types.ts +23 -0
  409. package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
  410. package/src/messaging/providers/a2a/deliver.ts +156 -0
  411. package/src/messaging/providers/gmail/client.ts +9 -2
  412. package/src/messaging/providers/index.ts +11 -2
  413. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
  414. package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
  415. package/src/messaging/providers/slack/adapter.ts +43 -5
  416. package/src/messaging/providers/slack/client.ts +27 -0
  417. package/src/messaging/providers/slack/deep-link.ts +65 -0
  418. package/src/messaging/providers/slack/download.ts +104 -0
  419. package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
  420. package/src/messaging/providers/slack/message-metadata.ts +27 -0
  421. package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
  422. package/src/messaging/providers/slack/render-transcript.ts +69 -5
  423. package/src/messaging/providers/slack/types.ts +20 -1
  424. package/src/notifications/__tests__/broadcaster.test.ts +203 -0
  425. package/src/notifications/__tests__/decision-engine.test.ts +283 -0
  426. package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
  427. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  428. package/src/notifications/__tests__/home-feed-side-effect.test.ts +430 -7
  429. package/src/notifications/adapters/macos.ts +12 -2
  430. package/src/notifications/broadcaster.ts +29 -4
  431. package/src/notifications/conversation-pairing.ts +2 -1
  432. package/src/notifications/copy-composer.ts +17 -64
  433. package/src/notifications/decision-engine.ts +113 -45
  434. package/src/notifications/deterministic-checks.ts +96 -0
  435. package/src/notifications/emit-signal.ts +21 -1
  436. package/src/notifications/home-feed-side-effect.ts +138 -5
  437. package/src/notifications/signal.ts +3 -5
  438. package/src/notifications/types.ts +8 -0
  439. package/src/oauth/connection-resolver.ts +8 -4
  440. package/src/oauth/platform-connection.test.ts +43 -3
  441. package/src/oauth/platform-connection.ts +19 -6
  442. package/src/oauth/seed-providers.ts +10 -1
  443. package/src/permissions/checker.ts +2 -0
  444. package/src/permissions/ipc-risk-types.ts +1 -0
  445. package/src/permissions/question-prompter.test.ts +416 -0
  446. package/src/permissions/question-prompter.ts +294 -0
  447. package/src/platform/client.test.ts +1 -1
  448. package/src/platform/client.ts +1 -1
  449. package/src/plugin-api/constants.ts +26 -0
  450. package/src/plugin-api/index.ts +34 -1
  451. package/src/plugin-api/types.ts +104 -22
  452. package/src/plugins/defaults/circuit-breaker.ts +0 -5
  453. package/src/plugins/defaults/compaction.ts +0 -4
  454. package/src/plugins/defaults/empty-response.ts +0 -2
  455. package/src/plugins/defaults/history-repair.ts +0 -2
  456. package/src/plugins/defaults/injectors.ts +74 -22
  457. package/src/plugins/defaults/llm-call.ts +0 -2
  458. package/src/plugins/defaults/memory-retrieval.ts +0 -1
  459. package/src/plugins/defaults/overflow-reduce.ts +0 -1
  460. package/src/plugins/defaults/persistence.ts +0 -2
  461. package/src/plugins/defaults/title-generate.ts +0 -5
  462. package/src/plugins/defaults/token-estimate.ts +0 -2
  463. package/src/plugins/defaults/tool-error.ts +0 -7
  464. package/src/plugins/defaults/tool-execute.ts +0 -2
  465. package/src/plugins/defaults/tool-result-truncate.ts +0 -4
  466. package/src/plugins/ensure-plugin-api-shim.ts +96 -0
  467. package/src/plugins/external-api.ts +104 -0
  468. package/src/plugins/external-plugin-loader.ts +187 -42
  469. package/src/plugins/feature-gate.ts +22 -0
  470. package/src/plugins/pipeline.ts +37 -0
  471. package/src/plugins/registry.ts +48 -80
  472. package/src/plugins/types.ts +40 -26
  473. package/src/plugins/user-loader.ts +21 -2
  474. package/src/proactive-artifact/aux-message-injector.ts +11 -0
  475. package/src/proactive-artifact/job.test.ts +37 -5
  476. package/src/prompts/__tests__/system-prompt.test.ts +10 -43
  477. package/src/prompts/__tests__/task-progress-hint-section.test.ts +95 -0
  478. package/src/prompts/normalize-onboarding.ts +27 -0
  479. package/src/prompts/sections.ts +302 -0
  480. package/src/prompts/system-prompt.ts +63 -174
  481. package/src/prompts/templates/BOOTSTRAP.md +17 -1
  482. package/src/prompts/templates/system-sections.ts +164 -0
  483. package/src/providers/__tests__/inference.test.ts +24 -7
  484. package/src/providers/anthropic/client.ts +28 -28
  485. package/src/providers/call-site-routing.ts +24 -6
  486. package/src/providers/connection-resolution.ts +68 -11
  487. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
  488. package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
  489. package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
  490. package/src/providers/inference/adapter-factory.ts +32 -6
  491. package/src/providers/inference/auth.ts +12 -0
  492. package/src/providers/inference/backfill.ts +14 -1
  493. package/src/providers/inference/connections.ts +159 -34
  494. package/src/providers/inference/resolve-auth.ts +14 -4
  495. package/src/providers/model-catalog.ts +249 -12
  496. package/src/providers/model-intents.ts +3 -3
  497. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
  498. package/src/providers/openai/chat-completions-provider.ts +169 -8
  499. package/src/providers/openrouter/client.ts +49 -4
  500. package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -2
  501. package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
  502. package/src/providers/provider-availability.ts +17 -2
  503. package/src/providers/provider-catalog-visibility.ts +38 -0
  504. package/src/providers/provider-send-message.ts +27 -12
  505. package/src/providers/registry.ts +52 -15
  506. package/src/providers/retry.ts +47 -1
  507. package/src/runtime/__tests__/agent-wake.test.ts +152 -0
  508. package/src/runtime/agent-wake.ts +103 -15
  509. package/src/runtime/auth/route-policy.ts +21 -1
  510. package/src/runtime/btw-sidechain.ts +2 -0
  511. package/src/runtime/http-server.ts +7 -16
  512. package/src/runtime/http-types.ts +19 -47
  513. package/src/runtime/migrations/origin-mode.ts +1 -1
  514. package/src/runtime/pending-interactions.ts +1 -0
  515. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +17 -0
  516. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
  517. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +5 -1
  518. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +172 -23
  519. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
  520. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
  521. package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
  522. package/src/runtime/routes/__tests__/tts-routes.test.ts +64 -1
  523. package/src/runtime/routes/acp-routes-list.test.ts +143 -0
  524. package/src/runtime/routes/acp-routes.ts +5 -3
  525. package/src/runtime/routes/auth-routes.ts +1 -1
  526. package/src/runtime/routes/bookmark-routes.ts +5 -3
  527. package/src/runtime/routes/btw-routes.ts +5 -1
  528. package/src/runtime/routes/channel-availability-routes.ts +126 -0
  529. package/src/runtime/routes/consolidation-routes.ts +100 -0
  530. package/src/runtime/routes/conversation-cli-routes.ts +44 -3
  531. package/src/runtime/routes/conversation-list-routes.ts +3 -20
  532. package/src/runtime/routes/conversation-management-routes.ts +17 -42
  533. package/src/runtime/routes/conversation-query-routes.ts +99 -35
  534. package/src/runtime/routes/conversation-routes.ts +97 -11
  535. package/src/runtime/routes/documents-routes.ts +25 -86
  536. package/src/runtime/routes/group-routes.ts +5 -0
  537. package/src/runtime/routes/inbound-conversation.ts +28 -8
  538. package/src/runtime/routes/inbound-message-handler.ts +236 -41
  539. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +111 -0
  540. package/src/runtime/routes/inbound-stages/background-dispatch.ts +32 -1
  541. package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
  542. package/src/runtime/routes/index.ts +8 -0
  543. package/src/runtime/routes/inference-profile-session-handler.ts +17 -44
  544. package/src/runtime/routes/inference-profile-session-reaper.ts +7 -21
  545. package/src/runtime/routes/inference-provider-connection-routes.ts +199 -22
  546. package/src/runtime/routes/integrations/a2a.ts +235 -0
  547. package/src/runtime/routes/integrations/slack/share.ts +4 -52
  548. package/src/runtime/routes/integrations/slack/token.ts +43 -0
  549. package/src/runtime/routes/integrations/twilio.ts +6 -13
  550. package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
  551. package/src/runtime/routes/notification-routes.ts +1 -1
  552. package/src/runtime/routes/oauth-commands-routes.ts +105 -15
  553. package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
  554. package/src/runtime/routes/question-routes.ts +259 -0
  555. package/src/runtime/routes/rename-conversation-routes.ts +2 -33
  556. package/src/runtime/routes/schedule-routes.ts +4 -7
  557. package/src/runtime/routes/subagents-routes.ts +98 -18
  558. package/src/runtime/routes/telemetry-routes.ts +27 -0
  559. package/src/runtime/routes/tts-routes.ts +27 -2
  560. package/src/runtime/routes/workspace-routes.test.ts +43 -0
  561. package/src/runtime/routes/workspace-routes.ts +28 -0
  562. package/src/runtime/services/conversation-serializer.ts +39 -7
  563. package/src/runtime/sync/resource-sync-events.ts +93 -1
  564. package/src/schedule/schedule-store.ts +27 -2
  565. package/src/schedule/scheduler.ts +9 -1
  566. package/src/security/__tests__/untrusted-content.test.ts +86 -0
  567. package/src/security/untrusted-content.ts +93 -8
  568. package/src/skills/catalog-files.ts +1 -1
  569. package/src/skills/catalog-install.ts +233 -116
  570. package/src/skills/clawhub.ts +70 -13
  571. package/src/skills/managed-store.ts +4 -119
  572. package/src/skills/skillssh-registry.ts +27 -48
  573. package/src/subagent/manager.ts +17 -7
  574. package/src/telemetry/types.ts +113 -1
  575. package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
  576. package/src/telemetry/usage-telemetry-reporter.ts +113 -7
  577. package/src/tools/apps/executors.ts +58 -7
  578. package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
  579. package/src/tools/ask-question/ask-question-tool.ts +304 -0
  580. package/src/tools/browser/browser-execution.ts +15 -11
  581. package/src/tools/computer-use/definitions.ts +3 -3
  582. package/src/tools/credentials/vault.ts +1 -1
  583. package/src/tools/document/document-tool.ts +124 -1
  584. package/src/tools/filesystem/edit.ts +1 -1
  585. package/src/tools/filesystem/list.ts +1 -1
  586. package/src/tools/filesystem/read.ts +1 -1
  587. package/src/tools/filesystem/write.ts +5 -2
  588. package/src/tools/host-filesystem/transfer.ts +1 -1
  589. package/src/tools/host-terminal/host-shell.ts +1 -1
  590. package/src/tools/memory/register.ts +1 -9
  591. package/src/tools/permission-checker.ts +1 -1
  592. package/src/tools/registry.ts +17 -7
  593. package/src/tools/schedule/create.ts +2 -2
  594. package/src/tools/schema-transforms.ts +7 -2
  595. package/src/tools/side-effects.ts +1 -0
  596. package/src/tools/skills/delete-managed.ts +4 -4
  597. package/src/tools/skills/execute.ts +1 -1
  598. package/src/tools/skills/scaffold-managed.ts +3 -2
  599. package/src/tools/subagent/notify-parent.ts +1 -1
  600. package/src/tools/system/request-permission.ts +2 -2
  601. package/src/tools/terminal/safe-env.ts +60 -1
  602. package/src/tools/tool-manifest.ts +2 -0
  603. package/src/tools/types.ts +107 -21
  604. package/src/tools/ui-surface/definitions.ts +6 -5
  605. package/src/tts/__tests__/provider-adapters.test.ts +76 -2
  606. package/src/tts/providers/elevenlabs-provider.ts +75 -1
  607. package/src/types/onboarding-context.ts +2 -0
  608. package/src/util/errors.ts +17 -0
  609. package/src/util/platform.ts +10 -0
  610. package/src/watcher/__tests__/engine.test.ts +22 -0
  611. package/src/watcher/engine.ts +6 -2
  612. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +80 -15
  613. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +35 -22
  614. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +3 -1
  615. package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
  616. package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
  617. package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
  618. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
  619. package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
  620. package/src/workspace/migrations/registry.ts +10 -0
  621. package/src/workspace/migrations/runner.ts +39 -9
  622. package/src/workspace/migrations/types.ts +4 -0
  623. package/examples/plugins/echo/bun.lock +0 -25
  624. package/src/__tests__/context-window-manager.test.ts +0 -2481
  625. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
  626. package/src/context/__tests__/compact-prompt.test.ts +0 -63
  627. package/src/context/prompts/compact.md +0 -26
  628. package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
  629. package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
  630. package/src/runtime/guardian-action-conversation-turn.ts +0 -99
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
 
3
3
  import { getCatalogProviderForModel } from "../providers/model-catalog.js";
4
+ import { CALL_SITE_DEFAULTS } from "./call-site-defaults.js";
4
5
  import {
5
6
  type LLMCallSite,
6
7
  LLMConfigBase,
@@ -56,7 +57,9 @@ export function resolveCallSiteConfig(
56
57
  opts.overrideProfile != null
57
58
  ? llm.profiles?.[opts.overrideProfile]
58
59
  : undefined;
59
- const site = llm.callSites?.[callSite];
60
+ const site =
61
+ llm.callSites?.[callSite] ??
62
+ effectiveDefault(callSite, llm, opts.overrideProfile != null);
60
63
 
61
64
  if (callSite === "mainAgent") {
62
65
  appendCallSiteLayers(layers, callSite, llm, site);
@@ -77,6 +80,54 @@ export function resolveCallSiteConfig(
77
80
 
78
81
  type Mergeable = Record<string, unknown>;
79
82
 
83
+ /**
84
+ * Returns the resolved default profile key for a call site, accounting for
85
+ * the `custom-*` user-profile fallback when the managed profile is unavailable.
86
+ */
87
+ export function resolveDefaultProfileKey(
88
+ callSite: LLMCallSite,
89
+ llm: z.infer<typeof LLMSchema>,
90
+ ): string | undefined {
91
+ const dflt = CALL_SITE_DEFAULTS[callSite];
92
+ if (dflt?.profile == null) return undefined;
93
+ const target = llm.profiles?.[dflt.profile];
94
+ if (target != null && target.status !== "disabled") return dflt.profile;
95
+ const customKey = `custom-${dflt.profile}`;
96
+ const customTarget = llm.profiles?.[customKey];
97
+ if (customTarget != null && customTarget.status !== "disabled")
98
+ return customKey;
99
+ return undefined;
100
+ }
101
+
102
+ function effectiveDefault(
103
+ callSite: LLMCallSite,
104
+ llm: z.infer<typeof LLMSchema>,
105
+ hasOverrideProfile = false,
106
+ ): z.infer<typeof LLMSchema>["callSites"][LLMCallSite] | undefined {
107
+ const dflt = CALL_SITE_DEFAULTS[callSite];
108
+ if (dflt == null) return undefined;
109
+ const targetProfile =
110
+ dflt.profile != null ? llm.profiles?.[dflt.profile] : undefined;
111
+ const profileUnavailable =
112
+ dflt.profile != null &&
113
+ (targetProfile == null || targetProfile.status === "disabled");
114
+
115
+ if (profileUnavailable && !hasOverrideProfile) {
116
+ const customKey = `custom-${dflt.profile}`;
117
+ const customProfile = llm.profiles?.[customKey];
118
+ if (customProfile != null && customProfile.status !== "disabled") {
119
+ return { ...dflt, profile: customKey };
120
+ }
121
+ }
122
+
123
+ const stripProfile = hasOverrideProfile || profileUnavailable;
124
+ if (stripProfile) {
125
+ const { profile: _profile, ...rest } = dflt;
126
+ return Object.keys(rest).length > 0 ? rest : undefined;
127
+ }
128
+ return dflt;
129
+ }
130
+
80
131
  function withImpliedProviderForKnownModel(source: Mergeable): Mergeable {
81
132
  if (source.provider !== undefined) return source;
82
133
  const model = source.model;
@@ -25,6 +25,7 @@ const log = getLogger("config");
25
25
  let cached: AssistantConfig | null = null;
26
26
  let cachedFileSignature: ConfigFileSignature | null = null;
27
27
  let loading = false;
28
+ let suppressConfigDiskWritesDepth = 0;
28
29
 
29
30
  type ConfigFileSignature =
30
31
  | {
@@ -683,49 +684,54 @@ export function loadConfig(): AssistantConfig {
683
684
  configFileExisted = false;
684
685
  }
685
686
 
686
- // Warn about and strip deprecated config fields so users know their
687
- // settings are no longer honored rather than silently dropping them.
688
- warnAndStripDeprecatedFields(fileConfig, configPath);
687
+ if (suppressConfigDiskWritesDepth === 0) {
688
+ warnAndStripDeprecatedFields(fileConfig, configPath);
689
+ }
689
690
 
690
691
  // Validate and apply defaults via Zod schema
691
692
  let config = validateWithSchema(fileConfig);
692
693
 
693
- // Managed Gemini embedding defaults migration.
694
- // When on a managed platform (IS_PLATFORM=true) with the feature flag
695
- // enabled and no explicit embedding provider chosen (provider=auto),
696
- // persist Gemini embedding defaults into the raw config file.
697
- // Idempotent: once provider=gemini is written, subsequent loads skip this.
698
- if (config.memory.embeddings.provider === "auto") {
699
- try {
700
- if (
701
- (process.env.IS_PLATFORM === "true" ||
702
- process.env.IS_PLATFORM === "1") &&
703
- isManagedGeminiFFEnabled(config)
704
- ) {
705
- setNestedValue(fileConfig, "memory.embeddings.provider", "gemini");
706
- setNestedValue(
707
- fileConfig,
708
- "memory.embeddings.geminiModel",
709
- "gemini-embedding-2",
710
- );
711
- setNestedValue(
712
- fileConfig,
713
- "memory.embeddings.geminiDimensions",
714
- 3072,
715
- );
716
- setNestedValue(fileConfig, "memory.qdrant.vectorSize", 3072);
717
- writeFileSync(configPath, JSON.stringify(fileConfig, null, 2) + "\n");
718
- log.info(
719
- "Applied managed Gemini embedding defaults (provider=gemini, model=gemini-embedding-2, dimensions=3072, vectorSize=3072)",
694
+ if (suppressConfigDiskWritesDepth === 0) {
695
+ // Managed Gemini embedding defaults migration.
696
+ // When on a managed platform (IS_PLATFORM=true) with the feature flag
697
+ // enabled and no explicit embedding provider chosen (provider=auto),
698
+ // persist Gemini embedding defaults into the raw config file.
699
+ // Idempotent: once provider=gemini is written, subsequent loads skip this.
700
+ if (config.memory.embeddings.provider === "auto") {
701
+ try {
702
+ if (
703
+ (process.env.IS_PLATFORM === "true" ||
704
+ process.env.IS_PLATFORM === "1") &&
705
+ isManagedGeminiFFEnabled(config)
706
+ ) {
707
+ setNestedValue(fileConfig, "memory.embeddings.provider", "gemini");
708
+ setNestedValue(
709
+ fileConfig,
710
+ "memory.embeddings.geminiModel",
711
+ "gemini-embedding-2",
712
+ );
713
+ setNestedValue(
714
+ fileConfig,
715
+ "memory.embeddings.geminiDimensions",
716
+ 3072,
717
+ );
718
+ setNestedValue(fileConfig, "memory.qdrant.vectorSize", 3072);
719
+ writeFileSync(
720
+ configPath,
721
+ JSON.stringify(fileConfig, null, 2) + "\n",
722
+ );
723
+ log.info(
724
+ "Applied managed Gemini embedding defaults (provider=gemini, model=gemini-embedding-2, dimensions=3072, vectorSize=3072)",
725
+ );
726
+ // Re-validate so the returned config reflects the migration.
727
+ config = validateWithSchema(fileConfig);
728
+ }
729
+ } catch (err) {
730
+ log.warn(
731
+ { err },
732
+ "Managed Gemini defaults migration failed — continuing with existing config",
720
733
  );
721
- // Re-validate so the returned config reflects the migration.
722
- config = validateWithSchema(fileConfig);
723
734
  }
724
- } catch (err) {
725
- log.warn(
726
- { err },
727
- "Managed Gemini defaults migration failed — continuing with existing config",
728
- );
729
735
  }
730
736
  }
731
737
 
@@ -763,7 +769,7 @@ export function loadConfig(): AssistantConfig {
763
769
  // changes were inert because the merge only filled absent keys and never
764
770
  // reconciled existing values. Contract: disk = user intent, in-memory
765
771
  // cache = effective values.
766
- if (!configFileExisted) {
772
+ if (!configFileExisted && suppressConfigDiskWritesDepth === 0) {
767
773
  try {
768
774
  const dir = dirname(configPath);
769
775
  if (!existsSync(dir)) {
@@ -842,6 +848,26 @@ export function invalidateConfigCache(): void {
842
848
  loading = false;
843
849
  }
844
850
 
851
+ export async function withSuppressedConfigDiskWrites<T>(
852
+ fn: () => T | Promise<T>,
853
+ ): Promise<T> {
854
+ suppressConfigDiskWritesDepth++;
855
+ try {
856
+ return await fn();
857
+ } finally {
858
+ suppressConfigDiskWritesDepth--;
859
+ }
860
+ }
861
+
862
+ export function withSuppressedConfigDiskWritesSync<T>(fn: () => T): T {
863
+ suppressConfigDiskWritesDepth++;
864
+ try {
865
+ return fn();
866
+ } finally {
867
+ suppressConfigDiskWritesDepth--;
868
+ }
869
+ }
870
+
845
871
  /**
846
872
  * Load the raw config from disk without any secure-storage merging.
847
873
  * Used by CLI config commands to read/write the file directly.
@@ -20,11 +20,13 @@ import { AnalysisConfigSchema } from "./schemas/analysis.js";
20
20
  import { BackupConfigSchema } from "./schemas/backup.js";
21
21
  import { CallsConfigSchema } from "./schemas/calls.js";
22
22
  import {
23
+ A2AConfigSchema,
23
24
  SlackConfigSchema,
24
25
  TelegramConfigSchema,
25
26
  TwilioConfigSchema,
26
27
  WhatsAppConfigSchema,
27
28
  } from "./schemas/channels.js";
29
+ import { CompactionConfigSchema } from "./schemas/compaction.js";
28
30
  import { ConversationsConfigSchema } from "./schemas/conversations.js";
29
31
  import { FilingConfigSchema } from "./schemas/filing.js";
30
32
  import { HeartbeatConfigSchema } from "./schemas/heartbeat.js";
@@ -52,6 +54,7 @@ import {
52
54
  RateLimitConfigSchema,
53
55
  TimeoutConfigSchema,
54
56
  } from "./schemas/timeouts.js";
57
+ import { ToolsConfigSchema } from "./schemas/tools.js";
55
58
  import { UpdatesConfigSchema } from "./schemas/updates.js";
56
59
  import { WorkspaceGitConfigSchema } from "./schemas/workspace-git.js";
57
60
 
@@ -82,9 +85,7 @@ export const AssistantConfigSchema = z
82
85
  // ensures the loader's leaf-deletion recovery path can repair a partially
83
86
  // invalid `llm` block without falling back to `cloneDefaultConfig()`.
84
87
  llm: LLMSchema.default(LLMSchema.parse({})),
85
- llmRequestLogs: LlmRequestLogsConfigSchema.default(
86
- LlmRequestLogsConfigSchema.parse({}),
87
- ),
88
+ llmRequestLogs: LlmRequestLogsConfigSchema,
88
89
  filing: FilingConfigSchema.default(FilingConfigSchema.parse({})),
89
90
  heartbeat: HeartbeatConfigSchema.default(HeartbeatConfigSchema.parse({})),
90
91
  updates: UpdatesConfigSchema.default(UpdatesConfigSchema.parse({})),
@@ -103,11 +104,15 @@ export const AssistantConfigSchema = z
103
104
  workspaceGit: WorkspaceGitConfigSchema.default(
104
105
  WorkspaceGitConfigSchema.parse({}),
105
106
  ),
107
+ compaction: CompactionConfigSchema.default(
108
+ CompactionConfigSchema.parse({}),
109
+ ),
106
110
  twilio: TwilioConfigSchema.default(TwilioConfigSchema.parse({})),
107
111
  calls: CallsConfigSchema.default(CallsConfigSchema.parse({})),
108
112
  whatsapp: WhatsAppConfigSchema.default(WhatsAppConfigSchema.parse({})),
109
113
  telegram: TelegramConfigSchema.default(TelegramConfigSchema.parse({})),
110
114
  slack: SlackConfigSchema.default(SlackConfigSchema.parse({})),
115
+ a2a: A2AConfigSchema.default(A2AConfigSchema.parse({})),
111
116
  ingress: IngressConfigSchema,
112
117
  platform: PlatformConfigSchema.default(PlatformConfigSchema.parse({})),
113
118
  daemon: DaemonConfigSchema.default(DaemonConfigSchema.parse({})),
@@ -115,6 +120,7 @@ export const AssistantConfigSchema = z
115
120
  NotificationsConfigSchema.parse({}),
116
121
  ),
117
122
  ui: UiConfigSchema.default(UiConfigSchema.parse({})),
123
+ tools: ToolsConfigSchema.default(ToolsConfigSchema.parse({})),
118
124
  // Per-plugin config blocks keyed by plugin name. The schema is intentionally
119
125
  // permissive — each plugin's manifest supplies its own validator which the
120
126
  // plugin bootstrap (`external-plugins-bootstrap.ts`) runs against the raw
@@ -145,13 +151,6 @@ export const AssistantConfigSchema = z
145
151
  .max(200, "maxStepsPerSession must be <= 200")
146
152
  .default(50)
147
153
  .describe("Maximum number of computer-use steps per session"),
148
- systemPromptPrefix: z
149
- .string({ error: "systemPromptPrefix must be a string" })
150
- .nullable()
151
- .default(null)
152
- .describe(
153
- "Custom text injected at the very beginning of the system prompt. Defaults to null (no injection).",
154
- ),
155
154
  })
156
155
  .superRefine((config, ctx) => {
157
156
  const llmContextWindow = config.llm?.default?.contextWindow;
@@ -0,0 +1,36 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { LlmRequestLogsConfigSchema } from "../llm-request-logs.js";
4
+
5
+ describe("LlmRequestLogsConfigSchema", () => {
6
+ test("parses undefined to the local default", () => {
7
+ expect(LlmRequestLogsConfigSchema.parse(undefined)).toEqual({
8
+ readSource: "local",
9
+ });
10
+ });
11
+
12
+ test("parses an explicit local readSource", () => {
13
+ expect(
14
+ LlmRequestLogsConfigSchema.parse({ readSource: "local" }),
15
+ ).toEqual({ readSource: "local" });
16
+ });
17
+
18
+ test("parses an explicit clickhouse readSource with defaulted connection fields", () => {
19
+ expect(
20
+ LlmRequestLogsConfigSchema.parse({ readSource: "clickhouse" }),
21
+ ).toEqual({
22
+ readSource: "clickhouse",
23
+ clickhouse: {
24
+ database: "default",
25
+ table: "llm_request_logs",
26
+ user: "default",
27
+ },
28
+ });
29
+ });
30
+
31
+ test("rejects an unknown readSource", () => {
32
+ expect(() =>
33
+ LlmRequestLogsConfigSchema.parse({ readSource: "postgres" }),
34
+ ).toThrow();
35
+ });
36
+ });
@@ -33,7 +33,7 @@ describe("MemoryV2ConfigSchema", () => {
33
33
  dtype: "q8",
34
34
  },
35
35
  router: {
36
- enabled: false,
36
+ enabled: true,
37
37
  max_page_ids: 25,
38
38
  router_prompt_path: null,
39
39
  },
@@ -161,9 +161,9 @@ describe("MemoryV2ConfigSchema", () => {
161
161
  expect(() => MemoryV2ConfigSchema.parse({ epsilon: 1.5 })).toThrow();
162
162
  });
163
163
 
164
- test("router defaults to disabled with max_page_ids=25", () => {
164
+ test("router defaults to enabled with max_page_ids=25", () => {
165
165
  const parsed = MemoryV2ConfigSchema.parse({});
166
- expect(parsed.router.enabled).toBe(false);
166
+ expect(parsed.router.enabled).toBe(true);
167
167
  expect(parsed.router.max_page_ids).toBe(25);
168
168
  });
169
169
 
@@ -10,6 +10,10 @@ export const TwilioConfigSchema = z
10
10
  .string({ error: "twilio.phoneNumber must be a string" })
11
11
  .default("")
12
12
  .describe("Twilio phone number used for outbound calls and SMS"),
13
+ setupStarted: z
14
+ .boolean({ error: "twilio.setupStarted must be a boolean" })
15
+ .default(false)
16
+ .describe("Whether Twilio setup has ever been started"),
13
17
  })
14
18
  .describe("Twilio account configuration");
15
19
 
@@ -95,6 +99,15 @@ export const TelegramConfigSchema = z
95
99
  })
96
100
  .describe("Telegram bot channel configuration");
97
101
 
102
+ export const A2AConfigSchema = z
103
+ .object({
104
+ enabled: z
105
+ .boolean({ error: "a2a.enabled must be a boolean" })
106
+ .default(false)
107
+ .describe("Whether the A2A channel is enabled"),
108
+ })
109
+ .describe("Agent-to-Agent protocol channel configuration");
110
+
98
111
  export const SlackConfigSchema = z
99
112
  .object({
100
113
  deliverAuthBypass: z
@@ -111,6 +124,10 @@ export const SlackConfigSchema = z
111
124
  .string({ error: "slack.teamName must be a string" })
112
125
  .default("")
113
126
  .describe("Slack workspace team name"),
127
+ teamUrl: z
128
+ .string({ error: "slack.teamUrl must be a string" })
129
+ .default("")
130
+ .describe("Slack workspace URL"),
114
131
  botUserId: z
115
132
  .string({ error: "slack.botUserId must be a string" })
116
133
  .default("")
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+
3
+ export const CompactionConfigSchema = z
4
+ .object({
5
+ enabled: z
6
+ .boolean({ error: "compaction.enabled must be a boolean" })
7
+ .default(true)
8
+ .describe("Whether assistant-driven context compaction is enabled"),
9
+ autoThreshold: z
10
+ .number({ error: "compaction.autoThreshold must be a number" })
11
+ .finite("compaction.autoThreshold must be finite")
12
+ .gt(0, "compaction.autoThreshold must be greater than 0")
13
+ .lte(1, "compaction.autoThreshold must be less than or equal to 1")
14
+ .default(0.7)
15
+ .describe(
16
+ "Fraction of the context window at which automatic compaction fires",
17
+ ),
18
+ prompt: z
19
+ .string({ error: "compaction.prompt must be a string" })
20
+ .nullable()
21
+ .optional()
22
+ .describe(
23
+ "Custom compaction instruction. When set, replaces the generic default verbatim. The `{image_manifest}` placeholder is still interpolated.",
24
+ ),
25
+ })
26
+ .describe("Assistant-driven context compaction");
27
+
28
+ export type CompactionConfig = z.infer<typeof CompactionConfigSchema>;
@@ -10,6 +10,16 @@ export const ConversationsConfigSchema = z
10
10
  .describe(
11
11
  "When true, skip the second-pass title regeneration that fires after the third user turn. The initial auto-generated title and manual renames are unaffected.",
12
12
  ),
13
+ backgroundInjection: z
14
+ .string({
15
+ error: "conversations.backgroundInjection must be a string",
16
+ })
17
+ .default(
18
+ "This is a background turn — your guardian isn't watching. If anything noteworthy comes up, send them a notification so they see it when they're back by invoking the `notifications` skill (`assistant notifications send --message \"...\"`)",
19
+ )
20
+ .describe(
21
+ "Inner text injected into the tail user message of non-interactive turns in background/scheduled conversations. The injector wraps this in <background_turn>...</background_turn> tags. Empty string disables the injection.",
22
+ ),
13
23
  })
14
24
  .describe("Conversation behavior configuration");
15
25
 
@@ -47,6 +47,29 @@ export const HeartbeatConfigSchema = z
47
47
  .describe(
48
48
  "Hour of the day (0-23) when heartbeat checks stop, or null to disable active hours restriction",
49
49
  ),
50
+ maxConsecutiveRuns: z
51
+ .number({ error: "heartbeat.maxConsecutiveRuns must be a number" })
52
+ .int("heartbeat.maxConsecutiveRuns must be an integer")
53
+ .positive("heartbeat.maxConsecutiveRuns must be a positive integer")
54
+ .nullable()
55
+ .default(3)
56
+ .describe(
57
+ "Maximum heartbeats that can run consecutively without a guardian message. Counter resets when the guardian sends a message. Set to null for unlimited.",
58
+ ),
59
+ disposition: z
60
+ .string({ error: "heartbeat.disposition must be a string" })
61
+ .default(
62
+ `This is your time to do something useful, interesting, or creative while your guardian is away.
63
+
64
+ Before checking on anything, ask yourself: is there something I want to work on, think about, or make progress on right now? A project, an idea, something I noticed, something I've been meaning to get to. If so, do it.
65
+
66
+ If you do something worth sharing — built something, noticed something, had an idea — send your guardian a notification so they see it when they're back.
67
+
68
+ If nothing needs attention and nothing stirs, that's fine. But make sure you actually considered it first rather than defaulting to "nothing to do."`,
69
+ )
70
+ .describe(
71
+ "Inner text injected into the heartbeat prompt. The service wraps this in <heartbeat-disposition>...</heartbeat-disposition> tags. Empty string disables the block.",
72
+ ),
50
73
  })
51
74
  .describe("Periodic heartbeat configuration for health monitoring")
52
75
  .superRefine((config, ctx) => {
@@ -8,6 +8,10 @@
8
8
  * from the credential store (`clickhouse:url`, `clickhouse:password`).
9
9
  * The connection options below describe everything else (database/table/user).
10
10
  *
11
+ * The shape is a discriminated union on `readSource` so the `clickhouse`
12
+ * block only exists on the ClickHouse branch — there's no stray defaults
13
+ * sitting around when the source is local.
14
+ *
11
15
  * Note: the existing retention setting lives under
12
16
  * `memory.cleanup.llmRequestLogRetentionMs` and is independent of this block.
13
17
  * That covers when local rows get pruned; this block governs where reads
@@ -37,18 +41,38 @@ export const LlmRequestLogsClickHouseConfigSchema = z
37
41
  "ClickHouse connection settings used when `readSource` is `clickhouse`",
38
42
  );
39
43
 
40
- export const LlmRequestLogsConfigSchema = z
44
+ const LocalLlmRequestLogsConfigSchema = z
45
+ .object({
46
+ readSource: z.literal("local"),
47
+ })
48
+ .describe("Read LLM request logs from local SQLite (default).");
49
+
50
+ const ClickHouseLlmRequestLogsConfigSchema = z
41
51
  .object({
42
- readSource: z
43
- .enum(["local", "clickhouse"])
44
- .default("local")
45
- .describe(
46
- "Where to read LLM request logs from for Inspector queries. `local` reads the SQLite source-of-truth (default, lowest latency). `clickhouse` reads the mirror, which retains data longer than local but only sees writes that the mirror job has flushed.",
47
- ),
52
+ readSource: z.literal("clickhouse"),
48
53
  clickhouse: LlmRequestLogsClickHouseConfigSchema.default(
49
54
  LlmRequestLogsClickHouseConfigSchema.parse({}),
50
55
  ),
51
56
  })
57
+ .describe(
58
+ "Read LLM request logs from the ClickHouse mirror. Requires the `clickhouse:url` and `clickhouse:password` credentials to be set.",
59
+ );
60
+
61
+ // The default is baked into the export so the schema matches the sibling
62
+ // pattern across `assistant/src/config/schemas/*` — `Schema.parse(undefined)`
63
+ // returns documented defaults. The discriminated union has no inherent
64
+ // default (no shared discriminator value), so we explicitly select the
65
+ // `local` branch.
66
+ //
67
+ // Note: `LlmRequestLogsConfigSchema.parse({})` still throws — a discriminated
68
+ // union cannot pick a branch without a discriminator. Use `parse(undefined)`
69
+ // or omit the field entirely to get the default.
70
+ export const LlmRequestLogsConfigSchema = z
71
+ .discriminatedUnion("readSource", [
72
+ LocalLlmRequestLogsConfigSchema,
73
+ ClickHouseLlmRequestLogsConfigSchema,
74
+ ])
75
+ .default({ readSource: "local" })
52
76
  .describe("LLM request log read source configuration");
53
77
 
54
78
  export type LlmRequestLogsConfig = z.infer<typeof LlmRequestLogsConfigSchema>;
@@ -20,6 +20,7 @@ const LLMProvider = z.enum([
20
20
  "ollama",
21
21
  "fireworks",
22
22
  "openrouter",
23
+ "openai-compatible",
23
24
  ]);
24
25
  type LLMProvider = z.infer<typeof LLMProvider>;
25
26
 
@@ -284,6 +284,21 @@ const MemoryInjectionConfigSchema = z
284
284
  "Controls how many memory items are injected at conversation start and per turn",
285
285
  );
286
286
 
287
+ const ScratchpadInjectionConfigSchema = z
288
+ .object({
289
+ enabled: z
290
+ .boolean({
291
+ error: "memory.retrieval.scratchpadInjection.enabled must be a boolean",
292
+ })
293
+ .default(true)
294
+ .describe(
295
+ "Whether NOW.md scratchpad content is injected into the conversation prompt. Injection occurs on the first turn and post-compaction; flipping this off takes effect on the next conversation or compaction.",
296
+ ),
297
+ })
298
+ .describe(
299
+ "Controls whether the user-maintained NOW.md scratchpad is injected into prompts",
300
+ );
301
+
287
302
  export const MemoryRetrievalConfigSchema = z
288
303
  .object({
289
304
  maxInjectTokens: z
@@ -312,6 +327,9 @@ export const MemoryRetrievalConfigSchema = z
312
327
  injection: MemoryInjectionConfigSchema.default(
313
328
  MemoryInjectionConfigSchema.parse({}),
314
329
  ),
330
+ scratchpadInjection: ScratchpadInjectionConfigSchema.default(
331
+ ScratchpadInjectionConfigSchema.parse({}),
332
+ ),
315
333
  })
316
334
  .describe(
317
335
  "Controls how memories are retrieved and injected into conversations",
@@ -40,7 +40,7 @@ export const MemoryRetrospectiveConfigSchema = z
40
40
  ),
41
41
  })
42
42
  .describe(
43
- "Controls the memory-retrospective background pass triggered by the `memory-retrospective` feature flag. Model selection lives under llm.callSites.memoryRetrospective.",
43
+ "Controls the memory-retrospective background pass. Model selection lives under llm.callSites.memoryRetrospective.",
44
44
  );
45
45
 
46
46
  export type MemoryRetrospectiveConfig = z.infer<
@@ -260,9 +260,9 @@ export const MemoryV2ConfigSchema = z
260
260
  .object({
261
261
  enabled: z
262
262
  .boolean()
263
- .default(false)
263
+ .default(true)
264
264
  .describe(
265
- "Whether to use the LLM router as the per-turn page-selection mechanism in place of spreading activation. Disabled by default — opt in once the router orchestration and dispatcher land.",
265
+ "Whether to use the LLM router as the per-turn page-selection mechanism in place of spreading activation. Enabled by default.",
266
266
  ),
267
267
  max_page_ids: z
268
268
  .number()
@@ -283,9 +283,9 @@ export const MemoryV2ConfigSchema = z
283
283
  "Optional path to a file whose contents replace the bundled router prompt. Absolute paths are used as-is, a leading `~/` is expanded to the home directory, otherwise the path is resolved under the workspace root. The loaded contents may include `{{ASSISTANT_NAME}}`, `{{USER_NAME}}`, and `{{PAGE_INDEX}}`, which are substituted at runtime. If the file is missing, unreadable, or empty, the bundled prompt is used and a warning is logged.",
284
284
  ),
285
285
  })
286
- .default({ enabled: false, max_page_ids: 25, router_prompt_path: null })
286
+ .default({ enabled: true, max_page_ids: 25, router_prompt_path: null })
287
287
  .describe(
288
- "LLM router configuration. When enabled, a single Sonnet router call replaces spreading activation for per-turn page selection.",
288
+ "LLM router configuration. When enabled, a single router LLM call replaces spreading activation for per-turn page selection.",
289
289
  ),
290
290
  })
291
291
  .describe(
@@ -23,7 +23,9 @@ export const MemoryConfigSchema = z
23
23
  enabled: z
24
24
  .boolean({ error: "memory.enabled must be a boolean" })
25
25
  .default(true)
26
- .describe("Whether the long-term memory system is enabled"),
26
+ .describe(
27
+ "Whether the long-term memory system is enabled — gates background memory jobs, embedding generation, and `<memory>` block injection into user messages",
28
+ ),
27
29
  embeddings: MemoryEmbeddingsConfigSchema.default(
28
30
  MemoryEmbeddingsConfigSchema.parse({}),
29
31
  ),
@@ -0,0 +1,14 @@
1
+ import { z } from "zod";
2
+
3
+ export const ToolsConfigSchema = z
4
+ .object({
5
+ exclude: z
6
+ .array(z.string(), { error: "tools.exclude must be an array of strings" })
7
+ .default([])
8
+ .describe(
9
+ "Tool names to suppress. Excluded tools are not sent to the LLM. Names match `ToolDefinition.name` exactly (e.g. `bash`, `mcp__server__tool`).",
10
+ ),
11
+ })
12
+ .describe("Tool visibility configuration");
13
+
14
+ export type ToolsConfig = z.infer<typeof ToolsConfigSchema>;