@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
@@ -2,26 +2,15 @@ import { and, asc, eq, inArray, lt } from "drizzle-orm";
2
2
 
3
3
  import type { AssistantConfig } from "../../config/types.js";
4
4
  import { getLogger } from "../../util/logger.js";
5
- import { checkContradictions } from "../contradiction-checker.js";
6
5
  import { getDb, rawAll, rawRun } from "../db.js";
7
- import { asPositiveMs, asString } from "../job-utils.js";
6
+ import { asPositiveMs } from "../job-utils.js";
8
7
  import { enqueueMemoryJob, type MemoryJob } from "../jobs-store.js";
9
- import {
10
- memoryEmbeddings,
11
- memoryItemEntities,
12
- memoryItems,
13
- } from "../schema.js";
8
+ import { memoryEmbeddings, memoryItems } from "../schema.js";
14
9
 
15
10
  const log = getLogger("memory-jobs-worker");
16
11
 
17
12
  const CLEANUP_BATCH_LIMIT = 250;
18
13
 
19
- export async function checkContradictionsJob(job: MemoryJob): Promise<void> {
20
- const itemId = asString(job.payload.itemId);
21
- if (!itemId) return;
22
- await checkContradictions(itemId);
23
- }
24
-
25
14
  export function cleanupStaleSupersededItemsJob(
26
15
  job: MemoryJob,
27
16
  config: AssistantConfig,
@@ -46,9 +35,6 @@ export function cleanupStaleSupersededItemsJob(
46
35
  if (stale.length === 0) return;
47
36
 
48
37
  const ids = stale.map((row) => row.id);
49
- db.delete(memoryItemEntities)
50
- .where(inArray(memoryItemEntities.memoryItemId, ids))
51
- .run();
52
38
  db.delete(memoryEmbeddings)
53
39
  .where(
54
40
  and(
@@ -1,21 +1,11 @@
1
1
  import { eq } from "drizzle-orm";
2
2
 
3
- import { getConfig } from "../../config/loader.js";
4
- import type { AssistantConfig } from "../../config/types.js";
5
3
  import { getLogger } from "../../util/logger.js";
6
4
  import { getDb } from "../db.js";
7
- import {
8
- extractEntitiesWithLLM,
9
- linkMemoryItemToEntity,
10
- resolveEntityName,
11
- upsertEntity,
12
- upsertEntityRelation,
13
- } from "../entity-extractor.js";
14
5
  import { extractAndUpsertMemoryItemsForMessage } from "../items-extractor.js";
15
6
  import { asString } from "../job-utils.js";
16
- import { enqueueMemoryJob, type MemoryJob } from "../jobs-store.js";
17
- import { extractTextFromStoredMessageContent } from "../message-content.js";
18
- import { memoryItemSources, messages } from "../schema.js";
7
+ import type { MemoryJob } from "../jobs-store.js";
8
+ import { messages } from "../schema.js";
19
9
  import { isConversationFailed } from "../task-memory-cleanup.js";
20
10
 
21
11
  const log = getLogger("memory-jobs-worker");
@@ -47,130 +37,4 @@ export async function extractItemsJob(job: MemoryJob): Promise<void> {
47
37
  scopeId,
48
38
  msg?.conversationId,
49
39
  );
50
- // Queue entity extraction for this message after items are extracted
51
- const config = getConfig();
52
- if (config.memory.entity.enabled) {
53
- enqueueMemoryJob("extract_entities", { messageId, scopeId });
54
- }
55
- }
56
-
57
- export async function extractEntitiesJob(
58
- job: MemoryJob,
59
- config: AssistantConfig,
60
- ): Promise<void> {
61
- const messageId = asString(job.payload.messageId);
62
- if (!messageId) return;
63
-
64
- const db = getDb();
65
-
66
- // Guard: skip entity extraction for failed conversations. Entity extraction
67
- // jobs are enqueued by extractItemsJob after items are extracted; while new
68
- // jobs won't be queued (extractItemsJob returns early for failed convos),
69
- // any entity jobs enqueued before the failure marker was set must be caught.
70
- const msgRow = db
71
- .select({ conversationId: messages.conversationId })
72
- .from(messages)
73
- .where(eq(messages.id, messageId))
74
- .get();
75
- if (msgRow && isConversationFailed(msgRow.conversationId)) {
76
- log.info(
77
- { messageId, conversationId: msgRow.conversationId },
78
- "Skipping entity extraction for failed conversation",
79
- );
80
- return;
81
- }
82
-
83
- const message = db
84
- .select({
85
- id: messages.id,
86
- content: messages.content,
87
- })
88
- .from(messages)
89
- .where(eq(messages.id, messageId))
90
- .get();
91
- if (!message) return;
92
-
93
- const text = extractTextFromStoredMessageContent(message.content);
94
- if (text.trim().length < 15) return;
95
-
96
- const extracted = await extractEntitiesWithLLM(text, config.memory.entity);
97
- const entities = extracted.entities;
98
- const relations = extracted.relations;
99
- if (entities.length === 0 && relations.length === 0) return;
100
-
101
- // Find all memory items linked to this message via memory_item_sources
102
- const linkedItems = db
103
- .select({ memoryItemId: memoryItemSources.memoryItemId })
104
- .from(memoryItemSources)
105
- .where(eq(memoryItemSources.messageId, messageId))
106
- .all();
107
- const itemIds = linkedItems.map((row) => row.memoryItemId);
108
- const entityNameToId = new Map<string, string>();
109
-
110
- for (const entity of entities) {
111
- const entityId = upsertEntity(entity);
112
- entityNameToId.set(entity.name.toLowerCase(), entityId);
113
- for (const alias of entity.aliases) {
114
- entityNameToId.set(alias.toLowerCase(), entityId);
115
- }
116
- // Link all memory items from this message to the entity
117
- for (const itemId of itemIds) {
118
- linkMemoryItemToEntity(itemId, entityId);
119
- }
120
- }
121
-
122
- const relationTelemetry = {
123
- attempted: 0,
124
- parsed: relations.length,
125
- persisted: 0,
126
- dropped: 0,
127
- };
128
-
129
- if (config.memory.entity.extractRelations.enabled && relations.length > 0) {
130
- const seenRelationKeys = new Set<string>();
131
- for (const relation of relations) {
132
- relationTelemetry.attempted += 1;
133
- const sourceLookup = relation.sourceEntityName.toLowerCase();
134
- const targetLookup = relation.targetEntityName.toLowerCase();
135
- const sourceEntityId =
136
- entityNameToId.get(sourceLookup) ??
137
- resolveEntityName(relation.sourceEntityName);
138
- const targetEntityId =
139
- entityNameToId.get(targetLookup) ??
140
- resolveEntityName(relation.targetEntityName);
141
- if (
142
- !sourceEntityId ||
143
- !targetEntityId ||
144
- sourceEntityId === targetEntityId
145
- ) {
146
- relationTelemetry.dropped += 1;
147
- continue;
148
- }
149
-
150
- const dedupeKey = `${sourceEntityId}|${targetEntityId}|${relation.relation}`;
151
- if (seenRelationKeys.has(dedupeKey)) continue;
152
- seenRelationKeys.add(dedupeKey);
153
-
154
- upsertEntityRelation({
155
- sourceEntityId,
156
- targetEntityId,
157
- relation: relation.relation,
158
- evidence: relation.evidence,
159
- });
160
- relationTelemetry.persisted += 1;
161
- }
162
- }
163
-
164
- log.debug(
165
- {
166
- messageId,
167
- entityCount: entities.length,
168
- linkedItems: itemIds.length,
169
- relationAttempts: relationTelemetry.attempted,
170
- relationParsed: relationTelemetry.parsed,
171
- relationPersisted: relationTelemetry.persisted,
172
- relationDropped: relationTelemetry.dropped,
173
- },
174
- "Extracted entity graph from message",
175
- );
176
40
  }
@@ -2,7 +2,7 @@ import { eq, like } from "drizzle-orm";
2
2
 
3
3
  import { getConfig } from "../../config/loader.js";
4
4
  import { getLogger } from "../../util/logger.js";
5
- import { getDb, rawExec } from "../db.js";
5
+ import { getDb } from "../db.js";
6
6
  import { selectedBackendSupportsMultimodal } from "../embedding-backend.js";
7
7
  import { asString, BackendUnavailableError } from "../job-utils.js";
8
8
  import { enqueueMemoryJob, type MemoryJob } from "../jobs-store.js";
@@ -22,11 +22,6 @@ const log = getLogger("memory-jobs-worker");
22
22
 
23
23
  export function rebuildIndexJob(): void {
24
24
  const db = getDb();
25
- rawExec(/*sql*/ `DELETE FROM memory_segment_fts`);
26
- rawExec(/*sql*/ `
27
- INSERT INTO memory_segment_fts(segment_id, text)
28
- SELECT id, text FROM memory_segments
29
- `);
30
25
  db.delete(memoryEmbeddings).run();
31
26
 
32
27
  const items = db
@@ -1,4 +1,4 @@
1
- import { and, desc, eq, gte, isNull, lt, sql } from "drizzle-orm";
1
+ import { and, desc, eq, sql } from "drizzle-orm";
2
2
  import { v4 as uuid } from "uuid";
3
3
 
4
4
  import type { AssistantConfig } from "../../config/types.js";
@@ -12,14 +12,9 @@ import {
12
12
  import { getLogger } from "../../util/logger.js";
13
13
  import { getConversationMemoryScopeId } from "../conversation-crud.js";
14
14
  import { getDb } from "../db.js";
15
- import {
16
- asString,
17
- currentMonthWindow,
18
- currentWeekWindow,
19
- truncate,
20
- } from "../job-utils.js";
15
+ import { asString, truncate } from "../job-utils.js";
21
16
  import { enqueueMemoryJob, type MemoryJob } from "../jobs-store.js";
22
- import { memoryItems, memorySegments, memorySummaries } from "../schema.js";
17
+ import { memorySegments, memorySummaries } from "../schema.js";
23
18
 
24
19
  const log = getLogger("memory-jobs-worker");
25
20
 
@@ -38,18 +33,6 @@ const CONVERSATION_SUMMARY_SYSTEM_PROMPT = [
38
33
  "- If updating an existing summary with new data, merge new information and remove anything that was superseded.",
39
34
  ].join("\n");
40
35
 
41
- const GLOBAL_SUMMARY_SYSTEM_PROMPT = [
42
- "You are a memory summarization system. Your job is to synthesize a higher-level summary from multiple conversation summaries and memory items.",
43
- "",
44
- "Guidelines:",
45
- "- Identify recurring themes, cross-cutting decisions, and persistent user preferences.",
46
- "- Highlight the most important facts, active projects, and ongoing concerns.",
47
- "- De-duplicate information that appears across multiple conversations.",
48
- "- Use concise sections with bullet points.",
49
- "- Target 400-600 tokens. Be dense but readable.",
50
- "- If updating an existing summary with new data, merge new information and remove anything that was superseded.",
51
- ].join("\n");
52
-
53
36
  export async function buildConversationSummaryJob(
54
37
  job: MemoryJob,
55
38
  config: AssistantConfig,
@@ -144,134 +127,6 @@ export async function buildConversationSummaryJob(
144
127
  }
145
128
  }
146
129
 
147
- export async function buildGlobalSummaryJob(
148
- scope: "weekly_global" | "monthly_global",
149
- config: AssistantConfig,
150
- ): Promise<void> {
151
- const db = getDb();
152
- const now = new Date();
153
- const { startMs, endMs, scopeKey } =
154
- scope === "weekly_global"
155
- ? currentWeekWindow(now)
156
- : currentMonthWindow(now);
157
-
158
- const items = db
159
- .select()
160
- .from(memoryItems)
161
- .where(
162
- and(
163
- eq(memoryItems.status, "active"),
164
- isNull(memoryItems.invalidAt),
165
- eq(memoryItems.scopeId, "default"),
166
- gte(memoryItems.lastSeenAt, startMs),
167
- lt(memoryItems.lastSeenAt, endMs),
168
- ),
169
- )
170
- .orderBy(desc(memoryItems.lastSeenAt))
171
- .limit(80)
172
- .all();
173
-
174
- // Gather conversation summaries from this period for higher-level synthesis
175
- const convSummaries = db
176
- .select()
177
- .from(memorySummaries)
178
- .where(
179
- and(
180
- eq(memorySummaries.scope, "conversation"),
181
- eq(memorySummaries.scopeId, "default"),
182
- gte(memorySummaries.endAt, startMs),
183
- lt(memorySummaries.startAt, endMs),
184
- ),
185
- )
186
- .orderBy(desc(memorySummaries.endAt))
187
- .limit(20)
188
- .all();
189
-
190
- if (items.length === 0 && convSummaries.length === 0) return;
191
-
192
- // Build input for LLM: conversation summaries + active items
193
- const parts: string[] = [];
194
- if (convSummaries.length > 0) {
195
- parts.push("## Conversation Summaries");
196
- for (const cs of convSummaries) {
197
- parts.push(`### ${cs.scopeKey}\n${truncate(cs.summary, 600)}`);
198
- }
199
- }
200
- if (items.length > 0) {
201
- parts.push("## Active Memory Items");
202
- for (const item of items.slice(0, 40)) {
203
- parts.push(
204
- `- [${item.kind}] ${item.subject}: ${truncate(item.statement, 180)}`,
205
- );
206
- }
207
- }
208
- const inputText = parts.join("\n\n");
209
-
210
- const existing = db
211
- .select()
212
- .from(memorySummaries)
213
- .where(
214
- and(
215
- eq(memorySummaries.scope, scope),
216
- eq(memorySummaries.scopeKey, scopeKey),
217
- ),
218
- )
219
- .get();
220
-
221
- const label = scope === "weekly_global" ? "weekly" : "monthly";
222
- const summaryText = await summarizeWithLLM(
223
- config,
224
- GLOBAL_SUMMARY_SYSTEM_PROMPT,
225
- existing?.summary ?? null,
226
- inputText,
227
- label,
228
- );
229
-
230
- const ts = Date.now();
231
- const summaryId = existing?.id ?? uuid();
232
- db.insert(memorySummaries)
233
- .values({
234
- id: summaryId,
235
- scope,
236
- scopeKey,
237
- summary: summaryText,
238
- tokenEstimate: estimateTextTokens(summaryText),
239
- version: (existing?.version ?? 0) + 1,
240
- startAt: startMs,
241
- endAt: endMs,
242
- createdAt: ts,
243
- updatedAt: ts,
244
- })
245
- .onConflictDoUpdate({
246
- target: [memorySummaries.scope, memorySummaries.scopeKey],
247
- set: {
248
- summary: summaryText,
249
- tokenEstimate: estimateTextTokens(summaryText),
250
- version: sql`${memorySummaries.version} + 1`,
251
- startAt: startMs,
252
- endAt: endMs,
253
- updatedAt: ts,
254
- },
255
- })
256
- .run();
257
-
258
- // Re-query to get the actual persisted row ID — during a race the ON CONFLICT
259
- // path keeps the winner's ID, not the pre-generated UUID from the loser.
260
- const actualRow = db
261
- .select({ id: memorySummaries.id })
262
- .from(memorySummaries)
263
- .where(
264
- and(
265
- eq(memorySummaries.scope, scope),
266
- eq(memorySummaries.scopeKey, scopeKey),
267
- ),
268
- )
269
- .get();
270
- if (actualRow) {
271
- enqueueMemoryJob("embed_summary", { summaryId: actualRow.id });
272
- }
273
- }
274
-
275
130
  async function summarizeWithLLM(
276
131
  config: AssistantConfig,
277
132
  systemPrompt: string,
@@ -8,6 +8,7 @@ import { getLogger } from "../util/logger.js";
8
8
  import { getDb } from "./db.js";
9
9
  import {
10
10
  embedWithBackend,
11
+ generateSparseEmbedding,
11
12
  getMemoryBackendStatus,
12
13
  } from "./embedding-backend.js";
13
14
  import type { EmbeddingInput } from "./embedding-types.js";
@@ -201,6 +202,14 @@ export async function embedAndUpsert(
201
202
  ? normalized.text
202
203
  : `[${normalized.type}:${normalized.mimeType}]`;
203
204
 
205
+ // Generate sparse embedding from the same source text used for dense embedding.
206
+ // For non-text (media) inputs, sparse vectors are skipped since tokenization
207
+ // only applies to text content.
208
+ const sparseVector =
209
+ normalized.type === "text"
210
+ ? generateSparseEmbedding(normalized.text)
211
+ : undefined;
212
+
204
213
  // Persist embedding in SQLite for cross-restart cache
205
214
  const now = Date.now();
206
215
  try {
@@ -249,12 +258,18 @@ export async function embedAndUpsert(
249
258
  try {
250
259
  const modality = normalized.type;
251
260
  await withQdrantBreaker(() =>
252
- qdrant.upsert(targetType, targetId, vector, {
253
- text: payloadText,
254
- modality,
255
- created_at: (extraPayload?.created_at as number) ?? now,
256
- ...(extraPayload as Record<string, unknown> | undefined),
257
- }),
261
+ qdrant.upsert(
262
+ targetType,
263
+ targetId,
264
+ vector,
265
+ {
266
+ text: payloadText,
267
+ modality,
268
+ created_at: (extraPayload?.created_at as number) ?? now,
269
+ ...(extraPayload as Record<string, unknown> | undefined),
270
+ },
271
+ sparseVector,
272
+ ),
258
273
  );
259
274
  } catch (err) {
260
275
  log.warn(
@@ -265,56 +280,3 @@ export async function embedAndUpsert(
265
280
  }
266
281
  }
267
282
 
268
- // ── Time window utilities ──────────────────────────────────────────
269
-
270
- export function currentWeekWindow(now: Date): {
271
- scopeKey: string;
272
- startMs: number;
273
- endMs: number;
274
- } {
275
- const day = (now.getUTCDay() + 6) % 7;
276
- const start = new Date(
277
- Date.UTC(
278
- now.getUTCFullYear(),
279
- now.getUTCMonth(),
280
- now.getUTCDate() - day,
281
- 0,
282
- 0,
283
- 0,
284
- 0,
285
- ),
286
- );
287
- const end = new Date(start);
288
- end.setUTCDate(end.getUTCDate() + 7);
289
- const scopeKey = `${start.getUTCFullYear()}-W${weekNumber(start)
290
- .toString()
291
- .padStart(2, "0")}`;
292
- return { scopeKey, startMs: start.getTime(), endMs: end.getTime() };
293
- }
294
-
295
- export function currentMonthWindow(now: Date): {
296
- scopeKey: string;
297
- startMs: number;
298
- endMs: number;
299
- } {
300
- const start = new Date(
301
- Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1, 0, 0, 0, 0),
302
- );
303
- const end = new Date(
304
- Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1, 0, 0, 0, 0),
305
- );
306
- const scopeKey = `${start.getUTCFullYear()}-${String(
307
- start.getUTCMonth() + 1,
308
- ).padStart(2, "0")}`;
309
- return { scopeKey, startMs: start.getTime(), endMs: end.getTime() };
310
- }
311
-
312
- function weekNumber(date: Date): number {
313
- const tmp = new Date(
314
- Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()),
315
- );
316
- const dayNum = tmp.getUTCDay() || 7;
317
- tmp.setUTCDate(tmp.getUTCDate() + 4 - dayNum);
318
- const yearStart = new Date(Date.UTC(tmp.getUTCFullYear(), 0, 1));
319
- return Math.ceil(((tmp.getTime() - yearStart.getTime()) / 86400000 + 1) / 7);
320
- }
@@ -3,7 +3,7 @@ import { v4 as uuid } from "uuid";
3
3
 
4
4
  import { getLogger } from "../util/logger.js";
5
5
  import { truncate } from "../util/truncate.js";
6
- import { getDb, rawAll, rawChanges, rawGet } from "./db.js";
6
+ import { getDb, rawAll, rawChanges } from "./db.js";
7
7
  import { memoryJobs } from "./schema.js";
8
8
 
9
9
  const log = getLogger("memory-jobs-store");
@@ -14,18 +14,14 @@ export type MemoryJobType =
14
14
  | "embed_summary"
15
15
  | "extract_items"
16
16
  | "extract_entities"
17
- | "resolve_pending_conflicts_for_message"
18
- | "cleanup_resolved_conflicts"
19
17
  | "cleanup_stale_superseded_items"
20
18
  | "prune_old_conversations"
21
19
  | "backfill_entity_relations"
22
- | "check_contradictions"
23
20
  | "refresh_weekly_summary"
24
21
  | "refresh_monthly_summary"
25
22
  | "build_conversation_summary"
26
23
  | "backfill"
27
24
  | "rebuild_index"
28
- | "reconcile_fts"
29
25
  | "delete_qdrant_vectors"
30
26
  | "media_processing"
31
27
  | "embed_media"
@@ -83,143 +79,6 @@ export function enqueueMemoryJob(
83
79
  return id;
84
80
  }
85
81
 
86
- /**
87
- * Ensure there is only one pending relation backfill orchestrator job.
88
- * If `force=true` arrives while a pending job exists, its payload is upgraded.
89
- */
90
- export function enqueueBackfillEntityRelationsJob(force = false): string {
91
- const db = getDb();
92
- const now = Date.now();
93
- const existing = db
94
- .select()
95
- .from(memoryJobs)
96
- .where(
97
- and(
98
- eq(memoryJobs.type, "backfill_entity_relations"),
99
- eq(memoryJobs.status, "pending"),
100
- ),
101
- )
102
- .orderBy(asc(memoryJobs.createdAt))
103
- .get();
104
-
105
- if (existing) {
106
- if (force) {
107
- let payload: Record<string, unknown> = {};
108
- try {
109
- payload = JSON.parse(existing.payload) as Record<string, unknown>;
110
- } catch {
111
- payload = {};
112
- }
113
- if (payload.force !== true) {
114
- db.update(memoryJobs)
115
- .set({
116
- payload: JSON.stringify({ ...payload, force: true }),
117
- updatedAt: now,
118
- })
119
- .where(eq(memoryJobs.id, existing.id))
120
- .run();
121
- }
122
- }
123
- return existing.id;
124
- }
125
-
126
- return enqueueMemoryJob("backfill_entity_relations", { force });
127
- }
128
-
129
- export function enqueueResolvePendingConflictsForMessageJob(
130
- messageId: string,
131
- scopeId = "default",
132
- dbOverride?: Parameters<ReturnType<typeof getDb>["transaction"]>[0] extends (
133
- tx: infer T,
134
- ) => unknown
135
- ? T
136
- : never,
137
- ): string {
138
- const normalizedMessageId = messageId.trim();
139
- if (!normalizedMessageId) {
140
- throw new Error(
141
- "enqueueResolvePendingConflictsForMessageJob requires a non-empty messageId",
142
- );
143
- }
144
- const normalizedScopeId = scopeId.trim() || "default";
145
- // Dedup check always uses root db since tx doesn't expose raw client
146
- const existing = rawGet<{ id: string }>(
147
- `
148
- SELECT id
149
- FROM memory_jobs
150
- WHERE type = 'resolve_pending_conflicts_for_message'
151
- AND status IN ('pending', 'running')
152
- AND json_extract(payload, '$.messageId') = ?
153
- AND COALESCE(json_extract(payload, '$.scopeId'), 'default') = ?
154
- ORDER BY created_at ASC
155
- LIMIT 1
156
- `,
157
- normalizedMessageId,
158
- normalizedScopeId,
159
- );
160
- if (existing?.id) return existing.id;
161
-
162
- return enqueueMemoryJob(
163
- "resolve_pending_conflicts_for_message",
164
- {
165
- messageId: normalizedMessageId,
166
- scopeId: normalizedScopeId,
167
- },
168
- Date.now(),
169
- dbOverride,
170
- );
171
- }
172
-
173
- export function enqueueCleanupResolvedConflictsJob(
174
- retentionMs?: number,
175
- ): string {
176
- const db = getDb();
177
- const now = Date.now();
178
- const existing = db
179
- .select()
180
- .from(memoryJobs)
181
- .where(
182
- and(
183
- eq(memoryJobs.type, "cleanup_resolved_conflicts"),
184
- inArray(memoryJobs.status, ["pending", "running"]),
185
- ),
186
- )
187
- .orderBy(asc(memoryJobs.createdAt))
188
- .get();
189
- if (existing) {
190
- if (
191
- existing.status === "pending" &&
192
- typeof retentionMs === "number" &&
193
- Number.isFinite(retentionMs) &&
194
- retentionMs > 0
195
- ) {
196
- let payload: Record<string, unknown> = {};
197
- try {
198
- payload = JSON.parse(existing.payload) as Record<string, unknown>;
199
- } catch {
200
- payload = {};
201
- }
202
- if (payload.retentionMs !== retentionMs) {
203
- db.update(memoryJobs)
204
- .set({
205
- payload: JSON.stringify({ ...payload, retentionMs }),
206
- updatedAt: now,
207
- })
208
- .where(eq(memoryJobs.id, existing.id))
209
- .run();
210
- }
211
- }
212
- return existing.id;
213
- }
214
- const payload =
215
- typeof retentionMs === "number" &&
216
- Number.isFinite(retentionMs) &&
217
- retentionMs > 0
218
- ? { retentionMs }
219
- : {};
220
- return enqueueMemoryJob("cleanup_resolved_conflicts", payload);
221
- }
222
-
223
82
  export function enqueueCleanupStaleSupersededItemsJob(
224
83
  retentionMs?: number,
225
84
  ): string {
@@ -319,23 +178,6 @@ export function enqueuePruneOldConversationsJob(
319
178
  return enqueueMemoryJob("prune_old_conversations", payload);
320
179
  }
321
180
 
322
- export function enqueueReconcileFtsJob(): string {
323
- const db = getDb();
324
- const existing = db
325
- .select()
326
- .from(memoryJobs)
327
- .where(
328
- and(
329
- eq(memoryJobs.type, "reconcile_fts"),
330
- inArray(memoryJobs.status, ["pending", "running"]),
331
- ),
332
- )
333
- .orderBy(asc(memoryJobs.createdAt))
334
- .get();
335
- if (existing) return existing.id;
336
- return enqueueMemoryJob("reconcile_fts", {});
337
- }
338
-
339
181
  export function claimMemoryJobs(limit: number): MemoryJob[] {
340
182
  if (limit <= 0) return [];
341
183
  const db = getDb();