@vellumai/assistant 0.8.4 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (438) hide show
  1. package/ARCHITECTURE.md +2 -2
  2. package/docs/browser-use-architecture-phase2.md +1 -1
  3. package/knip.json +2 -1
  4. package/openapi.yaml +809 -11
  5. package/package.json +1 -1
  6. package/src/__tests__/anthropic-provider.test.ts +34 -37
  7. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  8. package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
  9. package/src/__tests__/audit-log-rotation.test.ts +70 -16
  10. package/src/__tests__/background-workers-disk-pressure.test.ts +3 -3
  11. package/src/__tests__/btw-routes.test.ts +2 -3
  12. package/src/__tests__/call-controller.test.ts +0 -1
  13. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  14. package/src/__tests__/channel-guardian.test.ts +3 -3
  15. package/src/__tests__/checker.test.ts +6 -15
  16. package/src/__tests__/compaction-events.test.ts +1 -0
  17. package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
  18. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
  19. package/src/__tests__/computer-use-tools.test.ts +2 -4
  20. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  21. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
  22. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
  23. package/src/__tests__/conversation-agent-loop-overflow.test.ts +197 -2
  24. package/src/__tests__/conversation-agent-loop.test.ts +163 -122
  25. package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
  26. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  27. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  28. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  29. package/src/__tests__/conversation-error.test.ts +31 -0
  30. package/src/__tests__/conversation-fork-crud.test.ts +178 -15
  31. package/src/__tests__/conversation-lifecycle.test.ts +52 -11
  32. package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +13 -13
  33. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -0
  34. package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
  35. package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
  36. package/src/__tests__/conversation-skill-tools.test.ts +2 -5
  37. package/src/__tests__/conversation-store.test.ts +1 -1
  38. package/src/__tests__/conversation-sync-tags.test.ts +99 -32
  39. package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
  40. package/src/__tests__/conversation-workspace-injection.test.ts +1 -1
  41. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
  42. package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
  43. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  44. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  45. package/src/__tests__/credential-vault-unit.test.ts +2 -2
  46. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  47. package/src/__tests__/email-html-renderer.test.ts +12 -0
  48. package/src/__tests__/gateway-flag-listener.test.ts +237 -0
  49. package/src/__tests__/gemini-provider.test.ts +78 -0
  50. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  51. package/src/__tests__/guardian-outbound-http.test.ts +7 -5
  52. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  53. package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
  54. package/src/__tests__/heartbeat-service.test.ts +4 -0
  55. package/src/__tests__/host-shell-tool.test.ts +1 -1
  56. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  57. package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
  58. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  59. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  60. package/src/__tests__/llm-resolver.test.ts +77 -9
  61. package/src/__tests__/llm-usage-store.test.ts +66 -0
  62. package/src/__tests__/logger.test.ts +89 -0
  63. package/src/__tests__/mcp-abort-signal.test.ts +2 -2
  64. package/src/__tests__/media-generate-image.test.ts +31 -0
  65. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  66. package/src/__tests__/model-intents.test.ts +2 -4
  67. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  68. package/src/__tests__/onboarding-template-contract.test.ts +1 -1
  69. package/src/__tests__/openai-provider.test.ts +46 -0
  70. package/src/__tests__/openai-responses-provider.test.ts +114 -12
  71. package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
  72. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  73. package/src/__tests__/platform.test.ts +2 -2
  74. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  75. package/src/__tests__/plugin-bootstrap.test.ts +2 -2
  76. package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
  77. package/src/__tests__/plugin-types.test.ts +3 -2
  78. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  79. package/src/__tests__/pricing.test.ts +12 -0
  80. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  81. package/src/__tests__/registry.test.ts +2 -8
  82. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  83. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  84. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  85. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  86. package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
  87. package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
  88. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  89. package/src/__tests__/subagent-notify-parent.test.ts +1 -1
  90. package/src/__tests__/suggestion-routes.test.ts +1 -0
  91. package/src/__tests__/sync-message-contract.test.ts +59 -0
  92. package/src/__tests__/system-prompt.test.ts +145 -131
  93. package/src/__tests__/terminal-tools.test.ts +1 -1
  94. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  95. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  96. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  97. package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
  98. package/src/__tests__/tool-executor.test.ts +9 -62
  99. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  100. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  101. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  102. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  103. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  104. package/src/__tests__/usage-routes.test.ts +3 -0
  105. package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
  106. package/src/__tests__/workspace-git-service.test.ts +6 -5
  107. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  108. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  109. package/src/acp/prepare-agent-env.ts +78 -0
  110. package/src/acp/session-manager.ts +1 -1
  111. package/src/agent/loop.ts +8 -0
  112. package/src/api/README.md +5 -0
  113. package/src/api/index.ts +4 -0
  114. package/src/api/package.json +10 -0
  115. package/src/background-wake/background-wake-routes.test.ts +233 -0
  116. package/src/background-wake/runtime-registry.ts +24 -0
  117. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  118. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  119. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  120. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  121. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  122. package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
  123. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  124. package/src/cli/commands/browser.ts +247 -0
  125. package/src/cli/commands/domain.ts +91 -41
  126. package/src/cli/commands/inference.ts +93 -40
  127. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  128. package/src/cli/commands/memory-v2.ts +176 -1
  129. package/src/cli/commands/memory-v3-render.ts +344 -0
  130. package/src/cli/commands/memory-v3.ts +316 -0
  131. package/src/cli/program.ts +2 -0
  132. package/src/config/assistant-feature-flags.ts +21 -9
  133. package/src/config/bundled-skills/document-editor/SKILL.md +11 -2
  134. package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
  135. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  136. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  137. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  138. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  139. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  140. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  141. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  142. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  143. package/src/config/bundled-tool-registry.ts +2 -0
  144. package/src/config/call-site-defaults.ts +7 -6
  145. package/src/config/feature-flag-registry.json +16 -0
  146. package/src/config/schemas/__tests__/memory-v2.test.ts +213 -1
  147. package/src/config/schemas/call-site-catalog.ts +21 -7
  148. package/src/config/schemas/llm.ts +12 -1
  149. package/src/config/schemas/memory-v2.ts +246 -0
  150. package/src/config/schemas/memory.ts +2 -1
  151. package/src/context/compactor.ts +52 -0
  152. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  153. package/src/conversations/message-consolidation.ts +404 -0
  154. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
  155. package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
  156. package/src/daemon/conversation-agent-loop-handlers.ts +2 -13
  157. package/src/daemon/conversation-agent-loop.ts +126 -76
  158. package/src/daemon/conversation-error.ts +31 -1
  159. package/src/daemon/conversation-lifecycle.ts +27 -22
  160. package/src/daemon/conversation-runtime-assembly.ts +10 -9
  161. package/src/daemon/conversation-tool-setup.ts +63 -3
  162. package/src/daemon/conversation-usage.ts +2 -0
  163. package/src/daemon/conversation.ts +14 -29
  164. package/src/daemon/disk-pressure-guard.ts +14 -2
  165. package/src/daemon/handlers/config-model.test.ts +1 -0
  166. package/src/daemon/handlers/conversations.ts +11 -3
  167. package/src/daemon/host-browser-proxy.ts +5 -5
  168. package/src/daemon/host-cu-proxy.ts +4 -4
  169. package/src/daemon/host-file-proxy.ts +4 -4
  170. package/src/daemon/host-proxy-base.ts +4 -4
  171. package/src/daemon/host-transfer-proxy.ts +10 -10
  172. package/src/daemon/lifecycle.ts +23 -20
  173. package/src/daemon/meet-manifest-loader.ts +1 -7
  174. package/src/daemon/message-types/conversations.ts +6 -9
  175. package/src/daemon/message-types/home.ts +1 -13
  176. package/src/daemon/message-types/messages.ts +6 -14
  177. package/src/daemon/message-types/sync.ts +14 -0
  178. package/src/daemon/shutdown-handlers.ts +24 -5
  179. package/src/daemon/switch-inference-profile-tool.ts +52 -0
  180. package/src/daemon/tool-setup-types.ts +13 -0
  181. package/src/events/relationship-state-updated.ts +25 -0
  182. package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -1
  183. package/src/home/home-greeting.ts +0 -9
  184. package/src/home/suggested-prompts.ts +0 -9
  185. package/src/ipc/gateway-flag-listener.ts +123 -0
  186. package/src/ipc/skill-routes/registries.ts +8 -12
  187. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  188. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  189. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
  190. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  191. package/src/memory/__tests__/memory-retrospective-job.test.ts +7 -0
  192. package/src/memory/auto-analysis-enqueue.ts +5 -1
  193. package/src/memory/conversation-crud.ts +71 -70
  194. package/src/memory/conversation-starters-cadence.ts +3 -1
  195. package/src/memory/conversation-title-service.ts +19 -3
  196. package/src/memory/db-async-query.ts +214 -0
  197. package/src/memory/db-init.ts +10 -0
  198. package/src/memory/db-maintenance.ts +30 -21
  199. package/src/memory/graph/bootstrap.ts +8 -1
  200. package/src/memory/graph/capability-seed.ts +7 -3
  201. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  202. package/src/memory/graph/extraction.ts +1 -5
  203. package/src/memory/graph/graph-search.ts +7 -1
  204. package/src/memory/indexer.ts +28 -18
  205. package/src/memory/job-handlers/cleanup.ts +76 -18
  206. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  207. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  208. package/src/memory/jobs-store.ts +14 -0
  209. package/src/memory/jobs-worker.ts +55 -22
  210. package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
  211. package/src/memory/llm-request-log-source-local.ts +7 -0
  212. package/src/memory/llm-request-log-source.ts +9 -2
  213. package/src/memory/llm-request-log-store.ts +43 -1
  214. package/src/memory/llm-usage-store.ts +24 -0
  215. package/src/memory/memory-retrospective-enqueue.ts +8 -1
  216. package/src/memory/memory-retrospective-job.ts +5 -0
  217. package/src/memory/memory-v2-activation-log-store.ts +15 -6
  218. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  219. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  220. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  221. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  222. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  223. package/src/memory/migrations/index.ts +17 -0
  224. package/src/memory/migrations/registry.ts +33 -0
  225. package/src/memory/schema/conversations.ts +1 -1
  226. package/src/memory/schema/infrastructure.ts +21 -0
  227. package/src/memory/tool-usage-store.ts +36 -8
  228. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  229. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  230. package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
  231. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  232. package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
  233. package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
  234. package/src/memory/v2/__tests__/injection.test.ts +127 -98
  235. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  236. package/src/memory/v2/__tests__/router.test.ts +171 -3
  237. package/src/memory/v2/harness/compare.ts +57 -0
  238. package/src/memory/v2/harness/metrics.ts +124 -0
  239. package/src/memory/v2/harness/oracle.ts +145 -0
  240. package/src/memory/v2/harness/replay-input.ts +224 -0
  241. package/src/memory/v2/harness/retriever.ts +74 -0
  242. package/src/memory/v2/harness/router-retriever.ts +43 -0
  243. package/src/memory/v2/harness/runner.ts +106 -0
  244. package/src/memory/v2/harness/trace.ts +58 -0
  245. package/src/memory/v2/injection.ts +21 -15
  246. package/src/memory/v2/prompts/router.ts +26 -1
  247. package/src/memory/v2/qdrant.ts +14 -2
  248. package/src/memory/v2/router.ts +171 -18
  249. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  250. package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
  251. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  252. package/src/memory/v3/__tests__/edges.test.ts +563 -0
  253. package/src/memory/v3/__tests__/filter.test.ts +512 -0
  254. package/src/memory/v3/__tests__/gate.test.ts +574 -0
  255. package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
  256. package/src/memory/v3/__tests__/loop.test.ts +530 -0
  257. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  258. package/src/memory/v3/__tests__/scouts.test.ts +440 -0
  259. package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
  260. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  261. package/src/memory/v3/__tests__/traversal.test.ts +469 -0
  262. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  263. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  264. package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
  265. package/src/memory/v3/__tests__/validate.test.ts +245 -0
  266. package/src/memory/v3/auto-edges.ts +223 -0
  267. package/src/memory/v3/coactivation-store.ts +124 -0
  268. package/src/memory/v3/consolidation-job.ts +323 -0
  269. package/src/memory/v3/edge-learning-job.ts +160 -0
  270. package/src/memory/v3/edges.ts +249 -0
  271. package/src/memory/v3/filter.ts +281 -0
  272. package/src/memory/v3/gate.ts +334 -0
  273. package/src/memory/v3/index-composition.ts +113 -0
  274. package/src/memory/v3/llm-capture.ts +46 -0
  275. package/src/memory/v3/loop.ts +382 -0
  276. package/src/memory/v3/maintenance.ts +144 -0
  277. package/src/memory/v3/prompt-context.ts +33 -0
  278. package/src/memory/v3/prompts/consolidation.ts +458 -0
  279. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  280. package/src/memory/v3/retriever.ts +33 -0
  281. package/src/memory/v3/scouts.ts +420 -0
  282. package/src/memory/v3/shadow-middleware.ts +305 -0
  283. package/src/memory/v3/traversal.ts +206 -0
  284. package/src/memory/v3/tree-index.ts +237 -0
  285. package/src/memory/v3/tree-store.ts +394 -0
  286. package/src/memory/v3/tree-walk.ts +351 -0
  287. package/src/memory/v3/types.ts +65 -0
  288. package/src/memory/v3/validate.ts +300 -0
  289. package/src/notifications/adapters/macos.ts +18 -1
  290. package/src/notifications/adapters/platform.ts +1 -1
  291. package/src/notifications/decision-engine.ts +1 -4
  292. package/src/notifications/emit-signal.ts +29 -49
  293. package/src/permissions/prompter.ts +3 -3
  294. package/src/permissions/question-prompter.ts +5 -2
  295. package/src/permissions/secret-prompter.ts +2 -2
  296. package/src/plugin-api/index.ts +4 -0
  297. package/src/plugin-api/types.ts +7 -33
  298. package/src/plugins/defaults/index.ts +6 -0
  299. package/src/plugins/defaults/injectors.ts +18 -11
  300. package/src/plugins/external-plugin-loader.ts +5 -68
  301. package/src/plugins/types.ts +11 -16
  302. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  303. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  304. package/src/prompts/persona-resolver.ts +36 -21
  305. package/src/prompts/sections.ts +39 -7
  306. package/src/prompts/system-prompt.ts +50 -185
  307. package/src/prompts/templates/BOOTSTRAP.md +2 -2
  308. package/src/prompts/templates/system-sections.ts +230 -8
  309. package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
  310. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  311. package/src/providers/anthropic/client.ts +32 -66
  312. package/src/providers/call-site-routing.ts +14 -2
  313. package/src/providers/connection-model-compat.ts +38 -0
  314. package/src/providers/connection-resolution.ts +16 -2
  315. package/src/providers/gemini/client.ts +49 -6
  316. package/src/providers/inference/adapter-factory.ts +3 -0
  317. package/src/providers/minimax/client.ts +106 -0
  318. package/src/providers/model-catalog.ts +43 -0
  319. package/src/providers/model-intents.ts +1 -1
  320. package/src/providers/openai/chat-completions-provider.ts +6 -3
  321. package/src/providers/openai/codex-models.ts +18 -0
  322. package/src/providers/openai/responses-provider.ts +78 -21
  323. package/src/providers/provider-send-message.ts +7 -1
  324. package/src/providers/retry.ts +34 -3
  325. package/src/providers/thinking-config.ts +26 -1
  326. package/src/providers/usage-tracking.ts +2 -0
  327. package/src/runtime/AGENTS.md +2 -2
  328. package/src/runtime/agent-wake.ts +1 -0
  329. package/src/runtime/assistant-event-hub.ts +76 -6
  330. package/src/runtime/auth/route-policy.ts +36 -0
  331. package/src/runtime/btw-sidechain.ts +0 -6
  332. package/src/runtime/http-types.ts +0 -2
  333. package/src/runtime/migrations/vbundle-builder.ts +10 -3
  334. package/src/runtime/pending-interactions.ts +0 -1
  335. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +106 -0
  336. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +25 -6
  337. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  338. package/src/runtime/routes/acp-routes.test.ts +255 -6
  339. package/src/runtime/routes/acp-routes.ts +8 -1
  340. package/src/runtime/routes/avatar-routes.ts +10 -10
  341. package/src/runtime/routes/background-wake-routes.ts +188 -0
  342. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  343. package/src/runtime/routes/btw-routes.ts +0 -6
  344. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  345. package/src/runtime/routes/conversation-list-routes.ts +12 -4
  346. package/src/runtime/routes/conversation-management-routes.ts +77 -20
  347. package/src/runtime/routes/conversation-query-routes.ts +142 -36
  348. package/src/runtime/routes/conversation-routes.ts +252 -410
  349. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  350. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  351. package/src/runtime/routes/domain-routes.ts +60 -10
  352. package/src/runtime/routes/email-routes.ts +5 -2
  353. package/src/runtime/routes/events-routes.ts +54 -10
  354. package/src/runtime/routes/group-routes.ts +24 -8
  355. package/src/runtime/routes/host-browser-routes.ts +10 -2
  356. package/src/runtime/routes/host-cu-routes.ts +2 -2
  357. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  358. package/src/runtime/routes/index.ts +8 -0
  359. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  360. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  361. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  362. package/src/runtime/routes/memory-item-routes.ts +8 -3
  363. package/src/runtime/routes/memory-v2-routes.ts +215 -5
  364. package/src/runtime/routes/memory-v3-routes.ts +316 -0
  365. package/src/runtime/routes/migration-routes.ts +21 -24
  366. package/src/runtime/routes/plugins-routes.ts +337 -0
  367. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  368. package/src/runtime/routes/secret-routes.ts +25 -5
  369. package/src/runtime/routes/settings-routes.ts +12 -11
  370. package/src/runtime/routes/slack-channel-routes.ts +5 -4
  371. package/src/runtime/routes/workspace-routes.ts +25 -10
  372. package/src/runtime/sync/resource-sync-events.ts +106 -38
  373. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  374. package/src/runtime/sync/sync-publisher.ts +2 -1
  375. package/src/runtime/verification-outbound-actions.ts +73 -1
  376. package/src/telemetry/types.ts +12 -0
  377. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  378. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  379. package/src/tools/acp/spawn.test.ts +119 -0
  380. package/src/tools/acp/spawn.ts +15 -2
  381. package/src/tools/apps/definitions.ts +2 -8
  382. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  383. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  384. package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
  385. package/src/tools/browser/browser-execution.ts +16 -3
  386. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  387. package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
  388. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
  389. package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
  390. package/src/tools/browser/cdp-client/factory.ts +100 -17
  391. package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
  392. package/src/tools/browser/cdp-client/types.ts +65 -0
  393. package/src/tools/browser/pinned-tabs.ts +96 -40
  394. package/src/tools/computer-use/definitions.ts +22 -78
  395. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  396. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  397. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  398. package/src/tools/credentials/vault.ts +3 -9
  399. package/src/tools/document/document-tool.ts +59 -0
  400. package/src/tools/execution-target.ts +21 -23
  401. package/src/tools/executor.ts +6 -1
  402. package/src/tools/filesystem/edit.ts +3 -9
  403. package/src/tools/filesystem/list.ts +3 -9
  404. package/src/tools/filesystem/read.ts +3 -9
  405. package/src/tools/filesystem/write.ts +3 -9
  406. package/src/tools/host-filesystem/edit.ts +3 -9
  407. package/src/tools/host-filesystem/read.ts +3 -9
  408. package/src/tools/host-filesystem/transfer.ts +3 -9
  409. package/src/tools/host-filesystem/write.ts +3 -9
  410. package/src/tools/host-terminal/host-shell.ts +3 -9
  411. package/src/tools/mcp/mcp-tool-factory.ts +1 -8
  412. package/src/tools/memory/register.test.ts +1 -1
  413. package/src/tools/memory/register.ts +4 -9
  414. package/src/tools/network/web-fetch.ts +3 -9
  415. package/src/tools/network/web-search.ts +25 -32
  416. package/src/tools/registry.ts +7 -23
  417. package/src/tools/schema-transforms.ts +1 -1
  418. package/src/tools/skills/execute.ts +3 -9
  419. package/src/tools/skills/load.ts +3 -9
  420. package/src/tools/skills/skill-tool-factory.ts +1 -8
  421. package/src/tools/subagent/notify-parent.ts +3 -9
  422. package/src/tools/system/request-permission.ts +3 -9
  423. package/src/tools/terminal/shell.ts +3 -9
  424. package/src/tools/tool-defaults.ts +94 -0
  425. package/src/tools/types.ts +27 -98
  426. package/src/tools/ui-surface/definitions.ts +6 -22
  427. package/src/usage/pricing.ts +23 -0
  428. package/src/usage/types.ts +12 -0
  429. package/src/util/logger.ts +16 -7
  430. package/src/util/platform.ts +7 -2
  431. package/src/util/sqlite3-runtime.ts +65 -0
  432. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  433. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  434. package/src/workspace/migrations/registry.ts +2 -0
  435. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  436. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  437. package/src/daemon/query-complexity-router.ts +0 -75
  438. package/src/prompts/cache-boundary.ts +0 -8
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Memory v3 — Tree structure validator.
3
+ *
4
+ * The v3 tree is hand-authored by a data-migration during the v2 → v3 rollout
5
+ * (nodes reference pages and sub-nodes by `page:`/`node:` refs). Because the
6
+ * structure is authored, not derived, it can drift: a ref can dangle, a page
7
+ * can be left unwired, two nodes can reference each other into a cycle, a
8
+ * parent node's compositional summary can fall behind a freshly-edited child,
9
+ * or a page `edges:` entry can point at a slug with no page.
10
+ *
11
+ * `validateTree` is the read-only report the migration (and any later
12
+ * structure-health probe) runs to surface those defects. It is deliberately
13
+ * **non-throwing**: the migration is in progress, so an incomplete tree is
14
+ * expected — the report is informational, and the caller decides what (if
15
+ * anything) is fatal. It builds the three indices it needs (tree, page, edge),
16
+ * walks the DAG, and returns counts plus the offending ids for each category.
17
+ *
18
+ * Categories:
19
+ * - `danglingChildRefs` — a node `children` entry (`node:`/`page:`) whose
20
+ * target node/page does not exist on disk.
21
+ * - `orphanPages` — concept pages present in the page index but not reachable
22
+ * from the tree root by descending every `node:` child. Informational while
23
+ * the migration is mid-flight (not every page is wired in yet). Synthetic
24
+ * page-index entries (skills, CLI commands) are excluded — they are never
25
+ * tree members.
26
+ * - `cycles` — back-edges found during a full DFS over `node:` adjacency
27
+ * (A → B → A). A cycle would make a naive descent loop forever.
28
+ * - `staleIndex` — a node whose own file mtime predates one of its `node:`
29
+ * children's mtime, hinting its compositional index/summary may be out of
30
+ * date relative to the child it composes.
31
+ * - `unknownEdgeTargets` — page `edges:` targets with no corresponding page
32
+ * index slug, reusing v2's `validateEdgeTargets`.
33
+ */
34
+
35
+ import { CLI_COMMAND_SLUG_PREFIX } from "../v2/cli-command-store.js";
36
+ import { getEdgeIndex, validateEdgeTargets } from "../v2/edge-index.js";
37
+ import { getPageIndex } from "../v2/page-index.js";
38
+ import { SKILL_SLUG_PREFIX } from "../v2/skill-store.js";
39
+ import { getTreeIndex, type TreeIndex } from "./tree-index.js";
40
+ import { getNodeMtimeMs } from "./tree-store.js";
41
+
42
+ /**
43
+ * A `node:` child whose mtime is newer than the parent node that composes it.
44
+ * `node` is the parent, `child` the fresher child, and the two `*MtimeMs`
45
+ * fields are their epoch-ms mtimes (parent < child triggers the report).
46
+ */
47
+ export interface StaleIndexEntry {
48
+ node: string;
49
+ child: string;
50
+ nodeMtimeMs: number;
51
+ childMtimeMs: number;
52
+ }
53
+
54
+ /**
55
+ * Read-only health report over the v3 tree + its referenced pages/edges.
56
+ * Every list is sorted for deterministic output; `*Count` fields mirror the
57
+ * corresponding list length so callers can summarize without re-counting.
58
+ */
59
+ export interface TreeValidationReport {
60
+ /** `node:`/`page:` children whose target does not exist. */
61
+ danglingChildRefs: Array<{
62
+ node: string;
63
+ ref: string;
64
+ kind: "node" | "page";
65
+ }>;
66
+ danglingChildRefCount: number;
67
+ /** Concept pages not reachable from the root by descending all node children. */
68
+ orphanPages: string[];
69
+ orphanPageCount: number;
70
+ /** Back-edges (`from → to`) closing a cycle during the full DFS descent. */
71
+ cycles: Array<{ from: string; to: string }>;
72
+ cycleCount: number;
73
+ /** Nodes whose mtime predates a child node's mtime. */
74
+ staleIndex: StaleIndexEntry[];
75
+ staleIndexCount: number;
76
+ /** Page `edges:` targets with no corresponding page-index slug. */
77
+ unknownEdgeTargets: Array<{ from: string; to: string }>;
78
+ unknownEdgeTargetCount: number;
79
+ }
80
+
81
+ /** True when a page-index slug is a synthetic (non-concept-page) entry. */
82
+ function isSyntheticSlug(slug: string): boolean {
83
+ return (
84
+ slug.startsWith(SKILL_SLUG_PREFIX) ||
85
+ slug.startsWith(CLI_COMMAND_SLUG_PREFIX)
86
+ );
87
+ }
88
+
89
+ /**
90
+ * Collect dangling `node:`/`page:` child refs: every node child whose target
91
+ * node id is absent from `tree.nodes`, and every page child whose slug is
92
+ * absent from `knownPageSlugs`. Sorted by `(node, kind, ref)`.
93
+ */
94
+ function collectDanglingChildRefs(
95
+ tree: TreeIndex,
96
+ knownPageSlugs: ReadonlySet<string>,
97
+ ): Array<{ node: string; ref: string; kind: "node" | "page" }> {
98
+ const dangling: Array<{ node: string; ref: string; kind: "node" | "page" }> =
99
+ [];
100
+ for (const [nodeId, children] of tree.childrenByNode) {
101
+ for (const child of children) {
102
+ const exists =
103
+ child.kind === "node"
104
+ ? tree.nodes.has(child.ref)
105
+ : knownPageSlugs.has(child.ref);
106
+ if (!exists) {
107
+ dangling.push({ node: nodeId, ref: child.ref, kind: child.kind });
108
+ }
109
+ }
110
+ }
111
+ dangling.sort(
112
+ (a, b) =>
113
+ a.node.localeCompare(b.node) ||
114
+ a.kind.localeCompare(b.kind) ||
115
+ a.ref.localeCompare(b.ref),
116
+ );
117
+ return dangling;
118
+ }
119
+
120
+ /**
121
+ * Resolve the existing `node:` children of `nodeId`, in `children` order. Refs
122
+ * to absent nodes are skipped (those are reported separately as dangling) so
123
+ * the descent never recurses into a node that isn't on disk.
124
+ */
125
+ function nodeChildrenOf(tree: TreeIndex, nodeId: string): string[] {
126
+ const children = tree.childrenByNode.get(nodeId) ?? [];
127
+ const out: string[] = [];
128
+ for (const child of children) {
129
+ if (child.kind === "node" && tree.nodes.has(child.ref)) {
130
+ out.push(child.ref);
131
+ }
132
+ }
133
+ return out;
134
+ }
135
+
136
+ /**
137
+ * Full DFS over `node:` adjacency from `tree.root`. Returns the set of
138
+ * reachable node ids (for orphan-page reachability) and the back-edges that
139
+ * close a cycle. A back-edge is an edge into a node still on the active
140
+ * recursion stack (classic gray-node cycle detection); `visited` (black)
141
+ * prevents re-walking shared DAG sub-nodes.
142
+ */
143
+ function descend(tree: TreeIndex): {
144
+ reachableNodes: Set<string>;
145
+ cycles: Array<{ from: string; to: string }>;
146
+ } {
147
+ const reachableNodes = new Set<string>();
148
+ const onStack = new Set<string>();
149
+ const cycles: Array<{ from: string; to: string }> = [];
150
+
151
+ // Iterative DFS with an explicit stack so deep trees don't blow the call
152
+ // stack. Each frame tracks its child cursor; we push a child frame, and on
153
+ // exhaustion pop the parent off the recursion stack (`onStack`).
154
+ type Frame = { node: string; children: string[]; cursor: number };
155
+ const stack: Frame[] = [];
156
+
157
+ function enter(nodeId: string): void {
158
+ reachableNodes.add(nodeId);
159
+ onStack.add(nodeId);
160
+ stack.push({
161
+ node: nodeId,
162
+ children: nodeChildrenOf(tree, nodeId),
163
+ cursor: 0,
164
+ });
165
+ }
166
+
167
+ if (tree.nodes.has(tree.root)) {
168
+ enter(tree.root);
169
+ }
170
+
171
+ while (stack.length > 0) {
172
+ const frame = stack[stack.length - 1];
173
+ if (frame.cursor >= frame.children.length) {
174
+ onStack.delete(frame.node);
175
+ stack.pop();
176
+ continue;
177
+ }
178
+ const child = frame.children[frame.cursor++];
179
+ if (onStack.has(child)) {
180
+ // Edge into an ancestor still on the stack → cycle-closing back-edge.
181
+ cycles.push({ from: frame.node, to: child });
182
+ continue;
183
+ }
184
+ if (reachableNodes.has(child)) {
185
+ // Already fully explored via another parent (shared DAG sub-node).
186
+ continue;
187
+ }
188
+ enter(child);
189
+ }
190
+
191
+ cycles.sort(
192
+ (a, b) => a.from.localeCompare(b.from) || a.to.localeCompare(b.to),
193
+ );
194
+ return { reachableNodes, cycles };
195
+ }
196
+
197
+ /**
198
+ * Concept pages reachable from the tree: every `page:` child of a reachable
199
+ * node. Pages hanging off unreachable nodes are *not* counted reachable — they
200
+ * only become reachable once their parent chain links back to the root.
201
+ */
202
+ function reachablePages(
203
+ tree: TreeIndex,
204
+ reachableNodes: ReadonlySet<string>,
205
+ ): Set<string> {
206
+ const pages = new Set<string>();
207
+ for (const nodeId of reachableNodes) {
208
+ for (const child of tree.childrenByNode.get(nodeId) ?? []) {
209
+ if (child.kind === "page") pages.add(child.ref);
210
+ }
211
+ }
212
+ return pages;
213
+ }
214
+
215
+ /**
216
+ * Nodes whose own mtime predates one of their `node:` children's mtime. A
217
+ * missing node file reads as mtime 0 (oldest), so the check never flags a
218
+ * parent against an absent child. Sorted by `(node, child)`.
219
+ */
220
+ async function collectStaleIndex(
221
+ workspaceDir: string,
222
+ tree: TreeIndex,
223
+ ): Promise<StaleIndexEntry[]> {
224
+ const ids = [...tree.nodes.keys()];
225
+ const mtimes = new Map<string, number>();
226
+ await Promise.all(
227
+ ids.map(async (id) => {
228
+ mtimes.set(id, await getNodeMtimeMs(workspaceDir, id));
229
+ }),
230
+ );
231
+
232
+ const stale: StaleIndexEntry[] = [];
233
+ for (const node of ids) {
234
+ const nodeMtimeMs = mtimes.get(node) ?? 0;
235
+ for (const child of nodeChildrenOf(tree, node)) {
236
+ const childMtimeMs = mtimes.get(child) ?? 0;
237
+ if (nodeMtimeMs < childMtimeMs) {
238
+ stale.push({ node, child, nodeMtimeMs, childMtimeMs });
239
+ }
240
+ }
241
+ }
242
+ stale.sort(
243
+ (a, b) => a.node.localeCompare(b.node) || a.child.localeCompare(b.child),
244
+ );
245
+ return stale;
246
+ }
247
+
248
+ /**
249
+ * Validate the hand-authored v3 tree structure for `workspaceDir` and return a
250
+ * {@link TreeValidationReport}. Builds the tree, page, and edge indices, walks
251
+ * the DAG from the root, and reports the five defect categories. Never throws —
252
+ * it is a report, not an assertion.
253
+ */
254
+ export async function validateTree(
255
+ workspaceDir: string,
256
+ ): Promise<TreeValidationReport> {
257
+ const [tree, pageIndex, edgeIndex] = await Promise.all([
258
+ getTreeIndex(workspaceDir),
259
+ getPageIndex(workspaceDir),
260
+ getEdgeIndex(workspaceDir),
261
+ ]);
262
+
263
+ const knownPageSlugs = new Set(pageIndex.bySlug.keys());
264
+
265
+ // Kick off the stale-index mtime stats up front — it only depends on the
266
+ // tree, not on the DAG walk below — so its filesystem reads overlap the
267
+ // (synchronous) descent rather than running strictly after it.
268
+ const staleIndexPromise = collectStaleIndex(workspaceDir, tree);
269
+
270
+ const danglingChildRefs = collectDanglingChildRefs(tree, knownPageSlugs);
271
+
272
+ const { reachableNodes, cycles } = descend(tree);
273
+
274
+ const reached = reachablePages(tree, reachableNodes);
275
+ const orphanPages = [...knownPageSlugs]
276
+ .filter((slug) => !isSyntheticSlug(slug) && !reached.has(slug))
277
+ .sort();
278
+
279
+ const staleIndex = await staleIndexPromise;
280
+
281
+ // Edge graph is page-only; knownSlugs is the full page-index slug set so an
282
+ // edge pointing at a skill/CLI entry is not spuriously flagged unknown.
283
+ const unknownEdgeTargets = validateEdgeTargets(
284
+ edgeIndex,
285
+ knownPageSlugs,
286
+ ).missing;
287
+
288
+ return {
289
+ danglingChildRefs,
290
+ danglingChildRefCount: danglingChildRefs.length,
291
+ orphanPages,
292
+ orphanPageCount: orphanPages.length,
293
+ cycles,
294
+ cycleCount: cycles.length,
295
+ staleIndex,
296
+ staleIndexCount: staleIndex.length,
297
+ unknownEdgeTargets,
298
+ unknownEdgeTargetCount: unknownEdgeTargets.length,
299
+ };
300
+ }
@@ -18,6 +18,7 @@
18
18
  * does not match their own identity.
19
19
  */
20
20
 
21
+ import type { InterfaceId } from "../../channels/types.js";
21
22
  import type { ServerMessage } from "../../daemon/message-protocol.js";
22
23
  import { getLogger } from "../../util/logger.js";
23
24
  import type {
@@ -30,7 +31,23 @@ import type {
30
31
 
31
32
  const log = getLogger("notif-adapter-vellum");
32
33
 
33
- export type BroadcastFn = (msg: ServerMessage) => void;
34
+ /**
35
+ * Optional targeting/filtering applied at the hub when a broadcast is
36
+ * emitted. Mirrors the third argument of
37
+ * `broadcastMessage()` in `runtime/assistant-event-hub.ts`. Callers can
38
+ * use `targetInterfaceId` to scope a legacy message to a single client
39
+ * surface (e.g. macOS) during a migration window.
40
+ */
41
+ export interface BroadcastFnOptions {
42
+ targetClientId?: string;
43
+ targetInterfaceId?: InterfaceId;
44
+ }
45
+
46
+ export type BroadcastFn = (
47
+ msg: ServerMessage,
48
+ conversationId?: string,
49
+ options?: BroadcastFnOptions,
50
+ ) => void;
34
51
 
35
52
  /**
36
53
  * Event name prefixes that carry guardian-sensitive content (approval
@@ -5,7 +5,7 @@
5
5
  * POSTs a `notification_intent` payload to
6
6
  * `/v1/assistants/{id}/push/dispatch/`. The platform endpoint fans the
7
7
  * notification out to all registered device tokens for the bound user and
8
- * gates on the `ios-remote-push-enabled` LD flag server-side (returning 202
8
+ * gates on the `ios-remote-push-enabled` feature flag server-side (returning 202
9
9
  * with `{ skipped: "flag_off" }` when the flag is OFF — no action needed
10
10
  * from the daemon).
11
11
  *
@@ -13,7 +13,6 @@ import { v4 as uuid } from "uuid";
13
13
 
14
14
  import { getDeliverableChannels } from "../channels/config.js";
15
15
  import { listGuardianChannels } from "../contacts/contact-store.js";
16
- import { resolveGuardianPersona } from "../prompts/persona-resolver.js";
17
16
  import { buildCoreIdentityContext } from "../prompts/system-prompt.js";
18
17
  import {
19
18
  createTimeout,
@@ -921,9 +920,7 @@ async function classifyWithLLM(
921
920
  const candidateContext = candidateSet
922
921
  ? (serializeCandidatesForPrompt(candidateSet) ?? undefined)
923
922
  : undefined;
924
- const rawIdentityContext = buildCoreIdentityContext({
925
- userPersona: resolveGuardianPersona(),
926
- });
923
+ const rawIdentityContext = buildCoreIdentityContext();
927
924
  const identityContext = rawIdentityContext
928
925
  ? truncate(rawIdentityContext, MAX_IDENTITY_CONTEXT_CHARS, "\n…[truncated]")
929
926
  : undefined;
@@ -14,8 +14,9 @@ import { v4 as uuid } from "uuid";
14
14
  import { getDeliverableChannels } from "../channels/config.js";
15
15
  import { findGuardianForChannel } from "../contacts/contact-store.js";
16
16
  import type { ConversationCreateType } from "../memory/conversation-crud.js";
17
+ import { broadcastMessage } from "../runtime/assistant-event-hub.js";
17
18
  import { getLogger } from "../util/logger.js";
18
- import { type BroadcastFn, VellumAdapter } from "./adapters/macos.js";
19
+ import { VellumAdapter } from "./adapters/macos.js";
19
20
  import { PlatformPushAdapter } from "./adapters/platform.js";
20
21
  import { SlackAdapter } from "./adapters/slack.js";
21
22
  import { TelegramAdapter } from "./adapters/telegram.js";
@@ -49,56 +50,38 @@ const log = getLogger("emit-signal");
49
50
  // ── Broadcaster singleton ──────────────────────────────────────────────
50
51
 
51
52
  let broadcasterInstance: NotificationBroadcaster | null = null;
52
- let registeredBroadcastFn: BroadcastFn | null = null;
53
-
54
- /**
55
- * Register the broadcast function so the vellum adapter can deliver
56
- * notifications to connected clients. Must be called once during
57
- * daemon startup (before any signals are emitted).
58
- */
59
- export function registerBroadcastFn(fn: BroadcastFn): void {
60
- registeredBroadcastFn = fn;
61
- // Reset the broadcaster so it picks up the new broadcast function
62
- broadcasterInstance = null;
63
- }
64
53
 
65
54
  function getBroadcaster(): NotificationBroadcaster {
66
55
  if (!broadcasterInstance) {
67
- const adapters = [
56
+ broadcasterInstance = new NotificationBroadcaster([
57
+ new VellumAdapter(broadcastMessage),
68
58
  new TelegramAdapter(),
69
59
  new SlackAdapter(),
70
60
  new PlatformPushAdapter(),
71
- ];
72
- if (registeredBroadcastFn) {
73
- adapters.unshift(new VellumAdapter(registeredBroadcastFn));
74
- }
75
- broadcasterInstance = new NotificationBroadcaster(adapters);
61
+ ]);
76
62
 
77
63
  // Wire the conversation-created callback so the macOS client is notified
78
64
  // immediately when a vellum notification conversation is paired — before
79
65
  // slower channel deliveries (e.g. Telegram) delay the push.
80
- if (registeredBroadcastFn) {
81
- const broadcastFn = registeredBroadcastFn;
82
- broadcasterInstance.setOnConversationCreated((info) => {
83
- broadcastFn({
84
- type: "notification_conversation_created",
85
- conversationId: info.conversationId,
86
- title: info.title,
87
- sourceEventName: info.sourceEventName,
88
- targetGuardianPrincipalId: info.targetGuardianPrincipalId,
89
- groupId: info.groupId,
90
- source: info.source,
91
- silent: info.silent,
92
- });
93
- log.info(
94
- {
95
- conversationId: info.conversationId,
96
- guardianScoped: info.targetGuardianPrincipalId != null,
97
- },
98
- "Emitted notification_conversation_created push event",
99
- );
66
+ broadcasterInstance.setOnConversationCreated((info) => {
67
+ broadcastMessage({
68
+ type: "notification_conversation_created",
69
+ conversationId: info.conversationId,
70
+ title: info.title,
71
+ sourceEventName: info.sourceEventName,
72
+ targetGuardianPrincipalId: info.targetGuardianPrincipalId,
73
+ groupId: info.groupId,
74
+ source: info.source,
75
+ silent: info.silent,
100
76
  });
101
- }
77
+ log.info(
78
+ {
79
+ conversationId: info.conversationId,
80
+ guardianScoped: info.targetGuardianPrincipalId != null,
81
+ },
82
+ "Emitted notification_conversation_created push event",
83
+ );
84
+ });
102
85
  }
103
86
  return broadcasterInstance;
104
87
  }
@@ -115,18 +98,15 @@ function getConnectedChannels(): NotificationChannel[] {
115
98
  switch (channel) {
116
99
  case "vellum":
117
100
  // Vellum is always considered connected (the local transport is
118
- // always available when the daemon is running).
101
+ // always available when the assistant is running).
119
102
  channels.push(channel);
120
103
  break;
121
104
  case "platform":
122
- // Platform push is connected when the daemon has a registered
123
- // broadcast function i.e., full daemon mode where platform
124
- // credentials are also available. Mirrors the vellum gate so
125
- // the decision engine doesn't route to platform in standalone
126
- // CLI contexts where VellumPlatformClient.create() returns null.
127
- if (registeredBroadcastFn) {
128
- channels.push(channel);
129
- }
105
+ // Platform push is treated as connected at the decision-engine
106
+ // layer; the actual delivery path lazily resolves
107
+ // `VellumPlatformClient.create()` in `PlatformPushAdapter.send()`
108
+ // and reports a delivery failure when credentials are absent.
109
+ channels.push(channel);
130
110
  break;
131
111
  case "telegram": {
132
112
  // A binding-based channel is connected when the guardian has an
@@ -79,7 +79,7 @@ export class PermissionPrompter {
79
79
  const timeoutMs = getConfig().timeouts.permissionTimeoutSec * 1000;
80
80
 
81
81
  const timer = setTimeout(() => {
82
- const interaction = pendingInteractions.resolve(requestId);
82
+ const interaction = pendingInteractions.resolve(requestId, "cancelled");
83
83
  this.ownedIds.delete(requestId);
84
84
  log.warn(
85
85
  { requestId, toolName },
@@ -130,7 +130,7 @@ export class PermissionPrompter {
130
130
  if (signal) {
131
131
  const onAbort = () => {
132
132
  if (this.ownedIds.has(requestId)) {
133
- pendingInteractions.resolve(requestId);
133
+ pendingInteractions.resolve(requestId, "cancelled");
134
134
  this.ownedIds.delete(requestId);
135
135
  resolve({ decision: "deny", wasAbort: true });
136
136
  }
@@ -232,7 +232,7 @@ export class PermissionPrompter {
232
232
 
233
233
  dispose(): void {
234
234
  for (const requestId of [...this.ownedIds]) {
235
- const interaction = pendingInteractions.resolve(requestId);
235
+ const interaction = pendingInteractions.resolve(requestId, "cancelled");
236
236
  this.ownedIds.delete(requestId);
237
237
  interaction?.rpcReject?.(
238
238
  new AssistantError("Prompter disposed", ErrorCode.INTERNAL_ERROR),
@@ -223,8 +223,11 @@ export class QuestionPrompter {
223
223
  signal.removeEventListener("abort", onAbort);
224
224
  }
225
225
  // Idempotent: a no-op if the entry was already removed (e.g. by
226
- // `removeByConversation`) or by an earlier path.
227
- pendingInteractions.resolve(requestId);
226
+ // `removeByConversation`) or by an earlier path. The route's
227
+ // success path resolves with "answered" before invoking rpcResolve,
228
+ // so this fallback only fires for timeout / abort / removeByConversation —
229
+ // all cancellation-shaped outcomes.
230
+ pendingInteractions.resolve(requestId, "cancelled");
228
231
  fn();
229
232
  };
230
233
 
@@ -71,7 +71,7 @@ export class SecretPrompter {
71
71
  const timeoutMs = getConfig().timeouts.permissionTimeoutSec * 1000;
72
72
 
73
73
  const timer = setTimeout(() => {
74
- pendingInteractions.resolve(requestId);
74
+ pendingInteractions.resolve(requestId, "cancelled");
75
75
  this.ownedIds.delete(requestId);
76
76
  log.warn({ requestId, service, field }, "Secret prompt timed out");
77
77
  resolve({ value: null, delivery: "store" });
@@ -142,7 +142,7 @@ export class SecretPrompter {
142
142
 
143
143
  dispose(): void {
144
144
  for (const requestId of [...this.ownedIds]) {
145
- const interaction = pendingInteractions.resolve(requestId);
145
+ const interaction = pendingInteractions.resolve(requestId, "cancelled");
146
146
  this.ownedIds.delete(requestId);
147
147
  interaction?.rpcReject?.(
148
148
  new AssistantError("Prompter disposed", ErrorCode.INTERNAL_ERROR),
@@ -25,6 +25,8 @@
25
25
  * - {@link UserPromptSubmitContext} — passed to `user-prompt-submit` hook,
26
26
  * fired immediately before the agent loop receives a user's prompt
27
27
  * - {@link PluginLogger} — pino-compatible logger shape on the contexts
28
+ * - {@link ToolDefinition} — author-facing tool spec (default-export shape
29
+ * for both plugin tool files and workspace tool files)
28
30
  * - {@link ToolContext} — passed to a plugin tool's `execute` method
29
31
  * - {@link ToolExecutionResult} — return shape of a plugin tool's `execute`
30
32
  *
@@ -41,6 +43,8 @@ export type {
41
43
  PluginLogger,
42
44
  PluginShutdownContext,
43
45
  ToolContext,
46
+ ToolDefinition,
44
47
  ToolExecutionResult,
45
48
  UserPromptSubmitContext,
46
49
  } from "./types.js";
50
+ export { RiskLevel } from "./types.js";
@@ -1,43 +1,17 @@
1
1
  /**
2
- * Public plugin-API types.
3
- *
4
- * This module is the entry point plugin authors land on when they import
5
- * from `@vellumai/plugin-api`. The shapes here are the canonical public
6
- * contract — anything exported is part of the surface that semver gates.
7
- *
8
- * ## Tool-execution types
9
- *
10
- * `ToolContext` and `ToolExecutionResult` are re-exports of the narrow,
11
- * stable bases defined alongside their daemon-internal counterparts in
12
- * `assistant/src/tools/types.ts`. The daemon-internal `ToolContext` /
13
- * `ToolExecutionResult` (with CES, trust classification, lifecycle
14
- * events, sensitive-output bindings, risk metadata, etc.) `extends`
15
- * the public bases, so the runtime can hand plugins the full value
16
- * without a manual cast and tsc enforces the structural relationship.
17
- * Plugin tools see the narrow surface only — they MUST NOT set fields
18
- * that belong to the daemon-internal extension.
19
- *
20
- * ## Hook contexts
21
- *
22
- * The init / shutdown hook contexts are owned by this module directly.
23
- * They have no daemon-internal extension today (the daemon constructs
24
- * and hands them straight through), so there's nothing to inherit from.
25
- *
26
- * ## Compatibility
27
- *
28
- * Adding fields to any public shape is non-breaking. Renaming or
29
- * removing fields is breaking and gated on a major bump of
30
- * `@vellumai/plugin-api`.
2
+ * Public plugin-API types — the canonical contract for
3
+ * `@vellumai/plugin-api`. Adding fields is non-breaking; renaming /
4
+ * removing is breaking and gated on a major bump.
31
5
  */
32
6
 
33
7
  import type { Message } from "../providers/types.js";
34
8
 
35
- // ─── Tool-execution types (re-exported from daemon source-of-truth) ──────────
36
-
37
9
  export type {
38
- PluginToolContext as ToolContext,
39
- PluginToolExecutionResult as ToolExecutionResult,
10
+ ToolContext,
11
+ ToolDefinition,
12
+ ToolExecutionResult,
40
13
  } from "../tools/types.js";
14
+ export { RiskLevel } from "../tools/types.js";
41
15
 
42
16
  // ─── Logger ──────────────────────────────────────────────────────────────────
43
17
 
@@ -24,6 +24,7 @@
24
24
  * chain) does not trip a TDZ.
25
25
  */
26
26
 
27
+ import { memoryV3ShadowPlugin } from "../../memory/v3/shadow-middleware.js";
27
28
  import { registerPlugin, resetPluginRegistryForTests } from "../registry.js";
28
29
  import { type Plugin, PluginExecutionError } from "../types.js";
29
30
  import { defaultCircuitBreakerPlugin } from "./circuit-breaker.js";
@@ -60,6 +61,11 @@ function getAllDefaultPlugins(): readonly Plugin[] {
60
61
  defaultEmptyResponsePlugin,
61
62
  defaultToolErrorPlugin,
62
63
  defaultMemoryRetrievalPlugin,
64
+ // Live-shadow v3 retrieval. Always registered; inert unless both
65
+ // `memory.v3.enabled` and `memory.v3.shadow` are on (gated inside the
66
+ // middleware). Ordered after the default so the default terminal still
67
+ // produces the injected (v2) `MemoryResult`.
68
+ memoryV3ShadowPlugin,
63
69
  defaultInjectorsPlugin,
64
70
  defaultTokenEstimatePlugin,
65
71
  defaultOverflowReducePlugin,