@vellumai/assistant 0.10.12 → 0.11.0-staging.1

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 (776) hide show
  1. package/AGENTS.md +1 -1
  2. package/ARCHITECTURE.md +4 -5
  3. package/README.md +1 -1
  4. package/docs/architecture/memory.md +60 -23
  5. package/docs/error-handling.md +3 -3
  6. package/docs/guardian-request-flow.md +112 -0
  7. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  8. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
  9. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
  10. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
  11. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
  12. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts +28 -0
  13. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts.map +1 -1
  14. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts +2 -2
  15. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts.map +1 -1
  16. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.js.map +1 -1
  17. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts +2 -0
  18. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts.map +1 -1
  19. package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/package.json +1 -1
  20. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  21. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
  22. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
  23. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
  24. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
  25. package/node_modules/@vellumai/gateway-client/package.json +1 -1
  26. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +6 -0
  27. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +34 -0
  28. package/node_modules/@vellumai/service-contracts/package.json +1 -0
  29. package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
  30. package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
  31. package/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
  32. package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
  33. package/openapi.yaml +246 -10
  34. package/package.json +2 -2
  35. package/src/__tests__/acp-session.test.ts +3 -3
  36. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +3 -0
  37. package/src/__tests__/anthropic-provider.test.ts +40 -0
  38. package/src/__tests__/approval-cascade.test.ts +5 -5
  39. package/src/__tests__/approval-routes-http.test.ts +3 -3
  40. package/src/__tests__/ask-question-resolver.test.ts +207 -0
  41. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
  42. package/src/__tests__/assistant-event-hub-targeted.test.ts +13 -11
  43. package/src/__tests__/assistant-event-hub.test.ts +13 -11
  44. package/src/__tests__/assistant-event.test.ts +12 -9
  45. package/src/__tests__/assistant-feature-flag-guard.test.ts +3 -3
  46. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +1 -1
  47. package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -58
  48. package/src/__tests__/assistant-stream-state.test.ts +17 -7
  49. package/src/__tests__/avatar-identity-sync.test.ts +3 -3
  50. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
  51. package/src/__tests__/call-conversation-messages.test.ts +134 -18
  52. package/src/__tests__/call-start-guardian-guard.test.ts +27 -0
  53. package/src/__tests__/channel-approvals.test.ts +0 -27
  54. package/src/__tests__/channel-guardian.test.ts +85 -512
  55. package/src/__tests__/channel-readiness-slack-remote.test.ts +151 -3
  56. package/src/__tests__/channel-retry-sweep.test.ts +88 -1
  57. package/src/__tests__/channel-setup-panel-ack.test.ts +12 -9
  58. package/src/__tests__/chat-reveal-guard-priming.test.ts +31 -34
  59. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +2 -2
  60. package/src/__tests__/compaction-events.test.ts +8 -8
  61. package/src/__tests__/config-loader-platform-defaults.test.ts +54 -28
  62. package/src/__tests__/config-model-image-provider.test.ts +20 -0
  63. package/src/__tests__/config-schema-memory-substrate.test.ts +306 -0
  64. package/src/__tests__/config-schema.test.ts +14 -2
  65. package/src/__tests__/config-set-platform-guard.test.ts +11 -12
  66. package/src/__tests__/config-sounds-sync.test.ts +4 -4
  67. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +5 -0
  68. package/src/__tests__/context-search-memory-source.test.ts +1 -1
  69. package/src/__tests__/context-search-memory-v2-source.test.ts +6 -6
  70. package/src/__tests__/context-token-estimator.test.ts +54 -1
  71. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +12 -3
  72. package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +13 -4
  73. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
  74. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -1
  75. package/src/__tests__/conversation-agent-loop-overflow.test.ts +22 -13
  76. package/src/__tests__/conversation-agent-loop.test.ts +39 -30
  77. package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
  78. package/src/__tests__/conversation-evictor.test.ts +49 -0
  79. package/src/__tests__/conversation-fork-crud.test.ts +1 -1
  80. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  81. package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
  82. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +5 -5
  83. package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
  84. package/src/__tests__/conversation-queue.test.ts +81 -81
  85. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +8 -1
  86. package/src/__tests__/conversation-routes-hidden-queue.test.ts +8 -1
  87. package/src/__tests__/conversation-routes-slash-commands.test.ts +10 -1
  88. package/src/__tests__/conversation-runtime-assembly.test.ts +29 -2
  89. package/src/__tests__/conversation-slash-queue.test.ts +11 -11
  90. package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
  91. package/src/__tests__/conversation-speed-override.test.ts +2 -2
  92. package/src/__tests__/conversation-summarize-route.test.ts +9 -0
  93. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +18 -16
  94. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
  95. package/src/__tests__/conversation-surfaces-app-open.test.ts +7 -4
  96. package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
  97. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
  98. package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
  99. package/src/__tests__/conversation-surfaces-state-update.test.ts +8 -5
  100. package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -3
  101. package/src/__tests__/conversation-surfaces-task-progress.test.ts +46 -46
  102. package/src/__tests__/conversation-sync-tags.test.ts +5 -5
  103. package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
  104. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
  105. package/src/__tests__/conversation-workspace-injection.test.ts +0 -3
  106. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -3
  107. package/src/__tests__/copy-composer-tc-templates.test.ts +3 -131
  108. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  109. package/src/__tests__/daemon-assistant-events.test.ts +14 -15
  110. package/src/__tests__/db-test-helpers.ts +13 -27
  111. package/src/__tests__/disk-pressure-routes.test.ts +12 -3
  112. package/src/__tests__/document-tool-security.test.ts +95 -0
  113. package/src/__tests__/drain-kick-guard.test.ts +232 -0
  114. package/src/__tests__/dynamic-skill-background-guard.test.ts +19 -6
  115. package/src/__tests__/emit-event-signal.test.ts +5 -6
  116. package/src/__tests__/encrypted-store-test-helpers.ts +10 -20
  117. package/src/__tests__/events-tail-route.test.ts +6 -4
  118. package/src/__tests__/feature-flag-test-helpers.ts +10 -20
  119. package/src/__tests__/file-edit-tool.test.ts +24 -4
  120. package/src/__tests__/file-list-tool.test.ts +2 -1
  121. package/src/__tests__/file-read-tool.test.ts +62 -10
  122. package/src/__tests__/file-write-tool.test.ts +24 -5
  123. package/src/__tests__/followup-tools.test.ts +58 -0
  124. package/src/__tests__/gateway-threshold-reader-mock.ts +99 -0
  125. package/src/__tests__/graph-extraction-event-date.test.ts +1 -1
  126. package/src/__tests__/guardian-question-mode.test.ts +42 -3
  127. package/src/__tests__/guardian-reply-router-answer-mode.test.ts +283 -0
  128. package/src/__tests__/guardian-vellum-destination-pinning.test.ts +221 -0
  129. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  130. package/src/__tests__/heartbeat-service.test.ts +1 -0
  131. package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
  132. package/src/__tests__/host-browser-proxy.test.ts +1 -1
  133. package/src/__tests__/host-file-edit-tool.test.ts +3 -3
  134. package/src/__tests__/host-file-read-tool.test.ts +2 -2
  135. package/src/__tests__/host-file-write-tool.test.ts +7 -3
  136. package/src/__tests__/host-shell-tool.test.ts +17 -5
  137. package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
  138. package/src/__tests__/image-credentials.test.ts +65 -8
  139. package/src/__tests__/injection-block.test.ts +4 -4
  140. package/src/__tests__/injector-chain.test.ts +1 -1
  141. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  142. package/src/__tests__/injector-registry-order-guard.test.ts +4 -9
  143. package/src/__tests__/injector-v3-suppression.test.ts +6 -4
  144. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +27 -28
  145. package/src/__tests__/list-messages-page-latest.test.ts +2 -2
  146. package/src/__tests__/llm-usage-store.test.ts +67 -4
  147. package/src/__tests__/log-redact.test.ts +18 -0
  148. package/src/__tests__/managed-profile-guard.test.ts +27 -0
  149. package/src/__tests__/managed-skill-lifecycle.test.ts +2 -2
  150. package/src/__tests__/media-generate-image.test.ts +62 -11
  151. package/src/__tests__/memory-identity-context-parity.test.ts +1 -1
  152. package/src/__tests__/memory-jobs-worker-lanes.test.ts +9 -1
  153. package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
  154. package/src/__tests__/notification-decision-strategy.test.ts +115 -11
  155. package/src/__tests__/notification-deep-link.test.ts +12 -12
  156. package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
  157. package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
  158. package/src/__tests__/path-policy.test.ts +315 -0
  159. package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
  160. package/src/__tests__/persistence-layering-guard.test.ts +2 -2
  161. package/src/__tests__/pkb-autoinject.test.ts +1 -1
  162. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -0
  163. package/src/__tests__/plugin-event-hub-facade.test.ts +22 -15
  164. package/src/__tests__/plugin-import-boundary-guard.test.ts +15 -15
  165. package/src/__tests__/processing-flag-persist-failure.test.ts +0 -4
  166. package/src/__tests__/provider-platform-proxy-integration.test.ts +0 -1
  167. package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
  168. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +5 -5
  169. package/src/__tests__/require-fresh-approval.test.ts +38 -38
  170. package/src/__tests__/run-due-schedules.test.ts +72 -1
  171. package/src/__tests__/runtime-events-sse-parity.test.ts +11 -10
  172. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  173. package/src/__tests__/schedule-routes.test.ts +44 -5
  174. package/src/__tests__/schedule-store.test.ts +3 -3
  175. package/src/__tests__/schedule-tools.test.ts +176 -0
  176. package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
  177. package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
  178. package/src/__tests__/secret-response-routing.test.ts +3 -3
  179. package/src/__tests__/secret-routes-platform-proxy.test.ts +4 -7
  180. package/src/__tests__/secret-scanner.test.ts +36 -0
  181. package/src/__tests__/send-endpoint-busy.test.ts +7 -7
  182. package/src/__tests__/slack-required-scopes-mirror.test.ts +81 -0
  183. package/src/__tests__/starter-task-flow.test.ts +6 -3
  184. package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
  185. package/src/__tests__/subagent-disposal.test.ts +40 -11
  186. package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
  187. package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
  188. package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
  189. package/src/__tests__/subagent-manager-notify.test.ts +73 -14
  190. package/src/__tests__/subagent-notify-parent.test.ts +48 -4
  191. package/src/__tests__/subagent-spawn-and-await.test.ts +62 -14
  192. package/src/__tests__/subagent-tools.test.ts +64 -0
  193. package/src/__tests__/sync-message-contract.test.ts +3 -3
  194. package/src/__tests__/terminal-tools.test.ts +12 -3
  195. package/src/__tests__/test-preload.ts +9 -0
  196. package/src/__tests__/tool-approval-handler.test.ts +583 -43
  197. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +7 -4
  198. package/src/__tests__/tool-executor.test.ts +116 -0
  199. package/src/__tests__/tool-grant-request-escalation.test.ts +5 -0
  200. package/src/__tests__/tool-preview-lifecycle.test.ts +32 -29
  201. package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
  202. package/src/__tests__/tool-start-timestamp.test.ts +4 -4
  203. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -22
  204. package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
  205. package/src/__tests__/ui-work-result-surface.test.ts +3 -3
  206. package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
  207. package/src/__tests__/voice-session-bridge.test.ts +44 -44
  208. package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +284 -0
  209. package/src/__tests__/workspace-policy.test.ts +399 -0
  210. package/src/acp/__tests__/client-handler.test.ts +3 -3
  211. package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
  212. package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
  213. package/src/acp/client-handler.ts +3 -3
  214. package/src/acp/session-manager.ts +8 -8
  215. package/src/api/events/subagent-event.ts +2 -2
  216. package/src/api/responses/memory-v2-activation-log.ts +2 -2
  217. package/src/approvals/AGENTS.md +2 -0
  218. package/src/approvals/guardian-request-resolvers.ts +118 -24
  219. package/src/calls/__tests__/voice-control-protocol.test.ts +57 -0
  220. package/src/calls/__tests__/voice-session-bridge.test.ts +158 -4
  221. package/src/calls/__tests__/voice-triage-escalate.test.ts +3 -4
  222. package/src/calls/call-controller.ts +27 -27
  223. package/src/calls/call-conversation-messages.ts +58 -18
  224. package/src/calls/voice-control-protocol.ts +56 -0
  225. package/src/calls/voice-session-bridge.ts +156 -58
  226. package/src/calls/voice-triage-escalate.ts +2 -3
  227. package/src/channels/config.ts +8 -0
  228. package/src/channels/types.ts +1 -0
  229. package/src/cli/commands/config.ts +49 -13
  230. package/src/cli/commands/memory/index.help.ts +4 -2
  231. package/src/cli/commands/memory/memory-retrospective.ts +5 -0
  232. package/src/cli/lib/bundled-marketplace.json +12 -0
  233. package/src/cli.ts +2 -109
  234. package/src/config/__tests__/deployment-context-defaults.test.ts +9 -0
  235. package/src/config/__tests__/substrate-twin-shadowing.test.ts +191 -0
  236. package/src/config/assistant-feature-flags.ts +1 -1
  237. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +13 -7
  238. package/src/config/feature-flag-cache.ts +6 -16
  239. package/src/config/feature-flag-registry.json +14 -30
  240. package/src/config/loader.ts +7 -1
  241. package/src/config/memory-tier.ts +15 -10
  242. package/src/config/memory-v3-gate.test.ts +278 -1
  243. package/src/config/memory-v3-gate.ts +88 -26
  244. package/src/config/raw-config-utils.ts +1 -1
  245. package/src/config/schemas/__tests__/live-voice.test.ts +27 -16
  246. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  247. package/src/config/schemas/live-voice.ts +33 -7
  248. package/src/config/schemas/llm.ts +1 -0
  249. package/src/config/schemas/memory-retrospective.ts +13 -0
  250. package/src/config/schemas/memory-substrate.ts +183 -0
  251. package/src/config/schemas/memory-v2.ts +3 -2
  252. package/src/config/schemas/memory-v3.ts +11 -4
  253. package/src/config/schemas/memory.ts +35 -1
  254. package/src/config/schemas/services.ts +10 -2
  255. package/src/config/substrate-twin-shadowing.ts +195 -0
  256. package/src/config/webhook-routing.ts +67 -0
  257. package/src/context/compactor.ts +10 -3
  258. package/src/context/token-estimator.ts +21 -0
  259. package/src/daemon/__tests__/channel-ui-capability.test.ts +85 -0
  260. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
  261. package/src/daemon/__tests__/embedding-reconcile.test.ts +3 -3
  262. package/src/daemon/__tests__/inference-profile-notification.test.ts +3 -6
  263. package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
  264. package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
  265. package/src/daemon/channel-ui-capability.ts +70 -1
  266. package/src/daemon/conversation-agent-loop-handlers.ts +4 -4
  267. package/src/daemon/conversation-agent-loop.ts +12 -5
  268. package/src/daemon/conversation-evictor.ts +26 -4
  269. package/src/daemon/conversation-launch.ts +11 -14
  270. package/src/daemon/conversation-messaging.ts +14 -14
  271. package/src/daemon/conversation-notifiers.ts +2 -2
  272. package/src/daemon/conversation-process.ts +133 -21
  273. package/src/daemon/conversation-queue-manager.ts +7 -7
  274. package/src/daemon/conversation-runtime-assembly.ts +16 -0
  275. package/src/daemon/conversation-store.ts +11 -3
  276. package/src/daemon/conversation-surfaces.ts +4 -4
  277. package/src/daemon/conversation-tool-setup.ts +13 -7
  278. package/src/daemon/conversation-usage.ts +12 -11
  279. package/src/daemon/conversation.ts +38 -15
  280. package/src/daemon/disk-pressure-guard.ts +5 -12
  281. package/src/daemon/embedding-reconcile.ts +14 -9
  282. package/src/daemon/handlers/config-channels.ts +40 -134
  283. package/src/daemon/handlers/config-model.ts +15 -7
  284. package/src/daemon/handlers/conversations.ts +4 -2
  285. package/src/daemon/handlers/shared.ts +29 -0
  286. package/src/daemon/host-proxy-base.ts +4 -4
  287. package/src/daemon/lifecycle.ts +13 -0
  288. package/src/daemon/message-protocol.ts +8 -144
  289. package/src/daemon/message-types/computer-use.ts +0 -12
  290. package/src/daemon/message-types/conversations.ts +9 -345
  291. package/src/daemon/message-types/host-app-control.ts +0 -9
  292. package/src/daemon/message-types/host-browser.ts +0 -7
  293. package/src/daemon/message-types/host-ui-snapshot.ts +0 -7
  294. package/src/daemon/message-types/messages.ts +0 -48
  295. package/src/daemon/message-types/notifications.ts +0 -7
  296. package/src/daemon/message-types/skills.ts +0 -5
  297. package/src/daemon/message-types/surfaces.ts +0 -9
  298. package/src/daemon/message-types/sync.ts +0 -2
  299. package/src/daemon/process-message.ts +5 -5
  300. package/src/daemon/skill-memory-refresh.ts +5 -5
  301. package/src/daemon/tool-side-effects.ts +13 -13
  302. package/src/daemon/trust-context.ts +1 -1
  303. package/src/daemon/wake-conversation-ops.ts +4 -4
  304. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +100 -7
  305. package/src/heartbeat/__tests__/heartbeat-service.test.ts +67 -0
  306. package/src/heartbeat/heartbeat-run-store.ts +81 -4
  307. package/src/heartbeat/heartbeat-service.ts +32 -1
  308. package/src/home/__tests__/feed-writer.test.ts +7 -7
  309. package/src/home/__tests__/home-content-refresh.test.ts +3 -0
  310. package/src/home/__tests__/suggested-prompts.test.ts +1 -0
  311. package/src/home/feed-writer.ts +6 -13
  312. package/src/home/home-content-refresh.ts +6 -9
  313. package/src/home/relationship-state-writer.ts +5 -12
  314. package/src/home/suggested-prompts-cache.ts +6 -19
  315. package/src/ipc/__tests__/events-publish-client.test.ts +67 -0
  316. package/src/ipc/events-publish-client.ts +44 -0
  317. package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
  318. package/src/ipc/routes/__tests__/events-ipc-routes.test.ts +38 -9
  319. package/src/ipc/routes/events-ipc-routes.ts +11 -31
  320. package/src/live-voice/__tests__/front-decision.test.ts +4 -176
  321. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +276 -68
  322. package/src/live-voice/__tests__/live-voice-events.test.ts +6 -3
  323. package/src/live-voice/__tests__/live-voice-progress.test.ts +185 -46
  324. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +24 -59
  325. package/src/live-voice/__tests__/live-voice-tts-session.test.ts +38 -54
  326. package/src/live-voice/__tests__/live-voice-vad.test.ts +218 -422
  327. package/src/live-voice/front-decision.ts +5 -155
  328. package/src/live-voice/live-voice-metrics.ts +4 -1
  329. package/src/live-voice/live-voice-session.ts +650 -333
  330. package/src/live-voice/progress-phrases.ts +17 -0
  331. package/src/live-voice/protocol.ts +15 -0
  332. package/src/media/app-icon-generator.ts +15 -8
  333. package/src/media/avatar-router.ts +9 -5
  334. package/src/media/image-credentials.ts +42 -10
  335. package/src/media/image-service.ts +1 -13
  336. package/src/media/types.ts +26 -3
  337. package/src/notifications/AGENTS.md +2 -0
  338. package/src/notifications/__tests__/broadcaster.test.ts +95 -0
  339. package/src/notifications/adapters/macos.ts +3 -3
  340. package/src/notifications/broadcaster.ts +57 -0
  341. package/src/notifications/copy-composer.ts +0 -15
  342. package/src/notifications/decision-engine.ts +21 -22
  343. package/src/notifications/guardian-question-mode.ts +57 -2
  344. package/src/notifications/home-feed-side-effect.ts +4 -0
  345. package/src/notifications/signal.ts +6 -4
  346. package/src/notifications/trusted-contact-payloads.ts +3 -4
  347. package/src/notifications/vellum-card-affinity.ts +39 -0
  348. package/src/oauth/AGENTS.md +1 -1
  349. package/src/permissions/channel-permission-query.test.ts +69 -0
  350. package/src/permissions/channel-permission-query.ts +73 -1
  351. package/src/permissions/checker.test.ts +85 -9
  352. package/src/permissions/checker.ts +17 -22
  353. package/src/permissions/confirmation-guardian-request.test.ts +2 -2
  354. package/src/permissions/confirmation-guardian-request.ts +2 -2
  355. package/src/permissions/gateway-threshold-reader.test.ts +224 -17
  356. package/src/permissions/gateway-threshold-reader.ts +82 -10
  357. package/src/permissions/ipc-risk-types.ts +8 -0
  358. package/src/permissions/prompter.ts +5 -5
  359. package/src/permissions/question-guardian-request.test.ts +222 -0
  360. package/src/permissions/question-guardian-request.ts +179 -0
  361. package/src/permissions/question-prompter.test.ts +8 -8
  362. package/src/permissions/question-prompter.ts +18 -0
  363. package/src/permissions/secret-prompter.ts +2 -4
  364. package/src/permissions/workspace-policy.ts +236 -34
  365. package/src/persistence/__tests__/lifecycle-quiesce.test.ts +82 -0
  366. package/src/persistence/__tests__/message-content-file.test.ts +58 -3
  367. package/src/persistence/conversation-crud.ts +93 -0
  368. package/src/persistence/conversation-key-store.ts +63 -0
  369. package/src/persistence/db-async-query.ts +1 -1
  370. package/src/persistence/db-singleton.ts +14 -27
  371. package/src/persistence/delivery-crud.ts +45 -0
  372. package/src/persistence/embeddings/embedding-backend.ts +2 -1
  373. package/src/persistence/embeddings/embedding-identity.ts +7 -3
  374. package/src/persistence/job-utils.ts +32 -27
  375. package/src/persistence/jobs-store.ts +92 -3
  376. package/src/persistence/lifecycle-quiesce.ts +80 -0
  377. package/src/persistence/llm-usage-store.ts +45 -8
  378. package/src/persistence/message-content-file.ts +4 -4
  379. package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +1 -1
  380. package/src/persistence/migrations/351-schedule-skill-script-handoff.ts +39 -0
  381. package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.test.ts +83 -0
  382. package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.ts +36 -0
  383. package/src/persistence/migrations/353-add-llm-usage-conversation-type.test.ts +110 -0
  384. package/src/persistence/migrations/353-add-llm-usage-conversation-type.ts +49 -0
  385. package/src/persistence/schema/infrastructure.ts +11 -0
  386. package/src/persistence/steps.ts +7 -1
  387. package/src/plugin-api/__tests__/publish-event-forwarding.test.ts +113 -0
  388. package/src/plugin-api/__tests__/publish-event.test.ts +57 -0
  389. package/src/plugin-api/conversation-turn.ts +4 -4
  390. package/src/plugin-api/event-hub-facade.ts +15 -6
  391. package/src/plugin-api/index.ts +10 -4
  392. package/src/plugin-api/publish-event.ts +36 -0
  393. package/src/plugins/AGENTS.md +2 -0
  394. package/src/plugins/defaults/compaction/window-manager.ts +9 -0
  395. package/src/plugins/defaults/index.ts +9 -13
  396. package/src/plugins/defaults/memory/AGENTS.md +775 -0
  397. package/src/plugins/defaults/memory/__tests__/capability-seed-embed-gate.test.ts +186 -0
  398. package/src/plugins/defaults/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +1 -1
  399. package/src/plugins/defaults/memory/__tests__/indexer-tier-dispatch.test.ts +129 -0
  400. package/src/plugins/defaults/memory/__tests__/jobs-worker-quiesce-gate.test.ts +91 -0
  401. package/src/plugins/defaults/memory/__tests__/jobs-worker-v1-graph-substrate-noop.test.ts +342 -0
  402. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +9 -1
  403. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +36 -1
  404. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-sweep-defer.test.ts +9 -1
  405. package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +2 -2
  406. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +44 -10
  407. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +151 -10
  408. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +1155 -0
  409. package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
  410. package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -3
  411. package/src/plugins/defaults/memory/__tests__/tools-delete-memory-page.test.ts +1 -1
  412. package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +71 -35
  413. package/src/plugins/defaults/memory/context-search/sources/memory.ts +5 -1
  414. package/src/plugins/defaults/memory/fork-conversation-memory.ts +4 -4
  415. package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +80 -10
  416. package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +1 -1
  417. package/src/plugins/defaults/memory/graph/capability-seed.ts +24 -10
  418. package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +123 -49
  419. package/src/plugins/defaults/memory/graph/graph-search.ts +6 -118
  420. package/src/plugins/defaults/memory/graph/in-context-tracker.test.ts +173 -0
  421. package/src/plugins/defaults/memory/graph/in-context-tracker.ts +109 -0
  422. package/src/plugins/defaults/memory/graph/store.ts +1 -0
  423. package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +1 -1
  424. package/src/plugins/defaults/memory/graph/tool-handlers.ts +5 -2
  425. package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +1 -1
  426. package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +6 -9
  427. package/src/plugins/defaults/memory/hooks/__tests__/user-prompt-submit.test.ts +30 -16
  428. package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +18 -14
  429. package/src/plugins/defaults/memory/indexer.ts +146 -89
  430. package/src/plugins/defaults/memory/injectors.ts +86 -41
  431. package/src/plugins/defaults/memory/job-handlers.ts +130 -39
  432. package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +2 -2
  433. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +22 -10
  434. package/src/plugins/defaults/memory/jobs-worker.ts +279 -208
  435. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +4 -2
  436. package/src/plugins/defaults/memory/memory-retrospective-job.ts +40 -3
  437. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +99 -11
  438. package/src/plugins/defaults/memory/src/__tests__/memory-v2-routes.test.ts +5 -3
  439. package/src/plugins/defaults/memory/src/__tests__/memory-v2-simulate-route.test.ts +3 -4
  440. package/src/plugins/defaults/memory/src/memory-graph-routes.ts +2 -1
  441. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +7 -5
  442. package/src/plugins/defaults/memory/src/memory-item-routes.ts +51 -19
  443. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +31 -20
  444. package/src/plugins/defaults/memory/startup.ts +58 -21
  445. package/src/plugins/defaults/memory/substrate/__tests__/boot-maintenance.test.ts +335 -0
  446. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/cli-command-store.test.ts +14 -8
  447. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-job.test.ts +51 -21
  448. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/edge-index.test.ts +1 -1
  449. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/frontmatter-sweep.test.ts +3 -3
  450. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-index.test.ts +1 -1
  451. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-store.test.ts +1 -1
  452. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/prompts-consolidation.test.ts +2 -2
  453. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/qdrant.test.ts +23 -14
  454. package/src/plugins/defaults/memory/substrate/__tests__/reembed-job.test.ts +262 -0
  455. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sim.test.ts +9 -12
  456. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-content.test.ts +2 -2
  457. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-store.test.ts +9 -9
  458. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sparse-bm25.test.ts +12 -5
  459. package/src/plugins/defaults/memory/substrate/__tests__/spread.test.ts +276 -0
  460. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/static-context.test.ts +17 -8
  461. package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sweep-job.test.ts +9 -9
  462. package/src/plugins/defaults/memory/{v3/substrate/memory-v2-startup.ts → substrate/boot-maintenance.ts} +43 -24
  463. package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-store.ts +13 -8
  464. package/src/plugins/defaults/memory/{v3/substrate → substrate}/consolidation-job.ts +51 -27
  465. package/src/plugins/defaults/memory/{v3/substrate → substrate}/constants.ts +1 -0
  466. package/src/plugins/defaults/memory/{v3/substrate → substrate}/edge-index.ts +28 -9
  467. package/src/plugins/defaults/memory/{v3/substrate → substrate}/frontmatter-sweep.ts +14 -7
  468. package/src/plugins/defaults/memory/{v3/substrate → substrate}/injected-block-slugs.ts +9 -3
  469. package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-index.ts +29 -10
  470. package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-store.ts +35 -12
  471. package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/consolidation.ts +14 -8
  472. package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/sweep.ts +4 -1
  473. package/src/plugins/defaults/memory/{v3/substrate → substrate}/qdrant.ts +96 -36
  474. package/src/plugins/defaults/memory/substrate/reembed-job.ts +54 -0
  475. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sim.ts +26 -15
  476. package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-content.ts +1 -1
  477. package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-store.ts +13 -8
  478. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sparse-bm25.ts +27 -10
  479. package/src/plugins/defaults/memory/substrate/spread.ts +165 -0
  480. package/src/plugins/defaults/memory/{v3/substrate → substrate}/static-context.ts +12 -7
  481. package/src/plugins/defaults/memory/{v3/substrate → substrate}/sweep-job.ts +20 -15
  482. package/src/plugins/defaults/memory/substrate/tuning.ts +93 -0
  483. package/src/plugins/defaults/memory/{v3/substrate → substrate}/types.ts +7 -4
  484. package/src/plugins/defaults/memory/tools.test.ts +1 -1
  485. package/src/plugins/defaults/memory/tools.ts +1 -1
  486. package/src/plugins/defaults/memory/v1/README.md +5 -0
  487. package/src/plugins/defaults/memory/{__tests__ → v1/__tests__}/filing-jobs.test.ts +4 -4
  488. package/src/plugins/defaults/memory/{filing-jobs.ts → v1/filing-jobs.ts} +3 -3
  489. package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.test.ts +68 -6
  490. package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.ts +40 -21
  491. package/src/plugins/defaults/memory/{graph → v1/graph}/consolidation.ts +14 -14
  492. package/src/plugins/defaults/memory/{graph → v1/graph}/decay.test.ts +1 -1
  493. package/src/plugins/defaults/memory/{graph → v1/graph}/decay.ts +3 -3
  494. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction-job.ts +5 -5
  495. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.test.ts +1 -1
  496. package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.ts +20 -14
  497. package/src/plugins/defaults/memory/{graph → v1/graph}/graph-search.test.ts +3 -3
  498. package/src/plugins/defaults/memory/v1/graph/graph-search.ts +123 -0
  499. package/src/plugins/defaults/memory/{graph → v1/graph}/injection.test.ts +1 -118
  500. package/src/plugins/defaults/memory/{graph → v1/graph}/injection.ts +9 -111
  501. package/src/plugins/defaults/memory/{graph → v1/graph}/narrative.ts +6 -6
  502. package/src/plugins/defaults/memory/{graph → v1/graph}/pattern-scan.ts +5 -5
  503. package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.test.ts +135 -42
  504. package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.ts +40 -22
  505. package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.test.ts +1 -1
  506. package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.ts +1 -1
  507. package/src/plugins/defaults/memory/{graph → v1/graph}/serendipity.ts +1 -1
  508. package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.test.ts +1 -1
  509. package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.ts +1 -1
  510. package/src/plugins/defaults/memory/{identity-context.ts → v1/identity-context.ts} +4 -4
  511. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/backfill.ts +6 -6
  512. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.test.ts +6 -6
  513. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.ts +6 -6
  514. package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/index-maintenance.ts +8 -8
  515. package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.test.ts +7 -7
  516. package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.ts +5 -5
  517. package/src/plugins/defaults/memory/{pkb → v1/pkb}/autoinject.ts +1 -1
  518. package/src/plugins/defaults/memory/{pkb → v1/pkb}/context.ts +2 -2
  519. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.test.ts +3 -3
  520. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.ts +2 -2
  521. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.test.ts +3 -3
  522. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.ts +2 -2
  523. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.test.ts +3 -3
  524. package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.ts +6 -6
  525. package/src/plugins/defaults/memory/{pkb → v1/pkb}/types.ts +3 -5
  526. package/src/plugins/defaults/memory/{pkb-schedule.ts → v1/pkb-schedule.ts} +2 -2
  527. package/src/plugins/defaults/memory/{search/semantic.ts → v1/semantic-search.ts} +1 -1
  528. package/src/plugins/defaults/memory/v2/__tests__/activation-store.test.ts +1 -1
  529. package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +11 -274
  530. package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +9 -131
  531. package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -1
  532. package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -1
  533. package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
  534. package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +14 -10
  535. package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +7 -5
  536. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +12 -6
  537. package/src/plugins/defaults/memory/{memory-v2-activation-log-store.ts → v2/activation-log-store.ts} +2 -2
  538. package/src/plugins/defaults/memory/v2/activation-store.ts +22 -8
  539. package/src/plugins/defaults/memory/v2/activation.ts +30 -163
  540. package/src/plugins/defaults/memory/v2/backfill-jobs.ts +7 -54
  541. package/src/plugins/defaults/memory/{memory-v2-concept-frequency.ts → v2/concept-frequency.ts} +3 -3
  542. package/src/plugins/defaults/memory/v2/harness/oracle.ts +1 -1
  543. package/src/plugins/defaults/memory/v2/harness/replay-input.ts +2 -2
  544. package/src/plugins/defaults/memory/v2/harness/retriever.ts +1 -1
  545. package/src/plugins/defaults/memory/v2/injection.ts +36 -26
  546. package/src/plugins/defaults/memory/v2/migration.ts +2 -2
  547. package/src/plugins/defaults/memory/{rerank-local.ts → v2/rerank-local.ts} +44 -18
  548. package/src/plugins/defaults/memory/v2/reranker.ts +29 -11
  549. package/src/plugins/defaults/memory/v2/router.ts +38 -15
  550. package/src/plugins/defaults/memory/v3/__tests__/candidate-match.test.ts +5 -3
  551. package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +21 -8
  552. package/src/plugins/defaults/memory/v3/__tests__/edge.test.ts +1 -1
  553. package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +1 -1
  554. package/src/plugins/defaults/memory/v3/__tests__/maintain-job.test.ts +4 -1
  555. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +181 -3
  556. package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +3 -0
  557. package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +14 -5
  558. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +40 -50
  559. package/src/plugins/defaults/memory/v3/__tests__/tuning-profile.test.ts +1 -0
  560. package/src/plugins/defaults/memory/v3/candidate-match.ts +2 -2
  561. package/src/plugins/defaults/memory/v3/capabilities.ts +6 -4
  562. package/src/plugins/defaults/memory/v3/card.ts +25 -9
  563. package/src/plugins/defaults/memory/v3/edge.ts +52 -18
  564. package/src/plugins/defaults/memory/v3/gate.ts +4 -4
  565. package/src/plugins/defaults/memory/v3/injector.ts +10 -3
  566. package/src/plugins/defaults/memory/v3/maintain-job.ts +3 -3
  567. package/src/plugins/defaults/memory/v3/orchestrate.ts +100 -18
  568. package/src/plugins/defaults/memory/v3/page-content.ts +26 -10
  569. package/src/plugins/defaults/memory/v3/prune.ts +40 -16
  570. package/src/plugins/defaults/memory/v3/selection-log-store.ts +34 -12
  571. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +9 -13
  572. package/src/plugins/defaults/memory/v3/span-query.test.ts +86 -0
  573. package/src/plugins/defaults/memory/v3/span-query.ts +71 -0
  574. package/src/plugins/defaults/memory/v3/tuning-profile.ts +3 -0
  575. package/src/plugins/defaults/memory/v3/types.ts +4 -1
  576. package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +2 -2
  577. package/src/plugins/defaults/memory/validation.ts +1 -1
  578. package/src/plugins/defaults/memory/worker.ts +2 -1
  579. package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +104 -12
  580. package/src/plugins/defaults/platform-hosted/routes/reengage.ts +104 -12
  581. package/src/plugins/types.ts +2 -2
  582. package/src/providers/__tests__/registry-native-web-search.test.ts +47 -2
  583. package/src/providers/anthropic/client.ts +15 -6
  584. package/src/providers/content-block-schema.ts +26 -0
  585. package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +87 -0
  586. package/src/providers/inference/adapter-factory.ts +6 -0
  587. package/src/providers/inference/connections.ts +30 -14
  588. package/src/providers/model-catalog.ts +77 -0
  589. package/src/providers/openai/__tests__/chat-completions-input-audio.test.ts +260 -0
  590. package/src/providers/openai/chat-completions-provider.ts +65 -17
  591. package/src/providers/openai/input-audio.ts +76 -0
  592. package/src/providers/openrouter/client.ts +0 -2
  593. package/src/providers/platform-proxy/constants.ts +4 -0
  594. package/src/providers/poolside/client.ts +42 -0
  595. package/src/providers/registry.ts +40 -8
  596. package/src/providers/retry.ts +2 -0
  597. package/src/providers/types.ts +39 -1
  598. package/src/providers/vercel-ai-gateway/client.ts +0 -2
  599. package/src/runtime/AGENTS.md +7 -5
  600. package/src/runtime/__tests__/question-request-guardian-bridge.test.ts +173 -0
  601. package/src/runtime/__tests__/question-resolution.test.ts +111 -0
  602. package/src/runtime/access-request-helper.ts +7 -15
  603. package/src/runtime/assistant-event-hub.ts +43 -31
  604. package/src/runtime/assistant-event-publish-options.ts +31 -0
  605. package/src/runtime/assistant-event.ts +19 -30
  606. package/src/runtime/assistant-stream-state.ts +4 -4
  607. package/src/runtime/channel-approvals.ts +0 -25
  608. package/src/runtime/channel-readiness-service.ts +99 -40
  609. package/src/runtime/channel-retry-sweep.ts +38 -15
  610. package/src/runtime/confirmation-request-guardian-bridge.ts +4 -0
  611. package/src/runtime/guardian-reply-router.ts +108 -0
  612. package/src/runtime/http-server.ts +8 -0
  613. package/src/runtime/http-types.ts +2 -2
  614. package/src/runtime/process-role.ts +42 -0
  615. package/src/runtime/question-request-guardian-bridge.ts +184 -0
  616. package/src/runtime/question-resolution.ts +153 -0
  617. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +6 -2
  618. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -1
  619. package/src/runtime/routes/acp-routes.ts +2 -2
  620. package/src/runtime/routes/bookmark-routes.ts +3 -15
  621. package/src/runtime/routes/canned-message-complete.ts +2 -2
  622. package/src/runtime/routes/consolidation-routes.ts +8 -2
  623. package/src/runtime/routes/conversation-list-routes.ts +3 -19
  624. package/src/runtime/routes/conversation-management-routes.ts +1 -5
  625. package/src/runtime/routes/conversation-query-routes.ts +52 -8
  626. package/src/runtime/routes/conversation-routes.ts +36 -22
  627. package/src/runtime/routes/credential-request-routes.ts +0 -1
  628. package/src/runtime/routes/filing-routes.ts +7 -7
  629. package/src/runtime/routes/global-search-routes.ts +1 -1
  630. package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
  631. package/src/runtime/routes/image-generation-routes.ts +12 -9
  632. package/src/runtime/routes/inbound-message-handler.ts +17 -0
  633. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +50 -0
  634. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +19 -0
  635. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -4
  636. package/src/runtime/routes/inbound-stages/inbound-content-prep.test.ts +129 -0
  637. package/src/runtime/routes/inbound-stages/inbound-content-prep.ts +141 -9
  638. package/src/runtime/routes/index.ts +2 -0
  639. package/src/runtime/routes/lifecycle-routes.ts +199 -0
  640. package/src/runtime/routes/platform-routes.ts +3 -8
  641. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
  642. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
  643. package/src/runtime/routes/question-routes.ts +34 -87
  644. package/src/runtime/routes/secret-routes.ts +11 -1
  645. package/src/runtime/routes/settings-routes.ts +8 -18
  646. package/src/runtime/routes/upgrade-broadcast-routes.ts +4 -5
  647. package/src/runtime/routes/workspace-routes.test.ts +7 -4
  648. package/src/runtime/slack-reply-session.test.ts +12 -12
  649. package/src/runtime/slack-reply-session.ts +17 -17
  650. package/src/runtime/sync/sync-publisher.test.ts +7 -5
  651. package/src/runtime/tool-grant-request-helper.ts +4 -0
  652. package/src/schedule/schedule-store.ts +70 -0
  653. package/src/schedule/scheduler.ts +27 -0
  654. package/src/security/AGENTS.md +1 -1
  655. package/src/security/credential-key.ts +17 -0
  656. package/src/security/secret-ingress.ts +14 -105
  657. package/src/security/secret-patterns.ts +8 -139
  658. package/src/security/secret-scanner.ts +8 -3
  659. package/src/security/store-path-override.ts +6 -16
  660. package/src/sequence/store.ts +8 -0
  661. package/src/signals/emit-event.ts +5 -10
  662. package/src/signals/event-stream.ts +20 -10
  663. package/src/subagent/manager.ts +76 -25
  664. package/src/subagent/notify.ts +8 -0
  665. package/src/subagent/types.ts +13 -3
  666. package/src/telegram/__tests__/webhook-health.test.ts +442 -0
  667. package/src/telegram/webhook-health.ts +478 -0
  668. package/src/telemetry/AGENTS.md +6 -0
  669. package/src/telemetry/memory-corpus-size.test.ts +129 -0
  670. package/src/telemetry/memory-corpus-size.ts +184 -0
  671. package/src/telemetry/memory-tier-reporter.test.ts +67 -2
  672. package/src/telemetry/memory-tier-reporter.ts +30 -3
  673. package/src/tools/__tests__/document-tool-input-schemas.test.ts +103 -0
  674. package/src/tools/__tests__/followup-call-acp-tool-input-schemas.test.ts +125 -0
  675. package/src/tools/__tests__/schedule-tool-input-schemas.test.ts +83 -0
  676. package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +116 -0
  677. package/src/tools/__tests__/tool-input-schemas.test.ts +192 -0
  678. package/src/tools/__tests__/tool-schema-drift-harness.ts +142 -0
  679. package/src/tools/acp/abort.ts +21 -1
  680. package/src/tools/acp/context.ts +5 -5
  681. package/src/tools/acp/spawn.test.ts +15 -5
  682. package/src/tools/acp/spawn.ts +26 -3
  683. package/src/tools/acp/status.ts +20 -1
  684. package/src/tools/acp/steer.test.ts +20 -0
  685. package/src/tools/acp/steer.ts +23 -2
  686. package/src/tools/ask-question/ask-question-tool.test.ts +65 -0
  687. package/src/tools/ask-question/ask-question-tool.ts +68 -92
  688. package/src/tools/browser/browser-screencast.ts +6 -6
  689. package/src/tools/calls/call-end.ts +24 -3
  690. package/src/tools/calls/call-start.ts +35 -11
  691. package/src/tools/calls/call-status.ts +20 -1
  692. package/src/tools/document/document-comment-tool.test.ts +49 -0
  693. package/src/tools/document/document-comment-tool.ts +45 -6
  694. package/src/tools/document/document-tool.ts +142 -24
  695. package/src/tools/executor.ts +27 -13
  696. package/src/tools/filesystem/edit.ts +62 -60
  697. package/src/tools/filesystem/list.ts +36 -29
  698. package/src/tools/filesystem/read.ts +56 -39
  699. package/src/tools/filesystem/write.ts +44 -38
  700. package/src/tools/followups/followup_create.ts +41 -12
  701. package/src/tools/followups/followup_list.ts +34 -6
  702. package/src/tools/followups/followup_resolve.ts +26 -4
  703. package/src/tools/host-filesystem/edit.ts +50 -60
  704. package/src/tools/host-filesystem/read.ts +45 -39
  705. package/src/tools/host-filesystem/write.ts +31 -36
  706. package/src/tools/host-terminal/host-shell.ts +76 -62
  707. package/src/tools/policy-context.ts +27 -10
  708. package/src/tools/schedule/create.ts +76 -33
  709. package/src/tools/schedule/delete.ts +21 -2
  710. package/src/tools/schedule/list.ts +25 -3
  711. package/src/tools/schedule/update.ts +105 -48
  712. package/src/tools/shared/filesystem/path-policy.ts +246 -40
  713. package/src/tools/shared/zod-tool-schema.ts +117 -0
  714. package/src/tools/subagent/abort.ts +12 -4
  715. package/src/tools/subagent/consult-deadline.ts +9 -3
  716. package/src/tools/subagent/message.ts +21 -5
  717. package/src/tools/subagent/notify-parent.ts +44 -23
  718. package/src/tools/subagent/read.ts +15 -4
  719. package/src/tools/subagent/resolve.ts +26 -4
  720. package/src/tools/subagent/spawn.ts +37 -13
  721. package/src/tools/subagent/status.ts +12 -4
  722. package/src/tools/system/request-permission.ts +35 -26
  723. package/src/tools/terminal/shell.ts +68 -55
  724. package/src/tools/tool-approval-handler.ts +327 -53
  725. package/src/tools/tool-input-schemas.ts +85 -0
  726. package/src/tools/tool-types.ts +7 -0
  727. package/src/tools/types.ts +8 -0
  728. package/src/tools/workflows/manage-workflows.ts +30 -2
  729. package/src/tools/workflows/run-workflow.test.ts +54 -2
  730. package/src/tools/workflows/run-workflow.ts +32 -4
  731. package/src/util/fs-symlinks.ts +30 -0
  732. package/src/util/log-redact.ts +7 -3
  733. package/src/vellum-assistant-namespace.d.ts +80 -0
  734. package/src/watcher/watcher-store.ts +8 -0
  735. package/src/workflows/leaf-runner.test.ts +104 -2
  736. package/src/workflows/leaf-runner.ts +31 -6
  737. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +2 -2
  738. package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +128 -0
  739. package/src/workspace/migrations/135-copy-substrate-tunables.ts +248 -0
  740. package/src/workspace/migrations/__tests__/135-copy-substrate-tunables.test.ts +446 -0
  741. package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +2 -2
  742. package/src/workspace/migrations/registry.ts +4 -0
  743. package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
  744. package/src/__tests__/secret-patterns.test.ts +0 -27
  745. package/src/config/__tests__/proc-to-skills.test.ts +0 -21
  746. package/src/config/memory-tier.test.ts +0 -44
  747. package/src/daemon/message-types/acp.ts +0 -20
  748. package/src/daemon/message-types/apps.ts +0 -11
  749. package/src/daemon/message-types/background-tools.ts +0 -14
  750. package/src/daemon/message-types/bookmarks.ts +0 -13
  751. package/src/daemon/message-types/contacts.ts +0 -13
  752. package/src/daemon/message-types/document-comments.ts +0 -14
  753. package/src/daemon/message-types/documents.ts +0 -13
  754. package/src/daemon/message-types/home.ts +0 -15
  755. package/src/daemon/message-types/host-bash.ts +0 -12
  756. package/src/daemon/message-types/host-cu.ts +0 -10
  757. package/src/daemon/message-types/host-file.ts +0 -12
  758. package/src/daemon/message-types/host-transfer.ts +0 -12
  759. package/src/daemon/message-types/integrations.ts +0 -90
  760. package/src/daemon/message-types/memory.ts +0 -10
  761. package/src/daemon/message-types/schedules.ts +0 -14
  762. package/src/daemon/message-types/settings.ts +0 -17
  763. package/src/daemon/message-types/subagents.ts +0 -63
  764. package/src/daemon/message-types/upgrades.ts +0 -14
  765. package/src/daemon/message-types/workflows.ts +0 -25
  766. package/src/daemon/message-types/workspace.ts +0 -137
  767. package/src/live-voice/ack-phrases.ts +0 -58
  768. package/src/plugins/defaults/memory/retrieval-budget.ts +0 -29
  769. package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +0 -69
  770. package/src/plugins/defaults/memory/v3/gate-flag.ts +0 -20
  771. package/src/plugins/defaults/memory/v3/substrate/__tests__/memory-v2-startup.test.ts +0 -86
  772. package/src/plugins/defaults/memory/v3/substrate/memory-v2-startup.test.ts +0 -205
  773. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/concept-page-frontmatter-schema.test.ts +0 -0
  774. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-prompt-flag-gating-guard.test.ts +0 -0
  775. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/injected-block-slugs.test.ts +0 -0
  776. /package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-content.ts +0 -0
@@ -0,0 +1,183 @@
1
+ import { z } from "zod";
2
+
3
+ import { WEIGHT_SUM_TOLERANCE } from "./memory-v2.js";
4
+
5
+ /**
6
+ * Memory substrate (shared concept-page infrastructure) tuning.
7
+ *
8
+ * Every key is optional with no default: an unset key resolves to its
9
+ * historical `memory.v2` counterpart via `resolveSubstrateTuning` (the
10
+ * substrate's single config choke point), so the v2 schema keeps supplying
11
+ * the effective defaults. `spread_k`, `spread_hops`, and
12
+ * `ann_candidate_limit` map onto `memory.v2.k`, `memory.v2.hops`, and
13
+ * `memory.v2.ann_candidate_limit` respectively; every other key shares its
14
+ * name with its `memory.v2` twin.
15
+ */
16
+ export const MemorySubstrateConfigSchema = z
17
+ .object({
18
+ sweep_enabled: z
19
+ .boolean({ error: "memory.substrate.sweep_enabled must be a boolean" })
20
+ .optional()
21
+ .describe(
22
+ "Whether the idle-debounced memory sweep job is enabled. `remember()` is the primary capture path; opt in only when the model is missing entries the sweep would have caught.",
23
+ ),
24
+ dense_weight: z
25
+ .number({ error: "memory.substrate.dense_weight must be a number" })
26
+ .min(0, "memory.substrate.dense_weight must be >= 0")
27
+ .max(1, "memory.substrate.dense_weight must be <= 1")
28
+ .optional()
29
+ .describe(
30
+ "Weight on dense (cosine) similarity in the hybrid retrieval score.",
31
+ ),
32
+ sparse_weight: z
33
+ .number({ error: "memory.substrate.sparse_weight must be a number" })
34
+ .min(0, "memory.substrate.sparse_weight must be >= 0")
35
+ .max(1, "memory.substrate.sparse_weight must be <= 1")
36
+ .optional()
37
+ .describe(
38
+ "Weight on sparse (BM25-style) similarity in the hybrid retrieval score — sparse acts as a discriminator for keyword-rich queries.",
39
+ ),
40
+ min_sparse_spread: z
41
+ .number({ error: "memory.substrate.min_sparse_spread must be a number" })
42
+ .min(0, "memory.substrate.min_sparse_spread must be >= 0")
43
+ .max(1, "memory.substrate.min_sparse_spread must be <= 1")
44
+ .optional()
45
+ .describe(
46
+ "Adaptive sparse weighting: when the spread (max - min) of normalized sparse scores across the candidate hit set falls below this, sparse contribution collapses to 0. Linear interpolation between this and `full_sparse_spread`. Optional escape hatch — leave unset to use the built-in default.",
47
+ ),
48
+ full_sparse_spread: z
49
+ .number({ error: "memory.substrate.full_sparse_spread must be a number" })
50
+ .min(0, "memory.substrate.full_sparse_spread must be >= 0")
51
+ .max(1, "memory.substrate.full_sparse_spread must be <= 1")
52
+ .optional()
53
+ .describe(
54
+ "Adaptive sparse weighting: at or above this spread, sparse weight stays at the configured `sparse_weight`. Optional escape hatch — leave unset to use the built-in default.",
55
+ ),
56
+ bm25_k1: z
57
+ .number({ error: "memory.substrate.bm25_k1 must be a number" })
58
+ .min(0, "memory.substrate.bm25_k1 must be >= 0")
59
+ .optional()
60
+ .describe(
61
+ "BM25 term-frequency saturation parameter. Increase to make repeated mentions of a term matter more, decrease to flatten the curve.",
62
+ ),
63
+ bm25_b: z
64
+ .number({ error: "memory.substrate.bm25_b must be a number" })
65
+ .min(0, "memory.substrate.bm25_b must be >= 0")
66
+ .max(1, "memory.substrate.bm25_b must be <= 1")
67
+ .optional()
68
+ .describe(
69
+ "BM25 document-length normalization. 0 disables length normalization, 1 fully normalizes. Concept-page collections include structured list pages with high information density per word, so values below Lucene's 0.75 default avoid over-penalizing them.",
70
+ ),
71
+ consolidation_interval_hours: z
72
+ .number({
73
+ error: "memory.substrate.consolidation_interval_hours must be a number",
74
+ })
75
+ .int("memory.substrate.consolidation_interval_hours must be an integer")
76
+ .positive(
77
+ "memory.substrate.consolidation_interval_hours must be a positive integer",
78
+ )
79
+ .optional()
80
+ .describe(
81
+ "Hours between scheduled consolidation runs that synthesize buffered memories into concept pages",
82
+ ),
83
+ consolidation_max_buffer_lines: z
84
+ .number({
85
+ error:
86
+ "memory.substrate.consolidation_max_buffer_lines must be a number",
87
+ })
88
+ .int("memory.substrate.consolidation_max_buffer_lines must be an integer")
89
+ .positive(
90
+ "memory.substrate.consolidation_max_buffer_lines must be a positive integer",
91
+ )
92
+ .nullable()
93
+ .optional()
94
+ .describe(
95
+ "Size-based trigger for consolidation. When `memory/buffer.md` reaches this many non-empty lines, consolidation runs even if the time-based interval hasn't elapsed. Set to `null` to disable the size trigger and rely solely on `consolidation_interval_hours`.",
96
+ ),
97
+ consolidation_max_entries_per_run: z
98
+ .number({
99
+ error:
100
+ "memory.substrate.consolidation_max_entries_per_run must be a number",
101
+ })
102
+ .int(
103
+ "memory.substrate.consolidation_max_entries_per_run must be an integer",
104
+ )
105
+ .positive(
106
+ "memory.substrate.consolidation_max_entries_per_run must be a positive integer",
107
+ )
108
+ .nullable()
109
+ .optional()
110
+ .describe(
111
+ "Upper bound on buffer entries one consolidation run may process. When the buffer holds more, the run's cutoff is moved back to the first over-cap entry's timestamp so the overflow is deferred to a follow-up pass. Bounds the context a single agentic run must read after a backlog. Set to `null` to always process the full buffer.",
112
+ ),
113
+ max_page_chars: z
114
+ .number({ error: "memory.substrate.max_page_chars must be a number" })
115
+ .int("memory.substrate.max_page_chars must be an integer")
116
+ .positive("memory.substrate.max_page_chars must be a positive integer")
117
+ .optional()
118
+ .describe(
119
+ "Soft upper bound on concept-page body length — pages exceeding this are flagged for split during consolidation",
120
+ ),
121
+ consolidation_prompt_path: z
122
+ .string({
123
+ error: "memory.substrate.consolidation_prompt_path must be a string",
124
+ })
125
+ .nullable()
126
+ .optional()
127
+ .describe(
128
+ "Optional path to a file whose contents replace the bundled consolidation prompt. Relative paths resolve under the workspace root; absolute paths and a leading `~/` (expanded to the home directory) are honored only when they still resolve inside the workspace root — a path that lands outside the workspace (including via symlinks) is rejected. The loaded contents may include `{{CUTOFF}}`, which is substituted with the run's ISO-8601 cutoff timestamp. If the file is rejected, missing, unreadable, or empty, the bundled prompt is used and a warning is logged.",
129
+ ),
130
+ spread_k: z
131
+ .number({ error: "memory.substrate.spread_k must be a number" })
132
+ .min(0, "memory.substrate.spread_k must be >= 0")
133
+ .max(1, "memory.substrate.spread_k must be <= 1")
134
+ .optional()
135
+ .describe(
136
+ "Spreading-activation propagation coefficient — fraction of own activation that flows to neighbors per hop. Falls back to `memory.v2.k`.",
137
+ ),
138
+ spread_hops: z
139
+ .number({ error: "memory.substrate.spread_hops must be a number" })
140
+ .int("memory.substrate.spread_hops must be an integer")
141
+ .nonnegative("memory.substrate.spread_hops must be non-negative")
142
+ .optional()
143
+ .describe(
144
+ "Maximum BFS distance for spreading activation across the concept graph. Falls back to `memory.v2.hops`.",
145
+ ),
146
+ ann_candidate_limit: z
147
+ .number({
148
+ error: "memory.substrate.ann_candidate_limit must be a number",
149
+ })
150
+ .int("memory.substrate.ann_candidate_limit must be an integer")
151
+ .positive(
152
+ "memory.substrate.ann_candidate_limit must be a positive integer",
153
+ )
154
+ .nullable()
155
+ .optional()
156
+ .describe(
157
+ "Per-channel cap on the unrestricted ANN candidate query used by memory recall (dense and sparse each return up to this many hits before they are unioned). `null` = unlimited (every page in the concept-page collection is eligible).",
158
+ ),
159
+ })
160
+ .describe(
161
+ "Memory substrate tuning — overrides for the shared concept-page infrastructure (consolidation, hybrid retrieval, BM25 encoding, sweep). Unset keys resolve to their historical `memory.v2` counterparts.",
162
+ )
163
+ .superRefine((config, ctx) => {
164
+ if (
165
+ config.dense_weight === undefined ||
166
+ config.sparse_weight === undefined
167
+ ) {
168
+ return;
169
+ }
170
+ const hybridSum = config.dense_weight + config.sparse_weight;
171
+ if (Math.abs(hybridSum - 1.0) >= WEIGHT_SUM_TOLERANCE) {
172
+ const message = `memory.substrate hybrid weights (dense_weight + sparse_weight) must sum to 1.0 (got ${hybridSum.toFixed(4)})`;
173
+ for (const path of ["dense_weight", "sparse_weight"] as const) {
174
+ ctx.addIssue({
175
+ code: z.ZodIssueCode.custom,
176
+ path: [path],
177
+ message,
178
+ });
179
+ }
180
+ }
181
+ });
182
+
183
+ export type MemorySubstrateConfig = z.infer<typeof MemorySubstrateConfigSchema>;
@@ -3,9 +3,10 @@ import { z } from "zod";
3
3
  /**
4
4
  * Tolerance for floating-point comparisons of weight sums. Using 0.001 lets
5
5
  * users specify weights to three decimal places without spurious rejections,
6
- * while still catching obvious mis-sums.
6
+ * while still catching obvious mis-sums. Shared with the `memory.substrate`
7
+ * schema so both namespaces apply the same hybrid-weight refinement.
7
8
  */
8
- const WEIGHT_SUM_TOLERANCE = 0.001;
9
+ export const WEIGHT_SUM_TOLERANCE = 0.001;
9
10
 
10
11
  /**
11
12
  * Default cross-encoder model for memory v2 reranking.
@@ -252,8 +252,7 @@ export const MemoryV3EntitySchema = z
252
252
  /**
253
253
  * Per-turn injection-gate tuning: thresholds the retrieval signals must clear
254
254
  * for the gate to open and run the selector. The gate runs only when the
255
- * `memory-v3-injection-gate` feature flag (the rollout switch) AND the
256
- * `enabled` kill-switch below are both on.
255
+ * `enabled` kill-switch below is on.
257
256
  */
258
257
  export const MemoryV3GateSchema = z
259
258
  .object({
@@ -261,7 +260,7 @@ export const MemoryV3GateSchema = z
261
260
  .boolean({ error: "memory.v3.gate.enabled must be a boolean" })
262
261
  .default(true)
263
262
  .describe(
264
- "Whether the injection gate may run at all. false forces the full selection process every turn regardless of the `memory-v3-injection-gate` feature flag; true (default) defers to the flag.",
263
+ "Whether the injection gate may run at all. false forces the full selection process every turn; true (default) lets the gate run when the thresholds are met.",
265
264
  ),
266
265
  denseThreshold: z
267
266
  .number({ error: "memory.v3.gate.denseThreshold must be a number" })
@@ -327,7 +326,7 @@ export const MemoryV3GateSchema = z
327
326
  ),
328
327
  })
329
328
  .describe(
330
- "Memory v3 per-turn injection gate tuning (thresholds; the gate runs when the `memory-v3-injection-gate` feature flag AND `enabled` are both on).",
329
+ "Memory v3 per-turn injection gate tuning (thresholds; the gate runs when `enabled` is on).",
331
330
  );
332
331
 
333
332
  // NOTE: a retired `workingSet` sub-config (maxPages/evictWindow for the old
@@ -383,6 +382,14 @@ export const MemoryV3ConfigSchema = z
383
382
  .describe(
384
383
  "Per-lane article budget for the reply-query finder pass: needle and dense each re-run over the assistant's previous message as separate queries (never concatenated with the user's message). 0 disables the pass. Deliberately small next to needleK/denseK — the pass adds the assistant-side retrieval signal, not a second full sweep.",
385
384
  ),
385
+ spanQueryK: z
386
+ .number({ error: "memory.v3.spanQueryK must be a number" })
387
+ .int("memory.v3.spanQueryK must be an integer")
388
+ .nonnegative("memory.v3.spanQueryK must be a non-negative integer")
389
+ .default(0)
390
+ .describe(
391
+ "Per-chunk article budget for the span-query dense pass: the current message's clause spans (merged into at most 8 contiguous chunks) re-run through the dense lane as separate queries, union-additive into the candidate pool. 0 disables the pass; it is also inert when denseK is 0 or the message yields fewer than two chunks. Deliberately small next to denseK — the pass rescues motifs a long message's single query vector averages away, not a second full sweep.",
392
+ ),
386
393
  selectorEnabled: z
387
394
  .boolean({ error: "memory.v3.selectorEnabled must be a boolean" })
388
395
  .default(true)
@@ -17,7 +17,8 @@ import {
17
17
  MemorySegmentationConfigSchema,
18
18
  QdrantConfigSchema,
19
19
  } from "./memory-storage.js";
20
- import { MemoryV2ConfigSchema } from "./memory-v2.js";
20
+ import { MemorySubstrateConfigSchema } from "./memory-substrate.js";
21
+ import { MemoryV2ConfigSchema, WEIGHT_SUM_TOLERANCE } from "./memory-v2.js";
21
22
  import { MemoryV3ConfigSchema } from "./memory-v3.js";
22
23
 
23
24
  export const MemoryConfigSchema = z
@@ -54,6 +55,9 @@ export const MemoryConfigSchema = z
54
55
  summarization: MemorySummarizationConfigSchema.default(
55
56
  MemorySummarizationConfigSchema.parse({}),
56
57
  ),
58
+ substrate: MemorySubstrateConfigSchema.default(
59
+ MemorySubstrateConfigSchema.parse({}),
60
+ ),
57
61
  v2: MemoryV2ConfigSchema.default(MemoryV2ConfigSchema.parse({})),
58
62
  v3: MemoryV3ConfigSchema.default(MemoryV3ConfigSchema.parse({})),
59
63
  retrospective: MemoryRetrospectiveConfigSchema.default(
@@ -118,6 +122,36 @@ export const MemoryConfigSchema = z
118
122
  "memory.retrieval.injection.perTurn.capabilityReserve + serendipitySlots must be less than maxNodes",
119
123
  });
120
124
  }
125
+ // Resolved hybrid-weight invariant. `resolveSubstrateTuning` pairs each
126
+ // `memory.substrate` weight with its `memory.v2` twin on an
127
+ // undefined-only fallback, so a single substrate weight forms its
128
+ // effective pair with the v2 value (schema default applied by now). The
129
+ // substrate schema's own refinement already covers the both-set case, and
130
+ // the v2 schema covers the neither-set case — this check guards the mixed
131
+ // case those local refinements cannot see.
132
+ const substrateDense = config.substrate?.dense_weight;
133
+ const substrateSparse = config.substrate?.sparse_weight;
134
+ const oneSubstrateWeightSet =
135
+ (substrateDense === undefined) !== (substrateSparse === undefined);
136
+ if (oneSubstrateWeightSet) {
137
+ const effectiveDense =
138
+ substrateDense !== undefined ? substrateDense : config.v2.dense_weight;
139
+ const effectiveSparse =
140
+ substrateSparse !== undefined
141
+ ? substrateSparse
142
+ : config.v2.sparse_weight;
143
+ const effectiveSum = effectiveDense + effectiveSparse;
144
+ if (Math.abs(effectiveSum - 1.0) >= WEIGHT_SUM_TOLERANCE) {
145
+ ctx.addIssue({
146
+ code: z.ZodIssueCode.custom,
147
+ path: [
148
+ "substrate",
149
+ substrateDense !== undefined ? "dense_weight" : "sparse_weight",
150
+ ],
151
+ message: `memory hybrid weights must sum to 1.0 after memory.substrate → memory.v2 fallback (effective dense_weight ${effectiveDense.toFixed(4)} + sparse_weight ${effectiveSparse.toFixed(4)} = ${effectiveSum.toFixed(4)})`,
152
+ });
153
+ }
154
+ }
121
155
  });
122
156
 
123
157
  export type MemoryConfig = z.infer<typeof MemoryConfigSchema>;
@@ -20,7 +20,9 @@ export const VALID_INFERENCE_PROVIDERS = [
20
20
  "openrouter",
21
21
  ] as const;
22
22
 
23
- const VALID_IMAGE_GEN_PROVIDERS = ["gemini", "openai"] as const;
23
+ // `vellum` generates through the platform runtime proxy; the backend
24
+ // (gemini/openai) derives from the selected model's prefix at request time.
25
+ const VALID_IMAGE_GEN_PROVIDERS = ["vellum", "gemini", "openai"] as const;
24
26
 
25
27
  /**
26
28
  * Derived from `SEARCH_PROVIDER_CATALOG`. Adding a new web-search provider
@@ -51,7 +53,13 @@ const BaseServiceSchema = z.object({
51
53
  */
52
54
  const InferenceServiceSchema = z.object({});
53
55
 
54
- const ImageGenerationServiceSchema = BaseServiceSchema.extend({
56
+ /**
57
+ * Image generation carries no `mode`: `provider` is the only axis. `"vellum"`
58
+ * generates through the platform runtime proxy for the model-appropriate
59
+ * backend, billed to Vellum credits; `"gemini"`/`"openai"` use the user's
60
+ * key. A `mode` key sent by an older client is stripped at parse.
61
+ */
62
+ const ImageGenerationServiceSchema = z.object({
55
63
  provider: z.enum(VALID_IMAGE_GEN_PROVIDERS).default("gemini"),
56
64
  model: z.string().default(DEFAULT_IMAGE_MODEL),
57
65
  });
@@ -0,0 +1,195 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Memory substrate — twin-namespace shadowing detection
3
+ // ---------------------------------------------------------------------------
4
+
5
+ /** One `memory.v2` tunable's `memory.substrate` twin. */
6
+ interface SubstrateTwin {
7
+ /** The twin's `memory.substrate` key, e.g. `spread_k` for `k`. */
8
+ readonly substrateKey: string;
9
+ /**
10
+ * Whether the v2 injection engine reads the `memory.v2` key straight out of
11
+ * its own namespace (`v2/injection.ts`, `v2/activation.ts`,
12
+ * `v2/backfill-jobs.ts`) rather than through `resolveSubstrateTuning`. For
13
+ * these keys the two namespaces feed two different consumers, so a
14
+ * `memory.v2` write retunes the v2 engine while substrate recall keeps
15
+ * reading the substrate twin — the pair can hold different effective values
16
+ * at once.
17
+ */
18
+ readonly alsoReadByV2Engine: boolean;
19
+ }
20
+
21
+ /**
22
+ * `memory.v2` key → its `memory.substrate` twin, for the fifteen substrate
23
+ * tunables that exist in both namespaces. `k` / `hops` are the historical
24
+ * `memory.v2` names for `spread_k` / `spread_hops`; every other key shares its
25
+ * name with its twin.
26
+ *
27
+ * Substrate precedence lives in `resolveSubstrateTuning`
28
+ * (`plugins/defaults/memory/substrate/tuning.ts`), which resolves each tunable
29
+ * as `memory.substrate.X ?? memory.v2.X`. Twelve keys reach the runtime only
30
+ * through that resolver; the three carrying `alsoReadByV2Engine` are read a
31
+ * second time by the live v2 injection engine off `config.memory.v2` directly.
32
+ *
33
+ * This table is the config surface's view of the same pairing, kept honest by
34
+ * `__tests__/substrate-twin-shadowing.test.ts`, which asserts it covers exactly
35
+ * the `memory.substrate` schema's keys.
36
+ */
37
+ export const SUBSTRATE_TWIN_BY_V2_KEY: Readonly<Record<string, SubstrateTwin>> =
38
+ {
39
+ sweep_enabled: { substrateKey: "sweep_enabled", alsoReadByV2Engine: false },
40
+ dense_weight: { substrateKey: "dense_weight", alsoReadByV2Engine: false },
41
+ sparse_weight: { substrateKey: "sparse_weight", alsoReadByV2Engine: false },
42
+ min_sparse_spread: {
43
+ substrateKey: "min_sparse_spread",
44
+ alsoReadByV2Engine: false,
45
+ },
46
+ full_sparse_spread: {
47
+ substrateKey: "full_sparse_spread",
48
+ alsoReadByV2Engine: false,
49
+ },
50
+ bm25_k1: { substrateKey: "bm25_k1", alsoReadByV2Engine: false },
51
+ bm25_b: { substrateKey: "bm25_b", alsoReadByV2Engine: false },
52
+ consolidation_interval_hours: {
53
+ substrateKey: "consolidation_interval_hours",
54
+ alsoReadByV2Engine: false,
55
+ },
56
+ consolidation_max_buffer_lines: {
57
+ substrateKey: "consolidation_max_buffer_lines",
58
+ alsoReadByV2Engine: false,
59
+ },
60
+ consolidation_max_entries_per_run: {
61
+ substrateKey: "consolidation_max_entries_per_run",
62
+ alsoReadByV2Engine: false,
63
+ },
64
+ max_page_chars: {
65
+ substrateKey: "max_page_chars",
66
+ alsoReadByV2Engine: false,
67
+ },
68
+ consolidation_prompt_path: {
69
+ substrateKey: "consolidation_prompt_path",
70
+ alsoReadByV2Engine: false,
71
+ },
72
+ // The v2 injection engine reads these three off `config.memory.v2`:
73
+ // `k` / `hops` in `v2/injection.ts` and `v2/backfill-jobs.ts`,
74
+ // `ann_candidate_limit` in `v2/activation.ts`.
75
+ k: { substrateKey: "spread_k", alsoReadByV2Engine: true },
76
+ hops: { substrateKey: "spread_hops", alsoReadByV2Engine: true },
77
+ ann_candidate_limit: {
78
+ substrateKey: "ann_candidate_limit",
79
+ alsoReadByV2Engine: true,
80
+ },
81
+ };
82
+
83
+ /** A `memory.substrate` value set on the twin of a given `memory.v2` key. */
84
+ export type SubstrateShadowing = {
85
+ /** Dotted path of the twin, e.g. `memory.substrate.spread_k`. */
86
+ substratePath: string;
87
+ /** The twin's persisted value — what substrate recall resolves to. */
88
+ substrateValue: unknown;
89
+ /**
90
+ * Whether the v2 injection engine also reads the `memory.v2` key directly,
91
+ * so the write is not inert (see {@link SubstrateTwin.alsoReadByV2Engine}).
92
+ */
93
+ alsoReadByV2Engine: boolean;
94
+ };
95
+
96
+ function readPlainObject(value: unknown): Record<string, unknown> | undefined {
97
+ return value != null && typeof value === "object" && !Array.isArray(value)
98
+ ? (value as Record<string, unknown>)
99
+ : undefined;
100
+ }
101
+
102
+ /**
103
+ * The `memory.substrate` twin covering `path`, or `undefined` when `path` is
104
+ * not a shadowable `memory.v2` tunable or its twin is unset.
105
+ *
106
+ * `memory.substrate` is override-only and wins for substrate recall whenever
107
+ * its key is present — including when it holds an explicit `null`, which
108
+ * `resolveSubstrateTuning` treats as present. Detection therefore keys on
109
+ * presence, not truthiness. What that means for the `memory.v2` key depends on
110
+ * `alsoReadByV2Engine`: for a substrate-only twin the `memory.v2` value has no
111
+ * remaining consumer, while for the three engine-read twins it still tunes v2
112
+ * injection.
113
+ *
114
+ * `raw` is the unparsed config object (`loadRawConfig()` / the `config_get`
115
+ * payload), so the check sees exactly what is persisted.
116
+ */
117
+ export function findSubstrateShadowing(
118
+ raw: Record<string, unknown>,
119
+ path: string,
120
+ ): SubstrateShadowing | undefined {
121
+ const segments = path.split(".");
122
+ if (segments.length !== 3 || segments[0] !== "memory") {
123
+ return undefined;
124
+ }
125
+ const [, namespace, key] = segments as [string, string, string];
126
+ if (namespace !== "v2") {
127
+ return undefined;
128
+ }
129
+ const twin = SUBSTRATE_TWIN_BY_V2_KEY[key];
130
+ if (twin === undefined) {
131
+ return undefined;
132
+ }
133
+ const substrate = readPlainObject(readPlainObject(raw.memory)?.substrate);
134
+ if (!substrate || !(twin.substrateKey in substrate)) {
135
+ return undefined;
136
+ }
137
+ return {
138
+ substratePath: `memory.substrate.${twin.substrateKey}`,
139
+ substrateValue: substrate[twin.substrateKey],
140
+ alsoReadByV2Engine: twin.alsoReadByV2Engine,
141
+ };
142
+ }
143
+
144
+ /**
145
+ * Operator-facing warning for a `config set` on a `memory.v2` tunable whose
146
+ * `memory.substrate` twin is set.
147
+ *
148
+ * Two classes, two messages. A substrate-only twin leaves the write with no
149
+ * consumer, so the warning names the winning key and the command that actually
150
+ * retunes it. An engine-read twin (`k`, `hops`, `ann_candidate_limit`) makes
151
+ * the write effective for v2 injection while substrate recall stays on the
152
+ * twin, so the warning reports the split rather than a no-op.
153
+ */
154
+ export function describeShadowedConfigSet(
155
+ shadowing: SubstrateShadowing,
156
+ path: string,
157
+ ): string {
158
+ const value = JSON.stringify(shadowing.substrateValue) ?? "undefined";
159
+ if (shadowing.alsoReadByV2Engine) {
160
+ return (
161
+ `${path} is read directly by the memory-v2 injection engine, so this write ` +
162
+ `does change its behavior. Substrate recall reads ${shadowing.substratePath} ` +
163
+ `(${value}) instead, so the two can diverge. ` +
164
+ `Run 'assistant config set ${shadowing.substratePath} <value>' to move substrate recall with it.`
165
+ );
166
+ }
167
+ return (
168
+ `${shadowing.substratePath} is set (${value}) and takes precedence over ${path}, ` +
169
+ `so this write does not change the effective value. ` +
170
+ `Run 'assistant config set ${shadowing.substratePath} <value>' to retune it.`
171
+ );
172
+ }
173
+
174
+ /**
175
+ * Operator-facing annotation for a `config get` of a `memory.v2` tunable whose
176
+ * `memory.substrate` twin is set — the read-side counterpart of
177
+ * {@link describeShadowedConfigSet}, split along the same two classes so a read
178
+ * never confirms a value the runtime ignores nor denies one it honors.
179
+ */
180
+ export function describeShadowedConfigGet(
181
+ shadowing: SubstrateShadowing,
182
+ path: string,
183
+ ): string {
184
+ const value = JSON.stringify(shadowing.substrateValue) ?? "undefined";
185
+ if (shadowing.alsoReadByV2Engine) {
186
+ return (
187
+ `Split: ${shadowing.substratePath} = ${value} is the effective value for ` +
188
+ `substrate recall, while the memory-v2 injection engine reads ${path} above.`
189
+ );
190
+ }
191
+ return (
192
+ `Shadowed: ${shadowing.substratePath} = ${value} takes precedence and is ` +
193
+ `the effective value.`
194
+ );
195
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Derivations answering "is this deployment set up to receive provider
3
+ * webhooks?" from workspace config.
4
+ *
5
+ * Two consumers ask the same question for different reasons: the channel
6
+ * readiness probes report it to the user, and the Telegram webhook health
7
+ * sweep uses it to decide whether a missing/broken registration is even
8
+ * meaningful. Both must agree — a probe that says "ingress is configured"
9
+ * while the sweep says "no webhook expected" would be a silent divergence.
10
+ */
11
+
12
+ import {
13
+ normalizePublicBaseUrl,
14
+ resolveTwilioPublicBaseUrl,
15
+ } from "@vellumai/service-contracts/twilio-ingress";
16
+
17
+ import { getIsPlatform } from "./env-registry.js";
18
+ import { loadRawConfig } from "./loader.js";
19
+
20
+ /**
21
+ * True when a public ingress base URL is set and ingress is enabled.
22
+ *
23
+ * `ingress.enabled` is treated as opt-out: an unset flag with a base URL
24
+ * present counts as enabled, matching how the URL alone has always been
25
+ * enough to drive registration.
26
+ */
27
+ export function hasIngressConfigured(
28
+ options: { twilio?: boolean } = {},
29
+ ): boolean {
30
+ try {
31
+ const raw = loadRawConfig();
32
+ const ingress = (raw?.ingress ?? {}) as Record<string, unknown>;
33
+ const effectiveBaseUrl = options.twilio
34
+ ? (resolveTwilioPublicBaseUrl(ingress) ?? "")
35
+ : (normalizePublicBaseUrl(ingress.publicBaseUrl) ?? "");
36
+ const enabled =
37
+ (ingress.enabled as boolean | undefined) ??
38
+ (effectiveBaseUrl ? true : false);
39
+ return enabled && effectiveBaseUrl.trim().length > 0;
40
+ } catch {
41
+ return false;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * True when inbound webhooks have somewhere to land: either a self-hosted
47
+ * public ingress URL, or — when `allowManagedCallbacks` is set and this is a
48
+ * platform deployment — the platform's managed callback routes.
49
+ */
50
+ export function hasWebhookRoutingConfigured(
51
+ allowManagedCallbacks = false,
52
+ options: { twilio?: boolean } = {},
53
+ ): {
54
+ configured: boolean;
55
+ usesManagedCallbacks: boolean;
56
+ } {
57
+ const ingressConfigured = hasIngressConfigured(options);
58
+ if (ingressConfigured) {
59
+ return { configured: true, usesManagedCallbacks: false };
60
+ }
61
+
62
+ const usesManagedCallbacks = allowManagedCallbacks && getIsPlatform();
63
+ return {
64
+ configured: usesManagedCallbacks,
65
+ usesManagedCallbacks,
66
+ };
67
+ }
@@ -1050,9 +1050,13 @@ function truncateHistoryToBudget(args: {
1050
1050
  systemPrompt: string;
1051
1051
  budgetTokens: number;
1052
1052
  providerName: string;
1053
+ model?: string;
1053
1054
  }): Message[] {
1054
- const { messages, systemPrompt, budgetTokens, providerName } = args;
1055
- let estimate = estimatePromptTokens(messages, systemPrompt, { providerName });
1055
+ const { messages, systemPrompt, budgetTokens, providerName, model } = args;
1056
+ let estimate = estimatePromptTokens(messages, systemPrompt, {
1057
+ providerName,
1058
+ model,
1059
+ });
1056
1060
  if (estimate <= budgetTokens || messages.length <= 1) {
1057
1061
  return messages;
1058
1062
  }
@@ -1061,6 +1065,7 @@ function truncateHistoryToBudget(args: {
1061
1065
  dropCount++;
1062
1066
  estimate = estimatePromptTokens(messages.slice(dropCount), systemPrompt, {
1063
1067
  providerName,
1068
+ model,
1064
1069
  });
1065
1070
  }
1066
1071
  if (dropCount === 0) {
@@ -1155,6 +1160,7 @@ export async function runAssistantDrivenCompaction(
1155
1160
  systemPrompt: args.systemPrompt,
1156
1161
  budgetTokens: compactionPrefixBudget(args.maxInputTokens),
1157
1162
  providerName: args.provider.tokenEstimationProvider ?? args.provider.name,
1163
+ model: args.provider.defaultModel,
1158
1164
  });
1159
1165
  const requestMessages = buildCompactionRequest(summaryHistory, instruction);
1160
1166
 
@@ -1354,7 +1360,7 @@ export async function runAssistantDrivenCompaction(
1354
1360
  estimatePromptTokens(
1355
1361
  [...fixedPrefix, ...stripInjectionsForCompaction(tail)],
1356
1362
  args.systemPrompt,
1357
- { providerName, toolTokenBudget },
1363
+ { providerName, model: args.provider.defaultModel, toolTokenBudget },
1358
1364
  );
1359
1365
  const floorIndex = resolveTailFloorIndex(args.messages, pairedTailIndex);
1360
1366
  const advanced = advanceTailForBudget({
@@ -1616,6 +1622,7 @@ export async function runEmergencyCompaction(
1616
1622
  systemPrompt: args.systemPrompt,
1617
1623
  budgetTokens: compactionPrefixBudget(args.maxInputTokens),
1618
1624
  providerName: args.provider.tokenEstimationProvider ?? args.provider.name,
1625
+ model: args.provider.defaultModel,
1619
1626
  });
1620
1627
 
1621
1628
  const instruction: Message = {
@@ -3,6 +3,11 @@ import {
3
3
  normalizeGeminiAudioMime,
4
4
  } from "../providers/gemini/inline-media.js";
5
5
  import { mediaSourceByteLength } from "../providers/media-resolve.js";
6
+ import { modelSupportsAudioInput } from "../providers/model-catalog.js";
7
+ import {
8
+ estimateOpenAICompatAudioTokens,
9
+ isOpenAICompatInlineAudio,
10
+ } from "../providers/openai/input-audio.js";
6
11
  import type {
7
12
  ContentBlock,
8
13
  Message,
@@ -90,6 +95,12 @@ const TOOL_DEFINITION_OVERHEAD_TOKENS = 28;
90
95
 
91
96
  export interface TokenEstimatorOptions {
92
97
  providerName?: string;
98
+ /**
99
+ * Model id the estimated request dispatches to, for model-keyed rules
100
+ * (e.g. audio-capable OpenAI-compatible models). Callers pass the
101
+ * provider's `defaultModel` when available.
102
+ */
103
+ model?: string;
93
104
  /** Pre-computed tool token budget. When provided, added to the prompt total. */
94
105
  toolTokenBudget?: number;
95
106
  }
@@ -142,6 +153,16 @@ function estimateFileDataTokens(
142
153
  return Math.ceil((Math.ceil(byteLength / 3) * 4) / CHARS_PER_TOKEN);
143
154
  }
144
155
 
156
+ // Audio-native OpenAI-compatible models (catalog `supportsAudioInput`)
157
+ // receive eligible audio inline as `input_audio` parts, billed by duration.
158
+ if (
159
+ options?.model !== undefined &&
160
+ modelSupportsAudioInput(options.model) &&
161
+ isOpenAICompatInlineAudio(block.source.media_type, byteLength)
162
+ ) {
163
+ return estimateOpenAICompatAudioTokens(byteLength);
164
+ }
165
+
145
166
  return 0;
146
167
  }
147
168