@vellumai/assistant 0.8.4 → 0.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (802) hide show
  1. package/AGENTS.md +33 -1
  2. package/ARCHITECTURE.md +3 -3
  3. package/bunfig.toml +6 -1
  4. package/docs/browser-use-architecture-phase2.md +1 -1
  5. package/docs/credential-execution-service.md +6 -6
  6. package/docs/plugins.md +4 -3
  7. package/knip.json +2 -1
  8. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
  9. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
  10. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
  11. package/openapi.yaml +2748 -216
  12. package/package.json +1 -1
  13. package/src/__tests__/actor-token-service.test.ts +3 -2
  14. package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
  15. package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
  16. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
  17. package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
  18. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  19. package/src/__tests__/annotate-risk-options.test.ts +1 -0
  20. package/src/__tests__/anthropic-provider.test.ts +34 -37
  21. package/src/__tests__/approval-cascade.test.ts +1 -0
  22. package/src/__tests__/approval-routes-http.test.ts +9 -13
  23. package/src/__tests__/assert-not-live-db.ts +79 -0
  24. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  25. package/src/__tests__/assistant-feature-flags-integration.test.ts +12 -28
  26. package/src/__tests__/audit-log-rotation.test.ts +72 -18
  27. package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
  28. package/src/__tests__/background-workers-disk-pressure.test.ts +8 -11
  29. package/src/__tests__/browser-skill-endstate.test.ts +3 -3
  30. package/src/__tests__/btw-routes.test.ts +5 -5
  31. package/src/__tests__/call-controller.test.ts +3 -3
  32. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  33. package/src/__tests__/channel-approval-routes.test.ts +3 -2
  34. package/src/__tests__/channel-guardian.test.ts +6 -5
  35. package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
  36. package/src/__tests__/channel-reply-delivery.test.ts +35 -0
  37. package/src/__tests__/channel-retry-sweep.test.ts +320 -3
  38. package/src/__tests__/checker.test.ts +18 -27
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/compaction-trail-store.test.ts +264 -0
  41. package/src/__tests__/compactor-call-site-logging.test.ts +215 -0
  42. package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
  43. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +12 -16
  44. package/src/__tests__/computer-use-tools.test.ts +14 -18
  45. package/src/__tests__/config-loader-backfill.test.ts +13 -28
  46. package/src/__tests__/config-loader-corrupt.test.ts +5 -5
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
  48. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
  49. package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
  50. package/src/__tests__/config-schema.test.ts +10 -10
  51. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  52. package/src/__tests__/connection-model-compat.test.ts +83 -0
  53. package/src/__tests__/contacts-tools.test.ts +3 -2
  54. package/src/__tests__/context-token-estimator.test.ts +22 -0
  55. package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
  56. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -1
  57. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
  58. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -1
  59. package/src/__tests__/conversation-agent-loop-overflow.test.ts +231 -2
  60. package/src/__tests__/conversation-agent-loop.test.ts +581 -54
  61. package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
  62. package/src/__tests__/conversation-app-control-instantiation.test.ts +31 -24
  63. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
  64. package/src/__tests__/conversation-attention-store.test.ts +101 -0
  65. package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
  66. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  67. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
  68. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  69. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  70. package/src/__tests__/conversation-error.test.ts +61 -0
  71. package/src/__tests__/conversation-fork-crud.test.ts +239 -15
  72. package/src/__tests__/conversation-fork-route.test.ts +3 -2
  73. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  74. package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
  75. package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
  76. package/src/__tests__/conversation-lifecycle.test.ts +53 -11
  77. package/src/__tests__/conversation-list-source.test.ts +3 -2
  78. package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
  79. package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +14 -13
  80. package/src/__tests__/conversation-pairing.test.ts +53 -0
  81. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
  82. package/src/__tests__/conversation-process-callsite.test.ts +1 -0
  83. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  84. package/src/__tests__/conversation-queue.test.ts +333 -291
  85. package/src/__tests__/conversation-routes-disk-view.test.ts +112 -18
  86. package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
  87. package/src/__tests__/conversation-routes-slash-commands.test.ts +68 -2
  88. package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
  89. package/src/__tests__/conversation-skill-tools.test.ts +40 -147
  90. package/src/__tests__/conversation-slash-queue.test.ts +84 -32
  91. package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
  92. package/src/__tests__/conversation-speed-override.test.ts +1 -0
  93. package/src/__tests__/conversation-store.test.ts +1 -1
  94. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
  95. package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
  96. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
  97. package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
  98. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
  99. package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
  100. package/src/__tests__/conversation-sync-tags.test.ts +218 -35
  101. package/src/__tests__/conversation-title-service.test.ts +1 -0
  102. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
  103. package/src/__tests__/conversation-usage.test.ts +1 -0
  104. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
  105. package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
  106. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -1
  107. package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
  108. package/src/__tests__/credential-broker-server-use.test.ts +5 -5
  109. package/src/__tests__/credential-execution-client.test.ts +72 -1
  110. package/src/__tests__/credential-execution-feature-gates.test.ts +19 -19
  111. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  112. package/src/__tests__/credential-health-service.test.ts +252 -3
  113. package/src/__tests__/credential-security-invariants.test.ts +6 -5
  114. package/src/__tests__/credential-vault-unit.test.ts +21 -21
  115. package/src/__tests__/credential-vault.test.ts +5 -5
  116. package/src/__tests__/cross-provider-web-search.test.ts +56 -2
  117. package/src/__tests__/db-connection-isolation.test.ts +7 -6
  118. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
  119. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
  120. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
  121. package/src/__tests__/db-test-helpers.ts +58 -0
  122. package/src/__tests__/disk-pressure-guard.test.ts +58 -41
  123. package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
  124. package/src/__tests__/disk-pressure-routes.test.ts +0 -33
  125. package/src/__tests__/disk-pressure-tools.test.ts +0 -4
  126. package/src/__tests__/dm-persistence.test.ts +26 -40
  127. package/src/__tests__/document-create-dedupe.test.ts +189 -0
  128. package/src/__tests__/document-find-replace.test.ts +3 -2
  129. package/src/__tests__/document-tool-security.test.ts +81 -2
  130. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  131. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
  132. package/src/__tests__/email-html-renderer.test.ts +12 -0
  133. package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
  134. package/src/__tests__/encrypted-store.test.ts +11 -9
  135. package/src/__tests__/feature-flag-test-helpers.ts +53 -0
  136. package/src/__tests__/filing-service.test.ts +1 -0
  137. package/src/__tests__/first-greeting.test.ts +62 -12
  138. package/src/__tests__/gateway-flag-listener.test.ts +236 -0
  139. package/src/__tests__/gemini-provider.test.ts +104 -0
  140. package/src/__tests__/guardian-action-sweep.test.ts +3 -2
  141. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  142. package/src/__tests__/guardian-outbound-http.test.ts +10 -7
  143. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
  144. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -1
  145. package/src/__tests__/heartbeat-disk-pressure.test.ts +5 -0
  146. package/src/__tests__/heartbeat-service.test.ts +5 -0
  147. package/src/__tests__/helpers/mock-logger.ts +26 -0
  148. package/src/__tests__/host-bash-routes.test.ts +1 -0
  149. package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
  150. package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
  151. package/src/__tests__/host-shell-tool.test.ts +6 -5
  152. package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
  153. package/src/__tests__/http-conversation-lineage.test.ts +3 -2
  154. package/src/__tests__/http-user-message-parity.test.ts +29 -7
  155. package/src/__tests__/identity-intro-cache.test.ts +133 -22
  156. package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
  157. package/src/__tests__/inference-profile-reaper.test.ts +3 -2
  158. package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
  159. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  160. package/src/__tests__/injector-disk-pressure.test.ts +3 -17
  161. package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
  162. package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
  163. package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
  164. package/src/__tests__/llm-context-normalization.test.ts +42 -0
  165. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  166. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  167. package/src/__tests__/llm-resolver.test.ts +408 -9
  168. package/src/__tests__/llm-schema.test.ts +1 -1
  169. package/src/__tests__/llm-usage-store.test.ts +66 -0
  170. package/src/__tests__/logger.test.ts +89 -0
  171. package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
  172. package/src/__tests__/mcp-abort-signal.test.ts +16 -2
  173. package/src/__tests__/mcp-client-auth.test.ts +14 -0
  174. package/src/__tests__/media-generate-image.test.ts +31 -0
  175. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  176. package/src/__tests__/messaging-send-tool.test.ts +1 -0
  177. package/src/__tests__/migration-import-from-url.test.ts +3 -3
  178. package/src/__tests__/mock-gateway-ipc.ts +18 -2
  179. package/src/__tests__/model-intents.test.ts +4 -6
  180. package/src/__tests__/native-web-search.test.ts +30 -2
  181. package/src/__tests__/notification-deep-link.test.ts +62 -0
  182. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  183. package/src/__tests__/oauth-commands-routes.test.ts +37 -0
  184. package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
  185. package/src/__tests__/oauth-store.test.ts +3 -2
  186. package/src/__tests__/onboarding-template-contract.test.ts +4 -3
  187. package/src/__tests__/openai-provider.test.ts +54 -9
  188. package/src/__tests__/openai-responses-provider.test.ts +176 -14
  189. package/src/__tests__/openrouter-provider-only.test.ts +27 -5
  190. package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
  191. package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
  192. package/src/__tests__/persistence-pipeline.test.ts +139 -1
  193. package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
  194. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  195. package/src/__tests__/platform.test.ts +2 -2
  196. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  197. package/src/__tests__/plugin-bootstrap.test.ts +11 -13
  198. package/src/__tests__/plugin-tool-contribution.test.ts +50 -40
  199. package/src/__tests__/plugin-types.test.ts +3 -2
  200. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  201. package/src/__tests__/pricing.test.ts +12 -0
  202. package/src/__tests__/process-message-background-slack.test.ts +21 -16
  203. package/src/__tests__/process-message-display-content.test.ts +19 -22
  204. package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
  205. package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
  206. package/src/__tests__/provider-registry-ollama.test.ts +45 -22
  207. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  208. package/src/__tests__/recording-handler.test.ts +1 -0
  209. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
  210. package/src/__tests__/registry.test.ts +84 -84
  211. package/src/__tests__/relay-server.test.ts +10 -10
  212. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  213. package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
  214. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  215. package/src/__tests__/schedule-store.test.ts +16 -1
  216. package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
  217. package/src/__tests__/secret-ingress-http.test.ts +5 -1
  218. package/src/__tests__/secure-keys.test.ts +3 -3
  219. package/src/__tests__/send-endpoint-busy.test.ts +81 -42
  220. package/src/__tests__/server-history-render.test.ts +4 -1
  221. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  222. package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
  223. package/src/__tests__/skill-feature-flags.test.ts +16 -18
  224. package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
  225. package/src/__tests__/skill-projection-feature-flag.test.ts +48 -37
  226. package/src/__tests__/skill-projection.benchmark.test.ts +7 -13
  227. package/src/__tests__/skill-tool-factory.test.ts +97 -96
  228. package/src/__tests__/slack-channel-config.test.ts +3 -3
  229. package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
  230. package/src/__tests__/subagent-disposal.test.ts +27 -8
  231. package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
  232. package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
  233. package/src/__tests__/subagent-manager-notify.test.ts +20 -8
  234. package/src/__tests__/subagent-notify-parent.test.ts +6 -5
  235. package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
  236. package/src/__tests__/subagent-tools.test.ts +2 -1
  237. package/src/__tests__/suggestion-routes.test.ts +2 -0
  238. package/src/__tests__/sync-message-contract.test.ts +59 -0
  239. package/src/__tests__/system-prompt.test.ts +183 -131
  240. package/src/__tests__/terminal-tools.test.ts +1 -1
  241. package/src/__tests__/test-preload-verifier.ts +68 -0
  242. package/src/__tests__/test-preload.ts +32 -39
  243. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  244. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  245. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  246. package/src/__tests__/tool-executor-lifecycle-events.test.ts +35 -12
  247. package/src/__tests__/tool-executor.test.ts +64 -72
  248. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  249. package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
  250. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  251. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  252. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  253. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  254. package/src/__tests__/twilio-routes.test.ts +3 -2
  255. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  256. package/src/__tests__/usage-routes.test.ts +3 -0
  257. package/src/__tests__/validate-input.test.ts +381 -0
  258. package/src/__tests__/verification-control-plane-policy.test.ts +3 -2
  259. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
  260. package/src/__tests__/voice-session-bridge.test.ts +37 -28
  261. package/src/__tests__/workspace-git-service.test.ts +6 -5
  262. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  263. package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
  264. package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
  265. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  266. package/src/acp/prepare-agent-env.ts +78 -0
  267. package/src/acp/session-manager.ts +6 -7
  268. package/src/agent/loop.ts +88 -0
  269. package/src/api/README.md +127 -0
  270. package/src/api/constants/call-sites.ts +27 -0
  271. package/src/api/events/assistant-outbound-attachment.ts +51 -0
  272. package/src/api/events/assistant-text-delta.ts +32 -0
  273. package/src/api/events/assistant-turn-start.ts +33 -0
  274. package/src/api/events/document-comment-created.ts +48 -0
  275. package/src/api/events/document-comment-deleted.ts +24 -0
  276. package/src/api/events/document-comment-reopened.ts +25 -0
  277. package/src/api/events/document-comment-resolved.ts +27 -0
  278. package/src/api/events/generation-cancelled.ts +24 -0
  279. package/src/api/events/generation-handoff.ts +41 -0
  280. package/src/api/events/message-complete.ts +42 -0
  281. package/src/api/events/open-url.ts +30 -0
  282. package/src/api/events/relationship-state-updated.ts +25 -0
  283. package/src/api/events/tool-use-start.ts +32 -0
  284. package/src/api/index.ts +129 -0
  285. package/src/api/package.json +10 -0
  286. package/src/api/responses/llm-context-response.ts +39 -0
  287. package/src/api/responses/llm-request-log-entry.ts +93 -0
  288. package/src/api/responses/memory-recall-log.ts +65 -0
  289. package/src/api/responses/memory-v2-activation-log.ts +78 -0
  290. package/src/background-wake/background-wake-routes.test.ts +868 -0
  291. package/src/background-wake/platform-client.test.ts +308 -0
  292. package/src/background-wake/platform-client.ts +167 -0
  293. package/src/background-wake/publisher.ts +91 -0
  294. package/src/background-wake/runtime-registry.ts +24 -0
  295. package/src/background-wake/wake-intent-hooks.test.ts +282 -0
  296. package/src/calls/guardian-dispatch.ts +1 -0
  297. package/src/calls/voice-session-bridge.ts +4 -4
  298. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  299. package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
  300. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  301. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  302. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  303. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  304. package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
  305. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  306. package/src/cli/commands/__tests__/notifications.test.ts +184 -40
  307. package/src/cli/commands/browser.ts +247 -0
  308. package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
  309. package/src/cli/commands/channels/index.ts +229 -0
  310. package/src/cli/commands/domain.ts +91 -41
  311. package/src/cli/commands/inference.ts +93 -40
  312. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  313. package/src/cli/commands/memory-v2.ts +176 -1
  314. package/src/cli/commands/memory-v3-render.ts +491 -0
  315. package/src/cli/commands/memory-v3.ts +567 -0
  316. package/src/cli/commands/notifications.ts +365 -55
  317. package/src/cli/lib/open-browser.ts +7 -2
  318. package/src/cli/program.ts +4 -0
  319. package/src/config/assistant-feature-flags.ts +39 -46
  320. package/src/config/bundled-skills/document-editor/SKILL.md +16 -3
  321. package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
  322. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  323. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  324. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  325. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  326. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  327. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  328. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  329. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  330. package/src/config/bundled-skills/schedule/SKILL.md +1 -1
  331. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  332. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
  333. package/src/config/bundled-tool-registry.ts +2 -0
  334. package/src/config/call-site-defaults.ts +8 -7
  335. package/src/config/feature-flag-cache.ts +86 -0
  336. package/src/config/feature-flag-registry.json +33 -17
  337. package/src/config/llm-context-resolution.ts +10 -1
  338. package/src/config/llm-resolver.ts +121 -15
  339. package/src/config/loader.ts +4 -5
  340. package/src/config/schemas/__tests__/memory-v2.test.ts +228 -1
  341. package/src/config/schemas/call-site-catalog.ts +21 -7
  342. package/src/config/schemas/heartbeat.ts +1 -1
  343. package/src/config/schemas/llm.ts +102 -2
  344. package/src/config/schemas/memory-v2.ts +272 -0
  345. package/src/config/schemas/memory.ts +2 -1
  346. package/src/config/schemas/services.ts +6 -2
  347. package/src/config/seed-inference-profiles.ts +36 -16
  348. package/src/context/compactor.ts +52 -0
  349. package/src/context/token-estimator.ts +10 -5
  350. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  351. package/src/conversations/message-consolidation.ts +404 -0
  352. package/src/credential-execution/executable-discovery.ts +40 -0
  353. package/src/credential-execution/process-manager.ts +6 -2
  354. package/src/credential-health/credential-health-service.ts +125 -40
  355. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
  356. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
  357. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +2 -3
  358. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
  359. package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
  360. package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
  361. package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
  362. package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
  363. package/src/daemon/conversation-agent-loop-handlers.ts +390 -80
  364. package/src/daemon/conversation-agent-loop.ts +244 -90
  365. package/src/daemon/conversation-error.ts +64 -6
  366. package/src/daemon/conversation-lifecycle.ts +27 -22
  367. package/src/daemon/conversation-messaging.ts +84 -43
  368. package/src/daemon/conversation-process.ts +74 -37
  369. package/src/daemon/conversation-runtime-assembly.ts +38 -17
  370. package/src/daemon/conversation-skill-tools.ts +14 -30
  371. package/src/daemon/conversation-surfaces.ts +69 -34
  372. package/src/daemon/conversation-tool-setup.ts +77 -32
  373. package/src/daemon/conversation-usage.ts +2 -0
  374. package/src/daemon/conversation.ts +40 -75
  375. package/src/daemon/daemon-control.ts +1 -1
  376. package/src/daemon/daemon-skill-host.ts +9 -2
  377. package/src/daemon/disk-pressure-guard.ts +39 -29
  378. package/src/daemon/first-greeting.ts +31 -13
  379. package/src/daemon/handlers/config-model.test.ts +1 -0
  380. package/src/daemon/handlers/conversations.ts +11 -3
  381. package/src/daemon/handlers/shared.ts +6 -1
  382. package/src/daemon/host-browser-proxy.ts +5 -5
  383. package/src/daemon/host-cu-proxy.ts +4 -4
  384. package/src/daemon/host-file-proxy.ts +4 -4
  385. package/src/daemon/host-proxy-base.ts +4 -4
  386. package/src/daemon/host-transfer-proxy.ts +10 -10
  387. package/src/daemon/lifecycle.ts +29 -26
  388. package/src/daemon/mcp-reload-service.ts +1 -1
  389. package/src/daemon/meet-manifest-loader.ts +11 -24
  390. package/src/daemon/message-types/conversations.ts +22 -27
  391. package/src/daemon/message-types/document-comments.ts +8 -44
  392. package/src/daemon/message-types/home.ts +2 -14
  393. package/src/daemon/message-types/integrations.ts +2 -7
  394. package/src/daemon/message-types/messages.ts +25 -48
  395. package/src/daemon/message-types/subagents.ts +6 -0
  396. package/src/daemon/message-types/sync.ts +14 -0
  397. package/src/daemon/process-message.ts +9 -9
  398. package/src/daemon/providers-setup.ts +1 -1
  399. package/src/daemon/server.ts +16 -0
  400. package/src/daemon/shutdown-handlers.ts +24 -5
  401. package/src/daemon/switch-inference-profile-tool.ts +62 -0
  402. package/src/daemon/tool-setup-types.ts +7 -0
  403. package/src/daemon/wake-target-adapter.ts +10 -0
  404. package/src/documents/document-store.ts +38 -0
  405. package/src/export/__tests__/transcript-formatter.test.ts +1 -0
  406. package/src/heartbeat/__tests__/heartbeat-service.test.ts +30 -1
  407. package/src/heartbeat/heartbeat-service.ts +63 -0
  408. package/src/home/__tests__/feed-writer.test.ts +161 -0
  409. package/src/home/__tests__/post-connect-feed.test.ts +1 -0
  410. package/src/home/__tests__/suggested-prompts.test.ts +55 -59
  411. package/src/home/feed-writer.ts +146 -7
  412. package/src/home/home-greeting.ts +0 -9
  413. package/src/home/suggested-prompts.ts +27 -154
  414. package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
  415. package/src/ipc/gateway-client.test.ts +4 -1
  416. package/src/ipc/gateway-flag-listener.ts +123 -0
  417. package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
  418. package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
  419. package/src/ipc/skill-routes/memory.ts +4 -3
  420. package/src/ipc/skill-routes/registries.ts +35 -40
  421. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  422. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  423. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +242 -0
  424. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  425. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
  426. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
  427. package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
  428. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
  429. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
  430. package/src/memory/auto-analysis-enqueue.ts +5 -1
  431. package/src/memory/conversation-attention-store.ts +17 -3
  432. package/src/memory/conversation-crud.ts +423 -182
  433. package/src/memory/conversation-starters-cadence.ts +3 -1
  434. package/src/memory/conversation-title-service.ts +19 -3
  435. package/src/memory/db-async-query.ts +214 -0
  436. package/src/memory/db-connection.ts +29 -19
  437. package/src/memory/db-init.ts +14 -0
  438. package/src/memory/db-maintenance.ts +30 -21
  439. package/src/memory/db-singleton.ts +77 -0
  440. package/src/memory/delivery-channels.ts +82 -0
  441. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
  442. package/src/memory/graph/bootstrap.ts +8 -1
  443. package/src/memory/graph/capability-seed.ts +7 -3
  444. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  445. package/src/memory/graph/extraction.ts +1 -5
  446. package/src/memory/graph/graph-search.ts +7 -1
  447. package/src/memory/graph/retriever.test.ts +3 -3
  448. package/src/memory/indexer.ts +28 -18
  449. package/src/memory/job-handlers/cleanup.ts +76 -18
  450. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  451. package/src/memory/job-handlers/embedding.test.ts +3 -2
  452. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
  453. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  454. package/src/memory/jobs-store.ts +14 -0
  455. package/src/memory/jobs-worker.ts +66 -22
  456. package/src/memory/llm-request-log-source-clickhouse.ts +122 -2
  457. package/src/memory/llm-request-log-source-local.ts +31 -0
  458. package/src/memory/llm-request-log-source.ts +40 -2
  459. package/src/memory/llm-request-log-store.ts +228 -1
  460. package/src/memory/llm-usage-store.ts +24 -0
  461. package/src/memory/memory-retrospective-enqueue.ts +8 -1
  462. package/src/memory/memory-retrospective-job.ts +5 -0
  463. package/src/memory/memory-v2-activation-log-store.ts +110 -7
  464. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  465. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  466. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  467. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  468. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  469. package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
  470. package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
  471. package/src/memory/migrations/index.ts +19 -0
  472. package/src/memory/migrations/registry.ts +33 -0
  473. package/src/memory/schema/conversations.ts +10 -2
  474. package/src/memory/schema/inference.ts +0 -1
  475. package/src/memory/schema/infrastructure.ts +21 -0
  476. package/src/memory/tool-usage-store.ts +36 -8
  477. package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
  478. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  479. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  480. package/src/memory/v2/__tests__/harness-metrics.test.ts +83 -0
  481. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  482. package/src/memory/v2/__tests__/harness-replay-input.test.ts +230 -0
  483. package/src/memory/v2/__tests__/harness-runner.test.ts +135 -0
  484. package/src/memory/v2/__tests__/injection.test.ts +127 -98
  485. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  486. package/src/memory/v2/__tests__/router.test.ts +171 -3
  487. package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
  488. package/src/memory/v2/harness/compare.ts +57 -0
  489. package/src/memory/v2/harness/metrics.ts +128 -0
  490. package/src/memory/v2/harness/oracle.ts +145 -0
  491. package/src/memory/v2/harness/replay-input.ts +240 -0
  492. package/src/memory/v2/harness/retriever.ts +74 -0
  493. package/src/memory/v2/harness/router-retriever.ts +43 -0
  494. package/src/memory/v2/harness/runner.ts +112 -0
  495. package/src/memory/v2/harness/trace.ts +64 -0
  496. package/src/memory/v2/injection.ts +21 -15
  497. package/src/memory/v2/prompts/router.ts +26 -1
  498. package/src/memory/v2/qdrant.ts +14 -2
  499. package/src/memory/v2/router.ts +171 -18
  500. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  501. package/src/memory/v3/__tests__/consolidation-job.test.ts +466 -0
  502. package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
  503. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  504. package/src/memory/v3/__tests__/edges.test.ts +706 -0
  505. package/src/memory/v3/__tests__/filter.test.ts +560 -0
  506. package/src/memory/v3/__tests__/gate.test.ts +637 -0
  507. package/src/memory/v3/__tests__/index-composition.test.ts +291 -0
  508. package/src/memory/v3/__tests__/loop.test.ts +775 -0
  509. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  510. package/src/memory/v3/__tests__/scouts.test.ts +489 -0
  511. package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
  512. package/src/memory/v3/__tests__/shadow-middleware.test.ts +398 -0
  513. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  514. package/src/memory/v3/__tests__/traversal.test.ts +508 -0
  515. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  516. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  517. package/src/memory/v3/__tests__/tree-walk.test.ts +784 -0
  518. package/src/memory/v3/__tests__/validate.test.ts +277 -0
  519. package/src/memory/v3/auto-edges.ts +223 -0
  520. package/src/memory/v3/coactivation-store.ts +124 -0
  521. package/src/memory/v3/consolidation-job.ts +323 -0
  522. package/src/memory/v3/coretrieval-seed.ts +240 -0
  523. package/src/memory/v3/edge-learning-job.ts +160 -0
  524. package/src/memory/v3/edges.ts +286 -0
  525. package/src/memory/v3/filter.ts +286 -0
  526. package/src/memory/v3/gate.ts +349 -0
  527. package/src/memory/v3/index-composition.ts +126 -0
  528. package/src/memory/v3/llm-capture.ts +46 -0
  529. package/src/memory/v3/loop.ts +430 -0
  530. package/src/memory/v3/maintenance.ts +144 -0
  531. package/src/memory/v3/prompt-context.ts +33 -0
  532. package/src/memory/v3/prompts/consolidation.ts +458 -0
  533. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  534. package/src/memory/v3/retriever.ts +33 -0
  535. package/src/memory/v3/scouts.ts +431 -0
  536. package/src/memory/v3/shadow-diff.ts +287 -0
  537. package/src/memory/v3/shadow-middleware.ts +347 -0
  538. package/src/memory/v3/traversal.ts +211 -0
  539. package/src/memory/v3/tree-index.ts +237 -0
  540. package/src/memory/v3/tree-store.ts +394 -0
  541. package/src/memory/v3/tree-walk.ts +356 -0
  542. package/src/memory/v3/types.ts +65 -0
  543. package/src/memory/v3/validate.ts +323 -0
  544. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  545. package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
  546. package/src/notifications/adapters/macos.ts +18 -1
  547. package/src/notifications/adapters/platform.ts +1 -1
  548. package/src/notifications/adapters/slack.ts +45 -11
  549. package/src/notifications/broadcaster.ts +114 -63
  550. package/src/notifications/conversation-pairing.ts +23 -3
  551. package/src/notifications/decision-engine.ts +1 -4
  552. package/src/notifications/decisions-store.ts +32 -1
  553. package/src/notifications/deliveries-store.ts +45 -0
  554. package/src/notifications/edit-notification.ts +201 -0
  555. package/src/notifications/emit-signal.ts +40 -50
  556. package/src/notifications/signal.ts +10 -0
  557. package/src/notifications/types.ts +37 -0
  558. package/src/oauth/byo-connection.test.ts +67 -3
  559. package/src/oauth/byo-connection.ts +32 -5
  560. package/src/oauth/connect-orchestrator.ts +9 -0
  561. package/src/oauth/connection-resolver.test.ts +76 -0
  562. package/src/oauth/connection-resolver.ts +49 -10
  563. package/src/oauth/manual-token-connection.ts +51 -3
  564. package/src/oauth/seed-providers.ts +3 -0
  565. package/src/permissions/approval-policy.test.ts +19 -5
  566. package/src/permissions/approval-policy.ts +14 -3
  567. package/src/permissions/checker.ts +21 -8
  568. package/src/permissions/prompter.ts +3 -3
  569. package/src/permissions/question-prompter.ts +5 -2
  570. package/src/permissions/secret-prompter.ts +2 -2
  571. package/src/platform/client.test.ts +24 -1
  572. package/src/platform/client.ts +8 -0
  573. package/src/platform/feature-gate.ts +15 -0
  574. package/src/plugin-api/index.ts +4 -0
  575. package/src/plugin-api/types.ts +7 -33
  576. package/src/plugins/defaults/index.ts +6 -0
  577. package/src/plugins/defaults/injectors.ts +20 -19
  578. package/src/plugins/defaults/persistence.ts +25 -6
  579. package/src/plugins/external-plugin-loader.ts +5 -68
  580. package/src/plugins/types.ts +68 -29
  581. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  582. package/src/proactive-artifact/job.test.ts +1 -0
  583. package/src/prompts/__tests__/system-prompt.test.ts +4 -4
  584. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  585. package/src/prompts/persona-resolver.ts +36 -21
  586. package/src/prompts/sections.ts +39 -7
  587. package/src/prompts/system-prompt.ts +84 -221
  588. package/src/prompts/template-detection.ts +10 -4
  589. package/src/prompts/templates/BOOTSTRAP.md +9 -13
  590. package/src/prompts/templates/IDENTITY.md +0 -2
  591. package/src/prompts/templates/system-sections.ts +230 -8
  592. package/src/providers/__tests__/connection-model-compat.test.ts +233 -0
  593. package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
  594. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  595. package/src/providers/anthropic/client.ts +32 -66
  596. package/src/providers/call-site-routing.ts +42 -6
  597. package/src/providers/connection-model-compat.ts +61 -0
  598. package/src/providers/connection-resolution.ts +47 -14
  599. package/src/providers/fireworks/client.ts +1 -0
  600. package/src/providers/gemini/client.ts +70 -6
  601. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
  602. package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
  603. package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
  604. package/src/providers/inference/adapter-factory.ts +3 -0
  605. package/src/providers/inference/auth.ts +0 -8
  606. package/src/providers/inference/connections.ts +3 -66
  607. package/src/providers/inference/resolve-auth.ts +2 -3
  608. package/src/providers/minimax/client.ts +106 -0
  609. package/src/providers/model-catalog.ts +78 -1
  610. package/src/providers/model-intents.ts +4 -4
  611. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  612. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
  613. package/src/providers/openai/chat-completions-provider.ts +116 -15
  614. package/src/providers/openai/codex-models.ts +20 -0
  615. package/src/providers/openai/responses-provider.ts +87 -30
  616. package/src/providers/openrouter/client.ts +13 -8
  617. package/src/providers/provider-send-message.ts +20 -5
  618. package/src/providers/registry.ts +48 -8
  619. package/src/providers/retry.ts +50 -7
  620. package/src/providers/search-provider-catalog.ts +17 -9
  621. package/src/providers/thinking-config.ts +26 -1
  622. package/src/providers/types.ts +9 -0
  623. package/src/providers/usage-tracking.ts +2 -0
  624. package/src/runtime/AGENTS.md +2 -2
  625. package/src/runtime/__tests__/agent-wake.test.ts +1 -0
  626. package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
  627. package/src/runtime/access-request-helper.ts +1 -0
  628. package/src/runtime/agent-wake.ts +1 -0
  629. package/src/runtime/assistant-event-hub.ts +76 -6
  630. package/src/runtime/auth/route-policy.ts +46 -0
  631. package/src/runtime/btw-sidechain.ts +0 -6
  632. package/src/runtime/channel-readiness-service.ts +68 -0
  633. package/src/runtime/channel-reply-delivery.ts +23 -0
  634. package/src/runtime/channel-retry-sweep.ts +47 -14
  635. package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
  636. package/src/runtime/http-types.ts +0 -2
  637. package/src/runtime/migrations/vbundle-builder.ts +12 -4
  638. package/src/runtime/pending-interactions.ts +0 -1
  639. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
  640. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
  641. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +204 -0
  642. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  643. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
  644. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
  645. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +76 -9
  646. package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
  647. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  648. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
  649. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
  650. package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
  651. package/src/runtime/routes/acp-routes-list.test.ts +3 -0
  652. package/src/runtime/routes/acp-routes.test.ts +255 -6
  653. package/src/runtime/routes/acp-routes.ts +8 -1
  654. package/src/runtime/routes/app-management-routes.ts +111 -4
  655. package/src/runtime/routes/avatar-routes.ts +10 -10
  656. package/src/runtime/routes/background-wake-routes.ts +356 -0
  657. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  658. package/src/runtime/routes/btw-routes.ts +4 -10
  659. package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
  660. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  661. package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
  662. package/src/runtime/routes/conversation-list-routes.ts +159 -4
  663. package/src/runtime/routes/conversation-management-routes.ts +108 -26
  664. package/src/runtime/routes/conversation-query-routes.ts +200 -44
  665. package/src/runtime/routes/conversation-routes.ts +409 -521
  666. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  667. package/src/runtime/routes/conversations-import-routes.ts +19 -6
  668. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  669. package/src/runtime/routes/documents-routes.ts +10 -1
  670. package/src/runtime/routes/domain-routes.ts +60 -10
  671. package/src/runtime/routes/email-routes.ts +5 -2
  672. package/src/runtime/routes/events-routes.ts +54 -10
  673. package/src/runtime/routes/group-routes.ts +35 -8
  674. package/src/runtime/routes/home-feed-routes.ts +129 -0
  675. package/src/runtime/routes/host-browser-routes.ts +10 -2
  676. package/src/runtime/routes/host-cu-routes.ts +2 -2
  677. package/src/runtime/routes/identity-intro-cache.ts +61 -16
  678. package/src/runtime/routes/identity-routes.ts +30 -9
  679. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  680. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
  681. package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
  682. package/src/runtime/routes/index.ts +10 -0
  683. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  684. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  685. package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
  686. package/src/runtime/routes/integrations/vercel.ts +15 -0
  687. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  688. package/src/runtime/routes/llm-context-normalization.ts +7 -2
  689. package/src/runtime/routes/memory-item-routes.ts +8 -3
  690. package/src/runtime/routes/memory-v2-routes.ts +215 -5
  691. package/src/runtime/routes/memory-v3-routes.ts +474 -0
  692. package/src/runtime/routes/migration-routes.ts +32 -28
  693. package/src/runtime/routes/notification-routes.ts +63 -1
  694. package/src/runtime/routes/oauth-commands-routes.ts +6 -1
  695. package/src/runtime/routes/plugins-routes.ts +337 -0
  696. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  697. package/src/runtime/routes/secret-routes.ts +25 -5
  698. package/src/runtime/routes/settings-routes.ts +12 -11
  699. package/src/runtime/routes/slack-channel-routes.ts +5 -4
  700. package/src/runtime/routes/surface-action-routes.ts +1 -38
  701. package/src/runtime/routes/surface-content-routes.ts +12 -5
  702. package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
  703. package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
  704. package/src/runtime/routes/workspace-routes.ts +25 -10
  705. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
  706. package/src/runtime/slack-dm-text-delivery.ts +177 -0
  707. package/src/runtime/sync/resource-sync-events.ts +106 -38
  708. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  709. package/src/runtime/sync/sync-publisher.ts +2 -1
  710. package/src/runtime/tool-grant-request-helper.ts +1 -0
  711. package/src/runtime/verification-outbound-actions.ts +73 -1
  712. package/src/schedule/schedule-store.ts +8 -1
  713. package/src/schedule/scheduler.ts +111 -15
  714. package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
  715. package/src/security/encrypted-store.ts +7 -16
  716. package/src/security/store-path-override.ts +61 -0
  717. package/src/signals/user-message.ts +5 -8
  718. package/src/skills/validate-input.ts +177 -0
  719. package/src/subagent/manager.ts +13 -13
  720. package/src/subagent/types.ts +6 -0
  721. package/src/tasks/tool-sanitizer.ts +2 -2
  722. package/src/telemetry/types.ts +12 -0
  723. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  724. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  725. package/src/tools/acp/spawn.test.ts +119 -0
  726. package/src/tools/acp/spawn.ts +15 -2
  727. package/src/tools/apps/definitions.ts +36 -28
  728. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  729. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  730. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
  731. package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
  732. package/src/tools/browser/browser-execution.ts +16 -3
  733. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  734. package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
  735. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
  736. package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
  737. package/src/tools/browser/cdp-client/factory.ts +100 -17
  738. package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
  739. package/src/tools/browser/cdp-client/types.ts +65 -0
  740. package/src/tools/browser/pinned-tabs.ts +96 -40
  741. package/src/tools/computer-use/definitions.ts +282 -336
  742. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  743. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  744. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  745. package/src/tools/credentials/vault.ts +3 -9
  746. package/src/tools/document/document-tool.ts +189 -7
  747. package/src/tools/execution-target.ts +18 -23
  748. package/src/tools/executor.ts +24 -56
  749. package/src/tools/filesystem/edit.ts +3 -9
  750. package/src/tools/filesystem/list.ts +3 -9
  751. package/src/tools/filesystem/read.ts +3 -9
  752. package/src/tools/filesystem/write.ts +3 -9
  753. package/src/tools/host-filesystem/edit.test.ts +1 -0
  754. package/src/tools/host-filesystem/edit.ts +3 -9
  755. package/src/tools/host-filesystem/read.test.ts +1 -0
  756. package/src/tools/host-filesystem/read.ts +3 -9
  757. package/src/tools/host-filesystem/transfer.test.ts +31 -6
  758. package/src/tools/host-filesystem/transfer.ts +3 -9
  759. package/src/tools/host-filesystem/write.test.ts +1 -0
  760. package/src/tools/host-filesystem/write.ts +3 -9
  761. package/src/tools/host-terminal/host-shell.ts +3 -9
  762. package/src/tools/mcp/mcp-tool-factory.ts +1 -10
  763. package/src/tools/memory/register.test.ts +1 -1
  764. package/src/tools/memory/register.ts +4 -9
  765. package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
  766. package/src/tools/network/__tests__/web-search.test.ts +211 -3
  767. package/src/tools/network/managed-search-proxy.ts +183 -0
  768. package/src/tools/network/web-fetch.ts +3 -9
  769. package/src/tools/network/web-search.ts +224 -76
  770. package/src/tools/policy-context.ts +3 -1
  771. package/src/tools/registry.ts +150 -123
  772. package/src/tools/schedule/create.ts +1 -1
  773. package/src/tools/schema-transforms.ts +1 -1
  774. package/src/tools/skills/execute.ts +3 -9
  775. package/src/tools/skills/load.ts +3 -9
  776. package/src/tools/skills/skill-tool-factory.ts +18 -44
  777. package/src/tools/subagent/notify-parent.ts +3 -9
  778. package/src/tools/subagent/spawn.ts +3 -0
  779. package/src/tools/system/request-permission.ts +3 -9
  780. package/src/tools/terminal/shell.ts +3 -9
  781. package/src/tools/tool-approval-handler.ts +10 -4
  782. package/src/tools/tool-defaults.ts +94 -0
  783. package/src/tools/tool-name-aliases.ts +72 -14
  784. package/src/tools/types.ts +32 -101
  785. package/src/tools/ui-surface/definitions.ts +104 -108
  786. package/src/types/onboarding-context.ts +6 -0
  787. package/src/usage/attribution.ts +32 -1
  788. package/src/usage/pricing.ts +23 -0
  789. package/src/usage/types.ts +12 -0
  790. package/src/util/browser.ts +7 -2
  791. package/src/util/logger.ts +16 -7
  792. package/src/util/platform.ts +7 -2
  793. package/src/util/sqlite3-runtime.ts +65 -0
  794. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  795. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  796. package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
  797. package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
  798. package/src/workspace/migrations/registry.ts +6 -0
  799. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  800. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  801. package/src/daemon/query-complexity-router.ts +0 -75
  802. package/src/prompts/cache-boundary.ts +0 -8
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Pure JSON-schema input validator for skill tool calls.
3
+ *
4
+ * Deliberate strict subset of JSON Schema: it covers only the keywords
5
+ * actually used by `assistant/src/config/bundled-skills/**\/TOOLS.json`
6
+ * (required / type / enum / items.type) plus unknown-key detection. Anything
7
+ * else (`$ref`, `oneOf`, `anyOf`, `allOf`, `format`, `pattern`, `minimum`,
8
+ * `maximum`, object-shape `additionalProperties`, etc.) is silently skipped so
9
+ * a richer schema can never cause us to reject a legitimate call.
10
+ *
11
+ * Each error message is written to be agent-readable and self-correcting
12
+ * (e.g. `surface_id is required`, `mode must be one of "replace", "append"`).
13
+ */
14
+
15
+ import { isPlainObject } from "../util/object.js";
16
+
17
+ export interface InputValidationSuccess {
18
+ ok: true;
19
+ }
20
+
21
+ export interface InputValidationFailure {
22
+ ok: false;
23
+ /** Human-readable messages, one per problem. */
24
+ errors: string[];
25
+ }
26
+
27
+ export type InputValidationResult =
28
+ | InputValidationSuccess
29
+ | InputValidationFailure;
30
+
31
+ type SupportedType =
32
+ | "string"
33
+ | "number"
34
+ | "integer"
35
+ | "boolean"
36
+ | "array"
37
+ | "object";
38
+
39
+ const SUPPORTED_TYPES: ReadonlySet<string> = new Set([
40
+ "string",
41
+ "number",
42
+ "integer",
43
+ "boolean",
44
+ "array",
45
+ "object",
46
+ ]);
47
+
48
+ function matchesType(value: unknown, type: SupportedType): boolean {
49
+ switch (type) {
50
+ case "string":
51
+ return typeof value === "string";
52
+ case "number":
53
+ return typeof value === "number";
54
+ case "integer":
55
+ return typeof value === "number" && Number.isInteger(value);
56
+ case "boolean":
57
+ return typeof value === "boolean";
58
+ case "array":
59
+ return Array.isArray(value);
60
+ case "object":
61
+ return isPlainObject(value);
62
+ }
63
+ }
64
+
65
+ function quoteList(values: readonly string[]): string {
66
+ return values.map((v) => `"${v}"`).join(", ");
67
+ }
68
+
69
+ /**
70
+ * Validate a tool input object against the (optional) JSON-schema definition
71
+ * declared on the tool entry. Returns `{ ok: true }` if the input is valid (or
72
+ * if there is nothing actionable to validate); otherwise returns a list of
73
+ * human-readable error strings.
74
+ *
75
+ * Pure: never mutates `input` or `schema`, no I/O.
76
+ */
77
+ export function validateInputAgainstSchema(
78
+ _toolName: string,
79
+ input: Record<string, unknown>,
80
+ schema: Record<string, unknown> | undefined,
81
+ ): InputValidationResult {
82
+ // Skip when there's no schema or no properties block — matches today's
83
+ // lenient behaviour for tools that declare only `{ type: "object" }`.
84
+ if (!schema) return { ok: true };
85
+ const properties = schema.properties;
86
+ if (!isPlainObject(properties)) return { ok: true };
87
+
88
+ const errors: string[] = [];
89
+ const knownKeys = Object.keys(properties);
90
+ const knownKeySet = new Set(knownKeys);
91
+
92
+ // 1. Required fields — presence-only check per JSON Schema spec.
93
+ // `required` only requires the property to be present; `null` is a valid
94
+ // value when the schema allows it (e.g. `type: ["string", "null"]`).
95
+ const required = schema.required;
96
+ if (Array.isArray(required)) {
97
+ for (const key of required) {
98
+ if (typeof key !== "string") continue;
99
+ if (!(key in input)) {
100
+ errors.push(`${key} is required`);
101
+ }
102
+ }
103
+ }
104
+
105
+ // 2. Per-property checks: type, enum, items.type.
106
+ for (const [key, rawSubSchema] of Object.entries(properties)) {
107
+ if (!(key in input)) continue;
108
+ const value = input[key];
109
+ // Skip type-checking for absent values; presence is enforced by the
110
+ // `required` check above. Note: `null` IS a present value and is
111
+ // type-checked below — only schemas that explicitly opt in to null via
112
+ // a union type (`type: ["string","null"]`) bypass the check, handled
113
+ // by the `Array.isArray(declaredType)` skip immediately below.
114
+ if (value === undefined) continue;
115
+ if (!isPlainObject(rawSubSchema)) continue;
116
+
117
+ const declaredType = rawSubSchema.type;
118
+ // Skip union types (e.g. `["string", "null"]`) — same lenient treatment
119
+ // we give `oneOf`/`anyOf`/`$ref`. We only validate single-type schemas.
120
+ if (Array.isArray(declaredType)) continue;
121
+ if (typeof declaredType === "string" && SUPPORTED_TYPES.has(declaredType)) {
122
+ const type = declaredType as SupportedType;
123
+ if (!matchesType(value, type)) {
124
+ errors.push(`${key} must be ${typeArticle(type)} ${type}`);
125
+ // No point checking enum/items if the base type is wrong.
126
+ continue;
127
+ }
128
+
129
+ // 2a. Enum (string enums are the only shape used today).
130
+ const enumValues = rawSubSchema.enum;
131
+ if (Array.isArray(enumValues) && enumValues.length > 0) {
132
+ if (!enumValues.includes(value)) {
133
+ errors.push(
134
+ `${key} must be one of ${quoteList(enumValues.map(String))}`,
135
+ );
136
+ }
137
+ }
138
+
139
+ // 2b. Array items.type — per-element check.
140
+ if (type === "array" && isPlainObject(rawSubSchema.items)) {
141
+ const itemType = rawSubSchema.items.type;
142
+ if (
143
+ typeof itemType === "string" &&
144
+ SUPPORTED_TYPES.has(itemType) &&
145
+ Array.isArray(value)
146
+ ) {
147
+ const itemTypeName = itemType as SupportedType;
148
+ value.forEach((element, index) => {
149
+ if (!matchesType(element, itemTypeName)) {
150
+ errors.push(
151
+ `${key}[${index}] must be ${typeArticle(itemTypeName)} ${itemTypeName}`,
152
+ );
153
+ }
154
+ });
155
+ }
156
+ }
157
+ }
158
+ }
159
+
160
+ // 3. Unknown keys — parity with the previous `validateNoUnknownParams`.
161
+ const unknownKeys = Object.keys(input).filter((k) => !knownKeySet.has(k));
162
+ for (const key of unknownKeys) {
163
+ errors.push(
164
+ `Unknown parameter "${key}". Supported: ${quoteList(knownKeys)}`,
165
+ );
166
+ }
167
+
168
+ if (errors.length === 0) return { ok: true };
169
+ return { ok: false, errors };
170
+ }
171
+
172
+ function typeArticle(type: SupportedType): "a" | "an" {
173
+ // `integer`, `array`, `object` start with a vowel sound.
174
+ return type === "integer" || type === "array" || type === "object"
175
+ ? "an"
176
+ : "a";
177
+ }
@@ -365,6 +365,7 @@ export class SubagentManager {
365
365
  label: config.label,
366
366
  objective: config.objective,
367
367
  isFork: config.fork ?? false,
368
+ parentToolUseId: config.parentToolUseId,
368
369
  } as ServerMessage);
369
370
 
370
371
  log.info(
@@ -435,7 +436,9 @@ export class SubagentManager {
435
436
  "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯",
436
437
  ].join("\n")
437
438
  : objective;
438
- const messageId = await conversation.persistUserMessage(message, []);
439
+ const { id: messageId } = await conversation.persistUserMessage({
440
+ content: message,
441
+ });
439
442
  await conversation.runAgentLoop(message, messageId, undefined, {
440
443
  callSite: "subagentSpawn",
441
444
  ...(managed.state.config.overrideProfile
@@ -609,7 +612,7 @@ export class SubagentManager {
609
612
  return "terminal";
610
613
 
611
614
  // If the conversation is busy, queue the message; otherwise process immediately.
612
- const result = managed.conversation.enqueueMessage(trimmed, []);
615
+ const result = managed.conversation.enqueueMessage({ content: trimmed });
613
616
  if (result.rejected) {
614
617
  return "sent"; // error event already delivered via sendToClient
615
618
  }
@@ -620,7 +623,9 @@ export class SubagentManager {
620
623
  // Capture conversation before the await — managed.conversation may be
621
624
  // nulled by an external dispose() while persistUserMessage is awaited.
622
625
  const conversation = managed.conversation;
623
- const messageId = await conversation.persistUserMessage(trimmed, []);
626
+ const { id: messageId } = await conversation.persistUserMessage({
627
+ content: trimmed,
628
+ });
624
629
  conversation
625
630
  .runAgentLoop(trimmed, messageId, undefined, {
626
631
  callSite: "subagentSpawn",
@@ -984,19 +989,14 @@ export class SubagentManager {
984
989
  );
985
990
  return;
986
991
  }
987
- const enqueueResult = parentConversation.enqueueMessage(
988
- message,
989
- [],
990
- undefined,
991
- undefined,
992
- undefined,
993
- undefined,
992
+ const enqueueResult = parentConversation.enqueueMessage({
993
+ content: message,
994
994
  metadata,
995
- );
995
+ });
996
996
  if (!enqueueResult.queued && !enqueueResult.rejected) {
997
997
  parentConversation
998
- .persistUserMessage(message, [], undefined, metadata)
999
- .then((messageId) =>
998
+ .persistUserMessage({ content: message, metadata })
999
+ .then(({ id: messageId }) =>
1000
1000
  parentConversation.runAgentLoop(message, messageId),
1001
1001
  )
1002
1002
  .catch((err) => {
@@ -69,6 +69,12 @@ export interface SubagentConfig {
69
69
  * profile, every spawned subagent inherits it automatically.
70
70
  */
71
71
  overrideProfile?: string;
72
+ /**
73
+ * Tool-use id of the `skill_execute` call that spawned this subagent.
74
+ * Forwarded into the `subagent_spawned` event so the client can anchor the
75
+ * inline subagent card to the exact spawn tool call.
76
+ */
77
+ parentToolUseId?: string;
72
78
  }
73
79
 
74
80
  // ── State (runtime) ─────────────────────────────────────────────────────
@@ -1,4 +1,4 @@
1
- import { getAllTools, getTool } from "../tools/registry.js";
1
+ import { getAllTools, getTool, getToolOwner } from "../tools/registry.js";
2
2
 
3
3
  /**
4
4
  * Deduplicate and sort a list of tool names, validating against the live
@@ -24,7 +24,7 @@ export function sanitizeToolList(tools: string[]): string[] {
24
24
  */
25
25
  export function getRegisteredToolNames(): string[] {
26
26
  return getAllTools()
27
- .filter((t) => t.executionMode !== "proxy" && t.origin !== "skill")
27
+ .filter((t) => getToolOwner(t.name)?.kind !== "skill")
28
28
  .map((t) => t.name)
29
29
  .sort();
30
30
  }
@@ -38,6 +38,18 @@ export interface LlmUsageTelemetryEvent extends TelemetryEventBase {
38
38
  output_tokens: number;
39
39
  cache_creation_input_tokens: number | null;
40
40
  cache_read_input_tokens: number | null;
41
+ /**
42
+ * The provider's untouched `usage` block. Anthropic surfaces a TTL
43
+ * breakdown under `cache_creation.ephemeral_{5m,1h}_input_tokens`;
44
+ * OpenAI surfaces cached-read counts under
45
+ * `prompt_tokens_details.cached_tokens` (and reasoning tokens under
46
+ * `completion_tokens_details`). Both shapes are forwarded verbatim so
47
+ * downstream consumers (admin charts, dbt models) can extract any
48
+ * provider-specific detail without requiring a schema change here.
49
+ * Null when the provider did not return a usage payload, and for
50
+ * daemons that predate `260-llm-usage-add-raw-usage`.
51
+ */
52
+ raw_usage: Record<string, unknown> | null;
41
53
  actor: string;
42
54
  llm_call_site: LLMCallSite | null;
43
55
  inference_profile: string | null;
@@ -159,6 +159,7 @@ function makeUsageEvent(
159
159
  outputTokens: 50,
160
160
  cacheCreationInputTokens: 10,
161
161
  cacheReadInputTokens: 5,
162
+ rawUsage: null,
162
163
  actor: "main_agent",
163
164
  callSite: null,
164
165
  inferenceProfile: null,
@@ -435,6 +436,53 @@ describe("UsageTelemetryReporter", () => {
435
436
  expect(e.inference_profile_source).toBe("conversation");
436
437
  expect(e.cost).toBe(0.001);
437
438
  expect(e.recorded_at).toBe(1700000099000);
439
+ // raw_usage defaults to null on this fixture (the makeUsageEvent default),
440
+ // confirming the wire shape carries the key as `null` rather than
441
+ // dropping it for legacy rows or providers that did not return a
442
+ // usage block.
443
+ expect(e.raw_usage).toBeNull();
444
+ });
445
+
446
+ test("payload forwards the provider's raw_usage block verbatim", async () => {
447
+ // The reporter must surface the literal usage object the provider
448
+ // returned (Anthropic nests TTL breakdown under `cache_creation`,
449
+ // OpenAI nests cached-read counts under `prompt_tokens_details`,
450
+ // etc.) so downstream consumers can extract any provider-specific
451
+ // detail without a wire-level schema change. Anything that
452
+ // transforms, summarises, or strips fields here destroys data the
453
+ // admin charts and dbt models depend on.
454
+ const rawUsage = {
455
+ input_tokens: 200,
456
+ output_tokens: 100,
457
+ cache_creation_input_tokens: 750,
458
+ cache_creation: {
459
+ ephemeral_5m_input_tokens: 250,
460
+ ephemeral_1h_input_tokens: 500,
461
+ },
462
+ cache_read_input_tokens: 15,
463
+ service_tier: "standard",
464
+ };
465
+ const event = makeUsageEvent({
466
+ id: "evt-raw-usage",
467
+ provider: "anthropic",
468
+ model: "claude-sonnet-4-20250514",
469
+ cacheCreationInputTokens: 750,
470
+ rawUsage,
471
+ });
472
+ mockQueryUnreportedUsageEvents.mockReturnValue([event]);
473
+ mockFetch.mockImplementation(() =>
474
+ Promise.resolve(new Response('{"accepted":1}', { status: 200 })),
475
+ );
476
+
477
+ const reporter = new UsageTelemetryReporter();
478
+ await reporter.flush();
479
+
480
+ const body = JSON.parse(
481
+ (mockFetch.mock.calls[0] as [string, RequestInit])[1].body as string,
482
+ );
483
+ const e = body.events[0];
484
+ expect(e.cache_creation_input_tokens).toBe(750);
485
+ expect(e.raw_usage).toEqual(rawUsage);
438
486
  });
439
487
 
440
488
  test("payload preserves null attribution for historical usage rows", async () => {
@@ -234,6 +234,7 @@ export class UsageTelemetryReporter {
234
234
  output_tokens: e.outputTokens,
235
235
  cache_creation_input_tokens: e.cacheCreationInputTokens ?? null,
236
236
  cache_read_input_tokens: e.cacheReadInputTokens ?? null,
237
+ raw_usage: e.rawUsage,
237
238
  actor: e.actor,
238
239
  llm_call_site: e.callSite,
239
240
  inference_profile: e.inferenceProfile,
@@ -82,6 +82,25 @@ mock.module("../../util/logger.js", () => ({
82
82
  }),
83
83
  }));
84
84
 
85
+ // Stub secure-keys so the `prepareAgentEnv` preflight finds a token without
86
+ // the test having to populate the real OS keyring. Driven via `secureKeyStore`
87
+ // per test in beforeEach; the default seeds a vault token so existing tests
88
+ // (which assume claude spawns succeed) keep passing.
89
+ //
90
+ // The real module's other exports are spread in so transitive importers
91
+ // (e.g. session-manager → pending-interactions → credential-routes, which
92
+ // imports `getSecureKeyResultAsync`) still resolve at parse time. Bun's
93
+ // `mock.module` is process-global and returns *exactly* the keys the factory
94
+ // returns — without the spread, any consumer pulling a non-`getSecureKeyAsync`
95
+ // export errors with "Export named '<X>' not found".
96
+ const secureKeyStore = new Map<string, string>();
97
+ const realSecureKeys = await import("../../security/secure-keys.js");
98
+
99
+ mock.module("../../security/secure-keys.js", () => ({
100
+ ...realSecureKeys,
101
+ getSecureKeyAsync: async (key: string) => secureKeyStore.get(key),
102
+ }));
103
+
85
104
  // Stub session manager so we don't actually spawn child processes.
86
105
  const spawnMock = mock(
87
106
  async (
@@ -131,6 +150,14 @@ beforeEach(() => {
131
150
  _resetAdapterVersionCacheForTests();
132
151
  config.setConfig({ agents: DEFAULT_TEST_AGENTS });
133
152
  which.setWhich((cmd) => `/usr/local/bin/${cmd}`);
153
+ // Default: vault has a claude token so the preflight in `prepareAgentEnv`
154
+ // succeeds for tests that don't care about env injection. Env-injection
155
+ // tests below clear/override this explicitly.
156
+ secureKeyStore.clear();
157
+ secureKeyStore.set(
158
+ "credential/acp/claude_oauth_token",
159
+ "default-test-token",
160
+ );
134
161
  });
135
162
 
136
163
  // ---------------------------------------------------------------------------
@@ -376,3 +403,95 @@ describe("executeAcpSpawn — per-agent resume hint", () => {
376
403
  expect(payload.message).not.toContain("To resume this session later");
377
404
  });
378
405
  });
406
+
407
+ // ---------------------------------------------------------------------------
408
+ // executeAcpSpawn — CLAUDE_CODE_OAUTH_TOKEN env injection + preflight
409
+ //
410
+ // Mirrors the HTTP-route test block in
411
+ // `runtime/routes/acp-routes.test.ts` — the skill tool calls into the same
412
+ // `prepareAgentEnv` helper, and the contract must be identical so a
413
+ // missing token fails the spawn at the tool boundary (`isError: true`)
414
+ // instead of letting a token-less subprocess zombie out. PR-history
415
+ // context: the inline env-injection used to live in the route only; this
416
+ // tool path was bypassing it entirely, causing every skill-driven ACP
417
+ // spawn to die on first prompt with "Authentication required". Pin both
418
+ // the happy paths and the throw path here so future drift on either
419
+ // caller fails the suite loudly.
420
+ // ---------------------------------------------------------------------------
421
+
422
+ describe("executeAcpSpawn — CLAUDE_CODE_OAUTH_TOKEN injection", () => {
423
+ test("injects CLAUDE_CODE_OAUTH_TOKEN from the secure store for the claude agent", async () => {
424
+ secureKeyStore.clear();
425
+ secureKeyStore.set(
426
+ "credential/acp/claude_oauth_token",
427
+ "tool-vault-token-abc",
428
+ );
429
+ execScripts.set("npm ls", { error: new Error("npm not installed") });
430
+ execScripts.set("npm view", { error: new Error("npm not installed") });
431
+
432
+ const result = await executeAcpSpawn(
433
+ { agent: "claude", task: "do something" },
434
+ makeContext(),
435
+ );
436
+
437
+ expect(result.isError).toBe(false);
438
+ expect(spawnMock).toHaveBeenCalledTimes(1);
439
+ const agentConfigArg = spawnMock.mock.calls[0][1] as {
440
+ env?: Record<string, string>;
441
+ };
442
+ expect(agentConfigArg.env?.CLAUDE_CODE_OAUTH_TOKEN).toBe(
443
+ "tool-vault-token-abc",
444
+ );
445
+ });
446
+
447
+ test("accepts CLAUDE_CODE_OAUTH_TOKEN from config.json agent.env without a vault entry", async () => {
448
+ // Mirrors the route-level precedence test: a config.json env override
449
+ // is the first-priority provisioning route. The resolver surfaces it
450
+ // on `resolved.agent.env`, which the helper preserves.
451
+ secureKeyStore.clear();
452
+ config.setConfig({
453
+ agents: {
454
+ claude: {
455
+ command: "claude-agent-acp",
456
+ args: [],
457
+ env: { CLAUDE_CODE_OAUTH_TOKEN: "tool-config-token-xyz" },
458
+ },
459
+ codex: { command: "codex-acp", args: [] },
460
+ "unknown-agent": { command: "some-other-binary", args: [] },
461
+ },
462
+ });
463
+ execScripts.set("npm ls", { error: new Error("npm not installed") });
464
+ execScripts.set("npm view", { error: new Error("npm not installed") });
465
+
466
+ const result = await executeAcpSpawn(
467
+ { agent: "claude", task: "do something" },
468
+ makeContext(),
469
+ );
470
+
471
+ expect(result.isError).toBe(false);
472
+ const agentConfigArg = spawnMock.mock.calls[0][1] as {
473
+ env?: Record<string, string>;
474
+ };
475
+ expect(agentConfigArg.env?.CLAUDE_CODE_OAUTH_TOKEN).toBe(
476
+ "tool-config-token-xyz",
477
+ );
478
+ });
479
+
480
+ test("returns isError when no token is available from either route (preflight throw mapped to tool result)", async () => {
481
+ // Both routes empty. The helper throws `FailedDependencyError`; the
482
+ // tool catches it and returns `{ isError: true, content: <msg> }`
483
+ // rather than letting it propagate (the tool boundary is a sync
484
+ // ToolExecutionResult, not an HTTP response).
485
+ secureKeyStore.clear();
486
+
487
+ const result = await executeAcpSpawn(
488
+ { agent: "claude", task: "do something" },
489
+ makeContext(),
490
+ );
491
+
492
+ expect(result.isError).toBe(true);
493
+ expect(result.content).toContain("CLAUDE_CODE_OAUTH_TOKEN");
494
+ // Spawn was NEVER called — preflight fired before the subprocess started.
495
+ expect(spawnMock).not.toHaveBeenCalled();
496
+ });
497
+ });
@@ -1,6 +1,7 @@
1
1
  import { execFile } from "node:child_process";
2
2
 
3
3
  import { getAcpSessionManager } from "../../acp/index.js";
4
+ import { prepareAgentEnv } from "../../acp/prepare-agent-env.js";
4
5
  import { resolveAcpAgent } from "../../acp/resolve-agent.js";
5
6
  import { DEFAULT_AGENT_NPM_PACKAGES } from "../../config/acp-defaults.js";
6
7
  import { getLogger } from "../../util/logger.js";
@@ -159,8 +160,6 @@ export async function executeAcpSpawn(
159
160
  }
160
161
  }
161
162
  }
162
- const agentConfig = resolved.agent;
163
-
164
163
  const sendToClient = context.sendToClient as
165
164
  | ((msg: { type: string; [key: string]: unknown }) => void)
166
165
  | undefined;
@@ -171,6 +170,20 @@ export async function executeAcpSpawn(
171
170
  };
172
171
  }
173
172
 
173
+ // Inject required env vars and preflight via the shared helper. Mirrors
174
+ // the HTTP route at `runtime/routes/acp-routes.ts:spawnSession` — both
175
+ // call sites MUST go through `prepareAgentEnv` before `manager.spawn`,
176
+ // otherwise the spawned subprocess starts with no auth and dies as a
177
+ // zombie after the first prompt. See `acp/prepare-agent-env.ts` for
178
+ // the full rationale.
179
+ let agentConfig;
180
+ try {
181
+ agentConfig = await prepareAgentEnv(resolved.agent);
182
+ } catch (err) {
183
+ const msg = err instanceof Error ? err.message : String(err);
184
+ return { content: msg, isError: true };
185
+ }
186
+
174
187
  // Best-effort version check — never blocks the spawn. If outdated, we
175
188
  // append a non-blocking warning to the success payload.
176
189
  const versionInfo = await checkAdapterVersion(agentConfig.command);
@@ -9,17 +9,31 @@
9
9
  */
10
10
 
11
11
  import { RiskLevel } from "../../permissions/types.js";
12
- import type { ToolDefinition } from "../../providers/types.js";
13
- import type { Tool, ToolExecutionResult } from "../types.js";
12
+ import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
14
13
 
15
14
  // ---------------------------------------------------------------------------
16
15
  // Helpers
17
16
  // ---------------------------------------------------------------------------
18
17
 
19
- function proxyExecute(): Promise<ToolExecutionResult> {
20
- throw new Error(
21
- "Proxy tool: execution must be forwarded to the connected client",
22
- );
18
+ /**
19
+ * Forward execution to the connected macOS client via the request-bound
20
+ * `proxyToolResolver`. Returns a structured error when no resolver is
21
+ * configured (e.g. no client connected) so callers see a normal tool
22
+ * failure rather than an unhandled throw.
23
+ */
24
+ function proxyExecute(toolName: string) {
25
+ return async (
26
+ input: Record<string, unknown>,
27
+ context: ToolContext,
28
+ ): Promise<ToolExecutionResult> => {
29
+ if (!context.proxyToolResolver) {
30
+ return {
31
+ content: `No proxy resolver configured for proxy tool "${toolName}". This tool requires an external resolver (e.g. a connected macOS client).`,
32
+ isError: true,
33
+ };
34
+ }
35
+ return context.proxyToolResolver(toolName, input);
36
+ };
23
37
  }
24
38
 
25
39
  // ---------------------------------------------------------------------------
@@ -32,32 +46,26 @@ const appOpenTool: Tool = {
32
46
  "Open a persistent app in a dynamic_page surface on the connected client.",
33
47
  category: "apps",
34
48
  defaultRiskLevel: RiskLevel.Low,
35
- executionMode: "proxy",
49
+ executionTarget: "host",
36
50
 
37
- getDefinition(): ToolDefinition {
38
- return {
39
- name: this.name,
40
- description: this.description,
41
- input_schema: {
42
- type: "object",
43
- properties: {
44
- app_id: {
45
- type: "string",
46
- description: "The ID of the app to open",
47
- },
48
- open_mode: {
49
- type: "string",
50
- enum: ["preview", "workspace"],
51
- description:
52
- "Display mode. 'preview' shows an inline preview card in chat. 'workspace' opens the full app in a workspace panel. Defaults to 'workspace'.",
53
- },
54
- },
55
- required: ["app_id"],
51
+ input_schema: {
52
+ type: "object",
53
+ properties: {
54
+ app_id: {
55
+ type: "string",
56
+ description: "The ID of the app to open",
57
+ },
58
+ open_mode: {
59
+ type: "string",
60
+ enum: ["preview", "workspace"],
61
+ description:
62
+ "Display mode. 'preview' shows an inline preview card in chat. 'workspace' opens the full app in a workspace panel. Defaults to 'workspace'.",
56
63
  },
57
- };
64
+ },
65
+ required: ["app_id"],
58
66
  },
59
67
 
60
- execute: proxyExecute,
68
+ execute: proxyExecute("app_open"),
61
69
  };
62
70
 
63
71
  // ---------------------------------------------------------------------------
@@ -51,7 +51,7 @@ const singleQ = {
51
51
 
52
52
  describe("AskQuestionTool definition", () => {
53
53
  test("exposes the expected schema shape and description language", () => {
54
- const def = new AskQuestionTool().getDefinition();
54
+ const def = new AskQuestionTool();
55
55
  expect(def.name).toBe("ask_question");
56
56
  expect(def.description).toContain("free-text fallback is always added");
57
57
  expect(def.description).toContain("do not");
@@ -463,8 +463,8 @@ describe("AskQuestionTool batched input", () => {
463
463
 
464
464
  describe("AskQuestionTool definition (batched schema)", () => {
465
465
  test("exposes `questions[]` shape, keeps legacy fields, omits per-question id", () => {
466
- const def = new AskQuestionTool().getDefinition();
467
- const schema = def.input_schema as {
466
+ const def = new AskQuestionTool();
467
+ const schema = def.input_schema as unknown as {
468
468
  properties: Record<
469
469
  string,
470
470
  {