@vellumai/assistant 0.7.1 → 0.7.3

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 (739) hide show
  1. package/ARCHITECTURE.md +48 -50
  2. package/Dockerfile +1 -0
  3. package/README.md +1 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +9 -3
  5. package/bun.lock +26 -26
  6. package/docs/architecture/memory.md +5 -2
  7. package/docs/architecture/security.md +20 -0
  8. package/docs/plugins.md +7 -9
  9. package/knip.json +1 -0
  10. package/node_modules/@vellumai/gateway-client/src/index.ts +1 -0
  11. package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +52 -5
  12. package/node_modules/@vellumai/gateway-client/src/types.ts +11 -0
  13. package/node_modules/@vellumai/service-contracts/package.json +2 -0
  14. package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +4 -0
  15. package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +107 -0
  16. package/node_modules/@vellumai/service-contracts/src/index.ts +5 -1
  17. package/node_modules/@vellumai/service-contracts/src/ingress.ts +24 -0
  18. package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +84 -0
  19. package/node_modules/@vellumai/slack-text/src/index.test.ts +18 -35
  20. package/node_modules/@vellumai/slack-text/src/index.ts +2 -48
  21. package/node_modules/@vellumai/twilio-client/bun.lock +24 -0
  22. package/node_modules/@vellumai/twilio-client/package.json +18 -0
  23. package/node_modules/@vellumai/twilio-client/src/__tests__/twilio-client.test.ts +128 -0
  24. package/node_modules/@vellumai/twilio-client/src/index.ts +179 -0
  25. package/node_modules/@vellumai/twilio-client/tsconfig.json +20 -0
  26. package/openapi.yaml +1020 -40
  27. package/package.json +6 -3
  28. package/src/__tests__/app-builder-tool-scripts.test.ts +3 -3
  29. package/src/__tests__/app-bundler.test.ts +170 -1
  30. package/src/__tests__/app-control-flow.test.ts +384 -0
  31. package/src/__tests__/app-control-no-global-cgevent.test.ts +98 -0
  32. package/src/__tests__/app-control-tool-schemas.test.ts +621 -0
  33. package/src/__tests__/app-executors.test.ts +30 -43
  34. package/src/__tests__/approval-routes-http.test.ts +23 -6
  35. package/src/__tests__/assistant-event-hub-machine-name.test.ts +146 -0
  36. package/src/__tests__/assistant-event-hub-targeted.test.ts +257 -0
  37. package/src/__tests__/assistant-event-hub.test.ts +157 -2
  38. package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -7
  39. package/src/__tests__/auto-analysis-end-to-end.test.ts +62 -1
  40. package/src/__tests__/background-shell-host-bash.test.ts +14 -15
  41. package/src/__tests__/background-workers-disk-pressure.test.ts +268 -0
  42. package/src/__tests__/bootstrap-turn-cleanup.test.ts +44 -0
  43. package/src/__tests__/btw-routes.test.ts +13 -4
  44. package/src/__tests__/call-controller.test.ts +49 -1
  45. package/src/__tests__/call-conversation-messages.test.ts +8 -2
  46. package/src/__tests__/call-domain.test.ts +0 -2
  47. package/src/__tests__/call-routes-http.test.ts +0 -2
  48. package/src/__tests__/channel-inbound-disk-pressure.test.ts +537 -0
  49. package/src/__tests__/channel-readiness-service.test.ts +62 -2
  50. package/src/__tests__/checker.test.ts +3 -4
  51. package/src/__tests__/config-loader-backfill.test.ts +461 -147
  52. package/src/__tests__/config-loader-platform-defaults.test.ts +196 -0
  53. package/src/__tests__/config-schema-cmd.test.ts +0 -1
  54. package/src/__tests__/config-schema.test.ts +1 -0
  55. package/src/__tests__/config-set-platform-guard.test.ts +48 -4
  56. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +20 -11
  57. package/src/__tests__/config-watcher.test.ts +142 -71
  58. package/src/__tests__/context-search-agent-runner.test.ts +61 -3
  59. package/src/__tests__/context-search-conversations-source.test.ts +0 -24
  60. package/src/__tests__/context-search-fanout.test.ts +0 -1
  61. package/src/__tests__/context-search-memory-source.test.ts +3 -7
  62. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -2
  63. package/src/__tests__/context-search-pkb-source.test.ts +0 -1
  64. package/src/__tests__/context-search-workspace-source.test.ts +0 -1
  65. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  66. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +223 -0
  67. package/src/__tests__/conversation-agent-loop.test.ts +454 -5
  68. package/src/__tests__/conversation-app-control-instantiation.test.ts +392 -0
  69. package/src/__tests__/conversation-app-control-lifecycle.test.ts +237 -0
  70. package/src/__tests__/conversation-error.test.ts +150 -3
  71. package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
  72. package/src/__tests__/conversation-lifecycle.test.ts +36 -0
  73. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +283 -0
  74. package/src/__tests__/conversation-process-callsite.test.ts +43 -0
  75. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  76. package/src/__tests__/conversation-routes-disk-view.test.ts +6 -0
  77. package/src/__tests__/conversation-routes-guardian-reply.test.ts +120 -72
  78. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  79. package/src/__tests__/conversation-runtime-assembly.test.ts +65 -0
  80. package/src/__tests__/conversation-slash-commands.test.ts +0 -4
  81. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  82. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  83. package/src/__tests__/conversation-store.test.ts +0 -18
  84. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +202 -0
  85. package/src/__tests__/conversation-surfaces-app-control.test.ts +328 -0
  86. package/src/__tests__/conversation-surfaces-data-persist.test.ts +404 -0
  87. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +2 -5
  88. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  89. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  90. package/src/__tests__/credential-execution-feature-gates.test.ts +5 -12
  91. package/src/__tests__/credential-execution-managed-contract.test.ts +3 -131
  92. package/src/__tests__/credentials-cli.test.ts +12 -12
  93. package/src/__tests__/cu-unified-flow.test.ts +351 -23
  94. package/src/__tests__/daemon-credential-client.test.ts +101 -19
  95. package/src/__tests__/date-context.test.ts +164 -2
  96. package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -0
  97. package/src/__tests__/disk-pressure-guard.test.ts +262 -0
  98. package/src/__tests__/disk-pressure-lifecycle.test.ts +168 -0
  99. package/src/__tests__/disk-pressure-policy.test.ts +241 -0
  100. package/src/__tests__/disk-pressure-routes.test.ts +379 -0
  101. package/src/__tests__/disk-pressure-tools.test.ts +277 -0
  102. package/src/__tests__/disk-usage.test.ts +150 -0
  103. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  104. package/src/__tests__/events-client-registration.test.ts +52 -0
  105. package/src/__tests__/events-dev-bypass-actor.test.ts +162 -0
  106. package/src/__tests__/file-write-tool.test.ts +4 -10
  107. package/src/__tests__/filing-service.test.ts +3 -4
  108. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  109. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -2
  110. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +0 -2
  111. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -1
  112. package/src/__tests__/heartbeat-disk-pressure.test.ts +183 -0
  113. package/src/__tests__/heartbeat-service.test.ts +968 -2
  114. package/src/__tests__/helpers/call-route-handler.ts +7 -1
  115. package/src/__tests__/host-app-control-proxy.test.ts +772 -0
  116. package/src/__tests__/host-app-control-routes.test.ts +263 -0
  117. package/src/__tests__/host-bash-proxy.test.ts +439 -47
  118. package/src/__tests__/host-bash-routes.test.ts +459 -0
  119. package/src/__tests__/host-browser-proxy.test.ts +24 -22
  120. package/src/__tests__/host-browser-routes.test.ts +39 -13
  121. package/src/__tests__/host-cu-proxy.test.ts +248 -52
  122. package/src/__tests__/host-cu-routes-targeted.test.ts +429 -0
  123. package/src/__tests__/host-file-edit-tool.test.ts +47 -1
  124. package/src/__tests__/host-file-proxy-targeted.test.ts +378 -0
  125. package/src/__tests__/host-file-proxy.test.ts +301 -45
  126. package/src/__tests__/host-file-read-tool.test.ts +17 -0
  127. package/src/__tests__/host-file-routes-targeted.test.ts +420 -0
  128. package/src/__tests__/host-file-write-tool.test.ts +42 -1
  129. package/src/__tests__/host-proxy-base.test.ts +312 -0
  130. package/src/__tests__/host-shell-tool.test.ts +22 -4
  131. package/src/__tests__/host-transfer-proxy-targeted.test.ts +932 -0
  132. package/src/__tests__/host-transfer-proxy.test.ts +121 -22
  133. package/src/__tests__/host-transfer-routes-targeted.test.ts +662 -0
  134. package/src/__tests__/http-user-message-parity.test.ts +108 -1
  135. package/src/__tests__/identity-intro-cache.test.ts +29 -0
  136. package/src/__tests__/identity-routes.test.ts +103 -1
  137. package/src/__tests__/init-feature-flag-overrides.test.ts +26 -3
  138. package/src/__tests__/injector-chain.test.ts +18 -6
  139. package/src/__tests__/injector-disk-pressure.test.ts +224 -0
  140. package/src/__tests__/inline-command-runner.test.ts +0 -1
  141. package/src/__tests__/inline-skill-load-permissions.test.ts +5 -11
  142. package/src/__tests__/integration-status.test.ts +85 -5
  143. package/src/__tests__/intent-routing.test.ts +0 -1
  144. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +95 -5
  145. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +17 -0
  146. package/src/__tests__/managed-profile-guard.test.ts +18 -0
  147. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -1
  148. package/src/__tests__/mcp-abort-signal.test.ts +130 -0
  149. package/src/__tests__/mcp-auth-routes.test.ts +197 -0
  150. package/src/__tests__/mcp-cli.test.ts +338 -2
  151. package/src/__tests__/memory-admin-recall.test.ts +3 -11
  152. package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -0
  153. package/src/__tests__/memory-retrieval-pipeline.test.ts +22 -1
  154. package/src/__tests__/migration-import-commit-http.test.ts +108 -2
  155. package/src/__tests__/mock-gateway-ipc.ts +1 -0
  156. package/src/__tests__/normalize-onboarding.test.ts +180 -0
  157. package/src/__tests__/oauth-cli.test.ts +0 -2
  158. package/src/__tests__/oauth-connect-routes.test.ts +316 -0
  159. package/src/__tests__/oauth-provider-seed-logos.test.ts +24 -2
  160. package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
  161. package/src/__tests__/onboarding-persona-write.test.ts +308 -0
  162. package/src/__tests__/openai-provider.test.ts +45 -8
  163. package/src/__tests__/persist-onboarding-artifacts.test.ts +44 -64
  164. package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
  165. package/src/__tests__/platform-bash-auto-approve.test.ts +5 -9
  166. package/src/__tests__/platform-callback-registration.test.ts +21 -4
  167. package/src/__tests__/platform.test.ts +2 -1
  168. package/src/__tests__/playbook-execution.test.ts +0 -43
  169. package/src/__tests__/plugin-tool-contribution.test.ts +47 -0
  170. package/src/__tests__/prechat-onboarding-contract.test.ts +214 -25
  171. package/src/__tests__/process-message-background-slack.test.ts +2 -0
  172. package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
  173. package/src/__tests__/provider-tool-name.test.ts +23 -0
  174. package/src/__tests__/public-ingress-urls.test.ts +97 -0
  175. package/src/__tests__/relay-server.test.ts +15 -4
  176. package/src/__tests__/require-fresh-approval.test.ts +0 -1
  177. package/src/__tests__/retry-backoff.test.ts +87 -0
  178. package/src/__tests__/runtime-events-sse.test.ts +2 -2
  179. package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
  180. package/src/__tests__/schedule-retry.test.ts +715 -0
  181. package/src/__tests__/scheduler-disk-pressure.test.ts +148 -0
  182. package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
  183. package/src/__tests__/secret-ingress-http.test.ts +1 -1
  184. package/src/__tests__/send-endpoint-busy.test.ts +3 -0
  185. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -1
  186. package/src/__tests__/skill-feature-flags.test.ts +43 -41
  187. package/src/__tests__/skill-load-feature-flag.test.ts +13 -14
  188. package/src/__tests__/skill-load-inline-command.test.ts +0 -51
  189. package/src/__tests__/skill-load-inline-includes.test.ts +0 -43
  190. package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
  191. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -1
  192. package/src/__tests__/slack-channel-config.test.ts +9 -14
  193. package/src/__tests__/suggestion-routes.test.ts +46 -0
  194. package/src/__tests__/system-prompt-ask-mode.test.ts +0 -1
  195. package/src/__tests__/system-prompt.test.ts +0 -1
  196. package/src/__tests__/telegram-config.test.ts +0 -1
  197. package/src/__tests__/test-preload.ts +8 -0
  198. package/src/__tests__/tool-approval-handler.test.ts +3 -4
  199. package/src/__tests__/tool-audit-listener.test.ts +48 -0
  200. package/src/__tests__/tool-execute-pipeline.test.ts +0 -1
  201. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
  202. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
  203. package/src/__tests__/tool-executor.test.ts +0 -1
  204. package/src/__tests__/twilio-config.test.ts +3 -16
  205. package/src/__tests__/twilio-routes.test.ts +3 -5
  206. package/src/__tests__/twilio-validation.test.ts +93 -0
  207. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +1 -4
  208. package/src/__tests__/verification-control-plane-policy.test.ts +2 -4
  209. package/src/__tests__/voice-ingress-preflight.test.ts +19 -0
  210. package/src/__tests__/workspace-migration-006-services-config.test.ts +3 -2
  211. package/src/__tests__/workspace-migration-065-bump-stale-heartbeat-interval.test.ts +122 -0
  212. package/src/__tests__/workspace-migration-066-seed-heartbeat-callsite-cost-default.test.ts +285 -0
  213. package/src/__tests__/workspace-migration-068-release-notes-local-timezone.test.ts +90 -0
  214. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +1 -5
  215. package/src/__tests__/workspace-migration-down-functions.test.ts +8 -8
  216. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +90 -0
  217. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
  218. package/src/approvals/guardian-decision-primitive.ts +13 -0
  219. package/src/approvals/guardian-request-resolvers.ts +16 -17
  220. package/src/backup/__tests__/paths.test.ts +0 -22
  221. package/src/backup/__tests__/restore.test.ts +51 -151
  222. package/src/backup/paths.ts +2 -18
  223. package/src/backup/restore.ts +107 -231
  224. package/src/backup/snapshot-lock.ts +2 -27
  225. package/src/bundler/app-bundler.ts +51 -3
  226. package/src/bundler/compiler-tools.ts +3 -2
  227. package/src/calls/call-conversation-messages.ts +46 -10
  228. package/src/calls/relay-server.ts +4 -44
  229. package/src/calls/twilio-config.ts +2 -17
  230. package/src/calls/twilio-rest.ts +33 -105
  231. package/src/calls/twilio-routes.ts +11 -12
  232. package/src/channels/types.ts +8 -7
  233. package/src/cli/commands/__tests__/backup.test.ts +6 -277
  234. package/src/cli/commands/__tests__/gateway.test.ts +288 -0
  235. package/src/cli/commands/__tests__/memory-v2.test.ts +4 -0
  236. package/src/cli/commands/__tests__/webhooks.test.ts +0 -5
  237. package/src/cli/commands/backup.ts +6 -331
  238. package/src/cli/commands/bash.ts +35 -108
  239. package/src/cli/commands/clients.ts +36 -37
  240. package/src/cli/commands/contacts.ts +137 -25
  241. package/src/cli/commands/conversations.ts +2 -5
  242. package/src/cli/commands/credentials.ts +71 -7
  243. package/src/cli/commands/domain.ts +66 -15
  244. package/src/cli/commands/gateway.ts +183 -0
  245. package/src/cli/commands/keys.ts +9 -6
  246. package/src/cli/commands/mcp.ts +116 -156
  247. package/src/cli/commands/memory-v2.ts +303 -7
  248. package/src/cli/commands/oauth/__tests__/connect.test.ts +437 -1
  249. package/src/cli/commands/oauth/connect.ts +127 -1
  250. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -4
  251. package/src/cli/commands/platform/__tests__/connect.test.ts +7 -3
  252. package/src/cli/commands/platform/__tests__/disconnect.test.ts +7 -3
  253. package/src/cli/commands/platform/__tests__/status.test.ts +116 -21
  254. package/src/cli/commands/platform/disconnect.ts +5 -4
  255. package/src/cli/commands/platform/index.ts +16 -25
  256. package/src/cli/commands/status.ts +57 -0
  257. package/src/cli/lib/daemon-credential-client.ts +110 -28
  258. package/src/cli/program.ts +6 -2
  259. package/src/config/assistant-feature-flags.ts +79 -12
  260. package/src/config/bundled-skills/acp/SKILL.md +6 -0
  261. package/src/config/bundled-skills/acp/TOOLS.json +1 -22
  262. package/src/config/bundled-skills/app-builder/SKILL.md +14 -109
  263. package/src/config/bundled-skills/app-builder/TOOLS.json +1 -28
  264. package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -10
  265. package/src/config/bundled-skills/app-control/SKILL.md +75 -0
  266. package/src/config/bundled-skills/app-control/TOOLS.json +299 -0
  267. package/src/config/bundled-skills/app-control/tools/app-control-click.ts +12 -0
  268. package/src/config/bundled-skills/app-control/tools/app-control-combo.ts +12 -0
  269. package/src/config/bundled-skills/app-control/tools/app-control-drag.ts +12 -0
  270. package/src/config/bundled-skills/app-control/tools/app-control-observe.ts +12 -0
  271. package/src/config/bundled-skills/app-control/tools/app-control-press.ts +12 -0
  272. package/src/config/bundled-skills/app-control/tools/app-control-sequence.ts +12 -0
  273. package/src/config/bundled-skills/app-control/tools/app-control-start.ts +12 -0
  274. package/src/config/bundled-skills/app-control/tools/app-control-stop.ts +12 -0
  275. package/src/config/bundled-skills/app-control/tools/app-control-type.ts +12 -0
  276. package/src/config/bundled-skills/computer-use/SKILL.md +6 -0
  277. package/src/config/bundled-skills/computer-use/TOOLS.json +67 -43
  278. package/src/config/bundled-skills/contacts/TOOLS.json +0 -16
  279. package/src/config/bundled-skills/document/TOOLS.json +0 -8
  280. package/src/config/bundled-skills/followups/TOOLS.json +0 -12
  281. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  282. package/src/config/bundled-skills/image-studio/TOOLS.json +0 -4
  283. package/src/config/bundled-skills/media-processing/TOOLS.json +0 -24
  284. package/src/config/bundled-skills/messaging/TOOLS.json +0 -40
  285. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -3
  286. package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
  287. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +25 -4
  288. package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
  289. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -2
  290. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +2 -2
  291. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -2
  292. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -2
  293. package/src/config/bundled-skills/schedule/TOOLS.json +14 -14
  294. package/src/config/bundled-skills/sequences/TOOLS.json +0 -36
  295. package/src/config/bundled-skills/settings/SKILL.md +4 -0
  296. package/src/config/bundled-skills/settings/TOOLS.json +0 -12
  297. package/src/config/bundled-skills/skill-management/SKILL.md +6 -0
  298. package/src/config/bundled-skills/skill-management/TOOLS.json +0 -8
  299. package/src/config/bundled-skills/subagent/SKILL.md +6 -2
  300. package/src/config/bundled-skills/subagent/TOOLS.json +0 -20
  301. package/src/config/bundled-skills/transcribe/SKILL.md +4 -0
  302. package/src/config/bundled-skills/transcribe/TOOLS.json +0 -4
  303. package/src/config/bundled-tool-registry.ts +21 -0
  304. package/src/config/env-registry.ts +0 -2
  305. package/src/config/env.ts +19 -20
  306. package/src/config/feature-flag-registry.json +47 -135
  307. package/src/config/loader.ts +197 -104
  308. package/src/config/sanitize-for-transfer.ts +2 -0
  309. package/src/config/schemas/__tests__/memory-lifecycle.test.ts +80 -0
  310. package/src/config/schemas/__tests__/memory-v2.test.ts +17 -9
  311. package/src/config/schemas/call-site-catalog.ts +14 -0
  312. package/src/config/schemas/calls.ts +0 -9
  313. package/src/config/schemas/channels.ts +0 -5
  314. package/src/config/schemas/heartbeat.ts +64 -1
  315. package/src/config/schemas/ingress.ts +10 -6
  316. package/src/config/schemas/llm.ts +7 -10
  317. package/src/config/schemas/memory-lifecycle.ts +90 -24
  318. package/src/config/schemas/memory-v2.ts +121 -13
  319. package/src/config/schemas/platform.ts +49 -3
  320. package/src/config/schemas/services.ts +29 -15
  321. package/src/config/schemas/skills.ts +0 -6
  322. package/src/config/seed-inference-profiles.ts +230 -33
  323. package/src/contacts/contact-store.ts +0 -55
  324. package/src/contacts/contacts-write.ts +0 -27
  325. package/src/context/window-manager.ts +1 -2
  326. package/src/credential-execution/feature-gates.ts +10 -10
  327. package/src/credential-execution/process-manager.ts +12 -41
  328. package/src/daemon/__tests__/conversation-tool-setup.test.ts +187 -5
  329. package/src/daemon/assistant-attachments.ts +4 -4
  330. package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
  331. package/src/daemon/config-watcher.ts +89 -60
  332. package/src/daemon/conversation-agent-loop-handlers.ts +27 -3
  333. package/src/daemon/conversation-agent-loop.ts +202 -61
  334. package/src/daemon/conversation-error.ts +87 -15
  335. package/src/daemon/conversation-lifecycle.ts +9 -4
  336. package/src/daemon/conversation-process.ts +24 -11
  337. package/src/daemon/conversation-runtime-assembly.ts +28 -2
  338. package/src/daemon/conversation-store.ts +2 -2
  339. package/src/daemon/conversation-surfaces.ts +305 -4
  340. package/src/daemon/conversation-tool-setup.ts +66 -62
  341. package/src/daemon/conversation.ts +38 -24
  342. package/src/daemon/date-context.ts +71 -22
  343. package/src/daemon/disk-pressure-background-gate.ts +73 -0
  344. package/src/daemon/disk-pressure-guard.ts +343 -0
  345. package/src/daemon/disk-pressure-policy.ts +163 -0
  346. package/src/daemon/doordash-steps.ts +1 -1
  347. package/src/daemon/handlers/shared.ts +4 -2
  348. package/src/daemon/handlers/skills.ts +3 -4
  349. package/src/daemon/host-app-control-proxy.ts +389 -0
  350. package/src/daemon/host-bash-proxy.ts +117 -82
  351. package/src/daemon/host-browser-proxy.ts +67 -82
  352. package/src/daemon/host-cu-proxy.ts +127 -86
  353. package/src/daemon/host-file-proxy.ts +129 -69
  354. package/src/daemon/host-proxy-base.ts +294 -0
  355. package/src/daemon/host-proxy-preactivation.ts +82 -0
  356. package/src/daemon/host-transfer-proxy.ts +338 -129
  357. package/src/daemon/lifecycle.ts +194 -145
  358. package/src/daemon/meet-host-supervisor.ts +4 -4
  359. package/src/daemon/meet-manifest-loader.ts +0 -1
  360. package/src/daemon/memory-v2-startup.ts +14 -4
  361. package/src/daemon/message-protocol.ts +6 -8
  362. package/src/daemon/message-types/contacts.ts +23 -1
  363. package/src/daemon/message-types/conversations.ts +15 -8
  364. package/src/daemon/message-types/disk-pressure.ts +9 -0
  365. package/src/daemon/message-types/host-app-control.ts +150 -0
  366. package/src/daemon/message-types/host-bash.ts +4 -0
  367. package/src/daemon/message-types/host-cu.ts +2 -0
  368. package/src/daemon/message-types/host-file.ts +4 -0
  369. package/src/daemon/message-types/host-transfer.ts +3 -0
  370. package/src/daemon/message-types/messages.ts +3 -0
  371. package/src/daemon/message-types/schedules.ts +8 -3
  372. package/src/daemon/message-types/skills.ts +2 -2
  373. package/src/daemon/process-message.ts +18 -1
  374. package/src/daemon/profiler-run-store.ts +5 -5
  375. package/src/daemon/shutdown-handlers.ts +0 -3
  376. package/src/daemon/tool-setup-types.ts +51 -0
  377. package/src/daemon/tool-side-effects.ts +1 -1
  378. package/src/documents/document-store.ts +85 -0
  379. package/src/events/tool-audit-listener.ts +2 -1
  380. package/src/filing/filing-service.ts +30 -5
  381. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +24 -23
  382. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +252 -0
  383. package/src/heartbeat/heartbeat-run-store.ts +249 -0
  384. package/src/heartbeat/heartbeat-service.ts +459 -54
  385. package/src/home/__tests__/post-connect-feed.test.ts +99 -0
  386. package/src/home/__tests__/relationship-state-writer.test.ts +11 -9
  387. package/src/home/__tests__/suggested-prompts.test.ts +89 -0
  388. package/src/home/feed-scheduler.ts +18 -0
  389. package/src/home/post-connect-feed.ts +68 -0
  390. package/src/home/relationship-state-writer.ts +17 -92
  391. package/src/home/suggested-prompts.ts +46 -10
  392. package/src/inbound/platform-callback-registration.ts +8 -15
  393. package/src/inbound/public-ingress-urls.ts +32 -34
  394. package/src/ipc/__tests__/clients-list-ipc.test.ts +169 -0
  395. package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
  396. package/src/ipc/assistant-server.ts +70 -3
  397. package/src/ipc/cli-client.ts +32 -1
  398. package/src/ipc/gateway-client.ts +37 -3
  399. package/src/live-voice/live-voice-archive.ts +4 -4
  400. package/src/live-voice/live-voice-metrics.ts +10 -10
  401. package/src/live-voice/protocol.ts +5 -7
  402. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +304 -0
  403. package/src/mcp/mcp-auth-orchestrator.ts +213 -0
  404. package/src/mcp/mcp-auth-state.ts +133 -0
  405. package/src/mcp/mcp-oauth-provider.ts +19 -0
  406. package/src/media/image-service.ts +1 -7
  407. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +21 -13
  408. package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
  409. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +52 -22
  410. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +0 -6
  411. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +272 -0
  412. package/src/memory/__tests__/qdrant-client-sentinel.test.ts +49 -0
  413. package/src/memory/__tests__/sparse-tokenize.test.ts +66 -0
  414. package/src/memory/admin.ts +5 -9
  415. package/src/memory/anisotropy.test.ts +247 -0
  416. package/src/memory/anisotropy.ts +443 -0
  417. package/src/memory/auto-analysis-constants.ts +17 -0
  418. package/src/memory/auto-analysis-guard.ts +5 -15
  419. package/src/memory/canonical-guardian-store.ts +7 -7
  420. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +122 -0
  421. package/src/memory/context-search/agent-protocol.ts +6 -6
  422. package/src/memory/context-search/agent-runner.ts +51 -9
  423. package/src/memory/context-search/sources/conversations.ts +2 -11
  424. package/src/memory/context-search/sources/memory-v2.ts +22 -9
  425. package/src/memory/context-search/sources/memory.ts +0 -1
  426. package/src/memory/context-search/types.ts +0 -1
  427. package/src/memory/conversation-crud.ts +5 -13
  428. package/src/memory/conversation-key-store.ts +2 -15
  429. package/src/memory/db-init.ts +6 -0
  430. package/src/memory/embedding-backend.ts +9 -21
  431. package/src/memory/embedding-runtime-manager.ts +119 -5
  432. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +81 -25
  433. package/src/memory/graph/conversation-graph-memory.ts +43 -78
  434. package/src/memory/graph/extraction.ts +1 -3
  435. package/src/memory/graph/graph-search.test.ts +10 -67
  436. package/src/memory/graph/graph-search.ts +9 -20
  437. package/src/memory/graph/retriever.test.ts +6 -0
  438. package/src/memory/graph/retriever.ts +34 -10
  439. package/src/memory/graph/tools.ts +1 -1
  440. package/src/memory/indexer.ts +54 -45
  441. package/src/memory/job-handlers/backfill.ts +2 -11
  442. package/src/memory/job-handlers/cleanup.ts +43 -0
  443. package/src/memory/job-handlers/embedding.ts +6 -8
  444. package/src/memory/job-handlers/summarization.ts +2 -7
  445. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +8 -2
  446. package/src/memory/jobs/embed-concept-page.ts +28 -2
  447. package/src/memory/jobs/embed-pkb-file.test.ts +2 -2
  448. package/src/memory/jobs-store.ts +114 -22
  449. package/src/memory/jobs-worker.ts +193 -106
  450. package/src/memory/memory-v2-activation-log-store.ts +33 -15
  451. package/src/memory/memory-v2-concept-frequency.ts +169 -0
  452. package/src/memory/migrations/237-heartbeat-runs.ts +45 -0
  453. package/src/memory/migrations/238-schedule-retry-policy.ts +20 -0
  454. package/src/memory/migrations/239-trace-events-created-at-index.ts +18 -0
  455. package/src/memory/migrations/index.ts +6 -0
  456. package/src/memory/migrations/registry.ts +8 -0
  457. package/src/memory/pkb/pkb-search.test.ts +6 -0
  458. package/src/memory/pkb/pkb-search.ts +7 -0
  459. package/src/memory/qdrant-client.ts +49 -32
  460. package/src/memory/rerank-local.ts +374 -0
  461. package/src/memory/schema/infrastructure.ts +15 -0
  462. package/src/memory/search/semantic.ts +13 -67
  463. package/src/memory/sparse-tokenize.ts +49 -0
  464. package/src/memory/trace-event-store.ts +1 -17
  465. package/src/memory/v2/__tests__/activation.test.ts +387 -344
  466. package/src/memory/v2/__tests__/consolidation-job.test.ts +40 -8
  467. package/src/memory/v2/__tests__/injection.test.ts +181 -169
  468. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +61 -2
  469. package/src/memory/v2/__tests__/qdrant.test.ts +16 -0
  470. package/src/memory/v2/__tests__/reranker.test.ts +338 -0
  471. package/src/memory/v2/__tests__/sim.test.ts +154 -188
  472. package/src/memory/v2/__tests__/skill-store.test.ts +71 -65
  473. package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
  474. package/src/memory/v2/__tests__/static-context.test.ts +76 -2
  475. package/src/memory/v2/activation.ts +213 -239
  476. package/src/memory/v2/consolidation-job.ts +65 -17
  477. package/src/memory/v2/constants.ts +7 -0
  478. package/src/memory/v2/injection.ts +123 -103
  479. package/src/memory/v2/prompts/consolidation.ts +348 -92
  480. package/src/memory/v2/qdrant.ts +198 -1
  481. package/src/memory/v2/reranker.ts +177 -0
  482. package/src/memory/v2/sim.ts +113 -77
  483. package/src/memory/v2/skill-content.ts +4 -3
  484. package/src/memory/v2/skill-store.ts +91 -53
  485. package/src/memory/v2/sparse-bm25.ts +245 -0
  486. package/src/memory/v2/static-context.ts +28 -5
  487. package/src/memory/v2/types.ts +10 -10
  488. package/src/messaging/providers/gmail/types.ts +0 -49
  489. package/src/messaging/providers/slack/adapter.ts +1 -31
  490. package/src/messaging/providers/slack/types.ts +0 -32
  491. package/src/notifications/README.md +10 -10
  492. package/src/notifications/broadcaster.ts +1 -1
  493. package/src/notifications/copy-composer.ts +13 -0
  494. package/src/notifications/guardian-question-mode.ts +5 -5
  495. package/src/notifications/signal.ts +4 -0
  496. package/src/oauth/AGENTS.md +3 -1
  497. package/src/oauth/__tests__/oauth-connect-state.test.ts +137 -0
  498. package/src/oauth/connect-orchestrator.ts +6 -0
  499. package/src/oauth/connection-resolver.test.ts +66 -1
  500. package/src/oauth/connection-resolver.ts +55 -1
  501. package/src/oauth/credential-token-resolver.ts +1 -3
  502. package/src/oauth/manual-token-connection.ts +0 -4
  503. package/src/oauth/oauth-connect-state.ts +77 -0
  504. package/src/oauth/seed-providers.ts +58 -1
  505. package/src/outbound-proxy/index.ts +1 -37
  506. package/src/outbound-proxy/logging.ts +1 -1
  507. package/src/outbound-proxy/policy.ts +6 -5
  508. package/src/outbound-proxy/router.ts +2 -1
  509. package/src/permissions/approval-policy.test.ts +6 -275
  510. package/src/permissions/approval-policy.ts +0 -51
  511. package/src/permissions/checker.test.ts +0 -1
  512. package/src/permissions/checker.ts +3 -17
  513. package/src/permissions/gateway-threshold-reader.ts +2 -0
  514. package/src/permissions/prompter.ts +34 -1
  515. package/src/permissions/secret-prompter.ts +6 -2
  516. package/src/plugins/defaults/injectors.ts +35 -2
  517. package/src/plugins/defaults/memory-retrieval.ts +5 -6
  518. package/src/plugins/types.ts +7 -0
  519. package/src/proactive-artifact/aux-message-injector.ts +74 -0
  520. package/src/proactive-artifact/decision.test.ts +226 -0
  521. package/src/proactive-artifact/decision.ts +165 -0
  522. package/src/proactive-artifact/index.ts +7 -0
  523. package/src/proactive-artifact/job.test.ts +867 -0
  524. package/src/proactive-artifact/job.ts +352 -0
  525. package/src/proactive-artifact/message-copy.ts +41 -0
  526. package/src/proactive-artifact/trigger-state.test.ts +277 -0
  527. package/src/proactive-artifact/trigger-state.ts +119 -0
  528. package/src/prompts/bootstrap-cleanup.ts +27 -0
  529. package/src/prompts/normalize-onboarding.ts +80 -0
  530. package/src/prompts/persona-resolver.ts +101 -9
  531. package/src/prompts/system-prompt.ts +23 -24
  532. package/src/prompts/templates/BOOTSTRAP.md +13 -5
  533. package/src/prompts/templates/SOUL.md +13 -1
  534. package/src/providers/__tests__/retry-callsite.test.ts +222 -1
  535. package/src/providers/model-intents.ts +7 -0
  536. package/src/providers/openrouter/client.ts +8 -0
  537. package/src/providers/retry.ts +50 -0
  538. package/src/providers/speech-to-text/provider-catalog.ts +7 -8
  539. package/src/providers/types.ts +1 -0
  540. package/src/runtime/__tests__/agent-wake.test.ts +456 -3
  541. package/src/runtime/agent-wake.ts +238 -100
  542. package/src/runtime/assistant-event-hub.ts +151 -99
  543. package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
  544. package/src/runtime/auth/__tests__/route-policy.test.ts +64 -0
  545. package/src/runtime/auth/middleware.ts +0 -96
  546. package/src/runtime/auth/route-policy.ts +32 -0
  547. package/src/runtime/auth/same-actor.ts +216 -0
  548. package/src/runtime/btw-sidechain.ts +2 -3
  549. package/src/runtime/channel-invite-transport.ts +2 -48
  550. package/src/runtime/channel-invite-transports/email.ts +1 -1
  551. package/src/runtime/channel-invite-transports/slack.ts +1 -1
  552. package/src/runtime/channel-invite-transports/telegram.ts +1 -1
  553. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  554. package/src/runtime/channel-invite-transports/whatsapp.ts +1 -1
  555. package/src/runtime/channel-invite-types.ts +54 -0
  556. package/src/runtime/channel-readiness-service.ts +32 -13
  557. package/src/runtime/channel-retry-sweep.ts +65 -1
  558. package/src/runtime/guardian-reply-router.ts +10 -0
  559. package/src/runtime/http-server.ts +3 -329
  560. package/src/runtime/http-types.ts +0 -5
  561. package/src/runtime/local-actor-identity.ts +52 -11
  562. package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +413 -0
  563. package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +260 -0
  564. package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +189 -0
  565. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +153 -1
  566. package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +451 -0
  567. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
  568. package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +515 -0
  569. package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +437 -0
  570. package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +319 -0
  571. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +51 -1
  572. package/src/runtime/migrations/migration-transport.ts +7 -7
  573. package/src/runtime/migrations/vbundle-builder.ts +327 -60
  574. package/src/runtime/migrations/vbundle-import-analyzer.ts +4 -4
  575. package/src/runtime/migrations/vbundle-import-policy.ts +172 -0
  576. package/src/runtime/migrations/vbundle-importer.ts +245 -68
  577. package/src/runtime/migrations/vbundle-streaming-importer.ts +326 -35
  578. package/src/runtime/migrations/vbundle-streaming-validator.ts +157 -4
  579. package/src/runtime/migrations/vbundle-tar-stream.ts +15 -6
  580. package/src/runtime/migrations/vbundle-validator.ts +114 -0
  581. package/src/runtime/pending-interactions.ts +43 -9
  582. package/src/runtime/routes/__tests__/backup-routes.test.ts +22 -150
  583. package/src/runtime/routes/__tests__/client-routes.test.ts +155 -0
  584. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -5
  585. package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +242 -0
  586. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +112 -0
  587. package/src/runtime/routes/approval-interception-types.ts +13 -0
  588. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +1 -1
  589. package/src/runtime/routes/backup-routes.ts +15 -38
  590. package/src/runtime/routes/btw-routes.ts +14 -37
  591. package/src/runtime/routes/client-routes.ts +21 -2
  592. package/src/runtime/routes/contact-prompt-routes.ts +183 -0
  593. package/src/runtime/routes/contact-routes.ts +0 -25
  594. package/src/runtime/routes/conversation-query-routes.ts +36 -1
  595. package/src/runtime/routes/conversation-routes.ts +65 -39
  596. package/src/runtime/routes/debug-bash-routes.ts +163 -0
  597. package/src/runtime/routes/disk-pressure-routes.ts +121 -0
  598. package/src/runtime/routes/document-pdf-renderer.ts +169 -0
  599. package/src/runtime/routes/documents-routes.ts +32 -75
  600. package/src/runtime/routes/errors.ts +19 -4
  601. package/src/runtime/routes/events-routes.ts +38 -0
  602. package/src/runtime/routes/gateway-log-routes.ts +79 -0
  603. package/src/runtime/routes/guardian-approval-interception.ts +2 -8
  604. package/src/runtime/routes/heartbeat-routes.ts +103 -38
  605. package/src/runtime/routes/host-app-control-routes.ts +134 -0
  606. package/src/runtime/routes/host-bash-routes.ts +56 -6
  607. package/src/runtime/routes/host-browser-routes.ts +108 -13
  608. package/src/runtime/routes/host-cu-routes.ts +66 -9
  609. package/src/runtime/routes/host-file-routes.ts +54 -5
  610. package/src/runtime/routes/host-transfer-routes.ts +122 -19
  611. package/src/runtime/routes/http-adapter.ts +1 -0
  612. package/src/runtime/routes/identity-intro-cache.ts +30 -0
  613. package/src/runtime/routes/identity-routes.ts +21 -180
  614. package/src/runtime/routes/inbound-message-handler.ts +78 -21
  615. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -7
  616. package/src/runtime/routes/inbound-stages/edit-intercept.ts +0 -8
  617. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +3 -0
  618. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -20
  619. package/src/runtime/routes/inbound-stages/transcribe-audio.ts +5 -13
  620. package/src/runtime/routes/index.ts +14 -0
  621. package/src/runtime/routes/mcp-auth-routes.ts +132 -0
  622. package/src/runtime/routes/memory-item-routes.test.ts +41 -15
  623. package/src/runtime/routes/memory-item-routes.ts +10 -12
  624. package/src/runtime/routes/memory-v2-routes.ts +474 -1
  625. package/src/runtime/routes/migration-routes.ts +96 -0
  626. package/src/runtime/routes/oauth-connect-routes.ts +153 -0
  627. package/src/runtime/routes/schedule-routes.ts +7 -0
  628. package/src/runtime/verification-outbound-actions.ts +4 -4
  629. package/src/runtime/verification-templates.ts +4 -7
  630. package/src/schedule/integration-status.ts +66 -2
  631. package/src/schedule/recurrence-engine.ts +4 -1
  632. package/src/schedule/retry-backoff.ts +18 -0
  633. package/src/schedule/retry-policy.ts +82 -0
  634. package/src/schedule/run-script.ts +37 -5
  635. package/src/schedule/schedule-recovery.ts +64 -0
  636. package/src/schedule/schedule-store.ts +106 -2
  637. package/src/schedule/scheduler-types.ts +25 -0
  638. package/src/schedule/scheduler.ts +83 -39
  639. package/src/security/encrypted-store.ts +2 -0
  640. package/src/security/oauth-callback-registry.ts +8 -0
  641. package/src/security/secure-keys.ts +55 -0
  642. package/src/sequence/analytics.ts +5 -5
  643. package/src/sequence/engine.ts +1 -1
  644. package/src/skills/catalog-files.ts +2 -8
  645. package/src/skills/include-graph.ts +5 -5
  646. package/src/skills/remote-skill-policy.ts +10 -16
  647. package/src/skills/skill-file-provider.ts +1 -1
  648. package/src/skills/skill-file-types.ts +13 -0
  649. package/src/skills/skillssh-audit-types.ts +28 -0
  650. package/src/skills/skillssh-registry.ts +8 -21
  651. package/src/subagent/index.ts +1 -7
  652. package/src/subagent/manager.ts +1 -15
  653. package/src/tasks/task-runner.ts +0 -1
  654. package/src/tasks/task-store.ts +0 -3
  655. package/src/telemetry/types.ts +2 -0
  656. package/src/telemetry/usage-telemetry-reporter.test.ts +21 -0
  657. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  658. package/src/tools/app-control/skill-proxy-bridge.ts +28 -0
  659. package/src/tools/apps/executors.ts +56 -69
  660. package/src/tools/background-tool-registry.ts +17 -3
  661. package/src/tools/browser/__tests__/browser-status.test.ts +21 -18
  662. package/src/tools/browser/browser-execution.ts +2 -2
  663. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +55 -4
  664. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +12 -6
  665. package/src/tools/browser/cdp-client/factory.ts +23 -24
  666. package/src/tools/browser/cdp-client/index.ts +1 -14
  667. package/src/tools/computer-use/definitions.ts +42 -20
  668. package/src/tools/executor.ts +2 -0
  669. package/src/tools/host-filesystem/edit.test.ts +151 -0
  670. package/src/tools/host-filesystem/edit.ts +68 -0
  671. package/src/tools/host-filesystem/read.test.ts +129 -0
  672. package/src/tools/host-filesystem/read.ts +68 -0
  673. package/src/tools/host-filesystem/transfer.test.ts +127 -2
  674. package/src/tools/host-filesystem/transfer.ts +78 -3
  675. package/src/tools/host-filesystem/write.test.ts +134 -0
  676. package/src/tools/host-filesystem/write.ts +68 -0
  677. package/src/tools/host-terminal/host-shell.ts +66 -1
  678. package/src/tools/mcp/mcp-tool-factory.ts +2 -1
  679. package/src/tools/memory/register.test.ts +12 -9
  680. package/src/tools/memory/register.ts +1 -2
  681. package/src/tools/provider-tool-name.ts +28 -0
  682. package/src/tools/registry.ts +30 -9
  683. package/src/tools/schedule/create.ts +6 -0
  684. package/src/tools/schedule/list.ts +2 -0
  685. package/src/tools/schedule/update.ts +10 -0
  686. package/src/tools/shared/filesystem/file-ops-service.ts +2 -0
  687. package/src/tools/shared/filesystem/path-policy.ts +25 -1
  688. package/src/tools/skills/load.ts +0 -32
  689. package/src/tools/terminal/shell.ts +9 -1
  690. package/src/tools/tool-approval-handler.ts +32 -11
  691. package/src/tools/types.ts +28 -2
  692. package/src/tts/provider-catalog.ts +3 -5
  693. package/src/usage/pricing.ts +1 -1
  694. package/src/util/disk-usage.ts +138 -0
  695. package/src/util/platform.ts +21 -11
  696. package/src/util/process-liveness.ts +26 -0
  697. package/src/workspace/hatched-date.ts +86 -0
  698. package/src/workspace/heartbeat-service.ts +19 -0
  699. package/src/workspace/migrations/003-seed-device-id.ts +1 -1
  700. package/src/workspace/migrations/006-services-config.ts +8 -5
  701. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +3 -9
  702. package/src/workspace/migrations/021-move-signals-to-workspace.ts +4 -10
  703. package/src/workspace/migrations/022-move-hooks-to-workspace.ts +4 -10
  704. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +4 -11
  705. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +3 -10
  706. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +3 -2
  707. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +2 -1
  708. package/src/workspace/migrations/059-move-pid-to-workspace.ts +3 -8
  709. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +3 -8
  710. package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +60 -0
  711. package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +146 -0
  712. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +72 -0
  713. package/src/workspace/migrations/068-release-notes-local-timezone.ts +65 -0
  714. package/src/workspace/migrations/AGENTS.md +1 -1
  715. package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
  716. package/src/workspace/migrations/registry.ts +8 -0
  717. package/src/workspace/migrations/utils.ts +21 -0
  718. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +0 -167
  719. package/src/__tests__/host-browser-e2e-cloud.test.ts +0 -443
  720. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +0 -226
  721. package/src/__tests__/host-browser-ws-events-e2e.test.ts +0 -427
  722. package/src/__tests__/twilio-rest.test.ts +0 -34
  723. package/src/backup/__tests__/backup-key.test.ts +0 -152
  724. package/src/backup/__tests__/backup-worker.test.ts +0 -782
  725. package/src/backup/__tests__/offsite-writer.test.ts +0 -641
  726. package/src/backup/__tests__/stream-crypt.test.ts +0 -228
  727. package/src/backup/backup-key.ts +0 -137
  728. package/src/backup/backup-worker.ts +0 -472
  729. package/src/backup/offsite-writer.ts +0 -222
  730. package/src/backup/stream-crypt.ts +0 -263
  731. package/src/daemon/message-types/pairing.ts +0 -58
  732. package/src/memory/v2/__tests__/skill-qdrant.test.ts +0 -657
  733. package/src/memory/v2/skill-qdrant.ts +0 -395
  734. package/src/outbound-proxy/config.ts +0 -20
  735. package/src/outbound-proxy/health.ts +0 -18
  736. package/src/outbound-proxy/types.ts +0 -150
  737. package/src/runtime/capability-tokens.ts +0 -190
  738. package/src/signals/bash.ts +0 -198
  739. package/src/signals/mcp-reload.ts +0 -18
@@ -8,17 +8,45 @@ import { z } from "zod";
8
8
 
9
9
  import { isAssistantFeatureFlagEnabled } from "../../config/assistant-feature-flags.js";
10
10
  import { loadConfig } from "../../config/loader.js";
11
+ import {
12
+ applyCorrectionIfCalibrated,
13
+ explainedVarianceRatio,
14
+ fitAnisotropyCalibration,
15
+ saveCalibration,
16
+ } from "../../memory/anisotropy.js";
17
+ import {
18
+ embedWithBackend,
19
+ selectEmbeddingBackend,
20
+ } from "../../memory/embedding-backend.js";
11
21
  import {
12
22
  enqueueMemoryJob,
13
23
  type MemoryJobType,
14
24
  } from "../../memory/jobs-store.js";
25
+ import {
26
+ type ConceptFrequencyResponse,
27
+ getConceptFrequencySummary,
28
+ } from "../../memory/memory-v2-concept-frequency.js";
15
29
  import {
16
30
  getEdgeIndex,
17
31
  totalEdgeCount,
18
32
  validateEdgeTargets,
19
33
  } from "../../memory/v2/edge-index.js";
20
- import { listPages, readPage } from "../../memory/v2/page-store.js";
34
+ import {
35
+ listPages,
36
+ readPage,
37
+ renderPageContent,
38
+ } from "../../memory/v2/page-store.js";
39
+ import {
40
+ hybridQueryConceptPages,
41
+ sampleConceptPageDenseVectors,
42
+ } from "../../memory/v2/qdrant.js";
43
+ import { effectiveWeights } from "../../memory/v2/sim.js";
21
44
  import { seedV2SkillEntries } from "../../memory/v2/skill-store.js";
45
+ import {
46
+ generateBm25QueryEmbedding,
47
+ getConceptPageCorpusStats,
48
+ rebuildConceptPageCorpusStats,
49
+ } from "../../memory/v2/sparse-bm25.js";
22
50
  import { getWorkspaceDir } from "../../util/platform.js";
23
51
  import { RouteError } from "./errors.js";
24
52
  import type { RouteDefinition } from "./types.js";
@@ -113,6 +141,79 @@ async function handleValidate({
113
141
  };
114
142
  }
115
143
 
144
+ // ── Get concept page ────────────────────────────────────────────────────
145
+
146
+ const MemoryV2GetConceptPageParams = z
147
+ .object({
148
+ slug: z.string().min(1),
149
+ })
150
+ .strict();
151
+
152
+ export type MemoryV2GetConceptPageResult = {
153
+ slug: string;
154
+ /** Frontmatter + body, as produced by `renderPageContent`. */
155
+ rendered: string;
156
+ };
157
+
158
+ async function handleGetConceptPage({
159
+ body = {},
160
+ }: RouteHandlerArgs): Promise<MemoryV2GetConceptPageResult> {
161
+ const { slug } = MemoryV2GetConceptPageParams.parse(body);
162
+ const workspaceDir = getWorkspaceDir();
163
+ let page;
164
+ try {
165
+ page = await readPage(workspaceDir, slug);
166
+ } catch (err) {
167
+ throw new RouteError(
168
+ `Failed to read concept page '${slug}': ${err instanceof Error ? err.message : String(err)}`,
169
+ "MEMORY_V2_PAGE_READ_FAILED",
170
+ 400,
171
+ );
172
+ }
173
+ if (!page) {
174
+ throw new RouteError(
175
+ `Concept page '${slug}' not found on disk`,
176
+ "MEMORY_V2_PAGE_NOT_FOUND",
177
+ 404,
178
+ );
179
+ }
180
+ return { slug, rendered: renderPageContent(page) };
181
+ }
182
+
183
+ // ── Rebuild BM25 corpus stats ───────────────────────────────────────────
184
+
185
+ const MemoryV2RebuildCorpusStatsParams = z.object({}).strict();
186
+
187
+ export interface MemoryV2RebuildCorpusStatsResult {
188
+ totalDocs: number;
189
+ avgDl: number;
190
+ /** Number of distinct hashed-token buckets that received any DF count. */
191
+ vocabularyBuckets: number;
192
+ }
193
+
194
+ async function handleRebuildCorpusStats({
195
+ body = {},
196
+ }: RouteHandlerArgs): Promise<MemoryV2RebuildCorpusStatsResult> {
197
+ MemoryV2RebuildCorpusStatsParams.parse(body);
198
+ const workspaceDir = getWorkspaceDir();
199
+ await rebuildConceptPageCorpusStats(workspaceDir);
200
+ const stats = getConceptPageCorpusStats();
201
+ if (!stats) {
202
+ // The rebuild always swaps in a non-null table on success, so a missing
203
+ // value here means an unexpected reset between rebuild and read.
204
+ throw new RouteError(
205
+ "Corpus stats rebuild completed but no table is loaded",
206
+ "MEMORY_V2_CORPUS_STATS_MISSING",
207
+ 500,
208
+ );
209
+ }
210
+ return {
211
+ totalDocs: stats.totalDocs,
212
+ avgDl: stats.avgDl,
213
+ vocabularyBuckets: stats.df.size,
214
+ };
215
+ }
216
+
116
217
  // ── Reembed skills ──────────────────────────────────────────────────────
117
218
 
118
219
  const MemoryV2ReembedSkillsParams = z.object({}).strict();
@@ -149,6 +250,323 @@ async function handleReembedSkills({
149
250
  return { success: true };
150
251
  }
151
252
 
253
+ // ── Explain similarity ──────────────────────────────────────────────────
254
+
255
+ const MemoryV2ExplainSimilarityParams = z
256
+ .object({
257
+ userText: z.string().min(1),
258
+ assistantText: z.string().optional(),
259
+ nowText: z.string().optional(),
260
+ top: z.number().int().min(1).default(25),
261
+ })
262
+ .strict();
263
+
264
+ export interface MemoryV2ExplainSimilarityRow {
265
+ slug: string;
266
+ /** Raw dense cosine score, or null when the slug missed the dense channel. */
267
+ denseScore: number | null;
268
+ /** Raw sparse score (Qdrant scale), or null when the slug missed sparse. */
269
+ sparseRaw: number | null;
270
+ /** Sparse score divided by the per-batch max, in [0, 1]. */
271
+ sparseNorm: number | null;
272
+ /** `clamp01(dense_weight·dense + sparse_weight·sparseNorm)` — the simBatch fused value. */
273
+ fused: number;
274
+ }
275
+
276
+ export interface MemoryV2ExplainSimilarityStats {
277
+ count: number;
278
+ min: number;
279
+ max: number;
280
+ mean: number;
281
+ stddev: number;
282
+ }
283
+
284
+ export interface MemoryV2ExplainSimilarityChannel {
285
+ channel: "user" | "assistant" | "now";
286
+ textPreview: string;
287
+ maxSparse: number;
288
+ /**
289
+ * Spread (max - min) of normalized sparse scores across this channel's
290
+ * hits. Drives adaptive sparse weighting — low spread means the sparse
291
+ * channel can't discriminate, so its weight collapses for this query.
292
+ */
293
+ sparseSpread: number;
294
+ /** Sparse weight after adaptive collapse (≤ the configured base). */
295
+ effectiveSparseWeight: number;
296
+ /** Dense weight after adaptive compensation (≥ the configured base). */
297
+ effectiveDenseWeight: number;
298
+ rows: MemoryV2ExplainSimilarityRow[];
299
+ stats: {
300
+ dense: MemoryV2ExplainSimilarityStats;
301
+ sparseRaw: MemoryV2ExplainSimilarityStats;
302
+ sparseNorm: MemoryV2ExplainSimilarityStats;
303
+ fused: MemoryV2ExplainSimilarityStats;
304
+ };
305
+ }
306
+
307
+ export interface MemoryV2ExplainSimilarityResult {
308
+ config: {
309
+ dense_weight: number;
310
+ sparse_weight: number;
311
+ };
312
+ channels: MemoryV2ExplainSimilarityChannel[];
313
+ }
314
+
315
+ function summarizeStats(values: number[]): MemoryV2ExplainSimilarityStats {
316
+ if (values.length === 0) {
317
+ return { count: 0, min: 0, max: 0, mean: 0, stddev: 0 };
318
+ }
319
+ let min = Infinity;
320
+ let max = -Infinity;
321
+ let sum = 0;
322
+ for (const v of values) {
323
+ if (v < min) min = v;
324
+ if (v > max) max = v;
325
+ sum += v;
326
+ }
327
+ const mean = sum / values.length;
328
+ let sqDiff = 0;
329
+ for (const v of values) sqDiff += (v - mean) * (v - mean);
330
+ const stddev = Math.sqrt(sqDiff / values.length);
331
+ return { count: values.length, min, max, mean, stddev };
332
+ }
333
+
334
+ async function scoreChannel(
335
+ channel: "user" | "assistant" | "now",
336
+ text: string,
337
+ top: number,
338
+ denseWeight: number,
339
+ sparseWeight: number,
340
+ config: ReturnType<typeof loadConfig>,
341
+ ): Promise<MemoryV2ExplainSimilarityChannel> {
342
+ const denseResult = await embedWithBackend(config, [text]);
343
+ const denseVec = await applyCorrectionIfCalibrated(
344
+ denseResult.vectors[0],
345
+ denseResult.provider,
346
+ denseResult.model,
347
+ );
348
+ const sparseVec = generateBm25QueryEmbedding(text);
349
+
350
+ const hits = await hybridQueryConceptPages(denseVec, sparseVec, top);
351
+
352
+ let maxSparse = 0;
353
+ for (const hit of hits) {
354
+ if (hit.sparseScore !== undefined && hit.sparseScore > maxSparse) {
355
+ maxSparse = hit.sparseScore;
356
+ }
357
+ }
358
+
359
+ // Mirror simBatch's adaptive weighting so the printed `fused` matches what
360
+ // production retrieval would actually score for this query — otherwise
361
+ // operators staring at the diagnostic would see different numbers than
362
+ // the activation pipeline saw.
363
+ const {
364
+ dense: effDense,
365
+ sparse: effSparse,
366
+ spread: sparseSpread,
367
+ } = effectiveWeights(hits, maxSparse, denseWeight, sparseWeight, config);
368
+
369
+ const rows: MemoryV2ExplainSimilarityRow[] = hits.map((hit) => {
370
+ const dense = hit.denseScore ?? 0;
371
+ const sparseNorm =
372
+ hit.sparseScore !== undefined && maxSparse > 0
373
+ ? hit.sparseScore / maxSparse
374
+ : 0;
375
+ const fusedRaw = effDense * dense + effSparse * sparseNorm;
376
+ const fused = Math.max(0, Math.min(1, fusedRaw));
377
+ return {
378
+ slug: hit.slug,
379
+ denseScore: hit.denseScore ?? null,
380
+ sparseRaw: hit.sparseScore ?? null,
381
+ sparseNorm: hit.sparseScore !== undefined ? sparseNorm : null,
382
+ fused,
383
+ };
384
+ });
385
+
386
+ rows.sort((a, b) => b.fused - a.fused);
387
+
388
+ const denseValues: number[] = [];
389
+ const sparseRawValues: number[] = [];
390
+ const sparseNormValues: number[] = [];
391
+ const fusedValues: number[] = [];
392
+ for (const row of rows) {
393
+ if (row.denseScore !== null) denseValues.push(row.denseScore);
394
+ if (row.sparseRaw !== null) sparseRawValues.push(row.sparseRaw);
395
+ if (row.sparseNorm !== null) sparseNormValues.push(row.sparseNorm);
396
+ fusedValues.push(row.fused);
397
+ }
398
+
399
+ return {
400
+ channel,
401
+ textPreview: text.length > 120 ? `${text.slice(0, 120)}…` : text,
402
+ maxSparse,
403
+ sparseSpread,
404
+ effectiveSparseWeight: effSparse,
405
+ effectiveDenseWeight: effDense,
406
+ rows,
407
+ stats: {
408
+ dense: summarizeStats(denseValues),
409
+ sparseRaw: summarizeStats(sparseRawValues),
410
+ sparseNorm: summarizeStats(sparseNormValues),
411
+ fused: summarizeStats(fusedValues),
412
+ },
413
+ };
414
+ }
415
+
416
+ async function handleExplainSimilarity({
417
+ body = {},
418
+ }: RouteHandlerArgs): Promise<MemoryV2ExplainSimilarityResult> {
419
+ const params = MemoryV2ExplainSimilarityParams.parse(body);
420
+ const config = loadConfig();
421
+ const { dense_weight: denseWeight, sparse_weight: sparseWeight } =
422
+ config.memory.v2;
423
+
424
+ const channels: MemoryV2ExplainSimilarityChannel[] = [];
425
+ channels.push(
426
+ await scoreChannel(
427
+ "user",
428
+ params.userText,
429
+ params.top,
430
+ denseWeight,
431
+ sparseWeight,
432
+ config,
433
+ ),
434
+ );
435
+ if (params.assistantText && params.assistantText.length > 0) {
436
+ channels.push(
437
+ await scoreChannel(
438
+ "assistant",
439
+ params.assistantText,
440
+ params.top,
441
+ denseWeight,
442
+ sparseWeight,
443
+ config,
444
+ ),
445
+ );
446
+ }
447
+ if (params.nowText && params.nowText.length > 0) {
448
+ channels.push(
449
+ await scoreChannel(
450
+ "now",
451
+ params.nowText,
452
+ params.top,
453
+ denseWeight,
454
+ sparseWeight,
455
+ config,
456
+ ),
457
+ );
458
+ }
459
+
460
+ return {
461
+ config: { dense_weight: denseWeight, sparse_weight: sparseWeight },
462
+ channels,
463
+ };
464
+ }
465
+
466
+ // ── Concept injection frequency (debug-only) ────────────────────────────
467
+
468
+ const MemoryV2ConceptFrequencyParams = z
469
+ .object({
470
+ conversationId: z.string().min(1).optional(),
471
+ sinceMs: z.number().int().nonnegative().optional(),
472
+ })
473
+ .strict();
474
+
475
+ async function handleConceptFrequency({
476
+ body = {},
477
+ }: RouteHandlerArgs): Promise<ConceptFrequencyResponse> {
478
+ const { conversationId, sinceMs } =
479
+ MemoryV2ConceptFrequencyParams.parse(body);
480
+ const workspaceDir = getWorkspaceDir();
481
+ return getConceptFrequencySummary(workspaceDir, { conversationId, sinceMs });
482
+ }
483
+
484
+ // ── Fit anisotropy calibration ──────────────────────────────────────────
485
+
486
+ const MemoryV2FitAnisotropyParams = z
487
+ .object({
488
+ /**
489
+ * Number of leading principal components to project out at apply time.
490
+ * `1` is the canonical default for transformer embeddings; raise to 2-3
491
+ * only when the variance spectrum shows multiple dominant directions.
492
+ */
493
+ k: z.number().int().min(1).max(16).default(1),
494
+ /**
495
+ * Maximum number of stored vectors to pull from Qdrant for the fit.
496
+ * 5_000 is plenty for 3072-dim Gemini — power iteration converges fast
497
+ * and pulling the full corpus would just cost wall-clock time.
498
+ */
499
+ sample: z.number().int().min(1).max(100_000).default(5_000),
500
+ })
501
+ .strict();
502
+
503
+ export interface MemoryV2FitAnisotropyResult {
504
+ provider: string;
505
+ model: string;
506
+ dim: number;
507
+ k: number;
508
+ sampleCount: number;
509
+ totalVariance: number;
510
+ componentVariance: number[];
511
+ /** `componentVariance[i] / totalVariance` for each component. */
512
+ explainedVarianceRatio: number[];
513
+ /** Absolute path the calibration was written to. */
514
+ path: string;
515
+ }
516
+
517
+ async function handleFitAnisotropy({
518
+ body = {},
519
+ }: RouteHandlerArgs): Promise<MemoryV2FitAnisotropyResult> {
520
+ const { k, sample } = MemoryV2FitAnisotropyParams.parse(body);
521
+ const config = loadConfig();
522
+
523
+ const selection = await selectEmbeddingBackend(config);
524
+ if (!selection.backend) {
525
+ throw new RouteError(
526
+ `Cannot fit anisotropy calibration: ${selection.reason ?? "no embedding backend configured"}`,
527
+ "MEMORY_V2_NO_EMBEDDING_BACKEND",
528
+ 409,
529
+ );
530
+ }
531
+
532
+ const vectors = await sampleConceptPageDenseVectors(sample);
533
+ if (vectors.length === 0) {
534
+ throw new RouteError(
535
+ "Cannot fit anisotropy calibration: the v2 concept-page collection is empty. " +
536
+ "Embed some concept pages first (run `assistant memory v2 reembed`), then retry.",
537
+ "MEMORY_V2_NO_VECTORS",
538
+ 409,
539
+ );
540
+ }
541
+ if (vectors.length < k * 4) {
542
+ // PCA on too-few samples is unstable — refuse rather than hand back
543
+ // overfit components. The 4× heuristic is conservative; in practice
544
+ // anisotropy fits stabilise at a few hundred samples per component.
545
+ throw new RouteError(
546
+ `Cannot fit k=${k} components from only ${vectors.length} vectors — need at least ${k * 4}. ` +
547
+ "Embed more concept pages or fit a smaller k.",
548
+ "MEMORY_V2_INSUFFICIENT_VECTORS",
549
+ 409,
550
+ );
551
+ }
552
+
553
+ const { provider, model } = selection.backend;
554
+ const calib = fitAnisotropyCalibration(vectors, k, { provider, model });
555
+ const path = await saveCalibration(calib);
556
+
557
+ return {
558
+ provider,
559
+ model,
560
+ dim: calib.dim,
561
+ k,
562
+ sampleCount: calib.sampleCount,
563
+ totalVariance: calib.totalVariance,
564
+ componentVariance: calib.componentVariance,
565
+ explainedVarianceRatio: explainedVarianceRatio(calib),
566
+ path,
567
+ };
568
+ }
569
+
152
570
  // ── Route definitions ───────────────────────────────────────────────────
153
571
 
154
572
  export const ROUTES: RouteDefinition[] = [
@@ -174,6 +592,17 @@ export const ROUTES: RouteDefinition[] = [
174
592
  tags: ["memory"],
175
593
  requestBody: MemoryV2ValidateParams,
176
594
  },
595
+ {
596
+ operationId: "memory_v2_get_concept_page",
597
+ method: "POST",
598
+ endpoint: "memory/v2/concept-page",
599
+ handler: handleGetConceptPage,
600
+ summary: "Read a single memory v2 concept page",
601
+ description:
602
+ "Returns the rendered (frontmatter + body) markdown for a slug. 404 when the slug has no on-disk page — the activation log inspector uses this to show what got injected.",
603
+ tags: ["memory"],
604
+ requestBody: MemoryV2GetConceptPageParams,
605
+ },
177
606
  {
178
607
  operationId: "memory_v2_reembed_skills",
179
608
  method: "POST",
@@ -185,4 +614,48 @@ export const ROUTES: RouteDefinition[] = [
185
614
  tags: ["memory"],
186
615
  requestBody: MemoryV2ReembedSkillsParams,
187
616
  },
617
+ {
618
+ operationId: "memory_v2_explain_similarity",
619
+ method: "POST",
620
+ endpoint: "memory/v2/explain-similarity",
621
+ handler: handleExplainSimilarity,
622
+ summary: "Diagnose dense vs sparse similarity score distributions",
623
+ description:
624
+ "Read-only diagnostic. Embeds the supplied text(s), runs hybrid dense + sparse queries against the concept-page collection, and returns per-slug raw dense, raw sparse, normalized sparse, and fused scores plus per-channel summary stats. Used to investigate score-compression at the head of the activation distribution.",
625
+ tags: ["memory"],
626
+ requestBody: MemoryV2ExplainSimilarityParams,
627
+ },
628
+ {
629
+ operationId: "memory_v2_rebuild_corpus_stats",
630
+ method: "POST",
631
+ endpoint: "memory/v2/rebuild-corpus-stats",
632
+ handler: handleRebuildCorpusStats,
633
+ summary: "Rebuild the BM25 corpus statistics for memory v2",
634
+ description:
635
+ "Walks every concept page on disk, recomputes the document-frequency table and average document length used by the BM25 sparse channel, and atomically swaps the in-memory stats. Run after bulk content imports or to recover from a rebuild that errored at startup. Does not reembed individual page sparse vectors — pair with `assistant memory v2 reembed` when document-side weights need refreshing.",
636
+ tags: ["memory"],
637
+ requestBody: MemoryV2RebuildCorpusStatsParams,
638
+ },
639
+ {
640
+ operationId: "memory_v2_concept_frequency",
641
+ method: "POST",
642
+ endpoint: "memory/v2/concept-frequency",
643
+ handler: handleConceptFrequency,
644
+ summary: "Aggregate per-concept injection frequency from activation logs",
645
+ description:
646
+ "Debug-only. Aggregates the existing memory_v2_activation_logs table by (slug, status) and cross-references on-disk concept pages so an operator can see which concepts get injected often, which get scored but rejected, and which on-disk pages never even surface as candidates. Optional filters: conversationId narrows to a single conversation; sinceMs restricts to logs created at-or-after the given epoch ms timestamp.",
647
+ tags: ["memory"],
648
+ requestBody: MemoryV2ConceptFrequencyParams,
649
+ },
650
+ {
651
+ operationId: "memory_v2_fit_anisotropy",
652
+ method: "POST",
653
+ endpoint: "memory/v2/fit-anisotropy",
654
+ handler: handleFitAnisotropy,
655
+ summary: "Fit the embedding anisotropy correction for memory v2",
656
+ description:
657
+ "Samples stored dense vectors from the concept-page Qdrant collection, fits a corpus mean + top-k principal components (Mu & Viswanath 'all-but-the-top'), and persists the calibration so subsequent embeds and queries apply the correction. Run `assistant memory v2 reembed` after fitting so stored vectors are written under the new calibration — until then, queries (corrected) and stored vectors (uncorrected) live in different spaces.",
658
+ tags: ["memory"],
659
+ requestBody: MemoryV2FitAnisotropyParams,
660
+ },
188
661
  ];
@@ -65,6 +65,11 @@ import {
65
65
  analyzeImport,
66
66
  DefaultPathResolver,
67
67
  } from "../migrations/vbundle-import-analyzer.js";
68
+ import {
69
+ evaluateRuntimeCompatibility,
70
+ formatRuntimeCompatibilityMessage,
71
+ type RuntimeCompatibility,
72
+ } from "../migrations/vbundle-import-policy.js";
68
73
  import {
69
74
  commitImport,
70
75
  extractCredentialsFromBundle,
@@ -79,6 +84,7 @@ import {
79
84
  InternalError,
80
85
  NotFoundError,
81
86
  RouteError,
87
+ UnprocessableEntityError,
82
88
  } from "./errors.js";
83
89
  import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
84
90
  import { RouteResponse } from "./types.js";
@@ -866,6 +872,23 @@ export async function handleMigrationImport(
866
872
  };
867
873
  }
868
874
 
875
+ // Pre-check runtime-version compat before the DB close/reopen cycle.
876
+ // commitImport runs the same gate as defense-in-depth for callers that
877
+ // don't pre-check; we run it here too so an incompatible bundle short-
878
+ // circuits before resetDb().
879
+ const compatResult = evaluateRuntimeCompatibility(
880
+ validation.manifest!.compatibility,
881
+ APP_VERSION,
882
+ );
883
+ if (!compatResult.ok) {
884
+ throwImportCommitFailure({
885
+ ok: false,
886
+ reason: "version_incompatible",
887
+ bundle_compat: compatResult.bundle_compat,
888
+ runtime_version: compatResult.runtime_version,
889
+ });
890
+ }
891
+
869
892
  const pathResolver = new DefaultPathResolver(
870
893
  getWorkspaceDir(),
871
894
  getWorkspaceHooksDir(),
@@ -918,6 +941,12 @@ export async function handleMigrationImport(
918
941
 
919
942
  return importCommitSuccessResult(result.report, credentialsImported);
920
943
  } catch (err) {
944
+ // Preserve typed RouteError instances (e.g. UnprocessableEntityError for
945
+ // version_incompatible, BadRequestError for validation_failed) — only
946
+ // wrap genuinely unexpected errors as 500 InternalError.
947
+ if (err instanceof RouteError) {
948
+ throw err;
949
+ }
921
950
  log.error({ err }, "Unexpected error during import commit");
922
951
  throw new InternalError(
923
952
  err instanceof Error ? err.message : "Unexpected import error",
@@ -1014,12 +1043,18 @@ interface GcsImportErrorInit {
1014
1043
  | "fetch_failed"
1015
1044
  | "validation_failed"
1016
1045
  | "extraction_failed"
1046
+ | "version_incompatible"
1017
1047
  | "write_failed";
1018
1048
  message: string;
1019
1049
  upstreamStatus?: number;
1020
1050
  reason?: string;
1021
1051
  errors?: Array<{ code: string; message: string; path?: string }>;
1022
1052
  partial_report?: ImportCommitReport;
1053
+ /** Populated for `version_incompatible` — mirrors the platform's PR #5470
1054
+ * response shape so the URL-body endpoint can return the same body. */
1055
+ bundle_compat?: RuntimeCompatibility;
1056
+ /** Populated for `version_incompatible`. */
1057
+ runtime_version?: string;
1023
1058
  }
1024
1059
 
1025
1060
  class GcsImportError extends Error {
@@ -1028,6 +1063,8 @@ class GcsImportError extends Error {
1028
1063
  public readonly reason?: string;
1029
1064
  public readonly errors?: GcsImportErrorInit["errors"];
1030
1065
  public readonly partial_report?: ImportCommitReport;
1066
+ public readonly bundle_compat?: RuntimeCompatibility;
1067
+ public readonly runtime_version?: string;
1031
1068
 
1032
1069
  constructor(init: GcsImportErrorInit) {
1033
1070
  super(init.message);
@@ -1045,6 +1082,12 @@ class GcsImportError extends Error {
1045
1082
  if (init.partial_report !== undefined) {
1046
1083
  this.partial_report = init.partial_report;
1047
1084
  }
1085
+ if (init.bundle_compat !== undefined) {
1086
+ this.bundle_compat = init.bundle_compat;
1087
+ }
1088
+ if (init.runtime_version !== undefined) {
1089
+ this.runtime_version = init.runtime_version;
1090
+ }
1048
1091
  }
1049
1092
  }
1050
1093
 
@@ -1343,6 +1386,22 @@ async function runGcsImport(
1343
1386
  reason: result.reason,
1344
1387
  });
1345
1388
  }
1389
+ if (result.reason === "version_incompatible") {
1390
+ // Returned by commitImport / streamCommitImport when the runtime falls
1391
+ // outside the bundle's compat range. The platform-side gate is the
1392
+ // primary check; this catches legacy bundles whose ExportJob row
1393
+ // predates PR #5470 (compat columns NULL → platform gate skipped).
1394
+ throw new GcsImportError({
1395
+ code: "version_incompatible",
1396
+ message: formatRuntimeCompatibilityMessage(
1397
+ result.bundle_compat,
1398
+ result.runtime_version,
1399
+ ),
1400
+ reason: result.reason,
1401
+ bundle_compat: result.bundle_compat,
1402
+ runtime_version: result.runtime_version,
1403
+ });
1404
+ }
1346
1405
  // write_failed
1347
1406
  throw new GcsImportError({
1348
1407
  code: "write_failed",
@@ -1442,6 +1501,20 @@ function throwGcsImportError(err: unknown): never {
1442
1501
  }),
1443
1502
  );
1444
1503
  }
1504
+ if (err.code === "version_incompatible") {
1505
+ // 422 (not 500) — the bundle is structurally valid but cannot be
1506
+ // imported on this runtime. Body mirrors the platform's PR #5470
1507
+ // response shape.
1508
+ throw new UnprocessableEntityError(err.message, {
1509
+ reason: "version_incompatible" as const,
1510
+ ...(err.bundle_compat !== undefined && {
1511
+ bundle_compat: err.bundle_compat,
1512
+ }),
1513
+ ...(err.runtime_version !== undefined && {
1514
+ runtime_version: err.runtime_version,
1515
+ }),
1516
+ });
1517
+ }
1445
1518
  if (err.code === "extraction_failed") {
1446
1519
  throw new InternalError(err.message);
1447
1520
  }
@@ -1674,6 +1747,29 @@ function throwImportCommitFailure(
1674
1747
  throw new InternalError(result.message);
1675
1748
  }
1676
1749
 
1750
+ if (result.reason === "version_incompatible") {
1751
+ // Returned by commitImport / streamCommitImport when the runtime falls
1752
+ // outside the bundle's compat range. The platform-side gate is the
1753
+ // primary check; this catches legacy bundles whose ExportJob row
1754
+ // predates PR #5470 (compat columns NULL → platform gate skipped).
1755
+ //
1756
+ // 422 (not 500) — the bundle is structurally valid but cannot be
1757
+ // imported on this runtime; the caller can act on it (upgrade the
1758
+ // runtime, choose a different bundle). Body mirrors the platform's
1759
+ // PR #5470 response shape.
1760
+ throw new UnprocessableEntityError(
1761
+ formatRuntimeCompatibilityMessage(
1762
+ result.bundle_compat,
1763
+ result.runtime_version,
1764
+ ),
1765
+ {
1766
+ reason: "version_incompatible" as const,
1767
+ bundle_compat: result.bundle_compat,
1768
+ runtime_version: result.runtime_version,
1769
+ },
1770
+ );
1771
+ }
1772
+
1677
1773
  // write_failed
1678
1774
  throw new InternalError(result.message);
1679
1775
  }