@vellumai/assistant 0.4.48 → 0.4.50

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 (423) hide show
  1. package/ARCHITECTURE.md +26 -35
  2. package/README.md +5 -26
  3. package/docs/architecture/integrations.md +45 -41
  4. package/docs/architecture/keychain-broker.md +3 -3
  5. package/docs/architecture/memory.md +180 -119
  6. package/docs/runbook-trusted-contacts.md +3 -8
  7. package/hook-templates/debug-prompt-logger/hook.json +1 -1
  8. package/hook-templates/debug-prompt-logger/run.sh +1 -3
  9. package/package.json +2 -2
  10. package/src/__tests__/actor-token-service.test.ts +0 -1
  11. package/src/__tests__/agent-loop.test.ts +3 -1
  12. package/src/__tests__/anthropic-provider.test.ts +249 -2
  13. package/src/__tests__/approval-cascade.test.ts +796 -0
  14. package/src/__tests__/approval-primitive.test.ts +0 -1
  15. package/src/__tests__/approval-routes-http.test.ts +4 -0
  16. package/src/__tests__/assistant-attachments.test.ts +12 -34
  17. package/src/__tests__/assistant-feature-flag-guard.test.ts +0 -23
  18. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +76 -0
  19. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -1
  20. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
  21. package/src/__tests__/canonical-guardian-store.test.ts +95 -0
  22. package/src/__tests__/channel-guardian.test.ts +0 -2
  23. package/src/__tests__/channel-readiness-routes.test.ts +15 -6
  24. package/src/__tests__/channel-readiness-service.test.ts +10 -9
  25. package/src/__tests__/checker.test.ts +13 -20
  26. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
  27. package/src/__tests__/computer-use-tools.test.ts +2 -19
  28. package/src/__tests__/config-schema.test.ts +1 -68
  29. package/src/__tests__/config-watcher.test.ts +0 -1
  30. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  31. package/src/__tests__/context-image-dimensions.test.ts +332 -0
  32. package/src/__tests__/context-memory-e2e.test.ts +11 -100
  33. package/src/__tests__/context-token-estimator.test.ts +196 -13
  34. package/src/__tests__/conversation-attention-store.test.ts +0 -1
  35. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  36. package/src/__tests__/conversation-routes-guardian-reply.test.ts +152 -0
  37. package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -0
  38. package/src/__tests__/credential-metadata-store.test.ts +64 -73
  39. package/src/__tests__/credential-security-e2e.test.ts +1 -0
  40. package/src/__tests__/credential-security-invariants.test.ts +13 -7
  41. package/src/__tests__/credential-vault-unit.test.ts +284 -49
  42. package/src/__tests__/credential-vault.test.ts +150 -16
  43. package/src/__tests__/credentials-cli.test.ts +71 -0
  44. package/src/__tests__/cu-unified-flow.test.ts +532 -0
  45. package/src/__tests__/date-context.test.ts +93 -77
  46. package/src/__tests__/deterministic-verification-control-plane.test.ts +64 -0
  47. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  48. package/src/__tests__/ephemeral-permissions.test.ts +3 -3
  49. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  50. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
  51. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
  52. package/src/__tests__/guardian-routing-invariants.test.ts +93 -1
  53. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  54. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -39
  55. package/src/__tests__/heartbeat-service.test.ts +0 -1
  56. package/src/__tests__/history-repair.test.ts +245 -0
  57. package/src/__tests__/host-cu-proxy.test.ts +791 -0
  58. package/src/__tests__/host-shell-tool.test.ts +27 -15
  59. package/src/__tests__/http-user-message-parity.test.ts +2 -0
  60. package/src/__tests__/ingress-url-consistency.test.ts +14 -21
  61. package/src/__tests__/integration-status.test.ts +32 -51
  62. package/src/__tests__/intent-routing.test.ts +0 -1
  63. package/src/__tests__/invite-redemption-service.test.ts +65 -1
  64. package/src/__tests__/invite-routes-http.test.ts +10 -9
  65. package/src/__tests__/keychain-broker-client.test.ts +14 -46
  66. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +56 -18
  67. package/src/__tests__/memory-lifecycle-e2e.test.ts +244 -387
  68. package/src/__tests__/memory-recall-quality.test.ts +244 -407
  69. package/src/__tests__/memory-regressions.experimental.test.ts +126 -101
  70. package/src/__tests__/memory-regressions.test.ts +477 -2841
  71. package/src/__tests__/memory-retrieval.benchmark.test.ts +33 -150
  72. package/src/__tests__/memory-upsert-concurrency.test.ts +5 -244
  73. package/src/__tests__/mime-builder.test.ts +28 -0
  74. package/src/__tests__/native-web-search.test.ts +1 -0
  75. package/src/__tests__/notification-routing-intent.test.ts +0 -1
  76. package/src/__tests__/oauth-cli.test.ts +941 -15
  77. package/src/__tests__/oauth-provider-profiles.test.ts +9 -9
  78. package/src/__tests__/oauth-scope-policy.test.ts +4 -6
  79. package/src/__tests__/oauth-store.test.ts +870 -0
  80. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
  81. package/src/__tests__/provider-error-scenarios.test.ts +0 -1
  82. package/src/__tests__/provider-streaming.benchmark.test.ts +0 -1
  83. package/src/__tests__/public-ingress-urls.test.ts +15 -21
  84. package/src/__tests__/qdrant-collection-migration.test.ts +53 -8
  85. package/src/__tests__/recording-handler.test.ts +3 -4
  86. package/src/__tests__/registry.test.ts +2 -3
  87. package/src/__tests__/relay-server.test.ts +46 -1
  88. package/src/__tests__/runtime-events-sse.test.ts +55 -7
  89. package/src/__tests__/schedule-store.test.ts +0 -1
  90. package/src/__tests__/schedule-tools.test.ts +32 -0
  91. package/src/__tests__/scheduler-recurrence.test.ts +0 -1
  92. package/src/__tests__/scoped-approval-grants.test.ts +0 -1
  93. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
  94. package/src/__tests__/script-proxy-certs.test.ts +1 -1
  95. package/src/__tests__/secret-ingress-handler.test.ts +0 -1
  96. package/src/__tests__/secret-onetime-send.test.ts +1 -0
  97. package/src/__tests__/secure-keys.test.ts +7 -2
  98. package/src/__tests__/send-endpoint-busy.test.ts +24 -6
  99. package/src/__tests__/sequence-store.test.ts +0 -1
  100. package/src/__tests__/session-abort-tool-results.test.ts +1 -14
  101. package/src/__tests__/session-agent-loop-overflow.test.ts +1583 -0
  102. package/src/__tests__/session-agent-loop.test.ts +19 -15
  103. package/src/__tests__/session-confirmation-signals.test.ts +1 -15
  104. package/src/__tests__/session-error.test.ts +124 -2
  105. package/src/__tests__/session-history-web-search.test.ts +918 -0
  106. package/src/__tests__/session-init.benchmark.test.ts +4 -5
  107. package/src/__tests__/session-pre-run-repair.test.ts +1 -14
  108. package/src/__tests__/session-provider-retry-repair.test.ts +25 -28
  109. package/src/__tests__/session-queue.test.ts +37 -27
  110. package/src/__tests__/session-runtime-assembly.test.ts +54 -0
  111. package/src/__tests__/session-slash-known.test.ts +1 -15
  112. package/src/__tests__/session-slash-queue.test.ts +1 -15
  113. package/src/__tests__/session-slash-unknown.test.ts +1 -15
  114. package/src/__tests__/session-workspace-cache-state.test.ts +3 -33
  115. package/src/__tests__/session-workspace-injection.test.ts +3 -37
  116. package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -37
  117. package/src/__tests__/skill-include-graph.test.ts +66 -0
  118. package/src/__tests__/skill-load-feature-flag.test.ts +0 -1
  119. package/src/__tests__/skill-load-tool.test.ts +149 -1
  120. package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
  121. package/src/__tests__/skills-install-extract.test.ts +93 -0
  122. package/src/__tests__/skills-uninstall.test.ts +1 -1
  123. package/src/__tests__/skills.test.ts +3 -3
  124. package/src/__tests__/skillssh-registry.test.ts +451 -0
  125. package/src/__tests__/slack-channel-config.test.ts +67 -3
  126. package/src/__tests__/slack-share-routes.test.ts +17 -19
  127. package/src/__tests__/system-prompt.test.ts +0 -1
  128. package/src/__tests__/telegram-invite-adapter.test.ts +18 -22
  129. package/src/__tests__/terminal-tools.test.ts +4 -3
  130. package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
  131. package/src/__tests__/tool-approval-handler.test.ts +0 -1
  132. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
  133. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
  134. package/src/__tests__/tool-executor-shell-integration.test.ts +0 -1
  135. package/src/__tests__/tool-executor.test.ts +0 -1
  136. package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
  137. package/src/__tests__/trust-store-pattern-matches.test.ts +29 -0
  138. package/src/__tests__/trust-store.test.ts +7 -13
  139. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  140. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  141. package/src/__tests__/twilio-routes.test.ts +0 -16
  142. package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
  143. package/src/__tests__/voice-invite-redemption.test.ts +32 -1
  144. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
  145. package/src/agent/ax-tree-compaction.test.ts +286 -0
  146. package/src/agent/loop.ts +104 -131
  147. package/src/approvals/AGENTS.md +1 -1
  148. package/src/approvals/guardian-request-resolvers.ts +14 -2
  149. package/src/bundler/compiler-tools.ts +66 -2
  150. package/src/calls/call-domain.ts +133 -6
  151. package/src/calls/call-store.ts +6 -0
  152. package/src/calls/relay-server.ts +52 -18
  153. package/src/calls/relay-setup-router.ts +17 -1
  154. package/src/calls/twilio-config.ts +3 -8
  155. package/src/calls/twilio-routes.ts +1 -2
  156. package/src/calls/types.ts +3 -1
  157. package/src/calls/voice-ingress-preflight.ts +1 -1
  158. package/src/cli/commands/browser-relay.ts +18 -12
  159. package/src/cli/commands/completions.ts +0 -3
  160. package/src/cli/commands/credentials.ts +101 -15
  161. package/src/cli/commands/doctor.ts +4 -3
  162. package/src/cli/commands/mcp.ts +46 -59
  163. package/src/cli/commands/memory.ts +16 -165
  164. package/src/cli/commands/oauth/apps.ts +284 -0
  165. package/src/cli/commands/oauth/connections.ts +633 -0
  166. package/src/cli/commands/oauth/index.ts +52 -0
  167. package/src/cli/commands/oauth/providers.ts +256 -0
  168. package/src/cli/commands/sessions.ts +5 -2
  169. package/src/cli/commands/skills.ts +177 -339
  170. package/src/cli/http-client.ts +0 -20
  171. package/src/cli/main-screen.tsx +2 -2
  172. package/src/cli/program.ts +6 -11
  173. package/src/cli/reference.ts +1 -3
  174. package/src/cli.ts +4 -10
  175. package/src/config/assistant-feature-flags.ts +0 -3
  176. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
  177. package/src/config/bundled-skills/computer-use/SKILL.md +3 -6
  178. package/src/config/bundled-skills/computer-use/TOOLS.json +23 -5
  179. package/src/config/bundled-skills/computer-use/tools/{computer-use-request-control.ts → computer-use-observe.ts} +1 -5
  180. package/src/config/bundled-skills/google-calendar/calendar-client.ts +21 -16
  181. package/src/config/bundled-skills/messaging/tools/shared.ts +1 -4
  182. package/src/config/bundled-skills/settings/SKILL.md +1 -1
  183. package/src/config/bundled-skills/settings/TOOLS.json +2 -8
  184. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +5 -33
  185. package/src/config/bundled-tool-registry.ts +2 -5
  186. package/src/config/env-registry.ts +14 -83
  187. package/src/config/env.ts +11 -50
  188. package/src/config/feature-flag-registry.json +16 -16
  189. package/src/config/loader.ts +0 -6
  190. package/src/config/schema.ts +4 -13
  191. package/src/config/schemas/memory-lifecycle.ts +0 -9
  192. package/src/config/schemas/memory-processing.ts +0 -180
  193. package/src/config/schemas/memory-retrieval.ts +32 -104
  194. package/src/config/schemas/memory.ts +0 -10
  195. package/src/config/skills.ts +21 -2
  196. package/src/config/types.ts +0 -4
  197. package/src/context/image-dimensions.ts +229 -0
  198. package/src/context/token-estimator.ts +75 -12
  199. package/src/context/window-manager.ts +53 -11
  200. package/src/daemon/assistant-attachments.ts +1 -13
  201. package/src/daemon/config-watcher.ts +61 -3
  202. package/src/daemon/daemon-control.ts +1 -1
  203. package/src/daemon/date-context.ts +114 -31
  204. package/src/daemon/handlers/config-ingress.ts +8 -33
  205. package/src/daemon/handlers/config-slack-channel.ts +49 -46
  206. package/src/daemon/handlers/config-telegram.ts +32 -16
  207. package/src/daemon/handlers/sessions.ts +27 -36
  208. package/src/daemon/handlers/shared.ts +0 -130
  209. package/src/daemon/handlers/skills.ts +20 -1
  210. package/src/daemon/history-repair.ts +72 -8
  211. package/src/daemon/host-cu-proxy.ts +430 -0
  212. package/src/daemon/lifecycle.ts +67 -71
  213. package/src/daemon/mcp-reload-service.ts +2 -2
  214. package/src/daemon/message-protocol.ts +3 -0
  215. package/src/daemon/message-types/computer-use.ts +1 -129
  216. package/src/daemon/message-types/host-cu.ts +19 -0
  217. package/src/daemon/message-types/memory.ts +4 -16
  218. package/src/daemon/message-types/messages.ts +4 -0
  219. package/src/daemon/message-types/sessions.ts +4 -0
  220. package/src/daemon/server.ts +25 -21
  221. package/src/daemon/session-agent-loop-handlers.ts +40 -0
  222. package/src/daemon/session-agent-loop.ts +334 -48
  223. package/src/daemon/session-attachments.ts +1 -2
  224. package/src/daemon/session-error.ts +89 -6
  225. package/src/daemon/session-history.ts +17 -7
  226. package/src/daemon/session-media-retry.ts +6 -2
  227. package/src/daemon/session-memory.ts +69 -149
  228. package/src/daemon/session-process.ts +10 -1
  229. package/src/daemon/session-runtime-assembly.ts +49 -19
  230. package/src/daemon/session-slash.ts +1 -1
  231. package/src/daemon/session-surfaces.ts +43 -28
  232. package/src/daemon/session-tool-setup.ts +9 -10
  233. package/src/daemon/session.ts +150 -17
  234. package/src/daemon/tool-side-effects.ts +2 -8
  235. package/src/daemon/watch-handler.ts +2 -2
  236. package/src/events/tool-metrics-listener.ts +2 -2
  237. package/src/hooks/manager.ts +1 -4
  238. package/src/inbound/public-ingress-urls.ts +7 -7
  239. package/src/instrument.ts +61 -1
  240. package/src/logfire.ts +16 -5
  241. package/src/memory/admin.ts +2 -191
  242. package/src/memory/canonical-guardian-store.ts +38 -2
  243. package/src/memory/conversation-crud.ts +0 -33
  244. package/src/memory/conversation-key-store.ts +21 -0
  245. package/src/memory/conversation-queries.ts +22 -3
  246. package/src/memory/db-init.ts +32 -0
  247. package/src/memory/embedding-backend.ts +84 -8
  248. package/src/memory/embedding-types.ts +9 -1
  249. package/src/memory/indexer.ts +7 -46
  250. package/src/memory/items-extractor.ts +274 -76
  251. package/src/memory/job-handlers/backfill.ts +2 -127
  252. package/src/memory/job-handlers/cleanup.ts +2 -16
  253. package/src/memory/job-handlers/extraction.ts +2 -138
  254. package/src/memory/job-handlers/index-maintenance.ts +1 -6
  255. package/src/memory/job-handlers/summarization.ts +3 -148
  256. package/src/memory/job-utils.ts +21 -59
  257. package/src/memory/jobs-store.ts +1 -159
  258. package/src/memory/jobs-worker.ts +9 -52
  259. package/src/memory/migrations/104-core-indexes.ts +3 -3
  260. package/src/memory/migrations/149-oauth-tables.ts +62 -0
  261. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +98 -0
  262. package/src/memory/migrations/151-oauth-providers-ping-url.ts +11 -0
  263. package/src/memory/migrations/152-memory-item-supersession.ts +44 -0
  264. package/src/memory/migrations/153-drop-entity-tables.ts +15 -0
  265. package/src/memory/migrations/154-drop-fts.ts +20 -0
  266. package/src/memory/migrations/155-drop-conflicts.ts +7 -0
  267. package/src/memory/migrations/156-call-session-invite-metadata.ts +24 -0
  268. package/src/memory/migrations/index.ts +8 -0
  269. package/src/memory/qdrant-client.ts +148 -51
  270. package/src/memory/raw-query.ts +1 -1
  271. package/src/memory/retriever.test.ts +294 -273
  272. package/src/memory/retriever.ts +421 -645
  273. package/src/memory/schema/calls.ts +2 -0
  274. package/src/memory/schema/index.ts +1 -0
  275. package/src/memory/schema/memory-core.ts +3 -48
  276. package/src/memory/schema/oauth.ts +67 -0
  277. package/src/memory/search/formatting.ts +263 -176
  278. package/src/memory/search/lexical.ts +1 -254
  279. package/src/memory/search/ranking.ts +0 -455
  280. package/src/memory/search/semantic.ts +100 -14
  281. package/src/memory/search/staleness.ts +47 -0
  282. package/src/memory/search/tier-classifier.ts +21 -0
  283. package/src/memory/search/types.ts +15 -77
  284. package/src/memory/task-memory-cleanup.ts +4 -6
  285. package/src/messaging/provider.ts +4 -4
  286. package/src/messaging/providers/gmail/client.ts +82 -2
  287. package/src/messaging/providers/gmail/mime-builder.ts +17 -7
  288. package/src/messaging/providers/gmail/people-client.ts +10 -10
  289. package/src/messaging/providers/telegram-bot/adapter.ts +17 -17
  290. package/src/messaging/providers/whatsapp/adapter.ts +11 -8
  291. package/src/messaging/registry.ts +2 -32
  292. package/src/notifications/copy-composer.ts +0 -5
  293. package/src/notifications/signal.ts +4 -5
  294. package/src/oauth/byo-connection.test.ts +133 -25
  295. package/src/oauth/byo-connection.ts +22 -6
  296. package/src/oauth/connect-orchestrator.ts +113 -57
  297. package/src/oauth/connect-types.ts +17 -23
  298. package/src/oauth/connection-resolver.ts +35 -11
  299. package/src/oauth/connection.ts +1 -1
  300. package/src/oauth/manual-token-connection.ts +104 -0
  301. package/src/oauth/oauth-store.ts +582 -0
  302. package/src/oauth/platform-connection.test.ts +29 -0
  303. package/src/oauth/platform-connection.ts +6 -5
  304. package/src/oauth/provider-behaviors.ts +124 -0
  305. package/src/oauth/scope-policy.ts +9 -2
  306. package/src/oauth/seed-providers.ts +167 -0
  307. package/src/oauth/token-persistence.ts +81 -77
  308. package/src/permissions/checker.ts +3 -3
  309. package/src/permissions/defaults.ts +1 -1
  310. package/src/permissions/prompter.ts +10 -1
  311. package/src/permissions/trust-store.ts +36 -1
  312. package/src/playbooks/playbook-compiler.ts +1 -1
  313. package/src/prompts/__tests__/build-cli-reference-section.test.ts +3 -1
  314. package/src/prompts/system-prompt.ts +46 -42
  315. package/src/providers/anthropic/client.ts +59 -20
  316. package/src/providers/retry.ts +1 -27
  317. package/src/providers/types.ts +7 -1
  318. package/src/runtime/AGENTS.md +9 -0
  319. package/src/runtime/auth/route-policy.ts +6 -6
  320. package/src/runtime/channel-reply-delivery.ts +0 -40
  321. package/src/runtime/gateway-client.ts +0 -7
  322. package/src/runtime/guardian-reply-router.ts +24 -22
  323. package/src/runtime/http-server.ts +10 -8
  324. package/src/runtime/http-types.ts +2 -2
  325. package/src/runtime/invite-redemption-service.ts +19 -1
  326. package/src/runtime/invite-service.ts +25 -0
  327. package/src/runtime/middleware/twilio-validation.ts +1 -11
  328. package/src/runtime/pending-interactions.ts +14 -12
  329. package/src/runtime/routes/brain-graph-routes.ts +10 -90
  330. package/src/runtime/routes/channel-delivery-routes.ts +0 -1
  331. package/src/runtime/routes/conversation-routes.ts +81 -19
  332. package/src/runtime/routes/events-routes.ts +21 -11
  333. package/src/runtime/routes/host-cu-routes.ts +97 -0
  334. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -12
  335. package/src/runtime/routes/inbound-stages/background-dispatch.ts +12 -111
  336. package/src/runtime/routes/integrations/slack/share.ts +6 -7
  337. package/src/runtime/routes/log-export-routes.ts +126 -8
  338. package/src/runtime/routes/memory-item-routes.test.ts +754 -0
  339. package/src/runtime/routes/memory-item-routes.ts +503 -0
  340. package/src/runtime/routes/session-management-routes.ts +3 -3
  341. package/src/runtime/routes/settings-routes.ts +55 -48
  342. package/src/runtime/routes/surface-action-routes.ts +1 -1
  343. package/src/runtime/routes/trust-rules-routes.ts +14 -0
  344. package/src/runtime/routes/watch-routes.ts +128 -0
  345. package/src/runtime/routes/workspace-routes.ts +2 -1
  346. package/src/schedule/integration-status.ts +10 -9
  347. package/src/security/credential-key.ts +0 -156
  348. package/src/security/keychain-broker-client.ts +22 -10
  349. package/src/security/oauth2.ts +1 -1
  350. package/src/security/secure-keys.ts +25 -3
  351. package/src/security/token-manager.ts +137 -64
  352. package/src/skills/catalog-install.ts +414 -0
  353. package/src/skills/include-graph.ts +32 -0
  354. package/src/skills/skillssh-registry.ts +503 -0
  355. package/src/telegram/bot-username.ts +2 -3
  356. package/src/tools/assets/search.ts +5 -1
  357. package/src/tools/browser/network-recorder.ts +1 -1
  358. package/src/tools/browser/network-recording-types.ts +1 -1
  359. package/src/tools/computer-use/definitions.ts +36 -11
  360. package/src/tools/computer-use/registry.ts +5 -6
  361. package/src/tools/credentials/broker.ts +1 -2
  362. package/src/tools/credentials/metadata-store.ts +17 -121
  363. package/src/tools/credentials/vault.ts +92 -167
  364. package/src/tools/memory/definitions.ts +4 -13
  365. package/src/tools/memory/handlers.test.ts +83 -103
  366. package/src/tools/memory/handlers.ts +50 -85
  367. package/src/tools/registry.ts +2 -7
  368. package/src/tools/schedule/create.ts +8 -1
  369. package/src/tools/schedule/update.ts +8 -1
  370. package/src/tools/skills/load.ts +85 -3
  371. package/src/tools/watch/watch-state.ts +0 -12
  372. package/src/util/logger.ts +7 -41
  373. package/src/util/platform.ts +9 -28
  374. package/src/watcher/providers/google-calendar.ts +2 -1
  375. package/src/__tests__/clarification-resolver.test.ts +0 -193
  376. package/src/__tests__/computer-use-session-compaction.test.ts +0 -143
  377. package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -322
  378. package/src/__tests__/computer-use-session-working-dir.test.ts +0 -166
  379. package/src/__tests__/computer-use-skill-baseline.test.ts +0 -78
  380. package/src/__tests__/computer-use-skill-endstate.test.ts +0 -105
  381. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -249
  382. package/src/__tests__/conflict-intent-tokenization.test.ts +0 -160
  383. package/src/__tests__/conflict-policy.test.ts +0 -269
  384. package/src/__tests__/conflict-store.test.ts +0 -372
  385. package/src/__tests__/contradiction-checker.test.ts +0 -361
  386. package/src/__tests__/entity-extractor.test.ts +0 -211
  387. package/src/__tests__/entity-search.test.ts +0 -1117
  388. package/src/__tests__/profile-compiler.test.ts +0 -392
  389. package/src/__tests__/ride-shotgun-handler.test.ts +0 -452
  390. package/src/__tests__/session-conflict-gate.test.ts +0 -1228
  391. package/src/__tests__/session-profile-injection.test.ts +0 -557
  392. package/src/cli/commands/dev.ts +0 -129
  393. package/src/cli/commands/map.ts +0 -391
  394. package/src/cli/commands/oauth.ts +0 -77
  395. package/src/config/bundled-skills/knowledge-graph/SKILL.md +0 -25
  396. package/src/config/bundled-skills/knowledge-graph/TOOLS.json +0 -66
  397. package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +0 -211
  398. package/src/daemon/computer-use-session.ts +0 -1026
  399. package/src/daemon/ride-shotgun-handler.ts +0 -569
  400. package/src/daemon/session-conflict-gate.ts +0 -167
  401. package/src/daemon/session-dynamic-profile.ts +0 -77
  402. package/src/memory/clarification-resolver.ts +0 -417
  403. package/src/memory/conflict-intent.ts +0 -205
  404. package/src/memory/conflict-policy.ts +0 -127
  405. package/src/memory/conflict-store.ts +0 -410
  406. package/src/memory/contradiction-checker.ts +0 -508
  407. package/src/memory/entity-extractor.ts +0 -535
  408. package/src/memory/format-recall.ts +0 -47
  409. package/src/memory/fts-reconciler.ts +0 -165
  410. package/src/memory/job-handlers/conflict.ts +0 -200
  411. package/src/memory/profile-compiler.ts +0 -195
  412. package/src/memory/recall-cache.ts +0 -117
  413. package/src/memory/search/entity.ts +0 -535
  414. package/src/memory/search/query-expansion.test.ts +0 -70
  415. package/src/memory/search/query-expansion.ts +0 -118
  416. package/src/oauth/provider-base-urls.ts +0 -21
  417. package/src/oauth/provider-profiles.ts +0 -192
  418. package/src/prompts/computer-use-prompt.ts +0 -98
  419. package/src/runtime/routes/computer-use-routes.ts +0 -641
  420. package/src/runtime/routes/mcp-routes.ts +0 -20
  421. package/src/runtime/telegram-streaming-delivery.test.ts +0 -729
  422. package/src/runtime/telegram-streaming-delivery.ts +0 -393
  423. package/src/tools/computer-use/request-computer-control.ts +0 -56
@@ -161,60 +161,7 @@ describe("AssistantConfigSchema", () => {
161
161
  expect(result.secretDetection.action).toBe("block");
162
162
  });
163
163
 
164
- test("applies memory.conflicts defaults", () => {
165
- const result = AssistantConfigSchema.parse({});
166
- expect(result.memory.conflicts).toEqual({
167
- enabled: true,
168
- gateMode: "soft",
169
- resolverLlmTimeoutMs: 12000,
170
- relevanceThreshold: 0.3,
171
- conflictableKinds: [
172
- "preference",
173
- "profile",
174
- "constraint",
175
- "instruction",
176
- "style",
177
- ],
178
- });
179
- });
180
-
181
- test("rejects invalid memory.conflicts.relevanceThreshold", () => {
182
- const result = AssistantConfigSchema.safeParse({
183
- memory: { conflicts: { relevanceThreshold: 2 } },
184
- });
185
- expect(result.success).toBe(false);
186
- });
187
-
188
- test("rejects invalid memory.conflicts.conflictableKinds entry", () => {
189
- const result = AssistantConfigSchema.safeParse({
190
- memory: { conflicts: { conflictableKinds: ["invalid_kind"] } },
191
- });
192
- expect(result.success).toBe(false);
193
- });
194
-
195
- test("rejects empty memory.conflicts.conflictableKinds", () => {
196
- const result = AssistantConfigSchema.safeParse({
197
- memory: { conflicts: { conflictableKinds: [] } },
198
- });
199
- expect(result.success).toBe(false);
200
- });
201
-
202
- test("applies memory.profile defaults", () => {
203
- const result = AssistantConfigSchema.parse({});
204
- expect(result.memory.profile).toEqual({
205
- enabled: true,
206
- maxInjectTokens: 800,
207
- });
208
- });
209
-
210
- test("rejects invalid memory.profile.maxInjectTokens", () => {
211
- const result = AssistantConfigSchema.safeParse({
212
- memory: { profile: { maxInjectTokens: 0 } },
213
- });
214
- expect(result.success).toBe(false);
215
- });
216
-
217
- test("applies rollout defaults for dynamic budget and entity relation features", () => {
164
+ test("applies rollout defaults for dynamic budget", () => {
218
165
  const result = AssistantConfigSchema.parse({});
219
166
  expect(result.memory.retrieval.dynamicBudget).toEqual({
220
167
  enabled: true,
@@ -222,19 +169,6 @@ describe("AssistantConfigSchema", () => {
222
169
  maxInjectTokens: 10000,
223
170
  targetHeadroomTokens: 10000,
224
171
  });
225
- expect(result.memory.entity.extractRelations).toEqual({
226
- enabled: true,
227
- backfillBatchSize: 200,
228
- });
229
- expect(result.memory.entity.relationRetrieval).toEqual({
230
- enabled: true,
231
- maxSeedEntities: 8,
232
- maxNeighborEntities: 20,
233
- maxEdges: 40,
234
- neighborScoreMultiplier: 0.7,
235
- maxDepth: 3,
236
- depthDecay: true,
237
- });
238
172
  });
239
173
 
240
174
  test("applies memory.cleanup defaults", () => {
@@ -242,7 +176,6 @@ describe("AssistantConfigSchema", () => {
242
176
  expect(result.memory.cleanup).toEqual({
243
177
  enabled: true,
244
178
  enqueueIntervalMs: 6 * 60 * 60 * 1000,
245
- resolvedConflictRetentionMs: 30 * 24 * 60 * 60 * 1000,
246
179
  supersededItemRetentionMs: 30 * 24 * 60 * 60 * 1000,
247
180
  conversationRetentionDays: 90,
248
181
  });
@@ -54,7 +54,6 @@ mock.module("../util/logger.js", () => ({
54
54
  new Proxy({} as Record<string, unknown>, {
55
55
  get: () => () => {},
56
56
  }),
57
- isDebug: () => false,
58
57
  truncateForLog: (v: string) => v,
59
58
  }));
60
59
 
@@ -31,7 +31,6 @@ mock.module("../util/logger.js", () => ({
31
31
  new Proxy({} as Record<string, unknown>, {
32
32
  get: () => () => {},
33
33
  }),
34
- isDebug: () => false,
35
34
  truncateForLog: (value: string) => value,
36
35
  }));
37
36
 
@@ -0,0 +1,332 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { describe, expect, it } from "bun:test";
4
+
5
+ import { parseImageDimensions } from "../context/image-dimensions.js";
6
+
7
+ /**
8
+ * Helper: build a Buffer of given bytes and return its base64 encoding.
9
+ */
10
+ function toBase64(bytes: number[]): string {
11
+ return Buffer.from(bytes).toString("base64");
12
+ }
13
+
14
+ /**
15
+ * Minimal valid PNG IHDR: 8-byte signature + 13-byte IHDR chunk.
16
+ * Width = 320, Height = 240.
17
+ */
18
+ function minimalPngHeader(width: number, height: number): number[] {
19
+ const sig = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
20
+ // IHDR chunk: length (13 = 0x0000000D), "IHDR", width(4), height(4), bitDepth, colorType, compression, filter, interlace
21
+ const ihdrLength = [0x00, 0x00, 0x00, 0x0d];
22
+ const ihdrType = [0x49, 0x48, 0x44, 0x52]; // "IHDR"
23
+ const w = [
24
+ (width >> 24) & 0xff,
25
+ (width >> 16) & 0xff,
26
+ (width >> 8) & 0xff,
27
+ width & 0xff,
28
+ ];
29
+ const h = [
30
+ (height >> 24) & 0xff,
31
+ (height >> 16) & 0xff,
32
+ (height >> 8) & 0xff,
33
+ height & 0xff,
34
+ ];
35
+ const rest = [0x08, 0x06, 0x00, 0x00, 0x00]; // bit depth, color type RGBA, compression, filter, interlace
36
+ const crc = [0x00, 0x00, 0x00, 0x00]; // dummy CRC (not validated by parser)
37
+ return [...sig, ...ihdrLength, ...ihdrType, ...w, ...h, ...rest, ...crc];
38
+ }
39
+
40
+ /**
41
+ * Minimal valid JPEG with SOF0 marker.
42
+ * Structure: SOI + APP0 (short) + SOF0 with given dimensions.
43
+ */
44
+ function minimalJpegHeader(width: number, height: number): number[] {
45
+ const soi = [0xff, 0xd8]; // Start of image
46
+ // APP0 marker (JFIF) - minimal
47
+ const app0 = [
48
+ 0xff,
49
+ 0xe0, // APP0 marker
50
+ 0x00,
51
+ 0x10, // length = 16
52
+ 0x4a,
53
+ 0x46,
54
+ 0x49,
55
+ 0x46,
56
+ 0x00, // "JFIF\0"
57
+ 0x01,
58
+ 0x01, // version 1.1
59
+ 0x00, // aspect ratio units
60
+ 0x00,
61
+ 0x01, // X density
62
+ 0x00,
63
+ 0x01, // Y density
64
+ 0x00,
65
+ 0x00, // no thumbnail
66
+ ];
67
+ // SOF0 marker
68
+ const sof0 = [
69
+ 0xff,
70
+ 0xc0, // SOF0 marker
71
+ 0x00,
72
+ 0x0b, // length = 11
73
+ 0x08, // precision = 8 bits
74
+ (height >> 8) & 0xff,
75
+ height & 0xff, // height
76
+ (width >> 8) & 0xff,
77
+ width & 0xff, // width
78
+ 0x03, // number of components
79
+ 0x01,
80
+ 0x11,
81
+ 0x00, // Y component
82
+ ];
83
+ return [...soi, ...app0, ...sof0];
84
+ }
85
+
86
+ /**
87
+ * Minimal valid GIF89a header with given dimensions.
88
+ */
89
+ function minimalGifHeader(width: number, height: number): number[] {
90
+ // "GIF89a"
91
+ const sig = [0x47, 0x49, 0x46, 0x38, 0x39, 0x61];
92
+ const w = [width & 0xff, (width >> 8) & 0xff]; // little-endian uint16
93
+ const h = [height & 0xff, (height >> 8) & 0xff]; // little-endian uint16
94
+ return [...sig, ...w, ...h, 0x00, 0x00]; // pad to 12 bytes
95
+ }
96
+
97
+ /**
98
+ * Minimal valid WebP VP8 (lossy) header with given dimensions.
99
+ */
100
+ function minimalWebpVP8Header(width: number, height: number): number[] {
101
+ const riff = [0x52, 0x49, 0x46, 0x46]; // "RIFF"
102
+ const fileSize = [0x00, 0x00, 0x00, 0x00]; // dummy file size
103
+ const webp = [0x57, 0x45, 0x42, 0x50]; // "WEBP"
104
+ const vp8 = [0x56, 0x50, 0x38, 0x20]; // "VP8 "
105
+ const chunkSize = [0x00, 0x00, 0x00, 0x00]; // dummy chunk size
106
+ // VP8 bitstream header (bytes 20-25): frame tag + start code
107
+ const frameTag = [0x9d, 0x01, 0x2a]; // key frame tag bytes
108
+ const padding = [0x00, 0x00, 0x00]; // padding to reach offset 26
109
+ // Width at byte 26 (LE uint16), height at byte 28 (LE uint16)
110
+ const w = [width & 0xff, (width >> 8) & 0x3f]; // little-endian uint16, upper bits masked
111
+ const h = [height & 0xff, (height >> 8) & 0x3f]; // little-endian uint16, upper bits masked
112
+ return [
113
+ ...riff,
114
+ ...fileSize,
115
+ ...webp,
116
+ ...vp8,
117
+ ...chunkSize,
118
+ ...frameTag,
119
+ ...padding,
120
+ ...w,
121
+ ...h,
122
+ 0x00,
123
+ 0x00,
124
+ ];
125
+ }
126
+
127
+ /**
128
+ * Minimal valid WebP VP8L (lossless) header with given dimensions.
129
+ */
130
+ function minimalWebpVP8LHeader(width: number, height: number): number[] {
131
+ const riff = [0x52, 0x49, 0x46, 0x46];
132
+ const fileSize = [0x00, 0x00, 0x00, 0x00];
133
+ const webp = [0x57, 0x45, 0x42, 0x50];
134
+ const vp8l = [0x56, 0x50, 0x38, 0x4c]; // "VP8L"
135
+ const chunkSize = [0x00, 0x00, 0x00, 0x00];
136
+ // Signature byte at offset 20
137
+ const sigByte = [0x2f];
138
+ // At offset 21: LE uint32 encoding width-1 in bits 0-13 and height-1 in bits 14-27
139
+ const bits = ((width - 1) & 0x3fff) | (((height - 1) & 0x3fff) << 14);
140
+ const bitsBytes = [
141
+ bits & 0xff,
142
+ (bits >> 8) & 0xff,
143
+ (bits >> 16) & 0xff,
144
+ (bits >> 24) & 0xff,
145
+ ];
146
+ return [
147
+ ...riff,
148
+ ...fileSize,
149
+ ...webp,
150
+ ...vp8l,
151
+ ...chunkSize,
152
+ ...sigByte,
153
+ ...bitsBytes,
154
+ ];
155
+ }
156
+
157
+ /**
158
+ * Minimal valid WebP VP8X (extended) header with given dimensions.
159
+ */
160
+ function minimalWebpVP8XHeader(width: number, height: number): number[] {
161
+ const riff = [0x52, 0x49, 0x46, 0x46];
162
+ const fileSize = [0x00, 0x00, 0x00, 0x00];
163
+ const webp = [0x57, 0x45, 0x42, 0x50];
164
+ const vp8x = [0x56, 0x50, 0x38, 0x58]; // "VP8X"
165
+ const chunkSize = [0x0a, 0x00, 0x00, 0x00]; // chunk size = 10
166
+ const flags = [0x00, 0x00, 0x00, 0x00]; // flags (bytes 20-23)
167
+ // Width-1 as LE uint24 at offset 24
168
+ const w1 = width - 1;
169
+ const wBytes = [w1 & 0xff, (w1 >> 8) & 0xff, (w1 >> 16) & 0xff];
170
+ // Height-1 as LE uint24 at offset 27
171
+ const h1 = height - 1;
172
+ const hBytes = [h1 & 0xff, (h1 >> 8) & 0xff, (h1 >> 16) & 0xff];
173
+ return [
174
+ ...riff,
175
+ ...fileSize,
176
+ ...webp,
177
+ ...vp8x,
178
+ ...chunkSize,
179
+ ...flags,
180
+ ...wBytes,
181
+ ...hBytes,
182
+ ];
183
+ }
184
+
185
+ describe("parseImageDimensions", () => {
186
+ describe("PNG", () => {
187
+ it("extracts dimensions from a valid PNG header", () => {
188
+ const base64 = toBase64(minimalPngHeader(320, 240));
189
+ const result = parseImageDimensions(base64, "image/png");
190
+ expect(result).toEqual({ width: 320, height: 240 });
191
+ });
192
+
193
+ it("extracts dimensions from a large PNG", () => {
194
+ const base64 = toBase64(minimalPngHeader(3840, 2160));
195
+ const result = parseImageDimensions(base64, "image/png");
196
+ expect(result).toEqual({ width: 3840, height: 2160 });
197
+ });
198
+
199
+ it("returns null for truncated PNG data", () => {
200
+ const bytes = minimalPngHeader(320, 240);
201
+ const truncated = toBase64(bytes.slice(0, 10));
202
+ expect(parseImageDimensions(truncated, "image/png")).toBeNull();
203
+ });
204
+
205
+ it("returns null for corrupt PNG signature", () => {
206
+ const bytes = minimalPngHeader(320, 240);
207
+ bytes[0] = 0x00; // corrupt signature
208
+ expect(parseImageDimensions(toBase64(bytes), "image/png")).toBeNull();
209
+ });
210
+ });
211
+
212
+ describe("JPEG", () => {
213
+ it("extracts dimensions from a valid JPEG with SOF0", () => {
214
+ const base64 = toBase64(minimalJpegHeader(640, 480));
215
+ const result = parseImageDimensions(base64, "image/jpeg");
216
+ expect(result).toEqual({ width: 640, height: 480 });
217
+ });
218
+
219
+ it("extracts dimensions from a JPEG with SOF2 (progressive)", () => {
220
+ const bytes = minimalJpegHeader(800, 600);
221
+ // Change SOF0 (0xC0) to SOF2 (0xC2)
222
+ const sof0Idx = bytes.indexOf(0xc0, 2);
223
+ bytes[sof0Idx] = 0xc2;
224
+ const result = parseImageDimensions(toBase64(bytes), "image/jpeg");
225
+ expect(result).toEqual({ width: 800, height: 600 });
226
+ });
227
+
228
+ it("returns null for truncated JPEG data", () => {
229
+ const truncated = toBase64([0xff, 0xd8, 0xff, 0xc0]);
230
+ expect(parseImageDimensions(truncated, "image/jpeg")).toBeNull();
231
+ });
232
+
233
+ it("returns null for corrupt JPEG (missing SOI)", () => {
234
+ const bytes = minimalJpegHeader(640, 480);
235
+ bytes[0] = 0x00;
236
+ expect(parseImageDimensions(toBase64(bytes), "image/jpeg")).toBeNull();
237
+ });
238
+ });
239
+
240
+ describe("GIF", () => {
241
+ it("extracts dimensions from a valid GIF89a header", () => {
242
+ const base64 = toBase64(minimalGifHeader(100, 50));
243
+ const result = parseImageDimensions(base64, "image/gif");
244
+ expect(result).toEqual({ width: 100, height: 50 });
245
+ });
246
+
247
+ it("extracts dimensions from GIF87a header", () => {
248
+ const bytes = minimalGifHeader(256, 128);
249
+ bytes[4] = 0x37; // Change '9' to '7' for GIF87a — signature check is GIF8 only
250
+ bytes[5] = 0x61;
251
+ const result = parseImageDimensions(toBase64(bytes), "image/gif");
252
+ expect(result).toEqual({ width: 256, height: 128 });
253
+ });
254
+
255
+ it("returns null for truncated GIF data", () => {
256
+ const truncated = toBase64([0x47, 0x49, 0x46, 0x38, 0x39, 0x61]);
257
+ expect(parseImageDimensions(truncated, "image/gif")).toBeNull();
258
+ });
259
+
260
+ it("returns null for corrupt GIF signature", () => {
261
+ const bytes = minimalGifHeader(100, 50);
262
+ bytes[0] = 0x00;
263
+ expect(parseImageDimensions(toBase64(bytes), "image/gif")).toBeNull();
264
+ });
265
+ });
266
+
267
+ describe("WebP", () => {
268
+ it("extracts dimensions from a VP8 (lossy) WebP", () => {
269
+ const base64 = toBase64(minimalWebpVP8Header(400, 300));
270
+ const result = parseImageDimensions(base64, "image/webp");
271
+ expect(result).toEqual({ width: 400, height: 300 });
272
+ });
273
+
274
+ it("extracts dimensions from a VP8L (lossless) WebP", () => {
275
+ const base64 = toBase64(minimalWebpVP8LHeader(500, 250));
276
+ const result = parseImageDimensions(base64, "image/webp");
277
+ expect(result).toEqual({ width: 500, height: 250 });
278
+ });
279
+
280
+ it("extracts dimensions from a VP8X (extended) WebP", () => {
281
+ const base64 = toBase64(minimalWebpVP8XHeader(1920, 1080));
282
+ const result = parseImageDimensions(base64, "image/webp");
283
+ expect(result).toEqual({ width: 1920, height: 1080 });
284
+ });
285
+
286
+ it("returns null for truncated WebP data", () => {
287
+ const truncated = toBase64([
288
+ 0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
289
+ ]);
290
+ expect(parseImageDimensions(truncated, "image/webp")).toBeNull();
291
+ });
292
+
293
+ it("returns null for corrupt RIFF signature", () => {
294
+ const bytes = minimalWebpVP8Header(400, 300);
295
+ bytes[0] = 0x00;
296
+ expect(parseImageDimensions(toBase64(bytes), "image/webp")).toBeNull();
297
+ });
298
+ });
299
+
300
+ describe("unknown media type", () => {
301
+ it("returns null for unsupported media type", () => {
302
+ expect(parseImageDimensions("AAAA", "image/bmp")).toBeNull();
303
+ });
304
+
305
+ it("returns null for non-image media type", () => {
306
+ expect(parseImageDimensions("AAAA", "application/pdf")).toBeNull();
307
+ });
308
+ });
309
+
310
+ describe("empty/invalid data", () => {
311
+ it("returns null for empty base64 string", () => {
312
+ expect(parseImageDimensions("", "image/png")).toBeNull();
313
+ expect(parseImageDimensions("", "image/jpeg")).toBeNull();
314
+ expect(parseImageDimensions("", "image/gif")).toBeNull();
315
+ expect(parseImageDimensions("", "image/webp")).toBeNull();
316
+ });
317
+ });
318
+
319
+ describe("real image file", () => {
320
+ it("parses dimensions from an actual PNG file in the repo", () => {
321
+ const pngPath = join(
322
+ import.meta.dir,
323
+ "../../..",
324
+ "clients/chrome-extension/icons/icon16.png",
325
+ );
326
+ const pngData = readFileSync(pngPath);
327
+ const base64 = pngData.toString("base64");
328
+ const result = parseImageDimensions(base64, "image/png");
329
+ expect(result).toEqual({ width: 16, height: 16 });
330
+ });
331
+ });
332
+ });
@@ -20,9 +20,6 @@ import { computeRecallBudget } from "../memory/retrieval-budget.js";
20
20
  import { buildMemoryRecall } from "../memory/retriever.js";
21
21
  import {
22
22
  conversations,
23
- memoryEntities,
24
- memoryEntityRelations,
25
- memoryItemEntities,
26
23
  memoryItems,
27
24
  memoryItemSources,
28
25
  messages,
@@ -52,6 +49,7 @@ mock.module("../util/logger.js", () => ({
52
49
  mock.module("../memory/qdrant-client.js", () => ({
53
50
  getQdrantClient: () => ({
54
51
  searchWithFilter: async () => [],
52
+ hybridSearch: async () => [],
55
53
  upsertPoints: async () => {},
56
54
  deletePoints: async () => {},
57
55
  }),
@@ -168,13 +166,9 @@ describe("Context + Memory E2E regression", () => {
168
166
  beforeEach(() => {
169
167
  const db = getDb();
170
168
  db.run("DELETE FROM memory_item_sources");
171
- db.run("DELETE FROM memory_item_entities");
172
- db.run("DELETE FROM memory_entity_relations");
173
- db.run("DELETE FROM memory_entities");
174
169
  db.run("DELETE FROM memory_embeddings");
175
- db.run("DELETE FROM memory_summaries");
176
170
  db.run("DELETE FROM memory_items");
177
- db.run("DELETE FROM memory_segment_fts");
171
+
178
172
  db.run("DELETE FROM memory_segments");
179
173
  db.run("DELETE FROM messages");
180
174
  db.run("DELETE FROM conversations");
@@ -279,43 +273,6 @@ describe("Context + Memory E2E regression", () => {
279
273
  now + 100_000,
280
274
  );
281
275
 
282
- db.insert(memoryEntities)
283
- .values([
284
- {
285
- id: "entity-apollo",
286
- name: "Apollo",
287
- type: "project",
288
- aliases: JSON.stringify(["project-apollo"]),
289
- description: null,
290
- firstSeenAt: now,
291
- lastSeenAt: now + 100_000,
292
- mentionCount: 6,
293
- },
294
- {
295
- id: "entity-hermes",
296
- name: "HermesGate",
297
- type: "strategy",
298
- aliases: JSON.stringify(["hermes-gate"]),
299
- description: null,
300
- firstSeenAt: now,
301
- lastSeenAt: now + 100_000,
302
- mentionCount: 4,
303
- },
304
- ])
305
- .run();
306
-
307
- db.insert(memoryEntityRelations)
308
- .values({
309
- id: "rel-apollo-hermes",
310
- sourceEntityId: "entity-apollo",
311
- targetEntityId: "entity-hermes",
312
- relation: "uses",
313
- evidence: "Apollo uses HermesGate for risky changes",
314
- firstSeenAt: now,
315
- lastSeenAt: now + 50_000,
316
- })
317
- .run();
318
-
319
276
  insertMemoryItem({
320
277
  id: "item-apollo-direct",
321
278
  kind: "preference",
@@ -335,16 +292,10 @@ describe("Context + Memory E2E regression", () => {
335
292
  createdAt: now + 10_000,
336
293
  })
337
294
  .run();
338
- db.insert(memoryItemEntities)
339
- .values({
340
- memoryItemId: "item-apollo-direct",
341
- entityId: "entity-apollo",
342
- })
343
- .run();
344
295
 
345
296
  insertMemoryItem({
346
297
  id: "item-hermes-relation",
347
- kind: "fact",
298
+ kind: "identity",
348
299
  subject: "hermes rollout execution",
349
300
  statement:
350
301
  "HermesGate rollout guidance: start at 5% traffic and promote only after error budget checks pass.",
@@ -361,12 +312,6 @@ describe("Context + Memory E2E regression", () => {
361
312
  createdAt: now + 12_000,
362
313
  })
363
314
  .run();
364
- db.insert(memoryItemEntities)
365
- .values({
366
- memoryItemId: "item-hermes-relation",
367
- entityId: "entity-hermes",
368
- })
369
- .run();
370
315
 
371
316
  insertMemoryItem({
372
317
  id: "item-apollo-stale",
@@ -387,16 +332,10 @@ describe("Context + Memory E2E regression", () => {
387
332
  createdAt: now - 390 * 24 * 60 * 60 * 1000,
388
333
  })
389
334
  .run();
390
- db.insert(memoryItemEntities)
391
- .values({
392
- memoryItemId: "item-apollo-stale",
393
- entityId: "entity-apollo",
394
- })
395
- .run();
396
335
 
397
336
  insertMemoryItem({
398
337
  id: "item-apollo-secret",
399
- kind: "fact",
338
+ kind: "identity",
400
339
  subject: "apollo secret",
401
340
  statement: "Current-turn secret: Apollo code is 123XYZ.",
402
341
  confidence: 0.99,
@@ -412,12 +351,6 @@ describe("Context + Memory E2E regression", () => {
412
351
  createdAt: now + 100_000,
413
352
  })
414
353
  .run();
415
- db.insert(memoryItemEntities)
416
- .values({
417
- memoryItemId: "item-apollo-secret",
418
- entityId: "entity-apollo",
419
- })
420
- .run();
421
354
 
422
355
  const summaryCounter = { calls: 0 };
423
356
  const provider = makeSummaryProvider(summaryCounter);
@@ -454,13 +387,7 @@ describe("Context + Memory E2E regression", () => {
454
387
  },
455
388
  retrieval: {
456
389
  ...DEFAULT_CONFIG.memory.retrieval,
457
- lexicalTopK: 50,
458
- semanticTopK: 16,
459
390
  maxInjectTokens: 900,
460
- reranking: {
461
- ...DEFAULT_CONFIG.memory.retrieval.reranking,
462
- enabled: false,
463
- },
464
391
  dynamicBudget: {
465
392
  enabled: true,
466
393
  minInjectTokens: 180,
@@ -468,17 +395,6 @@ describe("Context + Memory E2E regression", () => {
468
395
  targetHeadroomTokens: 700,
469
396
  },
470
397
  },
471
- entity: {
472
- ...DEFAULT_CONFIG.memory.entity,
473
- relationRetrieval: {
474
- ...DEFAULT_CONFIG.memory.entity.relationRetrieval,
475
- enabled: true,
476
- maxSeedEntities: 4,
477
- maxNeighborEntities: 6,
478
- maxEdges: 8,
479
- neighborScoreMultiplier: 0.65,
480
- },
481
- },
482
398
  },
483
399
  };
484
400
 
@@ -511,19 +427,14 @@ describe("Context + Memory E2E regression", () => {
511
427
  );
512
428
 
513
429
  expect(recall.injectedTokens).toBeLessThanOrEqual(recallBudget);
514
- expect(recall.relationSeedEntityCount).toBeGreaterThan(0);
515
- expect(recall.relationTraversedEdgeCount).toBeGreaterThan(0);
516
- expect(recall.relationNeighborEntityCount).toBeGreaterThan(0);
517
- expect(recall.relationExpandedItemCount).toBeGreaterThan(0);
518
430
 
519
- expect(recall.injectedText).toContain("staged canary releases");
520
- expect(recall.injectedText).toContain("start at 5% traffic");
431
+ // With Qdrant mocked empty the only retrieval path is recency search,
432
+ // but recency-only candidates score below the tier-2 threshold (0.6)
433
+ // since finalScore = semantic*0.7 + recency*0.2 + confidence*0.1 and
434
+ // semantic=0 for recency hits. This means no candidates pass tier
435
+ // classification and injectedText is empty — which is correct behavior:
436
+ // the pipeline requires at least tier-2 quality to inject memory context.
437
+ // Verify current-turn secrets never leak regardless.
521
438
  expect(recall.injectedText).not.toContain("123XYZ");
522
-
523
- const directIndex = recall.injectedText.indexOf("staged canary releases");
524
- const relationIndex = recall.injectedText.indexOf("start at 5% traffic");
525
- expect(directIndex).toBeGreaterThanOrEqual(0);
526
- expect(relationIndex).toBeGreaterThanOrEqual(0);
527
- expect(directIndex).toBeLessThan(relationIndex);
528
439
  });
529
440
  });