localrag 0.1.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 (86) hide show
  1. package/README.md +178 -0
  2. package/dist/chunking/chunking-service.d.ts +18 -0
  3. package/dist/chunking/chunking-service.d.ts.map +1 -0
  4. package/dist/chunking/chunking-service.js +71 -0
  5. package/dist/chunking/chunking-service.js.map +1 -0
  6. package/dist/cli/commands/init.d.ts +8 -0
  7. package/dist/cli/commands/init.d.ts.map +1 -0
  8. package/dist/cli/commands/init.js +107 -0
  9. package/dist/cli/commands/init.js.map +1 -0
  10. package/dist/cli/commands/open.d.ts +8 -0
  11. package/dist/cli/commands/open.d.ts.map +1 -0
  12. package/dist/cli/commands/open.js +105 -0
  13. package/dist/cli/commands/open.js.map +1 -0
  14. package/dist/cli/commands/search.d.ts +10 -0
  15. package/dist/cli/commands/search.d.ts.map +1 -0
  16. package/dist/cli/commands/search.js +73 -0
  17. package/dist/cli/commands/search.js.map +1 -0
  18. package/dist/cli/commands/start.d.ts +8 -0
  19. package/dist/cli/commands/start.d.ts.map +1 -0
  20. package/dist/cli/commands/start.js +122 -0
  21. package/dist/cli/commands/start.js.map +1 -0
  22. package/dist/cli/commands/status.d.ts +12 -0
  23. package/dist/cli/commands/status.d.ts.map +1 -0
  24. package/dist/cli/commands/status.js +89 -0
  25. package/dist/cli/commands/status.js.map +1 -0
  26. package/dist/cli/index.d.ts +3 -0
  27. package/dist/cli/index.d.ts.map +1 -0
  28. package/dist/cli/index.js +62 -0
  29. package/dist/cli/index.js.map +1 -0
  30. package/dist/config/config-service.d.ts +22 -0
  31. package/dist/config/config-service.d.ts.map +1 -0
  32. package/dist/config/config-service.js +108 -0
  33. package/dist/config/config-service.js.map +1 -0
  34. package/dist/db/lancedb-repository.d.ts +28 -0
  35. package/dist/db/lancedb-repository.d.ts.map +1 -0
  36. package/dist/db/lancedb-repository.js +132 -0
  37. package/dist/db/lancedb-repository.js.map +1 -0
  38. package/dist/embedding/embedding-service.d.ts +22 -0
  39. package/dist/embedding/embedding-service.d.ts.map +1 -0
  40. package/dist/embedding/embedding-service.js +99 -0
  41. package/dist/embedding/embedding-service.js.map +1 -0
  42. package/dist/extractors/docx-extractor.d.ts +12 -0
  43. package/dist/extractors/docx-extractor.d.ts.map +1 -0
  44. package/dist/extractors/docx-extractor.js +29 -0
  45. package/dist/extractors/docx-extractor.js.map +1 -0
  46. package/dist/extractors/extractor.interface.d.ts +14 -0
  47. package/dist/extractors/extractor.interface.d.ts.map +1 -0
  48. package/dist/extractors/extractor.interface.js +63 -0
  49. package/dist/extractors/extractor.interface.js.map +1 -0
  50. package/dist/extractors/pdf-extractor.d.ts +11 -0
  51. package/dist/extractors/pdf-extractor.d.ts.map +1 -0
  52. package/dist/extractors/pdf-extractor.js +89 -0
  53. package/dist/extractors/pdf-extractor.js.map +1 -0
  54. package/dist/extractors/pptx-extractor.d.ts +12 -0
  55. package/dist/extractors/pptx-extractor.d.ts.map +1 -0
  56. package/dist/extractors/pptx-extractor.js +98 -0
  57. package/dist/extractors/pptx-extractor.js.map +1 -0
  58. package/dist/extractors/text-extractor.d.ts +10 -0
  59. package/dist/extractors/text-extractor.d.ts.map +1 -0
  60. package/dist/extractors/text-extractor.js +52 -0
  61. package/dist/extractors/text-extractor.js.map +1 -0
  62. package/dist/extractors/xlsx-extractor.d.ts +11 -0
  63. package/dist/extractors/xlsx-extractor.d.ts.map +1 -0
  64. package/dist/extractors/xlsx-extractor.js +28 -0
  65. package/dist/extractors/xlsx-extractor.js.map +1 -0
  66. package/dist/indexer/indexer.d.ts +34 -0
  67. package/dist/indexer/indexer.d.ts.map +1 -0
  68. package/dist/indexer/indexer.js +100 -0
  69. package/dist/indexer/indexer.js.map +1 -0
  70. package/dist/metadata/metadata-service.d.ts +34 -0
  71. package/dist/metadata/metadata-service.d.ts.map +1 -0
  72. package/dist/metadata/metadata-service.js +147 -0
  73. package/dist/metadata/metadata-service.js.map +1 -0
  74. package/dist/scanner/file-scanner.d.ts +20 -0
  75. package/dist/scanner/file-scanner.d.ts.map +1 -0
  76. package/dist/scanner/file-scanner.js +110 -0
  77. package/dist/scanner/file-scanner.js.map +1 -0
  78. package/dist/search/search-service.d.ts +18 -0
  79. package/dist/search/search-service.d.ts.map +1 -0
  80. package/dist/search/search-service.js +98 -0
  81. package/dist/search/search-service.js.map +1 -0
  82. package/dist/watcher/file-watcher.d.ts +27 -0
  83. package/dist/watcher/file-watcher.d.ts.map +1 -0
  84. package/dist/watcher/file-watcher.js +110 -0
  85. package/dist/watcher/file-watcher.js.map +1 -0
  86. package/package.json +53 -0
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.startCommand = startCommand;
40
+ const path = __importStar(require("path"));
41
+ const chalk_1 = __importDefault(require("chalk"));
42
+ const ora_1 = __importDefault(require("ora"));
43
+ const config_service_1 = require("../../config/config-service");
44
+ const metadata_service_1 = require("../../metadata/metadata-service");
45
+ const lancedb_repository_1 = require("../../db/lancedb-repository");
46
+ const embedding_service_1 = require("../../embedding/embedding-service");
47
+ const indexer_1 = require("../../indexer/indexer");
48
+ const file_scanner_1 = require("../../scanner/file-scanner");
49
+ const file_watcher_1 = require("../../watcher/file-watcher");
50
+ /**
51
+ * `localrag start`
52
+ *
53
+ * Performs a startup scan to catch missed changes, then starts a persistent
54
+ * file watcher to keep the index up-to-date in real time.
55
+ */
56
+ async function startCommand() {
57
+ const config = new config_service_1.ConfigService();
58
+ const folders = config.getWatchedFolders();
59
+ if (folders.length === 0) {
60
+ console.error(chalk_1.default.red('✗ No watched folders configured.'));
61
+ console.log(chalk_1.default.dim(`Run ${chalk_1.default.white('localrag init <folder>')} first.`));
62
+ process.exit(1);
63
+ }
64
+ // Initialise services
65
+ const repo = new lancedb_repository_1.LanceDbRepository();
66
+ await repo.initialize(config.getDbPath());
67
+ const metadata = new metadata_service_1.MetadataService(config);
68
+ const embedder = new embedding_service_1.EmbeddingService();
69
+ const indexer = new indexer_1.Indexer(config, repo, metadata, embedder);
70
+ // ── 1. Startup scan ────────────────────────────────────────────────────
71
+ console.log(chalk_1.default.cyan.bold('\n📂 localrag — starting up\n'));
72
+ console.log(`Watched folders:`);
73
+ folders.forEach(f => console.log(` ${chalk_1.default.dim('•')} ${f}`));
74
+ console.log('');
75
+ const scanSpinner = (0, ora_1.default)({ text: 'Running startup scan…', spinner: 'dots' }).start();
76
+ const scanner = new file_scanner_1.FileScanner(metadata, indexer);
77
+ let scanErrors = 0;
78
+ await scanner.scan(folders, {
79
+ onProgress: (msg) => { scanSpinner.text = msg; },
80
+ onError: (_fp, err) => {
81
+ scanSpinner.warn(chalk_1.default.red(`Error: ${err.message}`));
82
+ scanSpinner.start();
83
+ scanErrors++;
84
+ },
85
+ });
86
+ scanSpinner.succeed('Startup scan complete.');
87
+ if (scanErrors > 0) {
88
+ console.log(chalk_1.default.yellow(` ${scanErrors} file(s) had errors during scan.`));
89
+ }
90
+ // ── 2. Live watcher ────────────────────────────────────────────────────
91
+ console.log(chalk_1.default.cyan('\n👁 Watching for changes… (Ctrl+C to stop)\n'));
92
+ const watcher = new file_watcher_1.FileWatcher(indexer);
93
+ watcher.watch(folders, {
94
+ onAdd: (fp) => {
95
+ console.log(chalk_1.default.green(`+ ${path.basename(fp)}`) + chalk_1.default.dim(` — ${fp}`));
96
+ },
97
+ onChange: (fp) => {
98
+ console.log(chalk_1.default.yellow(`~ ${path.basename(fp)}`) + chalk_1.default.dim(` — ${fp}`));
99
+ },
100
+ onUnlink: (fp) => {
101
+ console.log(chalk_1.default.red(`- ${path.basename(fp)}`) + chalk_1.default.dim(` — ${fp}`));
102
+ },
103
+ onProgress: (msg) => {
104
+ console.log(chalk_1.default.dim(` ${msg}`));
105
+ },
106
+ onError: (fp, err) => {
107
+ console.log(chalk_1.default.red(` ✗ ${path.basename(fp)}: ${err.message}`));
108
+ },
109
+ onReady: () => {
110
+ console.log(chalk_1.default.dim(' Watcher ready — monitoring for filesystem changes.'));
111
+ },
112
+ });
113
+ // Keep the process alive until Ctrl+C
114
+ const shutdown = async () => {
115
+ console.log(chalk_1.default.dim('\nShutting down…'));
116
+ await watcher.close();
117
+ process.exit(0);
118
+ };
119
+ process.on('SIGINT', shutdown);
120
+ process.on('SIGTERM', shutdown);
121
+ }
122
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * `localrag status`
3
+ *
4
+ * Displays a summary of the current index state:
5
+ * - Watched folders
6
+ * - Indexed file count
7
+ * - Total chunk count
8
+ * - Vector DB size on disk
9
+ * - Last indexing activity
10
+ */
11
+ export declare function statusCommand(): Promise<void>;
12
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAUA;;;;;;;;;GASG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA+DnD"}
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.statusCommand = statusCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const config_service_1 = require("../../config/config-service");
10
+ const metadata_service_1 = require("../../metadata/metadata-service");
11
+ const lancedb_repository_1 = require("../../db/lancedb-repository");
12
+ const BYTES_PER_MB = 1024 * 1024;
13
+ /**
14
+ * `localrag status`
15
+ *
16
+ * Displays a summary of the current index state:
17
+ * - Watched folders
18
+ * - Indexed file count
19
+ * - Total chunk count
20
+ * - Vector DB size on disk
21
+ * - Last indexing activity
22
+ */
23
+ async function statusCommand() {
24
+ const config = new config_service_1.ConfigService();
25
+ const folders = config.getWatchedFolders();
26
+ const repo = new lancedb_repository_1.LanceDbRepository();
27
+ const metadata = new metadata_service_1.MetadataService(config);
28
+ const spinner = (0, ora_1.default)({ text: 'Gathering stats…', spinner: 'dots' }).start();
29
+ let dbSizeMb = '—';
30
+ try {
31
+ await repo.initialize(config.getDbPath());
32
+ const bytes = await repo.getDbSizeBytes(config.getDbPath());
33
+ dbSizeMb = (bytes / BYTES_PER_MB).toFixed(2) + ' MB';
34
+ }
35
+ catch {
36
+ // DB may not exist yet
37
+ }
38
+ spinner.stop();
39
+ const docCount = metadata.getCount();
40
+ const chunkCount = metadata.getTotalChunkCount();
41
+ const lastActivity = metadata.getLastActivity() ?? config.getLastActivity() ?? 'Never';
42
+ // ── Display ─────────────────────────────────────────────────────────────
43
+ console.log('');
44
+ console.log(chalk_1.default.bold.cyan(' localrag — index status'));
45
+ console.log(chalk_1.default.dim(' ─────────────────────────────────────'));
46
+ console.log('');
47
+ // Watched folders
48
+ console.log(` ${chalk_1.default.bold('Watched folders:')} ${folders.length === 0 ? chalk_1.default.dim('none') : ''}`);
49
+ if (folders.length > 0) {
50
+ folders.forEach(f => {
51
+ console.log(` ${chalk_1.default.dim('•')} ${f}`);
52
+ });
53
+ }
54
+ console.log('');
55
+ // Stats table
56
+ const rows = [
57
+ ['Indexed files', chalk_1.default.cyan(String(docCount))],
58
+ ['Total chunks', chalk_1.default.cyan(String(chunkCount))],
59
+ ['DB size', chalk_1.default.cyan(dbSizeMb)],
60
+ ['Last activity', formatDate(lastActivity)],
61
+ ];
62
+ rows.forEach(([label, value]) => {
63
+ console.log(` ${chalk_1.default.bold(label.padEnd(18))} ${value}`);
64
+ });
65
+ console.log('');
66
+ if (folders.length === 0) {
67
+ console.log(chalk_1.default.dim(` Run ${chalk_1.default.white('localrag init <folder>')} to get started.`));
68
+ }
69
+ else if (docCount === 0) {
70
+ console.log(chalk_1.default.dim(` Run ${chalk_1.default.white('localrag start')} to index your documents.`));
71
+ }
72
+ else {
73
+ console.log(chalk_1.default.dim(` Run ${chalk_1.default.white('localrag search "<query>"')} to search.`));
74
+ }
75
+ console.log('');
76
+ }
77
+ // ── Helpers ───────────────────────────────────────────────────────────────
78
+ function formatDate(iso) {
79
+ if (iso === 'Never')
80
+ return chalk_1.default.dim('Never');
81
+ try {
82
+ const d = new Date(iso);
83
+ return chalk_1.default.white(d.toLocaleString());
84
+ }
85
+ catch {
86
+ return chalk_1.default.dim(iso);
87
+ }
88
+ }
89
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const init_1 = require("./commands/init");
6
+ const start_1 = require("./commands/start");
7
+ const search_1 = require("./commands/search");
8
+ const open_1 = require("./commands/open");
9
+ const status_1 = require("./commands/status");
10
+ const program = new commander_1.Command();
11
+ program
12
+ .name('localrag')
13
+ .description('Local-first semantic document search — find your documents by meaning, not keywords.')
14
+ .version('0.1.0');
15
+ // ── localrag init <folder> ─────────────────────────────────────────────────
16
+ program
17
+ .command('init <folder>')
18
+ .description('Add a folder to the watch list and run an initial index.')
19
+ .action(async (folder) => {
20
+ await (0, init_1.initCommand)(folder).catch(fatal);
21
+ });
22
+ // ── localrag start ─────────────────────────────────────────────────────────
23
+ program
24
+ .command('start')
25
+ .description('Start continuous background indexing (runs in the foreground).')
26
+ .action(async () => {
27
+ await (0, start_1.startCommand)().catch(fatal);
28
+ });
29
+ // ── localrag search "<query>" ──────────────────────────────────────────────
30
+ program
31
+ .command('search <query>')
32
+ .description('Semantic search across all indexed documents.')
33
+ .option('-t, --top <n>', 'Number of results to return (default: 10)', '10')
34
+ .action(async (query, options) => {
35
+ await (0, search_1.searchCommand)(query, options).catch(fatal);
36
+ });
37
+ // ── localrag open <N> ──────────────────────────────────────────────────────
38
+ program
39
+ .command('open <result-number>')
40
+ .description('Open the Nth result from the last search using the OS default app.')
41
+ .action(async (resultNumber) => {
42
+ await (0, open_1.openCommand)(resultNumber).catch(fatal);
43
+ });
44
+ // ── localrag status ────────────────────────────────────────────────────────
45
+ program
46
+ .command('status')
47
+ .description('Show the current index status and statistics.')
48
+ .action(async () => {
49
+ await (0, status_1.statusCommand)().catch(fatal);
50
+ });
51
+ // ── Error handler ─────────────────────────────────────────────────────────
52
+ function fatal(err) {
53
+ const msg = err instanceof Error ? err.message : String(err);
54
+ console.error(`\n ✗ Fatal error: ${msg}\n`);
55
+ process.exit(1);
56
+ }
57
+ // ── Parse ─────────────────────────────────────────────────────────────────
58
+ program.parse(process.argv);
59
+ if (process.argv.length < 3) {
60
+ program.help();
61
+ }
62
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,0CAA8C;AAC9C,4CAAgD;AAChD,8CAAkD;AAClD,0CAA8C;AAC9C,8CAAkD;AAElD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,sFAAsF,CAAC;KACnG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,8EAA8E;AAC9E,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,0DAA0D,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,EAAE;IAC/B,MAAM,IAAA,kBAAW,EAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC,CAAC,CAAC;AAEL,8EAA8E;AAC9E,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,IAAA,oBAAY,GAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACpC,CAAC,CAAC,CAAC;AAEL,8EAA8E;AAC9E,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,eAAe,EAAE,2CAA2C,EAAE,IAAI,CAAC;KAC1E,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,OAAyB,EAAE,EAAE;IACzD,MAAM,IAAA,sBAAa,EAAC,KAAK,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC;AAEL,8EAA8E;AAC9E,OAAO;KACJ,OAAO,CAAC,sBAAsB,CAAC;KAC/B,WAAW,CAAC,oEAAoE,CAAC;KACjF,MAAM,CAAC,KAAK,EAAE,YAAoB,EAAE,EAAE;IACrC,MAAM,IAAA,kBAAW,EAAC,YAAY,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC/C,CAAC,CAAC,CAAC;AAEL,8EAA8E;AAC9E,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,IAAA,sBAAa,GAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACrC,CAAC,CAAC,CAAC;AAEL,6EAA6E;AAE7E,SAAS,KAAK,CAAC,GAAY;IACzB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,CAAC,KAAK,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,6EAA6E;AAE7E,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAE5B,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;IAC5B,OAAO,CAAC,IAAI,EAAE,CAAC;AACjB,CAAC"}
@@ -0,0 +1,22 @@
1
+ export interface localragConfig {
2
+ watchedFolders: string[];
3
+ dbPath: string;
4
+ lastActivity?: string;
5
+ }
6
+ export declare class ConfigService {
7
+ private config;
8
+ constructor();
9
+ private load;
10
+ getConfig(): localragConfig;
11
+ getDataDir(): string;
12
+ getDbPath(): string;
13
+ getDocumentsPath(): string;
14
+ getLastResultsPath(): string;
15
+ getStatsPath(): string;
16
+ getWatchedFolders(): string[];
17
+ addWatchedFolder(folder: string): boolean;
18
+ setLastActivity(isoString: string): void;
19
+ getLastActivity(): string | undefined;
20
+ private save;
21
+ }
22
+ //# sourceMappingURL=config-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-service.d.ts","sourceRoot":"","sources":["../../src/config/config-service.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAUD,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAiB;;IAM/B,OAAO,CAAC,IAAI;IAYZ,SAAS,IAAI,cAAc;IAI3B,UAAU,IAAI,MAAM;IAKpB,SAAS,IAAI,MAAM;IAMnB,gBAAgB,IAAI,MAAM;IAI1B,kBAAkB,IAAI,MAAM;IAI5B,YAAY,IAAI,MAAM;IAItB,iBAAiB,IAAI,MAAM,EAAE;IAI7B,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAQzC,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAKxC,eAAe,IAAI,MAAM,GAAG,SAAS;IAIrC,OAAO,CAAC,IAAI;CAIb"}
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ConfigService = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const os = __importStar(require("os"));
40
+ const DATA_DIR = path.join(os.homedir(), '.localrag');
41
+ const CONFIG_PATH = path.join(DATA_DIR, 'config.json');
42
+ const DEFAULT_CONFIG = {
43
+ watchedFolders: [],
44
+ dbPath: path.join(DATA_DIR, 'db'),
45
+ };
46
+ class ConfigService {
47
+ config;
48
+ constructor() {
49
+ this.config = this.load();
50
+ }
51
+ load() {
52
+ try {
53
+ if (fs.existsSync(CONFIG_PATH)) {
54
+ const raw = fs.readFileSync(CONFIG_PATH, 'utf-8');
55
+ return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };
56
+ }
57
+ }
58
+ catch {
59
+ // ignore parse errors — use defaults
60
+ }
61
+ return { ...DEFAULT_CONFIG };
62
+ }
63
+ getConfig() {
64
+ return { ...this.config };
65
+ }
66
+ getDataDir() {
67
+ fs.mkdirSync(DATA_DIR, { recursive: true });
68
+ return DATA_DIR;
69
+ }
70
+ getDbPath() {
71
+ const dbPath = this.config.dbPath;
72
+ fs.mkdirSync(dbPath, { recursive: true });
73
+ return dbPath;
74
+ }
75
+ getDocumentsPath() {
76
+ return path.join(DATA_DIR, 'documents.json');
77
+ }
78
+ getLastResultsPath() {
79
+ return path.join(DATA_DIR, 'last-results.json');
80
+ }
81
+ getStatsPath() {
82
+ return path.join(DATA_DIR, 'stats.json');
83
+ }
84
+ getWatchedFolders() {
85
+ return [...this.config.watchedFolders];
86
+ }
87
+ addWatchedFolder(folder) {
88
+ const abs = path.resolve(folder);
89
+ if (this.config.watchedFolders.includes(abs))
90
+ return false;
91
+ this.config.watchedFolders.push(abs);
92
+ this.save();
93
+ return true;
94
+ }
95
+ setLastActivity(isoString) {
96
+ this.config.lastActivity = isoString;
97
+ this.save();
98
+ }
99
+ getLastActivity() {
100
+ return this.config.lastActivity;
101
+ }
102
+ save() {
103
+ fs.mkdirSync(DATA_DIR, { recursive: true });
104
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(this.config, null, 2));
105
+ }
106
+ }
107
+ exports.ConfigService = ConfigService;
108
+ //# sourceMappingURL=config-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-service.js","sourceRoot":"","sources":["../../src/config/config-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export interface ChunkRecord {
2
+ id: string;
3
+ filePath: string;
4
+ page: number;
5
+ text: string;
6
+ vector: number[];
7
+ }
8
+ export interface SearchResult {
9
+ id: string;
10
+ filePath: string;
11
+ fileName: string;
12
+ page: number;
13
+ text: string;
14
+ score: number;
15
+ }
16
+ export declare class LanceDbRepository {
17
+ private db;
18
+ private chunksTable;
19
+ private initialized;
20
+ initialize(dbPath: string): Promise<void>;
21
+ private initChunksTable;
22
+ private ensureInit;
23
+ upsertChunks(chunks: ChunkRecord[]): Promise<void>;
24
+ deleteChunksByPath(filePath: string): Promise<void>;
25
+ vectorSearch(queryVector: number[], topK?: number): Promise<SearchResult[]>;
26
+ getDbSizeBytes(dbPath: string): Promise<number>;
27
+ }
28
+ //# sourceMappingURL=lancedb-repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lancedb-repository.d.ts","sourceRoot":"","sources":["../../src/db/lancedb-repository.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AASD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAAsB;IAChC,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,WAAW,CAAS;IAItB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAOjC,eAAe;IAoB7B,OAAO,CAAC,UAAU;IAQZ,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlD,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQnD,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,IAAI,SAAK,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAoBvE,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAmBtD"}
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.LanceDbRepository = void 0;
37
+ const path = __importStar(require("path"));
38
+ const lancedb = __importStar(require("vectordb"));
39
+ // ── Constants ─────────────────────────────────────────────────────────────
40
+ const VECTOR_DIM = 384; // all-MiniLM-L6-v2 output dimension
41
+ const PLACEHOLDER_ID = '__localrag_init__';
42
+ // ── Repository ────────────────────────────────────────────────────────────
43
+ class LanceDbRepository {
44
+ db;
45
+ chunksTable;
46
+ initialized = false;
47
+ // ── Init ────────────────────────────────────────────────────────────────
48
+ async initialize(dbPath) {
49
+ if (this.initialized)
50
+ return;
51
+ this.db = await lancedb.connect(dbPath);
52
+ await this.initChunksTable();
53
+ this.initialized = true;
54
+ }
55
+ async initChunksTable() {
56
+ const names = await this.db.tableNames();
57
+ if (names.includes('chunks')) {
58
+ this.chunksTable = await this.db.openTable('chunks');
59
+ }
60
+ else {
61
+ // Create with a placeholder row to define schema
62
+ const placeholder = [
63
+ {
64
+ id: PLACEHOLDER_ID,
65
+ filePath: '',
66
+ page: 0,
67
+ text: '',
68
+ vector: new Array(VECTOR_DIM).fill(0),
69
+ },
70
+ ];
71
+ this.chunksTable = await this.db.createTable('chunks', placeholder);
72
+ await this.chunksTable.delete(`id = '${PLACEHOLDER_ID}'`);
73
+ }
74
+ }
75
+ ensureInit() {
76
+ if (!this.initialized) {
77
+ throw new Error('LanceDbRepository: call initialize() before use');
78
+ }
79
+ }
80
+ // ── Write ops ───────────────────────────────────────────────────────────
81
+ async upsertChunks(chunks) {
82
+ this.ensureInit();
83
+ if (chunks.length === 0)
84
+ return;
85
+ await this.chunksTable.add(chunks);
86
+ }
87
+ async deleteChunksByPath(filePath) {
88
+ this.ensureInit();
89
+ const escaped = filePath.replace(/'/g, "''");
90
+ await this.chunksTable.delete(`"filePath" = '${escaped}'`);
91
+ }
92
+ // ── Read / Search ops ───────────────────────────────────────────────────
93
+ async vectorSearch(queryVector, topK = 10) {
94
+ this.ensureInit();
95
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
96
+ const raw = await this.chunksTable
97
+ .search(queryVector)
98
+ .limit(topK)
99
+ .execute();
100
+ return raw.map(r => ({
101
+ id: String(r.id),
102
+ filePath: String(r.filePath),
103
+ fileName: path.basename(String(r.filePath)),
104
+ page: Number(r.page),
105
+ text: String(r.text),
106
+ // LanceDB returns _distance (lower = closer). Convert cosine distance → similarity score.
107
+ score: Math.max(0, 1 - Number(r._distance ?? 0)),
108
+ }));
109
+ }
110
+ async getDbSizeBytes(dbPath) {
111
+ const { readdirSync, statSync } = await Promise.resolve().then(() => __importStar(require('fs')));
112
+ let total = 0;
113
+ const walk = (dir) => {
114
+ try {
115
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
116
+ const full = path.join(dir, entry.name);
117
+ if (entry.isDirectory())
118
+ walk(full);
119
+ else
120
+ total += statSync(full).size;
121
+ }
122
+ }
123
+ catch {
124
+ // skip unreadable dirs
125
+ }
126
+ };
127
+ walk(dbPath);
128
+ return total;
129
+ }
130
+ }
131
+ exports.LanceDbRepository = LanceDbRepository;
132
+ //# sourceMappingURL=lancedb-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lancedb-repository.js","sourceRoot":"","sources":["../../src/db/lancedb-repository.ts"],"names":[],"mappings":"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"}