@vellumai/assistant 0.8.7 → 0.8.8-dev.202606052332.17fc8ea

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 (570) hide show
  1. package/Dockerfile +20 -4
  2. package/bun.lock +2 -2
  3. package/docker-entrypoint.sh +4 -2
  4. package/docker-init-apt-root.sh +3 -1
  5. package/docker-kata-apt-env.sh +3 -1
  6. package/docker-kata-runtime-family.sh +12 -0
  7. package/docs/architecture/memory.md +1 -1
  8. package/examples/plugins/echo/README.md +61 -66
  9. package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
  10. package/examples/plugins/echo/hooks/stop.ts +16 -0
  11. package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
  12. package/examples/plugins/echo/package.json +1 -2
  13. package/examples/plugins/echo/src/emit.ts +19 -0
  14. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
  15. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
  16. package/openapi.yaml +3378 -335
  17. package/package.json +2 -2
  18. package/scripts/generate-openapi.ts +68 -41
  19. package/src/__tests__/agent-loop-exit-reason.test.ts +35 -93
  20. package/src/__tests__/agent-loop-provider-error-recording.test.ts +1 -1
  21. package/src/__tests__/agent-loop.test.ts +37 -87
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
  23. package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
  24. package/src/__tests__/annotate-risk-options.test.ts +2 -3
  25. package/src/__tests__/anthropic-provider.test.ts +95 -2
  26. package/src/__tests__/app-control-flow.test.ts +1 -1
  27. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  28. package/src/__tests__/approval-routes-http.test.ts +4 -1
  29. package/src/__tests__/assistant-event-hub.test.ts +25 -0
  30. package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
  31. package/src/__tests__/{conversation-stream-state.test.ts → assistant-stream-state.test.ts} +252 -91
  32. package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
  33. package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
  34. package/src/__tests__/btw-routes.test.ts +62 -3
  35. package/src/__tests__/build-persisted-content.test.ts +184 -0
  36. package/src/__tests__/catalog-files.test.ts +1 -1
  37. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  38. package/src/__tests__/channel-approvals.test.ts +1 -1
  39. package/src/__tests__/clawhub-files.test.ts +1 -1
  40. package/src/__tests__/compaction-circuit.test.ts +258 -0
  41. package/src/__tests__/compaction-direct.test.ts +132 -0
  42. package/src/__tests__/compaction.benchmark.test.ts +0 -30
  43. package/src/__tests__/config-watcher.test.ts +1 -1
  44. package/src/__tests__/conversation-abort-tool-results.test.ts +57 -19
  45. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +6 -5
  46. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -7
  47. package/src/__tests__/conversation-agent-loop-overflow.test.ts +316 -1143
  48. package/src/__tests__/conversation-agent-loop.test.ts +638 -1655
  49. package/src/__tests__/conversation-analysis-routes.test.ts +6 -0
  50. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  51. package/src/__tests__/conversation-history-web-search.test.ts +11 -1
  52. package/src/__tests__/conversation-pairing.test.ts +4 -31
  53. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +6 -0
  54. package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -10
  55. package/src/__tests__/conversation-queue.test.ts +2 -0
  56. package/src/__tests__/conversation-routes-disk-view.test.ts +3 -0
  57. package/src/__tests__/conversation-routes-slash-commands.test.ts +6 -5
  58. package/src/__tests__/conversation-runtime-assembly.test.ts +310 -300
  59. package/src/__tests__/conversation-runtime-workspace.test.ts +105 -45
  60. package/src/__tests__/conversation-slash-commands.test.ts +8 -42
  61. package/src/__tests__/conversation-slash-queue.test.ts +6 -1
  62. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  63. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +84 -0
  64. package/src/__tests__/conversation-sync-tags.test.ts +27 -15
  65. package/src/__tests__/conversation-title-service.test.ts +135 -2
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +17 -16
  67. package/src/__tests__/conversation-workspace-injection.test.ts +67 -2
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +7 -6
  69. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  70. package/src/__tests__/cross-provider-web-search.test.ts +214 -1
  71. package/src/__tests__/db-acp-history.test.ts +101 -0
  72. package/src/__tests__/db-schedule-syntax-migration.test.ts +5 -0
  73. package/src/__tests__/dm-persistence.test.ts +5 -1
  74. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  75. package/src/__tests__/empty-response-hook.test.ts +304 -0
  76. package/src/__tests__/feature-flag-test-helpers.ts +2 -2
  77. package/src/__tests__/file-write-tool.test.ts +63 -0
  78. package/src/__tests__/gateway-only-guard.test.ts +12 -2
  79. package/src/__tests__/gemini-image-service.test.ts +13 -0
  80. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  81. package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
  82. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  83. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  84. package/src/__tests__/heartbeat-service.test.ts +1 -0
  85. package/src/__tests__/helpers/mock-provider.ts +110 -0
  86. package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
  87. package/src/__tests__/history-repair-hook.test.ts +1 -0
  88. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  89. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  90. package/src/__tests__/identity-intro-cache.test.ts +12 -100
  91. package/src/__tests__/identity-routes.test.ts +248 -7
  92. package/src/__tests__/inbound-slack-persistence.test.ts +5 -1
  93. package/src/__tests__/injector-background-turn.test.ts +3 -9
  94. package/src/__tests__/injector-chain.test.ts +139 -275
  95. package/src/__tests__/injector-disk-pressure.test.ts +75 -41
  96. package/src/__tests__/injector-document-comments.test.ts +3 -3
  97. package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
  98. package/src/__tests__/injector-v3-suppression.test.ts +31 -37
  99. package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
  100. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  101. package/src/__tests__/list-messages-page-latest.test.ts +60 -0
  102. package/src/__tests__/list-messages-tool-merge.test.ts +20 -0
  103. package/src/__tests__/llm-usage-store.test.ts +223 -1
  104. package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
  105. package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
  106. package/src/__tests__/native-web-search.test.ts +191 -0
  107. package/src/__tests__/onboarding-template-contract.test.ts +2 -0
  108. package/src/__tests__/openai-image-service.test.ts +17 -0
  109. package/src/__tests__/openai-provider.test.ts +31 -1
  110. package/src/__tests__/{overflow-reduce-pipeline.test.ts → overflow-reduction-loop.test.ts} +64 -284
  111. package/src/__tests__/persist-unsendable-image.test.ts +215 -0
  112. package/src/__tests__/persistence-secret-redaction.test.ts +1 -0
  113. package/src/__tests__/pkb-autoinject.test.ts +2 -5
  114. package/src/__tests__/plugin-api-shim.test.ts +3 -6
  115. package/src/__tests__/plugin-bootstrap.test.ts +14 -40
  116. package/src/__tests__/plugin-registry.test.ts +3 -76
  117. package/src/__tests__/plugin-types.test.ts +0 -193
  118. package/src/__tests__/process-message-display-content.test.ts +6 -2
  119. package/src/__tests__/reaction-persistence.test.ts +1 -1
  120. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
  121. package/src/__tests__/resolve-trust-class.test.ts +4 -4
  122. package/src/__tests__/runtime-events-sse-reconnect.test.ts +60 -23
  123. package/src/__tests__/schedule-routes.test.ts +603 -2
  124. package/src/__tests__/schedule-store.test.ts +41 -0
  125. package/src/__tests__/schedule-tools.test.ts +35 -0
  126. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  127. package/src/__tests__/server-history-render.test.ts +314 -1
  128. package/src/__tests__/skill-feature-flags-integration.test.ts +33 -0
  129. package/src/__tests__/skillssh-files.test.ts +1 -1
  130. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  131. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  132. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  133. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  134. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  135. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  136. package/src/__tests__/system-prompt.test.ts +20 -0
  137. package/src/__tests__/task-scheduler.test.ts +162 -1
  138. package/src/__tests__/terminal-tools.test.ts +6 -1
  139. package/src/__tests__/title-generate-hook.test.ts +319 -0
  140. package/src/__tests__/tool-error-hook.test.ts +278 -0
  141. package/src/__tests__/tool-preview-lifecycle.test.ts +468 -5
  142. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  143. package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
  144. package/src/__tests__/tool-result-truncation.test.ts +0 -2
  145. package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
  146. package/src/__tests__/ui-work-result-surface.test.ts +159 -0
  147. package/src/__tests__/usage-routes.test.ts +285 -1
  148. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  149. package/src/__tests__/voice-session-bridge.test.ts +6 -3
  150. package/src/__tests__/web-search-backend-failure.test.ts +166 -0
  151. package/src/acp/__tests__/agent-process.test.ts +161 -0
  152. package/src/acp/__tests__/client-handler.test.ts +40 -0
  153. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  154. package/src/acp/__tests__/helpers/exec-file-stub.ts +101 -0
  155. package/src/acp/__tests__/prepare-agent-env.test.ts +137 -0
  156. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  157. package/src/acp/__tests__/session-manager-resume.test.ts +736 -0
  158. package/src/acp/agent-process.ts +61 -1
  159. package/src/acp/auto-install.test.ts +196 -0
  160. package/src/acp/auto-install.ts +177 -0
  161. package/src/acp/client-handler.ts +31 -0
  162. package/src/acp/feature-gate.test.ts +48 -0
  163. package/src/acp/feature-gate.ts +34 -0
  164. package/src/acp/prepare-agent-env.ts +83 -29
  165. package/src/acp/resolve-agent.test.ts +320 -7
  166. package/src/acp/resolve-agent.ts +182 -18
  167. package/src/acp/resume-hint.ts +25 -0
  168. package/src/acp/session-manager.ts +495 -73
  169. package/src/acp/types.ts +8 -0
  170. package/src/agent/compaction-circuit.ts +60 -102
  171. package/src/agent/loop.ts +362 -485
  172. package/src/api/events/assistant-thinking-delta.ts +33 -0
  173. package/src/api/events/tool-output-chunk.ts +45 -0
  174. package/src/api/events/tool-use-preview-start.ts +32 -0
  175. package/src/api/events/trace-event.ts +69 -0
  176. package/src/api/index.ts +48 -13
  177. package/src/api/responses/conversation-message.ts +374 -0
  178. package/src/approvals/guardian-request-resolvers.ts +1 -1
  179. package/src/avatar/__tests__/avatar-store.test.ts +34 -29
  180. package/src/background-wake/next-wake.ts +1 -0
  181. package/src/cli/commands/__tests__/notifications.test.ts +58 -14
  182. package/src/cli/commands/notifications.ts +112 -60
  183. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  184. package/src/config/acp-defaults.test.ts +10 -0
  185. package/src/config/acp-defaults.ts +6 -0
  186. package/src/config/assistant-feature-flags.ts +22 -11
  187. package/src/config/bundled-skills/acp/SKILL.md +83 -31
  188. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  189. package/src/config/bundled-skills/app-builder/SKILL.md +224 -398
  190. package/src/config/bundled-skills/app-builder/TOOLS.json +29 -0
  191. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  192. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  193. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  194. package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
  195. package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
  196. package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
  197. package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
  198. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  199. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  200. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  201. package/src/config/bundled-skills/messaging/SKILL.md +0 -7
  202. package/src/config/bundled-tool-registry.ts +2 -0
  203. package/src/config/feature-flag-cache.ts +3 -3
  204. package/src/config/feature-flag-registry.json +48 -7
  205. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  206. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
  207. package/src/config/schemas/heartbeat.ts +9 -0
  208. package/src/config/schemas/llm.ts +1 -0
  209. package/src/config/schemas/memory-v2.ts +8 -0
  210. package/src/config/schemas/memory-v3.ts +8 -0
  211. package/src/config/schemas/platform.ts +8 -0
  212. package/src/config/seed-inference-profiles.ts +2 -2
  213. package/src/config/skills.ts +13 -0
  214. package/src/context/compactor.ts +1 -1
  215. package/src/context/strip-injections.ts +128 -0
  216. package/src/context/token-estimator.ts +23 -0
  217. package/src/context/tool-result-truncation.ts +0 -23
  218. package/src/context/window-manager.ts +5 -7
  219. package/src/credential-execution/executable-discovery.ts +16 -0
  220. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
  221. package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
  222. package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
  223. package/src/daemon/assistant-attachments.ts +1 -1
  224. package/src/daemon/config-watcher.ts +2 -2
  225. package/src/daemon/context-overflow-reducer.ts +0 -1
  226. package/src/daemon/conversation-agent-loop-handlers.ts +594 -153
  227. package/src/daemon/conversation-agent-loop.ts +301 -997
  228. package/src/daemon/conversation-history.ts +5 -4
  229. package/src/daemon/conversation-lifecycle.ts +3 -4
  230. package/src/daemon/conversation-messaging.ts +7 -6
  231. package/src/daemon/conversation-process.ts +11 -16
  232. package/src/daemon/conversation-registry.ts +159 -0
  233. package/src/daemon/conversation-runtime-assembly.ts +218 -398
  234. package/src/daemon/conversation-slash.ts +6 -25
  235. package/src/daemon/conversation-store.ts +9 -90
  236. package/src/daemon/conversation-surfaces.ts +222 -4
  237. package/src/daemon/conversation-tool-setup.ts +2 -29
  238. package/src/daemon/conversation-workspace.ts +17 -0
  239. package/src/daemon/conversation.ts +32 -20
  240. package/src/daemon/external-plugins-bootstrap.ts +17 -18
  241. package/src/daemon/handlers/config-a2a.ts +51 -36
  242. package/src/daemon/handlers/config-slack-channel.ts +20 -14
  243. package/src/daemon/handlers/config-telegram.ts +16 -2
  244. package/src/daemon/handlers/conversations.ts +3 -1
  245. package/src/daemon/handlers/shared.ts +156 -84
  246. package/src/daemon/handlers/skills.ts +42 -10
  247. package/src/daemon/lifecycle.ts +25 -0
  248. package/src/daemon/message-types/apps.ts +1 -29
  249. package/src/daemon/message-types/messages.ts +9 -57
  250. package/src/daemon/message-types/skills.ts +2 -0
  251. package/src/daemon/message-types/surfaces.ts +136 -3
  252. package/src/daemon/now-scratchpad.ts +21 -0
  253. package/src/daemon/orphan-reaper.test.ts +210 -0
  254. package/src/daemon/orphan-reaper.ts +240 -0
  255. package/src/daemon/overflow-reduction-loop.ts +230 -0
  256. package/src/daemon/persist-unsendable-image.ts +117 -0
  257. package/src/daemon/process-message.ts +1 -3
  258. package/src/daemon/server.ts +2 -0
  259. package/src/daemon/trace-emitter.ts +6 -4
  260. package/src/daemon/trust-context.ts +19 -0
  261. package/src/daemon/wake-target-adapter.ts +3 -1
  262. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  263. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  264. package/src/heartbeat/heartbeat-service.ts +26 -0
  265. package/src/home/home-greeting-cache.ts +24 -1
  266. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  267. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  268. package/src/ipc/gateway-client.test.ts +2 -2
  269. package/src/ipc/gateway-client.ts +3 -3
  270. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  271. package/src/ipc/skill-routes/memory.ts +4 -2
  272. package/src/media/gemini-image-service.ts +15 -0
  273. package/src/media/openai-image-service.ts +14 -0
  274. package/src/media/types.ts +34 -0
  275. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
  276. package/src/memory/auth-fallback-events-store.ts +94 -0
  277. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  278. package/src/memory/conversation-title-service.ts +65 -41
  279. package/src/memory/db-init.ts +6 -0
  280. package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
  281. package/src/memory/graph/conversation-graph-memory.ts +65 -0
  282. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  283. package/src/memory/jobs-store.ts +33 -0
  284. package/src/memory/jobs-worker.ts +32 -5
  285. package/src/memory/llm-usage-store.ts +224 -50
  286. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
  287. package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
  288. package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
  289. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  290. package/src/memory/migrations/index.ts +3 -0
  291. package/src/memory/pkb/autoinject.ts +61 -0
  292. package/src/memory/pkb/context.ts +50 -0
  293. package/src/memory/pkb/types.ts +14 -0
  294. package/src/memory/schedule-attribution-sql.ts +104 -0
  295. package/src/memory/schema/acp.ts +4 -0
  296. package/src/memory/schema/infrastructure.ts +16 -0
  297. package/src/memory/usage-grouped-buckets.ts +6 -1
  298. package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -4
  299. package/src/memory/v2/consolidation-job.ts +14 -5
  300. package/src/notifications/conversation-pairing.ts +8 -15
  301. package/src/notifications/decision-engine.ts +6 -3
  302. package/src/notifications/home-feed-side-effect.ts +12 -1
  303. package/src/permissions/prompter.ts +4 -0
  304. package/src/plugin-api/constants.ts +4 -0
  305. package/src/plugin-api/index.ts +7 -5
  306. package/src/plugin-api/types.ts +151 -1
  307. package/src/plugins/defaults/compaction/compact.ts +59 -0
  308. package/src/plugins/defaults/compaction/package.json +1 -1
  309. package/src/plugins/defaults/compaction/register.ts +8 -19
  310. package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
  311. package/src/plugins/defaults/empty-response/register.ts +8 -13
  312. package/src/plugins/defaults/index.ts +2 -18
  313. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +95 -0
  314. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
  315. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
  316. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +288 -81
  317. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/assign.test.ts +4 -4
  318. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/health.test.ts +16 -0
  319. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +4 -4
  320. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/maintain-job.test.ts +5 -5
  321. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/orchestrate.test.ts +48 -12
  322. package/src/plugins/defaults/memory-v3-shadow/__tests__/provider-blocks.test.ts +13 -0
  323. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/reconcile.test.ts +2 -2
  324. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/render-injection.test.ts +1 -1
  325. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/router.test.ts +104 -32
  326. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +8 -8
  327. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selector.test.ts +96 -30
  328. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/shadow-plugin.test.ts +34 -16
  329. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/assign.ts +5 -5
  330. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/capabilities.ts +2 -2
  331. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/health.ts +0 -0
  332. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  333. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  334. package/src/plugins/defaults/memory-v3-shadow/injector.ts +75 -0
  335. package/src/plugins/defaults/memory-v3-shadow/llm-retry.ts +32 -0
  336. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/maintain-job.ts +8 -8
  337. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/orchestrate.ts +26 -14
  338. package/src/plugins/defaults/{llm-call → memory-v3-shadow}/package.json +2 -2
  339. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/page-content.ts +2 -2
  340. package/src/plugins/defaults/memory-v3-shadow/provider-blocks.ts +26 -0
  341. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/reconcile.ts +3 -3
  342. package/src/plugins/defaults/memory-v3-shadow/register.ts +26 -0
  343. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +1 -1
  344. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/router.ts +51 -45
  345. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selection-log-store.ts +4 -4
  346. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/selector.ts +61 -46
  347. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/shadow-plugin.ts +69 -99
  348. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/tree.ts +1 -1
  349. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/types.ts +8 -0
  350. package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
  351. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
  352. package/src/plugins/defaults/title-generate/package.json +1 -1
  353. package/src/plugins/defaults/title-generate/register.ts +18 -18
  354. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
  355. package/src/plugins/defaults/tool-error/package.json +1 -1
  356. package/src/plugins/defaults/tool-error/register.ts +9 -21
  357. package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
  358. package/src/plugins/defaults/tool-result-truncate/register.ts +10 -21
  359. package/src/plugins/defaults/tool-result-truncate/terminal.ts +37 -18
  360. package/src/plugins/external-api.ts +2 -2
  361. package/src/plugins/pipeline.ts +6 -305
  362. package/src/plugins/registry.ts +10 -55
  363. package/src/plugins/types.ts +62 -797
  364. package/src/plugins/user-loader.ts +30 -127
  365. package/src/proactive-artifact/aux-message-injector.ts +4 -4
  366. package/src/proactive-artifact/job.test.ts +8 -13
  367. package/src/prompts/__tests__/system-prompt.test.ts +42 -0
  368. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +64 -0
  369. package/src/prompts/templates/BOOTSTRAP.md +2 -2
  370. package/src/prompts/templates/system-sections.ts +15 -0
  371. package/src/providers/anthropic/client.ts +37 -29
  372. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -0
  373. package/src/providers/openai/chat-completions-provider.ts +44 -0
  374. package/src/providers/openrouter/client.ts +1 -0
  375. package/src/providers/placeholder-sentinels.ts +35 -0
  376. package/src/runtime/__tests__/agent-wake.test.ts +10 -6
  377. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  378. package/src/runtime/agent-wake.ts +2 -5
  379. package/src/runtime/assistant-event-hub.ts +37 -7
  380. package/src/runtime/{conversation-stream-state.ts → assistant-stream-state.ts} +132 -58
  381. package/src/runtime/channel-approvals.ts +1 -1
  382. package/src/runtime/http-router.ts +16 -21
  383. package/src/runtime/http-types.ts +16 -70
  384. package/src/runtime/interactive-ui.ts +1 -1
  385. package/src/runtime/pending-interactions.ts +1 -0
  386. package/src/runtime/routes/__tests__/acp-routes.test.ts +283 -55
  387. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
  388. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  389. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
  390. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
  391. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  392. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  393. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  394. package/src/runtime/routes/acp-routes.test.ts +89 -25
  395. package/src/runtime/routes/acp-routes.ts +81 -29
  396. package/src/runtime/routes/app-management-routes.ts +6 -117
  397. package/src/runtime/routes/app-routes.ts +13 -15
  398. package/src/runtime/routes/approval-routes.ts +1 -1
  399. package/src/runtime/routes/attachment-routes.ts +26 -15
  400. package/src/runtime/routes/avatar-routes.ts +26 -0
  401. package/src/runtime/routes/browser-routes.ts +1 -1
  402. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  403. package/src/runtime/routes/btw-routes.ts +29 -23
  404. package/src/runtime/routes/consolidation-routes.ts +120 -20
  405. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  406. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  407. package/src/runtime/routes/conversation-query-routes.ts +3 -1
  408. package/src/runtime/routes/conversation-routes.ts +372 -185
  409. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  410. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  411. package/src/runtime/routes/documents-routes.ts +4 -0
  412. package/src/runtime/routes/domain-routes.ts +51 -37
  413. package/src/runtime/routes/epoch-millis-range.ts +34 -0
  414. package/src/runtime/routes/events-routes.ts +28 -34
  415. package/src/runtime/routes/gateway-log-routes.ts +26 -4
  416. package/src/runtime/routes/heartbeat-routes.ts +32 -12
  417. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  418. package/src/runtime/routes/host-cu-routes.ts +1 -1
  419. package/src/runtime/routes/identity-intro-cache.ts +11 -34
  420. package/src/runtime/routes/identity-routes.ts +224 -18
  421. package/src/runtime/routes/image-generation-routes.ts +40 -2
  422. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  423. package/src/runtime/routes/index.ts +2 -0
  424. package/src/runtime/routes/integrations/a2a.ts +12 -10
  425. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
  426. package/src/runtime/routes/integrations/slack/channel.ts +4 -0
  427. package/src/runtime/routes/integrations/slack/share.ts +27 -6
  428. package/src/runtime/routes/integrations/telegram.ts +6 -0
  429. package/src/runtime/routes/integrations/twilio.ts +42 -0
  430. package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
  431. package/src/runtime/routes/log-export-routes.ts +8 -0
  432. package/src/runtime/routes/memory-v2-routes.ts +15 -8
  433. package/src/runtime/routes/memory-v3-routes.ts +66 -34
  434. package/src/runtime/routes/oauth-apps.ts +66 -12
  435. package/src/runtime/routes/oauth-providers.ts +44 -5
  436. package/src/runtime/routes/platform-routes.ts +81 -5
  437. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +6 -4
  438. package/src/runtime/routes/playground/force-compact.ts +1 -1
  439. package/src/runtime/routes/playground/helpers.ts +1 -1
  440. package/src/runtime/routes/rename-conversation-routes.ts +5 -0
  441. package/src/runtime/routes/schedule-routes.ts +152 -42
  442. package/src/runtime/routes/secret-routes.ts +14 -2
  443. package/src/runtime/routes/skills-routes.ts +43 -14
  444. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  445. package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
  446. package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
  447. package/src/runtime/routes/trust-rules-routes.ts +26 -2
  448. package/src/runtime/routes/tts-routes.ts +35 -0
  449. package/src/runtime/routes/types.ts +66 -8
  450. package/src/runtime/routes/usage-routes.ts +47 -39
  451. package/src/runtime/routes/webhook-routes.ts +41 -2
  452. package/src/runtime/routes/work-items-routes.ts +2 -4
  453. package/src/runtime/routes/workspace-routes.ts +4 -0
  454. package/src/runtime/services/__tests__/analyze-conversation.test.ts +6 -0
  455. package/src/runtime/services/analyze-conversation.ts +2 -2
  456. package/src/runtime/services/conversation-serializer.ts +1 -1
  457. package/src/schedule/schedule-store.ts +20 -1
  458. package/src/schedule/schedule-usage-store.ts +83 -0
  459. package/src/schedule/scheduler.ts +12 -5
  460. package/src/signals/cancel.ts +2 -4
  461. package/src/skills/catalog-files.ts +2 -2
  462. package/src/skills/catalog-install.ts +3 -0
  463. package/src/skills/categories-cache.ts +118 -0
  464. package/src/skills/clawhub-files.ts +1 -2
  465. package/src/skills/skillssh-files.ts +1 -2
  466. package/src/subagent/manager.ts +17 -5
  467. package/src/telemetry/types.ts +29 -1
  468. package/src/telemetry/usage-telemetry-reporter.test.ts +112 -3
  469. package/src/telemetry/usage-telemetry-reporter.ts +57 -2
  470. package/src/tools/acp/context.ts +20 -0
  471. package/src/tools/acp/list-agents.test.ts +7 -1
  472. package/src/tools/acp/spawn.test.ts +158 -55
  473. package/src/tools/acp/spawn.ts +47 -72
  474. package/src/tools/acp/steer.test.ts +105 -8
  475. package/src/tools/acp/steer.ts +48 -17
  476. package/src/tools/apps/executors.ts +13 -8
  477. package/src/tools/executor.ts +1 -53
  478. package/src/tools/filesystem/write.ts +34 -0
  479. package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
  480. package/src/tools/network/__tests__/web-search.test.ts +11 -3
  481. package/src/tools/network/web-search-error.test.ts +248 -0
  482. package/src/tools/network/web-search-error.ts +267 -0
  483. package/src/tools/network/web-search.ts +207 -48
  484. package/src/tools/schedule/create.ts +2 -0
  485. package/src/tools/subagent/spawn.ts +2 -4
  486. package/src/tools/terminal/safe-env.ts +10 -1
  487. package/src/tools/ui-surface/definitions.ts +34 -5
  488. package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
  489. package/src/tts/provider-catalog.ts +76 -1
  490. package/src/util/mutex.ts +47 -0
  491. package/src/workspace/git-service.ts +1 -42
  492. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  493. package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
  494. package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
  495. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +117 -0
  496. package/src/workspace/migrations/registry.ts +6 -0
  497. package/docs/plugins.md +0 -836
  498. package/examples/plugins/echo/register.ts +0 -184
  499. package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
  500. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  501. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  502. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  503. package/src/__tests__/empty-response-pipeline.test.ts +0 -423
  504. package/src/__tests__/llm-call-pipeline.test.ts +0 -287
  505. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
  506. package/src/__tests__/persistence-pipeline.test.ts +0 -503
  507. package/src/__tests__/pipeline-runner.test.ts +0 -564
  508. package/src/__tests__/title-generate-pipeline.test.ts +0 -211
  509. package/src/__tests__/token-estimate-pipeline.test.ts +0 -479
  510. package/src/__tests__/tool-error-pipeline.test.ts +0 -241
  511. package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
  512. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -341
  513. package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
  514. package/src/gallery/default-gallery.ts +0 -1359
  515. package/src/gallery/gallery-manifest.ts +0 -28
  516. package/src/home/feature-gate.ts +0 -22
  517. package/src/memory/v3/provider-blocks.ts +0 -16
  518. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  519. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  520. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  521. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  522. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  523. package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +0 -22
  524. package/src/plugins/defaults/empty-response/terminal.ts +0 -106
  525. package/src/plugins/defaults/injectors/package.json +0 -15
  526. package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +0 -17
  527. package/src/plugins/defaults/llm-call/register.ts +0 -45
  528. package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +0 -17
  529. package/src/plugins/defaults/memory-retrieval/package.json +0 -15
  530. package/src/plugins/defaults/memory-retrieval/register.ts +0 -181
  531. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  532. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  533. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  534. package/src/plugins/defaults/persistence/middlewares/persistence.ts +0 -19
  535. package/src/plugins/defaults/persistence/package.json +0 -15
  536. package/src/plugins/defaults/persistence/register.ts +0 -38
  537. package/src/plugins/defaults/persistence/terminal.ts +0 -83
  538. package/src/plugins/defaults/title-generate/terminal.ts +0 -31
  539. package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +0 -23
  540. package/src/plugins/defaults/token-estimate/package.json +0 -15
  541. package/src/plugins/defaults/token-estimate/register.ts +0 -34
  542. package/src/plugins/defaults/token-estimate/terminal.ts +0 -40
  543. package/src/plugins/defaults/tool-error/middlewares/toolError.ts +0 -21
  544. package/src/plugins/defaults/tool-error/terminal.ts +0 -47
  545. package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +0 -23
  546. package/src/plugins/defaults/tool-execute/package.json +0 -15
  547. package/src/plugins/defaults/tool-execute/register.ts +0 -49
  548. package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +0 -23
  549. package/src/plugins/defaults/tool-result-truncate/types.ts +0 -22
  550. package/src/skills/category-inference.ts +0 -111
  551. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/capabilities.test.ts +0 -0
  552. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/core.test.ts +0 -0
  553. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  554. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  555. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/needle.test.ts +0 -0
  556. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/snapshot.test.ts +0 -0
  557. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/tree.test.ts +0 -0
  558. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +0 -0
  559. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  560. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  561. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/core.ts +0 -0
  562. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  563. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  564. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  565. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  566. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  567. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  568. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/needle.ts +0 -0
  569. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/snapshot.ts +0 -0
  570. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +0 -0
@@ -55,12 +55,21 @@ interface TtsProviderCatalogCapabilities {
55
55
  readonly supportedFormats: readonly string[];
56
56
  }
57
57
 
58
+ /**
59
+ * Link to a provider's API-key management page, shown in settings UI.
60
+ */
61
+ interface TtsCredentialsGuide {
62
+ readonly description: string;
63
+ readonly url: string;
64
+ readonly linkLabel: string;
65
+ }
66
+
58
67
  /**
59
68
  * A single entry in the TTS provider catalog.
60
69
  *
61
70
  * Captures everything the system needs to know about a provider at a
62
71
  * metadata level — identity, display name, telephony call mode,
63
- * capabilities, and secret requirements.
72
+ * capabilities, secret requirements, and client-facing display metadata.
64
73
  */
65
74
  interface TtsProviderCatalogEntry {
66
75
  /** Unique provider identifier matching {@link TtsProviderId}. */
@@ -69,6 +78,18 @@ interface TtsProviderCatalogEntry {
69
78
  /** Human-readable name for display in settings UI and logs. */
70
79
  readonly displayName: string;
71
80
 
81
+ /** Short description shown beneath the provider name in settings UI. */
82
+ readonly subtitle: string;
83
+
84
+ /** Whether the provider supports user-chosen voice IDs. */
85
+ readonly supportsVoiceSelection: boolean;
86
+
87
+ /** Placeholder text for the API-key input in settings UI. */
88
+ readonly apiKeyPlaceholder: string;
89
+
90
+ /** Link to the provider's API-key management page. */
91
+ readonly credentialsGuide: TtsCredentialsGuide;
92
+
72
93
  /** How this provider integrates with the telephony call path. */
73
94
  readonly callMode: TtsCallMode;
74
95
 
@@ -106,6 +127,16 @@ const CATALOG: readonly TtsProviderCatalogEntry[] = [
106
127
  {
107
128
  id: "elevenlabs",
108
129
  displayName: "ElevenLabs",
130
+ subtitle:
131
+ "High-quality voice synthesis for conversations and read-aloud. Requires an ElevenLabs API key.",
132
+ supportsVoiceSelection: true,
133
+ apiKeyPlaceholder: "sk_…",
134
+ credentialsGuide: {
135
+ description:
136
+ "Sign in to ElevenLabs, go to your Profile, and copy your API key.",
137
+ url: "https://elevenlabs.io/app/settings/api-keys",
138
+ linkLabel: "Open ElevenLabs API Keys",
139
+ },
109
140
  callMode: "native-twilio",
110
141
  allowNativeFallback: true,
111
142
  capabilities: {
@@ -124,6 +155,16 @@ const CATALOG: readonly TtsProviderCatalogEntry[] = [
124
155
  {
125
156
  id: "fish-audio",
126
157
  displayName: "Fish Audio",
158
+ subtitle:
159
+ "Natural-sounding voice synthesis with custom voice cloning. Requires a Fish Audio API key and voice reference ID.",
160
+ supportsVoiceSelection: true,
161
+ apiKeyPlaceholder: "Enter your Fish Audio API key",
162
+ credentialsGuide: {
163
+ description:
164
+ "Sign in to Fish Audio, navigate to API Keys in your dashboard, and create a new key.",
165
+ url: "https://fish.audio/app/api-keys/",
166
+ linkLabel: "Open Fish Audio API Keys",
167
+ },
127
168
  callMode: "synthesized-play",
128
169
  allowNativeFallback: true,
129
170
  capabilities: {
@@ -142,6 +183,16 @@ const CATALOG: readonly TtsProviderCatalogEntry[] = [
142
183
  {
143
184
  id: "deepgram",
144
185
  displayName: "Deepgram",
186
+ subtitle:
187
+ "Fast, accurate text-to-speech synthesis. Uses the same API key as Deepgram speech-to-text.",
188
+ supportsVoiceSelection: false,
189
+ apiKeyPlaceholder: "Enter your Deepgram API key",
190
+ credentialsGuide: {
191
+ description:
192
+ "Sign in to Deepgram, navigate to your API Keys page, and create or copy an existing key. This is the same key used for speech-to-text.",
193
+ url: "https://console.deepgram.com/",
194
+ linkLabel: "Open Deepgram Console",
195
+ },
145
196
  callMode: "synthesized-play",
146
197
  allowNativeFallback: false,
147
198
  capabilities: {
@@ -159,6 +210,16 @@ const CATALOG: readonly TtsProviderCatalogEntry[] = [
159
210
  {
160
211
  id: "xai",
161
212
  displayName: "xAI",
213
+ subtitle:
214
+ "Text-to-speech from xAI with expressive voices (eve, ara, rex, sal, leo). Requires an xAI API key.",
215
+ supportsVoiceSelection: false,
216
+ apiKeyPlaceholder: "Enter your xAI API key",
217
+ credentialsGuide: {
218
+ description:
219
+ "Sign in to the xAI console, navigate to API Keys, and create a new key.",
220
+ url: "https://console.x.ai/",
221
+ linkLabel: "Open xAI Console",
222
+ },
162
223
  callMode: "synthesized-play",
163
224
  allowNativeFallback: false,
164
225
  capabilities: {
@@ -199,6 +260,20 @@ export function listCatalogProviderIds(): TtsProviderId[] {
199
260
  return CATALOG.map((entry) => entry.id);
200
261
  }
201
262
 
263
+ /**
264
+ * List all catalog providers projected to client-facing display fields only.
265
+ */
266
+ export function listCatalogProvidersForDisplay() {
267
+ return CATALOG.map((e) => ({
268
+ id: e.id,
269
+ displayName: e.displayName,
270
+ subtitle: e.subtitle,
271
+ supportsVoiceSelection: e.supportsVoiceSelection,
272
+ apiKeyPlaceholder: e.apiKeyPlaceholder,
273
+ credentialsGuide: e.credentialsGuide,
274
+ }));
275
+ }
276
+
202
277
  /**
203
278
  * Look up a catalog entry by provider ID.
204
279
  *
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Async mutex for serializing access to a shared resource.
3
+ *
4
+ * Callers wait in FIFO order. `withLock(fn)` is the primary API —
5
+ * it acquires the lock, runs `fn`, and releases the lock when `fn`
6
+ * settles (even on throw).
7
+ *
8
+ * Used by git-service (per-workspace repo operations) and
9
+ * conversation-title-service (serial LLM calls) to prevent
10
+ * concurrent access to resources that cannot safely overlap.
11
+ */
12
+ export class Mutex {
13
+ private locked = false;
14
+ private waitQueue: Array<() => void> = [];
15
+
16
+ async acquire(): Promise<void> {
17
+ if (!this.locked) {
18
+ this.locked = true;
19
+ return;
20
+ }
21
+ await new Promise<void>((resolve) => {
22
+ this.waitQueue.push(resolve);
23
+ });
24
+ }
25
+
26
+ release(): void {
27
+ const next = this.waitQueue.shift();
28
+ if (next) {
29
+ next();
30
+ } else {
31
+ this.locked = false;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Execute `fn` while holding the lock.
37
+ * Automatically releases the lock when done, even if `fn` throws.
38
+ */
39
+ async withLock<T>(fn: () => Promise<T>): Promise<T> {
40
+ await this.acquire();
41
+ try {
42
+ return await fn();
43
+ } finally {
44
+ this.release();
45
+ }
46
+ }
47
+ }
@@ -12,6 +12,7 @@ import { promisify } from "node:util";
12
12
 
13
13
  import { getConfig } from "../config/loader.js";
14
14
  import { getLogger } from "../util/logger.js";
15
+ import { Mutex } from "../util/mutex.js";
15
16
  import { PromiseGuard } from "../util/promise-guard.js";
16
17
 
17
18
  const execFileAsync = promisify(execFile);
@@ -119,48 +120,6 @@ interface ExecError extends Error {
119
120
  code?: string | number;
120
121
  }
121
122
 
122
- /**
123
- * Simple mutex implementation for per-workspace git operation serialization.
124
- * Prevents concurrent git operations from corrupting the repository state.
125
- */
126
- class Mutex {
127
- private locked = false;
128
- private waitQueue: Array<() => void> = [];
129
-
130
- async acquire(): Promise<void> {
131
- if (!this.locked) {
132
- this.locked = true;
133
- return;
134
- }
135
- // Wait for the lock to be released
136
- await new Promise<void>((resolve) => {
137
- this.waitQueue.push(resolve);
138
- });
139
- }
140
-
141
- release(): void {
142
- const next = this.waitQueue.shift();
143
- if (next) {
144
- next();
145
- } else {
146
- this.locked = false;
147
- }
148
- }
149
-
150
- /**
151
- * Execute a function while holding the lock.
152
- * Automatically releases the lock when done, even if the function throws.
153
- */
154
- async withLock<T>(fn: () => Promise<T>): Promise<T> {
155
- await this.acquire();
156
- try {
157
- return await fn();
158
- } finally {
159
- this.release();
160
- }
161
- }
162
- }
163
-
164
123
  interface GitCommitMetadata {
165
124
  /** Optional metadata to include in the commit message or as git notes */
166
125
  [key: string]: unknown;
@@ -9,10 +9,9 @@ import type { WorkspaceMigration } from "./types.js";
9
9
  * `conversationSummarization` is invoked from `ContextWindowManager.
10
10
  * updateSummary()` during mid-loop compaction. Without a call-site entry it
11
11
  * falls through to `llm.default` (opus + `effort: "max"` + `thinking:
12
- * { enabled: true }` + `maxTokens: 64000`), which is far too expensive for
13
- * summarizing a ~150k-token transcript inside the agent-loop plugin
14
- * pipeline's 30s budget we were hitting `PluginTimeoutError` and hard-
15
- * failing the turn.
12
+ * { enabled: true }` + `maxTokens: 64000`), which is far too expensive and
13
+ * slow for summarizing a ~150k-token transcript inside the agent loop
14
+ * the summary call would stall the turn.
16
15
  *
17
16
  * This migration seeds `effort: "low"` and `thinking: { enabled: false }`
18
17
  * (and opus-4.7 as the model when absent) so the summary call runs cheaply
@@ -99,7 +98,7 @@ export const seedConversationSummarizationCallsiteMigration: WorkspaceMigration
99
98
  },
100
99
  down(_workspaceDir: string): void {
101
100
  // Forward-only: removing the seeded defaults would reintroduce the
102
- // 30s pipeline-budget timeout this migration fixes.
101
+ // expensive, slow summary call this migration fixes.
103
102
  },
104
103
  };
105
104
 
@@ -0,0 +1,51 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ const THIRTY_MINUTES_MS = 30 * 60 * 1000;
7
+ const SIXTY_MINUTES_MS = 60 * 60 * 1000;
8
+
9
+ /**
10
+ * Bump persisted heartbeat default from 30 minutes to 60 minutes.
11
+ *
12
+ * Migration 065 moved legacy 3h/6h defaults to 30 minutes. The schema default
13
+ * has since been raised to 60 minutes, but existing users whose config.json
14
+ * already has 1800000 persisted won't pick up the new default. This migration
15
+ * idempotently updates those configs.
16
+ */
17
+ export const bumpHeartbeatInterval30mTo60mMigration: WorkspaceMigration = {
18
+ id: "095-bump-heartbeat-interval-30m-to-60m",
19
+ description:
20
+ "Bump persisted heartbeat.intervalMs from 30 minutes to 60 minutes",
21
+ run(workspaceDir: string): void {
22
+ const configPath = join(workspaceDir, "config.json");
23
+ if (!existsSync(configPath)) return;
24
+
25
+ let config: Record<string, unknown>;
26
+ try {
27
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
28
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
29
+ config = raw as Record<string, unknown>;
30
+ } catch {
31
+ return;
32
+ }
33
+
34
+ const heartbeat = config.heartbeat;
35
+ if (!heartbeat || typeof heartbeat !== "object" || Array.isArray(heartbeat))
36
+ return;
37
+
38
+ const heartbeatConfig = heartbeat as Record<string, unknown>;
39
+ const intervalMs = heartbeatConfig.intervalMs;
40
+ if (typeof intervalMs !== "number" || intervalMs !== THIRTY_MINUTES_MS) {
41
+ return;
42
+ }
43
+
44
+ heartbeatConfig.intervalMs = SIXTY_MINUTES_MS;
45
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
46
+ },
47
+ down(_workspaceDir: string): void {
48
+ // Forward-only: cannot distinguish users who explicitly chose 60 minutes
49
+ // from those migrated by this migration.
50
+ },
51
+ };
@@ -0,0 +1,72 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ // Reduce effort from "max" to "high" on the quality-optimized profile.
7
+ //
8
+ // With adaptive thinking enabled, the effort parameter acts as a nudge for
9
+ // how much thinking the model does. "max" means "always think with no
10
+ // constraints on thinking depth", which defeats adaptive thinking's ability
11
+ // to skip or minimize thinking for simple queries. "high" (the API default)
12
+ // means "almost always thinks, deep reasoning on complex tasks" — letting
13
+ // adaptive thinking decide when full-depth reasoning is actually needed.
14
+ //
15
+ // This migration patches both managed and user quality-optimized profiles
16
+ // that still have effort: "max". It only downgrades "max" → "high"; any
17
+ // other effort value is preserved.
18
+
19
+ const TARGET_PROFILES = ["quality-optimized", "custom-quality-optimized"];
20
+
21
+ export const reduceQualityProfileEffortMigration: WorkspaceMigration = {
22
+ id: "096-reduce-quality-profile-effort",
23
+ description:
24
+ 'Reduce effort from "max" to "high" on quality-optimized profiles to let adaptive thinking work',
25
+ run(workspaceDir: string): void {
26
+ const configPath = join(workspaceDir, "config.json");
27
+ if (!existsSync(configPath)) return;
28
+
29
+ let config: Record<string, unknown>;
30
+ try {
31
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
32
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
33
+ config = raw as Record<string, unknown>;
34
+ } catch {
35
+ return;
36
+ }
37
+
38
+ const llm = readObject(config.llm);
39
+ if (llm === null) return;
40
+
41
+ const profiles = readObject(llm.profiles);
42
+ if (profiles === null) return;
43
+
44
+ let changed = false;
45
+
46
+ for (const name of TARGET_PROFILES) {
47
+ const profile = readObject(profiles[name]);
48
+ if (profile === null) continue;
49
+ if (profile.effort !== "max") continue;
50
+
51
+ profile.effort = "high";
52
+ profiles[name] = profile;
53
+ changed = true;
54
+ }
55
+
56
+ if (changed) {
57
+ llm.profiles = profiles;
58
+ config.llm = llm;
59
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
60
+ }
61
+ },
62
+ down(_workspaceDir: string): void {
63
+ // Forward-only.
64
+ },
65
+ };
66
+
67
+ function readObject(value: unknown): Record<string, unknown> | null {
68
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
69
+ return null;
70
+ }
71
+ return value as Record<string, unknown>;
72
+ }
@@ -0,0 +1,117 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { WorkspaceMigration } from "./types.js";
5
+
6
+ // Enable adaptive thinking on the managed "balanced" and "quality-optimized"
7
+ // profiles for existing platform instances.
8
+ //
9
+ // The assistant-side seed defaults (MANAGED_PROFILE_TEMPLATES in
10
+ // seed-inference-profiles.ts) already ship thinking: { enabled: true,
11
+ // streamThinking: true } for both profiles, which normalizes to
12
+ // { type: "adaptive" } on the wire. Off-platform (BYOK) instances pick this
13
+ // up on every boot because the seeder overwrites managed profiles. On-platform
14
+ // instances preserve existing profiles (the platform overlay is authoritative),
15
+ // so instances that were hatched before thinking was enabled in the templates
16
+ // are stuck with thinking disabled or absent.
17
+ //
18
+ // This migration patches the on-disk config for both profiles, adding
19
+ // thinking: { enabled: true, streamThinking: true } where it's missing or
20
+ // explicitly disabled. It skips profiles that:
21
+ // - Don't exist (no profile to patch)
22
+ // - Already have thinking enabled (idempotent)
23
+ // - Are source: "user" (user-created profiles are untouched)
24
+ // - Have a non-managed, non-absent source (unknown origin)
25
+ // - Use a non-Anthropic provider (adaptive thinking is Anthropic-specific)
26
+
27
+ const ADAPTIVE_THINKING = { enabled: true, streamThinking: true } as const;
28
+ const TARGET_PROFILES = ["balanced", "quality-optimized"] as const;
29
+
30
+ /**
31
+ * Patch managed Anthropic profiles that are missing adaptive thinking.
32
+ *
33
+ * Exported so lifecycle.ts can re-run the repair after mergeDefaultWorkspaceConfig()
34
+ * and seedInferenceProfiles(). On-platform instances with a config overlay have their
35
+ * profiles overwritten by the overlay merge (which runs after workspace migrations),
36
+ * so the migration alone is insufficient — the post-overlay call ensures the repair
37
+ * sticks even when the overlay supplies profiles without thinking enabled.
38
+ *
39
+ * The function is idempotent: profiles that already have thinking enabled are skipped.
40
+ */
41
+ export function repairAdaptiveThinkingOnManagedProfiles(
42
+ workspaceDir: string,
43
+ ): void {
44
+ const configPath = join(workspaceDir, "config.json");
45
+ if (!existsSync(configPath)) return;
46
+
47
+ let config: Record<string, unknown>;
48
+ try {
49
+ const raw = JSON.parse(readFileSync(configPath, "utf-8"));
50
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
51
+ config = raw as Record<string, unknown>;
52
+ } catch {
53
+ return;
54
+ }
55
+
56
+ const llm = readObject(config.llm);
57
+ if (llm === null) return;
58
+
59
+ const profiles = readObject(llm.profiles);
60
+ if (profiles === null) return;
61
+
62
+ let changed = false;
63
+
64
+ for (const name of TARGET_PROFILES) {
65
+ const profile = readObject(profiles[name]);
66
+ if (profile === null) continue;
67
+
68
+ // Only patch managed Anthropic profiles.
69
+ // Legacy profiles created before the `source` metadata field was introduced
70
+ // have source=undefined. Treat these as managed when the profile name is one
71
+ // of the canonical managed names (which TARGET_PROFILES already guarantees)
72
+ // and the provider is Anthropic (or absent). Explicit `source: "user"`
73
+ // profiles are always skipped.
74
+ if (profile.source === "user") continue;
75
+ if (profile.source !== undefined && profile.source !== "managed") continue;
76
+ if (
77
+ typeof profile.provider === "string" &&
78
+ profile.provider !== "anthropic"
79
+ ) {
80
+ continue;
81
+ }
82
+
83
+ // Skip if thinking is already enabled.
84
+ const thinking = readObject(profile.thinking);
85
+ if (thinking !== null && thinking.enabled === true) continue;
86
+
87
+ profile.thinking = { ...ADAPTIVE_THINKING };
88
+ profiles[name] = profile;
89
+ changed = true;
90
+ }
91
+
92
+ if (changed) {
93
+ llm.profiles = profiles;
94
+ config.llm = llm;
95
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
96
+ }
97
+ }
98
+
99
+ export const enableAdaptiveThinkingManagedProfilesMigration: WorkspaceMigration =
100
+ {
101
+ id: "097-enable-adaptive-thinking-managed-profiles",
102
+ description:
103
+ "Enable adaptive thinking on managed balanced and quality-optimized profiles",
104
+ run(workspaceDir: string): void {
105
+ repairAdaptiveThinkingOnManagedProfiles(workspaceDir);
106
+ },
107
+ down(_workspaceDir: string): void {
108
+ // Forward-only.
109
+ },
110
+ };
111
+
112
+ function readObject(value: unknown): Record<string, unknown> | null {
113
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
114
+ return null;
115
+ }
116
+ return value as Record<string, unknown>;
117
+ }
@@ -92,6 +92,9 @@ import { retightenMigrationOnboardingThreadMigration } from "./091-retighten-mig
92
92
  import { backfillV3LeavesMigration } from "./092-backfill-v3-leaves.js";
93
93
  import { backfillLeafIdsMigration } from "./093-backfill-leaf-ids.js";
94
94
  import { seedAvatarManifestMigration } from "./094-seed-avatar-manifest.js";
95
+ import { bumpHeartbeatInterval30mTo60mMigration } from "./095-bump-heartbeat-interval-30m-to-60m.js";
96
+ import { reduceQualityProfileEffortMigration } from "./096-reduce-quality-profile-effort.js";
97
+ import { enableAdaptiveThinkingManagedProfilesMigration } from "./097-enable-adaptive-thinking-managed-profiles.js";
95
98
  import { migrateToWorkspaceVolumeMigration } from "./migrate-to-workspace-volume.js";
96
99
  import type { WorkspaceMigration } from "./types.js";
97
100
 
@@ -195,4 +198,7 @@ export const WORKSPACE_MIGRATIONS: WorkspaceMigration[] = [
195
198
  backfillV3LeavesMigration,
196
199
  backfillLeafIdsMigration,
197
200
  seedAvatarManifestMigration,
201
+ bumpHeartbeatInterval30mTo60mMigration,
202
+ reduceQualityProfileEffortMigration,
203
+ enableAdaptiveThinkingManagedProfilesMigration,
198
204
  ];