@vellumai/assistant 0.8.4 → 0.8.5

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 (438) hide show
  1. package/ARCHITECTURE.md +2 -2
  2. package/docs/browser-use-architecture-phase2.md +1 -1
  3. package/knip.json +2 -1
  4. package/openapi.yaml +809 -11
  5. package/package.json +1 -1
  6. package/src/__tests__/anthropic-provider.test.ts +34 -37
  7. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  8. package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
  9. package/src/__tests__/audit-log-rotation.test.ts +70 -16
  10. package/src/__tests__/background-workers-disk-pressure.test.ts +3 -3
  11. package/src/__tests__/btw-routes.test.ts +2 -3
  12. package/src/__tests__/call-controller.test.ts +0 -1
  13. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  14. package/src/__tests__/channel-guardian.test.ts +3 -3
  15. package/src/__tests__/checker.test.ts +6 -15
  16. package/src/__tests__/compaction-events.test.ts +1 -0
  17. package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
  18. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
  19. package/src/__tests__/computer-use-tools.test.ts +2 -4
  20. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  21. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
  22. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
  23. package/src/__tests__/conversation-agent-loop-overflow.test.ts +197 -2
  24. package/src/__tests__/conversation-agent-loop.test.ts +163 -122
  25. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
  26. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  27. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  28. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  29. package/src/__tests__/conversation-error.test.ts +31 -0
  30. package/src/__tests__/conversation-fork-crud.test.ts +178 -15
  31. package/src/__tests__/conversation-lifecycle.test.ts +52 -11
  32. package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +13 -13
  33. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -0
  34. package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
  35. package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
  36. package/src/__tests__/conversation-skill-tools.test.ts +2 -5
  37. package/src/__tests__/conversation-store.test.ts +1 -1
  38. package/src/__tests__/conversation-sync-tags.test.ts +99 -32
  39. package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
  40. package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
  41. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
  42. package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
  43. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  44. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  45. package/src/__tests__/credential-vault-unit.test.ts +2 -2
  46. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  47. package/src/__tests__/email-html-renderer.test.ts +12 -0
  48. package/src/__tests__/gateway-flag-listener.test.ts +237 -0
  49. package/src/__tests__/gemini-provider.test.ts +78 -0
  50. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  51. package/src/__tests__/guardian-outbound-http.test.ts +7 -5
  52. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  53. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  54. package/src/__tests__/heartbeat-service.test.ts +4 -0
  55. package/src/__tests__/host-shell-tool.test.ts +1 -1
  56. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  57. package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
  58. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  59. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  60. package/src/__tests__/llm-resolver.test.ts +77 -9
  61. package/src/__tests__/llm-usage-store.test.ts +66 -0
  62. package/src/__tests__/logger.test.ts +89 -0
  63. package/src/__tests__/mcp-abort-signal.test.ts +2 -2
  64. package/src/__tests__/media-generate-image.test.ts +31 -0
  65. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  66. package/src/__tests__/model-intents.test.ts +2 -4
  67. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  68. package/src/__tests__/onboarding-template-contract.test.ts +1 -1
  69. package/src/__tests__/openai-provider.test.ts +46 -0
  70. package/src/__tests__/openai-responses-provider.test.ts +114 -12
  71. package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
  72. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  73. package/src/__tests__/platform.test.ts +2 -2
  74. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  75. package/src/__tests__/plugin-bootstrap.test.ts +2 -2
  76. package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
  77. package/src/__tests__/plugin-types.test.ts +3 -2
  78. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  79. package/src/__tests__/pricing.test.ts +12 -0
  80. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  81. package/src/__tests__/registry.test.ts +2 -8
  82. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  83. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  84. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  85. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  86. package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
  87. package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
  88. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  89. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  90. package/src/__tests__/suggestion-routes.test.ts +1 -0
  91. package/src/__tests__/sync-message-contract.test.ts +59 -0
  92. package/src/__tests__/system-prompt.test.ts +145 -131
  93. package/src/__tests__/terminal-tools.test.ts +1 -1
  94. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  95. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  96. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  97. package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
  98. package/src/__tests__/tool-executor.test.ts +9 -62
  99. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  100. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  101. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  102. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  103. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  104. package/src/__tests__/usage-routes.test.ts +3 -0
  105. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  106. package/src/__tests__/workspace-git-service.test.ts +6 -5
  107. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  108. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  109. package/src/acp/prepare-agent-env.ts +78 -0
  110. package/src/acp/session-manager.ts +1 -1
  111. package/src/agent/loop.ts +8 -0
  112. package/src/api/README.md +5 -0
  113. package/src/api/index.ts +4 -0
  114. package/src/api/package.json +10 -0
  115. package/src/background-wake/background-wake-routes.test.ts +233 -0
  116. package/src/background-wake/runtime-registry.ts +24 -0
  117. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  118. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  119. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  120. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  121. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  122. package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
  123. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  124. package/src/cli/commands/browser.ts +247 -0
  125. package/src/cli/commands/domain.ts +91 -41
  126. package/src/cli/commands/inference.ts +93 -40
  127. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  128. package/src/cli/commands/memory-v2.ts +176 -1
  129. package/src/cli/commands/memory-v3-render.ts +344 -0
  130. package/src/cli/commands/memory-v3.ts +316 -0
  131. package/src/cli/program.ts +2 -0
  132. package/src/config/assistant-feature-flags.ts +21 -9
  133. package/src/config/bundled-skills/document-editor/SKILL.md +11 -2
  134. package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
  135. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  136. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  137. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  138. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  139. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  140. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  141. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  142. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  143. package/src/config/bundled-tool-registry.ts +2 -0
  144. package/src/config/call-site-defaults.ts +7 -6
  145. package/src/config/feature-flag-registry.json +16 -0
  146. package/src/config/schemas/__tests__/memory-v2.test.ts +213 -1
  147. package/src/config/schemas/call-site-catalog.ts +21 -7
  148. package/src/config/schemas/llm.ts +12 -1
  149. package/src/config/schemas/memory-v2.ts +246 -0
  150. package/src/config/schemas/memory.ts +2 -1
  151. package/src/context/compactor.ts +52 -0
  152. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  153. package/src/conversations/message-consolidation.ts +404 -0
  154. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
  155. package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
  156. package/src/daemon/conversation-agent-loop-handlers.ts +2 -13
  157. package/src/daemon/conversation-agent-loop.ts +126 -76
  158. package/src/daemon/conversation-error.ts +31 -1
  159. package/src/daemon/conversation-lifecycle.ts +27 -22
  160. package/src/daemon/conversation-runtime-assembly.ts +10 -9
  161. package/src/daemon/conversation-tool-setup.ts +63 -3
  162. package/src/daemon/conversation-usage.ts +2 -0
  163. package/src/daemon/conversation.ts +14 -29
  164. package/src/daemon/disk-pressure-guard.ts +14 -2
  165. package/src/daemon/handlers/config-model.test.ts +1 -0
  166. package/src/daemon/handlers/conversations.ts +11 -3
  167. package/src/daemon/host-browser-proxy.ts +5 -5
  168. package/src/daemon/host-cu-proxy.ts +4 -4
  169. package/src/daemon/host-file-proxy.ts +4 -4
  170. package/src/daemon/host-proxy-base.ts +4 -4
  171. package/src/daemon/host-transfer-proxy.ts +10 -10
  172. package/src/daemon/lifecycle.ts +23 -20
  173. package/src/daemon/meet-manifest-loader.ts +1 -7
  174. package/src/daemon/message-types/conversations.ts +6 -9
  175. package/src/daemon/message-types/home.ts +1 -13
  176. package/src/daemon/message-types/messages.ts +6 -14
  177. package/src/daemon/message-types/sync.ts +14 -0
  178. package/src/daemon/shutdown-handlers.ts +24 -5
  179. package/src/daemon/switch-inference-profile-tool.ts +52 -0
  180. package/src/daemon/tool-setup-types.ts +13 -0
  181. package/src/events/relationship-state-updated.ts +25 -0
  182. package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -1
  183. package/src/home/home-greeting.ts +0 -9
  184. package/src/home/suggested-prompts.ts +0 -9
  185. package/src/ipc/gateway-flag-listener.ts +123 -0
  186. package/src/ipc/skill-routes/registries.ts +8 -12
  187. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  188. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  189. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
  190. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  191. package/src/memory/__tests__/memory-retrospective-job.test.ts +7 -0
  192. package/src/memory/auto-analysis-enqueue.ts +5 -1
  193. package/src/memory/conversation-crud.ts +71 -70
  194. package/src/memory/conversation-starters-cadence.ts +3 -1
  195. package/src/memory/conversation-title-service.ts +19 -3
  196. package/src/memory/db-async-query.ts +214 -0
  197. package/src/memory/db-init.ts +10 -0
  198. package/src/memory/db-maintenance.ts +30 -21
  199. package/src/memory/graph/bootstrap.ts +8 -1
  200. package/src/memory/graph/capability-seed.ts +7 -3
  201. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  202. package/src/memory/graph/extraction.ts +1 -5
  203. package/src/memory/graph/graph-search.ts +7 -1
  204. package/src/memory/indexer.ts +28 -18
  205. package/src/memory/job-handlers/cleanup.ts +76 -18
  206. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  207. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  208. package/src/memory/jobs-store.ts +14 -0
  209. package/src/memory/jobs-worker.ts +55 -22
  210. package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
  211. package/src/memory/llm-request-log-source-local.ts +7 -0
  212. package/src/memory/llm-request-log-source.ts +9 -2
  213. package/src/memory/llm-request-log-store.ts +43 -1
  214. package/src/memory/llm-usage-store.ts +24 -0
  215. package/src/memory/memory-retrospective-enqueue.ts +8 -1
  216. package/src/memory/memory-retrospective-job.ts +5 -0
  217. package/src/memory/memory-v2-activation-log-store.ts +15 -6
  218. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  219. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  220. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  221. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  222. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  223. package/src/memory/migrations/index.ts +17 -0
  224. package/src/memory/migrations/registry.ts +33 -0
  225. package/src/memory/schema/conversations.ts +1 -1
  226. package/src/memory/schema/infrastructure.ts +21 -0
  227. package/src/memory/tool-usage-store.ts +36 -8
  228. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  229. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  230. package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
  231. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  232. package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
  233. package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
  234. package/src/memory/v2/__tests__/injection.test.ts +127 -98
  235. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  236. package/src/memory/v2/__tests__/router.test.ts +171 -3
  237. package/src/memory/v2/harness/compare.ts +57 -0
  238. package/src/memory/v2/harness/metrics.ts +124 -0
  239. package/src/memory/v2/harness/oracle.ts +145 -0
  240. package/src/memory/v2/harness/replay-input.ts +224 -0
  241. package/src/memory/v2/harness/retriever.ts +74 -0
  242. package/src/memory/v2/harness/router-retriever.ts +43 -0
  243. package/src/memory/v2/harness/runner.ts +106 -0
  244. package/src/memory/v2/harness/trace.ts +58 -0
  245. package/src/memory/v2/injection.ts +21 -15
  246. package/src/memory/v2/prompts/router.ts +26 -1
  247. package/src/memory/v2/qdrant.ts +14 -2
  248. package/src/memory/v2/router.ts +171 -18
  249. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  250. package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
  251. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  252. package/src/memory/v3/__tests__/edges.test.ts +563 -0
  253. package/src/memory/v3/__tests__/filter.test.ts +512 -0
  254. package/src/memory/v3/__tests__/gate.test.ts +574 -0
  255. package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
  256. package/src/memory/v3/__tests__/loop.test.ts +530 -0
  257. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  258. package/src/memory/v3/__tests__/scouts.test.ts +440 -0
  259. package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
  260. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  261. package/src/memory/v3/__tests__/traversal.test.ts +469 -0
  262. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  263. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  264. package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
  265. package/src/memory/v3/__tests__/validate.test.ts +245 -0
  266. package/src/memory/v3/auto-edges.ts +223 -0
  267. package/src/memory/v3/coactivation-store.ts +124 -0
  268. package/src/memory/v3/consolidation-job.ts +323 -0
  269. package/src/memory/v3/edge-learning-job.ts +160 -0
  270. package/src/memory/v3/edges.ts +249 -0
  271. package/src/memory/v3/filter.ts +281 -0
  272. package/src/memory/v3/gate.ts +334 -0
  273. package/src/memory/v3/index-composition.ts +113 -0
  274. package/src/memory/v3/llm-capture.ts +46 -0
  275. package/src/memory/v3/loop.ts +382 -0
  276. package/src/memory/v3/maintenance.ts +144 -0
  277. package/src/memory/v3/prompt-context.ts +33 -0
  278. package/src/memory/v3/prompts/consolidation.ts +458 -0
  279. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  280. package/src/memory/v3/retriever.ts +33 -0
  281. package/src/memory/v3/scouts.ts +420 -0
  282. package/src/memory/v3/shadow-middleware.ts +305 -0
  283. package/src/memory/v3/traversal.ts +206 -0
  284. package/src/memory/v3/tree-index.ts +237 -0
  285. package/src/memory/v3/tree-store.ts +394 -0
  286. package/src/memory/v3/tree-walk.ts +351 -0
  287. package/src/memory/v3/types.ts +65 -0
  288. package/src/memory/v3/validate.ts +300 -0
  289. package/src/notifications/adapters/macos.ts +18 -1
  290. package/src/notifications/adapters/platform.ts +1 -1
  291. package/src/notifications/decision-engine.ts +1 -4
  292. package/src/notifications/emit-signal.ts +29 -49
  293. package/src/permissions/prompter.ts +3 -3
  294. package/src/permissions/question-prompter.ts +5 -2
  295. package/src/permissions/secret-prompter.ts +2 -2
  296. package/src/plugin-api/index.ts +4 -0
  297. package/src/plugin-api/types.ts +7 -33
  298. package/src/plugins/defaults/index.ts +6 -0
  299. package/src/plugins/defaults/injectors.ts +18 -11
  300. package/src/plugins/external-plugin-loader.ts +5 -68
  301. package/src/plugins/types.ts +11 -16
  302. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  303. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  304. package/src/prompts/persona-resolver.ts +36 -21
  305. package/src/prompts/sections.ts +39 -7
  306. package/src/prompts/system-prompt.ts +50 -185
  307. package/src/prompts/templates/BOOTSTRAP.md +2 -2
  308. package/src/prompts/templates/system-sections.ts +230 -8
  309. package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
  310. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  311. package/src/providers/anthropic/client.ts +32 -66
  312. package/src/providers/call-site-routing.ts +14 -2
  313. package/src/providers/connection-model-compat.ts +38 -0
  314. package/src/providers/connection-resolution.ts +16 -2
  315. package/src/providers/gemini/client.ts +49 -6
  316. package/src/providers/inference/adapter-factory.ts +3 -0
  317. package/src/providers/minimax/client.ts +106 -0
  318. package/src/providers/model-catalog.ts +43 -0
  319. package/src/providers/model-intents.ts +1 -1
  320. package/src/providers/openai/chat-completions-provider.ts +6 -3
  321. package/src/providers/openai/codex-models.ts +18 -0
  322. package/src/providers/openai/responses-provider.ts +78 -21
  323. package/src/providers/provider-send-message.ts +7 -1
  324. package/src/providers/retry.ts +34 -3
  325. package/src/providers/thinking-config.ts +26 -1
  326. package/src/providers/usage-tracking.ts +2 -0
  327. package/src/runtime/AGENTS.md +2 -2
  328. package/src/runtime/agent-wake.ts +1 -0
  329. package/src/runtime/assistant-event-hub.ts +76 -6
  330. package/src/runtime/auth/route-policy.ts +36 -0
  331. package/src/runtime/btw-sidechain.ts +0 -6
  332. package/src/runtime/http-types.ts +0 -2
  333. package/src/runtime/migrations/vbundle-builder.ts +10 -3
  334. package/src/runtime/pending-interactions.ts +0 -1
  335. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +106 -0
  336. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +25 -6
  337. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  338. package/src/runtime/routes/acp-routes.test.ts +255 -6
  339. package/src/runtime/routes/acp-routes.ts +8 -1
  340. package/src/runtime/routes/avatar-routes.ts +10 -10
  341. package/src/runtime/routes/background-wake-routes.ts +188 -0
  342. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  343. package/src/runtime/routes/btw-routes.ts +0 -6
  344. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  345. package/src/runtime/routes/conversation-list-routes.ts +12 -4
  346. package/src/runtime/routes/conversation-management-routes.ts +77 -20
  347. package/src/runtime/routes/conversation-query-routes.ts +142 -36
  348. package/src/runtime/routes/conversation-routes.ts +252 -410
  349. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  350. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  351. package/src/runtime/routes/domain-routes.ts +60 -10
  352. package/src/runtime/routes/email-routes.ts +5 -2
  353. package/src/runtime/routes/events-routes.ts +54 -10
  354. package/src/runtime/routes/group-routes.ts +24 -8
  355. package/src/runtime/routes/host-browser-routes.ts +10 -2
  356. package/src/runtime/routes/host-cu-routes.ts +2 -2
  357. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  358. package/src/runtime/routes/index.ts +8 -0
  359. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  360. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  361. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  362. package/src/runtime/routes/memory-item-routes.ts +8 -3
  363. package/src/runtime/routes/memory-v2-routes.ts +215 -5
  364. package/src/runtime/routes/memory-v3-routes.ts +316 -0
  365. package/src/runtime/routes/migration-routes.ts +21 -24
  366. package/src/runtime/routes/plugins-routes.ts +337 -0
  367. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  368. package/src/runtime/routes/secret-routes.ts +25 -5
  369. package/src/runtime/routes/settings-routes.ts +12 -11
  370. package/src/runtime/routes/slack-channel-routes.ts +5 -4
  371. package/src/runtime/routes/workspace-routes.ts +25 -10
  372. package/src/runtime/sync/resource-sync-events.ts +106 -38
  373. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  374. package/src/runtime/sync/sync-publisher.ts +2 -1
  375. package/src/runtime/verification-outbound-actions.ts +73 -1
  376. package/src/telemetry/types.ts +12 -0
  377. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  378. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  379. package/src/tools/acp/spawn.test.ts +119 -0
  380. package/src/tools/acp/spawn.ts +15 -2
  381. package/src/tools/apps/definitions.ts +2 -8
  382. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  383. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  384. package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
  385. package/src/tools/browser/browser-execution.ts +16 -3
  386. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  387. package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
  388. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
  389. package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
  390. package/src/tools/browser/cdp-client/factory.ts +100 -17
  391. package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
  392. package/src/tools/browser/cdp-client/types.ts +65 -0
  393. package/src/tools/browser/pinned-tabs.ts +96 -40
  394. package/src/tools/computer-use/definitions.ts +22 -78
  395. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  396. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  397. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  398. package/src/tools/credentials/vault.ts +3 -9
  399. package/src/tools/document/document-tool.ts +59 -0
  400. package/src/tools/execution-target.ts +21 -23
  401. package/src/tools/executor.ts +6 -1
  402. package/src/tools/filesystem/edit.ts +3 -9
  403. package/src/tools/filesystem/list.ts +3 -9
  404. package/src/tools/filesystem/read.ts +3 -9
  405. package/src/tools/filesystem/write.ts +3 -9
  406. package/src/tools/host-filesystem/edit.ts +3 -9
  407. package/src/tools/host-filesystem/read.ts +3 -9
  408. package/src/tools/host-filesystem/transfer.ts +3 -9
  409. package/src/tools/host-filesystem/write.ts +3 -9
  410. package/src/tools/host-terminal/host-shell.ts +3 -9
  411. package/src/tools/mcp/mcp-tool-factory.ts +1 -8
  412. package/src/tools/memory/register.test.ts +1 -1
  413. package/src/tools/memory/register.ts +4 -9
  414. package/src/tools/network/web-fetch.ts +3 -9
  415. package/src/tools/network/web-search.ts +25 -32
  416. package/src/tools/registry.ts +7 -23
  417. package/src/tools/schema-transforms.ts +1 -1
  418. package/src/tools/skills/execute.ts +3 -9
  419. package/src/tools/skills/load.ts +3 -9
  420. package/src/tools/skills/skill-tool-factory.ts +1 -8
  421. package/src/tools/subagent/notify-parent.ts +3 -9
  422. package/src/tools/system/request-permission.ts +3 -9
  423. package/src/tools/terminal/shell.ts +3 -9
  424. package/src/tools/tool-defaults.ts +94 -0
  425. package/src/tools/types.ts +27 -98
  426. package/src/tools/ui-surface/definitions.ts +6 -22
  427. package/src/usage/pricing.ts +23 -0
  428. package/src/usage/types.ts +12 -0
  429. package/src/util/logger.ts +16 -7
  430. package/src/util/platform.ts +7 -2
  431. package/src/util/sqlite3-runtime.ts +65 -0
  432. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  433. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  434. package/src/workspace/migrations/registry.ts +2 -0
  435. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  436. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  437. package/src/daemon/query-complexity-router.ts +0 -75
  438. package/src/prompts/cache-boundary.ts +0 -8
@@ -84,6 +84,7 @@ const SAMPLE_ROW = {
84
84
  // ClickHouse emits Int64 as a quoted string under JSONEachRow by default.
85
85
  created_at: "1778465138786",
86
86
  agent_loop_exit_reason: "no_tool_calls",
87
+ call_site: "mainAgent",
87
88
  };
88
89
 
89
90
  describe("ClickHouseLlmRequestLogSource", () => {
@@ -104,6 +105,7 @@ describe("ClickHouseLlmRequestLogSource", () => {
104
105
  responsePayload: '{"bar":2}',
105
106
  createdAt: 1778465138786,
106
107
  agentLoopExitReason: "no_tool_calls",
108
+ callSite: "mainAgent",
107
109
  });
108
110
  });
109
111
 
@@ -164,6 +166,30 @@ describe("ClickHouseLlmRequestLogSource", () => {
164
166
  expect(rows).toEqual([]);
165
167
  });
166
168
 
169
+ test("getRequestLogsByConversationId binds conversation id via parameterized placeholder", async () => {
170
+ // Regression guard: the conversation id flows from user-controlled
171
+ // input (conversationKey → conversations.id), so it must travel as a
172
+ // typed parameter, never as an inline string literal.
173
+ const recorder: FakeFetchCall[] = [];
174
+ const malicious = "conv-1' OR 1=1 --";
175
+ const src = makeSource({
176
+ body: JSON.stringify(SAMPLE_ROW) + "\n",
177
+ recorder,
178
+ });
179
+ const rows = await src.getRequestLogsByConversationId(malicious);
180
+ expect(rows).toHaveLength(1);
181
+ expect(recorder).toHaveLength(1);
182
+ const call = recorder[0]!;
183
+ const parsed = new URL(call.url);
184
+ expect(parsed.searchParams.get("param_assistant_id")).toBe(
185
+ "asst-fixture-001",
186
+ );
187
+ expect(parsed.searchParams.get("param_conversation_id")).toBe(malicious);
188
+ const body = String(call.init?.body ?? "");
189
+ expect(body).toContain("conversation_id = {conversation_id:String}");
190
+ expect(body).not.toContain(`'${malicious}'`);
191
+ });
192
+
167
193
  test("getRequestLogsByMessageId binds message ids via parameterized placeholders", async () => {
168
194
  // Regression for ATL-537. `getAssistantMessageIdsInTurn` returns the
169
195
  // caller-supplied id straight through when the message lookup misses,
@@ -2,7 +2,10 @@ import { describe, expect, test } from "bun:test";
2
2
 
3
3
  import { z } from "zod";
4
4
 
5
- import { resolveCallSiteConfig, resolveDefaultProfileKey } from "../config/llm-resolver.js";
5
+ import {
6
+ resolveCallSiteConfig,
7
+ resolveDefaultProfileKey,
8
+ } from "../config/llm-resolver.js";
6
9
  import { type LLMCallSite, LLMSchema } from "../config/schemas/llm.js";
7
10
 
8
11
  const fullDefault = {
@@ -690,13 +693,28 @@ describe("resolveCallSiteConfig", () => {
690
693
  });
691
694
 
692
695
  const callSites: LLMCallSite[] = [
693
- "mainAgent", "subagentSpawn", "heartbeatAgent", "filingAgent",
694
- "compactionAgent", "analyzeConversation", "callAgent",
695
- "memoryExtraction", "memoryConsolidation", "memoryRetrieval",
696
- "memoryRouter", "recall", "conversationSummarization",
697
- "commitMessage", "conversationStarters", "replySuggestion",
698
- "conversationTitle", "identityIntro", "emptyStateGreeting",
699
- "notificationDecision", "interactionClassifier", "inference",
696
+ "mainAgent",
697
+ "subagentSpawn",
698
+ "heartbeatAgent",
699
+ "filingAgent",
700
+ "compactionAgent",
701
+ "analyzeConversation",
702
+ "callAgent",
703
+ "memoryExtraction",
704
+ "memoryConsolidation",
705
+ "memoryRetrieval",
706
+ "memoryRouter",
707
+ "recall",
708
+ "conversationSummarization",
709
+ "commitMessage",
710
+ "conversationStarters",
711
+ "replySuggestion",
712
+ "conversationTitle",
713
+ "identityIntro",
714
+ "emptyStateGreeting",
715
+ "notificationDecision",
716
+ "interactionClassifier",
717
+ "inference",
700
718
  ];
701
719
 
702
720
  for (const cs of callSites) {
@@ -778,7 +796,10 @@ describe("resolveCallSiteConfig", () => {
778
796
  provider_connection: "anthropic-managed",
779
797
  },
780
798
  profiles: {
781
- fireworks: { provider: "fireworks", model: "accounts/fireworks/models/kimi-k2p5" },
799
+ fireworks: {
800
+ provider: "fireworks",
801
+ model: "accounts/fireworks/models/kimi-k2p5",
802
+ },
782
803
  },
783
804
  activeProfile: "fireworks",
784
805
  });
@@ -874,3 +895,50 @@ describe("resolveDefaultProfileKey", () => {
874
895
  );
875
896
  });
876
897
  });
898
+
899
+ describe("memory v3 call sites resolve through the standard resolver", () => {
900
+ const llm = LLMSchema.parse({
901
+ default: fullDefault,
902
+ profiles: {
903
+ balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
904
+ "cost-optimized": {
905
+ provider: "anthropic",
906
+ model: "claude-haiku-4-5-20251001",
907
+ },
908
+ },
909
+ });
910
+
911
+ test("memoryV3Filter and memoryV3Descent resolve to the cost-optimized profile", () => {
912
+ expect(resolveDefaultProfileKey("memoryV3Filter", llm)).toBe(
913
+ "cost-optimized",
914
+ );
915
+ expect(resolveDefaultProfileKey("memoryV3Descent", llm)).toBe(
916
+ "cost-optimized",
917
+ );
918
+ expect(resolveCallSiteConfig("memoryV3Filter", llm).model).toBe(
919
+ "claude-haiku-4-5-20251001",
920
+ );
921
+ expect(resolveCallSiteConfig("memoryV3Descent", llm).model).toBe(
922
+ "claude-haiku-4-5-20251001",
923
+ );
924
+ });
925
+
926
+ test("memoryV3Gate resolves to the balanced (capable) profile", () => {
927
+ expect(resolveDefaultProfileKey("memoryV3Gate", llm)).toBe("balanced");
928
+ expect(resolveCallSiteConfig("memoryV3Gate", llm).model).toBe(
929
+ "claude-sonnet-4-7",
930
+ );
931
+ });
932
+
933
+ test("v3 call sites are addressable as call-site override keys", () => {
934
+ const overridden = LLMSchema.parse({
935
+ default: fullDefault,
936
+ callSites: {
937
+ memoryV3Gate: { model: "claude-opus-4-7" },
938
+ },
939
+ });
940
+ expect(resolveCallSiteConfig("memoryV3Gate", overridden).model).toBe(
941
+ "claude-opus-4-7",
942
+ );
943
+ });
944
+ });
@@ -31,6 +31,7 @@ function makeInput(overrides?: Partial<UsageEventInput>): UsageEventInput {
31
31
  outputTokens: 500,
32
32
  cacheCreationInputTokens: null,
33
33
  cacheReadInputTokens: null,
34
+ rawUsage: null,
34
35
  actor: "main_agent",
35
36
  conversationId: null,
36
37
  runId: null,
@@ -217,6 +218,44 @@ describe("recordUsageEvent", () => {
217
218
  expect(events[0].cacheCreationInputTokens).toBe(200);
218
219
  expect(events[0].cacheReadInputTokens).toBe(300);
219
220
  });
221
+
222
+ test("round-trips the provider's raw_usage payload verbatim", () => {
223
+ // The `raw_usage` column carries the literal usage object the provider
224
+ // returned (Anthropic nests TTL breakdown under `cache_creation`,
225
+ // OpenAI nests cached-read details under `prompt_tokens_details`, etc.)
226
+ // It must round-trip from `recordUsageEvent` through SQLite back to
227
+ // `listUsageEvents` byte-for-byte so downstream consumers can extract
228
+ // any provider-specific detail without a schema change.
229
+ const rawUsage = {
230
+ input_tokens: 1000,
231
+ output_tokens: 500,
232
+ cache_creation_input_tokens: 500,
233
+ cache_creation: {
234
+ ephemeral_5m_input_tokens: 100,
235
+ ephemeral_1h_input_tokens: 400,
236
+ },
237
+ cache_read_input_tokens: 0,
238
+ service_tier: "standard",
239
+ };
240
+ recordUsageEvent(makeInput({ rawUsage }), pricedResult);
241
+
242
+ const [event] = listUsageEvents();
243
+ expect(event.rawUsage).toEqual(rawUsage);
244
+ });
245
+
246
+ test("raw_usage defaults to null when the provider did not return one", () => {
247
+ // Providers that don't surface a usage block (or daemons predating
248
+ // migration 260) write null. Coercing to `{}` would be
249
+ // indistinguishable from a usage block that genuinely has no fields,
250
+ // so we preserve null as the "absent" signal.
251
+ recordUsageEvent(
252
+ makeInput({ provider: "openai", model: "gpt-4o", rawUsage: null }),
253
+ pricedResult,
254
+ );
255
+
256
+ const [event] = listUsageEvents();
257
+ expect(event.rawUsage).toBeNull();
258
+ });
220
259
  });
221
260
 
222
261
  describe("listUsageEvents", () => {
@@ -1391,4 +1430,31 @@ describe("queryUnreportedUsageEvents", () => {
1391
1430
  // Analytics can treat 0 as "pre-first-turn" if needed.
1392
1431
  expect(events[0].turnIndex).toBe(0);
1393
1432
  });
1433
+
1434
+ test("surfaces raw_usage on unreported events", () => {
1435
+ // The telemetry reporter consumes `queryUnreportedUsageEvents` output
1436
+ // directly and forwards it to BigQuery. If the SELECT projection
1437
+ // drops the `raw_usage` column, every provider-specific detail
1438
+ // (Anthropic TTL breakdown, OpenAI prompt-token details, etc.)
1439
+ // vanishes silently — covered here so a refactor of the projection
1440
+ // can't regress the wire shape.
1441
+ const rawUsage = {
1442
+ input_tokens: 1500,
1443
+ output_tokens: 600,
1444
+ cache_creation_input_tokens: 800,
1445
+ cache_creation: {
1446
+ ephemeral_5m_input_tokens: 300,
1447
+ ephemeral_1h_input_tokens: 500,
1448
+ },
1449
+ };
1450
+ insertEventAt(1000, {
1451
+ cacheCreationInputTokens: 800,
1452
+ rawUsage,
1453
+ });
1454
+
1455
+ const events = queryUnreportedUsageEvents(0, undefined, 100);
1456
+ expect(events).toHaveLength(1);
1457
+ expect(events[0].cacheCreationInputTokens).toBe(800);
1458
+ expect(events[0].rawUsage).toEqual(rawUsage);
1459
+ });
1394
1460
  });
@@ -0,0 +1,89 @@
1
+ import { mkdtempSync, readdirSync, rmSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterAll, describe, expect, test } from "bun:test";
5
+
6
+ import { getLogger, initLogger, LOG_FILE_PATTERN } from "../util/logger.js";
7
+
8
+ // ---------------------------------------------------------------------------
9
+ // Test rationale
10
+ // ---------------------------------------------------------------------------
11
+ //
12
+ // `getLogger()` returns a Proxy that lazily creates a pino child against the
13
+ // current rootLogger. Before this PR's refactor, the child was cached on
14
+ // first access and never re-evaluated — which meant that across:
15
+ //
16
+ // 1. day rollover (ensureCurrentDate rebuilds rootLogger past UTC midnight),
17
+ // 2. or a late `initLogger()` call (which swaps the rootLogger),
18
+ //
19
+ // previously-cached children kept writing to the OLD root's destination
20
+ // forever — silently misrouting logs into the wrong daily file.
21
+ //
22
+ // These tests pin the new contract: when the rootLogger changes, the proxy's
23
+ // next access rebuilds the child against the new root.
24
+ //
25
+ // We assert via file-system side effects (logs appearing in the expected
26
+ // directory). pino's `sync: false` default makes the fd open asynchronous,
27
+ // so we wait a tick before reading.
28
+ //
29
+ // NB: the file-creating fallback path itself is gated behind a BUN_TEST=1
30
+ // stderr fast-path in `getRootLogger()` (so test output stays sensible), so
31
+ // these tests exercise the rebind via `initLogger()` calls instead. The
32
+ // "no vellum.log" property is covered by `platform.test.ts` (asserts
33
+ // `getLogsDir()` returns the directory) and by the mechanical guarantee that
34
+ // `buildRotatingLogger` derives filenames via `logFilePathForDate`.
35
+
36
+ const SLEEP_MS = 100;
37
+
38
+ const dirA = mkdtempSync(join(tmpdir(), "logger-rebind-A-"));
39
+ const dirB = mkdtempSync(join(tmpdir(), "logger-rebind-B-"));
40
+
41
+ afterAll(() => {
42
+ // Detach the module-level rootLogger from the temp dirs we're about to
43
+ // delete. Without this, a later flush (or the test runner's shutdown)
44
+ // could try to write into a removed directory.
45
+ initLogger({ dir: undefined, retentionDays: 0 });
46
+ rmSync(dirA, { recursive: true, force: true });
47
+ rmSync(dirB, { recursive: true, force: true });
48
+ });
49
+
50
+ describe("getLogger() proxy rebind", () => {
51
+ test("a proxy created BEFORE initLogger() still routes to the post-init root", async () => {
52
+ // Create the proxy before initLogger has run. This mirrors the real
53
+ // lifecycle.ts pattern: modules call `getLogger()` at import time, long
54
+ // before `initLogger()` boots in daemon startup.
55
+ const log = getLogger("early-binding");
56
+
57
+ initLogger({ dir: dirA, retentionDays: 0 });
58
+
59
+ log.info("first — should land in dirA");
60
+
61
+ await Bun.sleep(SLEEP_MS);
62
+
63
+ const aFiles = readdirSync(dirA);
64
+ expect(aFiles.some((f) => LOG_FILE_PATTERN.test(f))).toBe(true);
65
+ });
66
+
67
+ test("subsequent log calls follow rootLogger swaps from initLogger()", async () => {
68
+ // rootLogger is currently bound to dirA from the previous test. Reuse
69
+ // an existing proxy and verify it follows the swap.
70
+ const log = getLogger("rebind-target");
71
+ log.info("warm-up against dirA so the child is cached");
72
+
73
+ await Bun.sleep(SLEEP_MS);
74
+
75
+ // Swap the rootLogger to a different directory.
76
+ initLogger({ dir: dirB, retentionDays: 0 });
77
+
78
+ log.info("post-swap — should land in dirB if the proxy rebound");
79
+
80
+ await Bun.sleep(SLEEP_MS);
81
+
82
+ // If the proxy correctly re-evaluates getRootLogger() on each access,
83
+ // the second log call hits the dirB root and dirB gets a daily log
84
+ // file. If the proxy were still caching the original child against the
85
+ // dirA root, dirB would stay empty.
86
+ const bFiles = readdirSync(dirB);
87
+ expect(bFiles.some((f) => LOG_FILE_PATTERN.test(f))).toBe(true);
88
+ });
89
+ });
@@ -142,7 +142,7 @@ describe("MCP AbortSignal threading", () => {
142
142
  );
143
143
 
144
144
  expect(tool.name).toBe("mcp__test-server__my-tool");
145
- expect(tool.getDefinition().name).toBe("mcp__test-server__my-tool");
145
+ expect(tool.name).toBe("mcp__test-server__my-tool");
146
146
  });
147
147
 
148
148
  test("keeps MCP tool names with trailing whitespace distinct", () => {
@@ -211,7 +211,7 @@ describe("MCP AbortSignal threading", () => {
211
211
  expect(tool.name.startsWith("mcp__stripe_link-cli__create_link__")).toBe(
212
212
  true,
213
213
  );
214
- expect(tool.getDefinition().name).toBe(tool.name);
214
+ expect(tool.name).toBe(tool.name);
215
215
 
216
216
  await tool.execute(
217
217
  { someArg: "value" },
@@ -321,6 +321,9 @@ describe("image-studio skill script wrapper", () => {
321
321
 
322
322
  expect(result.isError).toBe(true);
323
323
  expect(result.content).toContain("Mock Gemini error: API failure");
324
+ expect(result.content).toContain(
325
+ "Do not change service configuration (mode, provider, or model) to try to fix it",
326
+ );
324
327
  });
325
328
 
326
329
  test("openai generation error uses OpenAI-specific mapping", async () => {
@@ -331,6 +334,34 @@ describe("image-studio skill script wrapper", () => {
331
334
 
332
335
  expect(result.isError).toBe(true);
333
336
  expect(result.content).toContain("Mock OpenAI error: openai failure");
337
+ expect(result.content).toContain(
338
+ "Do not change service configuration (mode, provider, or model) to try to fix it",
339
+ );
340
+ });
341
+
342
+ test("missing credentials error includes guidance not to change service config", async () => {
343
+ mockGeminiKey = undefined;
344
+
345
+ const result = await run({ prompt: "a cat" }, fakeContext);
346
+
347
+ expect(result.isError).toBe(true);
348
+ expect(result.content).toContain("No Gemini API key");
349
+ expect(result.content).toContain(
350
+ "Do not change service configuration (mode, provider, or model) to try to fix it",
351
+ );
352
+ });
353
+
354
+ test("managed mode credential error includes guidance not to change service config", async () => {
355
+ mockImageGenMode = "managed";
356
+ mockManagedBaseUrl = undefined;
357
+
358
+ const result = await run({ prompt: "a cat" }, fakeContext);
359
+
360
+ expect(result.isError).toBe(true);
361
+ expect(result.content).toContain("Managed proxy is not available");
362
+ expect(result.content).toContain(
363
+ "Do not change service configuration (mode, provider, or model) to try to fix it",
364
+ );
334
365
  });
335
366
 
336
367
  test("reads source images from file paths on disk", async () => {
@@ -4,9 +4,9 @@
4
4
  * Covers:
5
5
  * - Returns null when `memoryV2Static` is missing/empty.
6
6
  * - Returns null when `mode === "minimal"`.
7
- * - Wraps content in `<memory>...</memory>` and uses
7
+ * - Wraps content in `<info>...</info>` and uses
8
8
  * `after-memory-prefix` placement.
9
- * - Escapes any `</memory>` substring inside the authored content so the
9
+ * - Escapes any `</info>` substring inside the authored content so the
10
10
  * wrapper cannot be broken out of.
11
11
  *
12
12
  * Hermetic: drives the injector's `produce()` directly with a synthesized
@@ -66,7 +66,7 @@ describe("memory-v2-static injector", () => {
66
66
  expect(await memoryV2StaticInjector.produce(ctx)).toBeNull();
67
67
  });
68
68
 
69
- test("wraps content in <memory>...</memory> with after-memory-prefix placement", async () => {
69
+ test("wraps content in <info>...</info> with after-memory-prefix placement", async () => {
70
70
  const content =
71
71
  "## Essentials\n\nAlice prefers VS Code.\n\n## Threads\n\nOpen: ship PR.";
72
72
  const ctx = makeContext({
@@ -77,11 +77,11 @@ describe("memory-v2-static injector", () => {
77
77
  expect(block).not.toBeNull();
78
78
  expect(block!.id).toBe("memory-v2-static");
79
79
  expect(block!.placement).toBe("after-memory-prefix");
80
- expect(block!.text).toBe(`<memory>\n${content}\n</memory>`);
80
+ expect(block!.text).toBe(`<info>\n${content}\n</info>`);
81
81
  });
82
82
 
83
- test("escapes inner </memory> closing tags so the wrapper cannot be broken out of", async () => {
84
- const content = "## Essentials\n\nText with </memory> embedded.";
83
+ test("escapes inner </info> closing tags so the wrapper cannot be broken out of", async () => {
84
+ const content = "## Essentials\n\nText with </info> embedded.";
85
85
  const ctx = makeContext({
86
86
  injectionInputs: { memoryV2Static: content },
87
87
  });
@@ -89,7 +89,7 @@ describe("memory-v2-static injector", () => {
89
89
  const block = await memoryV2StaticInjector.produce(ctx);
90
90
  expect(block).not.toBeNull();
91
91
  expect(block!.text).toBe(
92
- "<memory>\n## Essentials\n\nText with &lt;/memory&gt; embedded.\n</memory>",
92
+ "<info>\n## Essentials\n\nText with &lt;/info&gt; embedded.\n</info>",
93
93
  );
94
94
  });
95
95
  });
@@ -29,7 +29,7 @@ describe("model intents", () => {
29
29
  "gpt-5.4-nano",
30
30
  );
31
31
  expect(resolveModelIntent("gemini", "latency-optimized")).toBe(
32
- "gemini-3.1-flash-lite-preview",
32
+ "gemini-3.1-flash-lite",
33
33
  );
34
34
  expect(resolveModelIntent("gemini", "quality-optimized")).toBe(
35
35
  "gemini-3.1-pro-preview",
@@ -44,9 +44,7 @@ describe("model intents", () => {
44
44
  });
45
45
 
46
46
  test("falls back to provider default for unknown providers", () => {
47
- expect(getProviderDefaultModel("unknown-provider")).toBe(
48
- "claude-opus-4-7",
49
- );
47
+ expect(getProviderDefaultModel("unknown-provider")).toBe("claude-opus-4-7");
50
48
  expect(resolveModelIntent("unknown-provider", "quality-optimized")).toBe(
51
49
  "claude-opus-4-7",
52
50
  );
@@ -66,7 +66,6 @@ mock.module("../notifications/emit-signal.js", () => ({
66
66
  }
67
67
  return mockEmitResult;
68
68
  },
69
- registerBroadcastFn: () => {},
70
69
  }));
71
70
 
72
71
  import {
@@ -44,7 +44,7 @@ describe("onboarding template contracts", () => {
44
44
  test("instructs saving to IDENTITY.md, SOUL.md, and user persona file via file_edit", () => {
45
45
  expect(bootstrap).toContain("IDENTITY.md");
46
46
  expect(bootstrap).toContain("SOUL.md");
47
- expect(bootstrap).toContain("{{USER_PERSONA_FILE}}");
47
+ expect(bootstrap).toContain("{{userSlug}}.md");
48
48
  expect(bootstrap).toContain("file_edit");
49
49
  });
50
50
 
@@ -56,6 +56,7 @@ let lastCreateParams: Record<string, unknown> | null = null;
56
56
  let lastCreateOptions: Record<string, unknown> | null = null;
57
57
  let lastConstructorOptions: Record<string, unknown> | null = null;
58
58
  let shouldThrow: Error | null = null;
59
+ const DEFAULT_SDK_TIMEOUT_MS = 1_860_000;
59
60
 
60
61
  function userMsg(text: string): Message {
61
62
  return { role: "user", content: [{ type: "text", text }] };
@@ -102,6 +103,7 @@ mock.module("openai", () => ({
102
103
 
103
104
  // Import after mocking
104
105
  import { FireworksProvider } from "../providers/fireworks/client.js";
106
+ import { MinimaxProvider } from "../providers/minimax/client.js";
105
107
  import { OllamaProvider } from "../providers/ollama/client.js";
106
108
  import { OpenAIChatCompletionsProvider } from "../providers/openai/chat-completions-provider.js";
107
109
  import { OpenAIProvider } from "../providers/openai/client.js";
@@ -307,6 +309,7 @@ describe("OpenAIProvider", () => {
307
309
  expect(lastConstructorOptions).toEqual({
308
310
  apiKey: "sk-local",
309
311
  baseURL: "http://127.0.0.1:11434/v1",
312
+ timeout: DEFAULT_SDK_TIMEOUT_MS,
310
313
  });
311
314
  });
312
315
 
@@ -319,6 +322,7 @@ describe("OpenAIProvider", () => {
319
322
  expect(lastConstructorOptions).toEqual({
320
323
  apiKey: "ollama",
321
324
  baseURL: "http://127.0.0.1:11434/v1",
325
+ timeout: DEFAULT_SDK_TIMEOUT_MS,
322
326
  });
323
327
  } finally {
324
328
  if (previousBaseUrl !== undefined) {
@@ -338,6 +342,7 @@ describe("OpenAIProvider", () => {
338
342
  expect(lastConstructorOptions).toEqual({
339
343
  apiKey: "ollama",
340
344
  baseURL: "http://127.0.0.1:11434/v1",
345
+ timeout: DEFAULT_SDK_TIMEOUT_MS,
341
346
  });
342
347
  } finally {
343
348
  if (previousBaseUrl !== undefined) {
@@ -1280,6 +1285,7 @@ describe("custom baseURL initialization", () => {
1280
1285
  expect(lastConstructorOptions).toEqual({
1281
1286
  apiKey: "ast-key-123",
1282
1287
  baseURL: "https://platform.example.com/v1/runtime-proxy/openai",
1288
+ timeout: DEFAULT_SDK_TIMEOUT_MS,
1283
1289
  });
1284
1290
  });
1285
1291
 
@@ -1289,6 +1295,19 @@ describe("custom baseURL initialization", () => {
1289
1295
  expect(lastConstructorOptions).toEqual({
1290
1296
  apiKey: "sk-user-key",
1291
1297
  baseURL: undefined,
1298
+ timeout: DEFAULT_SDK_TIMEOUT_MS,
1299
+ });
1300
+ });
1301
+
1302
+ test("OpenAIProvider passes configured stream timeout plus buffer to SDK", () => {
1303
+ new OpenAIProvider("sk-user-key", "gpt-4o", {
1304
+ streamTimeoutMs: 300_000,
1305
+ });
1306
+
1307
+ expect(lastConstructorOptions).toEqual({
1308
+ apiKey: "sk-user-key",
1309
+ baseURL: undefined,
1310
+ timeout: 360_000,
1292
1311
  });
1293
1312
  });
1294
1313
 
@@ -1305,6 +1324,7 @@ describe("custom baseURL initialization", () => {
1305
1324
  expect(lastConstructorOptions).toEqual({
1306
1325
  apiKey: "ast-key-123",
1307
1326
  baseURL: "https://platform.example.com/v1/runtime-proxy/fireworks",
1327
+ timeout: DEFAULT_SDK_TIMEOUT_MS,
1308
1328
  });
1309
1329
  });
1310
1330
 
@@ -1317,6 +1337,7 @@ describe("custom baseURL initialization", () => {
1317
1337
  expect(lastConstructorOptions).toEqual({
1318
1338
  apiKey: "fw-user-key",
1319
1339
  baseURL: "https://api.fireworks.ai/inference/v1",
1340
+ timeout: DEFAULT_SDK_TIMEOUT_MS,
1320
1341
  });
1321
1342
  });
1322
1343
 
@@ -1329,6 +1350,7 @@ describe("custom baseURL initialization", () => {
1329
1350
  expect(lastConstructorOptions).toEqual({
1330
1351
  apiKey: "ast-key-123",
1331
1352
  baseURL: "https://platform.example.com/v1/runtime-proxy/openrouter",
1353
+ timeout: DEFAULT_SDK_TIMEOUT_MS,
1332
1354
  });
1333
1355
  });
1334
1356
 
@@ -1338,6 +1360,30 @@ describe("custom baseURL initialization", () => {
1338
1360
  expect(lastConstructorOptions).toEqual({
1339
1361
  apiKey: "or-user-key",
1340
1362
  baseURL: "https://openrouter.ai/api/v1",
1363
+ timeout: DEFAULT_SDK_TIMEOUT_MS,
1364
+ });
1365
+ });
1366
+
1367
+ test("MinimaxProvider forwards a custom baseURL", () => {
1368
+ const managed = new MinimaxProvider("ast-key-123", "MiniMax-M2.7", {
1369
+ baseURL: "https://platform.example.com/v1/runtime-proxy/minimax",
1370
+ });
1371
+
1372
+ expect(managed.name).toBe("minimax");
1373
+ expect(lastConstructorOptions).toEqual({
1374
+ apiKey: "ast-key-123",
1375
+ baseURL: "https://platform.example.com/v1/runtime-proxy/minimax",
1376
+ timeout: DEFAULT_SDK_TIMEOUT_MS,
1377
+ });
1378
+ });
1379
+
1380
+ test("MinimaxProvider without custom baseURL uses default MiniMax URL", () => {
1381
+ new MinimaxProvider("mm-user-key", "MiniMax-M2.7");
1382
+
1383
+ expect(lastConstructorOptions).toEqual({
1384
+ apiKey: "mm-user-key",
1385
+ baseURL: "https://api.minimax.io/v1",
1386
+ timeout: DEFAULT_SDK_TIMEOUT_MS,
1341
1387
  });
1342
1388
  });
1343
1389
  });