@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
@@ -104,15 +104,12 @@ mock.module("../tools/skills/skill-tool-factory.js", () => ({
104
104
  description: entry.description,
105
105
  category: entry.category,
106
106
  defaultRiskLevel: RiskLevel.Medium,
107
+ executionTarget: "sandbox" as const,
107
108
  origin: "skill" as const,
108
109
  ownerSkillId: skillId,
109
110
  ownerSkillVersionHash: versionHash,
110
111
  ownerSkillBundled: bundled ?? undefined,
111
- getDefinition: () => ({
112
- name: entry.name,
113
- description: entry.description,
114
- input_schema: entry.input_schema as object,
115
- }),
112
+ input_schema: entry.input_schema as object,
116
113
  execute: async () => ({ content: "", isError: false }),
117
114
  }));
118
115
  },
@@ -334,7 +334,7 @@ describe("attachment orphan cleanup", () => {
334
334
  const stored = uploadAttachment("doc.pdf", "application/pdf", "JVBER");
335
335
  linkAttachmentToMessage(msg.id, stored.id, 0);
336
336
 
337
- clearAll();
337
+ await clearAll();
338
338
 
339
339
  const raw = (
340
340
  getDb() as unknown as {
@@ -73,7 +73,16 @@ describe("conversation sync tags", () => {
73
73
  resetDb();
74
74
  });
75
75
 
76
- test("rename emits legacy title/list events and conversation metadata sync tags", async () => {
76
+ test("rename emits the typed title event and a metadata-only sync tag (no list umbrella)", async () => {
77
+ // Rename is a content-only change: the row stays in place, the list
78
+ // shape is unchanged, only the title field flips. Web patches the
79
+ // single cached row via the typed `conversation_title_updated` event
80
+ // (`patchConversation` in `metadata-handlers.ts`) and the per-
81
+ // conversation `sync_changed` metadata tag is included as a belt-and-
82
+ // suspenders signal for sibling-tab consumers that missed the typed
83
+ // event. The legacy `conversation_list_invalidated` broadcast is
84
+ // scoped to `targetInterfaceId: "macos"` and therefore not visible to
85
+ // this process-type subscriber.
77
86
  const conversation = createConversation("Old title");
78
87
  const route = findRoute(
79
88
  CONVERSATION_MANAGEMENT_ROUTES,
@@ -85,23 +94,39 @@ describe("conversation sync tags", () => {
85
94
  pathParams: { id: conversation.id },
86
95
  body: { name: "New title" },
87
96
  });
88
- }, 3);
97
+ }, 2);
89
98
 
90
99
  expect(received.map((event) => event.message.type)).toEqual([
91
100
  "conversation_title_updated",
92
- "conversation_list_invalidated",
93
101
  "sync_changed",
94
102
  ]);
95
- expect(received[2]!.message).toEqual({
103
+ expect(received[1]!.message).toEqual({
96
104
  type: "sync_changed",
97
- tags: [
98
- SYNC_TAGS.conversationsList,
99
- conversationMetadataSyncTag(conversation.id),
100
- ],
105
+ tags: [conversationMetadataSyncTag(conversation.id)],
101
106
  });
107
+ // Defense-in-depth: the umbrella `conversationsList` tag would force
108
+ // web to redrain the full paginated list — we deliberately omit it
109
+ // for content-only reasons.
110
+ expect(
111
+ (received[1]!.message as { tags: string[] }).tags,
112
+ ).not.toContain(SYNC_TAGS.conversationsList);
113
+ // The legacy invalidation broadcast is macOS-scoped and must not
114
+ // reach this process-type subscriber.
115
+ expect(
116
+ received.some(
117
+ (event) => event.message.type === "conversation_list_invalidated",
118
+ ),
119
+ ).toBe(false);
102
120
  });
103
121
 
104
- test("create emits legacy list invalidation and list/metadata sync tags", async () => {
122
+ test("create emits a sync_changed with the conversationsList umbrella tag", async () => {
123
+ // Create is shape-changing — a row is added to the paginated list,
124
+ // so web must redrain the list (cannot patch a row it has never
125
+ // fetched). The umbrella `conversationsList` tag is the signal for
126
+ // that redrain. Per-conversation metadata is included so any future
127
+ // single-row consumer can patch the freshly added row in place
128
+ // without an extra GET. The legacy macOS-only invalidation broadcast
129
+ // is not visible to process subscribers.
105
130
  const route = findRoute(
106
131
  CONVERSATION_MANAGEMENT_ROUTES,
107
132
  "createConversation",
@@ -113,23 +138,33 @@ describe("conversation sync tags", () => {
113
138
  body: { conversationKey: "sync-create-test" },
114
139
  })) as { id: string };
115
140
  conversationId = result.id;
116
- }, 2);
141
+ }, 1);
117
142
 
118
143
  expect(conversationId).toBeDefined();
119
144
  expect(received.map((event) => event.message.type)).toEqual([
120
- "conversation_list_invalidated",
121
145
  "sync_changed",
122
146
  ]);
123
- expect(received[1]!.message).toEqual({
147
+ expect(received[0]!.message).toEqual({
124
148
  type: "sync_changed",
125
149
  tags: [
126
150
  SYNC_TAGS.conversationsList,
127
151
  conversationMetadataSyncTag(conversationId!),
128
152
  ],
129
153
  });
154
+ expect(
155
+ received.some(
156
+ (event) => event.message.type === "conversation_list_invalidated",
157
+ ),
158
+ ).toBe(false);
130
159
  });
131
160
 
132
- test("reorder emits list invalidation and metadata sync tags for touched conversations", async () => {
161
+ test("reorder emits a sync_changed with the umbrella tag and per-conversation metadata tags", async () => {
162
+ // Reorder changes the row position in the paginated list — also
163
+ // shape-changing. The umbrella `conversationsList` tag forces a
164
+ // redrain so the new ordering shows. Per-conversation metadata tags
165
+ // are bundled in to give any single-row consumer a hint that the
166
+ // touched conversations' positions have moved (currently web
167
+ // consumes only the umbrella tag; metadata tags are forward-compat).
133
168
  const first = createConversation("First");
134
169
  const second = createConversation("Second");
135
170
  const route = findRoute(
@@ -146,13 +181,12 @@ describe("conversation sync tags", () => {
146
181
  ],
147
182
  },
148
183
  });
149
- }, 2);
184
+ }, 1);
150
185
 
151
186
  expect(received.map((event) => event.message.type)).toEqual([
152
- "conversation_list_invalidated",
153
187
  "sync_changed",
154
188
  ]);
155
- expect(received[1]!.message).toEqual({
189
+ expect(received[0]!.message).toEqual({
156
190
  type: "sync_changed",
157
191
  tags: [
158
192
  SYNC_TAGS.conversationsList,
@@ -160,9 +194,28 @@ describe("conversation sync tags", () => {
160
194
  conversationMetadataSyncTag(second.id),
161
195
  ],
162
196
  });
197
+ expect(
198
+ received.some(
199
+ (event) => event.message.type === "conversation_list_invalidated",
200
+ ),
201
+ ).toBe(false);
163
202
  });
164
203
 
165
- test("record seen emits list invalidation and metadata sync tags for the touched conversation", async () => {
204
+ test("record seen emits only a per-conversation metadata sync tag (no list umbrella)", async () => {
205
+ // Seen state is per-conversation attention metadata, not list-
206
+ // shaped. The old behavior emitted `sync_changed` carrying the
207
+ // umbrella `conversationsList` tag, which forced every subscribed
208
+ // web client to redrain the full paginated sidebar on every
209
+ // conversation switch that landed on an unseen conversation (~14
210
+ // requests at ~300 conversations). The current behavior emits a
211
+ // single `sync_changed` with only the per-conversation
212
+ // `conversation:<id>:metadata` tag, which web consumes by GET-and-
213
+ // patching the single cached row via `refreshConversationRow`.
214
+ //
215
+ // The legacy `conversation_list_invalidated` broadcast is still
216
+ // emitted for macOS (which has no per-row patcher) but is scoped
217
+ // to `targetInterfaceId: "macos"` and therefore not visible to
218
+ // this process-type subscriber.
166
219
  const conversation = createConversation("Attention");
167
220
  projectAssistantMessage({
168
221
  conversationId: conversation.id,
@@ -181,22 +234,32 @@ describe("conversation sync tags", () => {
181
234
  source: "test",
182
235
  },
183
236
  });
184
- }, 2);
237
+ }, 1);
185
238
 
186
239
  expect(received.map((event) => event.message.type)).toEqual([
187
- "conversation_list_invalidated",
188
240
  "sync_changed",
189
241
  ]);
190
- expect(received[1]!.message).toEqual({
242
+ expect(received[0]!.message).toEqual({
191
243
  type: "sync_changed",
192
- tags: [
193
- SYNC_TAGS.conversationsList,
194
- conversationMetadataSyncTag(conversation.id),
195
- ],
244
+ tags: [conversationMetadataSyncTag(conversation.id)],
196
245
  });
246
+ // Defense-in-depth: the umbrella `conversationsList` tag would
247
+ // force the very paginated-list drain this redesign exists to
248
+ // avoid. It must not appear here.
249
+ expect(
250
+ (received[0]!.message as { tags: string[] }).tags,
251
+ ).not.toContain(SYNC_TAGS.conversationsList);
252
+ expect(
253
+ received.some(
254
+ (event) => event.message.type === "conversation_list_invalidated",
255
+ ),
256
+ ).toBe(false);
197
257
  });
198
258
 
199
- test("mark unread emits list invalidation and metadata sync tags for the touched conversation", async () => {
259
+ test("mark unread emits only a per-conversation metadata sync tag (no list umbrella)", async () => {
260
+ // Symmetric with `record seen`: mark-unread flips the per-conversation
261
+ // hasUnseen flag back to true. Same per-conversation sync tag, same
262
+ // absence of list-level fan-out.
200
263
  const conversation = createConversation("Attention");
201
264
  projectAssistantMessage({
202
265
  conversationId: conversation.id,
@@ -218,18 +281,22 @@ describe("conversation sync tags", () => {
218
281
  conversationId: conversation.id,
219
282
  },
220
283
  });
221
- }, 2);
284
+ }, 1);
222
285
 
223
286
  expect(received.map((event) => event.message.type)).toEqual([
224
- "conversation_list_invalidated",
225
287
  "sync_changed",
226
288
  ]);
227
- expect(received[1]!.message).toEqual({
289
+ expect(received[0]!.message).toEqual({
228
290
  type: "sync_changed",
229
- tags: [
230
- SYNC_TAGS.conversationsList,
231
- conversationMetadataSyncTag(conversation.id),
232
- ],
291
+ tags: [conversationMetadataSyncTag(conversation.id)],
233
292
  });
293
+ expect(
294
+ (received[0]!.message as { tags: string[] }).tags,
295
+ ).not.toContain(SYNC_TAGS.conversationsList);
296
+ expect(
297
+ received.some(
298
+ (event) => event.message.type === "conversation_list_invalidated",
299
+ ),
300
+ ).toBe(false);
234
301
  });
235
302
  });
@@ -87,6 +87,7 @@ mock.module("../security/secret-allowlist.js", () => ({
87
87
 
88
88
  mock.module("../memory/conversation-crud.js", () => ({
89
89
  setConversationOriginChannelIfUnset: () => {},
90
+ setConversationHistoryStrippedAt: () => {},
90
91
  provenanceFromTrustContext: () => ({
91
92
  source: "user",
92
93
  trustContext: undefined,
@@ -116,6 +116,7 @@ mock.module("../security/secret-allowlist.js", () => ({
116
116
 
117
117
  mock.module("../memory/conversation-crud.js", () => ({
118
118
  setConversationOriginChannelIfUnset: () => {},
119
+ setConversationHistoryStrippedAt: () => {},
119
120
  provenanceFromTrustContext: () => ({
120
121
  source: "user",
121
122
  trustContext: undefined,
@@ -144,7 +145,6 @@ mock.module("../memory/conversation-crud.js", () => ({
144
145
  setLastNotifiedInferenceProfile: () => {},
145
146
  getConversationOverrideProfileFromRow: () => undefined,
146
147
  updateMessageMetadata: () => {},
147
- clearStrippedInjectionMetadataForConversation: () => {},
148
148
  }));
149
149
 
150
150
  mock.module("../memory/conversation-queries.js", () => ({
@@ -114,6 +114,7 @@ mock.module("../security/secret-allowlist.js", () => ({
114
114
 
115
115
  mock.module("../memory/conversation-crud.js", () => ({
116
116
  setConversationOriginChannelIfUnset: () => {},
117
+ setConversationHistoryStrippedAt: () => {},
117
118
  provenanceFromTrustContext: () => ({
118
119
  source: "user",
119
120
  trustContext: undefined,
@@ -141,7 +142,6 @@ mock.module("../memory/conversation-crud.js", () => ({
141
142
  setLastNotifiedInferenceProfile: () => {},
142
143
  getConversationOverrideProfileFromRow: () => undefined,
143
144
  updateMessageMetadata: () => {},
144
- clearStrippedInjectionMetadataForConversation: () => {},
145
145
  }));
146
146
 
147
147
  mock.module("../memory/conversation-queries.js", () => ({
@@ -159,7 +159,7 @@ describe("CES flags respect explicit false overrides", () => {
159
159
  // ---------------------------------------------------------------------------
160
160
 
161
161
  describe("CES flags do not affect unrelated flags", () => {
162
- test("enabling all CES flags does not change browser flag (defaultEnabled: true)", () => {
162
+ test("enabling all CES flags does not change declared default-enabled flags", () => {
163
163
  const overrides: Record<string, boolean> = {};
164
164
  for (const key of ALL_CES_FLAG_KEYS) {
165
165
  overrides[key] = true;
@@ -167,11 +167,13 @@ describe("CES flags do not affect unrelated flags", () => {
167
167
  _setOverridesForTesting(overrides);
168
168
  const config = makeConfig();
169
169
 
170
- // browser defaults to true in the registry and should stay true
171
- expect(isAssistantFeatureFlagEnabled("browser", config)).toBe(true);
170
+ // account-deletion defaults to true in the registry and should stay true.
171
+ expect(isAssistantFeatureFlagEnabled("account-deletion", config)).toBe(
172
+ true,
173
+ );
172
174
  });
173
175
 
174
- test("enabling all CES flags does not change unrelated default-open flags", () => {
176
+ test("enabling all CES flags does not change unrelated fail-closed flags", () => {
175
177
  const overrides: Record<string, boolean> = {};
176
178
  for (const key of ALL_CES_FLAG_KEYS) {
177
179
  overrides[key] = true;
@@ -179,9 +181,9 @@ describe("CES flags do not affect unrelated flags", () => {
179
181
  _setOverridesForTesting(overrides);
180
182
  const config = makeConfig();
181
183
 
182
- // Unknown flags default open unless explicitly overridden.
184
+ // Unknown flags fail closed unless explicitly overridden.
183
185
  expect(
184
- isAssistantFeatureFlagEnabled("unrelated-default-open", config),
185
- ).toBe(true);
186
+ isAssistantFeatureFlagEnabled("unrelated-default-closed", config),
187
+ ).toBe(false);
186
188
  });
187
189
  });
@@ -13,7 +13,7 @@ import type { Tool } from "../tools/types.js";
13
13
 
14
14
  describe("CES tool schema shapes", () => {
15
15
  test("make_authenticated_request has correct name and required fields", () => {
16
- const def = makeAuthenticatedRequestTool.getDefinition();
16
+ const def = makeAuthenticatedRequestTool;
17
17
  expect(def.name).toBe("make_authenticated_request");
18
18
  const schema = def.input_schema as {
19
19
  required: string[];
@@ -28,7 +28,7 @@ describe("CES tool schema shapes", () => {
28
28
  });
29
29
 
30
30
  test("run_authenticated_command has correct name and required fields", () => {
31
- const def = runAuthenticatedCommandTool.getDefinition();
31
+ const def = runAuthenticatedCommandTool;
32
32
  expect(def.name).toBe("run_authenticated_command");
33
33
  const schema = def.input_schema as {
34
34
  required: string[];
@@ -43,7 +43,7 @@ describe("CES tool schema shapes", () => {
43
43
  });
44
44
 
45
45
  test("manage_secure_command_tool has correct name and required fields", () => {
46
- const def = manageSecureCommandTool.getDefinition();
46
+ const def = manageSecureCommandTool;
47
47
  expect(def.name).toBe("manage_secure_command_tool");
48
48
  const schema = def.input_schema as {
49
49
  required: string[];
@@ -95,7 +95,7 @@ describe("CES tool manifest registration", () => {
95
95
 
96
96
  test("no CES tool exposes raw secret values in its schema", () => {
97
97
  for (const tool of cesTools) {
98
- const def = tool.getDefinition();
98
+ const def = tool;
99
99
  const schema = def.input_schema as {
100
100
  properties: Record<string, { type?: string; description?: string }>;
101
101
  };
@@ -114,7 +114,7 @@ describe("CES tool manifest registration", () => {
114
114
 
115
115
  describe("secure tool installation is separate from credential grants", () => {
116
116
  test("manage_secure_command_tool accepts only bundle metadata, not raw bytes", () => {
117
- const def = manageSecureCommandTool.getDefinition();
117
+ const def = manageSecureCommandTool;
118
118
  const schema = def.input_schema as {
119
119
  properties: Record<string, unknown>;
120
120
  };
@@ -144,7 +144,7 @@ describe("secure tool installation is separate from credential grants", () => {
144
144
  });
145
145
 
146
146
  test("manage_secure_command_tool action enum does not include grant actions", () => {
147
- const def = manageSecureCommandTool.getDefinition();
147
+ const def = manageSecureCommandTool;
148
148
  const schema = def.input_schema as {
149
149
  properties: {
150
150
  action: { enum?: string[] };
@@ -171,6 +171,7 @@ describe("Invariant 2: no generic plaintext secret read API", () => {
171
171
  "daemon/handlers/config-telegram.ts", // Telegram bot token management
172
172
  "daemon/handlers/config-vercel.ts", // Vercel API token management
173
173
  "runtime/routes/integrations/twilio.ts", // Twilio credential management (HTTP control-plane)
174
+ "acp/prepare-agent-env.ts", // shared helper injects CLAUDE_CODE_OAUTH_TOKEN into claude-agent-acp subprocess env (called by route + skill tool spawn paths)
174
175
  "security/token-manager.ts", // OAuth token refresh flow
175
176
  "tools/network/script-proxy/session-manager.ts", // proxy credential injection at runtime
176
177
  "calls/call-domain.ts", // caller identity resolution (user phone number lookup)
@@ -1267,7 +1267,7 @@ describe("credential_store tool — tool definition", () => {
1267
1267
  });
1268
1268
 
1269
1269
  test("getDefinition returns valid schema with required action", () => {
1270
- const def = credentialStoreTool.getDefinition();
1270
+ const def = credentialStoreTool;
1271
1271
  expect(def.name).toBe("credential_store");
1272
1272
  const schema = def.input_schema as Record<string, unknown>;
1273
1273
  expect(schema.type).toBe("object");
@@ -1277,7 +1277,7 @@ describe("credential_store tool — tool definition", () => {
1277
1277
  });
1278
1278
 
1279
1279
  test("getDefinition includes injection_templates schema", () => {
1280
- const def = credentialStoreTool.getDefinition();
1280
+ const def = credentialStoreTool;
1281
1281
  const schemaProps = (def.input_schema as Record<string, unknown>)
1282
1282
  .properties as Record<string, Record<string, unknown>>;
1283
1283
  const templates = schemaProps.injection_templates as Record<
@@ -41,7 +41,7 @@ describe("DynamicPageSurfaceData shape", () => {
41
41
 
42
42
  describe("Tool definition includes dynamic_page", () => {
43
43
  test("input_schema surface_type enum includes dynamic_page", () => {
44
- const definition = uiShowTool.getDefinition();
44
+ const definition = uiShowTool;
45
45
  const surfaceTypeEnum = (
46
46
  definition.input_schema as {
47
47
  properties: { surface_type: { enum: string[] } };
@@ -52,7 +52,7 @@ describe("Tool definition includes dynamic_page", () => {
52
52
  });
53
53
 
54
54
  test("description mentions dynamic_page", () => {
55
- const definition = uiShowTool.getDefinition();
55
+ const definition = uiShowTool;
56
56
  expect(definition.description).toContain("dynamic_page");
57
57
  });
58
58
  });
@@ -49,6 +49,18 @@ describe("markdownToEmailHtml", () => {
49
49
  expect(result).toBe("");
50
50
  });
51
51
 
52
+ test("converts literal backslash-n after normalization", () => {
53
+ // LLMs often produce literal "\n" instead of real newlines.
54
+ // handleEmailSend normalizes them before calling markdownToEmailHtml.
55
+ const raw = "Hi Noa,\\n\\nTesting line breaks!\\n\\nThanks!";
56
+ const normalized = raw.replace(/\\n/g, "\n");
57
+ const result = markdownToEmailHtml(normalized);
58
+ expect(result).toContain("<p>Hi Noa,</p>");
59
+ expect(result).toContain("<p>Testing line breaks!</p>");
60
+ expect(result).toContain("<p>Thanks!</p>");
61
+ expect(result).not.toContain("\\n");
62
+ });
63
+
52
64
  test("handles multiline markdown email", () => {
53
65
  const md = `Hi there,
54
66