@askexenow/exe-os 0.9.270 → 0.9.272

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 (311) hide show
  1. package/dist/active-agent-BDYXURXQ.js +26 -0
  2. package/dist/active-agent-YWBGAKGU.js +25 -0
  3. package/dist/agentic-ontology-56VHSVS3.js +25 -0
  4. package/dist/backfill-metadata-G46ABBVR.js +597 -0
  5. package/dist/backfill-metadata-VAV27KJK.js +597 -0
  6. package/dist/behaviors-USUTDXVA.js +25 -0
  7. package/dist/bin/agentic-ontology-backfill.js +5 -5
  8. package/dist/bin/agentic-reflection-backfill.js +6 -6
  9. package/dist/bin/agentic-semantic-label.js +5 -5
  10. package/dist/bin/backfill-conversations.js +4 -4
  11. package/dist/bin/backfill-responses.js +4 -4
  12. package/dist/bin/backfill-vectors.js +5 -5
  13. package/dist/bin/bulk-sync-postgres.js +6 -6
  14. package/dist/bin/cc-doctor.js +4 -4
  15. package/dist/bin/cleanup-stale-review-tasks.js +10 -10
  16. package/dist/bin/cli.js +16 -16
  17. package/dist/bin/exe-agent-config.js +3 -3
  18. package/dist/bin/exe-agent.js +4 -4
  19. package/dist/bin/exe-assign.js +5 -5
  20. package/dist/bin/exe-boot.js +17 -17
  21. package/dist/bin/exe-call.js +4 -4
  22. package/dist/bin/exe-cloud.js +4 -4
  23. package/dist/bin/exe-dispatch.js +10 -10
  24. package/dist/bin/exe-doctor.js +1 -1
  25. package/dist/bin/exe-export-behaviors.js +7 -7
  26. package/dist/bin/exe-forget.js +6 -6
  27. package/dist/bin/exe-gateway.js +7 -7
  28. package/dist/bin/exe-healthcheck.js +4 -4
  29. package/dist/bin/exe-heartbeat.js +10 -10
  30. package/dist/bin/exe-kill.js +13 -13
  31. package/dist/bin/exe-launch-agent.js +37 -19
  32. package/dist/bin/exe-new-employee.js +6 -6
  33. package/dist/bin/exe-pending-messages.js +11 -11
  34. package/dist/bin/exe-pending-notifications.js +10 -10
  35. package/dist/bin/exe-pending-reviews.js +10 -10
  36. package/dist/bin/exe-rename.js +4 -4
  37. package/dist/bin/exe-review.js +12 -12
  38. package/dist/bin/exe-search.js +5 -5
  39. package/dist/bin/exe-session-cleanup.js +15 -15
  40. package/dist/bin/exe-settings.js +5 -5
  41. package/dist/bin/exe-start-codex.js +11 -11
  42. package/dist/bin/exe-start-opencode.js +8 -8
  43. package/dist/bin/exe-status.js +11 -11
  44. package/dist/bin/exe-team.js +3 -3
  45. package/dist/bin/git-sweep.js +11 -11
  46. package/dist/bin/graph-backfill.js +4 -4
  47. package/dist/bin/graph-export.js +5 -5
  48. package/dist/bin/import-history.js +7 -7
  49. package/dist/bin/install.js +6 -6
  50. package/dist/bin/intercom-check.js +4 -4
  51. package/dist/bin/mcp-sessions.js +2 -2
  52. package/dist/bin/orchestration-metrics.js +4 -4
  53. package/dist/bin/postgres-agentic-reflection-backfill.js +2 -2
  54. package/dist/bin/postgres-agentic-semantic-backfill.js +1 -1
  55. package/dist/bin/scan-tasks.js +10 -10
  56. package/dist/bin/setup.js +1 -1
  57. package/dist/bin/shard-migrate.js +4 -4
  58. package/dist/bin/stack-update.js +10 -3
  59. package/dist/bin/vps-health-gate.js +1 -1
  60. package/dist/capacity-monitor-IFVRCIM7.js +49 -0
  61. package/dist/capacity-monitor-Q47GBDSY.js +49 -0
  62. package/dist/catchup-brief-RP4QHXNT.js +151 -0
  63. package/dist/catchup-brief-TKA6TEK4.js +151 -0
  64. package/dist/chunk-23KJ2LXY.js +58 -0
  65. package/dist/chunk-2NQQP3FF.js +630 -0
  66. package/dist/chunk-3FU5I3KV.js +526 -0
  67. package/dist/chunk-46IEEKPU.js +13696 -0
  68. package/dist/chunk-57UAFTO2.js +3958 -0
  69. package/dist/chunk-5AS622MM.js +3958 -0
  70. package/dist/chunk-62DEE65H.js +371 -0
  71. package/dist/chunk-64T6DFSS.js +447 -0
  72. package/dist/chunk-6BWDP63Z.js +197 -0
  73. package/dist/chunk-6GPYL7TX.js +214 -0
  74. package/dist/chunk-6KWLUVFL.js +54 -0
  75. package/dist/chunk-6N5ISWBF.js +1148 -0
  76. package/dist/chunk-6OD7PVMC.js +333 -0
  77. package/dist/chunk-7ET5CYTD.js +382 -0
  78. package/dist/chunk-7IWLKR6N.js +76 -0
  79. package/dist/chunk-7OEUOJL5.js +1021 -0
  80. package/dist/chunk-AIRJTKDK.js +204 -0
  81. package/dist/chunk-ATJ3NXDP.js +244 -0
  82. package/dist/chunk-B5IS7LE4.js +128 -0
  83. package/dist/chunk-BKINEQVI.js +244 -0
  84. package/dist/chunk-BOJV6NI3.js +128 -0
  85. package/dist/chunk-BPHWI6N2.js +284 -0
  86. package/dist/chunk-BXCQWWJP.js +185 -0
  87. package/dist/chunk-BZ6K7AY3.js +50 -0
  88. package/dist/chunk-C54KIFLS.js +214 -0
  89. package/dist/chunk-C6OYEJJI.js +260 -0
  90. package/dist/chunk-CHBHR5W6.js +3556 -0
  91. package/dist/chunk-D2T3272U.js +171 -0
  92. package/dist/chunk-DCHEIVGT.js +221 -0
  93. package/dist/chunk-DHIBLMSP.js +30 -0
  94. package/dist/chunk-E2AF2WYY.js +346 -0
  95. package/dist/chunk-E2KZEZZW.js +1090 -0
  96. package/dist/chunk-E4KWB4WM.js +348 -0
  97. package/dist/chunk-ENU7URWK.js +1073 -0
  98. package/dist/chunk-EZ7KAZMC.js +132 -0
  99. package/dist/chunk-F4FSSHR4.js +1073 -0
  100. package/dist/chunk-FPXU56FG.js +346 -0
  101. package/dist/chunk-FY7HHR5I.js +128 -0
  102. package/dist/chunk-G2S2UMU4.js +159 -0
  103. package/dist/chunk-G33BHQCO.js +70 -0
  104. package/dist/chunk-GJQTL7RX.js +127 -0
  105. package/dist/chunk-GLCKDEM2.js +97 -0
  106. package/dist/chunk-GMA34SXV.js +240 -0
  107. package/dist/chunk-GVAVEBYR.js +2091 -0
  108. package/dist/chunk-HOSJTLBQ.js +513 -0
  109. package/dist/chunk-IBMTSEZC.js +230 -0
  110. package/dist/chunk-IC6HVAS3.js +56 -0
  111. package/dist/chunk-IDFJNO44.js +1051 -0
  112. package/dist/chunk-ILFJMEY5.js +97 -0
  113. package/dist/chunk-ISQAOSL3.js +1921 -0
  114. package/dist/chunk-J6V2DCZK.js +382 -0
  115. package/dist/chunk-JP4CLFLR.js +1148 -0
  116. package/dist/chunk-JTIOZHWG.js +58 -0
  117. package/dist/chunk-KDICWAYV.js +1345 -0
  118. package/dist/chunk-KOBIB6WG.js +159 -0
  119. package/dist/chunk-KQFDDQB6.js +13696 -0
  120. package/dist/chunk-KZNSOHCB.js +280 -0
  121. package/dist/chunk-LVMBYP3C.js +171 -0
  122. package/dist/chunk-M2WQW5NC.js +227 -0
  123. package/dist/chunk-MY6SP5NZ.js +551 -0
  124. package/dist/chunk-N2ACW2ZG.js +363 -0
  125. package/dist/chunk-NSMJDATI.js +495 -0
  126. package/dist/chunk-NSQ5JE23.js +1090 -0
  127. package/dist/chunk-NZL567WG.js +81 -0
  128. package/dist/chunk-O5OMH6LI.js +244 -0
  129. package/dist/chunk-O7YO7E2G.js +1512 -0
  130. package/dist/chunk-OBUV3W7L.js +163 -0
  131. package/dist/chunk-OLDS7LJN.js +495 -0
  132. package/dist/chunk-OO2I22RX.js +38 -0
  133. package/dist/chunk-OPUUT33V.js +447 -0
  134. package/dist/chunk-OT3VMTKB.js +50 -0
  135. package/dist/chunk-P6RVIOVA.js +157 -0
  136. package/dist/chunk-PUA5564C.js +210 -0
  137. package/dist/chunk-PUQLKLQX.js +731 -0
  138. package/dist/chunk-QROKS65G.js +76 -0
  139. package/dist/chunk-R54I2N2T.js +818 -0
  140. package/dist/chunk-RCFYQHUP.js +818 -0
  141. package/dist/chunk-RJTND4YS.js +284 -0
  142. package/dist/chunk-SBLHQMMZ.js +81 -0
  143. package/dist/chunk-SG2ANG5C.js +123 -0
  144. package/dist/chunk-SVFNKSZV.js +333 -0
  145. package/dist/chunk-TAQT2DC7.js +330 -0
  146. package/dist/chunk-TB7HFW7M.js +127 -0
  147. package/dist/chunk-UUKDAIH2.js +731 -0
  148. package/dist/chunk-V6VEFEEH.js +1345 -0
  149. package/dist/chunk-VIO2ALGH.js +290 -0
  150. package/dist/chunk-VKCUSNJW.js +377 -0
  151. package/dist/chunk-VRPPJFIQ.js +1921 -0
  152. package/dist/chunk-WP3PVBBP.js +204 -0
  153. package/dist/chunk-WQEUY7DC.js +129 -0
  154. package/dist/chunk-WXMXUKCA.js +262 -0
  155. package/dist/chunk-X2WBH2IO.js +297 -0
  156. package/dist/chunk-X33TSJNO.js +394 -0
  157. package/dist/chunk-X7MMI2UI.js +89 -0
  158. package/dist/chunk-XG3BQZIK.js +85 -0
  159. package/dist/chunk-XIKBIAOS.js +75 -0
  160. package/dist/chunk-XPEB545Q.js +54 -0
  161. package/dist/chunk-XWH2MLWS.js +330 -0
  162. package/dist/chunk-YH7V73XW.js +89 -0
  163. package/dist/chunk-YMLM5D65.js +135 -0
  164. package/dist/chunk-YNJPRQ6J.js +377 -0
  165. package/dist/chunk-YSNEHBI6.js +551 -0
  166. package/dist/chunk-ZD6BMW2K.js +33 -0
  167. package/dist/chunk-ZKG5IYCG.js +668 -0
  168. package/dist/chunk-ZU4K7ZNX.js +197 -0
  169. package/dist/co-activation-HZMJC34P.js +72 -0
  170. package/dist/co-occurrence-AVYXRV4L.js +74 -0
  171. package/dist/core-memory-NPJCVUMF.js +110 -0
  172. package/dist/core-memory-OKGXL33Z.js +110 -0
  173. package/dist/crdt-sync-ZCH55JNR.js +33 -0
  174. package/dist/crm-webhook-6OMVUUGR.js +10 -0
  175. package/dist/crm-webhook-UCWF3XDB.js +10 -0
  176. package/dist/cto-delegation-gate-JFZFZGC2.js +206 -0
  177. package/dist/cto-delegation-gate-K32M4GVM.js +206 -0
  178. package/dist/daemon-orchestration-2Q7BYOHC.js +135 -0
  179. package/dist/daemon-orchestration-4RJ2CZJL.js +135 -0
  180. package/dist/db-backup-5GA2YFDX.js +33 -0
  181. package/dist/dreaming-I6KXO6E2.js +32 -0
  182. package/dist/dreaming-NJBK5ILR.js +32 -0
  183. package/dist/exe-drift-VSMIMHL4.js +68 -0
  184. package/dist/exe-export-DVHHIA6Y.js +73 -0
  185. package/dist/exe-export-GIVQDENS.js +73 -0
  186. package/dist/exe-import-7N46LSMQ.js +76 -0
  187. package/dist/exe-import-FINYUV5T.js +76 -0
  188. package/dist/exe-key-H45JY44F.js +579 -0
  189. package/dist/exe-key-MAEQGTB7.js +579 -0
  190. package/dist/exe-snapshot-3TEM3BFD.js +164 -0
  191. package/dist/exe-snapshot-HECGUHL3.js +164 -0
  192. package/dist/fast-db-init-3CNTADVO.js +7 -0
  193. package/dist/fast-db-init-HXCS2AP5.js +7 -0
  194. package/dist/gateway/index.js +8 -8
  195. package/dist/git-staleness-YCEBBIVK.js +110 -0
  196. package/dist/git-task-sweep-H34STRNT.js +40 -0
  197. package/dist/git-task-sweep-YL7NLDCK.js +40 -0
  198. package/dist/global-procedures-IHZM6C2K.js +20 -0
  199. package/dist/graph-auto-extract-RZQ3MHP2.js +162 -0
  200. package/dist/hooks/bug-report-worker.js +12 -12
  201. package/dist/hooks/codex-stop-task-finalizer.js +12 -12
  202. package/dist/hooks/commit-complete.js +12 -12
  203. package/dist/hooks/error-recall.js +6 -6
  204. package/dist/hooks/exe-heartbeat-hook.js +3 -3
  205. package/dist/hooks/ingest.js +6 -6
  206. package/dist/hooks/instructions-loaded.js +4 -4
  207. package/dist/hooks/manifest.json +19 -19
  208. package/dist/hooks/notification.js +4 -4
  209. package/dist/hooks/post-compact.js +11 -11
  210. package/dist/hooks/post-tool-combined.js +5 -5
  211. package/dist/hooks/pre-compact.js +12 -12
  212. package/dist/hooks/pre-tool-use.js +15 -15
  213. package/dist/hooks/prompt-submit.js +21 -21
  214. package/dist/hooks/session-end.js +16 -16
  215. package/dist/hooks/session-start.js +10 -10
  216. package/dist/hooks/stop.js +15 -15
  217. package/dist/hooks/subagent-stop.js +11 -11
  218. package/dist/hooks/summary-worker.js +15 -15
  219. package/dist/index.js +18 -18
  220. package/dist/installer-4EW5ZDGD.js +296 -0
  221. package/dist/installer-B2JTQO55.js +38 -0
  222. package/dist/installer-MIL352T7.js +342 -0
  223. package/dist/lib/agent-config.js +9 -3
  224. package/dist/lib/cloud-sync.js +4 -4
  225. package/dist/lib/consolidation.js +5 -5
  226. package/dist/lib/database.js +2 -2
  227. package/dist/lib/db.js +2 -2
  228. package/dist/lib/employee-templates.js +4 -4
  229. package/dist/lib/employees.js +2 -2
  230. package/dist/lib/exe-daemon.js +34 -34
  231. package/dist/lib/hybrid-search.js +5 -5
  232. package/dist/lib/identity.js +2 -2
  233. package/dist/lib/messaging.js +10 -10
  234. package/dist/lib/reminders.js +3 -3
  235. package/dist/lib/schedules.js +5 -5
  236. package/dist/lib/session-registry.js +4 -4
  237. package/dist/lib/skill-learning.js +4 -4
  238. package/dist/lib/store.js +4 -4
  239. package/dist/lib/task-router.js +3 -3
  240. package/dist/lib/tasks.js +11 -11
  241. package/dist/lib/tmux-routing.js +9 -9
  242. package/dist/lib/token-spend.js +3 -3
  243. package/dist/mcp/register-tools.js +54 -54
  244. package/dist/mcp/server.js +55 -55
  245. package/dist/mcp/tools/complete-reminder.js +4 -4
  246. package/dist/mcp/tools/create-reminder.js +4 -4
  247. package/dist/mcp/tools/create-task.js +13 -13
  248. package/dist/mcp/tools/deactivate-behavior.js +5 -5
  249. package/dist/mcp/tools/list-reminders.js +4 -4
  250. package/dist/mcp/tools/list-tasks.js +13 -13
  251. package/dist/mcp/tools/send-message.js +12 -12
  252. package/dist/mcp/tools/update-task.js +12 -12
  253. package/dist/mcp-http-config-OJQR246S.js +27 -0
  254. package/dist/memory-cards-IPULSQFA.js +174 -0
  255. package/dist/memory-graph-extractor-3TZZOKHY.js +17 -0
  256. package/dist/memory-poisoning-defense-SGUGR5YJ.js +225 -0
  257. package/dist/memory-reflection-H3WGCEM6.js +238 -0
  258. package/dist/notifications-VWPO6NJF.js +45 -0
  259. package/dist/notifications-WCSRQN2V.js +45 -0
  260. package/dist/orchestration-events-O5PSDEIO.js +25 -0
  261. package/dist/orchestrator-RAPEJUOI.js +33 -0
  262. package/dist/orchestrator-XPG6LJAI.js +33 -0
  263. package/dist/pipeline-router-5NT6FUC3.js +13 -0
  264. package/dist/pipeline-router-KSUXONDT.js +13 -0
  265. package/dist/plan-limits-53NXLNDQ.js +26 -0
  266. package/dist/project-boot-ITN3FZMM.js +299 -0
  267. package/dist/projection-worker-27XX5M2W.js +964 -0
  268. package/dist/reranker-GU7L2PJX.js +19 -0
  269. package/dist/reranker-TZEXIJAN.js +19 -0
  270. package/dist/review-polling-FA2J2Q5O.js +124 -0
  271. package/dist/review-polling-MLS4BQ3N.js +124 -0
  272. package/dist/runtime/index.js +12 -12
  273. package/dist/session-events-WWGF3B2N.js +36 -0
  274. package/dist/session-events-ZHXXAH6B.js +36 -0
  275. package/dist/session-kill-telemetry-O4TJHHOZ.js +29 -0
  276. package/dist/session-scope-CQXB7VMH.js +86 -0
  277. package/dist/session-scope-HHUMJYF6.js +86 -0
  278. package/dist/setup-wizard-UM2RHSBJ.js +12 -0
  279. package/dist/skill-refinement-MJPOHYD5.js +157 -0
  280. package/dist/skill-refinement-NVUBRK22.js +157 -0
  281. package/dist/stack-release-2KSOYDIV.js +712 -0
  282. package/dist/stack-release-BAPCXMXW.js +713 -0
  283. package/dist/stack-release-W4TWTEZP.js +731 -0
  284. package/dist/stack-update-QQA64STQ.js +52 -0
  285. package/dist/steward-gate-VLE7OCKO.js +13 -0
  286. package/dist/task-enforcement-FUHDL6UR.js +391 -0
  287. package/dist/task-enforcement-QL3K4N3F.js +391 -0
  288. package/dist/task-scope-TZYMB634.js +35 -0
  289. package/dist/task-scope-ZVLUBS4C.js +35 -0
  290. package/dist/tasks-crud-4MSLJWXE.js +77 -0
  291. package/dist/tasks-crud-HIPXKRKX.js +77 -0
  292. package/dist/tasks-notify-7JBUNE7R.js +38 -0
  293. package/dist/tasks-notify-UPIJ3L4O.js +38 -0
  294. package/dist/tasks-review-5SJSFTUB.js +47 -0
  295. package/dist/tasks-review-JHSYBR5I.js +47 -0
  296. package/dist/telemetry-upload-BSGOXGUP.js +739 -0
  297. package/dist/telemetry-upload-LTX3C5HZ.js +739 -0
  298. package/dist/token-budget-2CDWQU3Q.js +84 -0
  299. package/dist/tool-telemetry-7YS7EN7B.js +17 -0
  300. package/dist/tui/App.js +17 -17
  301. package/dist/tui-data-GDGBOS6G.js +258 -0
  302. package/dist/tui-data-VXF2RBVM.js +258 -0
  303. package/dist/wiki-acl-MJIMXRQV.js +111 -0
  304. package/dist/worker-gate-WQGTZOSM.js +21 -0
  305. package/dist/worker-gate-X2YDTKTL.js +21 -0
  306. package/dist/workflow-engine-CYXRZXBM.js +28 -0
  307. package/dist/workflow-engine-KMLAXVA4.js +28 -0
  308. package/dist/worktree-NLSKVRNC.js +26 -0
  309. package/dist/worktree-sweep-44TMEPLE.js +19 -0
  310. package/package.json +1 -1
  311. package/release-notes.json +26 -40
@@ -0,0 +1,1148 @@
1
+ import {
2
+ attachDocumentMetadata,
3
+ buildRawVisibilityFilter,
4
+ buildWikiScopeFilter,
5
+ searchMemories
6
+ } from "./chunk-RCFYQHUP.js";
7
+ import {
8
+ getClient
9
+ } from "./chunk-CHBHR5W6.js";
10
+
11
+ // src/lib/hybrid-search.ts
12
+ var RRF_K = 60;
13
+ var DAEMON_SAFE_FTS_TERM_THRESHOLD = 3;
14
+ var DAEMON_SAFE_FTS_MAX_TERMS = 5;
15
+ var _daemonBroadFtsSkipLogged = false;
16
+ var _daemonGraphFtsSkipLogged = false;
17
+ function isDaemonProcess() {
18
+ return process.env.EXE_IS_DAEMON === "1";
19
+ }
20
+ function daemonSafeFtsTerms(terms) {
21
+ return isDaemonProcess() ? terms.slice(0, DAEMON_SAFE_FTS_MAX_TERMS) : terms;
22
+ }
23
+ function shouldUseFtsPrefix(terms) {
24
+ return !(isDaemonProcess() && terms.length >= DAEMON_SAFE_FTS_TERM_THRESHOLD);
25
+ }
26
+ function ftsTerm(term, usePrefix) {
27
+ return usePrefix ? `${term}*` : term;
28
+ }
29
+ function logDaemonBroadFtsSkipOnce(terms) {
30
+ if (_daemonBroadFtsSkipLogged || process.env.VITEST) return;
31
+ _daemonBroadFtsSkipLogged = true;
32
+ process.stderr.write(
33
+ `[hybrid-search] Daemon-safe FTS: skipped broad OR fallback for ${terms.length} terms to keep MCP responsive.
34
+ `
35
+ );
36
+ }
37
+ function logDaemonGraphFtsSkipOnce(terms) {
38
+ if (_daemonGraphFtsSkipLogged || process.env.VITEST) return;
39
+ _daemonGraphFtsSkipLogged = true;
40
+ process.stderr.write(
41
+ `[hybrid-search] Daemon-safe FTS: skipped graph/entity FTS for ${terms.length} terms to keep MCP responsive.
42
+ `
43
+ );
44
+ }
45
+ var _cardinalityCache = /* @__PURE__ */ new Map();
46
+ var CARDINALITY_TTL_MS = 6e4;
47
+ setInterval(() => {
48
+ const now = Date.now();
49
+ for (const [key, entry] of _cardinalityCache) {
50
+ if (now > entry.expires) _cardinalityCache.delete(key);
51
+ }
52
+ }, 5 * 60 * 1e3).unref();
53
+ async function getCachedCardinality(agentId) {
54
+ if (process.env.VITEST === "true" || process.env.NODE_ENV === "test") {
55
+ const { getMemoryCardinality: getMemoryCardinality2 } = await import("./lib/store.js");
56
+ return getMemoryCardinality2(agentId);
57
+ }
58
+ const cached = _cardinalityCache.get(agentId);
59
+ if (cached && Date.now() < cached.expires) return cached.count;
60
+ const { getMemoryCardinality } = await import("./lib/store.js");
61
+ const count = await getMemoryCardinality(agentId);
62
+ _cardinalityCache.set(agentId, { count, expires: Date.now() + CARDINALITY_TTL_MS });
63
+ return count;
64
+ }
65
+ var ABSTENTION_THRESHOLD = parseFloat(
66
+ process.env.EXE_ABSTENTION_THRESHOLD ?? "0.015"
67
+ );
68
+ var CONTRADICTION_TEMPORAL_BOOST = 1.5;
69
+ function buildTemporalFilter(options, columnPrefix) {
70
+ const asOf = options?.asOf;
71
+ if (asOf) {
72
+ return {
73
+ clause: ` AND (${columnPrefix}valid_from IS NULL OR ${columnPrefix}valid_from <= ?) AND (${columnPrefix}invalid_at IS NULL OR ${columnPrefix}invalid_at > ?)`,
74
+ args: [asOf, asOf]
75
+ };
76
+ }
77
+ return {
78
+ clause: ` AND ${columnPrefix}invalid_at IS NULL`,
79
+ args: []
80
+ };
81
+ }
82
+ function appendMemoryTypeFilter(sql, args, column, options) {
83
+ if (options?.memoryTypes && options.memoryTypes.length > 0) {
84
+ const uniqueTypes = [...new Set(options.memoryTypes)];
85
+ sql += ` AND ${column} IN (${uniqueTypes.map(() => "?").join(",")})`;
86
+ args.push(...uniqueTypes);
87
+ } else if (options?.memoryType) {
88
+ sql += ` AND ${column} = ?`;
89
+ args.push(options.memoryType);
90
+ }
91
+ return sql;
92
+ }
93
+ async function graphSearch(query, agentId, _options, limit) {
94
+ const client = getClient();
95
+ const queryWords = query.toLowerCase().split(/\s+/).filter((w) => w.length >= 3).map((w) => w.replace(/[^a-z0-9_-]/g, "")).filter((w) => w.length >= 3);
96
+ if (queryWords.length === 0) return [];
97
+ if (isDaemonProcess() && queryWords.length >= DAEMON_SAFE_FTS_TERM_THRESHOLD) {
98
+ logDaemonGraphFtsSkipOnce(queryWords);
99
+ return [];
100
+ }
101
+ let entityIds = [];
102
+ try {
103
+ const safeWords = daemonSafeFtsTerms(queryWords);
104
+ const usePrefix = shouldUseFtsPrefix(safeWords);
105
+ const matchExpr = safeWords.map((w) => ftsTerm(w, usePrefix)).join(" OR ");
106
+ const ftsResult = await client.execute({
107
+ sql: `SELECT e.id FROM entities e
108
+ JOIN entities_fts fts ON e.rowid = fts.rowid
109
+ WHERE entities_fts MATCH ?
110
+ ORDER BY rank LIMIT 10`,
111
+ args: [matchExpr]
112
+ });
113
+ entityIds = ftsResult.rows.map((r) => String(r.id));
114
+ } catch {
115
+ try {
116
+ const conditions = queryWords.map(() => `LOWER(name) LIKE ?`);
117
+ const args = queryWords.map((w) => `%${w}%`);
118
+ const likeResult = await client.execute({
119
+ sql: `SELECT id FROM entities WHERE ${conditions.join(" OR ")} LIMIT 10`,
120
+ args: [...args]
121
+ });
122
+ entityIds = likeResult.rows.map((r) => String(r.id));
123
+ } catch {
124
+ return [];
125
+ }
126
+ }
127
+ if (entityIds.length === 0) return [];
128
+ const allEntityIds = new Set(entityIds);
129
+ try {
130
+ const placeholders2 = entityIds.map(() => "?").join(",");
131
+ const neighborResult = await client.execute({
132
+ sql: `SELECT DISTINCT target_entity_id FROM relationships
133
+ WHERE source_entity_id IN (${placeholders2})
134
+ UNION
135
+ SELECT DISTINCT source_entity_id FROM relationships
136
+ WHERE target_entity_id IN (${placeholders2})
137
+ LIMIT 30`,
138
+ args: [...entityIds, ...entityIds]
139
+ });
140
+ for (const row of neighborResult.rows) {
141
+ allEntityIds.add(String(row.target_entity_id ?? row.source_entity_id));
142
+ }
143
+ } catch {
144
+ }
145
+ const entityIdArr = Array.from(allEntityIds);
146
+ const placeholders = entityIdArr.map(() => "?").join(",");
147
+ try {
148
+ const memResult = await client.execute({
149
+ sql: `SELECT DISTINCT m.id, m.agent_id, m.agent_role, m.session_id, m.timestamp,
150
+ m.tool_name, m.project_name, m.has_error, m.raw_text, m.vector,
151
+ m.task_id, m.importance, m.status, m.confidence, m.last_accessed,
152
+ m.workspace_id, m.document_id, m.user_id, m.char_offset,
153
+ m.page_number, m.source_path, m.source_type, m.memory_type, m.strength
154
+ FROM memories m
155
+ JOIN entity_memories em ON m.id = em.memory_id
156
+ WHERE em.entity_id IN (${placeholders})
157
+ AND (m.agent_id = ? OR m.agent_id = 'wiki')
158
+ AND COALESCE(m.status, 'active') = 'active'
159
+ AND COALESCE(m.confidence, 0.7) >= 0.3
160
+ ORDER BY m.importance DESC, m.timestamp DESC
161
+ LIMIT ?`,
162
+ args: [...entityIdArr, agentId, limit]
163
+ });
164
+ return memResult.rows.map((row) => rowToMemoryRecord(row));
165
+ } catch {
166
+ return [];
167
+ }
168
+ }
169
+ function extractEntitySubqueries(query) {
170
+ const subqueries = [];
171
+ const quoted = query.match(/"([^"]+)"/g);
172
+ if (quoted) {
173
+ for (const q of quoted) {
174
+ subqueries.push(q.replace(/"/g, ""));
175
+ }
176
+ }
177
+ const words = query.split(/\s+/);
178
+ const properNouns = [];
179
+ for (let i = 1; i < words.length; i++) {
180
+ const word = words[i].replace(/[^a-zA-Z]/g, "");
181
+ if (word.length >= 2 && /^[A-Z]/.test(word) && !/^(What|When|Where|Who|How|Why|Which|Does|Did|Is|Are|Was|Were|Has|Have|Had|Can|Could|Would|Should|Do|The|And|But|For|Not|You|Your|His|Her|Its|Our|Their|This|That|These|Those)$/.test(word)) {
182
+ properNouns.push(word);
183
+ }
184
+ }
185
+ if (properNouns.length > 0) {
186
+ subqueries.push(properNouns.join(" "));
187
+ }
188
+ const prepPatterns = /(?:about|regarding|concerning|towards?|with|for|against)\s+(.+?)(?:\?|$|,|\band\b)/gi;
189
+ let match;
190
+ while ((match = prepPatterns.exec(query)) !== null) {
191
+ const phrase = match[1].trim();
192
+ if (phrase.length >= 3 && phrase.split(/\s+/).length <= 5) {
193
+ subqueries.push(phrase);
194
+ }
195
+ }
196
+ return [...new Set(subqueries)].slice(0, 3);
197
+ }
198
+ function resolveContradictions(results) {
199
+ if (results.length < 2) return results;
200
+ const entityGroups = /* @__PURE__ */ new Map();
201
+ for (const r of results) {
202
+ const words = (r.raw_text ?? "").toLowerCase().replace(/[^a-z0-9\s]/g, "").split(/\s+/).filter((w) => w.length >= 4).slice(0, 3);
203
+ if (words.length < 2) continue;
204
+ const key = words.join("|");
205
+ for (const [existingKey, group] of entityGroups) {
206
+ const existingWords = new Set(existingKey.split("|"));
207
+ const overlapCount = words.filter((w) => existingWords.has(w)).length;
208
+ if (overlapCount >= 2) {
209
+ group.push(r);
210
+ entityGroups.set(existingKey, group);
211
+ break;
212
+ }
213
+ }
214
+ const existing = entityGroups.get(key) ?? [];
215
+ existing.push(r);
216
+ entityGroups.set(key, existing);
217
+ }
218
+ const temporalBoosts = /* @__PURE__ */ new Map();
219
+ for (const [, group] of entityGroups) {
220
+ if (group.length < 2) continue;
221
+ const sorted = [...group].sort(
222
+ (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
223
+ );
224
+ for (let i = 0; i < sorted.length; i++) {
225
+ const id = sorted[i].id;
226
+ const boost = i === 0 ? CONTRADICTION_TEMPORAL_BOOST : 1 / (1 + i * 0.3);
227
+ temporalBoosts.set(id, Math.max(temporalBoosts.get(id) ?? 0, boost));
228
+ }
229
+ }
230
+ if (temporalBoosts.size === 0) return results;
231
+ const scored = results.map((r, i) => {
232
+ const baseScore = 1 / (1 + i * 0.1);
233
+ const contradiction = temporalBoosts.get(r.id) ?? 1;
234
+ return { record: r, score: baseScore * contradiction };
235
+ });
236
+ scored.sort((a, b) => b.score - a.score);
237
+ return scored.map((s) => s.record);
238
+ }
239
+ async function hybridSearch(queryText, agentId, options) {
240
+ const { loadConfig } = await import("./lib/config.js");
241
+ const config = await loadConfig();
242
+ const searchStartMs = Date.now();
243
+ if (config.searchMode === "fts") {
244
+ return lightweightSearch(queryText, agentId, options);
245
+ }
246
+ const limit = options?.limit ?? 10;
247
+ const trajectoryResults = await trajectoryBypass(queryText, agentId, options, limit);
248
+ if (trajectoryResults !== null) return trajectoryResults;
249
+ let effectiveQuery = queryText;
250
+ const effectiveOptions = { ...options };
251
+ let _isBroadQuery = false;
252
+ let inferredTerms = [];
253
+ if (config.selfQueryRouter) {
254
+ try {
255
+ const { routeQuery } = await import("./self-query-router-PYVVFXJT.js");
256
+ const routed = await routeQuery(queryText, config.selfQueryModel, agentId);
257
+ effectiveQuery = routed.semanticQuery;
258
+ _isBroadQuery = routed.isBroadQuery;
259
+ inferredTerms = routed.inferredTerms ?? [];
260
+ if (routed.projectFilter && !effectiveOptions.projectName) {
261
+ effectiveOptions.projectName = routed.projectFilter;
262
+ }
263
+ if (routed.timeFilter && !effectiveOptions.since) {
264
+ effectiveOptions.since = routed.timeFilter;
265
+ }
266
+ if (routed.roleFilter) {
267
+ inferredTerms.push(routed.roleFilter.toLowerCase());
268
+ }
269
+ } catch (err) {
270
+ if (!process.env.VITEST) {
271
+ process.stderr.write(`[hybrid-search] Self-query router failed: ${err instanceof Error ? err.message : String(err)}
272
+ `);
273
+ }
274
+ }
275
+ }
276
+ const cardinality = await getCachedCardinality(agentId);
277
+ const { rerankerAutoTrigger } = config.scalingRoadmap ?? {};
278
+ const minCardForBroad = rerankerAutoTrigger?.broadQueryMinCardinality ?? 5e4;
279
+ const useNarrowPath = cardinality < 1e4;
280
+ const useBroadPath = cardinality > minCardForBroad || _isBroadQuery && cardinality >= 1e4;
281
+ const effectiveIsBroad = useBroadPath && !useNarrowPath;
282
+ if (effectiveIsBroad !== _isBroadQuery) {
283
+ process.stderr.write(
284
+ `[hybrid-search] Adaptive routing override: cardinality=${cardinality}, router=${_isBroadQuery ? "broad" : "narrow"} \u2192 ${effectiveIsBroad ? "broad" : "narrow"}
285
+ `
286
+ );
287
+ }
288
+ let rerankerAvailable = false;
289
+ if (process.env.EXE_IS_DAEMON === "1") {
290
+ try {
291
+ const { isRerankerAvailable } = await import("./reranker-TZEXIJAN.js");
292
+ rerankerAvailable = isRerankerAvailable();
293
+ } catch {
294
+ }
295
+ }
296
+ const broadFetchTopK = config.scalingRoadmap?.rerankerAutoTrigger?.fetchTopK ?? 150;
297
+ const fetchLimit = effectiveIsBroad ? Math.max(limit * 5, broadFetchTopK) : rerankerAvailable ? Math.max(limit * 4, 60) : Math.max(limit * 3, 30);
298
+ const fetchOptions = { ...effectiveOptions, limit: fetchLimit, includeSource: false };
299
+ let queryVector = null;
300
+ try {
301
+ const { embed } = await import("./lib/embedder.js");
302
+ queryVector = await embed(effectiveQuery);
303
+ } catch {
304
+ if (!process.env.VITEST) {
305
+ process.stderr.write("[hybrid-search] Embed daemon unavailable \u2014 FTS-only mode\n");
306
+ }
307
+ }
308
+ let grepPromise = Promise.resolve([]);
309
+ if (config.fileGrepEnabled === true && !process.env.VITEST) {
310
+ try {
311
+ if (process.env.EXE_IS_DAEMON !== "1") {
312
+ const { getProjectName } = await import("./project-name-EWG5KAZP.js");
313
+ const projectRoot = process.cwd();
314
+ const projectName = getProjectName(projectRoot);
315
+ if (projectName && projectName !== "tmp") {
316
+ const { grepProjectFiles } = await import("./lib/file-grep.js");
317
+ grepPromise = grepProjectFiles(effectiveQuery, projectRoot, {
318
+ maxResults: 10
319
+ }).catch(() => []);
320
+ }
321
+ }
322
+ } catch {
323
+ }
324
+ }
325
+ const entitySubqueries = extractEntitySubqueries(effectiveQuery);
326
+ if (inferredTerms.length > 0) {
327
+ entitySubqueries.push(...inferredTerms.filter(
328
+ (t) => !entitySubqueries.some((sq) => sq.toLowerCase() === t.toLowerCase())
329
+ ));
330
+ }
331
+ const subqueryPromises = entitySubqueries.map(
332
+ (sq) => lightweightSearch(sq, agentId, { ...fetchOptions, limit: Math.min(fetchLimit, 20) }).catch(() => [])
333
+ );
334
+ const includeStructuredCards = effectiveIsBroad || effectiveOptions.includeStructuredCards === true;
335
+ const [ftsResults, vectorResults, graphResults, cardResults, reflectionResults, grepResults, ...subqueryResults] = await Promise.all([
336
+ lightweightSearch(effectiveQuery, agentId, fetchOptions),
337
+ queryVector ? searchMemories(queryVector, agentId, fetchOptions) : Promise.resolve([]),
338
+ // Graph search: first-class parallel signal via entity → memory linkage.
339
+ // Non-blocking with 2s timeout — graph is a bonus, not a requirement.
340
+ Promise.race([
341
+ graphSearch(effectiveQuery, agentId, fetchOptions, Math.min(fetchLimit, 20)),
342
+ new Promise((resolve) => setTimeout(() => resolve([]), 2e3))
343
+ ]).catch(() => []),
344
+ includeStructuredCards ? (async () => {
345
+ try {
346
+ const { searchMemoryCards } = await import("./memory-cards-IPULSQFA.js");
347
+ return await searchMemoryCards(effectiveQuery, agentId, fetchOptions);
348
+ } catch {
349
+ return [];
350
+ }
351
+ })() : Promise.resolve([]),
352
+ // Reflection insights: patterns, contradictions, summaries across sessions
353
+ includeStructuredCards ? (async () => {
354
+ try {
355
+ const { searchReflections } = await import("./memory-reflection-H3WGCEM6.js");
356
+ const insights = await searchReflections(effectiveQuery, agentId, 5);
357
+ return insights.map((ins) => ({
358
+ id: ins.id,
359
+ agent_id: ins.agent_id,
360
+ raw_text: `[${ins.insight_type}] ${ins.content}`,
361
+ timestamp: ins.created_at,
362
+ session_id: "reflection",
363
+ importance: Math.round(ins.confidence * 10),
364
+ confidence: ins.confidence
365
+ }));
366
+ } catch {
367
+ return [];
368
+ }
369
+ })() : Promise.resolve([]),
370
+ grepPromise,
371
+ ...subqueryPromises
372
+ ]);
373
+ for (const r of ftsResults) {
374
+ r._source = "fts";
375
+ }
376
+ for (const r of vectorResults) {
377
+ r._source = "embed";
378
+ }
379
+ for (const r of graphResults) {
380
+ r._source = "graph";
381
+ }
382
+ for (const r of cardResults) {
383
+ r._source = "card";
384
+ }
385
+ for (const r of reflectionResults) {
386
+ r._source = "reflection";
387
+ }
388
+ for (const r of grepResults) {
389
+ r._source = "grep";
390
+ }
391
+ const lists = [];
392
+ const weights = [];
393
+ if (ftsResults.length > 0) {
394
+ lists.push(ftsResults);
395
+ weights.push(1);
396
+ }
397
+ if (vectorResults.length > 0) {
398
+ lists.push(vectorResults);
399
+ weights.push(1);
400
+ }
401
+ if (graphResults.length > 0) {
402
+ lists.push(graphResults);
403
+ weights.push(0.9);
404
+ }
405
+ if (reflectionResults.length > 0) {
406
+ lists.push(reflectionResults);
407
+ weights.push(0.65);
408
+ }
409
+ if (cardResults.length > 0) {
410
+ lists.push(cardResults);
411
+ weights.push(0.85);
412
+ }
413
+ if (grepResults.length > 0) {
414
+ lists.push(grepResults);
415
+ weights.push(0.5);
416
+ }
417
+ for (const sqResult of subqueryResults) {
418
+ if (sqResult.length > 0) {
419
+ lists.push(sqResult);
420
+ weights.push(0.7);
421
+ }
422
+ }
423
+ if (lists.length === 0) return [];
424
+ if (lists.length === 1 && !effectiveIsBroad) return lists[0].slice(0, limit);
425
+ const rrfLimit = effectiveIsBroad ? Math.max(limit * 5, broadFetchTopK) : limit;
426
+ let merged = lists.length === 1 ? lists[0].slice(0, rrfLimit) : rrfMergeMulti(lists, rrfLimit, RRF_K, weights);
427
+ let graphContextMap = /* @__PURE__ */ new Map();
428
+ let entityBoostRan = false;
429
+ if (merged.length > 0) {
430
+ try {
431
+ const { applyEntityBoost } = await import("./entity-boost-BEVW2KFT.js");
432
+ const boosted = await applyEntityBoost(merged, effectiveQuery, getClient());
433
+ merged = boosted.results;
434
+ graphContextMap = boosted.graphContext;
435
+ entityBoostRan = true;
436
+ } catch {
437
+ }
438
+ }
439
+ if (merged.length >= 2) {
440
+ merged = resolveContradictions(merged);
441
+ }
442
+ const auto = config.scalingRoadmap?.rerankerAutoTrigger ?? {
443
+ enabled: config.rerankerEnabled ?? true,
444
+ broadQueryMinCardinality: 5e4,
445
+ fetchTopK: 150,
446
+ returnTopK: 5
447
+ };
448
+ let rerankedAndBlended = null;
449
+ const rerankReturnLimit = Math.max(limit, auto.returnTopK ?? 5);
450
+ const shouldRerank = auto.enabled && rerankerAvailable && merged.length >= limit * 2 && (effectiveIsBroad || lists.length >= 2);
451
+ if (shouldRerank) {
452
+ try {
453
+ let rerankedRecords;
454
+ if (graphContextMap.size > 0) {
455
+ const { rerankWithContext } = await import("./reranker-TZEXIJAN.js");
456
+ const candidates = merged.map((m) => ({
457
+ text: m.raw_text,
458
+ context: graphContextMap.get(m.id)
459
+ }));
460
+ const scored = await rerankWithContext(effectiveQuery, candidates, rerankReturnLimit);
461
+ rerankedRecords = scored.map((s) => merged[s.index]);
462
+ } else {
463
+ const { rerank } = await import("./reranker-TZEXIJAN.js");
464
+ rerankedRecords = await rerank(effectiveQuery, merged, rerankReturnLimit);
465
+ }
466
+ if (rerankedRecords.length > 0) {
467
+ rerankedAndBlended = rrfMergeMulti(
468
+ [rerankedRecords],
469
+ rerankReturnLimit,
470
+ RRF_K
471
+ );
472
+ }
473
+ } catch {
474
+ }
475
+ }
476
+ const finalResults = (rerankedAndBlended ?? merged).slice(0, limit);
477
+ if (finalResults.length > 0) {
478
+ const topResult = finalResults[0];
479
+ const signalCount = lists.length;
480
+ const resultRatio = Math.min(1, finalResults.length / limit);
481
+ const retrievalConfidence = resultRatio * (signalCount >= 2 ? 1 : 0.7);
482
+ topResult._retrievalConfidence = retrievalConfidence;
483
+ if (retrievalConfidence < ABSTENTION_THRESHOLD) {
484
+ for (const r of finalResults) {
485
+ r._lowConfidence = true;
486
+ }
487
+ }
488
+ }
489
+ if (options?.includeSource && finalResults.length > 0) {
490
+ await attachDocumentMetadata(finalResults);
491
+ }
492
+ if (process.env.EXE_SEARCH_LOG !== "0") {
493
+ const logEntry = {
494
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
495
+ query: queryText,
496
+ agentId,
497
+ signals: {
498
+ fts: ftsResults.length,
499
+ vector: vectorResults.length,
500
+ graph: graphResults.length,
501
+ cards: cardResults.length,
502
+ reflections: reflectionResults.length,
503
+ grep: grepResults.length,
504
+ entitySubqueries: subqueryResults.filter((r) => r.length > 0).length,
505
+ entityBoost: entityBoostRan,
506
+ contradictionResolution: merged.length >= 2,
507
+ reranker: rerankedAndBlended !== null,
508
+ selfQueryRouter: effectiveQuery !== queryText,
509
+ inferredTerms: inferredTerms.length > 0 ? inferredTerms : void 0,
510
+ lowConfidence: finalResults[0]?._lowConfidence ?? false
511
+ },
512
+ topResults: finalResults.slice(0, 10).map((r, i) => {
513
+ const scored = r;
514
+ return {
515
+ rank: i + 1,
516
+ id: r.id.slice(0, 8),
517
+ tool: r.tool_name,
518
+ score: scored.distance ?? null,
519
+ age_hours: Math.round((Date.now() - new Date(r.timestamp).getTime()) / 36e5)
520
+ };
521
+ }),
522
+ latencyMs: Date.now() - searchStartMs
523
+ };
524
+ try {
525
+ const fs = await import("fs");
526
+ const path = await import("path");
527
+ const os = await import("os");
528
+ const logPath = path.join(os.homedir(), ".exe-os", "search-quality.jsonl");
529
+ fs.mkdirSync(path.dirname(logPath), { recursive: true });
530
+ const MAX_LOG_BYTES = 5 * 1024 * 1024;
531
+ try {
532
+ const stat = fs.statSync(logPath);
533
+ if (stat.size > MAX_LOG_BYTES) {
534
+ fs.renameSync(logPath, logPath + ".1");
535
+ }
536
+ } catch {
537
+ }
538
+ try {
539
+ const backupPath = logPath + ".1";
540
+ const bstat = fs.statSync(backupPath);
541
+ if (Date.now() - bstat.mtimeMs > 30 * 24 * 60 * 60 * 1e3) {
542
+ fs.unlinkSync(backupPath);
543
+ }
544
+ } catch {
545
+ }
546
+ fs.appendFileSync(logPath, JSON.stringify(logEntry) + "\n");
547
+ } catch {
548
+ }
549
+ }
550
+ if (finalResults.length > 0) {
551
+ const now = (/* @__PURE__ */ new Date()).toISOString();
552
+ const ids = finalResults.map((r) => r.id);
553
+ const placeholders = ids.map(() => "?").join(",");
554
+ try {
555
+ const client = getClient();
556
+ void client.execute({
557
+ sql: `UPDATE memories SET last_accessed = ?, retrieval_count = COALESCE(retrieval_count, 0) + 1, strength = MIN(1.0, COALESCE(strength, 1.0) + 0.1) WHERE id IN (${placeholders})`,
558
+ args: [now, ...ids]
559
+ }).catch(() => {
560
+ });
561
+ } catch {
562
+ }
563
+ }
564
+ return finalResults;
565
+ }
566
+ async function estimateCardinality(agentId, options) {
567
+ const client = getClient();
568
+ let sql = `SELECT COUNT(*) as cnt FROM memories
569
+ WHERE (agent_id = ? OR agent_id = 'wiki')
570
+ AND COALESCE(status, 'active') = 'active'
571
+ AND COALESCE(confidence, 0.7) >= 0.3`;
572
+ const args = [agentId];
573
+ const temporal = buildTemporalFilter(options, "");
574
+ sql += temporal.clause;
575
+ args.push(...temporal.args);
576
+ const rawVisibility = buildRawVisibilityFilter(options, "");
577
+ sql += rawVisibility.clause;
578
+ args.push(...rawVisibility.args);
579
+ if (options?.projectName) {
580
+ sql += ` AND project_name = ?`;
581
+ args.push(options.projectName);
582
+ }
583
+ if (options?.sessionScope) {
584
+ sql += ` AND (session_scope = ? OR session_scope IS NULL)`;
585
+ args.push(options.sessionScope);
586
+ }
587
+ if (options?.toolName) {
588
+ sql += ` AND tool_name = ?`;
589
+ args.push(options.toolName);
590
+ }
591
+ if (options?.hasError !== void 0) {
592
+ sql += ` AND has_error = ?`;
593
+ args.push(options.hasError ? 1 : 0);
594
+ }
595
+ if (options?.since) {
596
+ sql += ` AND timestamp >= ?`;
597
+ args.push(options.since);
598
+ }
599
+ sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
600
+ try {
601
+ const result = await client.execute({ sql, args });
602
+ return Number(result.rows[0]?.cnt) || 0;
603
+ } catch {
604
+ return 0;
605
+ }
606
+ }
607
+ function rrfMerge(listA, listB, limit, k = RRF_K) {
608
+ return rrfMergeMulti([listA, listB], limit, k);
609
+ }
610
+ function recencyScore(timestamp) {
611
+ const daysSince = (Date.now() - new Date(timestamp).getTime()) / (1e3 * 60 * 60 * 24);
612
+ return 1 / (1 + daysSince * 0.01);
613
+ }
614
+ function normalizedImportance(importance) {
615
+ return ((importance ?? 5) - 1) / 9;
616
+ }
617
+ function frecencyBoost(lastAccessed, timestamp) {
618
+ const accessTime = lastAccessed ? new Date(lastAccessed).getTime() : new Date(timestamp).getTime();
619
+ const hoursSince = Math.max(0, (Date.now() - accessTime) / (1e3 * 60 * 60));
620
+ return Math.exp(-0.01 * hoursSince);
621
+ }
622
+ function sourceConfidence(record) {
623
+ const tool = record.tool_name?.toLowerCase() ?? "";
624
+ if (tool === "manual" || tool === "store_memory") return 0.95;
625
+ if (tool === "auto-summary" || tool === "consolidation") return 0.9;
626
+ if (tool === "userprompt" || tool === "assistantresponse") return 0.75;
627
+ if (tool === "bash" || tool === "write" || tool === "edit") return 0.6;
628
+ if (tool === "file_grep" || tool === "file_read") return 0.5;
629
+ return record.confidence ?? 0.5;
630
+ }
631
+ function rrfMergeMulti(lists, limit, k = RRF_K, weights) {
632
+ const scores = /* @__PURE__ */ new Map();
633
+ for (let listIdx = 0; listIdx < lists.length; listIdx++) {
634
+ const list = lists[listIdx];
635
+ const weight = weights?.[listIdx] ?? 1;
636
+ for (let i = 0; i < list.length; i++) {
637
+ const rec = list[i];
638
+ const entry = scores.get(rec.id) ?? { rrfScore: 0, record: rec, sources: /* @__PURE__ */ new Set() };
639
+ entry.rrfScore += weight * (1 / (k + i + 1));
640
+ if (rec._source) entry.sources.add(rec._source);
641
+ scores.set(rec.id, entry);
642
+ }
643
+ }
644
+ for (const entry of scores.values()) {
645
+ if (entry.sources.size > 0) {
646
+ entry.record._source = Array.from(entry.sources).sort().join("+");
647
+ }
648
+ }
649
+ const entries = Array.from(scores.values()).map((e) => {
650
+ const recency = recencyScore(e.record.timestamp);
651
+ const importance = normalizedImportance(e.record.importance);
652
+ const confidence = sourceConfidence(e.record);
653
+ const strength = e.record.strength ?? 1;
654
+ const frecency = frecencyBoost(e.record.last_accessed, e.record.timestamp);
655
+ const baseScore = e.rrfScore * 0.4 + recency * 0.24 + importance * 0.2 + confidence * 0.1 + strength * 0.06;
656
+ const procedureBoost = e.record.memory_type === "procedure" ? 0.1 : 0;
657
+ const finalScore = (baseScore + procedureBoost) * (1 + 0.3 * frecency);
658
+ return { score: finalScore, record: e.record };
659
+ });
660
+ return entries.sort((a, b) => b.score - a.score).slice(0, limit).map((e) => e.record);
661
+ }
662
+ async function lightweightSearch(queryText, agentId, options) {
663
+ const client = getClient();
664
+ const limit = options?.limit ?? 5;
665
+ const FTS_STOP_WORDS = /* @__PURE__ */ new Set([
666
+ "the",
667
+ "and",
668
+ "but",
669
+ "for",
670
+ "not",
671
+ "you",
672
+ "your",
673
+ "his",
674
+ "her",
675
+ "its",
676
+ "our",
677
+ "their",
678
+ "this",
679
+ "that",
680
+ "these",
681
+ "those",
682
+ "what",
683
+ "when",
684
+ "where",
685
+ "who",
686
+ "how",
687
+ "why",
688
+ "which",
689
+ "does",
690
+ "did",
691
+ "was",
692
+ "were",
693
+ "has",
694
+ "have",
695
+ "had",
696
+ "can",
697
+ "could",
698
+ "would",
699
+ "should",
700
+ "are",
701
+ "with",
702
+ "from",
703
+ "about",
704
+ "into",
705
+ "through",
706
+ "during",
707
+ "before",
708
+ "after",
709
+ "above",
710
+ "below",
711
+ "between",
712
+ "same",
713
+ "each",
714
+ "every",
715
+ "both",
716
+ "more",
717
+ "most",
718
+ "other",
719
+ "some",
720
+ "such",
721
+ "than",
722
+ "too",
723
+ "very",
724
+ "just",
725
+ "also",
726
+ "any",
727
+ "all",
728
+ "own",
729
+ "being",
730
+ "been",
731
+ "they",
732
+ "them",
733
+ "will",
734
+ "may",
735
+ "might",
736
+ "shall",
737
+ "must",
738
+ "need",
739
+ "like",
740
+ "only",
741
+ "then",
742
+ "here",
743
+ "there",
744
+ "once",
745
+ "over",
746
+ "much",
747
+ "many"
748
+ ]);
749
+ const nameTermsSet = /* @__PURE__ */ new Set();
750
+ const rawWords = queryText.split(/\s+/);
751
+ for (let i = 0; i < rawWords.length; i++) {
752
+ const word = rawWords[i].replace(/[^a-zA-Z]/g, "");
753
+ if (word.length >= 2 && /^[A-Z][a-z]/.test(word) && !/^(What|When|Where|Who|How|Why|Which|Does|Did|Is|Are|Was|Were|Has|Have|Had|Can|Could|Would|Should|Do|The|And|But|For|Not|You|Your|His|Her|Its|Our|Their|This|That|These|Those|Also|Just|Very|Some|Any|All|Each|Every|Both|More|Most|Other)$/.test(word)) {
754
+ nameTermsSet.add(word.toLowerCase());
755
+ }
756
+ }
757
+ const allTerms = queryText.toLowerCase().split(/\s+/).filter((t) => t.length >= 3).map((t) => t.replace(/[^a-z0-9_]/g, "")).filter((t) => t.length >= 3 && !FTS_STOP_WORDS.has(t));
758
+ const contentTerms = allTerms.filter((t) => !nameTermsSet.has(t));
759
+ const terms = daemonSafeFtsTerms(contentTerms.length > 0 ? contentTerms : allTerms);
760
+ if (terms.length === 0) {
761
+ return recentRecords(agentId, options, limit);
762
+ }
763
+ const usePrefixTerms = shouldUseFtsPrefix(terms);
764
+ const prefixTerms = terms.map((t) => ftsTerm(t, usePrefixTerms));
765
+ const useAnd = terms.length >= 3;
766
+ const innerExpr = useAnd ? prefixTerms.join(" AND ") : prefixTerms.join(" OR ");
767
+ const matchExpr = `{raw_text keywords}: ${innerExpr}`;
768
+ const results = await ftsQuery(client, matchExpr, agentId, options, limit);
769
+ const broadOrFallbackIsSafe = !isDaemonProcess() || terms.length < DAEMON_SAFE_FTS_TERM_THRESHOLD;
770
+ if (useAnd && results.length < limit && broadOrFallbackIsSafe) {
771
+ const orExpr = `{raw_text keywords}: ${prefixTerms.join(" OR ")}`;
772
+ const orResults = await ftsQuery(client, orExpr, agentId, options, limit);
773
+ const seen = new Set(results.map((r) => r.id));
774
+ for (const r of orResults) {
775
+ if (!seen.has(r.id) && results.length < limit) {
776
+ results.push(r);
777
+ seen.add(r.id);
778
+ }
779
+ }
780
+ } else if (useAnd && results.length < limit && !broadOrFallbackIsSafe) {
781
+ logDaemonBroadFtsSkipOnce(terms);
782
+ }
783
+ if (options?.includeSource && results.length > 0) {
784
+ await attachDocumentMetadata(results);
785
+ }
786
+ if (results.length >= 2) {
787
+ try {
788
+ const { recordCoActivations } = await import("./co-activation-HZMJC34P.js");
789
+ const ids = results.slice(0, 10).map((r) => r.id);
790
+ void recordCoActivations(ids);
791
+ } catch {
792
+ }
793
+ }
794
+ if (options?.includeStructuredCards !== true) return results;
795
+ try {
796
+ const { searchMemoryCards } = await import("./memory-cards-IPULSQFA.js");
797
+ const cardResults = await searchMemoryCards(queryText, agentId, options);
798
+ if (cardResults.length > 0) {
799
+ return rrfMergeMulti([results, cardResults], limit, RRF_K, [1, 0.85]);
800
+ }
801
+ } catch {
802
+ }
803
+ return results;
804
+ }
805
+ async function ftsQuery(client, matchExpr, agentId, options, limit) {
806
+ const statusFilter = options?.includeArchived ? "" : `
807
+ AND COALESCE(m.status, 'active') = 'active'`;
808
+ const draftFilter = options?.includeDrafts ? "" : `
809
+ AND (m.draft = 0 OR m.draft IS NULL)`;
810
+ let sql = `SELECT m.id, m.agent_id, m.agent_role, m.session_id, m.timestamp,
811
+ m.tool_name, m.project_name,
812
+ m.has_error, m.raw_text, m.vector, m.task_id,
813
+ m.importance, m.status, m.confidence, m.last_accessed,
814
+ m.workspace_id, m.document_id, m.user_id,
815
+ m.char_offset, m.page_number,
816
+ m.source_path, m.source_type, m.memory_type, m.strength
817
+ FROM memories m
818
+ JOIN memories_fts fts ON m.rowid = fts.rowid
819
+ WHERE memories_fts MATCH ?
820
+ AND (m.agent_id = ? OR m.agent_id = 'wiki')${statusFilter}${draftFilter}
821
+ AND COALESCE(m.confidence, 0.7) >= 0.3`;
822
+ const args = [matchExpr, agentId];
823
+ const temporal = buildTemporalFilter(options, "m.");
824
+ sql += temporal.clause;
825
+ args.push(...temporal.args);
826
+ const scope = buildWikiScopeFilter(options, "m.");
827
+ sql += scope.clause;
828
+ args.push(...scope.args);
829
+ const rawVisibility = buildRawVisibilityFilter(options, "m.");
830
+ sql += rawVisibility.clause;
831
+ args.push(...rawVisibility.args);
832
+ if (options?.projectName) {
833
+ sql += ` AND m.project_name = ?`;
834
+ args.push(options.projectName);
835
+ }
836
+ if (options?.sessionScope) {
837
+ sql += ` AND (m.session_scope = ? OR m.session_scope IS NULL)`;
838
+ args.push(options.sessionScope);
839
+ }
840
+ if (options?.toolName) {
841
+ sql += ` AND m.tool_name = ?`;
842
+ args.push(options.toolName);
843
+ }
844
+ if (options?.hasError !== void 0) {
845
+ sql += ` AND m.has_error = ?`;
846
+ args.push(options.hasError ? 1 : 0);
847
+ }
848
+ if (options?.since) {
849
+ sql += ` AND m.timestamp >= ?`;
850
+ args.push(options.since);
851
+ }
852
+ sql = appendMemoryTypeFilter(sql, args, "m.memory_type", options);
853
+ sql += ` ORDER BY bm25(memories_fts, 1.0, 3.0) LIMIT ?`;
854
+ args.push(limit);
855
+ let result;
856
+ try {
857
+ result = await client.execute({ sql, args });
858
+ } catch (ftsErr) {
859
+ const msg = ftsErr instanceof Error ? ftsErr.message : String(ftsErr);
860
+ if (msg.includes("fts5") || msg.includes("FTS") || msg.includes("database disk image is malformed")) {
861
+ process.stderr.write(
862
+ `[hybrid-search] FTS5 corruption detected during query: ${msg}
863
+ [hybrid-search] Attempting auto-rebuild of memories_fts index...
864
+ `
865
+ );
866
+ try {
867
+ await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
868
+ process.stderr.write("[hybrid-search] FTS5 index rebuilt successfully \u2014 retrying query.\n");
869
+ result = await client.execute({ sql, args });
870
+ } catch (rebuildErr) {
871
+ process.stderr.write(
872
+ `[hybrid-search] FTS5 rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
873
+ `
874
+ );
875
+ return [];
876
+ }
877
+ } else {
878
+ throw ftsErr;
879
+ }
880
+ }
881
+ return result.rows.map((row) => ({
882
+ id: row.id,
883
+ agent_id: row.agent_id,
884
+ agent_role: row.agent_role,
885
+ session_id: row.session_id,
886
+ timestamp: row.timestamp,
887
+ tool_name: row.tool_name,
888
+ project_name: row.project_name,
889
+ has_error: row.has_error === 1,
890
+ raw_text: row.raw_text,
891
+ vector: row.vector == null ? [] : Array.isArray(row.vector) ? row.vector : Array.from(row.vector),
892
+ task_id: row.task_id ?? null,
893
+ importance: row.importance ?? 5,
894
+ status: row.status ?? "active",
895
+ confidence: row.confidence ?? 0.7,
896
+ last_accessed: row.last_accessed ?? row.timestamp,
897
+ workspace_id: row.workspace_id ?? null,
898
+ document_id: row.document_id ?? null,
899
+ user_id: row.user_id ?? null,
900
+ char_offset: row.char_offset ?? null,
901
+ page_number: row.page_number ?? null,
902
+ source_path: row.source_path ?? null,
903
+ source_type: row.source_type ?? null,
904
+ memory_type: row.memory_type ?? void 0
905
+ }));
906
+ }
907
+ async function recentRecords(agentId, options, limit, textFilter) {
908
+ const client = getClient();
909
+ const sessionBoundaryMemories = [];
910
+ try {
911
+ const kills = await client.execute({
912
+ sql: `SELECT killed_at FROM session_kills
913
+ WHERE agent_id = ?
914
+ ORDER BY killed_at DESC LIMIT 2`,
915
+ args: [agentId]
916
+ });
917
+ if (kills.rows.length > 0) {
918
+ const boundarySlots = Math.min(5, Math.floor(limit / 2));
919
+ for (const kill of kills.rows) {
920
+ const killedAt = kill.killed_at;
921
+ const windowStart = new Date(new Date(killedAt).getTime() - 10 * 60 * 1e3).toISOString();
922
+ const boundaryResult = await client.execute({
923
+ sql: `SELECT id, agent_id, agent_role, session_id, timestamp,
924
+ tool_name, project_name,
925
+ has_error, raw_text, vector, task_id,
926
+ importance, status, confidence, last_accessed,
927
+ workspace_id, document_id, user_id,
928
+ char_offset, page_number,
929
+ source_path, source_type, memory_type, strength
930
+ FROM memories
931
+ WHERE (agent_id = ? OR agent_id = 'wiki')
932
+ AND timestamp >= ? AND timestamp <= ?
933
+ AND COALESCE(status, 'active') = 'active'
934
+ AND ${options?.includeRaw === false ? "COALESCE(memory_type, 'raw') != 'raw'" : "1 = 1"}
935
+ ${options?.memoryTypes?.length ? `AND memory_type IN (${options.memoryTypes.map(() => "?").join(",")})` : options?.memoryType ? "AND memory_type = ?" : ""}
936
+ AND COALESCE(confidence, 0.7) >= 0.3
937
+ ORDER BY timestamp DESC LIMIT ?`,
938
+ args: [
939
+ agentId,
940
+ windowStart,
941
+ killedAt,
942
+ ...options?.memoryTypes?.length ? [...new Set(options.memoryTypes)] : options?.memoryType ? [options.memoryType] : [],
943
+ boundarySlots
944
+ ]
945
+ });
946
+ for (const row of boundaryResult.rows) {
947
+ sessionBoundaryMemories.push(rowToMemoryRecord(row));
948
+ }
949
+ }
950
+ }
951
+ } catch {
952
+ }
953
+ const statusFilter = options?.includeArchived ? "" : `
954
+ AND COALESCE(status, 'active') = 'active'`;
955
+ const draftFilter = options?.includeDrafts ? "" : `
956
+ AND (draft = 0 OR draft IS NULL)`;
957
+ let sql = `SELECT id, agent_id, agent_role, session_id, timestamp,
958
+ tool_name, project_name,
959
+ has_error, raw_text, vector, task_id,
960
+ importance, status, confidence, last_accessed,
961
+ workspace_id, document_id, user_id,
962
+ char_offset, page_number,
963
+ source_path, source_type, memory_type, strength
964
+ FROM memories
965
+ WHERE (agent_id = ? OR agent_id = 'wiki')${statusFilter}${draftFilter}
966
+ AND COALESCE(confidence, 0.7) >= 0.3`;
967
+ const args = [agentId];
968
+ const temporal = buildTemporalFilter(options, "");
969
+ sql += temporal.clause;
970
+ args.push(...temporal.args);
971
+ const scope = buildWikiScopeFilter(options, "");
972
+ sql += scope.clause;
973
+ args.push(...scope.args);
974
+ const rawVisibility = buildRawVisibilityFilter(options, "");
975
+ sql += rawVisibility.clause;
976
+ args.push(...rawVisibility.args);
977
+ if (options?.projectName) {
978
+ sql += ` AND project_name = ?`;
979
+ args.push(options.projectName);
980
+ }
981
+ if (options?.sessionScope) {
982
+ sql += ` AND (session_scope = ? OR session_scope IS NULL)`;
983
+ args.push(options.sessionScope);
984
+ }
985
+ if (options?.toolName) {
986
+ sql += ` AND tool_name = ?`;
987
+ args.push(options.toolName);
988
+ }
989
+ if (options?.hasError !== void 0) {
990
+ sql += ` AND has_error = ?`;
991
+ args.push(options.hasError ? 1 : 0);
992
+ }
993
+ if (options?.since) {
994
+ sql += ` AND timestamp >= ?`;
995
+ args.push(options.since);
996
+ }
997
+ sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
998
+ if (textFilter) {
999
+ sql += ` AND raw_text LIKE '%' || ? || '%'`;
1000
+ args.push(textFilter);
1001
+ }
1002
+ sql += ` ORDER BY timestamp DESC LIMIT ?`;
1003
+ args.push(limit);
1004
+ const result = await client.execute({ sql, args });
1005
+ const recentResults = result.rows.map((row) => rowToMemoryRecord(row));
1006
+ if (sessionBoundaryMemories.length > 0) {
1007
+ const seenIds = new Set(recentResults.map((r) => r.id));
1008
+ for (const bm of sessionBoundaryMemories) {
1009
+ if (!seenIds.has(bm.id)) {
1010
+ recentResults.push(bm);
1011
+ seenIds.add(bm.id);
1012
+ }
1013
+ }
1014
+ recentResults.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
1015
+ return recentResults.slice(0, limit);
1016
+ }
1017
+ return recentResults;
1018
+ }
1019
+ function rowToMemoryRecord(row) {
1020
+ return {
1021
+ id: row.id,
1022
+ agent_id: row.agent_id,
1023
+ agent_role: row.agent_role,
1024
+ session_id: row.session_id,
1025
+ timestamp: row.timestamp,
1026
+ tool_name: row.tool_name,
1027
+ project_name: row.project_name,
1028
+ has_error: row.has_error === 1,
1029
+ raw_text: row.raw_text,
1030
+ vector: row.vector == null ? [] : Array.isArray(row.vector) ? row.vector : Array.from(row.vector),
1031
+ task_id: row.task_id ?? null,
1032
+ importance: row.importance ?? 5,
1033
+ status: row.status ?? "active",
1034
+ confidence: row.confidence ?? 0.7,
1035
+ last_accessed: row.last_accessed ?? row.timestamp,
1036
+ workspace_id: row.workspace_id ?? null,
1037
+ document_id: row.document_id ?? null,
1038
+ user_id: row.user_id ?? null,
1039
+ char_offset: row.char_offset ?? null,
1040
+ page_number: row.page_number ?? null,
1041
+ source_path: row.source_path ?? null,
1042
+ source_type: row.source_type ?? null,
1043
+ memory_type: row.memory_type ?? void 0,
1044
+ strength: row.strength ?? 1
1045
+ };
1046
+ }
1047
+ var KNOWN_TOOLS = /* @__PURE__ */ new Set([
1048
+ "Bash",
1049
+ "Read",
1050
+ "Write",
1051
+ "Edit",
1052
+ "Grep",
1053
+ "Glob",
1054
+ "Agent",
1055
+ "Skill",
1056
+ "WebSearch",
1057
+ "WebFetch"
1058
+ ]);
1059
+ function detectToolQuery(query) {
1060
+ const lower = query.toLowerCase().trim();
1061
+ for (const tool of KNOWN_TOOLS) {
1062
+ if (lower === tool.toLowerCase()) return tool;
1063
+ if (lower.startsWith(tool.toLowerCase() + " ")) return tool;
1064
+ if (lower.includes(`tool:${tool.toLowerCase()}`)) return tool;
1065
+ }
1066
+ return null;
1067
+ }
1068
+ async function trajectoryBypass(queryText, agentId, options, limit) {
1069
+ const toolName = detectToolQuery(queryText);
1070
+ if (!toolName) return null;
1071
+ try {
1072
+ const client = getClient();
1073
+ const statusFilter = options?.includeArchived ? "" : `
1074
+ AND COALESCE(status, 'active') = 'active'`;
1075
+ const draftFilter = options?.includeDrafts ? "" : `
1076
+ AND (draft = 0 OR draft IS NULL)`;
1077
+ let sql = `SELECT id, agent_id, agent_role, session_id, timestamp,
1078
+ tool_name, project_name,
1079
+ has_error, raw_text, vector, task_id,
1080
+ importance, status, confidence, last_accessed,
1081
+ workspace_id, document_id, user_id,
1082
+ char_offset, page_number,
1083
+ source_path, source_type, memory_type
1084
+ FROM memories
1085
+ WHERE trajectory IS NOT NULL
1086
+ AND json_extract(trajectory, '$.tool') = ?
1087
+ AND (agent_id = ? OR agent_id = 'wiki')${statusFilter}${draftFilter}`;
1088
+ const args = [toolName, agentId];
1089
+ const temporal = buildTemporalFilter(options, "");
1090
+ sql += temporal.clause;
1091
+ args.push(...temporal.args);
1092
+ const rawVisibility = buildRawVisibilityFilter(options, "");
1093
+ sql += rawVisibility.clause;
1094
+ args.push(...rawVisibility.args);
1095
+ if (options?.projectName) {
1096
+ sql += ` AND project_name = ?`;
1097
+ args.push(options.projectName);
1098
+ }
1099
+ if (options?.sessionScope) {
1100
+ sql += ` AND (session_scope = ? OR session_scope IS NULL)`;
1101
+ args.push(options.sessionScope);
1102
+ }
1103
+ if (options?.since) {
1104
+ sql += ` AND timestamp >= ?`;
1105
+ args.push(options.since);
1106
+ }
1107
+ sql += ` ORDER BY timestamp DESC LIMIT ?`;
1108
+ args.push(limit);
1109
+ const result = await client.execute({ sql, args });
1110
+ if (result.rows.length < 3) return null;
1111
+ return result.rows.map((row) => ({
1112
+ id: row.id,
1113
+ agent_id: row.agent_id,
1114
+ agent_role: row.agent_role,
1115
+ session_id: row.session_id,
1116
+ timestamp: row.timestamp,
1117
+ tool_name: row.tool_name,
1118
+ project_name: row.project_name,
1119
+ has_error: row.has_error === 1,
1120
+ raw_text: row.raw_text,
1121
+ vector: row.vector == null ? [] : Array.isArray(row.vector) ? row.vector : Array.from(row.vector),
1122
+ task_id: row.task_id ?? null,
1123
+ importance: row.importance ?? 5,
1124
+ status: row.status ?? "active",
1125
+ confidence: row.confidence ?? 0.7,
1126
+ last_accessed: row.last_accessed ?? row.timestamp,
1127
+ workspace_id: row.workspace_id ?? null,
1128
+ document_id: row.document_id ?? null,
1129
+ user_id: row.user_id ?? null,
1130
+ char_offset: row.char_offset ?? null,
1131
+ page_number: row.page_number ?? null,
1132
+ source_path: row.source_path ?? null,
1133
+ source_type: row.source_type ?? null,
1134
+ memory_type: row.memory_type ?? void 0
1135
+ }));
1136
+ } catch {
1137
+ return null;
1138
+ }
1139
+ }
1140
+
1141
+ export {
1142
+ hybridSearch,
1143
+ estimateCardinality,
1144
+ rrfMerge,
1145
+ rrfMergeMulti,
1146
+ lightweightSearch,
1147
+ recentRecords
1148
+ };