@vellumai/assistant 0.8.3 → 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 (665) hide show
  1. package/ARCHITECTURE.md +2 -2
  2. package/docker-entrypoint.sh +0 -1
  3. package/docs/browser-use-architecture-phase2.md +1 -1
  4. package/knip.json +2 -1
  5. package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
  6. package/openapi.yaml +1492 -100
  7. package/package.json +1 -1
  8. package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
  9. package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
  10. package/src/__tests__/agent-loop.test.ts +88 -3
  11. package/src/__tests__/anthropic-provider.test.ts +302 -33
  12. package/src/__tests__/approval-cascade.test.ts +1 -1
  13. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  14. package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
  15. package/src/__tests__/audit-log-rotation.test.ts +70 -16
  16. package/src/__tests__/background-workers-disk-pressure.test.ts +4 -3
  17. package/src/__tests__/btw-routes.test.ts +2 -3
  18. package/src/__tests__/call-controller.test.ts +0 -1
  19. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  20. package/src/__tests__/channel-delivery-store.test.ts +193 -0
  21. package/src/__tests__/channel-guardian.test.ts +3 -3
  22. package/src/__tests__/channel-reply-delivery.test.ts +284 -5
  23. package/src/__tests__/channel-retry-sweep.test.ts +274 -1
  24. package/src/__tests__/checker.test.ts +6 -15
  25. package/src/__tests__/compaction-events.test.ts +2 -1
  26. package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
  27. package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
  28. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
  29. package/src/__tests__/computer-use-tools.test.ts +2 -4
  30. package/src/__tests__/config-watcher.test.ts +1 -1
  31. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  32. package/src/__tests__/context-token-estimator.test.ts +91 -1
  33. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
  34. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
  35. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +55 -4
  36. package/src/__tests__/conversation-agent-loop-overflow.test.ts +228 -8
  37. package/src/__tests__/conversation-agent-loop.test.ts +188 -129
  38. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
  39. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
  40. package/src/__tests__/conversation-clean-command.test.ts +137 -0
  41. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  42. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
  43. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  44. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  45. package/src/__tests__/conversation-error.test.ts +31 -0
  46. package/src/__tests__/conversation-fork-crud.test.ts +324 -0
  47. package/src/__tests__/conversation-lifecycle.test.ts +53 -12
  48. package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
  49. package/src/__tests__/conversation-load-history-stripped.test.ts +279 -0
  50. package/src/__tests__/conversation-pairing.test.ts +2 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +1 -1
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -1
  53. package/src/__tests__/conversation-queue.test.ts +1 -1
  54. package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
  56. package/src/__tests__/conversation-runtime-assembly.test.ts +264 -81
  57. package/src/__tests__/conversation-seed-composer.test.ts +66 -4
  58. package/src/__tests__/conversation-skill-tools.test.ts +2 -5
  59. package/src/__tests__/conversation-slash-commands.test.ts +36 -8
  60. package/src/__tests__/conversation-slash-queue.test.ts +1 -1
  61. package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
  62. package/src/__tests__/conversation-speed-override.test.ts +1 -1
  63. package/src/__tests__/conversation-store.test.ts +1 -1
  64. package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
  65. package/src/__tests__/conversation-sync-tags.test.ts +99 -32
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -1
  67. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  69. package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
  70. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  71. package/src/__tests__/credential-security-invariants.test.ts +7 -0
  72. package/src/__tests__/credential-vault-unit.test.ts +2 -2
  73. package/src/__tests__/cu-unified-flow.test.ts +10 -1
  74. package/src/__tests__/dm-backfill.test.ts +64 -0
  75. package/src/__tests__/dm-persistence.test.ts +33 -0
  76. package/src/__tests__/document-find-replace.test.ts +501 -0
  77. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  78. package/src/__tests__/email-html-renderer.test.ts +12 -0
  79. package/src/__tests__/first-greeting.test.ts +23 -2
  80. package/src/__tests__/gateway-flag-listener.test.ts +237 -0
  81. package/src/__tests__/gemini-provider.test.ts +78 -0
  82. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  83. package/src/__tests__/guardian-outbound-http.test.ts +7 -5
  84. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  85. package/src/__tests__/headless-browser-navigate.test.ts +172 -0
  86. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  87. package/src/__tests__/heartbeat-service.test.ts +4 -0
  88. package/src/__tests__/host-bash-proxy.test.ts +6 -0
  89. package/src/__tests__/host-browser-proxy.test.ts +10 -0
  90. package/src/__tests__/host-cu-proxy.test.ts +8 -1
  91. package/src/__tests__/host-file-proxy.test.ts +8 -1
  92. package/src/__tests__/host-shell-tool.test.ts +1 -1
  93. package/src/__tests__/host-transfer-proxy.test.ts +8 -1
  94. package/src/__tests__/identity-routes.test.ts +57 -0
  95. package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
  96. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  97. package/src/__tests__/injector-chain.test.ts +2 -0
  98. package/src/__tests__/injector-document-comments.test.ts +378 -0
  99. package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
  100. package/src/__tests__/list-messages-attachments.test.ts +21 -17
  101. package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
  102. package/src/__tests__/list-messages-page-latest.test.ts +130 -14
  103. package/src/__tests__/list-messages-tool-merge.test.ts +77 -17
  104. package/src/__tests__/llm-context-normalization.test.ts +0 -2
  105. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  106. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  107. package/src/__tests__/llm-resolver.test.ts +161 -9
  108. package/src/__tests__/llm-usage-store.test.ts +66 -0
  109. package/src/__tests__/log-export-routes.test.ts +99 -2
  110. package/src/__tests__/logger.test.ts +89 -0
  111. package/src/__tests__/mcp-abort-signal.test.ts +2 -2
  112. package/src/__tests__/media-generate-image.test.ts +31 -0
  113. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  114. package/src/__tests__/message-queue-steer.test.ts +114 -0
  115. package/src/__tests__/model-intents.test.ts +2 -4
  116. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  117. package/src/__tests__/onboarding-template-contract.test.ts +1 -1
  118. package/src/__tests__/openai-provider.test.ts +151 -0
  119. package/src/__tests__/openai-responses-provider.test.ts +118 -16
  120. package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
  121. package/src/__tests__/pending-interactions-resolved-event.test.ts +189 -0
  122. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  123. package/src/__tests__/platform.test.ts +2 -5
  124. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  125. package/src/__tests__/plugin-bootstrap.test.ts +2 -2
  126. package/src/__tests__/plugin-source-watcher.test.ts +302 -0
  127. package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
  128. package/src/__tests__/plugin-types.test.ts +3 -2
  129. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  130. package/src/__tests__/pricing.test.ts +12 -0
  131. package/src/__tests__/process-message-background-slack.test.ts +1 -51
  132. package/src/__tests__/process-message-display-content.test.ts +21 -16
  133. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  134. package/src/__tests__/registry.test.ts +2 -8
  135. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  136. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  137. package/src/__tests__/server-history-render.test.ts +83 -4
  138. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  139. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  140. package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
  141. package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
  142. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  143. package/src/__tests__/steer-tool-repair.test.ts +249 -0
  144. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  145. package/src/__tests__/suggestion-routes.test.ts +1 -0
  146. package/src/__tests__/sync-message-contract.test.ts +59 -0
  147. package/src/__tests__/system-prompt.test.ts +161 -124
  148. package/src/__tests__/terminal-tools.test.ts +12 -2
  149. package/src/__tests__/thinking-block-replay.test.ts +113 -0
  150. package/src/__tests__/thread-backfill.test.ts +370 -22
  151. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  152. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  153. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  154. package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
  155. package/src/__tests__/tool-executor.test.ts +89 -53
  156. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  157. package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
  158. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  159. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  160. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  161. package/src/__tests__/twilio-routes.test.ts +1 -1
  162. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  163. package/src/__tests__/usage-routes.test.ts +3 -0
  164. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  165. package/src/__tests__/web-fetch.test.ts +2 -2
  166. package/src/__tests__/workspace-git-service.test.ts +94 -10
  167. package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
  168. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  169. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  170. package/src/acp/prepare-agent-env.ts +78 -0
  171. package/src/acp/session-manager.ts +1 -1
  172. package/src/agent/attachments.ts +1 -0
  173. package/src/agent/loop.ts +65 -20
  174. package/src/api/README.md +5 -0
  175. package/src/api/index.ts +4 -0
  176. package/src/api/package.json +10 -0
  177. package/src/background-wake/background-wake-routes.test.ts +233 -0
  178. package/src/background-wake/next-wake.test.ts +289 -0
  179. package/src/background-wake/next-wake.ts +172 -0
  180. package/src/background-wake/runtime-registry.ts +24 -0
  181. package/src/browser/operations.ts +15 -0
  182. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  183. package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
  184. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  185. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  186. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  187. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  188. package/src/cli/commands/__tests__/memory-v2.test.ts +10 -12
  189. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  190. package/src/cli/commands/browser.ts +247 -0
  191. package/src/cli/commands/conversations.ts +128 -1
  192. package/src/cli/commands/domain.ts +91 -41
  193. package/src/cli/commands/inference-providers.ts +147 -1
  194. package/src/cli/commands/inference.ts +93 -40
  195. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  196. package/src/cli/commands/memory-v2.ts +483 -0
  197. package/src/cli/commands/memory-v3-render.ts +344 -0
  198. package/src/cli/commands/memory-v3.ts +316 -0
  199. package/src/cli/commands/notifications.ts +24 -2
  200. package/src/cli/program.ts +2 -0
  201. package/src/cli/utils/conversation-id.ts +17 -5
  202. package/src/config/assistant-feature-flags.ts +21 -9
  203. package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
  204. package/src/config/bundled-skills/document-editor/SKILL.md +124 -0
  205. package/src/config/bundled-skills/document-editor/TOOLS.json +258 -0
  206. package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
  207. package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
  208. package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
  209. package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
  210. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  211. package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
  212. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  213. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  214. package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
  215. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  216. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  217. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  218. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  219. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  220. package/src/config/bundled-skills/schedule/SKILL.md +8 -0
  221. package/src/config/bundled-tool-registry.ts +24 -12
  222. package/src/config/call-site-defaults.ts +20 -0
  223. package/src/config/feature-flag-registry.json +115 -3
  224. package/src/config/llm-resolver.ts +16 -2
  225. package/src/config/schemas/__tests__/memory-v2.test.ts +217 -1
  226. package/src/config/schemas/call-site-catalog.ts +35 -0
  227. package/src/config/schemas/llm.ts +14 -0
  228. package/src/config/schemas/memory-v2.ts +294 -1
  229. package/src/config/schemas/memory.ts +2 -1
  230. package/src/context/compactor.ts +60 -1
  231. package/src/context/token-estimator.ts +47 -4
  232. package/src/context/window-manager.ts +25 -0
  233. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  234. package/src/conversations/message-consolidation.ts +404 -0
  235. package/src/credential-health/credential-health-service.ts +34 -19
  236. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
  237. package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
  238. package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
  239. package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
  240. package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
  241. package/src/daemon/conversation-agent-loop-handlers.ts +155 -36
  242. package/src/daemon/conversation-agent-loop.ts +307 -88
  243. package/src/daemon/conversation-error.ts +31 -1
  244. package/src/daemon/conversation-lifecycle.ts +149 -118
  245. package/src/daemon/conversation-messaging.ts +3 -0
  246. package/src/daemon/conversation-process.ts +273 -0
  247. package/src/daemon/conversation-queue-manager.ts +14 -0
  248. package/src/daemon/conversation-runtime-assembly.ts +145 -84
  249. package/src/daemon/conversation-slash.ts +37 -5
  250. package/src/daemon/conversation-surfaces.ts +45 -2
  251. package/src/daemon/conversation-tool-setup.ts +70 -3
  252. package/src/daemon/conversation-usage.ts +2 -0
  253. package/src/daemon/conversation.ts +54 -32
  254. package/src/daemon/disk-pressure-guard.ts +14 -2
  255. package/src/daemon/first-greeting.ts +10 -0
  256. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
  257. package/src/daemon/handlers/config-a2a.ts +160 -0
  258. package/src/daemon/handlers/config-model.test.ts +2 -0
  259. package/src/daemon/handlers/conversations.ts +90 -3
  260. package/src/daemon/handlers/shared.ts +92 -29
  261. package/src/daemon/host-bash-proxy.ts +1 -1
  262. package/src/daemon/host-browser-proxy.ts +5 -5
  263. package/src/daemon/host-cu-proxy.ts +5 -5
  264. package/src/daemon/host-file-proxy.ts +5 -5
  265. package/src/daemon/host-proxy-base.ts +4 -4
  266. package/src/daemon/host-transfer-proxy.ts +11 -11
  267. package/src/daemon/lifecycle.ts +40 -23
  268. package/src/daemon/meet-manifest-loader.ts +1 -7
  269. package/src/daemon/message-protocol.ts +4 -0
  270. package/src/daemon/message-types/conversations.ts +14 -9
  271. package/src/daemon/message-types/document-comments.ts +50 -0
  272. package/src/daemon/message-types/home.ts +1 -13
  273. package/src/daemon/message-types/messages.ts +66 -7
  274. package/src/daemon/message-types/surfaces.ts +3 -1
  275. package/src/daemon/message-types/sync.ts +14 -0
  276. package/src/daemon/message-types/web-activity.ts +57 -0
  277. package/src/daemon/plugin-source-watcher.ts +135 -3
  278. package/src/daemon/process-message.ts +69 -12
  279. package/src/daemon/shutdown-handlers.ts +24 -5
  280. package/src/daemon/switch-inference-profile-tool.ts +52 -0
  281. package/src/daemon/tool-setup-types.ts +13 -0
  282. package/src/daemon/trust-context.ts +6 -0
  283. package/src/documents/document-comments-store.test.ts +338 -0
  284. package/src/documents/document-comments-store.ts +237 -0
  285. package/src/documents/document-store.ts +202 -0
  286. package/src/events/relationship-state-updated.ts +25 -0
  287. package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -2
  288. package/src/heartbeat/heartbeat-service.ts +1 -0
  289. package/src/home/__tests__/suggested-prompts.test.ts +33 -2
  290. package/src/home/feed-types.ts +6 -1
  291. package/src/home/home-content-refresh.ts +52 -0
  292. package/src/home/home-greeting-cache.ts +69 -0
  293. package/src/home/home-greeting.ts +85 -0
  294. package/src/home/suggested-prompts.ts +168 -9
  295. package/src/ipc/gateway-flag-listener.ts +123 -0
  296. package/src/ipc/skill-routes/registries.ts +8 -12
  297. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  298. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  299. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
  300. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  301. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
  302. package/src/memory/__tests__/memory-retrospective-job.test.ts +327 -6
  303. package/src/memory/auto-analysis-enqueue.ts +5 -1
  304. package/src/memory/conversation-crud.ts +191 -100
  305. package/src/memory/conversation-starters-cadence.ts +3 -1
  306. package/src/memory/conversation-title-service.ts +19 -3
  307. package/src/memory/db-async-query.ts +214 -0
  308. package/src/memory/db-init.ts +26 -0
  309. package/src/memory/db-maintenance.ts +30 -21
  310. package/src/memory/delivery-crud.ts +41 -0
  311. package/src/memory/delivery-status.ts +141 -15
  312. package/src/memory/external-conversation-store.ts +32 -1
  313. package/src/memory/graph/bootstrap.ts +8 -1
  314. package/src/memory/graph/capability-seed.ts +7 -3
  315. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  316. package/src/memory/graph/extraction.ts +1 -5
  317. package/src/memory/graph/graph-search.ts +7 -1
  318. package/src/memory/indexer.ts +28 -18
  319. package/src/memory/job-handlers/cleanup.ts +76 -18
  320. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  321. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  322. package/src/memory/jobs-store.ts +14 -0
  323. package/src/memory/jobs-worker.ts +68 -15
  324. package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
  325. package/src/memory/llm-request-log-source-local.ts +7 -0
  326. package/src/memory/llm-request-log-source.ts +9 -2
  327. package/src/memory/llm-request-log-store.ts +43 -1
  328. package/src/memory/llm-usage-store.ts +24 -0
  329. package/src/memory/memory-retrospective-constants.ts +28 -0
  330. package/src/memory/memory-retrospective-enqueue.ts +11 -3
  331. package/src/memory/memory-retrospective-job.ts +413 -18
  332. package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
  333. package/src/memory/memory-v2-activation-log-store.ts +41 -14
  334. package/src/memory/migrations/100-core-tables.ts +1 -0
  335. package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
  336. package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
  337. package/src/memory/migrations/253-document-comments.ts +47 -0
  338. package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
  339. package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
  340. package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
  341. package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
  342. package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
  343. package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
  344. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  345. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  346. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  347. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  348. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  349. package/src/memory/migrations/index.ts +34 -0
  350. package/src/memory/migrations/registry.ts +58 -0
  351. package/src/memory/onboarding-events-store.ts +7 -0
  352. package/src/memory/schema/calls.ts +1 -0
  353. package/src/memory/schema/conversations.ts +3 -0
  354. package/src/memory/schema/infrastructure.ts +22 -0
  355. package/src/memory/tool-usage-store.ts +36 -8
  356. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  357. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  358. package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
  359. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  360. package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
  361. package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
  362. package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
  363. package/src/memory/v2/__tests__/injection.test.ts +158 -112
  364. package/src/memory/v2/__tests__/page-index.test.ts +365 -1
  365. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  366. package/src/memory/v2/__tests__/router.test.ts +660 -4
  367. package/src/memory/v2/consolidation-job.ts +14 -0
  368. package/src/memory/v2/harness/compare.ts +57 -0
  369. package/src/memory/v2/harness/metrics.ts +124 -0
  370. package/src/memory/v2/harness/oracle.ts +145 -0
  371. package/src/memory/v2/harness/replay-input.ts +224 -0
  372. package/src/memory/v2/harness/retriever.ts +74 -0
  373. package/src/memory/v2/harness/router-retriever.ts +43 -0
  374. package/src/memory/v2/harness/runner.ts +106 -0
  375. package/src/memory/v2/harness/trace.ts +58 -0
  376. package/src/memory/v2/injection-events.ts +101 -0
  377. package/src/memory/v2/injection.ts +42 -25
  378. package/src/memory/v2/page-index.ts +209 -7
  379. package/src/memory/v2/page-store.ts +18 -0
  380. package/src/memory/v2/prompts/router.ts +26 -1
  381. package/src/memory/v2/qdrant.ts +14 -2
  382. package/src/memory/v2/router.ts +369 -62
  383. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  384. package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
  385. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  386. package/src/memory/v3/__tests__/edges.test.ts +563 -0
  387. package/src/memory/v3/__tests__/filter.test.ts +512 -0
  388. package/src/memory/v3/__tests__/gate.test.ts +574 -0
  389. package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
  390. package/src/memory/v3/__tests__/loop.test.ts +530 -0
  391. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  392. package/src/memory/v3/__tests__/scouts.test.ts +440 -0
  393. package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
  394. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  395. package/src/memory/v3/__tests__/traversal.test.ts +469 -0
  396. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  397. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  398. package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
  399. package/src/memory/v3/__tests__/validate.test.ts +245 -0
  400. package/src/memory/v3/auto-edges.ts +223 -0
  401. package/src/memory/v3/coactivation-store.ts +124 -0
  402. package/src/memory/v3/consolidation-job.ts +323 -0
  403. package/src/memory/v3/edge-learning-job.ts +160 -0
  404. package/src/memory/v3/edges.ts +249 -0
  405. package/src/memory/v3/filter.ts +281 -0
  406. package/src/memory/v3/gate.ts +334 -0
  407. package/src/memory/v3/index-composition.ts +113 -0
  408. package/src/memory/v3/llm-capture.ts +46 -0
  409. package/src/memory/v3/loop.ts +382 -0
  410. package/src/memory/v3/maintenance.ts +144 -0
  411. package/src/memory/v3/prompt-context.ts +33 -0
  412. package/src/memory/v3/prompts/consolidation.ts +458 -0
  413. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  414. package/src/memory/v3/retriever.ts +33 -0
  415. package/src/memory/v3/scouts.ts +420 -0
  416. package/src/memory/v3/shadow-middleware.ts +305 -0
  417. package/src/memory/v3/traversal.ts +206 -0
  418. package/src/memory/v3/tree-index.ts +237 -0
  419. package/src/memory/v3/tree-store.ts +394 -0
  420. package/src/memory/v3/tree-walk.ts +351 -0
  421. package/src/memory/v3/types.ts +65 -0
  422. package/src/memory/v3/validate.ts +300 -0
  423. package/src/messaging/providers/index.ts +7 -1
  424. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
  425. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
  426. package/src/messaging/providers/slack/adapter.ts +178 -25
  427. package/src/messaging/providers/slack/api.test.ts +54 -0
  428. package/src/messaging/providers/slack/api.ts +119 -3
  429. package/src/messaging/providers/slack/client.ts +12 -0
  430. package/src/messaging/providers/slack/deep-link.ts +20 -1
  431. package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
  432. package/src/messaging/providers/slack/message-metadata.ts +156 -0
  433. package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
  434. package/src/messaging/providers/slack/render-transcript.ts +176 -49
  435. package/src/messaging/providers/slack/send.test.ts +77 -0
  436. package/src/messaging/providers/slack/send.ts +8 -2
  437. package/src/messaging/providers/slack/types.ts +14 -0
  438. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
  439. package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
  440. package/src/notifications/adapters/macos.ts +18 -1
  441. package/src/notifications/adapters/platform.ts +1 -1
  442. package/src/notifications/conversation-seed-composer.ts +14 -2
  443. package/src/notifications/decision-engine.ts +1 -4
  444. package/src/notifications/deferred-emit.ts +135 -0
  445. package/src/notifications/emit-signal.ts +38 -50
  446. package/src/notifications/home-feed-side-effect.ts +60 -30
  447. package/src/oauth/connect-orchestrator.ts +3 -0
  448. package/src/oauth/credential-token-resolver.ts +2 -0
  449. package/src/oauth/manual-token-connection.ts +19 -0
  450. package/src/oauth/oauth-store.ts +12 -0
  451. package/src/oauth/seed-providers.ts +22 -0
  452. package/src/permissions/prompter.ts +8 -5
  453. package/src/permissions/question-prompter.ts +5 -2
  454. package/src/permissions/secret-prompter.ts +6 -3
  455. package/src/plugin-api/index.ts +4 -0
  456. package/src/plugin-api/types.ts +7 -33
  457. package/src/plugins/defaults/index.ts +6 -0
  458. package/src/plugins/defaults/injectors.ts +100 -20
  459. package/src/plugins/external-plugin-loader.ts +5 -68
  460. package/src/plugins/types.ts +11 -16
  461. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  462. package/src/prompts/__tests__/system-prompt.test.ts +46 -2
  463. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  464. package/src/prompts/normalize-onboarding.ts +40 -0
  465. package/src/prompts/persona-resolver.ts +36 -21
  466. package/src/prompts/sections.ts +69 -19
  467. package/src/prompts/system-prompt.ts +118 -216
  468. package/src/prompts/template-detection.ts +37 -0
  469. package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
  470. package/src/prompts/templates/BOOTSTRAP.md +10 -2
  471. package/src/prompts/templates/VOICE.md +3 -0
  472. package/src/prompts/templates/system-sections.ts +281 -9
  473. package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
  474. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  475. package/src/providers/anthropic/client.ts +159 -66
  476. package/src/providers/call-site-routing.ts +14 -2
  477. package/src/providers/connection-model-compat.ts +38 -0
  478. package/src/providers/connection-resolution.ts +16 -2
  479. package/src/providers/fireworks/client.ts +20 -2
  480. package/src/providers/gemini/client.ts +49 -6
  481. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
  482. package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
  483. package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
  484. package/src/providers/inference/adapter-factory.ts +18 -1
  485. package/src/providers/inference/auth.ts +3 -3
  486. package/src/providers/inference/codex-token-refresh.ts +128 -0
  487. package/src/providers/inference/resolve-auth.ts +49 -6
  488. package/src/providers/minimax/client.ts +106 -0
  489. package/src/providers/model-catalog.ts +91 -1
  490. package/src/providers/model-intents.ts +1 -1
  491. package/src/providers/openai/chat-completions-provider.ts +63 -23
  492. package/src/providers/openai/codex-models.ts +18 -0
  493. package/src/providers/openai/responses-provider.ts +86 -23
  494. package/src/providers/openrouter/client.ts +5 -1
  495. package/src/providers/provider-send-message.ts +7 -1
  496. package/src/providers/retry.ts +34 -3
  497. package/src/providers/thinking-config.ts +26 -1
  498. package/src/providers/types.ts +25 -0
  499. package/src/providers/usage-tracking.ts +2 -0
  500. package/src/runtime/AGENTS.md +2 -2
  501. package/src/runtime/__tests__/agent-wake.test.ts +214 -0
  502. package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
  503. package/src/runtime/agent-wake.ts +152 -56
  504. package/src/runtime/assistant-event-hub.ts +76 -6
  505. package/src/runtime/auth/route-policy.ts +43 -3
  506. package/src/runtime/background-job-runner.ts +26 -0
  507. package/src/runtime/btw-sidechain.ts +0 -6
  508. package/src/runtime/channel-reply-delivery.ts +182 -47
  509. package/src/runtime/channel-retry-sweep.ts +141 -16
  510. package/src/runtime/http-types.ts +7 -6
  511. package/src/runtime/migrations/vbundle-builder.ts +10 -3
  512. package/src/runtime/pending-interactions.ts +50 -8
  513. package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
  514. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +161 -1
  515. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
  516. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +290 -0
  517. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  518. package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
  519. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
  520. package/src/runtime/routes/acp-routes.test.ts +255 -6
  521. package/src/runtime/routes/acp-routes.ts +8 -1
  522. package/src/runtime/routes/approval-routes.ts +4 -1
  523. package/src/runtime/routes/avatar-routes.ts +10 -10
  524. package/src/runtime/routes/background-wake-routes.ts +188 -0
  525. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  526. package/src/runtime/routes/btw-routes.ts +0 -6
  527. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
  528. package/src/runtime/routes/content-source-routes.ts +78 -0
  529. package/src/runtime/routes/conversation-cli-routes.ts +147 -2
  530. package/src/runtime/routes/conversation-list-routes.ts +12 -4
  531. package/src/runtime/routes/conversation-management-routes.ts +77 -20
  532. package/src/runtime/routes/conversation-query-routes.ts +196 -31
  533. package/src/runtime/routes/conversation-routes.ts +472 -425
  534. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  535. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  536. package/src/runtime/routes/document-comments-routes.ts +287 -0
  537. package/src/runtime/routes/documents-routes.ts +33 -0
  538. package/src/runtime/routes/domain-routes.ts +60 -10
  539. package/src/runtime/routes/email-routes.ts +5 -2
  540. package/src/runtime/routes/events-routes.ts +54 -10
  541. package/src/runtime/routes/group-routes.ts +24 -8
  542. package/src/runtime/routes/home-feed-routes.ts +6 -3
  543. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  544. package/src/runtime/routes/host-browser-routes.ts +17 -2
  545. package/src/runtime/routes/host-cu-routes.ts +2 -2
  546. package/src/runtime/routes/identity-routes.ts +21 -0
  547. package/src/runtime/routes/inbound-message-handler.ts +288 -58
  548. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  549. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
  550. package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
  551. package/src/runtime/routes/index.ts +20 -4
  552. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  553. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  554. package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
  555. package/src/runtime/routes/integrations/a2a.ts +60 -1
  556. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  557. package/src/runtime/routes/log-export-routes.ts +39 -0
  558. package/src/runtime/routes/memory-item-routes.ts +8 -3
  559. package/src/runtime/routes/memory-v2-routes.ts +427 -0
  560. package/src/runtime/routes/memory-v3-routes.ts +316 -0
  561. package/src/runtime/routes/migration-routes.ts +21 -24
  562. package/src/runtime/routes/notification-routes.ts +19 -2
  563. package/src/runtime/routes/plugins-routes.ts +337 -0
  564. package/src/runtime/routes/question-routes.ts +4 -1
  565. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  566. package/src/runtime/routes/sanity-routes.ts +159 -0
  567. package/src/runtime/routes/secret-routes.ts +25 -5
  568. package/src/runtime/routes/settings-routes.ts +12 -11
  569. package/src/runtime/routes/slack-channel-routes.ts +188 -0
  570. package/src/runtime/routes/workspace-routes.ts +25 -10
  571. package/src/runtime/services/conversation-serializer.ts +30 -4
  572. package/src/runtime/sync/resource-sync-events.ts +106 -38
  573. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  574. package/src/runtime/sync/sync-publisher.ts +2 -1
  575. package/src/runtime/verification-outbound-actions.ts +73 -1
  576. package/src/schedule/integration-status.ts +3 -1
  577. package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
  578. package/src/security/oauth2-device-code.ts +307 -0
  579. package/src/security/oauth2.ts +26 -9
  580. package/src/security/secure-keys.ts +5 -0
  581. package/src/skills/catalog-install.ts +6 -2
  582. package/src/telemetry/types.ts +12 -0
  583. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  584. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  585. package/src/tools/acp/spawn.test.ts +119 -0
  586. package/src/tools/acp/spawn.ts +15 -2
  587. package/src/tools/apps/definitions.ts +2 -8
  588. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  589. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  590. package/src/tools/browser/__tests__/pinned-tabs.test.ts +150 -0
  591. package/src/tools/browser/browser-execution.ts +106 -0
  592. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  593. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
  594. package/src/tools/browser/cdp-client/__tests__/types.test.ts +4 -0
  595. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +22 -0
  596. package/src/tools/browser/cdp-client/extension-cdp-client.ts +42 -2
  597. package/src/tools/browser/cdp-client/factory.ts +171 -4
  598. package/src/tools/browser/cdp-client/local-cdp-client.ts +21 -0
  599. package/src/tools/browser/cdp-client/types.ts +101 -0
  600. package/src/tools/browser/pinned-tabs.ts +146 -0
  601. package/src/tools/computer-use/definitions.ts +22 -78
  602. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  603. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  604. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  605. package/src/tools/credentials/vault.ts +3 -9
  606. package/src/tools/document/document-comment-tool.test.ts +379 -0
  607. package/src/tools/document/document-comment-tool.ts +156 -0
  608. package/src/tools/document/document-tool.ts +187 -2
  609. package/src/tools/execution-target.ts +21 -23
  610. package/src/tools/executor.ts +6 -1
  611. package/src/tools/filesystem/edit.ts +3 -9
  612. package/src/tools/filesystem/list.ts +3 -9
  613. package/src/tools/filesystem/read.ts +3 -9
  614. package/src/tools/filesystem/write.ts +3 -9
  615. package/src/tools/host-filesystem/edit.ts +3 -9
  616. package/src/tools/host-filesystem/read.ts +3 -9
  617. package/src/tools/host-filesystem/transfer.ts +3 -9
  618. package/src/tools/host-filesystem/write.ts +3 -9
  619. package/src/tools/host-terminal/host-shell.ts +3 -9
  620. package/src/tools/mcp/mcp-tool-factory.ts +1 -8
  621. package/src/tools/memory/register.test.ts +1 -1
  622. package/src/tools/memory/register.ts +4 -9
  623. package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
  624. package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
  625. package/src/tools/network/domain-normalize.ts +17 -0
  626. package/src/tools/network/web-fetch.ts +216 -73
  627. package/src/tools/network/web-search.ts +216 -98
  628. package/src/tools/registry.ts +7 -23
  629. package/src/tools/schema-transforms.ts +1 -1
  630. package/src/tools/skills/execute.ts +3 -9
  631. package/src/tools/skills/load.ts +3 -9
  632. package/src/tools/skills/skill-tool-factory.ts +1 -8
  633. package/src/tools/subagent/notify-parent.ts +3 -9
  634. package/src/tools/system/request-permission.ts +3 -9
  635. package/src/tools/terminal/safe-env.ts +3 -2
  636. package/src/tools/terminal/shell.ts +3 -9
  637. package/src/tools/tool-approval-handler.ts +19 -12
  638. package/src/tools/tool-defaults.ts +94 -0
  639. package/src/tools/types.ts +31 -98
  640. package/src/tools/ui-surface/definitions.ts +9 -23
  641. package/src/types/onboarding-context.ts +4 -0
  642. package/src/usage/pricing.ts +23 -0
  643. package/src/usage/types.ts +12 -0
  644. package/src/util/__tests__/favicon.test.ts +84 -0
  645. package/src/util/favicon.ts +40 -0
  646. package/src/util/logger.ts +16 -7
  647. package/src/util/platform.ts +7 -7
  648. package/src/util/sqlite3-runtime.ts +65 -0
  649. package/src/workspace/git-service.ts +75 -4
  650. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  651. package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
  652. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  653. package/src/workspace/migrations/registry.ts +4 -0
  654. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  655. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  656. package/src/config/bundled-skills/document/SKILL.md +0 -54
  657. package/src/config/bundled-skills/document/TOOLS.json +0 -106
  658. package/src/daemon/seed-files.ts +0 -18
  659. package/src/prompts/cache-boundary.ts +0 -8
  660. package/src/runtime/routes/interface-routes.ts +0 -43
  661. /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
  662. /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
  663. /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
  664. /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
  665. /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
@@ -0,0 +1,337 @@
1
+ /**
2
+ * Route handlers for the assistant plugins surface.
3
+ *
4
+ * GET /v1/plugins — list installed plugins under `<workspaceDir>/plugins/`.
5
+ * GET /v1/plugins/search — search the canonical GitHub catalog of installable plugins.
6
+ * DELETE /v1/plugins/:name — uninstall a plugin from `<workspaceDir>/plugins/<name>/`.
7
+ *
8
+ * The read-only routes are projections over the same library functions
9
+ * the CLI uses (`assistant plugins list`, `assistant plugins search`).
10
+ * The DELETE route is symmetric to `assistant plugins uninstall` and
11
+ * delegates to the same `uninstallPlugin` lib function. CLI / daemon /
12
+ * web stay aligned on what an installed or available plugin looks like.
13
+ *
14
+ * Install is intentionally not exposed here. The CLI remains the
15
+ * install surface because installation fetches from GitHub, applies
16
+ * sanitization, and writes to disk — a heavier flow than a single
17
+ * JSON request justifies right now.
18
+ *
19
+ * # Policy gating
20
+ *
21
+ * Every route declares `policyKey: "plugins"` + `requirePolicyEnforcement:
22
+ * true`. The HTTP router enforces via `enforcePolicy()` against the
23
+ * `plugins:GET` / `plugins/search:GET` / `plugins:DELETE` registry
24
+ * entries in `runtime/auth/route-policy.ts`. The IPC adapter exposes
25
+ * the same policies to the gateway IPC proxy, whose own policy table
26
+ * (`gateway/src/auth/ipc-route-policy.ts`) holds the matching entries
27
+ * for `plugins_list` / `plugins_search` / `plugins_uninstall`. Reads
28
+ * require `settings.read`; uninstall requires `settings.write`.
29
+ */
30
+
31
+ import { z } from "zod";
32
+
33
+ import { InvalidPluginNameError } from "../../cli/lib/install-from-github.js";
34
+ import {
35
+ type InstalledPluginInfo,
36
+ listInstalledPlugins,
37
+ } from "../../cli/lib/list-installed-plugins.js";
38
+ import {
39
+ InvalidSearchPatternError,
40
+ type PluginSearchMatch,
41
+ searchPlugins,
42
+ } from "../../cli/lib/search-plugins.js";
43
+ import {
44
+ PluginNotInstalledError,
45
+ uninstallPlugin,
46
+ } from "../../cli/lib/uninstall-plugin.js";
47
+ import {
48
+ BadRequestError,
49
+ InternalError,
50
+ NotFoundError,
51
+ } from "./errors.js";
52
+ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
53
+
54
+ // ---------------------------------------------------------------------------
55
+ // Schema
56
+ // ---------------------------------------------------------------------------
57
+
58
+ const pluginInfoSchema = z.object({
59
+ id: z
60
+ .string()
61
+ .describe(
62
+ "Plugin's directory name (kebab-case). Matches `assistant plugins install <id>`.",
63
+ ),
64
+ name: z.string().describe("Display name. Equal to `id` today."),
65
+ description: z
66
+ .string()
67
+ .nullable()
68
+ .describe("From `package.json#description`; `null` when unknown."),
69
+ version: z
70
+ .string()
71
+ .nullable()
72
+ .describe("From `package.json#version`; `null` when unknown."),
73
+ path: z
74
+ .string()
75
+ .optional()
76
+ .describe("Absolute path to the plugin directory on the assistant host."),
77
+ issues: z
78
+ .array(z.string())
79
+ .optional()
80
+ .describe(
81
+ "Non-fatal issues with this entry (missing `package.json`, malformed JSON, ...). Omitted when clean.",
82
+ ),
83
+ });
84
+
85
+ const pluginsListResponseSchema = z.object({
86
+ plugins: z.array(pluginInfoSchema),
87
+ });
88
+
89
+ const pluginSearchMatchSchema = z.object({
90
+ name: z
91
+ .string()
92
+ .describe(
93
+ "Directory name under `experimental/plugins/`. Matches `assistant plugins install <name>`.",
94
+ ),
95
+ path: z
96
+ .string()
97
+ .describe(
98
+ "Repo-relative path of the match (e.g. `experimental/plugins/<name>`).",
99
+ ),
100
+ });
101
+
102
+ const pluginsSearchResponseSchema = z.object({
103
+ query: z
104
+ .string()
105
+ .describe("Echo of the requested query (ECMAScript regex source)."),
106
+ ref: z.string().describe("Git ref the catalog was listed at."),
107
+ matches: z
108
+ .array(pluginSearchMatchSchema)
109
+ .describe("Directory matches, sorted alphabetically by name."),
110
+ });
111
+
112
+ const pluginUninstallResponseSchema = z.object({
113
+ name: z
114
+ .string()
115
+ .describe(
116
+ "Directory name that was removed. Echoes the request's `:name` path parameter after sanitization.",
117
+ ),
118
+ target: z
119
+ .string()
120
+ .describe(
121
+ "Absolute path that was removed on the assistant host. Useful for audit logs and confirmation toasts.",
122
+ ),
123
+ });
124
+
125
+ // ---------------------------------------------------------------------------
126
+ // Helpers
127
+ // ---------------------------------------------------------------------------
128
+
129
+ interface PluginView {
130
+ id: string;
131
+ name: string;
132
+ description: string | null;
133
+ version: string | null;
134
+ path: string;
135
+ issues?: string[];
136
+ }
137
+
138
+ function projectPlugin(entry: InstalledPluginInfo): PluginView {
139
+ // `id` and `name` both track the directory name. `package.json#name` can
140
+ // be scoped (e.g. `@vendor/plugin-name`) which is fine for npm but not
141
+ // what the CLI uses to install — so we don't surface it as `name`.
142
+ const view: PluginView = {
143
+ id: entry.name,
144
+ name: entry.name,
145
+ description: entry.packageJson?.description ?? null,
146
+ version: entry.packageJson?.version ?? null,
147
+ path: entry.target,
148
+ };
149
+ if (entry.issues.length > 0) {
150
+ view.issues = [...entry.issues];
151
+ }
152
+ return view;
153
+ }
154
+
155
+ function matchesQuery(plugin: PluginView, needle: string): boolean {
156
+ const q = needle.toLowerCase();
157
+ if (plugin.id.toLowerCase().includes(q)) return true;
158
+ if (plugin.name.toLowerCase().includes(q)) return true;
159
+ if (plugin.description && plugin.description.toLowerCase().includes(q)) {
160
+ return true;
161
+ }
162
+ return false;
163
+ }
164
+
165
+ // ---------------------------------------------------------------------------
166
+ // Handler — list installed
167
+ // ---------------------------------------------------------------------------
168
+
169
+ function handleListPlugins({
170
+ queryParams = {},
171
+ }: RouteHandlerArgs): { plugins: PluginView[] } {
172
+ const q = queryParams.q?.trim();
173
+ const installed = listInstalledPlugins();
174
+ const projected = installed.map(projectPlugin);
175
+ const filtered = q ? projected.filter((p) => matchesQuery(p, q)) : projected;
176
+ return { plugins: filtered };
177
+ }
178
+
179
+ // ---------------------------------------------------------------------------
180
+ // Handler — search catalog
181
+ // ---------------------------------------------------------------------------
182
+
183
+ interface PluginsSearchResponse {
184
+ query: string;
185
+ ref: string;
186
+ matches: PluginSearchMatch[];
187
+ }
188
+
189
+ async function handleSearchPlugins({
190
+ queryParams = {},
191
+ }: RouteHandlerArgs): Promise<PluginsSearchResponse> {
192
+ // Empty string is a legitimate "match everything" query per the lib's
193
+ // contract — accept it without forcing the caller to pick a sentinel.
194
+ const query = queryParams.q ?? "";
195
+ const ref = queryParams.ref?.trim() || undefined;
196
+
197
+ try {
198
+ const result = await searchPlugins(
199
+ { query, ref },
200
+ { fetch: globalThis.fetch.bind(globalThis) },
201
+ );
202
+ // Re-pack `readonly` lib types into mutable copies so the route
203
+ // serializer's `Record<string, unknown>` contract holds. The wire
204
+ // shape is identical.
205
+ return {
206
+ query: result.query,
207
+ ref: result.ref,
208
+ matches: result.matches.map((m) => ({ name: m.name, path: m.path })),
209
+ };
210
+ } catch (err) {
211
+ if (err instanceof InvalidSearchPatternError) {
212
+ throw new BadRequestError(err.message);
213
+ }
214
+ throw new InternalError(
215
+ err instanceof Error ? err.message : "plugin catalog search failed",
216
+ );
217
+ }
218
+ }
219
+
220
+ // ---------------------------------------------------------------------------
221
+ // Handler — uninstall
222
+ // ---------------------------------------------------------------------------
223
+
224
+ interface PluginUninstallResponse {
225
+ name: string;
226
+ target: string;
227
+ }
228
+
229
+ function handleUninstallPlugin({
230
+ pathParams = {},
231
+ }: RouteHandlerArgs): PluginUninstallResponse {
232
+ // The HTTP router has already URL-decoded `:name` for us; pass it
233
+ // through verbatim — `uninstallPlugin` runs the same
234
+ // `sanitizePluginName` check the CLI uses, so attacker-supplied
235
+ // `../escape` style names get rejected before `rmSync` is reached.
236
+ const rawName = pathParams.name ?? "";
237
+
238
+ try {
239
+ const result = uninstallPlugin({ name: rawName });
240
+ return { name: result.name, target: result.target };
241
+ } catch (err) {
242
+ if (err instanceof InvalidPluginNameError) {
243
+ throw new BadRequestError(err.message);
244
+ }
245
+ if (err instanceof PluginNotInstalledError) {
246
+ throw new NotFoundError(err.message);
247
+ }
248
+ throw new InternalError(
249
+ err instanceof Error ? err.message : "plugin uninstall failed",
250
+ );
251
+ }
252
+ }
253
+
254
+ // ---------------------------------------------------------------------------
255
+ // Route definitions
256
+ // ---------------------------------------------------------------------------
257
+
258
+ export const ROUTES: RouteDefinition[] = [
259
+ {
260
+ operationId: "plugins_list",
261
+ endpoint: "plugins",
262
+ method: "GET",
263
+ policyKey: "plugins",
264
+ requirePolicyEnforcement: true,
265
+ summary: "List installed plugins",
266
+ description:
267
+ "Return one entry per directory under `<workspaceDir>/plugins/`, sorted alphabetically. Matches the CLI's `assistant plugins list`. Supports `?q=<text>` for case-insensitive substring matching across plugin id, name, and description.",
268
+ tags: ["plugins"],
269
+ queryParams: [
270
+ {
271
+ name: "q",
272
+ schema: { type: "string" },
273
+ description:
274
+ "Optional substring filter applied to plugin id, name, and description.",
275
+ },
276
+ ],
277
+ responseBody: pluginsListResponseSchema,
278
+ handler: handleListPlugins,
279
+ },
280
+ {
281
+ operationId: "plugins_search",
282
+ endpoint: "plugins/search",
283
+ method: "GET",
284
+ policyKey: "plugins",
285
+ requirePolicyEnforcement: true,
286
+ summary: "Search the plugin catalog",
287
+ description:
288
+ "List installable plugins from the canonical `vellum-ai/vellum-assistant` catalog at `experimental/plugins/`. The query is an ECMAScript regex matched case-insensitively against the directory name (e.g. `memory`, `^simple`). Empty query returns every entry. Mirrors the CLI's `assistant plugins search`.",
289
+ tags: ["plugins"],
290
+ queryParams: [
291
+ {
292
+ name: "q",
293
+ schema: { type: "string" },
294
+ description:
295
+ "ECMAScript regex pattern matched case-insensitively against catalog directory names. Empty/missing matches everything.",
296
+ },
297
+ {
298
+ name: "ref",
299
+ schema: { type: "string" },
300
+ description:
301
+ "Optional git ref to list the catalog at. Defaults to the CLI's `DEFAULT_PLUGIN_REF` (typically `main`).",
302
+ },
303
+ ],
304
+ responseBody: pluginsSearchResponseSchema,
305
+ handler: handleSearchPlugins,
306
+ },
307
+ {
308
+ operationId: "plugins_uninstall",
309
+ endpoint: "plugins/:name",
310
+ method: "DELETE",
311
+ policyKey: "plugins",
312
+ requirePolicyEnforcement: true,
313
+ summary: "Uninstall a plugin",
314
+ description:
315
+ "Remove the directory at `<workspaceDir>/plugins/<name>/`. Mirrors the CLI's `assistant plugins uninstall <name>` (without the interactive confirmation — the API caller is responsible for any prompt). The plugin name is sanitized by the same regex the CLI uses; `../escape`-style values, hidden names, and absolute paths return 400. Missing plugins return 404. The assistant must be restarted to drop the plugin from the running runtime.",
316
+ tags: ["plugins"],
317
+ pathParams: [
318
+ {
319
+ name: "name",
320
+ type: "string",
321
+ description:
322
+ "Directory name under `<workspaceDir>/plugins/`. Must match the kebab-case name accepted by `assistant plugins install`.",
323
+ },
324
+ ],
325
+ responseBody: pluginUninstallResponseSchema,
326
+ additionalResponses: {
327
+ "400": {
328
+ description:
329
+ "The plugin name failed sanitization (e.g. contained slashes, dots, or uppercase letters).",
330
+ },
331
+ "404": {
332
+ description: "No plugin directory exists with the given name.",
333
+ },
334
+ },
335
+ handler: handleUninstallPlugin,
336
+ },
337
+ ];
@@ -148,7 +148,10 @@ function handleQuestionResponse({ body }: RouteHandlerArgs) {
148
148
 
149
149
  // Validation passed — deregister now to clear the prompter timer, then
150
150
  // hand the result to the prompter's caller via rpcResolve.
151
- pendingInteractions.resolve(requestId);
151
+ pendingInteractions.resolve(
152
+ requestId,
153
+ response.kind === "close" ? "cancelled" : "answered",
154
+ );
152
155
 
153
156
  log.info(
154
157
  {
@@ -31,7 +31,7 @@ export const ROUTES: RouteDefinition[] = [
31
31
  description: "Update the display title of a conversation.",
32
32
  tags: ["conversations"],
33
33
  requestBody: RenameConversationBody,
34
- handler: ({ body }) => {
34
+ handler: ({ body, headers }) => {
35
35
  const parsed = RenameConversationBody.safeParse(body);
36
36
  if (!parsed.success) {
37
37
  throw new BadRequestError("conversationId and title are required");
@@ -46,7 +46,11 @@ export const ROUTES: RouteDefinition[] = [
46
46
 
47
47
  updateConversationTitle(conversationId, title, 0);
48
48
 
49
- publishConversationTitleChanged(conversationId, title);
49
+ publishConversationTitleChanged(
50
+ conversationId,
51
+ title,
52
+ headers?.["x-vellum-client-id"]?.trim() || undefined,
53
+ );
50
54
 
51
55
  return { ok: true };
52
56
  },
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Route definitions for Sanity CMS connection management.
3
+ *
4
+ * POST /v1/sanity/discover — project/dataset discovery using the stored API token
5
+ * POST /v1/sanity/connect — finalise connection by writing the sidecar file
6
+ *
7
+ * Both routes use policyKey: "secrets" — they read credentials and write
8
+ * workspace data, the same policy tier as the existing secrets routes.
9
+ */
10
+
11
+ import { mkdirSync, writeFileSync } from "node:fs";
12
+ import { dirname, join } from "node:path";
13
+
14
+ import { z } from "zod";
15
+
16
+ import { credentialKey } from "../../security/credential-key.js";
17
+ import { getSecureKeyAsync } from "../../security/secure-keys.js";
18
+ import { getWorkspaceDir } from "../../util/platform.js";
19
+ import { BadRequestError } from "./errors.js";
20
+ import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // Helpers
24
+ // ---------------------------------------------------------------------------
25
+
26
+ async function getStoredToken(): Promise<string | undefined> {
27
+ return getSecureKeyAsync(credentialKey("sanity", "api_token"));
28
+ }
29
+
30
+ function writeSidecar(relPath: string, data: Record<string, unknown>): void {
31
+ const workspaceDir = getWorkspaceDir();
32
+ const absPath = join(workspaceDir, relPath);
33
+ mkdirSync(dirname(absPath), { recursive: true });
34
+ writeFileSync(absPath, JSON.stringify(data, null, 2), "utf-8");
35
+ }
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // POST /v1/sanity/discover
39
+ // ---------------------------------------------------------------------------
40
+
41
+ async function handleDiscover(
42
+ args: RouteHandlerArgs,
43
+ ): Promise<Record<string, unknown>> {
44
+ const token = await getStoredToken();
45
+ if (!token) {
46
+ return { error: "no_token" };
47
+ }
48
+
49
+ const projectId =
50
+ typeof args.body?.projectId === "string" ? args.body.projectId : undefined;
51
+
52
+ if (!projectId) {
53
+ // List all projects this token has access to
54
+ const response = await fetch("https://api.sanity.io/v2021-06-07/projects", {
55
+ headers: { Authorization: `Bearer ${token}` },
56
+ });
57
+
58
+ if (response.status === 401 || response.status === 403) {
59
+ return { error: "token_scope_limited" };
60
+ }
61
+
62
+ if (!response.ok) {
63
+ return { error: "discovery_failed" };
64
+ }
65
+
66
+ const raw = (await response.json()) as Array<{
67
+ id: string;
68
+ displayName?: string;
69
+ }>;
70
+ const projects = raw.map((p) => ({
71
+ id: p.id,
72
+ displayName: p.displayName ?? p.id,
73
+ }));
74
+ return { projects };
75
+ }
76
+
77
+ // List datasets for a specific project
78
+ const response = await fetch(
79
+ `https://api.sanity.io/v2021-06-07/projects/${projectId}/datasets`,
80
+ {
81
+ headers: { Authorization: `Bearer ${token}` },
82
+ },
83
+ );
84
+
85
+ if (response.status === 401 || response.status === 403) {
86
+ return { error: "token_scope_limited" };
87
+ }
88
+
89
+ if (!response.ok) {
90
+ return { error: "discovery_failed" };
91
+ }
92
+
93
+ const raw = (await response.json()) as Array<{ name: string }>;
94
+ const datasets = raw.map((d) => d.name);
95
+ return { projectId, datasets };
96
+ }
97
+
98
+ // ---------------------------------------------------------------------------
99
+ // POST /v1/sanity/connect
100
+ // ---------------------------------------------------------------------------
101
+
102
+ async function handleConnect(
103
+ args: RouteHandlerArgs,
104
+ ): Promise<Record<string, unknown>> {
105
+ const token = await getStoredToken();
106
+ if (!token) {
107
+ throw new BadRequestError(
108
+ "Sanity API token not found. Store it first via POST /v1/secrets.",
109
+ );
110
+ }
111
+
112
+ const projectId =
113
+ typeof args.body?.projectId === "string" ? args.body.projectId.trim() : "";
114
+ const dataset =
115
+ typeof args.body?.dataset === "string" ? args.body.dataset.trim() : "";
116
+
117
+ if (!projectId) {
118
+ throw new BadRequestError(
119
+ "projectId is required and must be a non-empty string",
120
+ );
121
+ }
122
+ if (!dataset) {
123
+ throw new BadRequestError(
124
+ "dataset is required and must be a non-empty string",
125
+ );
126
+ }
127
+
128
+ writeSidecar("data/sanity-connection.json", { projectId, dataset });
129
+
130
+ return { ok: true };
131
+ }
132
+
133
+ // ---------------------------------------------------------------------------
134
+ // Route definitions
135
+ // ---------------------------------------------------------------------------
136
+
137
+ export const ROUTES: RouteDefinition[] = [
138
+ {
139
+ operationId: "sanity_discover",
140
+ endpoint: "sanity/discover",
141
+ method: "POST",
142
+ policyKey: "secrets",
143
+ summary: "Discover Sanity projects and datasets using the stored API token",
144
+ requestBody: z.object({ projectId: z.string().optional() }).optional(),
145
+ handler: handleDiscover,
146
+ },
147
+ {
148
+ operationId: "sanity_connect",
149
+ endpoint: "sanity/connect",
150
+ method: "POST",
151
+ policyKey: "secrets",
152
+ summary: "Finalise Sanity connection and write sidecar file",
153
+ requestBody: z.object({
154
+ projectId: z.string(),
155
+ dataset: z.string(),
156
+ }),
157
+ handler: handleConnect,
158
+ },
159
+ ];
@@ -27,6 +27,7 @@ import { clearEmbeddingBackendCache } from "../../memory/embedding-backend.js";
27
27
  import { syncManualTokenConnection } from "../../oauth/manual-token-connection.js";
28
28
  import { validateAnthropicApiKey } from "../../providers/anthropic/client.js";
29
29
  import { validateGeminiApiKey } from "../../providers/gemini/client.js";
30
+ import { validateMinimaxApiKey } from "../../providers/minimax/client.js";
30
31
  import { validateOpenAIApiKey } from "../../providers/openai/client.js";
31
32
  import { initializeProviders } from "../../providers/registry.js";
32
33
  import { credentialKey } from "../../security/credential-key.js";
@@ -195,9 +196,21 @@ async function handleAddSecret({ body }: RouteHandlerArgs) {
195
196
  );
196
197
  return { success: false, error: validation.reason };
197
198
  }
199
+ } else if (name === "minimax") {
200
+ const validation = await validateMinimaxApiKey(value);
201
+ if (!validation.valid) {
202
+ log.warn(
203
+ { provider: name, reason: validation.reason },
204
+ "API key validation failed",
205
+ );
206
+ return { success: false, error: validation.reason };
207
+ }
198
208
  }
199
209
 
200
- const stored = await setSecureKeyAsync(credentialKey(name, "api_key"), value);
210
+ const stored = await setSecureKeyAsync(
211
+ credentialKey(name, "api_key"),
212
+ value,
213
+ );
201
214
  if (!stored) {
202
215
  throw new InternalError(
203
216
  `Failed to store API key in secure storage (backend: ${getActiveBackendName()})`,
@@ -339,7 +352,9 @@ async function handleReadSecret({ body }: RouteHandlerArgs) {
339
352
 
340
353
  try {
341
354
  let accountKey: string;
342
- let prefetchedResult: Awaited<ReturnType<typeof getSecureKeyResultAsync>> | undefined;
355
+ let prefetchedResult:
356
+ | Awaited<ReturnType<typeof getSecureKeyResultAsync>>
357
+ | undefined;
343
358
 
344
359
  if (type === "api_key") {
345
360
  if (
@@ -350,7 +365,9 @@ async function handleReadSecret({ body }: RouteHandlerArgs) {
350
365
  );
351
366
  }
352
367
  // Check credential namespace first; fall back to bare key only if not found and store is reachable.
353
- const credResult = await getSecureKeyResultAsync(credentialKey(name, "api_key"));
368
+ const credResult = await getSecureKeyResultAsync(
369
+ credentialKey(name, "api_key"),
370
+ );
354
371
  if (credResult.value === undefined && !credResult.unreachable) {
355
372
  accountKey = name;
356
373
  } else {
@@ -373,7 +390,8 @@ async function handleReadSecret({ body }: RouteHandlerArgs) {
373
390
  );
374
391
  }
375
392
 
376
- const { value, unreachable } = prefetchedResult ?? await getSecureKeyResultAsync(accountKey);
393
+ const { value, unreachable } =
394
+ prefetchedResult ?? (await getSecureKeyResultAsync(accountKey));
377
395
  if (value === undefined) {
378
396
  return { found: false, unreachable };
379
397
  }
@@ -543,7 +561,9 @@ async function handleListSecrets() {
543
561
  const field = rest.slice(slashIdx + 1);
544
562
  if (
545
563
  field === "api_key" &&
546
- API_KEY_PROVIDERS.includes(service as (typeof API_KEY_PROVIDERS)[number])
564
+ API_KEY_PROVIDERS.includes(
565
+ service as (typeof API_KEY_PROVIDERS)[number],
566
+ )
547
567
  ) {
548
568
  return [service];
549
569
  }
@@ -78,7 +78,10 @@ function handleVoiceConfigUpdate({ body = {} }: RouteHandlerArgs) {
78
78
  // Avatar generation
79
79
  // ---------------------------------------------------------------------------
80
80
 
81
- async function handleGenerateAvatar({ body = {} }: RouteHandlerArgs) {
81
+ async function handleGenerateAvatar({
82
+ body = {},
83
+ headers,
84
+ }: RouteHandlerArgs) {
82
85
  const { description } = body as { description?: string };
83
86
  if (!description?.trim()) {
84
87
  throw new BadRequestError("Description is required.");
@@ -95,7 +98,7 @@ async function handleGenerateAvatar({ body = {} }: RouteHandlerArgs) {
95
98
 
96
99
  const avatarPath = getAvatarImagePath();
97
100
 
98
- publishAvatarChanged();
101
+ publishAvatarChanged(headers?.["x-vellum-client-id"]?.trim() || undefined);
99
102
 
100
103
  return { ok: true, avatarPath };
101
104
  } catch (err) {
@@ -381,14 +384,7 @@ function handleToolNamesList() {
381
384
  };
382
385
  const schemas: Record<string, SchemaShape> = {};
383
386
 
384
- const rawDefs: ToolDefinition[] = [];
385
- for (const tool of tools) {
386
- try {
387
- rawDefs.push(tool.getDefinition());
388
- } catch {
389
- // Skip tools whose definitions can't be resolved
390
- }
391
- }
387
+ const rawDefs: ToolDefinition[] = tools;
392
388
 
393
389
  const transformedDefs = injectActivityField(rawDefs, ACTIVITY_SKIP_SET);
394
390
  for (const def of transformedDefs) {
@@ -444,7 +440,12 @@ async function handleToolPermissionSimulate({ body = {} }: RouteHandlerArgs) {
444
440
 
445
441
  try {
446
442
  const manifestOverride = resolveManifestOverride(toolName);
447
- const executionTarget = resolveExecutionTarget(toolName, manifestOverride);
443
+ // Permission Simulator path: registered tool wins, then explicit
444
+ // manifest override, then the standard inference rules.
445
+ const executionTarget =
446
+ getTool(toolName)?.executionTarget ??
447
+ manifestOverride?.execution_target ??
448
+ resolveExecutionTarget({ name: toolName });
448
449
  const executionContext =
449
450
  isInteractive === false ? "headless" : "conversation";
450
451
  const policyContext = { executionTarget, executionContext } as const;