@vellumai/assistant 0.8.4 → 0.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (802) hide show
  1. package/AGENTS.md +33 -1
  2. package/ARCHITECTURE.md +3 -3
  3. package/bunfig.toml +6 -1
  4. package/docs/browser-use-architecture-phase2.md +1 -1
  5. package/docs/credential-execution-service.md +6 -6
  6. package/docs/plugins.md +4 -3
  7. package/knip.json +2 -1
  8. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
  9. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
  10. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
  11. package/openapi.yaml +2748 -216
  12. package/package.json +1 -1
  13. package/src/__tests__/actor-token-service.test.ts +3 -2
  14. package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
  15. package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
  16. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
  17. package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
  18. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  19. package/src/__tests__/annotate-risk-options.test.ts +1 -0
  20. package/src/__tests__/anthropic-provider.test.ts +34 -37
  21. package/src/__tests__/approval-cascade.test.ts +1 -0
  22. package/src/__tests__/approval-routes-http.test.ts +9 -13
  23. package/src/__tests__/assert-not-live-db.ts +79 -0
  24. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  25. package/src/__tests__/assistant-feature-flags-integration.test.ts +12 -28
  26. package/src/__tests__/audit-log-rotation.test.ts +72 -18
  27. package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
  28. package/src/__tests__/background-workers-disk-pressure.test.ts +8 -11
  29. package/src/__tests__/browser-skill-endstate.test.ts +3 -3
  30. package/src/__tests__/btw-routes.test.ts +5 -5
  31. package/src/__tests__/call-controller.test.ts +3 -3
  32. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  33. package/src/__tests__/channel-approval-routes.test.ts +3 -2
  34. package/src/__tests__/channel-guardian.test.ts +6 -5
  35. package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
  36. package/src/__tests__/channel-reply-delivery.test.ts +35 -0
  37. package/src/__tests__/channel-retry-sweep.test.ts +320 -3
  38. package/src/__tests__/checker.test.ts +18 -27
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/compaction-trail-store.test.ts +264 -0
  41. package/src/__tests__/compactor-call-site-logging.test.ts +215 -0
  42. package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
  43. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +12 -16
  44. package/src/__tests__/computer-use-tools.test.ts +14 -18
  45. package/src/__tests__/config-loader-backfill.test.ts +13 -28
  46. package/src/__tests__/config-loader-corrupt.test.ts +5 -5
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
  48. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
  49. package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
  50. package/src/__tests__/config-schema.test.ts +10 -10
  51. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  52. package/src/__tests__/connection-model-compat.test.ts +83 -0
  53. package/src/__tests__/contacts-tools.test.ts +3 -2
  54. package/src/__tests__/context-token-estimator.test.ts +22 -0
  55. package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
  56. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -1
  57. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
  58. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -1
  59. package/src/__tests__/conversation-agent-loop-overflow.test.ts +231 -2
  60. package/src/__tests__/conversation-agent-loop.test.ts +581 -54
  61. package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
  62. package/src/__tests__/conversation-app-control-instantiation.test.ts +31 -24
  63. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
  64. package/src/__tests__/conversation-attention-store.test.ts +101 -0
  65. package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
  66. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  67. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
  68. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  69. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  70. package/src/__tests__/conversation-error.test.ts +61 -0
  71. package/src/__tests__/conversation-fork-crud.test.ts +239 -15
  72. package/src/__tests__/conversation-fork-route.test.ts +3 -2
  73. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  74. package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
  75. package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
  76. package/src/__tests__/conversation-lifecycle.test.ts +53 -11
  77. package/src/__tests__/conversation-list-source.test.ts +3 -2
  78. package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
  79. package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +14 -13
  80. package/src/__tests__/conversation-pairing.test.ts +53 -0
  81. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
  82. package/src/__tests__/conversation-process-callsite.test.ts +1 -0
  83. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  84. package/src/__tests__/conversation-queue.test.ts +333 -291
  85. package/src/__tests__/conversation-routes-disk-view.test.ts +112 -18
  86. package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
  87. package/src/__tests__/conversation-routes-slash-commands.test.ts +68 -2
  88. package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
  89. package/src/__tests__/conversation-skill-tools.test.ts +40 -147
  90. package/src/__tests__/conversation-slash-queue.test.ts +84 -32
  91. package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
  92. package/src/__tests__/conversation-speed-override.test.ts +1 -0
  93. package/src/__tests__/conversation-store.test.ts +1 -1
  94. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
  95. package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
  96. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
  97. package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
  98. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
  99. package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
  100. package/src/__tests__/conversation-sync-tags.test.ts +218 -35
  101. package/src/__tests__/conversation-title-service.test.ts +1 -0
  102. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
  103. package/src/__tests__/conversation-usage.test.ts +1 -0
  104. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
  105. package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
  106. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -1
  107. package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
  108. package/src/__tests__/credential-broker-server-use.test.ts +5 -5
  109. package/src/__tests__/credential-execution-client.test.ts +72 -1
  110. package/src/__tests__/credential-execution-feature-gates.test.ts +19 -19
  111. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  112. package/src/__tests__/credential-health-service.test.ts +252 -3
  113. package/src/__tests__/credential-security-invariants.test.ts +6 -5
  114. package/src/__tests__/credential-vault-unit.test.ts +21 -21
  115. package/src/__tests__/credential-vault.test.ts +5 -5
  116. package/src/__tests__/cross-provider-web-search.test.ts +56 -2
  117. package/src/__tests__/db-connection-isolation.test.ts +7 -6
  118. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
  119. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
  120. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
  121. package/src/__tests__/db-test-helpers.ts +58 -0
  122. package/src/__tests__/disk-pressure-guard.test.ts +58 -41
  123. package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
  124. package/src/__tests__/disk-pressure-routes.test.ts +0 -33
  125. package/src/__tests__/disk-pressure-tools.test.ts +0 -4
  126. package/src/__tests__/dm-persistence.test.ts +26 -40
  127. package/src/__tests__/document-create-dedupe.test.ts +189 -0
  128. package/src/__tests__/document-find-replace.test.ts +3 -2
  129. package/src/__tests__/document-tool-security.test.ts +81 -2
  130. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  131. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
  132. package/src/__tests__/email-html-renderer.test.ts +12 -0
  133. package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
  134. package/src/__tests__/encrypted-store.test.ts +11 -9
  135. package/src/__tests__/feature-flag-test-helpers.ts +53 -0
  136. package/src/__tests__/filing-service.test.ts +1 -0
  137. package/src/__tests__/first-greeting.test.ts +62 -12
  138. package/src/__tests__/gateway-flag-listener.test.ts +236 -0
  139. package/src/__tests__/gemini-provider.test.ts +104 -0
  140. package/src/__tests__/guardian-action-sweep.test.ts +3 -2
  141. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  142. package/src/__tests__/guardian-outbound-http.test.ts +10 -7
  143. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
  144. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -1
  145. package/src/__tests__/heartbeat-disk-pressure.test.ts +5 -0
  146. package/src/__tests__/heartbeat-service.test.ts +5 -0
  147. package/src/__tests__/helpers/mock-logger.ts +26 -0
  148. package/src/__tests__/host-bash-routes.test.ts +1 -0
  149. package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
  150. package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
  151. package/src/__tests__/host-shell-tool.test.ts +6 -5
  152. package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
  153. package/src/__tests__/http-conversation-lineage.test.ts +3 -2
  154. package/src/__tests__/http-user-message-parity.test.ts +29 -7
  155. package/src/__tests__/identity-intro-cache.test.ts +133 -22
  156. package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
  157. package/src/__tests__/inference-profile-reaper.test.ts +3 -2
  158. package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
  159. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  160. package/src/__tests__/injector-disk-pressure.test.ts +3 -17
  161. package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
  162. package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
  163. package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
  164. package/src/__tests__/llm-context-normalization.test.ts +42 -0
  165. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  166. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  167. package/src/__tests__/llm-resolver.test.ts +408 -9
  168. package/src/__tests__/llm-schema.test.ts +1 -1
  169. package/src/__tests__/llm-usage-store.test.ts +66 -0
  170. package/src/__tests__/logger.test.ts +89 -0
  171. package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
  172. package/src/__tests__/mcp-abort-signal.test.ts +16 -2
  173. package/src/__tests__/mcp-client-auth.test.ts +14 -0
  174. package/src/__tests__/media-generate-image.test.ts +31 -0
  175. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  176. package/src/__tests__/messaging-send-tool.test.ts +1 -0
  177. package/src/__tests__/migration-import-from-url.test.ts +3 -3
  178. package/src/__tests__/mock-gateway-ipc.ts +18 -2
  179. package/src/__tests__/model-intents.test.ts +4 -6
  180. package/src/__tests__/native-web-search.test.ts +30 -2
  181. package/src/__tests__/notification-deep-link.test.ts +62 -0
  182. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  183. package/src/__tests__/oauth-commands-routes.test.ts +37 -0
  184. package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
  185. package/src/__tests__/oauth-store.test.ts +3 -2
  186. package/src/__tests__/onboarding-template-contract.test.ts +4 -3
  187. package/src/__tests__/openai-provider.test.ts +54 -9
  188. package/src/__tests__/openai-responses-provider.test.ts +176 -14
  189. package/src/__tests__/openrouter-provider-only.test.ts +27 -5
  190. package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
  191. package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
  192. package/src/__tests__/persistence-pipeline.test.ts +139 -1
  193. package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
  194. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  195. package/src/__tests__/platform.test.ts +2 -2
  196. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  197. package/src/__tests__/plugin-bootstrap.test.ts +11 -13
  198. package/src/__tests__/plugin-tool-contribution.test.ts +50 -40
  199. package/src/__tests__/plugin-types.test.ts +3 -2
  200. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  201. package/src/__tests__/pricing.test.ts +12 -0
  202. package/src/__tests__/process-message-background-slack.test.ts +21 -16
  203. package/src/__tests__/process-message-display-content.test.ts +19 -22
  204. package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
  205. package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
  206. package/src/__tests__/provider-registry-ollama.test.ts +45 -22
  207. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  208. package/src/__tests__/recording-handler.test.ts +1 -0
  209. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
  210. package/src/__tests__/registry.test.ts +84 -84
  211. package/src/__tests__/relay-server.test.ts +10 -10
  212. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  213. package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
  214. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  215. package/src/__tests__/schedule-store.test.ts +16 -1
  216. package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
  217. package/src/__tests__/secret-ingress-http.test.ts +5 -1
  218. package/src/__tests__/secure-keys.test.ts +3 -3
  219. package/src/__tests__/send-endpoint-busy.test.ts +81 -42
  220. package/src/__tests__/server-history-render.test.ts +4 -1
  221. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  222. package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
  223. package/src/__tests__/skill-feature-flags.test.ts +16 -18
  224. package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
  225. package/src/__tests__/skill-projection-feature-flag.test.ts +48 -37
  226. package/src/__tests__/skill-projection.benchmark.test.ts +7 -13
  227. package/src/__tests__/skill-tool-factory.test.ts +97 -96
  228. package/src/__tests__/slack-channel-config.test.ts +3 -3
  229. package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
  230. package/src/__tests__/subagent-disposal.test.ts +27 -8
  231. package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
  232. package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
  233. package/src/__tests__/subagent-manager-notify.test.ts +20 -8
  234. package/src/__tests__/subagent-notify-parent.test.ts +6 -5
  235. package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
  236. package/src/__tests__/subagent-tools.test.ts +2 -1
  237. package/src/__tests__/suggestion-routes.test.ts +2 -0
  238. package/src/__tests__/sync-message-contract.test.ts +59 -0
  239. package/src/__tests__/system-prompt.test.ts +183 -131
  240. package/src/__tests__/terminal-tools.test.ts +1 -1
  241. package/src/__tests__/test-preload-verifier.ts +68 -0
  242. package/src/__tests__/test-preload.ts +32 -39
  243. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  244. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  245. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  246. package/src/__tests__/tool-executor-lifecycle-events.test.ts +35 -12
  247. package/src/__tests__/tool-executor.test.ts +64 -72
  248. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  249. package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
  250. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  251. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  252. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  253. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  254. package/src/__tests__/twilio-routes.test.ts +3 -2
  255. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  256. package/src/__tests__/usage-routes.test.ts +3 -0
  257. package/src/__tests__/validate-input.test.ts +381 -0
  258. package/src/__tests__/verification-control-plane-policy.test.ts +3 -2
  259. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
  260. package/src/__tests__/voice-session-bridge.test.ts +37 -28
  261. package/src/__tests__/workspace-git-service.test.ts +6 -5
  262. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  263. package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
  264. package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
  265. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  266. package/src/acp/prepare-agent-env.ts +78 -0
  267. package/src/acp/session-manager.ts +6 -7
  268. package/src/agent/loop.ts +88 -0
  269. package/src/api/README.md +127 -0
  270. package/src/api/constants/call-sites.ts +27 -0
  271. package/src/api/events/assistant-outbound-attachment.ts +51 -0
  272. package/src/api/events/assistant-text-delta.ts +32 -0
  273. package/src/api/events/assistant-turn-start.ts +33 -0
  274. package/src/api/events/document-comment-created.ts +48 -0
  275. package/src/api/events/document-comment-deleted.ts +24 -0
  276. package/src/api/events/document-comment-reopened.ts +25 -0
  277. package/src/api/events/document-comment-resolved.ts +27 -0
  278. package/src/api/events/generation-cancelled.ts +24 -0
  279. package/src/api/events/generation-handoff.ts +41 -0
  280. package/src/api/events/message-complete.ts +42 -0
  281. package/src/api/events/open-url.ts +30 -0
  282. package/src/api/events/relationship-state-updated.ts +25 -0
  283. package/src/api/events/tool-use-start.ts +32 -0
  284. package/src/api/index.ts +129 -0
  285. package/src/api/package.json +10 -0
  286. package/src/api/responses/llm-context-response.ts +39 -0
  287. package/src/api/responses/llm-request-log-entry.ts +93 -0
  288. package/src/api/responses/memory-recall-log.ts +65 -0
  289. package/src/api/responses/memory-v2-activation-log.ts +78 -0
  290. package/src/background-wake/background-wake-routes.test.ts +868 -0
  291. package/src/background-wake/platform-client.test.ts +308 -0
  292. package/src/background-wake/platform-client.ts +167 -0
  293. package/src/background-wake/publisher.ts +91 -0
  294. package/src/background-wake/runtime-registry.ts +24 -0
  295. package/src/background-wake/wake-intent-hooks.test.ts +282 -0
  296. package/src/calls/guardian-dispatch.ts +1 -0
  297. package/src/calls/voice-session-bridge.ts +4 -4
  298. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  299. package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
  300. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  301. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  302. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  303. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  304. package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
  305. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  306. package/src/cli/commands/__tests__/notifications.test.ts +184 -40
  307. package/src/cli/commands/browser.ts +247 -0
  308. package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
  309. package/src/cli/commands/channels/index.ts +229 -0
  310. package/src/cli/commands/domain.ts +91 -41
  311. package/src/cli/commands/inference.ts +93 -40
  312. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  313. package/src/cli/commands/memory-v2.ts +176 -1
  314. package/src/cli/commands/memory-v3-render.ts +491 -0
  315. package/src/cli/commands/memory-v3.ts +567 -0
  316. package/src/cli/commands/notifications.ts +365 -55
  317. package/src/cli/lib/open-browser.ts +7 -2
  318. package/src/cli/program.ts +4 -0
  319. package/src/config/assistant-feature-flags.ts +39 -46
  320. package/src/config/bundled-skills/document-editor/SKILL.md +16 -3
  321. package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
  322. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  323. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  324. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  325. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  326. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  327. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  328. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  329. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  330. package/src/config/bundled-skills/schedule/SKILL.md +1 -1
  331. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  332. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
  333. package/src/config/bundled-tool-registry.ts +2 -0
  334. package/src/config/call-site-defaults.ts +8 -7
  335. package/src/config/feature-flag-cache.ts +86 -0
  336. package/src/config/feature-flag-registry.json +33 -17
  337. package/src/config/llm-context-resolution.ts +10 -1
  338. package/src/config/llm-resolver.ts +121 -15
  339. package/src/config/loader.ts +4 -5
  340. package/src/config/schemas/__tests__/memory-v2.test.ts +228 -1
  341. package/src/config/schemas/call-site-catalog.ts +21 -7
  342. package/src/config/schemas/heartbeat.ts +1 -1
  343. package/src/config/schemas/llm.ts +102 -2
  344. package/src/config/schemas/memory-v2.ts +272 -0
  345. package/src/config/schemas/memory.ts +2 -1
  346. package/src/config/schemas/services.ts +6 -2
  347. package/src/config/seed-inference-profiles.ts +36 -16
  348. package/src/context/compactor.ts +52 -0
  349. package/src/context/token-estimator.ts +10 -5
  350. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  351. package/src/conversations/message-consolidation.ts +404 -0
  352. package/src/credential-execution/executable-discovery.ts +40 -0
  353. package/src/credential-execution/process-manager.ts +6 -2
  354. package/src/credential-health/credential-health-service.ts +125 -40
  355. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
  356. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
  357. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +2 -3
  358. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
  359. package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
  360. package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
  361. package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
  362. package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
  363. package/src/daemon/conversation-agent-loop-handlers.ts +390 -80
  364. package/src/daemon/conversation-agent-loop.ts +244 -90
  365. package/src/daemon/conversation-error.ts +64 -6
  366. package/src/daemon/conversation-lifecycle.ts +27 -22
  367. package/src/daemon/conversation-messaging.ts +84 -43
  368. package/src/daemon/conversation-process.ts +74 -37
  369. package/src/daemon/conversation-runtime-assembly.ts +38 -17
  370. package/src/daemon/conversation-skill-tools.ts +14 -30
  371. package/src/daemon/conversation-surfaces.ts +69 -34
  372. package/src/daemon/conversation-tool-setup.ts +77 -32
  373. package/src/daemon/conversation-usage.ts +2 -0
  374. package/src/daemon/conversation.ts +40 -75
  375. package/src/daemon/daemon-control.ts +1 -1
  376. package/src/daemon/daemon-skill-host.ts +9 -2
  377. package/src/daemon/disk-pressure-guard.ts +39 -29
  378. package/src/daemon/first-greeting.ts +31 -13
  379. package/src/daemon/handlers/config-model.test.ts +1 -0
  380. package/src/daemon/handlers/conversations.ts +11 -3
  381. package/src/daemon/handlers/shared.ts +6 -1
  382. package/src/daemon/host-browser-proxy.ts +5 -5
  383. package/src/daemon/host-cu-proxy.ts +4 -4
  384. package/src/daemon/host-file-proxy.ts +4 -4
  385. package/src/daemon/host-proxy-base.ts +4 -4
  386. package/src/daemon/host-transfer-proxy.ts +10 -10
  387. package/src/daemon/lifecycle.ts +29 -26
  388. package/src/daemon/mcp-reload-service.ts +1 -1
  389. package/src/daemon/meet-manifest-loader.ts +11 -24
  390. package/src/daemon/message-types/conversations.ts +22 -27
  391. package/src/daemon/message-types/document-comments.ts +8 -44
  392. package/src/daemon/message-types/home.ts +2 -14
  393. package/src/daemon/message-types/integrations.ts +2 -7
  394. package/src/daemon/message-types/messages.ts +25 -48
  395. package/src/daemon/message-types/subagents.ts +6 -0
  396. package/src/daemon/message-types/sync.ts +14 -0
  397. package/src/daemon/process-message.ts +9 -9
  398. package/src/daemon/providers-setup.ts +1 -1
  399. package/src/daemon/server.ts +16 -0
  400. package/src/daemon/shutdown-handlers.ts +24 -5
  401. package/src/daemon/switch-inference-profile-tool.ts +62 -0
  402. package/src/daemon/tool-setup-types.ts +7 -0
  403. package/src/daemon/wake-target-adapter.ts +10 -0
  404. package/src/documents/document-store.ts +38 -0
  405. package/src/export/__tests__/transcript-formatter.test.ts +1 -0
  406. package/src/heartbeat/__tests__/heartbeat-service.test.ts +30 -1
  407. package/src/heartbeat/heartbeat-service.ts +63 -0
  408. package/src/home/__tests__/feed-writer.test.ts +161 -0
  409. package/src/home/__tests__/post-connect-feed.test.ts +1 -0
  410. package/src/home/__tests__/suggested-prompts.test.ts +55 -59
  411. package/src/home/feed-writer.ts +146 -7
  412. package/src/home/home-greeting.ts +0 -9
  413. package/src/home/suggested-prompts.ts +27 -154
  414. package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
  415. package/src/ipc/gateway-client.test.ts +4 -1
  416. package/src/ipc/gateway-flag-listener.ts +123 -0
  417. package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
  418. package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
  419. package/src/ipc/skill-routes/memory.ts +4 -3
  420. package/src/ipc/skill-routes/registries.ts +35 -40
  421. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  422. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  423. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +242 -0
  424. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  425. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
  426. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
  427. package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
  428. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
  429. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
  430. package/src/memory/auto-analysis-enqueue.ts +5 -1
  431. package/src/memory/conversation-attention-store.ts +17 -3
  432. package/src/memory/conversation-crud.ts +423 -182
  433. package/src/memory/conversation-starters-cadence.ts +3 -1
  434. package/src/memory/conversation-title-service.ts +19 -3
  435. package/src/memory/db-async-query.ts +214 -0
  436. package/src/memory/db-connection.ts +29 -19
  437. package/src/memory/db-init.ts +14 -0
  438. package/src/memory/db-maintenance.ts +30 -21
  439. package/src/memory/db-singleton.ts +77 -0
  440. package/src/memory/delivery-channels.ts +82 -0
  441. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
  442. package/src/memory/graph/bootstrap.ts +8 -1
  443. package/src/memory/graph/capability-seed.ts +7 -3
  444. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  445. package/src/memory/graph/extraction.ts +1 -5
  446. package/src/memory/graph/graph-search.ts +7 -1
  447. package/src/memory/graph/retriever.test.ts +3 -3
  448. package/src/memory/indexer.ts +28 -18
  449. package/src/memory/job-handlers/cleanup.ts +76 -18
  450. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  451. package/src/memory/job-handlers/embedding.test.ts +3 -2
  452. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
  453. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  454. package/src/memory/jobs-store.ts +14 -0
  455. package/src/memory/jobs-worker.ts +66 -22
  456. package/src/memory/llm-request-log-source-clickhouse.ts +122 -2
  457. package/src/memory/llm-request-log-source-local.ts +31 -0
  458. package/src/memory/llm-request-log-source.ts +40 -2
  459. package/src/memory/llm-request-log-store.ts +228 -1
  460. package/src/memory/llm-usage-store.ts +24 -0
  461. package/src/memory/memory-retrospective-enqueue.ts +8 -1
  462. package/src/memory/memory-retrospective-job.ts +5 -0
  463. package/src/memory/memory-v2-activation-log-store.ts +110 -7
  464. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  465. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  466. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  467. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  468. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  469. package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
  470. package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
  471. package/src/memory/migrations/index.ts +19 -0
  472. package/src/memory/migrations/registry.ts +33 -0
  473. package/src/memory/schema/conversations.ts +10 -2
  474. package/src/memory/schema/inference.ts +0 -1
  475. package/src/memory/schema/infrastructure.ts +21 -0
  476. package/src/memory/tool-usage-store.ts +36 -8
  477. package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
  478. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  479. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  480. package/src/memory/v2/__tests__/harness-metrics.test.ts +83 -0
  481. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  482. package/src/memory/v2/__tests__/harness-replay-input.test.ts +230 -0
  483. package/src/memory/v2/__tests__/harness-runner.test.ts +135 -0
  484. package/src/memory/v2/__tests__/injection.test.ts +127 -98
  485. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  486. package/src/memory/v2/__tests__/router.test.ts +171 -3
  487. package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
  488. package/src/memory/v2/harness/compare.ts +57 -0
  489. package/src/memory/v2/harness/metrics.ts +128 -0
  490. package/src/memory/v2/harness/oracle.ts +145 -0
  491. package/src/memory/v2/harness/replay-input.ts +240 -0
  492. package/src/memory/v2/harness/retriever.ts +74 -0
  493. package/src/memory/v2/harness/router-retriever.ts +43 -0
  494. package/src/memory/v2/harness/runner.ts +112 -0
  495. package/src/memory/v2/harness/trace.ts +64 -0
  496. package/src/memory/v2/injection.ts +21 -15
  497. package/src/memory/v2/prompts/router.ts +26 -1
  498. package/src/memory/v2/qdrant.ts +14 -2
  499. package/src/memory/v2/router.ts +171 -18
  500. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  501. package/src/memory/v3/__tests__/consolidation-job.test.ts +466 -0
  502. package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
  503. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  504. package/src/memory/v3/__tests__/edges.test.ts +706 -0
  505. package/src/memory/v3/__tests__/filter.test.ts +560 -0
  506. package/src/memory/v3/__tests__/gate.test.ts +637 -0
  507. package/src/memory/v3/__tests__/index-composition.test.ts +291 -0
  508. package/src/memory/v3/__tests__/loop.test.ts +775 -0
  509. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  510. package/src/memory/v3/__tests__/scouts.test.ts +489 -0
  511. package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
  512. package/src/memory/v3/__tests__/shadow-middleware.test.ts +398 -0
  513. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  514. package/src/memory/v3/__tests__/traversal.test.ts +508 -0
  515. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  516. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  517. package/src/memory/v3/__tests__/tree-walk.test.ts +784 -0
  518. package/src/memory/v3/__tests__/validate.test.ts +277 -0
  519. package/src/memory/v3/auto-edges.ts +223 -0
  520. package/src/memory/v3/coactivation-store.ts +124 -0
  521. package/src/memory/v3/consolidation-job.ts +323 -0
  522. package/src/memory/v3/coretrieval-seed.ts +240 -0
  523. package/src/memory/v3/edge-learning-job.ts +160 -0
  524. package/src/memory/v3/edges.ts +286 -0
  525. package/src/memory/v3/filter.ts +286 -0
  526. package/src/memory/v3/gate.ts +349 -0
  527. package/src/memory/v3/index-composition.ts +126 -0
  528. package/src/memory/v3/llm-capture.ts +46 -0
  529. package/src/memory/v3/loop.ts +430 -0
  530. package/src/memory/v3/maintenance.ts +144 -0
  531. package/src/memory/v3/prompt-context.ts +33 -0
  532. package/src/memory/v3/prompts/consolidation.ts +458 -0
  533. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  534. package/src/memory/v3/retriever.ts +33 -0
  535. package/src/memory/v3/scouts.ts +431 -0
  536. package/src/memory/v3/shadow-diff.ts +287 -0
  537. package/src/memory/v3/shadow-middleware.ts +347 -0
  538. package/src/memory/v3/traversal.ts +211 -0
  539. package/src/memory/v3/tree-index.ts +237 -0
  540. package/src/memory/v3/tree-store.ts +394 -0
  541. package/src/memory/v3/tree-walk.ts +356 -0
  542. package/src/memory/v3/types.ts +65 -0
  543. package/src/memory/v3/validate.ts +323 -0
  544. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  545. package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
  546. package/src/notifications/adapters/macos.ts +18 -1
  547. package/src/notifications/adapters/platform.ts +1 -1
  548. package/src/notifications/adapters/slack.ts +45 -11
  549. package/src/notifications/broadcaster.ts +114 -63
  550. package/src/notifications/conversation-pairing.ts +23 -3
  551. package/src/notifications/decision-engine.ts +1 -4
  552. package/src/notifications/decisions-store.ts +32 -1
  553. package/src/notifications/deliveries-store.ts +45 -0
  554. package/src/notifications/edit-notification.ts +201 -0
  555. package/src/notifications/emit-signal.ts +40 -50
  556. package/src/notifications/signal.ts +10 -0
  557. package/src/notifications/types.ts +37 -0
  558. package/src/oauth/byo-connection.test.ts +67 -3
  559. package/src/oauth/byo-connection.ts +32 -5
  560. package/src/oauth/connect-orchestrator.ts +9 -0
  561. package/src/oauth/connection-resolver.test.ts +76 -0
  562. package/src/oauth/connection-resolver.ts +49 -10
  563. package/src/oauth/manual-token-connection.ts +51 -3
  564. package/src/oauth/seed-providers.ts +3 -0
  565. package/src/permissions/approval-policy.test.ts +19 -5
  566. package/src/permissions/approval-policy.ts +14 -3
  567. package/src/permissions/checker.ts +21 -8
  568. package/src/permissions/prompter.ts +3 -3
  569. package/src/permissions/question-prompter.ts +5 -2
  570. package/src/permissions/secret-prompter.ts +2 -2
  571. package/src/platform/client.test.ts +24 -1
  572. package/src/platform/client.ts +8 -0
  573. package/src/platform/feature-gate.ts +15 -0
  574. package/src/plugin-api/index.ts +4 -0
  575. package/src/plugin-api/types.ts +7 -33
  576. package/src/plugins/defaults/index.ts +6 -0
  577. package/src/plugins/defaults/injectors.ts +20 -19
  578. package/src/plugins/defaults/persistence.ts +25 -6
  579. package/src/plugins/external-plugin-loader.ts +5 -68
  580. package/src/plugins/types.ts +68 -29
  581. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  582. package/src/proactive-artifact/job.test.ts +1 -0
  583. package/src/prompts/__tests__/system-prompt.test.ts +4 -4
  584. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  585. package/src/prompts/persona-resolver.ts +36 -21
  586. package/src/prompts/sections.ts +39 -7
  587. package/src/prompts/system-prompt.ts +84 -221
  588. package/src/prompts/template-detection.ts +10 -4
  589. package/src/prompts/templates/BOOTSTRAP.md +9 -13
  590. package/src/prompts/templates/IDENTITY.md +0 -2
  591. package/src/prompts/templates/system-sections.ts +230 -8
  592. package/src/providers/__tests__/connection-model-compat.test.ts +233 -0
  593. package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
  594. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  595. package/src/providers/anthropic/client.ts +32 -66
  596. package/src/providers/call-site-routing.ts +42 -6
  597. package/src/providers/connection-model-compat.ts +61 -0
  598. package/src/providers/connection-resolution.ts +47 -14
  599. package/src/providers/fireworks/client.ts +1 -0
  600. package/src/providers/gemini/client.ts +70 -6
  601. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
  602. package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
  603. package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
  604. package/src/providers/inference/adapter-factory.ts +3 -0
  605. package/src/providers/inference/auth.ts +0 -8
  606. package/src/providers/inference/connections.ts +3 -66
  607. package/src/providers/inference/resolve-auth.ts +2 -3
  608. package/src/providers/minimax/client.ts +106 -0
  609. package/src/providers/model-catalog.ts +78 -1
  610. package/src/providers/model-intents.ts +4 -4
  611. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  612. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
  613. package/src/providers/openai/chat-completions-provider.ts +116 -15
  614. package/src/providers/openai/codex-models.ts +20 -0
  615. package/src/providers/openai/responses-provider.ts +87 -30
  616. package/src/providers/openrouter/client.ts +13 -8
  617. package/src/providers/provider-send-message.ts +20 -5
  618. package/src/providers/registry.ts +48 -8
  619. package/src/providers/retry.ts +50 -7
  620. package/src/providers/search-provider-catalog.ts +17 -9
  621. package/src/providers/thinking-config.ts +26 -1
  622. package/src/providers/types.ts +9 -0
  623. package/src/providers/usage-tracking.ts +2 -0
  624. package/src/runtime/AGENTS.md +2 -2
  625. package/src/runtime/__tests__/agent-wake.test.ts +1 -0
  626. package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
  627. package/src/runtime/access-request-helper.ts +1 -0
  628. package/src/runtime/agent-wake.ts +1 -0
  629. package/src/runtime/assistant-event-hub.ts +76 -6
  630. package/src/runtime/auth/route-policy.ts +46 -0
  631. package/src/runtime/btw-sidechain.ts +0 -6
  632. package/src/runtime/channel-readiness-service.ts +68 -0
  633. package/src/runtime/channel-reply-delivery.ts +23 -0
  634. package/src/runtime/channel-retry-sweep.ts +47 -14
  635. package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
  636. package/src/runtime/http-types.ts +0 -2
  637. package/src/runtime/migrations/vbundle-builder.ts +12 -4
  638. package/src/runtime/pending-interactions.ts +0 -1
  639. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
  640. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
  641. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +204 -0
  642. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  643. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
  644. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
  645. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +76 -9
  646. package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
  647. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  648. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
  649. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
  650. package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
  651. package/src/runtime/routes/acp-routes-list.test.ts +3 -0
  652. package/src/runtime/routes/acp-routes.test.ts +255 -6
  653. package/src/runtime/routes/acp-routes.ts +8 -1
  654. package/src/runtime/routes/app-management-routes.ts +111 -4
  655. package/src/runtime/routes/avatar-routes.ts +10 -10
  656. package/src/runtime/routes/background-wake-routes.ts +356 -0
  657. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  658. package/src/runtime/routes/btw-routes.ts +4 -10
  659. package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
  660. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  661. package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
  662. package/src/runtime/routes/conversation-list-routes.ts +159 -4
  663. package/src/runtime/routes/conversation-management-routes.ts +108 -26
  664. package/src/runtime/routes/conversation-query-routes.ts +200 -44
  665. package/src/runtime/routes/conversation-routes.ts +409 -521
  666. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  667. package/src/runtime/routes/conversations-import-routes.ts +19 -6
  668. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  669. package/src/runtime/routes/documents-routes.ts +10 -1
  670. package/src/runtime/routes/domain-routes.ts +60 -10
  671. package/src/runtime/routes/email-routes.ts +5 -2
  672. package/src/runtime/routes/events-routes.ts +54 -10
  673. package/src/runtime/routes/group-routes.ts +35 -8
  674. package/src/runtime/routes/home-feed-routes.ts +129 -0
  675. package/src/runtime/routes/host-browser-routes.ts +10 -2
  676. package/src/runtime/routes/host-cu-routes.ts +2 -2
  677. package/src/runtime/routes/identity-intro-cache.ts +61 -16
  678. package/src/runtime/routes/identity-routes.ts +30 -9
  679. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  680. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
  681. package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
  682. package/src/runtime/routes/index.ts +10 -0
  683. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  684. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  685. package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
  686. package/src/runtime/routes/integrations/vercel.ts +15 -0
  687. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  688. package/src/runtime/routes/llm-context-normalization.ts +7 -2
  689. package/src/runtime/routes/memory-item-routes.ts +8 -3
  690. package/src/runtime/routes/memory-v2-routes.ts +215 -5
  691. package/src/runtime/routes/memory-v3-routes.ts +474 -0
  692. package/src/runtime/routes/migration-routes.ts +32 -28
  693. package/src/runtime/routes/notification-routes.ts +63 -1
  694. package/src/runtime/routes/oauth-commands-routes.ts +6 -1
  695. package/src/runtime/routes/plugins-routes.ts +337 -0
  696. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  697. package/src/runtime/routes/secret-routes.ts +25 -5
  698. package/src/runtime/routes/settings-routes.ts +12 -11
  699. package/src/runtime/routes/slack-channel-routes.ts +5 -4
  700. package/src/runtime/routes/surface-action-routes.ts +1 -38
  701. package/src/runtime/routes/surface-content-routes.ts +12 -5
  702. package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
  703. package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
  704. package/src/runtime/routes/workspace-routes.ts +25 -10
  705. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
  706. package/src/runtime/slack-dm-text-delivery.ts +177 -0
  707. package/src/runtime/sync/resource-sync-events.ts +106 -38
  708. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  709. package/src/runtime/sync/sync-publisher.ts +2 -1
  710. package/src/runtime/tool-grant-request-helper.ts +1 -0
  711. package/src/runtime/verification-outbound-actions.ts +73 -1
  712. package/src/schedule/schedule-store.ts +8 -1
  713. package/src/schedule/scheduler.ts +111 -15
  714. package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
  715. package/src/security/encrypted-store.ts +7 -16
  716. package/src/security/store-path-override.ts +61 -0
  717. package/src/signals/user-message.ts +5 -8
  718. package/src/skills/validate-input.ts +177 -0
  719. package/src/subagent/manager.ts +13 -13
  720. package/src/subagent/types.ts +6 -0
  721. package/src/tasks/tool-sanitizer.ts +2 -2
  722. package/src/telemetry/types.ts +12 -0
  723. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  724. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  725. package/src/tools/acp/spawn.test.ts +119 -0
  726. package/src/tools/acp/spawn.ts +15 -2
  727. package/src/tools/apps/definitions.ts +36 -28
  728. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  729. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  730. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
  731. package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
  732. package/src/tools/browser/browser-execution.ts +16 -3
  733. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  734. package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
  735. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
  736. package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
  737. package/src/tools/browser/cdp-client/factory.ts +100 -17
  738. package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
  739. package/src/tools/browser/cdp-client/types.ts +65 -0
  740. package/src/tools/browser/pinned-tabs.ts +96 -40
  741. package/src/tools/computer-use/definitions.ts +282 -336
  742. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  743. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  744. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  745. package/src/tools/credentials/vault.ts +3 -9
  746. package/src/tools/document/document-tool.ts +189 -7
  747. package/src/tools/execution-target.ts +18 -23
  748. package/src/tools/executor.ts +24 -56
  749. package/src/tools/filesystem/edit.ts +3 -9
  750. package/src/tools/filesystem/list.ts +3 -9
  751. package/src/tools/filesystem/read.ts +3 -9
  752. package/src/tools/filesystem/write.ts +3 -9
  753. package/src/tools/host-filesystem/edit.test.ts +1 -0
  754. package/src/tools/host-filesystem/edit.ts +3 -9
  755. package/src/tools/host-filesystem/read.test.ts +1 -0
  756. package/src/tools/host-filesystem/read.ts +3 -9
  757. package/src/tools/host-filesystem/transfer.test.ts +31 -6
  758. package/src/tools/host-filesystem/transfer.ts +3 -9
  759. package/src/tools/host-filesystem/write.test.ts +1 -0
  760. package/src/tools/host-filesystem/write.ts +3 -9
  761. package/src/tools/host-terminal/host-shell.ts +3 -9
  762. package/src/tools/mcp/mcp-tool-factory.ts +1 -10
  763. package/src/tools/memory/register.test.ts +1 -1
  764. package/src/tools/memory/register.ts +4 -9
  765. package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
  766. package/src/tools/network/__tests__/web-search.test.ts +211 -3
  767. package/src/tools/network/managed-search-proxy.ts +183 -0
  768. package/src/tools/network/web-fetch.ts +3 -9
  769. package/src/tools/network/web-search.ts +224 -76
  770. package/src/tools/policy-context.ts +3 -1
  771. package/src/tools/registry.ts +150 -123
  772. package/src/tools/schedule/create.ts +1 -1
  773. package/src/tools/schema-transforms.ts +1 -1
  774. package/src/tools/skills/execute.ts +3 -9
  775. package/src/tools/skills/load.ts +3 -9
  776. package/src/tools/skills/skill-tool-factory.ts +18 -44
  777. package/src/tools/subagent/notify-parent.ts +3 -9
  778. package/src/tools/subagent/spawn.ts +3 -0
  779. package/src/tools/system/request-permission.ts +3 -9
  780. package/src/tools/terminal/shell.ts +3 -9
  781. package/src/tools/tool-approval-handler.ts +10 -4
  782. package/src/tools/tool-defaults.ts +94 -0
  783. package/src/tools/tool-name-aliases.ts +72 -14
  784. package/src/tools/types.ts +32 -101
  785. package/src/tools/ui-surface/definitions.ts +104 -108
  786. package/src/types/onboarding-context.ts +6 -0
  787. package/src/usage/attribution.ts +32 -1
  788. package/src/usage/pricing.ts +23 -0
  789. package/src/usage/types.ts +12 -0
  790. package/src/util/browser.ts +7 -2
  791. package/src/util/logger.ts +16 -7
  792. package/src/util/platform.ts +7 -2
  793. package/src/util/sqlite3-runtime.ts +65 -0
  794. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  795. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  796. package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
  797. package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
  798. package/src/workspace/migrations/registry.ts +6 -0
  799. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  800. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  801. package/src/daemon/query-complexity-router.ts +0 -75
  802. package/src/prompts/cache-boundary.ts +0 -8
@@ -32,6 +32,7 @@ mock.module("../memory/conversation-crud.js", () => ({
32
32
  updateMessageContent: () => {},
33
33
  relinkAttachments: () => 0,
34
34
  deleteLastExchange: () => 0,
35
+ reserveMessage: mock(async () => ({ id: "msg-reserve" })),
35
36
  }));
36
37
 
37
38
  mock.module("../memory/conversation-queries.js", () => ({
@@ -1,7 +1,6 @@
1
1
  import { afterAll, beforeEach, describe, expect, test } from "bun:test";
2
2
 
3
3
  import { RiskLevel } from "../permissions/types.js";
4
- import type { ToolDefinition } from "../providers/types.js";
5
4
  import {
6
5
  __clearRegistryForTesting,
7
6
  __resetRegistryForTesting,
@@ -10,6 +9,7 @@ import {
10
9
  getSkillRefCount,
11
10
  getSkillToolNames,
12
11
  getTool,
12
+ getToolOwner,
13
13
  initializeTools,
14
14
  registerSkillTools,
15
15
  registerTool,
@@ -30,13 +30,8 @@ function makeFakeTool(name: string): Tool {
30
30
  description: `Fake ${name}`,
31
31
  category: "test",
32
32
  defaultRiskLevel: RiskLevel.Low,
33
- getDefinition(): ToolDefinition {
34
- return {
35
- name,
36
- description: `Fake ${name}`,
37
- input_schema: { type: "object", properties: {}, required: [] },
38
- };
39
- },
33
+ executionTarget: "sandbox",
34
+ input_schema: { type: "object", properties: {}, required: [] },
40
35
  async execute(
41
36
  _input: Record<string, unknown>,
42
37
  _context: ToolContext,
@@ -46,12 +41,11 @@ function makeFakeTool(name: string): Tool {
46
41
  };
47
42
  }
48
43
 
49
- function makeSkillTool(name: string, ownerSkillId: string): Tool {
50
- return {
51
- ...makeFakeTool(name),
52
- origin: "skill" as const,
53
- ownerSkillId,
54
- };
44
+ function makeSkillTool(name: string): Tool {
45
+ // Ownership is recorded by the registry (via `registerSkillTools`), not by
46
+ // any field on the Tool itself. This helper is now a thin alias for
47
+ // makeFakeTool; the wrapper is kept so call sites stay readable.
48
+ return makeFakeTool(name);
55
49
  }
56
50
 
57
51
  describe("tool registry host tools", () => {
@@ -201,11 +195,11 @@ describe("baseline characterization: core app tool surface", () => {
201
195
 
202
196
  const tool = getTool("app_open");
203
197
  expect(tool).toBeDefined();
204
- expect(tool?.executionMode).toBe("proxy");
205
198
 
206
- // Proxy tools are excluded from getAllToolDefinitions() by design
199
+ // app_open is core-owned (no skill owner) so it flows through
200
+ // `getAllToolDefinitions()` like any other core tool.
207
201
  const definitionNames = getAllToolDefinitions().map((def) => def.name);
208
- expect(definitionNames).not.toContain("app_open");
202
+ expect(definitionNames).toContain("app_open");
209
203
  });
210
204
 
211
205
  test("bundled app-builder skill has TOOLS.json manifest", async () => {
@@ -223,33 +217,27 @@ describe("baseline characterization: core app tool surface", () => {
223
217
  });
224
218
  });
225
219
 
226
- describe("tool origin metadata", () => {
220
+ describe("tool ownership metadata", () => {
227
221
  beforeEach(() => {
228
222
  __resetRegistryForTesting();
229
223
  });
230
224
 
231
- test("registers a skill-origin tool and preserves metadata via getTool()", () => {
232
- const skillTool: Tool = {
233
- ...makeFakeTool("test-skill-origin-tool"),
234
- origin: "skill",
235
- ownerSkillId: "test-skill",
236
- };
225
+ test("registerTool does not record ownership (bare-install path)", () => {
226
+ registerTool(makeFakeTool("test-bare-tool"));
237
227
 
238
- registerTool(skillTool);
239
-
240
- const retrieved = getTool("test-skill-origin-tool");
241
- expect(retrieved).toBeDefined();
242
- expect(retrieved?.origin).toBe("skill");
243
- expect(retrieved?.ownerSkillId).toBe("test-skill");
228
+ expect(getTool("test-bare-tool")).toBeDefined();
229
+ // `registerTool` is the bare-install path used by tests + core
230
+ // bootstraps; it does not record ownership. Tools that need an owner
231
+ // must go through `registerSkillTools(skillId, ...)` or its sibling
232
+ // entry points so the registry populates `ownersByName`.
233
+ expect(getToolOwner("test-bare-tool")).toBeUndefined();
244
234
  });
245
235
 
246
- test("core tools default to no origin metadata (undefined)", async () => {
236
+ test("core tools have no owner", async () => {
247
237
  await initializeTools();
248
238
 
249
- const coreTool = getTool("host_file_read");
250
- expect(coreTool).toBeDefined();
251
- expect(coreTool?.origin).toBeUndefined();
252
- expect(coreTool?.ownerSkillId).toBeUndefined();
239
+ expect(getTool("host_file_read")).toBeDefined();
240
+ expect(getToolOwner("host_file_read")).toBeUndefined();
253
241
  });
254
242
  });
255
243
 
@@ -258,66 +246,67 @@ describe("dynamic skill tool registry", () => {
258
246
  __resetRegistryForTesting();
259
247
  });
260
248
 
261
- test("registers skill tools and retrieves them", () => {
262
- const tools = [
263
- makeSkillTool("sk_tool_a", "my-skill"),
264
- makeSkillTool("sk_tool_b", "my-skill"),
265
- ];
266
- registerSkillTools(tools);
249
+ test("registers skill tools and retrieves them with owner via getToolOwner", () => {
250
+ registerSkillTools("my-skill", [
251
+ makeSkillTool("sk_tool_a"),
252
+ makeSkillTool("sk_tool_b"),
253
+ ]);
267
254
 
268
255
  expect(getTool("sk_tool_a")).toBeDefined();
269
- expect(getTool("sk_tool_a")?.origin).toBe("skill");
270
- expect(getTool("sk_tool_a")?.ownerSkillId).toBe("my-skill");
256
+ expect(getToolOwner("sk_tool_a")).toEqual({
257
+ kind: "skill",
258
+ id: "my-skill",
259
+ });
271
260
 
272
261
  expect(getTool("sk_tool_b")).toBeDefined();
273
- expect(getTool("sk_tool_b")?.origin).toBe("skill");
262
+ expect(getToolOwner("sk_tool_b")).toEqual({
263
+ kind: "skill",
264
+ id: "my-skill",
265
+ });
274
266
  });
275
267
 
276
268
  test("skips skill tool that collides with a core tool without throwing", async () => {
277
269
  await initializeTools();
278
270
 
279
271
  // host_file_read is a core tool registered during init
280
- const colliding = makeSkillTool("host_file_read", "rogue-skill");
281
- const accepted = registerSkillTools([colliding]);
272
+ const accepted = registerSkillTools("rogue-skill", [
273
+ makeSkillTool("host_file_read"),
274
+ ]);
282
275
 
283
276
  // The colliding tool should be silently skipped
284
277
  expect(accepted).toHaveLength(0);
285
278
  // The core tool should still be in place (not overwritten)
286
- const retrieved = getTool("host_file_read");
287
- expect(retrieved?.origin).toBeUndefined(); // core tools have no origin
279
+ expect(getTool("host_file_read")).toBeDefined();
280
+ expect(getToolOwner("host_file_read")).toBeUndefined();
288
281
  });
289
282
 
290
283
  test("allows replacement within the same owning skill", () => {
291
- const original = makeSkillTool("sk_replaceable", "owner-skill");
292
- registerSkillTools([original]);
284
+ registerSkillTools("owner-skill", [makeSkillTool("sk_replaceable")]);
293
285
 
294
286
  const replacement: Tool = {
295
- ...makeSkillTool("sk_replaceable", "owner-skill"),
287
+ ...makeSkillTool("sk_replaceable"),
296
288
  description: "Updated description",
297
289
  };
298
290
  // Should not throw
299
- registerSkillTools([replacement]);
291
+ registerSkillTools("owner-skill", [replacement]);
300
292
 
301
293
  const retrieved = getTool("sk_replaceable");
302
294
  expect(retrieved?.description).toBe("Updated description");
303
295
  });
304
296
 
305
297
  test("rejects replacement from a different owning skill", () => {
306
- const original = makeSkillTool("sk_owned", "skill-alpha");
307
- registerSkillTools([original]);
298
+ registerSkillTools("skill-alpha", [makeSkillTool("sk_owned")]);
308
299
 
309
- const intruder = makeSkillTool("sk_owned", "skill-beta");
310
- expect(() => registerSkillTools([intruder])).toThrow(
311
- 'already registered by skill "skill-alpha"',
312
- );
300
+ expect(() =>
301
+ registerSkillTools("skill-beta", [makeSkillTool("sk_owned")]),
302
+ ).toThrow('already registered by skill "skill-alpha"');
313
303
  });
314
304
 
315
305
  test("unregisterSkillTools removes all tools for a skill", () => {
316
- const tools = [
317
- makeSkillTool("sk_rm_1", "removable-skill"),
318
- makeSkillTool("sk_rm_2", "removable-skill"),
319
- ];
320
- registerSkillTools(tools);
306
+ registerSkillTools("removable-skill", [
307
+ makeSkillTool("sk_rm_1"),
308
+ makeSkillTool("sk_rm_2"),
309
+ ]);
321
310
  expect(getTool("sk_rm_1")).toBeDefined();
322
311
  expect(getTool("sk_rm_2")).toBeDefined();
323
312
 
@@ -325,24 +314,32 @@ describe("dynamic skill tool registry", () => {
325
314
 
326
315
  expect(getTool("sk_rm_1")).toBeUndefined();
327
316
  expect(getTool("sk_rm_2")).toBeUndefined();
317
+ // Ownership map is cleared in lockstep with the tools map.
318
+ expect(getToolOwner("sk_rm_1")).toBeUndefined();
319
+ expect(getToolOwner("sk_rm_2")).toBeUndefined();
328
320
  });
329
321
 
330
322
  test("unregisterSkillTools does not affect tools from other skills", () => {
331
- registerSkillTools([makeSkillTool("sk_keep", "keep-skill")]);
332
- registerSkillTools([makeSkillTool("sk_remove", "nuke-skill")]);
323
+ registerSkillTools("keep-skill", [makeSkillTool("sk_keep")]);
324
+ registerSkillTools("nuke-skill", [makeSkillTool("sk_remove")]);
333
325
 
334
326
  unregisterSkillTools("nuke-skill");
335
327
 
336
328
  expect(getTool("sk_keep")).toBeDefined();
337
329
  expect(getTool("sk_remove")).toBeUndefined();
330
+ expect(getToolOwner("sk_keep")).toEqual({
331
+ kind: "skill",
332
+ id: "keep-skill",
333
+ });
334
+ expect(getToolOwner("sk_remove")).toBeUndefined();
338
335
  });
339
336
 
340
337
  test("getSkillToolNames returns only skill tool names", async () => {
341
338
  await initializeTools();
342
339
 
343
- registerSkillTools([
344
- makeSkillTool("sk_names_a", "names-skill"),
345
- makeSkillTool("sk_names_b", "names-skill"),
340
+ registerSkillTools("names-skill", [
341
+ makeSkillTool("sk_names_a"),
342
+ makeSkillTool("sk_names_b"),
346
343
  ]);
347
344
 
348
345
  const skillNames = getSkillToolNames();
@@ -356,19 +353,22 @@ describe("dynamic skill tool registry", () => {
356
353
  test("registerSkillTools skips core-colliding tools but registers the rest", async () => {
357
354
  await initializeTools();
358
355
 
359
- const tools = [
360
- makeSkillTool("sk_atomic_ok", "atomic-skill"),
361
- makeSkillTool("host_file_read", "atomic-skill"), // collides with core
362
- ];
363
-
364
- const accepted = registerSkillTools(tools);
356
+ const accepted = registerSkillTools("atomic-skill", [
357
+ makeSkillTool("sk_atomic_ok"),
358
+ makeSkillTool("host_file_read"), // collides with core
359
+ ]);
365
360
  // Only the non-colliding tool should be accepted
366
361
  expect(accepted).toHaveLength(1);
367
362
  expect(accepted[0].name).toBe("sk_atomic_ok");
368
- // The non-colliding tool should be registered
363
+ // The non-colliding tool should be registered with the correct owner
369
364
  expect(getTool("sk_atomic_ok")).toBeDefined();
370
- // The core tool should be untouched
371
- expect(getTool("host_file_read")?.origin).toBeUndefined();
365
+ expect(getToolOwner("sk_atomic_ok")).toEqual({
366
+ kind: "skill",
367
+ id: "atomic-skill",
368
+ });
369
+ // The core tool should be untouched (no owner recorded)
370
+ expect(getTool("host_file_read")).toBeDefined();
371
+ expect(getToolOwner("host_file_read")).toBeUndefined();
372
372
  });
373
373
  });
374
374
 
@@ -378,17 +378,17 @@ describe("skill tool reference counting", () => {
378
378
  });
379
379
 
380
380
  test("ref count increments on each registerSkillTools call", () => {
381
- registerSkillTools([makeSkillTool("rc_a", "rc-skill")]);
381
+ registerSkillTools("rc-skill", [makeSkillTool("rc_a")]);
382
382
  expect(getSkillRefCount("rc-skill")).toBe(1);
383
383
 
384
- // Second session registers the same skill (same ownerSkillId allows replacement)
385
- registerSkillTools([makeSkillTool("rc_a", "rc-skill")]);
384
+ // Second session registers the same skill (same owner id allows replacement)
385
+ registerSkillTools("rc-skill", [makeSkillTool("rc_a")]);
386
386
  expect(getSkillRefCount("rc-skill")).toBe(2);
387
387
  });
388
388
 
389
389
  test("unregister decrements ref count but keeps tools when count > 0", () => {
390
- registerSkillTools([makeSkillTool("rc_keep", "rc-multi")]);
391
- registerSkillTools([makeSkillTool("rc_keep", "rc-multi")]);
390
+ registerSkillTools("rc-multi", [makeSkillTool("rc_keep")]);
391
+ registerSkillTools("rc-multi", [makeSkillTool("rc_keep")]);
392
392
  expect(getSkillRefCount("rc-multi")).toBe(2);
393
393
 
394
394
  unregisterSkillTools("rc-multi");
@@ -398,8 +398,8 @@ describe("skill tool reference counting", () => {
398
398
  });
399
399
 
400
400
  test("tools are removed only when last reference is unregistered", () => {
401
- registerSkillTools([makeSkillTool("rc_last", "rc-final")]);
402
- registerSkillTools([makeSkillTool("rc_last", "rc-final")]);
401
+ registerSkillTools("rc-final", [makeSkillTool("rc_last")]);
402
+ registerSkillTools("rc-final", [makeSkillTool("rc_last")]);
403
403
 
404
404
  unregisterSkillTools("rc-final");
405
405
  expect(getTool("rc_last")).toBeDefined();
@@ -225,7 +225,7 @@ import {
225
225
  createVerificationSession,
226
226
  } from "../memory/channel-verification-sessions.js";
227
227
  import { addMessage, getMessages } from "../memory/conversation-crud.js";
228
- import { getDb, resetDb } from "../memory/db-connection.js";
228
+ import { getDb } from "../memory/db-connection.js";
229
229
  import { initializeDb } from "../memory/db-init.js";
230
230
  import { createInvite } from "../memory/invite-store.js";
231
231
  import { resetTestTables } from "../memory/raw-query.js";
@@ -235,12 +235,13 @@ import {
235
235
  getGuardianBinding,
236
236
  } from "../runtime/channel-verification-service.js";
237
237
  import { generateVoiceCode, hashVoiceCode } from "../util/voice-code.js";
238
+ import { resetDbForTesting } from "./db-test-helpers.js";
238
239
  import { createGuardianBinding } from "./helpers/create-guardian-binding.js";
239
240
 
240
241
  initializeDb();
241
242
 
242
243
  afterAll(() => {
243
- resetDb();
244
+ resetDbForTesting();
244
245
  });
245
246
 
246
247
  // ── Mock WebSocket factory ──────────────────────────────────────────
@@ -423,16 +424,15 @@ describe("relay-server", () => {
423
424
  includeDefaultFallback: false,
424
425
  },
425
426
  isProcessing: () => false,
426
- persistUserMessage: async (
427
- content: string,
428
- _attachments: unknown[],
429
- requestId?: string,
430
- ) => {
431
- session.currentRequestId = requestId;
427
+ persistUserMessage: async (options: {
428
+ content: string;
429
+ requestId?: string;
430
+ }) => {
431
+ session.currentRequestId = options.requestId;
432
432
  const message = await addMessage(
433
433
  conversationId,
434
434
  "user",
435
- JSON.stringify([{ type: "text", text: content }]),
435
+ JSON.stringify([{ type: "text", text: options.content }]),
436
436
  {
437
437
  userMessageChannel: "phone",
438
438
  assistantMessageChannel: "phone",
@@ -440,7 +440,7 @@ describe("relay-server", () => {
440
440
  assistantMessageInterface: "phone",
441
441
  },
442
442
  );
443
- return message.id;
443
+ return { id: message.id, deduplicated: false };
444
444
  },
445
445
  setChannelCapabilities: () => {},
446
446
  setAssistantId: () => {},
@@ -103,7 +103,7 @@ mock.module("../permissions/checker.js", () => ({
103
103
  mock.module("../memory/tool-usage-store.js", () => ({
104
104
  recordToolInvocation: () => {},
105
105
  getRecentInvocations: () => [],
106
- rotateToolInvocations: () => 0,
106
+ rotateToolInvocations: async () => 0,
107
107
  }));
108
108
 
109
109
  mock.module("../tools/registry.js", () => ({
@@ -116,7 +116,7 @@ mock.module("../tools/registry.js", () => ({
116
116
  category: isGmailTool ? "gmail" : "credential-execution",
117
117
  defaultRiskLevel: "high",
118
118
  executionTarget: isGmailTool ? ("host" as const) : undefined,
119
- getDefinition: () => ({}),
119
+ input_schema: {},
120
120
  execute: async () => fakeToolResult,
121
121
  };
122
122
  },
@@ -51,17 +51,18 @@ import {
51
51
  } from "../memory/attachments-store.js";
52
52
  import * as conversationStore from "../memory/conversation-crud.js";
53
53
  import { getOrCreateConversation } from "../memory/conversation-key-store.js";
54
- import { getDb, resetDb } from "../memory/db-connection.js";
54
+ import { getDb } from "../memory/db-connection.js";
55
55
  import { initializeDb } from "../memory/db-init.js";
56
56
  import * as deliveryChannels from "../memory/delivery-channels.js";
57
57
  import { resetTestTables } from "../memory/raw-query.js";
58
58
  import { RuntimeHttpServer } from "../runtime/http-server.js";
59
59
  import * as pendingInteractions from "../runtime/pending-interactions.js";
60
+ import { resetDbForTesting } from "./db-test-helpers.js";
60
61
 
61
62
  initializeDb();
62
63
 
63
64
  afterAll(() => {
64
- resetDb();
65
+ resetDbForTesting();
65
66
  });
66
67
 
67
68
  const TEST_TOKEN = "test-bearer-token-attach";
@@ -0,0 +1,154 @@
1
+ /**
2
+ * `GET /v1/events` (`handleSubscribeAssistantEvents`) — bilingual scope
3
+ * resolution. Two query params are accepted, with distinct semantics:
4
+ *
5
+ * - `?conversationId=<internal-id>` — looks up the conversation row
6
+ * directly by its assistant-minted id. 404 if not found. Does NOT
7
+ * materialise a new row.
8
+ * - `?conversationKey=<external-key>` — resolves via the
9
+ * `conversation_keys` table; materialises on first use. Ignored when
10
+ * `conversationId` is also supplied.
11
+ *
12
+ * Companion to `runtime-events-sse.test.ts`, which exercises the broader
13
+ * `?conversationKey=` happy/error path.
14
+ */
15
+
16
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
17
+
18
+ mock.module("../util/logger.js", () => ({
19
+ getLogger: () =>
20
+ new Proxy({} as Record<string, unknown>, {
21
+ get: () => () => {},
22
+ }),
23
+ }));
24
+
25
+ mock.module("../config/loader.js", () => ({
26
+ getConfig: () => ({
27
+ ui: {},
28
+ model: "test",
29
+ provider: "test",
30
+ memory: { enabled: false },
31
+ rateLimit: { maxRequestsPerMinute: 0 },
32
+ secretDetection: { enabled: false },
33
+ }),
34
+ }));
35
+
36
+ import { getOrCreateConversation } from "../memory/conversation-key-store.js";
37
+ import { getDb } from "../memory/db-connection.js";
38
+ import { initializeDb } from "../memory/db-init.js";
39
+ import { buildAssistantEvent } from "../runtime/assistant-event.js";
40
+ import { AssistantEventHub } from "../runtime/assistant-event-hub.js";
41
+ import {
42
+ BadRequestError,
43
+ NotFoundError,
44
+ } from "../runtime/routes/errors.js";
45
+ import { handleSubscribeAssistantEvents } from "../runtime/routes/events-routes.js";
46
+
47
+ initializeDb();
48
+
49
+ describe("GET /v1/events — bilingual scope query params", () => {
50
+ beforeEach(() => {
51
+ const db = getDb();
52
+ db.run("DELETE FROM conversation_keys");
53
+ db.run("DELETE FROM conversations");
54
+ });
55
+
56
+ test("?conversationId=<existing-id> scopes the stream to that conversation", async () => {
57
+ // Materialise a conversation via the key path, then subscribe to it
58
+ // directly by its internal id.
59
+ const { conversationId } = getOrCreateConversation("sse-id-scope-source");
60
+
61
+ const ac = new AbortController();
62
+ const testHub = new AssistantEventHub();
63
+
64
+ const stream = handleSubscribeAssistantEvents(
65
+ {
66
+ queryParams: { conversationId },
67
+ abortSignal: ac.signal,
68
+ },
69
+ { hub: testHub },
70
+ );
71
+
72
+ const reader = stream.getReader();
73
+ // Consume the initial heartbeat.
74
+ const heartbeat = await reader.read();
75
+ expect(new TextDecoder().decode(heartbeat.value)).toBe(": heartbeat\n\n");
76
+
77
+ // Publish an event scoped to that conversation — should be delivered.
78
+ await testHub.publish(buildAssistantEvent({ type: "pong" }, conversationId));
79
+
80
+ const { value, done } = await reader.read();
81
+ ac.abort();
82
+
83
+ expect(done).toBe(false);
84
+ const frame = new TextDecoder().decode(value);
85
+ expect(frame).toContain("event: assistant_event");
86
+ expect(frame).toContain(`"conversationId":"${conversationId}"`);
87
+ });
88
+
89
+ test("?conversationId=<non-existent-id> throws NotFoundError", () => {
90
+ expect(() =>
91
+ handleSubscribeAssistantEvents({
92
+ queryParams: { conversationId: "does-not-exist" },
93
+ abortSignal: new AbortController().signal,
94
+ }),
95
+ ).toThrow(NotFoundError);
96
+ });
97
+
98
+ test("?conversationId is honored and ?conversationKey is ignored when both are present", async () => {
99
+ // Materialise two distinct conversations: one we'll subscribe to by id,
100
+ // one we'll publish to via the ignored key.
101
+ const { conversationId: idConv } = getOrCreateConversation("sse-id-wins");
102
+ const { conversationId: keyConv } = getOrCreateConversation(
103
+ "sse-key-ignored",
104
+ );
105
+ expect(idConv).not.toBe(keyConv);
106
+
107
+ const ac = new AbortController();
108
+ const testHub = new AssistantEventHub();
109
+
110
+ const stream = handleSubscribeAssistantEvents(
111
+ {
112
+ queryParams: {
113
+ conversationId: idConv,
114
+ conversationKey: "sse-key-ignored",
115
+ },
116
+ abortSignal: ac.signal,
117
+ },
118
+ { hub: testHub },
119
+ );
120
+ const reader = stream.getReader();
121
+ await reader.read(); // heartbeat
122
+
123
+ // Publish on the "key" conversation — should NOT be delivered (filter
124
+ // is locked to idConv because conversationId wins).
125
+ await testHub.publish(buildAssistantEvent({ type: "pong" }, keyConv));
126
+ // Publish on the "id" conversation — should be delivered.
127
+ await testHub.publish(buildAssistantEvent({ type: "pong" }, idConv));
128
+
129
+ const { value } = await reader.read();
130
+ ac.abort();
131
+ const frame = new TextDecoder().decode(value);
132
+
133
+ expect(frame).toContain(`"conversationId":"${idConv}"`);
134
+ expect(frame).not.toContain(`"conversationId":"${keyConv}"`);
135
+ });
136
+
137
+ test("empty conversationId is rejected with BadRequestError", () => {
138
+ expect(() =>
139
+ handleSubscribeAssistantEvents({
140
+ queryParams: { conversationId: "" },
141
+ abortSignal: new AbortController().signal,
142
+ }),
143
+ ).toThrow(BadRequestError);
144
+ });
145
+
146
+ test("empty conversationKey is still rejected (legacy parity)", () => {
147
+ expect(() =>
148
+ handleSubscribeAssistantEvents({
149
+ queryParams: { conversationKey: "" },
150
+ abortSignal: new AbortController().signal,
151
+ }),
152
+ ).toThrow(BadRequestError);
153
+ });
154
+ });
@@ -9,6 +9,17 @@ mock.module("../util/logger.js", () => ({
9
9
  truncateForLog: (value: string) => value,
10
10
  }));
11
11
 
12
+ // Stub the background-wake publisher so these store-level unit tests stay
13
+ // hermetic. `notifySchedulesChanged()` fires a debounced background-wake
14
+ // refresh on every mutation; left real, that 250ms timer performs a
15
+ // synchronous DB read plus a platform-client lookup which compete with the
16
+ // serialized async event delivery and can push a `sync_changed` past the
17
+ // wait deadline on loaded runners. Background-wake behavior is covered by the
18
+ // background-wake tests.
19
+ mock.module("../background-wake/publisher.js", () => ({
20
+ refreshBackgroundWakeIntent: () => {},
21
+ }));
22
+
12
23
  import { SYNC_TAGS } from "../daemon/message-types/sync.js";
13
24
  import { getDb } from "../memory/db-connection.js";
14
25
  import { initializeDb } from "../memory/db-init.js";
@@ -38,7 +49,11 @@ function getRawDb(): import("bun:sqlite").Database {
38
49
  }
39
50
 
40
51
  async function waitFor(predicate: () => boolean): Promise<void> {
41
- const deadline = Date.now() + 500;
52
+ // Event delivery is async (serialized through the hub's broadcast chain),
53
+ // so poll until it lands. The deadline is generous to absorb scheduling
54
+ // jitter on loaded CI runners — the happy path returns the moment the
55
+ // predicate holds, so a larger budget costs nothing when events flow.
56
+ const deadline = Date.now() + 2000;
42
57
  while (Date.now() < deadline) {
43
58
  if (predicate()) return;
44
59
  await new Promise((resolve) => setTimeout(resolve, 5));
@@ -210,12 +210,57 @@ describe("scheduler conversation reuse", () => {
210
210
  expect(runs2[0].conversationId).toBe(firstConversationId);
211
211
  });
212
212
 
213
+ test("recurring schedule defaults to reuseConversation=true", async () => {
214
+ /**
215
+ * When no explicit reuseConversation is provided, recurring schedules
216
+ * default to true — subsequent runs reuse the same conversation.
217
+ */
218
+
219
+ // GIVEN a recurring schedule with no explicit reuseConversation
220
+ const rruleExpr = buildEveryMinuteRrule();
221
+ const schedule = createSchedule({
222
+ name: "Default Reuse Test",
223
+ cronExpression: rruleExpr,
224
+ message: "Default reuse message",
225
+ syntax: "rrule",
226
+ expression: rruleExpr,
227
+ // no explicit reuseConversation — should default to true for recurring
228
+ });
229
+
230
+ // WHEN the schedule fires for the first time
231
+ forceScheduleDue(schedule.id);
232
+
233
+ const processMessage = async (conversationId: string, message: string) => {
234
+ processedMessages.push({ conversationId, message });
235
+ };
236
+
237
+ const scheduler1 = startScheduler(processMessage, () => {});
238
+ await new Promise((resolve) => setTimeout(resolve, 500));
239
+ scheduler1.stop();
240
+
241
+ expect(processedMessages).toHaveLength(1);
242
+ const firstConversationId = processedMessages[0].conversationId;
243
+ expect(firstConversationId).toBeTruthy();
244
+
245
+ // WHEN the schedule fires for the second time
246
+ forceScheduleDue(schedule.id);
247
+ processedMessages.length = 0;
248
+
249
+ const scheduler2 = startScheduler(processMessage, () => {});
250
+ await new Promise((resolve) => setTimeout(resolve, 500));
251
+ scheduler2.stop();
252
+
253
+ // THEN the same conversation is reused
254
+ expect(processedMessages).toHaveLength(1);
255
+ expect(processedMessages[0].conversationId).toBe(firstConversationId);
256
+ });
257
+
213
258
  test("recurring schedule with reuseConversation=false creates new conversation each run", async () => {
214
259
  /**
215
- * Default behavior: each run creates a brand-new conversation.
260
+ * When explicitly opted out, each run creates a brand-new conversation.
216
261
  */
217
262
 
218
- // GIVEN a recurring schedule with reuseConversation disabled (default)
263
+ // GIVEN a recurring schedule with reuseConversation explicitly disabled
219
264
  const rruleExpr = buildEveryMinuteRrule();
220
265
  const schedule = createSchedule({
221
266
  name: "No Reuse Test",
@@ -223,7 +268,7 @@ describe("scheduler conversation reuse", () => {
223
268
  message: "New conv each run",
224
269
  syntax: "rrule",
225
270
  expression: rruleExpr,
226
- // reuseConversation defaults to false
271
+ reuseConversation: false, // explicitly opt out of conversation reuse
227
272
  });
228
273
 
229
274
  // WHEN the schedule fires for the first time