@vellumai/assistant 0.8.5 → 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 (544) hide show
  1. package/AGENTS.md +33 -1
  2. package/ARCHITECTURE.md +1 -1
  3. package/bunfig.toml +6 -1
  4. package/docs/credential-execution-service.md +6 -6
  5. package/docs/plugins.md +4 -3
  6. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
  7. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
  8. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
  9. package/openapi.yaml +1900 -166
  10. package/package.json +1 -1
  11. package/src/__tests__/actor-token-service.test.ts +3 -2
  12. package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
  13. package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
  14. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
  15. package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
  16. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  17. package/src/__tests__/annotate-risk-options.test.ts +1 -0
  18. package/src/__tests__/approval-cascade.test.ts +1 -0
  19. package/src/__tests__/approval-routes-http.test.ts +9 -13
  20. package/src/__tests__/assert-not-live-db.ts +79 -0
  21. package/src/__tests__/assistant-feature-flags-integration.test.ts +9 -25
  22. package/src/__tests__/audit-log-rotation.test.ts +2 -2
  23. package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
  24. package/src/__tests__/background-workers-disk-pressure.test.ts +5 -8
  25. package/src/__tests__/browser-skill-endstate.test.ts +3 -3
  26. package/src/__tests__/btw-routes.test.ts +3 -2
  27. package/src/__tests__/call-controller.test.ts +3 -2
  28. package/src/__tests__/channel-approval-routes.test.ts +3 -2
  29. package/src/__tests__/channel-guardian.test.ts +3 -2
  30. package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
  31. package/src/__tests__/channel-reply-delivery.test.ts +35 -0
  32. package/src/__tests__/channel-retry-sweep.test.ts +320 -3
  33. package/src/__tests__/checker.test.ts +12 -12
  34. package/src/__tests__/compaction-events.test.ts +1 -0
  35. package/src/__tests__/compaction-trail-store.test.ts +264 -0
  36. package/src/__tests__/compactor-call-site-logging.test.ts +1 -0
  37. package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
  38. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +7 -5
  39. package/src/__tests__/computer-use-tools.test.ts +12 -14
  40. package/src/__tests__/config-loader-backfill.test.ts +13 -28
  41. package/src/__tests__/config-loader-corrupt.test.ts +5 -5
  42. package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
  43. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
  44. package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
  45. package/src/__tests__/config-schema.test.ts +10 -10
  46. package/src/__tests__/connection-model-compat.test.ts +83 -0
  47. package/src/__tests__/contacts-tools.test.ts +3 -2
  48. package/src/__tests__/context-token-estimator.test.ts +22 -0
  49. package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
  50. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
  51. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
  52. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  53. package/src/__tests__/conversation-agent-loop-overflow.test.ts +34 -0
  54. package/src/__tests__/conversation-agent-loop.test.ts +488 -2
  55. package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
  56. package/src/__tests__/conversation-app-control-instantiation.test.ts +29 -19
  57. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
  58. package/src/__tests__/conversation-attention-store.test.ts +101 -0
  59. package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
  60. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
  61. package/src/__tests__/conversation-error.test.ts +30 -0
  62. package/src/__tests__/conversation-fork-crud.test.ts +69 -8
  63. package/src/__tests__/conversation-fork-route.test.ts +3 -2
  64. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  65. package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
  66. package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
  67. package/src/__tests__/conversation-lifecycle.test.ts +1 -0
  68. package/src/__tests__/conversation-list-source.test.ts +3 -2
  69. package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
  70. package/src/__tests__/conversation-load-history-stripped.test.ts +1 -0
  71. package/src/__tests__/conversation-pairing.test.ts +53 -0
  72. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
  73. package/src/__tests__/conversation-process-callsite.test.ts +1 -0
  74. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -0
  75. package/src/__tests__/conversation-queue.test.ts +333 -291
  76. package/src/__tests__/conversation-routes-disk-view.test.ts +3 -18
  77. package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
  78. package/src/__tests__/conversation-routes-slash-commands.test.ts +33 -2
  79. package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
  80. package/src/__tests__/conversation-skill-tools.test.ts +38 -142
  81. package/src/__tests__/conversation-slash-queue.test.ts +84 -32
  82. package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
  83. package/src/__tests__/conversation-speed-override.test.ts +1 -0
  84. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
  85. package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
  86. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
  87. package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
  88. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
  89. package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
  90. package/src/__tests__/conversation-sync-tags.test.ts +128 -12
  91. package/src/__tests__/conversation-title-service.test.ts +1 -0
  92. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
  93. package/src/__tests__/conversation-usage.test.ts +1 -0
  94. package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
  95. package/src/__tests__/conversation-workspace-injection.test.ts +5 -0
  96. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -0
  97. package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
  98. package/src/__tests__/credential-broker-server-use.test.ts +5 -5
  99. package/src/__tests__/credential-execution-client.test.ts +72 -1
  100. package/src/__tests__/credential-execution-feature-gates.test.ts +10 -12
  101. package/src/__tests__/credential-health-service.test.ts +252 -3
  102. package/src/__tests__/credential-security-invariants.test.ts +5 -5
  103. package/src/__tests__/credential-vault-unit.test.ts +19 -19
  104. package/src/__tests__/credential-vault.test.ts +5 -5
  105. package/src/__tests__/cross-provider-web-search.test.ts +56 -2
  106. package/src/__tests__/db-connection-isolation.test.ts +7 -6
  107. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
  108. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
  109. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
  110. package/src/__tests__/db-test-helpers.ts +58 -0
  111. package/src/__tests__/disk-pressure-guard.test.ts +58 -41
  112. package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
  113. package/src/__tests__/disk-pressure-routes.test.ts +0 -33
  114. package/src/__tests__/disk-pressure-tools.test.ts +0 -4
  115. package/src/__tests__/dm-persistence.test.ts +26 -40
  116. package/src/__tests__/document-create-dedupe.test.ts +189 -0
  117. package/src/__tests__/document-find-replace.test.ts +3 -2
  118. package/src/__tests__/document-tool-security.test.ts +81 -2
  119. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
  120. package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
  121. package/src/__tests__/encrypted-store.test.ts +11 -9
  122. package/src/__tests__/feature-flag-test-helpers.ts +53 -0
  123. package/src/__tests__/filing-service.test.ts +1 -0
  124. package/src/__tests__/first-greeting.test.ts +62 -12
  125. package/src/__tests__/gateway-flag-listener.test.ts +0 -1
  126. package/src/__tests__/gemini-provider.test.ts +26 -0
  127. package/src/__tests__/guardian-action-sweep.test.ts +3 -2
  128. package/src/__tests__/guardian-outbound-http.test.ts +3 -2
  129. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
  130. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -0
  131. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  132. package/src/__tests__/heartbeat-service.test.ts +1 -0
  133. package/src/__tests__/helpers/mock-logger.ts +26 -0
  134. package/src/__tests__/host-bash-routes.test.ts +1 -0
  135. package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
  136. package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
  137. package/src/__tests__/host-shell-tool.test.ts +5 -4
  138. package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
  139. package/src/__tests__/http-conversation-lineage.test.ts +3 -2
  140. package/src/__tests__/http-user-message-parity.test.ts +29 -7
  141. package/src/__tests__/identity-intro-cache.test.ts +133 -22
  142. package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
  143. package/src/__tests__/inference-profile-reaper.test.ts +3 -2
  144. package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
  145. package/src/__tests__/injector-disk-pressure.test.ts +3 -17
  146. package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
  147. package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
  148. package/src/__tests__/llm-context-normalization.test.ts +42 -0
  149. package/src/__tests__/llm-resolver.test.ts +331 -0
  150. package/src/__tests__/llm-schema.test.ts +1 -1
  151. package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
  152. package/src/__tests__/mcp-abort-signal.test.ts +14 -0
  153. package/src/__tests__/mcp-client-auth.test.ts +14 -0
  154. package/src/__tests__/messaging-send-tool.test.ts +1 -0
  155. package/src/__tests__/migration-import-from-url.test.ts +3 -3
  156. package/src/__tests__/mock-gateway-ipc.ts +18 -2
  157. package/src/__tests__/model-intents.test.ts +3 -3
  158. package/src/__tests__/native-web-search.test.ts +30 -2
  159. package/src/__tests__/notification-deep-link.test.ts +62 -0
  160. package/src/__tests__/oauth-commands-routes.test.ts +37 -0
  161. package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
  162. package/src/__tests__/oauth-store.test.ts +3 -2
  163. package/src/__tests__/onboarding-template-contract.test.ts +3 -2
  164. package/src/__tests__/openai-provider.test.ts +8 -9
  165. package/src/__tests__/openai-responses-provider.test.ts +70 -10
  166. package/src/__tests__/openrouter-provider-only.test.ts +27 -5
  167. package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
  168. package/src/__tests__/persistence-pipeline.test.ts +139 -1
  169. package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
  170. package/src/__tests__/plugin-bootstrap.test.ts +9 -11
  171. package/src/__tests__/plugin-tool-contribution.test.ts +41 -38
  172. package/src/__tests__/process-message-background-slack.test.ts +21 -16
  173. package/src/__tests__/process-message-display-content.test.ts +19 -22
  174. package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
  175. package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
  176. package/src/__tests__/provider-registry-ollama.test.ts +45 -22
  177. package/src/__tests__/recording-handler.test.ts +1 -0
  178. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
  179. package/src/__tests__/registry.test.ts +82 -76
  180. package/src/__tests__/relay-server.test.ts +10 -10
  181. package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
  182. package/src/__tests__/schedule-store.test.ts +16 -1
  183. package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
  184. package/src/__tests__/secret-ingress-http.test.ts +5 -1
  185. package/src/__tests__/secure-keys.test.ts +3 -3
  186. package/src/__tests__/send-endpoint-busy.test.ts +81 -42
  187. package/src/__tests__/server-history-render.test.ts +4 -1
  188. package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
  189. package/src/__tests__/skill-feature-flags.test.ts +14 -16
  190. package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
  191. package/src/__tests__/skill-projection-feature-flag.test.ts +44 -30
  192. package/src/__tests__/skill-projection.benchmark.test.ts +5 -7
  193. package/src/__tests__/skill-tool-factory.test.ts +96 -95
  194. package/src/__tests__/slack-channel-config.test.ts +3 -3
  195. package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
  196. package/src/__tests__/subagent-disposal.test.ts +27 -8
  197. package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
  198. package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
  199. package/src/__tests__/subagent-manager-notify.test.ts +20 -8
  200. package/src/__tests__/subagent-notify-parent.test.ts +5 -4
  201. package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
  202. package/src/__tests__/subagent-tools.test.ts +2 -1
  203. package/src/__tests__/suggestion-routes.test.ts +1 -0
  204. package/src/__tests__/system-prompt.test.ts +38 -0
  205. package/src/__tests__/test-preload-verifier.ts +68 -0
  206. package/src/__tests__/test-preload.ts +32 -39
  207. package/src/__tests__/tool-executor-lifecycle-events.test.ts +20 -7
  208. package/src/__tests__/tool-executor.test.ts +55 -10
  209. package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
  210. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  211. package/src/__tests__/twilio-routes.test.ts +3 -2
  212. package/src/__tests__/validate-input.test.ts +381 -0
  213. package/src/__tests__/verification-control-plane-policy.test.ts +1 -0
  214. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
  215. package/src/__tests__/voice-session-bridge.test.ts +37 -28
  216. package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
  217. package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
  218. package/src/acp/session-manager.ts +5 -6
  219. package/src/agent/loop.ts +80 -0
  220. package/src/api/README.md +124 -2
  221. package/src/api/constants/call-sites.ts +27 -0
  222. package/src/api/events/assistant-outbound-attachment.ts +51 -0
  223. package/src/api/events/assistant-text-delta.ts +32 -0
  224. package/src/api/events/assistant-turn-start.ts +33 -0
  225. package/src/api/events/document-comment-created.ts +48 -0
  226. package/src/api/events/document-comment-deleted.ts +24 -0
  227. package/src/api/events/document-comment-reopened.ts +25 -0
  228. package/src/api/events/document-comment-resolved.ts +27 -0
  229. package/src/api/events/generation-cancelled.ts +24 -0
  230. package/src/api/events/generation-handoff.ts +41 -0
  231. package/src/api/events/message-complete.ts +42 -0
  232. package/src/api/events/open-url.ts +30 -0
  233. package/src/{events → api/events}/relationship-state-updated.ts +3 -3
  234. package/src/api/events/tool-use-start.ts +32 -0
  235. package/src/api/index.ts +128 -3
  236. package/src/api/responses/llm-context-response.ts +39 -0
  237. package/src/api/responses/llm-request-log-entry.ts +93 -0
  238. package/src/api/responses/memory-recall-log.ts +65 -0
  239. package/src/api/responses/memory-v2-activation-log.ts +78 -0
  240. package/src/background-wake/background-wake-routes.test.ts +687 -52
  241. package/src/background-wake/platform-client.test.ts +308 -0
  242. package/src/background-wake/platform-client.ts +167 -0
  243. package/src/background-wake/publisher.ts +91 -0
  244. package/src/background-wake/runtime-registry.ts +2 -2
  245. package/src/background-wake/wake-intent-hooks.test.ts +282 -0
  246. package/src/calls/guardian-dispatch.ts +1 -0
  247. package/src/calls/voice-session-bridge.ts +4 -4
  248. package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
  249. package/src/cli/commands/__tests__/notifications.test.ts +184 -40
  250. package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
  251. package/src/cli/commands/channels/index.ts +229 -0
  252. package/src/cli/commands/memory-v3-render.ts +147 -0
  253. package/src/cli/commands/memory-v3.ts +255 -4
  254. package/src/cli/commands/notifications.ts +365 -55
  255. package/src/cli/lib/open-browser.ts +7 -2
  256. package/src/cli/program.ts +2 -0
  257. package/src/config/assistant-feature-flags.ts +23 -42
  258. package/src/config/bundled-skills/document-editor/SKILL.md +5 -1
  259. package/src/config/bundled-skills/schedule/SKILL.md +1 -1
  260. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  261. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
  262. package/src/config/call-site-defaults.ts +1 -1
  263. package/src/config/feature-flag-cache.ts +86 -0
  264. package/src/config/feature-flag-registry.json +17 -17
  265. package/src/config/llm-context-resolution.ts +10 -1
  266. package/src/config/llm-resolver.ts +121 -15
  267. package/src/config/loader.ts +4 -5
  268. package/src/config/schemas/__tests__/memory-v2.test.ts +15 -0
  269. package/src/config/schemas/heartbeat.ts +1 -1
  270. package/src/config/schemas/llm.ts +90 -1
  271. package/src/config/schemas/memory-v2.ts +26 -0
  272. package/src/config/schemas/services.ts +6 -2
  273. package/src/config/seed-inference-profiles.ts +36 -16
  274. package/src/context/token-estimator.ts +10 -5
  275. package/src/credential-execution/executable-discovery.ts +40 -0
  276. package/src/credential-execution/process-manager.ts +6 -2
  277. package/src/credential-health/credential-health-service.ts +125 -40
  278. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
  279. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
  280. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -2
  281. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
  282. package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
  283. package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
  284. package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
  285. package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
  286. package/src/daemon/conversation-agent-loop-handlers.ts +389 -68
  287. package/src/daemon/conversation-agent-loop.ts +132 -28
  288. package/src/daemon/conversation-error.ts +33 -5
  289. package/src/daemon/conversation-messaging.ts +84 -43
  290. package/src/daemon/conversation-process.ts +74 -37
  291. package/src/daemon/conversation-runtime-assembly.ts +29 -9
  292. package/src/daemon/conversation-skill-tools.ts +14 -30
  293. package/src/daemon/conversation-surfaces.ts +69 -34
  294. package/src/daemon/conversation-tool-setup.ts +33 -48
  295. package/src/daemon/conversation.ts +26 -46
  296. package/src/daemon/daemon-control.ts +1 -1
  297. package/src/daemon/daemon-skill-host.ts +9 -2
  298. package/src/daemon/disk-pressure-guard.ts +27 -29
  299. package/src/daemon/first-greeting.ts +31 -13
  300. package/src/daemon/handlers/shared.ts +6 -1
  301. package/src/daemon/lifecycle.ts +12 -12
  302. package/src/daemon/mcp-reload-service.ts +1 -1
  303. package/src/daemon/meet-manifest-loader.ts +10 -17
  304. package/src/daemon/message-types/conversations.ts +20 -22
  305. package/src/daemon/message-types/document-comments.ts +8 -44
  306. package/src/daemon/message-types/home.ts +2 -2
  307. package/src/daemon/message-types/integrations.ts +2 -7
  308. package/src/daemon/message-types/messages.ts +23 -38
  309. package/src/daemon/message-types/subagents.ts +6 -0
  310. package/src/daemon/process-message.ts +9 -9
  311. package/src/daemon/providers-setup.ts +1 -1
  312. package/src/daemon/server.ts +16 -0
  313. package/src/daemon/switch-inference-profile-tool.ts +13 -3
  314. package/src/daemon/tool-setup-types.ts +0 -6
  315. package/src/daemon/wake-target-adapter.ts +10 -0
  316. package/src/documents/document-store.ts +38 -0
  317. package/src/export/__tests__/transcript-formatter.test.ts +1 -0
  318. package/src/heartbeat/__tests__/heartbeat-service.test.ts +29 -0
  319. package/src/heartbeat/heartbeat-service.ts +63 -0
  320. package/src/home/__tests__/feed-writer.test.ts +161 -0
  321. package/src/home/__tests__/post-connect-feed.test.ts +1 -0
  322. package/src/home/__tests__/suggested-prompts.test.ts +55 -59
  323. package/src/home/feed-writer.ts +146 -7
  324. package/src/home/suggested-prompts.ts +27 -145
  325. package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
  326. package/src/ipc/gateway-client.test.ts +4 -1
  327. package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
  328. package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
  329. package/src/ipc/skill-routes/memory.ts +4 -3
  330. package/src/ipc/skill-routes/registries.ts +28 -29
  331. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +1 -0
  332. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
  333. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
  334. package/src/memory/__tests__/memory-retrospective-job.test.ts +1 -0
  335. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
  336. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
  337. package/src/memory/conversation-attention-store.ts +17 -3
  338. package/src/memory/conversation-crud.ts +352 -112
  339. package/src/memory/db-connection.ts +29 -19
  340. package/src/memory/db-init.ts +4 -0
  341. package/src/memory/db-singleton.ts +77 -0
  342. package/src/memory/delivery-channels.ts +82 -0
  343. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
  344. package/src/memory/graph/retriever.test.ts +3 -3
  345. package/src/memory/job-handlers/embedding.test.ts +3 -2
  346. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
  347. package/src/memory/jobs-worker.ts +12 -1
  348. package/src/memory/llm-request-log-source-clickhouse.ts +80 -0
  349. package/src/memory/llm-request-log-source-local.ts +24 -0
  350. package/src/memory/llm-request-log-source.ts +31 -0
  351. package/src/memory/llm-request-log-store.ts +188 -3
  352. package/src/memory/memory-v2-activation-log-store.ts +95 -1
  353. package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
  354. package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
  355. package/src/memory/migrations/index.ts +2 -0
  356. package/src/memory/schema/conversations.ts +9 -1
  357. package/src/memory/schema/inference.ts +0 -1
  358. package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
  359. package/src/memory/v2/__tests__/harness-metrics.test.ts +9 -0
  360. package/src/memory/v2/__tests__/harness-replay-input.test.ts +9 -4
  361. package/src/memory/v2/__tests__/harness-runner.test.ts +26 -0
  362. package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
  363. package/src/memory/v2/harness/metrics.ts +5 -1
  364. package/src/memory/v2/harness/replay-input.ts +19 -3
  365. package/src/memory/v2/harness/runner.ts +6 -0
  366. package/src/memory/v2/harness/trace.ts +6 -0
  367. package/src/memory/v3/__tests__/consolidation-job.test.ts +2 -4
  368. package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
  369. package/src/memory/v3/__tests__/edges.test.ts +144 -1
  370. package/src/memory/v3/__tests__/filter.test.ts +48 -0
  371. package/src/memory/v3/__tests__/gate.test.ts +96 -33
  372. package/src/memory/v3/__tests__/index-composition.test.ts +58 -0
  373. package/src/memory/v3/__tests__/loop.test.ts +250 -5
  374. package/src/memory/v3/__tests__/scouts.test.ts +49 -0
  375. package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
  376. package/src/memory/v3/__tests__/shadow-middleware.test.ts +88 -2
  377. package/src/memory/v3/__tests__/traversal.test.ts +39 -0
  378. package/src/memory/v3/__tests__/tree-walk.test.ts +77 -0
  379. package/src/memory/v3/__tests__/validate.test.ts +32 -0
  380. package/src/memory/v3/coretrieval-seed.ts +240 -0
  381. package/src/memory/v3/edges.ts +58 -21
  382. package/src/memory/v3/filter.ts +27 -22
  383. package/src/memory/v3/gate.ts +51 -36
  384. package/src/memory/v3/index-composition.ts +18 -5
  385. package/src/memory/v3/loop.ts +65 -17
  386. package/src/memory/v3/scouts.ts +15 -4
  387. package/src/memory/v3/shadow-diff.ts +287 -0
  388. package/src/memory/v3/shadow-middleware.ts +44 -2
  389. package/src/memory/v3/traversal.ts +6 -1
  390. package/src/memory/v3/tree-walk.ts +6 -1
  391. package/src/memory/v3/validate.ts +56 -33
  392. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  393. package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
  394. package/src/notifications/adapters/slack.ts +45 -11
  395. package/src/notifications/broadcaster.ts +114 -63
  396. package/src/notifications/conversation-pairing.ts +23 -3
  397. package/src/notifications/decisions-store.ts +32 -1
  398. package/src/notifications/deliveries-store.ts +45 -0
  399. package/src/notifications/edit-notification.ts +201 -0
  400. package/src/notifications/emit-signal.ts +11 -1
  401. package/src/notifications/signal.ts +10 -0
  402. package/src/notifications/types.ts +37 -0
  403. package/src/oauth/byo-connection.test.ts +67 -3
  404. package/src/oauth/byo-connection.ts +32 -5
  405. package/src/oauth/connect-orchestrator.ts +9 -0
  406. package/src/oauth/connection-resolver.test.ts +76 -0
  407. package/src/oauth/connection-resolver.ts +49 -10
  408. package/src/oauth/manual-token-connection.ts +51 -3
  409. package/src/oauth/seed-providers.ts +3 -0
  410. package/src/permissions/approval-policy.test.ts +19 -5
  411. package/src/permissions/approval-policy.ts +14 -3
  412. package/src/permissions/checker.ts +21 -8
  413. package/src/platform/client.test.ts +24 -1
  414. package/src/platform/client.ts +8 -0
  415. package/src/platform/feature-gate.ts +15 -0
  416. package/src/plugins/defaults/injectors.ts +2 -8
  417. package/src/plugins/defaults/persistence.ts +25 -6
  418. package/src/plugins/types.ts +57 -13
  419. package/src/proactive-artifact/job.test.ts +1 -0
  420. package/src/prompts/__tests__/system-prompt.test.ts +4 -4
  421. package/src/prompts/system-prompt.ts +38 -40
  422. package/src/prompts/template-detection.ts +10 -4
  423. package/src/prompts/templates/BOOTSTRAP.md +7 -11
  424. package/src/prompts/templates/IDENTITY.md +0 -2
  425. package/src/providers/__tests__/connection-model-compat.test.ts +3 -4
  426. package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
  427. package/src/providers/call-site-routing.ts +33 -9
  428. package/src/providers/connection-model-compat.ts +23 -0
  429. package/src/providers/connection-resolution.ts +39 -20
  430. package/src/providers/fireworks/client.ts +1 -0
  431. package/src/providers/gemini/client.ts +24 -3
  432. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
  433. package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
  434. package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
  435. package/src/providers/inference/auth.ts +0 -8
  436. package/src/providers/inference/connections.ts +3 -66
  437. package/src/providers/inference/resolve-auth.ts +2 -3
  438. package/src/providers/model-catalog.ts +35 -1
  439. package/src/providers/model-intents.ts +3 -3
  440. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  441. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
  442. package/src/providers/openai/chat-completions-provider.ts +110 -12
  443. package/src/providers/openai/codex-models.ts +2 -0
  444. package/src/providers/openai/responses-provider.ts +53 -53
  445. package/src/providers/openrouter/client.ts +13 -8
  446. package/src/providers/provider-send-message.ts +18 -9
  447. package/src/providers/registry.ts +48 -8
  448. package/src/providers/retry.ts +16 -4
  449. package/src/providers/search-provider-catalog.ts +17 -9
  450. package/src/providers/types.ts +9 -0
  451. package/src/runtime/__tests__/agent-wake.test.ts +1 -0
  452. package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
  453. package/src/runtime/access-request-helper.ts +1 -0
  454. package/src/runtime/auth/route-policy.ts +10 -0
  455. package/src/runtime/channel-readiness-service.ts +68 -0
  456. package/src/runtime/channel-reply-delivery.ts +23 -0
  457. package/src/runtime/channel-retry-sweep.ts +47 -14
  458. package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
  459. package/src/runtime/migrations/vbundle-builder.ts +3 -2
  460. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
  461. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
  462. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
  463. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  464. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
  465. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
  466. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +51 -3
  467. package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
  468. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
  469. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
  470. package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
  471. package/src/runtime/routes/acp-routes-list.test.ts +3 -0
  472. package/src/runtime/routes/app-management-routes.ts +111 -4
  473. package/src/runtime/routes/background-wake-routes.ts +188 -20
  474. package/src/runtime/routes/btw-routes.ts +4 -4
  475. package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
  476. package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
  477. package/src/runtime/routes/conversation-list-routes.ts +147 -0
  478. package/src/runtime/routes/conversation-management-routes.ts +39 -14
  479. package/src/runtime/routes/conversation-query-routes.ts +60 -10
  480. package/src/runtime/routes/conversation-routes.ts +186 -140
  481. package/src/runtime/routes/conversations-import-routes.ts +19 -6
  482. package/src/runtime/routes/documents-routes.ts +10 -1
  483. package/src/runtime/routes/group-routes.ts +11 -0
  484. package/src/runtime/routes/home-feed-routes.ts +129 -0
  485. package/src/runtime/routes/identity-intro-cache.ts +61 -16
  486. package/src/runtime/routes/identity-routes.ts +30 -9
  487. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
  488. package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
  489. package/src/runtime/routes/index.ts +2 -0
  490. package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
  491. package/src/runtime/routes/integrations/vercel.ts +15 -0
  492. package/src/runtime/routes/llm-context-normalization.ts +7 -2
  493. package/src/runtime/routes/memory-v3-routes.ts +160 -2
  494. package/src/runtime/routes/migration-routes.ts +20 -13
  495. package/src/runtime/routes/notification-routes.ts +63 -1
  496. package/src/runtime/routes/oauth-commands-routes.ts +6 -1
  497. package/src/runtime/routes/surface-action-routes.ts +1 -38
  498. package/src/runtime/routes/surface-content-routes.ts +12 -5
  499. package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
  500. package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
  501. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
  502. package/src/runtime/slack-dm-text-delivery.ts +177 -0
  503. package/src/runtime/sync/resource-sync-events.ts +1 -1
  504. package/src/runtime/tool-grant-request-helper.ts +1 -0
  505. package/src/schedule/schedule-store.ts +8 -1
  506. package/src/schedule/scheduler.ts +111 -15
  507. package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
  508. package/src/security/encrypted-store.ts +7 -16
  509. package/src/security/store-path-override.ts +61 -0
  510. package/src/signals/user-message.ts +5 -8
  511. package/src/skills/validate-input.ts +177 -0
  512. package/src/subagent/manager.ts +13 -13
  513. package/src/subagent/types.ts +6 -0
  514. package/src/tasks/tool-sanitizer.ts +2 -2
  515. package/src/tools/apps/definitions.ts +35 -21
  516. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
  517. package/src/tools/computer-use/definitions.ts +268 -266
  518. package/src/tools/document/document-tool.ts +131 -8
  519. package/src/tools/execution-target.ts +2 -5
  520. package/src/tools/executor.ts +18 -55
  521. package/src/tools/host-filesystem/edit.test.ts +1 -0
  522. package/src/tools/host-filesystem/read.test.ts +1 -0
  523. package/src/tools/host-filesystem/transfer.test.ts +31 -6
  524. package/src/tools/host-filesystem/write.test.ts +1 -0
  525. package/src/tools/mcp/mcp-tool-factory.ts +0 -2
  526. package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
  527. package/src/tools/network/__tests__/web-search.test.ts +211 -3
  528. package/src/tools/network/managed-search-proxy.ts +183 -0
  529. package/src/tools/network/web-search.ts +199 -44
  530. package/src/tools/policy-context.ts +3 -1
  531. package/src/tools/registry.ts +146 -103
  532. package/src/tools/schedule/create.ts +1 -1
  533. package/src/tools/skills/skill-tool-factory.ts +17 -36
  534. package/src/tools/subagent/spawn.ts +3 -0
  535. package/src/tools/tool-approval-handler.ts +10 -4
  536. package/src/tools/tool-name-aliases.ts +72 -14
  537. package/src/tools/types.ts +17 -15
  538. package/src/tools/ui-surface/definitions.ts +98 -86
  539. package/src/types/onboarding-context.ts +6 -0
  540. package/src/usage/attribution.ts +32 -1
  541. package/src/util/browser.ts +7 -2
  542. package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
  543. package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
  544. package/src/workspace/migrations/registry.ts +4 -0
@@ -20,18 +20,14 @@ import type { SecretPrompter } from "../permissions/secret-prompter.js";
20
20
  import type { Message, ToolDefinition } from "../providers/types.js";
21
21
  import type { TrustClass } from "../runtime/actor-trust-resolver.js";
22
22
  import { assistantEventHub } from "../runtime/assistant-event-hub.js";
23
- import { coreAppProxyTools } from "../tools/apps/definitions.js";
24
23
  import { registerConversationSender } from "../tools/browser/browser-screencast.js";
25
24
  import type { ToolExecutor } from "../tools/executor.js";
26
- import {
27
- getAllToolDefinitions,
28
- getMcpToolDefinitions,
29
- } from "../tools/registry.js";
25
+ import { getMcpToolDefinitions } from "../tools/registry.js";
30
26
  import {
31
27
  ACTIVITY_SKIP_SET,
32
28
  injectActivityField,
33
29
  } from "../tools/schema-transforms.js";
34
- import { resolveToolNameAlias } from "../tools/tool-name-aliases.js";
30
+ import { resolveToolInvocationAlias } from "../tools/tool-name-aliases.js";
35
31
  import {
36
32
  isDiskPressureCleanupToolName,
37
33
  type ProxyApprovalCallback,
@@ -40,7 +36,6 @@ import {
40
36
  type ToolExecutionResult,
41
37
  type ToolLifecycleEventHandler,
42
38
  } from "../tools/types.js";
43
- import { allUiSurfaceTools } from "../tools/ui-surface/definitions.js";
44
39
  import { getLogger } from "../util/logger.js";
45
40
  import {
46
41
  projectSkillTools,
@@ -75,6 +70,7 @@ export function resolveTrustClass(
75
70
  }
76
71
 
77
72
  import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
73
+ import { AUTO_PROFILE_KEY } from "../config/seed-inference-profiles.js";
78
74
  import {
79
75
  buildSwitchInferenceProfileToolDef,
80
76
  SWITCH_INFERENCE_PROFILE_TOOL_NAME,
@@ -82,20 +78,6 @@ import {
82
78
  import type { ToolSetupContext } from "./tool-setup-types.js";
83
79
  export type { ToolSetupContext } from "./tool-setup-types.js";
84
80
 
85
- // ── buildToolDefinitions ─────────────────────────────────────────────
86
-
87
- /**
88
- * Collect all tool definitions for the agent loop: built-in tools,
89
- * UI surface proxy tools, and app proxy tools.
90
- */
91
- export function buildToolDefinitions(): ToolDefinition[] {
92
- return [
93
- ...getAllToolDefinitions(),
94
- ...allUiSurfaceTools,
95
- ...coreAppProxyTools,
96
- ];
97
- }
98
-
99
81
  // ── createToolExecutor ───────────────────────────────────────────────
100
82
 
101
83
  /**
@@ -129,10 +111,11 @@ export function createToolExecutor(
129
111
  toolUseId?: string,
130
112
  turnContext?: import("../plugins/types.js").TurnContext,
131
113
  ) => {
132
- const executionName = resolveToolNameAlias(name, ctx.allowedToolNames);
114
+ const { name: executionName, input: executionInput } =
115
+ resolveToolInvocationAlias(name, input, ctx.allowedToolNames);
133
116
 
134
- if (isDoordashCommand(executionName, input)) {
135
- markDoordashStepInProgress(ctx, input);
117
+ if (isDoordashCommand(executionName, executionInput)) {
118
+ markDoordashStepInProgress(ctx, executionInput);
136
119
  }
137
120
 
138
121
  // Build the context object shared by both the skill_execute interception
@@ -218,7 +201,10 @@ export function createToolExecutor(
218
201
  // model self-select a different inference profile mid-turn. No permission
219
202
  // checks — this is a control-flow signal, not a user-visible tool.
220
203
  if (executionName === SWITCH_INFERENCE_PROFILE_TOOL_NAME) {
221
- const profile = typeof input.profile === "string" ? input.profile : "";
204
+ const profile =
205
+ typeof executionInput.profile === "string"
206
+ ? executionInput.profile
207
+ : "";
222
208
  const config = getConfig();
223
209
  const profileEntry = config.llm.profiles?.[profile];
224
210
  if (!profileEntry) {
@@ -246,15 +232,19 @@ export function createToolExecutor(
246
232
  // risk level, permission checks, hooks, and lifecycle events all fire
247
233
  // with the real tool name.
248
234
  if (executionName === "skill_execute") {
249
- const rawToolName = typeof input.tool === "string" ? input.tool : "";
250
- const toolName = resolveToolNameAlias(rawToolName, ctx.allowedToolNames);
235
+ const rawToolName =
236
+ typeof executionInput.tool === "string" ? executionInput.tool : "";
251
237
  const rawToolInput =
252
- input.input != null && typeof input.input === "object"
253
- ? (input.input as Record<string, unknown>)
238
+ executionInput.input != null && typeof executionInput.input === "object"
239
+ ? (executionInput.input as Record<string, unknown>)
254
240
  : {};
255
241
 
256
242
  // Clone to avoid mutating shared input objects
257
- const toolInput = { ...rawToolInput };
243
+ const { name: toolName, input: toolInput } = resolveToolInvocationAlias(
244
+ rawToolName,
245
+ { ...rawToolInput },
246
+ ctx.allowedToolNames,
247
+ );
258
248
 
259
249
  if (!toolName) {
260
250
  return {
@@ -281,7 +271,7 @@ export function createToolExecutor(
281
271
 
282
272
  const result = await executor.execute(
283
273
  executionName,
284
- input,
274
+ executionInput,
285
275
  toolContext,
286
276
  turnContext,
287
277
  );
@@ -289,7 +279,7 @@ export function createToolExecutor(
289
279
  ctx.approvedViaPromptThisTurn = true;
290
280
  }
291
281
 
292
- runPostExecutionSideEffects(executionName, input, result, { ctx });
282
+ runPostExecutionSideEffects(executionName, executionInput, result, { ctx });
293
283
 
294
284
  return result;
295
285
  };
@@ -360,12 +350,6 @@ export interface SkillProjectionContext {
360
350
  readonly transportInterface?: InterfaceId;
361
351
  /** Per-turn override profile, read by the switch_inference_profile tool injection. */
362
352
  currentTurnOverrideProfile?: string;
363
- /**
364
- * True when the user has explicitly selected an inference profile for this
365
- * conversation (via the composer profile picker). When set, tool-based
366
- * auto-routing is suppressed — the user's explicit choice takes precedence.
367
- */
368
- hasExplicitProfileOverride?: boolean;
369
353
  }
370
354
 
371
355
  // ── Conditional tool sets ────────────────────────────────────────────
@@ -658,18 +642,19 @@ export function createResolveToolsCallback(
658
642
  const config = getConfig();
659
643
  if (
660
644
  isAssistantFeatureFlagEnabled("query-complexity-routing", config) &&
661
- config.llm &&
662
- !ctx.hasExplicitProfileOverride
645
+ config.llm
663
646
  ) {
664
- const currentProfile =
647
+ const effectiveProfile =
665
648
  ctx.currentTurnOverrideProfile ?? config.llm.activeProfile;
666
- const toolDef = buildSwitchInferenceProfileToolDef(
667
- config.llm.profiles ?? {},
668
- currentProfile,
669
- );
670
- if (toolDef) {
671
- turnAllowed.add(SWITCH_INFERENCE_PROFILE_TOOL_NAME);
672
- return [...baseDefs, toolDef];
649
+ if (effectiveProfile === AUTO_PROFILE_KEY) {
650
+ const toolDef = buildSwitchInferenceProfileToolDef(
651
+ config.llm.profiles ?? {},
652
+ effectiveProfile,
653
+ );
654
+ if (toolDef) {
655
+ turnAllowed.add(SWITCH_INFERENCE_PROFILE_TOOL_NAME);
656
+ return [...baseDefs, toolDef];
657
+ }
673
658
  }
674
659
  }
675
660
 
@@ -68,6 +68,7 @@ import { broadcastMessage } from "../runtime/assistant-event-hub.js";
68
68
  import type { AuthContext } from "../runtime/auth/types.js";
69
69
  import type { InteractiveUiResult } from "../runtime/interactive-ui.js";
70
70
  import { ToolExecutor } from "../tools/executor.js";
71
+ import { getAllToolDefinitions } from "../tools/registry.js";
71
72
  import type { ToolLifecycleEvent } from "../tools/types.js";
72
73
  import type { OnboardingContext } from "../types/onboarding-context.js";
73
74
  import type { AbortReason } from "../util/abort-reasons.js";
@@ -85,7 +86,11 @@ import {
85
86
  disposeConversation,
86
87
  loadFromDb as loadFromDbImpl,
87
88
  } from "./conversation-lifecycle.js";
88
- import type { RedirectToSecurePromptOptions } from "./conversation-messaging.js";
89
+ import type {
90
+ EnqueueMessageOptions,
91
+ PersistMessageOptions,
92
+ RedirectToSecurePromptOptions,
93
+ } from "./conversation-messaging.js";
89
94
  import {
90
95
  enqueueMessage as enqueueMessageImpl,
91
96
  persistUserMessage as persistUserMessageImpl,
@@ -116,7 +121,6 @@ import {
116
121
  } from "./conversation-surfaces.js";
117
122
  import type { ToolSetupContext } from "./conversation-tool-setup.js";
118
123
  import {
119
- buildToolDefinitions,
120
124
  createResolveToolsCallback,
121
125
  createToolExecutor,
122
126
  resolveTrustClass,
@@ -326,7 +330,12 @@ export class Conversation {
326
330
  surfaceType: SurfaceType;
327
331
  title?: string;
328
332
  data: SurfaceData;
329
- actions?: Array<{ id: string; label: string; style?: string }>;
333
+ actions?: Array<{
334
+ id: string;
335
+ label: string;
336
+ style?: string;
337
+ data?: Record<string, unknown>;
338
+ }>;
330
339
  display?: string;
331
340
  persistent?: boolean;
332
341
  }> = [];
@@ -451,7 +460,7 @@ export class Conversation {
451
460
  return publishToolDomainEvent(event);
452
461
  };
453
462
 
454
- const toolDefs = buildToolDefinitions();
463
+ const toolDefs = getAllToolDefinitions();
455
464
  this.coreToolNames = new Set(toolDefs.map((d) => d.name));
456
465
  const toolExecutor = createToolExecutor(
457
466
  this.executor,
@@ -581,7 +590,7 @@ export class Conversation {
581
590
  channelCapabilities: this.currentTurnChannelCapabilities,
582
591
  onboardingContext: this.getOnboardingContext(),
583
592
  });
584
- const tools = buildToolDefinitions();
593
+ const tools = getAllToolDefinitions();
585
594
  const provider = this.provider;
586
595
 
587
596
  const warmMessage: Message = {
@@ -823,33 +832,15 @@ export class Conversation {
823
832
  );
824
833
  }
825
834
 
826
- enqueueMessage(
827
- content: string,
828
- attachments: UserMessageAttachment[],
829
- onEvent?: (msg: ServerMessage) => void,
830
- requestId?: string,
831
- activeSurfaceId?: string,
832
- currentPage?: string,
833
- metadata?: Record<string, unknown>,
834
- options?: { isInteractive?: boolean },
835
- displayContent?: string,
836
- transport?: ConversationTransportMetadata,
837
- clientMessageId?: string,
838
- ): { queued: boolean; requestId: string; rejected?: boolean } {
839
- return enqueueMessageImpl(
840
- this,
841
- content,
842
- attachments,
843
- onEvent ?? this.sendToClient,
844
- requestId ?? crypto.randomUUID(),
845
- activeSurfaceId,
846
- currentPage,
847
- metadata,
848
- options,
849
- displayContent,
850
- transport,
851
- clientMessageId,
852
- );
835
+ enqueueMessage(options: EnqueueMessageOptions): {
836
+ queued: boolean;
837
+ requestId: string;
838
+ rejected?: boolean;
839
+ } {
840
+ return enqueueMessageImpl(this, {
841
+ ...options,
842
+ onEvent: options.onEvent ?? this.sendToClient,
843
+ });
853
844
  }
854
845
 
855
846
  getQueueDepth(): number {
@@ -1278,23 +1269,12 @@ export class Conversation {
1278
1269
  }
1279
1270
 
1280
1271
  async persistUserMessage(
1281
- content: string,
1282
- attachments: UserMessageAttachment[],
1283
- requestId?: string,
1284
- metadata?: Record<string, unknown>,
1285
- displayContent?: string,
1286
- ): Promise<string> {
1272
+ options: PersistMessageOptions,
1273
+ ): Promise<{ id: string; deduplicated: boolean }> {
1287
1274
  if (!this.processing) {
1288
1275
  await this.ensureActorScopedHistory();
1289
1276
  }
1290
- return persistUserMessageImpl(
1291
- this,
1292
- content,
1293
- attachments,
1294
- requestId,
1295
- metadata,
1296
- displayContent,
1297
- );
1277
+ return persistUserMessageImpl(this, options);
1298
1278
  }
1299
1279
 
1300
1280
  // ── Agent Loop ───────────────────────────────────────────────────
@@ -33,7 +33,7 @@ const DAEMON_TIMEOUT_DEFAULTS = {
33
33
  };
34
34
 
35
35
  const HEALTH_CHECK_TIMEOUT_MS = 1500;
36
- const STARTUP_LOCK_STALE_MS = 30_000;
36
+ const STARTUP_LOCK_STALE_MS = 120_000;
37
37
 
38
38
  function isPositiveInteger(v: unknown): v is number {
39
39
  return typeof v === "number" && Number.isInteger(v) && v > 0;
@@ -219,8 +219,15 @@ function buildRegistriesFacet(skillId: string): RegistriesFacet {
219
219
  // overlay (`assistant/src/tools/types.ts`); the assistant-side
220
220
  // registry accepts the daemon flavor. Skills construct tools via
221
221
  // helpers that already produce the daemon shape, so a cast at this
222
- // boundary is safe.
223
- registerTools: (provider) => registerExternalTools(provider as never),
222
+ // boundary is safe. The contract's `registerTools(provider)` stays
223
+ // single-arg skill code never needs to know its own id — and this
224
+ // adapter pairs the provider with the owner derived from the
225
+ // surrounding {@link buildRegistriesFacet} closure.
226
+ registerTools: (provider) =>
227
+ registerExternalTools(
228
+ { kind: "skill", id: skillId },
229
+ provider as never,
230
+ ),
224
231
  registerSkillRoute: (route: SkillRoute): SkillRouteHandle =>
225
232
  registerSkillRoute(route) as unknown as SkillRouteHandle,
226
233
  // Namespace hook names by skillId so two skills using the same label
@@ -1,5 +1,3 @@
1
- import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
2
- import { getConfig } from "../config/loader.js";
3
1
  import { buildAssistantEvent } from "../runtime/assistant-event.js";
4
2
  import { assistantEventHub } from "../runtime/assistant-event-hub.js";
5
3
  import { cancelBackgroundTools } from "../tools/background-tool-registry.js";
@@ -8,6 +6,12 @@ import { getLogger } from "../util/logger.js";
8
6
 
9
7
  export const DISK_PRESSURE_WARNING_THRESHOLD_PERCENT = 80;
10
8
  export const DISK_PRESSURE_THRESHOLD_PERCENT = 95;
9
+ // Hysteresis lower bound: once locked, the guard stays locked until usage
10
+ // falls below this clear threshold. The deadband between this and the
11
+ // critical threshold stops the lock from flapping when usage hovers near
12
+ // 95% — otherwise clearing the lock immediately resumes background work,
13
+ // which can refill the disk and re-trip the lock on the next sample.
14
+ export const DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT = 90;
11
15
  export const DISK_PRESSURE_CHECK_INTERVAL_MS = 60_000;
12
16
  export const DISK_PRESSURE_OVERRIDE_CONFIRMATION = "I understand the risks";
13
17
  export const DISK_PRESSURE_BLOCKED_CAPABILITIES = [
@@ -16,7 +20,12 @@ export const DISK_PRESSURE_BLOCKED_CAPABILITIES = [
16
20
  "remote-ingress",
17
21
  ] as const;
18
22
 
19
- export type DiskPressureState = "disabled" | "ok" | "warning" | "critical" | "unknown";
23
+ export type DiskPressureState =
24
+ | "disabled"
25
+ | "ok"
26
+ | "warning"
27
+ | "critical"
28
+ | "unknown";
20
29
 
21
30
  export type DiskPressureBlockedCapability =
22
31
  (typeof DISK_PRESSURE_BLOCKED_CAPABILITIES)[number];
@@ -119,24 +128,10 @@ function replaceStatus(next: DiskPressureStatus): DiskPressureStatus {
119
128
  return cloneStatus(state.status);
120
129
  }
121
130
 
122
- function isEnabled(): boolean {
123
- return isAssistantFeatureFlagEnabled("safe-storage-limits", getConfig());
124
- }
125
-
126
- function resetToDisabled(): DiskPressureStatus {
127
- const previous = cloneStatus(state.status);
128
- stopDiskPressureGuard();
129
- state.status = cloneStatus(DISABLED_STATUS);
130
- publishStatusChangedIfNeeded(previous);
131
- return cloneStatus(state.status);
132
- }
133
-
134
- function ensureEnabledStatus(): DiskPressureStatus | null {
135
- if (!isEnabled()) return resetToDisabled();
131
+ function ensureEnabledStatus(): void {
136
132
  if (!state.status.enabled) {
137
133
  state.status = cloneStatus(OPEN_STATUS);
138
134
  }
139
- return null;
140
135
  }
141
136
 
142
137
  function nextLockId(): string {
@@ -192,8 +187,7 @@ function rejectTransition(
192
187
  }
193
188
 
194
189
  export function startDiskPressureGuard(): DiskPressureStatus {
195
- const disabledStatus = ensureEnabledStatus();
196
- if (disabledStatus) return disabledStatus;
190
+ ensureEnabledStatus();
197
191
 
198
192
  if (!state.timer) {
199
193
  state.timer = setInterval(() => {
@@ -212,8 +206,7 @@ export function stopDiskPressureGuard(): void {
212
206
  }
213
207
 
214
208
  export function evaluateDiskPressureNow(): DiskPressureStatus {
215
- const disabledStatus = ensureEnabledStatus();
216
- if (disabledStatus) return disabledStatus;
209
+ ensureEnabledStatus();
217
210
 
218
211
  let usageInfo: ReturnType<typeof getDiskUsageInfo>;
219
212
  try {
@@ -229,8 +222,14 @@ export function evaluateDiskPressureNow(): DiskPressureStatus {
229
222
  const usagePercent = roundPercent(
230
223
  (usageInfo.usedMb / usageInfo.totalMb) * 100,
231
224
  );
232
- const isCritical = usagePercent >= DISK_PRESSURE_THRESHOLD_PERCENT;
233
- const isWarning = !isCritical && usagePercent >= DISK_PRESSURE_WARNING_THRESHOLD_PERCENT;
225
+ // Hysteresis: while locked, hold until usage drops below the lower clear
226
+ // threshold; otherwise lock at the critical threshold.
227
+ const criticalThreshold = state.status.locked
228
+ ? DISK_PRESSURE_CLEAR_THRESHOLD_PERCENT
229
+ : DISK_PRESSURE_THRESHOLD_PERCENT;
230
+ const isCritical = usagePercent >= criticalThreshold;
231
+ const isWarning =
232
+ !isCritical && usagePercent >= DISK_PRESSURE_WARNING_THRESHOLD_PERCENT;
234
233
  const lastCheckedAt = new Date().toISOString();
235
234
 
236
235
  if (!isCritical && !isWarning) {
@@ -277,14 +276,13 @@ export function evaluateDiskPressureNow(): DiskPressureStatus {
277
276
  }
278
277
 
279
278
  export function getDiskPressureStatus(): DiskPressureStatus {
280
- if (!isEnabled()) return cloneStatus(DISABLED_STATUS);
281
279
  if (!state.status.enabled) return cloneStatus(OPEN_STATUS);
282
280
  return cloneStatus(state.status);
283
281
  }
284
282
 
285
283
  export function acknowledgeDiskPressureLock(): DiskPressureTransitionResult {
286
- const disabledStatus = ensureEnabledStatus();
287
- const status = disabledStatus ?? cloneStatus(state.status);
284
+ ensureEnabledStatus();
285
+ const status = cloneStatus(state.status);
288
286
  if (!status.locked) {
289
287
  return rejectTransition(
290
288
  "not_locked",
@@ -310,8 +308,8 @@ export function acknowledgeDiskPressureLock(): DiskPressureTransitionResult {
310
308
  export function overrideDiskPressureLock(
311
309
  confirmation: string,
312
310
  ): DiskPressureTransitionResult {
313
- const disabledStatus = ensureEnabledStatus();
314
- const status = disabledStatus ?? cloneStatus(state.status);
311
+ ensureEnabledStatus();
312
+ const status = cloneStatus(state.status);
315
313
  if (!status.locked) {
316
314
  return rejectTransition(
317
315
  "not_locked",
@@ -14,12 +14,6 @@ export interface OnboardingGreetingContext {
14
14
  googleConnected?: boolean;
15
15
  }
16
16
 
17
- export const CANNED_FIRST_GREETING = [
18
- "Hey,",
19
- "",
20
- "We can get into whatever you've got, or just talk first — that tends to go better. Up to you.",
21
- ].join("\n");
22
-
23
17
  /**
24
18
  * Returns `true` when all of the following are true:
25
19
  * - `conversationMessageCount === 0` (no prior messages in this conversation)
@@ -67,30 +61,54 @@ function buildIntroLine(
67
61
  return [greeting, who, close].filter(Boolean).join(" ");
68
62
  }
69
63
 
70
- const TONE_INVITE: Record<Tone, string> = {
64
+ // Every greeting variant the no-onboarding CANNED greeting and all four
65
+ // personalized tones — ends with a migration offer. The opener (task-vs-talk)
66
+ // and the migration offer are kept as separate per-tone maps and composed in
67
+ // `buildInvite`, rather than inlined as one full sentence per variant, so the
68
+ // offer cannot be silently dropped from a variant when the opener copy is
69
+ // edited. The first-greeting test asserts every variant still includes it.
70
+ const TONE_INVITE_OPENER: Record<Tone, string> = {
71
71
  grounded:
72
72
  "We can get into whatever you've got, or just talk first — that tends to go better. Up to you.",
73
73
  warm: "We can start on something specific, or just talk for a bit first — honestly that tends to work out better. Either way, I'm here.",
74
74
  energetic:
75
- "We can jump straight into whatever you've got, or take a few minutes to just talk first. What sounds right?",
75
+ "We can jump straight into whatever you've got, or take a few minutes to just talk first.",
76
76
  poetic:
77
77
  "We can start with whatever's in front of you, or just talk for a bit first. Either way.",
78
78
  };
79
79
 
80
+ const TONE_MIGRATION_OFFER: Record<Tone, string> = {
81
+ grounded:
82
+ "If you have context or workflows from another assistant or harness, bring them over early and I'll help port them.",
83
+ warm: "If you have context or workflows from another assistant or harness, bring them over early and I can help port them.",
84
+ energetic:
85
+ "If you've got context or workflows from another assistant or harness, bring them over early and I'll port them with you. What sounds right?",
86
+ poetic:
87
+ "If there's old context or workflows from another assistant or harness, bring them over early and I'll help port them.",
88
+ };
89
+
80
90
  const TONE_GOOGLE_SCAN: Record<Tone, string> = {
81
91
  grounded:
82
- "I can scan your email, calendar, and drive in the background while we talk — just say the word.",
83
- warm: "Also — I can scan your email, calendar, and drive in the background while we chat, if you'd like. Just let me know.",
92
+ "I can scan Gmail in the background while we talk — just say the word.",
93
+ warm: "Also — I can scan Gmail in the background while we chat, if you'd like. Just let me know.",
84
94
  energetic:
85
- "Oh, and I can scan your email, calendar, and drive in the background right now — want me to?",
95
+ "Oh, and I can scan Gmail in the background right now — want me to?",
86
96
  poetic:
87
- "I can also look through your email, calendar, and drive quietly in the background — say the word.",
97
+ "I can also look through Gmail quietly in the background — say the word.",
88
98
  };
89
99
 
90
100
  function buildInvite(tone: Tone = "grounded"): string {
91
- return TONE_INVITE[tone];
101
+ return `${TONE_INVITE_OPENER[tone]} ${TONE_MIGRATION_OFFER[tone]}`;
92
102
  }
93
103
 
104
+ // Composed from the grounded opener + migration offer so the no-onboarding
105
+ // greeting reuses the same source as the personalized grounded greeting rather
106
+ // than duplicating the copy. Defined after the tone maps so they are
107
+ // initialized before this module-level evaluation runs.
108
+ export const CANNED_FIRST_GREETING = ["Hey,", "", buildInvite("grounded")].join(
109
+ "\n",
110
+ );
111
+
94
112
  const VALID_TONES = new Set<string>([
95
113
  "grounded",
96
114
  "warm",
@@ -85,7 +85,12 @@ export interface HistorySurface {
85
85
  surfaceType: string;
86
86
  title?: string;
87
87
  data: Record<string, unknown>;
88
- actions?: Array<{ id: string; label: string; style?: string }>;
88
+ actions?: Array<{
89
+ id: string;
90
+ label: string;
91
+ style?: string;
92
+ data?: Record<string, unknown>;
93
+ }>;
89
94
  display?: string;
90
95
  persistent?: boolean;
91
96
  completed?: boolean;
@@ -2,6 +2,7 @@ import { join } from "node:path";
2
2
 
3
3
  import { config as dotenvConfig } from "dotenv";
4
4
 
5
+ import { refreshBackgroundWakeIntent } from "../background-wake/publisher.js";
5
6
  import { registerBackgroundWakeRuntime } from "../background-wake/runtime-registry.js";
6
7
  import { setPointerMessageProcessor } from "../calls/call-pointer-messages.js";
7
8
  import { reconcileCallsOnStartup } from "../calls/call-recovery.js";
@@ -73,6 +74,7 @@ import {
73
74
  import { RuntimeHttpServer } from "../runtime/http-server.js";
74
75
  import { recoverInterruptedImport } from "../runtime/migrations/vbundle-streaming-importer.js";
75
76
  import { registerSecretsDeps } from "../runtime/routes/secrets-deps.js";
77
+ import { publishConversationListChanged } from "../runtime/sync/resource-sync-events.js";
76
78
  import { recoverStaleSchedules } from "../schedule/schedule-recovery.js";
77
79
  import { startScheduler } from "../schedule/scheduler.js";
78
80
  import {
@@ -1018,6 +1020,7 @@ export async function runDaemon(): Promise<void> {
1018
1020
  scheduleJobId: info.scheduleJobId,
1019
1021
  title: info.title,
1020
1022
  });
1023
+ publishConversationListChanged("created");
1021
1024
  },
1022
1025
  );
1023
1026
 
@@ -1082,13 +1085,11 @@ export async function runDaemon(): Promise<void> {
1082
1085
  // its own finally block.
1083
1086
  conversation.toolsDisabledDepth++;
1084
1087
  try {
1085
- const messageId = await conversation.persistUserMessage(
1086
- instruction,
1087
- [],
1088
- undefined,
1089
- { pointerInstruction: true },
1090
- "[Call status event]",
1091
- );
1088
+ const { id: messageId } = await conversation.persistUserMessage({
1089
+ content: instruction,
1090
+ metadata: { pointerInstruction: true },
1091
+ displayContent: "[Call status event]",
1092
+ });
1092
1093
 
1093
1094
  // Helper: roll back persisted messages on failure, then reload
1094
1095
  // in-memory history from the (now cleaned) DB. Reloading avoids
@@ -1271,11 +1272,9 @@ export async function runDaemon(): Promise<void> {
1271
1272
  })();
1272
1273
 
1273
1274
  if (config.auditLog.retentionDays > 0) {
1274
- void rotateToolInvocations(config.auditLog.retentionDays).catch(
1275
- (err) => {
1276
- log.warn({ err }, "Audit log rotation failed");
1277
- },
1278
- );
1275
+ void rotateToolInvocations(config.auditLog.retentionDays).catch((err) => {
1276
+ log.warn({ err }, "Audit log rotation failed");
1277
+ });
1279
1278
  }
1280
1279
 
1281
1280
  const workspaceHeartbeat = new WorkspaceHeartbeatService();
@@ -1293,6 +1292,7 @@ export async function runDaemon(): Promise<void> {
1293
1292
  });
1294
1293
  heartbeat.start();
1295
1294
  registerBackgroundWakeRuntime({ scheduler, heartbeat });
1295
+ refreshBackgroundWakeIntent("daemon-startup");
1296
1296
  log.info(
1297
1297
  {
1298
1298
  enabled: heartbeatConfig.enabled,
@@ -82,7 +82,7 @@ async function doReload(): Promise<McpReloadResult> {
82
82
  serverConfig,
83
83
  manager,
84
84
  );
85
- const accepted = registerMcpTools(mcpTools);
85
+ const accepted = registerMcpTools(serverId, mcpTools);
86
86
  const acceptedNames = accepted.map((t) => t.name);
87
87
  toolCount += accepted.length;
88
88
  servers.push({