mindlore 0.4.2 → 0.5.0

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 (76) hide show
  1. package/README.md +4 -2
  2. package/dist/scripts/lib/constants.d.ts +4 -0
  3. package/dist/scripts/lib/constants.d.ts.map +1 -1
  4. package/dist/scripts/lib/constants.js +5 -1
  5. package/dist/scripts/lib/constants.js.map +1 -1
  6. package/dist/scripts/lib/db-helpers.d.ts +15 -0
  7. package/dist/scripts/lib/db-helpers.d.ts.map +1 -1
  8. package/dist/scripts/lib/db-helpers.js +51 -0
  9. package/dist/scripts/lib/db-helpers.js.map +1 -1
  10. package/dist/scripts/lib/embedding.d.ts +5 -0
  11. package/dist/scripts/lib/embedding.d.ts.map +1 -0
  12. package/dist/scripts/lib/embedding.js +44 -0
  13. package/dist/scripts/lib/embedding.js.map +1 -0
  14. package/dist/scripts/lib/hybrid-search.d.ts +62 -0
  15. package/dist/scripts/lib/hybrid-search.d.ts.map +1 -0
  16. package/dist/scripts/lib/hybrid-search.js +150 -0
  17. package/dist/scripts/lib/hybrid-search.js.map +1 -0
  18. package/dist/scripts/lib/migrations.d.ts +3 -0
  19. package/dist/scripts/lib/migrations.d.ts.map +1 -0
  20. package/dist/scripts/lib/migrations.js +38 -0
  21. package/dist/scripts/lib/migrations.js.map +1 -0
  22. package/dist/scripts/lib/schema-version.d.ts +13 -0
  23. package/dist/scripts/lib/schema-version.d.ts.map +1 -0
  24. package/dist/scripts/lib/schema-version.js +37 -0
  25. package/dist/scripts/lib/schema-version.js.map +1 -0
  26. package/dist/scripts/lib/synonym.d.ts +4 -0
  27. package/dist/scripts/lib/synonym.d.ts.map +1 -0
  28. package/dist/scripts/lib/synonym.js +37 -0
  29. package/dist/scripts/lib/synonym.js.map +1 -0
  30. package/dist/scripts/mindlore-fts5-index.d.ts +2 -1
  31. package/dist/scripts/mindlore-fts5-index.d.ts.map +1 -1
  32. package/dist/scripts/mindlore-fts5-index.js +57 -5
  33. package/dist/scripts/mindlore-fts5-index.js.map +1 -1
  34. package/dist/scripts/mindlore-fts5-search.d.ts +3 -2
  35. package/dist/scripts/mindlore-fts5-search.d.ts.map +1 -1
  36. package/dist/scripts/mindlore-fts5-search.js +89 -35
  37. package/dist/scripts/mindlore-fts5-search.js.map +1 -1
  38. package/dist/scripts/mindlore-health-check.js +52 -0
  39. package/dist/scripts/mindlore-health-check.js.map +1 -1
  40. package/dist/tests/embedding.test.d.ts +6 -0
  41. package/dist/tests/embedding.test.d.ts.map +1 -0
  42. package/dist/tests/embedding.test.js +71 -0
  43. package/dist/tests/embedding.test.js.map +1 -0
  44. package/dist/tests/fts5.test.js +82 -0
  45. package/dist/tests/fts5.test.js.map +1 -1
  46. package/dist/tests/helpers/db.d.ts +5 -0
  47. package/dist/tests/helpers/db.d.ts.map +1 -1
  48. package/dist/tests/helpers/db.js +19 -0
  49. package/dist/tests/helpers/db.js.map +1 -1
  50. package/dist/tests/hook-smoke.test.js +2 -2
  51. package/dist/tests/hook-smoke.test.js.map +1 -1
  52. package/dist/tests/hybrid-search.test.d.ts +2 -0
  53. package/dist/tests/hybrid-search.test.d.ts.map +1 -0
  54. package/dist/tests/hybrid-search.test.js +114 -0
  55. package/dist/tests/hybrid-search.test.js.map +1 -0
  56. package/dist/tests/research-guard.test.d.ts +2 -0
  57. package/dist/tests/research-guard.test.d.ts.map +1 -0
  58. package/dist/tests/research-guard.test.js +143 -0
  59. package/dist/tests/research-guard.test.js.map +1 -0
  60. package/dist/tests/schema-version.test.d.ts +2 -0
  61. package/dist/tests/schema-version.test.d.ts.map +1 -0
  62. package/dist/tests/schema-version.test.js +99 -0
  63. package/dist/tests/schema-version.test.js.map +1 -0
  64. package/dist/tests/search-hook.test.js +11 -0
  65. package/dist/tests/search-hook.test.js.map +1 -1
  66. package/dist/tests/synonym.test.d.ts +2 -0
  67. package/dist/tests/synonym.test.d.ts.map +1 -0
  68. package/dist/tests/synonym.test.js +47 -0
  69. package/dist/tests/synonym.test.js.map +1 -0
  70. package/hooks/lib/mindlore-common.cjs +94 -0
  71. package/hooks/mindlore-research-guard.cjs +144 -0
  72. package/hooks/mindlore-search.cjs +56 -42
  73. package/hooks/mindlore-session-end.cjs +41 -13
  74. package/package.json +3 -1
  75. package/plugin.json +6 -1
  76. package/templates/config.json +15 -1
package/README.md CHANGED
@@ -163,6 +163,7 @@ SESSION START DURING SESSION SESSIO
163
163
  - **Project-scoped search** — results filtered by current project, falls back to all projects if none found
164
164
  - **No `.mindlore/`?** — hooks silently skip, zero overhead
165
165
  - **FTS5 search** — SQLite full-text search with BM25 ranking, no external services
166
+ - **Hybrid search** — RRF fusion combining FTS5 keyword + sqlite-vec vector results with synonym expansion
166
167
  - **Content-hash dedup** — SHA256 prevents re-indexing unchanged files
167
168
 
168
169
  ## Configuration
@@ -184,7 +185,7 @@ Skills spawn subagents with `[mindlore:SKILL]` markers — the model-router hook
184
185
 
185
186
  ## Hooks
186
187
 
187
- 13 Claude Code lifecycle hooks (v0.4.2):
188
+ 14 Claude Code lifecycle hooks (v0.5.0):
188
189
 
189
190
  | Event | Hook | What it does |
190
191
  |-------|------|-------------|
@@ -193,7 +194,7 @@ Skills spawn subagents with `[mindlore:SKILL]` markers — the model-router hook
193
194
  | UserPromptSubmit | decision-detector | TR+EN decision signal detection |
194
195
  | FileChanged | index | Sync changed files to FTS5 |
195
196
  | FileChanged | fts5-sync | Incremental batch re-index |
196
- | SessionEnd | session-end | Structured delta + bare episode + FTS5 mirror + git sync |
197
+ | SessionEnd | session-end | Structured delta + bare episode + FTS5 mirror + detached git sync |
197
198
  | PreCompact | pre-compact | FTS5 flush before compaction |
198
199
  | PostCompact | post-compact | Re-inject context |
199
200
  | PreToolUse (Read) | read-guard | Repeated-read warning, blocks 3+ repeats |
@@ -201,6 +202,7 @@ Skills spawn subagents with `[mindlore:SKILL]` markers — the model-router hook
201
202
  | PreToolUse (Write\|Edit) | dont-repeat | LESSONS/learnings rule enforcement |
202
203
  | CwdChanged | cwd-changed | Scope detection + _scope.json write |
203
204
  | PreToolUse (Agent) | model-router | Cost-optimized model routing via markers |
205
+ | PreToolUse (Agent) | research-guard | FTS5 check before research — blocks if recent+high quality exists |
204
206
 
205
207
  ## Uninstall
206
208
 
@@ -5,6 +5,10 @@ export declare const DIRECTORIES: readonly ["raw", "sources", "domains", "analys
5
5
  export declare const SKIP_FILES: Set<string>;
6
6
  export declare const CONFIG_FILE = "config.json";
7
7
  export declare const DEFAULT_MODELS: Record<string, string>;
8
+ export declare const VEC_TABLE_NAME = "documents_vec";
9
+ export declare const SCHEMA_VERSION = 1;
10
+ export declare const EMBEDDING_MODEL_NAME = "Xenova/multilingual-e5-small";
11
+ export declare const EMBEDDING_DIM_CONST = 384;
8
12
  export declare const FTS5_COLUMNS: readonly ["path", "slug", "description", "type", "category", "title", "content", "tags", "quality", "date_captured", "project"];
9
13
  export type FtsColumn = typeof FTS5_COLUMNS[number];
10
14
  export declare const FRONTMATTER_TYPES: readonly ["raw", "source", "domain", "analysis", "diary", "decision", "insight", "connection", "learning"];
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../scripts/lib/constants.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY,cAAc,CAAC;AACxC,eAAO,MAAM,mBAAmB,QAAqE,CAAC;AACtG,eAAO,MAAM,OAAO,gBAAgB,CAAC;AAErC,eAAO,MAAM,WAAW,kHAUd,CAAC;AAEX,eAAO,MAAM,UAAU,aAA+C,CAAC;AAEvE,eAAO,MAAM,WAAW,gBAAgB,CAAC;AAEzC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKxC,CAAC;AAEX,eAAO,MAAM,YAAY,iIAAkI,CAAC;AAC5J,MAAM,MAAM,SAAS,GAAG,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;AAEpD,eAAO,MAAM,iBAAiB,4GAA6G,CAAC;AAC5I,MAAM,MAAM,eAAe,GAAG,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE/D,eAAO,MAAM,cAAc,oCAAqC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAS3D,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAU9C,CAAC;AAEF,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAIpC;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAErC;AAID,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAI3D;AAOD,wBAAgB,aAAa,IAAI,OAAO,CAWvC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../scripts/lib/constants.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY,cAAc,CAAC;AACxC,eAAO,MAAM,mBAAmB,QAAqE,CAAC;AACtG,eAAO,MAAM,OAAO,gBAAgB,CAAC;AAErC,eAAO,MAAM,WAAW,kHAUd,CAAC;AAEX,eAAO,MAAM,UAAU,aAA+C,CAAC;AAEvE,eAAO,MAAM,WAAW,gBAAgB,CAAC;AAEzC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKxC,CAAC;AAEX,eAAO,MAAM,cAAc,kBAAkB,CAAC;AAC9C,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,oBAAoB,iCAAiC,CAAC;AACnE,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,eAAO,MAAM,YAAY,iIAAkI,CAAC;AAC5J,MAAM,MAAM,SAAS,GAAG,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;AAEpD,eAAO,MAAM,iBAAiB,4GAA6G,CAAC;AAC5I,MAAM,MAAM,eAAe,GAAG,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE/D,eAAO,MAAM,cAAc,oCAAqC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;AAEzD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAS3D,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAU9C,CAAC;AAEF,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAIpC;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;GAEG;AACH,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAErC;AAID,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAI3D;AAOD,wBAAgB,aAAa,IAAI,OAAO,CAWvC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C"}
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.TYPE_TO_DIR = exports.QUALITY_HEURISTICS = exports.QUALITY_VALUES = exports.FRONTMATTER_TYPES = exports.FTS5_COLUMNS = exports.DEFAULT_MODELS = exports.CONFIG_FILE = exports.SKIP_FILES = exports.DIRECTORIES = exports.DB_NAME = exports.GLOBAL_MINDLORE_DIR = exports.MINDLORE_DIR = void 0;
6
+ exports.TYPE_TO_DIR = exports.QUALITY_HEURISTICS = exports.QUALITY_VALUES = exports.FRONTMATTER_TYPES = exports.FTS5_COLUMNS = exports.EMBEDDING_DIM_CONST = exports.EMBEDDING_MODEL_NAME = exports.SCHEMA_VERSION = exports.VEC_TABLE_NAME = exports.DEFAULT_MODELS = exports.CONFIG_FILE = exports.SKIP_FILES = exports.DIRECTORIES = exports.DB_NAME = exports.GLOBAL_MINDLORE_DIR = exports.MINDLORE_DIR = void 0;
7
7
  exports.homedir = homedir;
8
8
  exports.getActiveMindloreDir = getActiveMindloreDir;
9
9
  exports.getAllDbs = getAllDbs;
@@ -38,6 +38,10 @@ exports.DEFAULT_MODELS = {
38
38
  explore: 'sonnet',
39
39
  default: 'haiku',
40
40
  };
41
+ exports.VEC_TABLE_NAME = 'documents_vec';
42
+ exports.SCHEMA_VERSION = 1;
43
+ exports.EMBEDDING_MODEL_NAME = 'Xenova/multilingual-e5-small';
44
+ exports.EMBEDDING_DIM_CONST = 384;
41
45
  exports.FTS5_COLUMNS = ['path', 'slug', 'description', 'type', 'category', 'title', 'content', 'tags', 'quality', 'date_captured', 'project'];
42
46
  exports.FRONTMATTER_TYPES = ['raw', 'source', 'domain', 'analysis', 'diary', 'decision', 'insight', 'connection', 'learning'];
43
47
  exports.QUALITY_VALUES = ['high', 'medium', 'low'];
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../scripts/lib/constants.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../scripts/lib/constants.ts"],"names":[],"mappings":"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"}
@@ -18,5 +18,20 @@ export declare function dbAll<T extends Record<string, unknown>>(db: Database, s
18
18
  * Typed wrapper for Database.pragma().
19
19
  */
20
20
  export declare function dbPragma<T>(db: Database, pragma: string): T[];
21
+ /**
22
+ * Load sqlite-vec extension into the database.
23
+ * Returns true if loaded, false if sqlite-vec is not available.
24
+ */
25
+ export declare function loadSqliteVec(db: Database): boolean;
26
+ /**
27
+ * Create documents_vec virtual table if it doesn't exist.
28
+ * Requires sqlite-vec to be loaded first.
29
+ * Silently does nothing if vec0 is not available.
30
+ */
31
+ export declare function ensureVecTable(db: Database): boolean;
32
+ /**
33
+ * Check if documents_vec table exists and is functional.
34
+ */
35
+ export declare function hasVecTable(db: Database): boolean;
21
36
  export {};
22
37
  //# sourceMappingURL=db-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"db-helpers.d.ts","sourceRoot":"","sources":["../../../scripts/lib/db-helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,KAAK,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrD,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE,MAAM,EACX,GAAG,MAAM,EAAE,OAAO,EAAE,GACnB,CAAC,GAAG,SAAS,CAQf;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrD,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE,MAAM,EACX,GAAG,MAAM,EAAE,OAAO,EAAE,GACnB,CAAC,EAAE,CAIL;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAI7D"}
1
+ {"version":3,"file":"db-helpers.d.ts","sourceRoot":"","sources":["../../../scripts/lib/db-helpers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,KAAK,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;AAIvC;;;GAGG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrD,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE,MAAM,EACX,GAAG,MAAM,EAAE,OAAO,EAAE,GACnB,CAAC,GAAG,SAAS,CAQf;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrD,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE,MAAM,EACX,GAAG,MAAM,EAAE,OAAO,EAAE,GACnB,CAAC,EAAE,CAIL;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAI7D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAQnD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAcpD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAOjD"}
@@ -3,6 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.dbGet = dbGet;
4
4
  exports.dbAll = dbAll;
5
5
  exports.dbPragma = dbPragma;
6
+ exports.loadSqliteVec = loadSqliteVec;
7
+ exports.ensureVecTable = ensureVecTable;
8
+ exports.hasVecTable = hasVecTable;
9
+ const constants_js_1 = require("./constants.js");
6
10
  /**
7
11
  * Typed wrapper for Statement.get().
8
12
  * Returns undefined if no row matches.
@@ -33,4 +37,51 @@ function dbPragma(db, pragma) {
33
37
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- centralized cast: pragma returns array of objects
34
38
  return result;
35
39
  }
40
+ /**
41
+ * Load sqlite-vec extension into the database.
42
+ * Returns true if loaded, false if sqlite-vec is not available.
43
+ */
44
+ function loadSqliteVec(db) {
45
+ try {
46
+ const sqliteVec = require('sqlite-vec');
47
+ sqliteVec.load(db);
48
+ return true;
49
+ }
50
+ catch (_err) {
51
+ return false;
52
+ }
53
+ }
54
+ /**
55
+ * Create documents_vec virtual table if it doesn't exist.
56
+ * Requires sqlite-vec to be loaded first.
57
+ * Silently does nothing if vec0 is not available.
58
+ */
59
+ function ensureVecTable(db) {
60
+ try {
61
+ db.exec(`
62
+ CREATE VIRTUAL TABLE IF NOT EXISTS ${constants_js_1.VEC_TABLE_NAME} USING vec0(
63
+ embedding float[${constants_js_1.EMBEDDING_DIM_CONST}],
64
+ slug text,
65
+ +created_at text,
66
+ +model_name text
67
+ )
68
+ `);
69
+ return true;
70
+ }
71
+ catch (_err) {
72
+ return false;
73
+ }
74
+ }
75
+ /**
76
+ * Check if documents_vec table exists and is functional.
77
+ */
78
+ function hasVecTable(db) {
79
+ try {
80
+ db.prepare(`SELECT slug FROM ${constants_js_1.VEC_TABLE_NAME} LIMIT 0`).run();
81
+ return true;
82
+ }
83
+ catch (_err) {
84
+ return false;
85
+ }
86
+ }
36
87
  //# sourceMappingURL=db-helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"db-helpers.js","sourceRoot":"","sources":["../../../scripts/lib/db-helpers.ts"],"names":[],"mappings":";;AAYA,sBAYC;AAKD,sBAQC;AAKD,4BAIC;AAtCD;;;GAGG;AACH,SAAgB,KAAK,CACnB,EAAY,EACZ,GAAW,EACX,GAAG,MAAiB;IAEpB,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC9C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAClD,MAAM,IAAI,SAAS,CAAC,mCAAmC,OAAO,MAAM,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,qHAAqH;IACrH,OAAO,MAAW,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,SAAgB,KAAK,CACnB,EAAY,EACZ,GAAW,EACX,GAAG,MAAiB;IAEpB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC/C,mIAAmI;IACnI,OAAO,OAAc,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,SAAgB,QAAQ,CAAI,EAAY,EAAE,MAAc;IACtD,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,4HAA4H;IAC5H,OAAO,MAAa,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"db-helpers.js","sourceRoot":"","sources":["../../../scripts/lib/db-helpers.ts"],"names":[],"mappings":";;AAcA,sBAYC;AAKD,sBAQC;AAKD,4BAIC;AAMD,sCAQC;AAOD,wCAcC;AAKD,kCAOC;AAvFD,iDAAqE;AAErE;;;GAGG;AACH,SAAgB,KAAK,CACnB,EAAY,EACZ,GAAW,EACX,GAAG,MAAiB;IAEpB,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC9C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAClD,MAAM,IAAI,SAAS,CAAC,mCAAmC,OAAO,MAAM,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,qHAAqH;IACrH,OAAO,MAAW,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,SAAgB,KAAK,CACnB,EAAY,EACZ,GAAW,EACX,GAAG,MAAiB;IAEpB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC/C,mIAAmI;IACnI,OAAO,OAAc,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,SAAgB,QAAQ,CAAI,EAAY,EAAE,MAAc;IACtD,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,4HAA4H;IAC5H,OAAO,MAAa,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,SAAgB,aAAa,CAAC,EAAY;IACxC,IAAI,CAAC;QACH,MAAM,SAAS,GAAoC,OAAO,CAAC,YAAY,CAAC,CAAC;QACzE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,IAAI,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,cAAc,CAAC,EAAY;IACzC,IAAI,CAAC;QACH,EAAE,CAAC,IAAI,CAAC;2CAC+B,6BAAc;0BAC/B,kCAAmB;;;;;KAKxC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,IAAI,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,WAAW,CAAC,EAAY;IACtC,IAAI,CAAC;QACH,EAAE,CAAC,OAAO,CAAC,oBAAoB,6BAAc,UAAU,CAAC,CAAC,GAAG,EAAE,CAAC;QAC/D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,IAAI,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const EMBEDDING_MODEL = "Xenova/multilingual-e5-small";
2
+ export declare const EMBEDDING_DIM = 384;
3
+ export declare function generateEmbedding(text: string): Promise<number[]>;
4
+ export declare function batchEmbed(texts: string[]): Promise<number[][]>;
5
+ //# sourceMappingURL=embedding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding.d.ts","sourceRoot":"","sources":["../../../scripts/lib/embedding.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,iCAAiC,CAAC;AAC9D,eAAO,MAAM,aAAa,MAAM,CAAC;AAgBjC,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAevE;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAMrE"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EMBEDDING_DIM = exports.EMBEDDING_MODEL = void 0;
4
+ exports.generateEmbedding = generateEmbedding;
5
+ exports.batchEmbed = batchEmbed;
6
+ exports.EMBEDDING_MODEL = 'Xenova/multilingual-e5-small';
7
+ exports.EMBEDDING_DIM = 384;
8
+ // Pipeline instance — cached after first load (~16s)
9
+ let cachedPipeline = null;
10
+ async function getEmbedder() {
11
+ if (cachedPipeline)
12
+ return cachedPipeline;
13
+ // Dynamic import — @xenova/transformers is ESM
14
+ const { pipeline: createPipeline } = await import('@xenova/transformers');
15
+ cachedPipeline = await createPipeline('feature-extraction', exports.EMBEDDING_MODEL, {
16
+ quantized: true, // int8 quantization — smaller, faster
17
+ });
18
+ return cachedPipeline;
19
+ }
20
+ async function generateEmbedding(text) {
21
+ const embedder = await getEmbedder();
22
+ // multilingual-e5-small expects "query: " or "passage: " prefix
23
+ const prefixed = text.startsWith('query:') || text.startsWith('passage:')
24
+ ? text
25
+ : `passage: ${text}`;
26
+ // Pipeline is callable — returns Tensor with tolist()
27
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- @xenova/transformers pipeline is callable but untyped
28
+ const run = embedder;
29
+ // normalize: true in pipeline options already returns L2-normalized vectors
30
+ const result = await run([prefixed], { pooling: 'mean', normalize: true });
31
+ const list = result.tolist();
32
+ const raw = list[0];
33
+ if (!raw)
34
+ throw new Error('Embedding pipeline returned empty result');
35
+ return raw;
36
+ }
37
+ async function batchEmbed(texts) {
38
+ const results = [];
39
+ for (const text of texts) {
40
+ results.push(await generateEmbedding(text));
41
+ }
42
+ return results;
43
+ }
44
+ //# sourceMappingURL=embedding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding.js","sourceRoot":"","sources":["../../../scripts/lib/embedding.ts"],"names":[],"mappings":";;;AAiBA,8CAeC;AAED,gCAMC;AAxCY,QAAA,eAAe,GAAG,8BAA8B,CAAC;AACjD,QAAA,aAAa,GAAG,GAAG,CAAC;AAEjC,qDAAqD;AACrD,IAAI,cAAc,GAAY,IAAI,CAAC;AAEnC,KAAK,UAAU,WAAW;IACxB,IAAI,cAAc;QAAE,OAAO,cAAc,CAAC;IAE1C,+CAA+C;IAC/C,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAC1E,cAAc,GAAG,MAAM,cAAc,CAAC,oBAAoB,EAAE,uBAAe,EAAE;QAC3E,SAAS,EAAE,IAAI,EAAE,sCAAsC;KACxD,CAAC,CAAC;IACH,OAAO,cAAc,CAAC;AACxB,CAAC;AAEM,KAAK,UAAU,iBAAiB,CAAC,IAAY;IAClD,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;IACrC,gEAAgE;IAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QACvE,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,YAAY,IAAI,EAAE,CAAC;IACvB,sDAAsD;IACtD,gIAAgI;IAChI,MAAM,GAAG,GAAG,QAAqG,CAAC;IAClH,4EAA4E;IAC5E,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACtE,OAAO,GAAG,CAAC;AACb,CAAC;AAEM,KAAK,UAAU,UAAU,CAAC,KAAe;IAC9C,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,62 @@
1
+ import type BetterSqlite3 from 'better-sqlite3';
2
+ type Database = BetterSqlite3.Database;
3
+ export interface FtsResult {
4
+ [key: string]: unknown;
5
+ slug: string;
6
+ rank: number;
7
+ path?: string;
8
+ description?: string;
9
+ title?: string;
10
+ category?: string;
11
+ tags?: string;
12
+ }
13
+ export interface VecResult {
14
+ [key: string]: unknown;
15
+ slug: string;
16
+ distance: number;
17
+ }
18
+ export interface FusedResult {
19
+ slug: string;
20
+ score: number;
21
+ ftsRank?: number;
22
+ vecDistance?: number;
23
+ path?: string;
24
+ description?: string;
25
+ title?: string;
26
+ category?: string;
27
+ tags?: string;
28
+ }
29
+ export interface RRFOptions {
30
+ k?: number;
31
+ ftsWeight?: number;
32
+ vecWeight?: number;
33
+ }
34
+ export interface HybridSearchOptions {
35
+ maxResults?: number;
36
+ k?: number;
37
+ ftsWeight?: number;
38
+ vecWeight?: number;
39
+ synonyms?: Record<string, string[]>;
40
+ project?: string;
41
+ queryEmbedding?: number[];
42
+ }
43
+ /**
44
+ * Convert L2 distance to cosine similarity.
45
+ * For normalized vectors: cosine_sim = 1.0 - (l2_dist² / 2.0)
46
+ */
47
+ export declare function l2ToCosine(l2Distance: number): number;
48
+ /**
49
+ * Normalize FTS5 BM25 rank to 0-1 range.
50
+ * FTS5 returns negative rank — more negative = better match.
51
+ */
52
+ export declare function normalizeBM25(rank: number): number;
53
+ export declare function computeRRF(ftsResults: FtsResult[], vecResults: VecResult[], options?: RRFOptions): FusedResult[];
54
+ export declare function searchFts5(db: Database, query: string, limit?: number, project?: string): FtsResult[];
55
+ export declare function searchVec(db: Database, queryEmbedding: number[], limit?: number): VecResult[];
56
+ /**
57
+ * Main hybrid search entry point.
58
+ * Falls back to pure FTS5 when vec table or embedding is not available.
59
+ */
60
+ export declare function hybridSearch(db: Database, query: string, options?: HybridSearchOptions): FusedResult[];
61
+ export {};
62
+ //# sourceMappingURL=hybrid-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hybrid-search.d.ts","sourceRoot":"","sources":["../../../scripts/lib/hybrid-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAGhD,KAAK,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;AAEvC,MAAM,WAAW,SAAS;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAID;;;GAGG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGrD;AAKD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAID,wBAAgB,UAAU,CACxB,UAAU,EAAE,SAAS,EAAE,EACvB,UAAU,EAAE,SAAS,EAAE,EACvB,OAAO,GAAE,UAAe,GACvB,WAAW,EAAE,CAiDf;AAID,wBAAgB,UAAU,CACxB,EAAE,EAAE,QAAQ,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAW,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,SAAS,EAAE,CA8Bb;AAED,wBAAgB,SAAS,CACvB,EAAE,EAAE,QAAQ,EACZ,cAAc,EAAE,MAAM,EAAE,EACxB,KAAK,GAAE,MAAW,GACjB,SAAS,EAAE,CAeb;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,EAAE,EAAE,QAAQ,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,mBAAwB,GAChC,WAAW,EAAE,CAoCf"}
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.l2ToCosine = l2ToCosine;
4
+ exports.normalizeBM25 = normalizeBM25;
5
+ exports.computeRRF = computeRRF;
6
+ exports.searchFts5 = searchFts5;
7
+ exports.searchVec = searchVec;
8
+ exports.hybridSearch = hybridSearch;
9
+ const db_helpers_js_1 = require("./db-helpers.js");
10
+ // ── Utility Functions ──────────────────────────────────────────────
11
+ /**
12
+ * Convert L2 distance to cosine similarity.
13
+ * For normalized vectors: cosine_sim = 1.0 - (l2_dist² / 2.0)
14
+ */
15
+ function l2ToCosine(l2Distance) {
16
+ const cosine = 1.0 - (l2Distance * l2Distance / 2.0);
17
+ return Math.max(0.0, Math.min(1.0, cosine));
18
+ }
19
+ // Empirical upper bound for BM25 absolute rank in Mindlore corpus (~150 docs)
20
+ const BM25_MAX_RANK = 25.0;
21
+ /**
22
+ * Normalize FTS5 BM25 rank to 0-1 range.
23
+ * FTS5 returns negative rank — more negative = better match.
24
+ */
25
+ function normalizeBM25(rank) {
26
+ return Math.abs(rank) / BM25_MAX_RANK;
27
+ }
28
+ // ── RRF Fusion ─────────────────────────────────────────────────────
29
+ function computeRRF(ftsResults, vecResults, options = {}) {
30
+ const k = options.k ?? 60;
31
+ const ftsWeight = options.ftsWeight ?? 0.4;
32
+ const vecWeight = options.vecWeight ?? 0.6;
33
+ const scores = new Map();
34
+ // FTS5 results — already sorted by rank (most negative first = best)
35
+ for (let i = 0; i < ftsResults.length; i++) {
36
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- loop guard: i < length
37
+ const r = ftsResults[i];
38
+ const rrfScore = ftsWeight * (1.0 / (k + i + 1));
39
+ const existing = scores.get(r.slug);
40
+ if (existing) {
41
+ existing.score += rrfScore;
42
+ existing.ftsRank = r.rank;
43
+ }
44
+ else {
45
+ scores.set(r.slug, {
46
+ slug: r.slug,
47
+ score: rrfScore,
48
+ ftsRank: r.rank,
49
+ path: r.path,
50
+ description: r.description,
51
+ title: r.title,
52
+ category: r.category,
53
+ tags: r.tags,
54
+ });
55
+ }
56
+ }
57
+ // Vec results — already sorted by distance (lowest first = most similar)
58
+ for (let i = 0; i < vecResults.length; i++) {
59
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- loop guard: i < length
60
+ const r = vecResults[i];
61
+ const rrfScore = vecWeight * (1.0 / (k + i + 1));
62
+ const existing = scores.get(r.slug);
63
+ if (existing) {
64
+ existing.score += rrfScore;
65
+ existing.vecDistance = r.distance;
66
+ }
67
+ else {
68
+ scores.set(r.slug, {
69
+ slug: r.slug,
70
+ score: rrfScore,
71
+ vecDistance: r.distance,
72
+ });
73
+ }
74
+ }
75
+ return Array.from(scores.values()).sort((a, b) => b.score - a.score);
76
+ }
77
+ // ── Search Functions ───────────────────────────────────────────────
78
+ function searchFts5(db, query, limit = 20, project) {
79
+ const sanitized = query.replace(/["*(){}[\]^~:]/g, '').trim();
80
+ if (!sanitized)
81
+ return [];
82
+ const terms = sanitized.split(/\s+/).map(t => `"${t}"`).join(' OR ');
83
+ try {
84
+ if (project) {
85
+ return (0, db_helpers_js_1.dbAll)(db, `SELECT slug, path, description, title, category, tags, rank
86
+ FROM mindlore_fts
87
+ WHERE mindlore_fts MATCH ? AND project = ?
88
+ ORDER BY rank
89
+ LIMIT ?`, terms, project, limit);
90
+ }
91
+ return (0, db_helpers_js_1.dbAll)(db, `SELECT slug, path, description, title, category, tags, rank
92
+ FROM mindlore_fts
93
+ WHERE mindlore_fts MATCH ?
94
+ ORDER BY rank
95
+ LIMIT ?`, terms, limit);
96
+ }
97
+ catch (_err) {
98
+ return [];
99
+ }
100
+ }
101
+ function searchVec(db, queryEmbedding, limit = 20) {
102
+ try {
103
+ const buf = Buffer.from(new Float32Array(queryEmbedding).buffer);
104
+ return (0, db_helpers_js_1.dbAll)(db, `SELECT slug, distance
105
+ FROM documents_vec
106
+ WHERE embedding MATCH ?
107
+ ORDER BY distance
108
+ LIMIT ?`, buf, limit);
109
+ }
110
+ catch (_err) {
111
+ return [];
112
+ }
113
+ }
114
+ /**
115
+ * Main hybrid search entry point.
116
+ * Falls back to pure FTS5 when vec table or embedding is not available.
117
+ */
118
+ function hybridSearch(db, query, options = {}) {
119
+ const maxResults = options.maxResults ?? 5;
120
+ const ftsLimit = 20;
121
+ const vecLimit = 20;
122
+ // Always search FTS5
123
+ const ftsResults = searchFts5(db, query, ftsLimit, options.project);
124
+ // Try vec search if embedding is provided and vec table exists
125
+ let vecResults = [];
126
+ if (options.queryEmbedding && (0, db_helpers_js_1.hasVecTable)(db)) {
127
+ vecResults = searchVec(db, options.queryEmbedding, vecLimit);
128
+ }
129
+ // If no vec results, return FTS5 results directly
130
+ if (vecResults.length === 0) {
131
+ return ftsResults.slice(0, maxResults).map(r => ({
132
+ slug: r.slug,
133
+ score: normalizeBM25(r.rank),
134
+ ftsRank: r.rank,
135
+ path: r.path,
136
+ description: r.description,
137
+ title: r.title,
138
+ category: r.category,
139
+ tags: r.tags,
140
+ }));
141
+ }
142
+ // Fuse results with RRF
143
+ const fused = computeRRF(ftsResults, vecResults, {
144
+ k: options.k,
145
+ ftsWeight: options.ftsWeight,
146
+ vecWeight: options.vecWeight,
147
+ });
148
+ return fused.slice(0, maxResults);
149
+ }
150
+ //# sourceMappingURL=hybrid-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hybrid-search.js","sourceRoot":"","sources":["../../../scripts/lib/hybrid-search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Migration } from './schema-version.js';
2
+ export declare const V050_MIGRATIONS: Migration[];
3
+ //# sourceMappingURL=migrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../scripts/lib/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAKrD,eAAO,MAAM,eAAe,EAAE,SAAS,EAiCtC,CAAC"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.V050_MIGRATIONS = void 0;
4
+ const constants_js_1 = require("./constants.js");
5
+ exports.V050_MIGRATIONS = [
6
+ {
7
+ version: 1,
8
+ name: 'add_vec_table_and_timestamps',
9
+ up: (db) => {
10
+ // 1. Create vec table (requires sqlite-vec loaded — skip gracefully if not)
11
+ try {
12
+ db.exec(`
13
+ CREATE VIRTUAL TABLE IF NOT EXISTS ${constants_js_1.VEC_TABLE_NAME} USING vec0(
14
+ embedding float[${constants_js_1.EMBEDDING_DIM_CONST}],
15
+ slug text,
16
+ +created_at text,
17
+ +model_name text
18
+ )
19
+ `);
20
+ }
21
+ catch (_err) {
22
+ // sqlite-vec not loaded — vec table will be created when extension is available
23
+ }
24
+ // 2. Add timestamp columns to file_hashes
25
+ // (FTS5 virtual tables can't be altered — timestamps go in file_hashes)
26
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- pragma returns array of objects
27
+ const cols = db.pragma('table_info(file_hashes)');
28
+ const colNames = new Set(cols.map(c => c.name));
29
+ if (!colNames.has('created_at')) {
30
+ db.exec('ALTER TABLE file_hashes ADD COLUMN created_at TEXT');
31
+ }
32
+ if (!colNames.has('updated_at')) {
33
+ db.exec('ALTER TABLE file_hashes ADD COLUMN updated_at TEXT');
34
+ }
35
+ },
36
+ },
37
+ ];
38
+ //# sourceMappingURL=migrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../../scripts/lib/migrations.ts"],"names":[],"mappings":";;;AACA,iDAAqE;AAIxD,QAAA,eAAe,GAAgB;IAC1C;QACE,OAAO,EAAE,CAAC;QACV,IAAI,EAAE,8BAA8B;QACpC,EAAE,EAAE,CAAC,EAAY,EAAE,EAAE;YACnB,4EAA4E;YAC5E,IAAI,CAAC;gBACH,EAAE,CAAC,IAAI,CAAC;+CAC+B,6BAAc;8BAC/B,kCAAmB;;;;;SAKxC,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,IAAI,EAAE,CAAC;gBACd,gFAAgF;YAClF,CAAC;YAED,0CAA0C;YAC1C,wEAAwE;YACxE,0GAA0G;YAC1G,MAAM,IAAI,GAAG,EAAE,CAAC,MAAM,CAAC,yBAAyB,CAA4B,CAAC;YAC7E,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAEhD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;gBAChC,EAAE,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;YAChE,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;gBAChC,EAAE,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;KACF;CACF,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type BetterSqlite3 from 'better-sqlite3';
2
+ type Database = BetterSqlite3.Database;
3
+ export interface Migration {
4
+ version: number;
5
+ name: string;
6
+ up: (db: Database) => void;
7
+ }
8
+ export declare function ensureSchemaTable(db: Database): void;
9
+ export declare function getSchemaVersion(db: Database): number;
10
+ export declare function setSchemaVersion(db: Database, version: number, name?: string): void;
11
+ export declare function runMigrations(db: Database, migrations: Migration[]): void;
12
+ export {};
13
+ //# sourceMappingURL=schema-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-version.d.ts","sourceRoot":"","sources":["../../../scripts/lib/schema-version.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAChD,KAAK,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;AAEvC,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,CAAC,EAAE,EAAE,QAAQ,KAAK,IAAI,CAAC;CAC5B;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAQpD;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAKrD;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAKnF;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,CAYzE"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureSchemaTable = ensureSchemaTable;
4
+ exports.getSchemaVersion = getSchemaVersion;
5
+ exports.setSchemaVersion = setSchemaVersion;
6
+ exports.runMigrations = runMigrations;
7
+ function ensureSchemaTable(db) {
8
+ db.exec(`
9
+ CREATE TABLE IF NOT EXISTS schema_versions (
10
+ version INTEGER PRIMARY KEY,
11
+ name TEXT NOT NULL,
12
+ applied_at TEXT NOT NULL
13
+ )
14
+ `);
15
+ }
16
+ function getSchemaVersion(db) {
17
+ ensureSchemaTable(db);
18
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- better-sqlite3 .get() returns unknown
19
+ const row = db.prepare('SELECT MAX(version) as v FROM schema_versions').get();
20
+ return row?.v ?? 0;
21
+ }
22
+ function setSchemaVersion(db, version, name) {
23
+ ensureSchemaTable(db);
24
+ db.prepare('INSERT OR REPLACE INTO schema_versions (version, name, applied_at) VALUES (?, ?, ?)').run(version, name ?? `migration_${version}`, new Date().toISOString());
25
+ }
26
+ function runMigrations(db, migrations) {
27
+ ensureSchemaTable(db);
28
+ const current = getSchemaVersion(db);
29
+ const pending = migrations
30
+ .filter(m => m.version > current)
31
+ .sort((a, b) => a.version - b.version);
32
+ for (const migration of pending) {
33
+ migration.up(db);
34
+ setSchemaVersion(db, migration.version, migration.name);
35
+ }
36
+ }
37
+ //# sourceMappingURL=schema-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-version.js","sourceRoot":"","sources":["../../../scripts/lib/schema-version.ts"],"names":[],"mappings":";;AASA,8CAQC;AAED,4CAKC;AAED,4CAKC;AAED,sCAYC;AApCD,SAAgB,iBAAiB,CAAC,EAAY;IAC5C,EAAE,CAAC,IAAI,CAAC;;;;;;GAMP,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,gBAAgB,CAAC,EAAY;IAC3C,iBAAiB,CAAC,EAAE,CAAC,CAAC;IACtB,gHAAgH;IAChH,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAC,GAAG,EAAsC,CAAC;IAClH,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAED,SAAgB,gBAAgB,CAAC,EAAY,EAAE,OAAe,EAAE,IAAa;IAC3E,iBAAiB,CAAC,EAAE,CAAC,CAAC;IACtB,EAAE,CAAC,OAAO,CACR,qFAAqF,CACtF,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,IAAI,aAAa,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED,SAAgB,aAAa,CAAC,EAAY,EAAE,UAAuB;IACjE,iBAAiB,CAAC,EAAE,CAAC,CAAC;IACtB,MAAM,OAAO,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAC;IAErC,MAAM,OAAO,GAAG,UAAU;SACvB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC;SAChC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;IAEzC,KAAK,MAAM,SAAS,IAAI,OAAO,EAAE,CAAC;QAChC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACjB,gBAAgB,CAAC,EAAE,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export type SynonymMap = Record<string, string[]>;
2
+ export declare function loadSynonyms(config: Record<string, unknown>): SynonymMap;
3
+ export declare function expandQuery(query: string, synonyms: SynonymMap): string[];
4
+ //# sourceMappingURL=synonym.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synonym.d.ts","sourceRoot":"","sources":["../../../scripts/lib/synonym.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAElD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAMxE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,MAAM,EAAE,CA2BzE"}