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.
- package/README.md +178 -0
- package/dist/chunking/chunking-service.d.ts +18 -0
- package/dist/chunking/chunking-service.d.ts.map +1 -0
- package/dist/chunking/chunking-service.js +71 -0
- package/dist/chunking/chunking-service.js.map +1 -0
- package/dist/cli/commands/init.d.ts +8 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +107 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/open.d.ts +8 -0
- package/dist/cli/commands/open.d.ts.map +1 -0
- package/dist/cli/commands/open.js +105 -0
- package/dist/cli/commands/open.js.map +1 -0
- package/dist/cli/commands/search.d.ts +10 -0
- package/dist/cli/commands/search.d.ts.map +1 -0
- package/dist/cli/commands/search.js +73 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/commands/start.d.ts +8 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +122 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.d.ts +12 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +89 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +62 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/config-service.d.ts +22 -0
- package/dist/config/config-service.d.ts.map +1 -0
- package/dist/config/config-service.js +108 -0
- package/dist/config/config-service.js.map +1 -0
- package/dist/db/lancedb-repository.d.ts +28 -0
- package/dist/db/lancedb-repository.d.ts.map +1 -0
- package/dist/db/lancedb-repository.js +132 -0
- package/dist/db/lancedb-repository.js.map +1 -0
- package/dist/embedding/embedding-service.d.ts +22 -0
- package/dist/embedding/embedding-service.d.ts.map +1 -0
- package/dist/embedding/embedding-service.js +99 -0
- package/dist/embedding/embedding-service.js.map +1 -0
- package/dist/extractors/docx-extractor.d.ts +12 -0
- package/dist/extractors/docx-extractor.d.ts.map +1 -0
- package/dist/extractors/docx-extractor.js +29 -0
- package/dist/extractors/docx-extractor.js.map +1 -0
- package/dist/extractors/extractor.interface.d.ts +14 -0
- package/dist/extractors/extractor.interface.d.ts.map +1 -0
- package/dist/extractors/extractor.interface.js +63 -0
- package/dist/extractors/extractor.interface.js.map +1 -0
- package/dist/extractors/pdf-extractor.d.ts +11 -0
- package/dist/extractors/pdf-extractor.d.ts.map +1 -0
- package/dist/extractors/pdf-extractor.js +89 -0
- package/dist/extractors/pdf-extractor.js.map +1 -0
- package/dist/extractors/pptx-extractor.d.ts +12 -0
- package/dist/extractors/pptx-extractor.d.ts.map +1 -0
- package/dist/extractors/pptx-extractor.js +98 -0
- package/dist/extractors/pptx-extractor.js.map +1 -0
- package/dist/extractors/text-extractor.d.ts +10 -0
- package/dist/extractors/text-extractor.d.ts.map +1 -0
- package/dist/extractors/text-extractor.js +52 -0
- package/dist/extractors/text-extractor.js.map +1 -0
- package/dist/extractors/xlsx-extractor.d.ts +11 -0
- package/dist/extractors/xlsx-extractor.d.ts.map +1 -0
- package/dist/extractors/xlsx-extractor.js +28 -0
- package/dist/extractors/xlsx-extractor.js.map +1 -0
- package/dist/indexer/indexer.d.ts +34 -0
- package/dist/indexer/indexer.d.ts.map +1 -0
- package/dist/indexer/indexer.js +100 -0
- package/dist/indexer/indexer.js.map +1 -0
- package/dist/metadata/metadata-service.d.ts +34 -0
- package/dist/metadata/metadata-service.d.ts.map +1 -0
- package/dist/metadata/metadata-service.js +147 -0
- package/dist/metadata/metadata-service.js.map +1 -0
- package/dist/scanner/file-scanner.d.ts +20 -0
- package/dist/scanner/file-scanner.d.ts.map +1 -0
- package/dist/scanner/file-scanner.js +110 -0
- package/dist/scanner/file-scanner.js.map +1 -0
- package/dist/search/search-service.d.ts +18 -0
- package/dist/search/search-service.d.ts.map +1 -0
- package/dist/search/search-service.js +98 -0
- package/dist/search/search-service.js.map +1 -0
- package/dist/watcher/file-watcher.d.ts +27 -0
- package/dist/watcher/file-watcher.d.ts.map +1 -0
- package/dist/watcher/file-watcher.js +110 -0
- package/dist/watcher/file-watcher.js.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# localrag
|
|
2
|
+
|
|
3
|
+
**Local-first semantic document search CLI.**
|
|
4
|
+
Find your files by *meaning*, not keywords — entirely on your machine. No cloud. No API keys.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- 🔍 **Semantic search** across PDF, DOCX, XLSX, PPTX, TXT, and Markdown
|
|
11
|
+
- ⚡ **Sub-second search** — queries hit pre-built vectors, not raw files
|
|
12
|
+
- 👁 **Watch-based indexing** — the index updates automatically as files change
|
|
13
|
+
- 🔒 **100% local** — embeddings and vectors never leave your machine
|
|
14
|
+
- 📦 **Zero config** — works out of the box with one command
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g localrag
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Requires **Node.js ≥ 18**.
|
|
25
|
+
|
|
26
|
+
> **First run note:** On first use the embedding model (`all-MiniLM-L6-v2`, ~25 MB) is downloaded from Hugging Face and cached permanently in `~/.cache/huggingface`. An internet connection is only needed this once.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# 1. Add a folder and run an initial index
|
|
34
|
+
localrag init ~/Documents
|
|
35
|
+
|
|
36
|
+
# 2. Search
|
|
37
|
+
localrag search "vacation policy"
|
|
38
|
+
|
|
39
|
+
# 3. Open the first result
|
|
40
|
+
localrag open 1
|
|
41
|
+
|
|
42
|
+
# 4. Start continuous watching (keeps index up-to-date)
|
|
43
|
+
localrag start
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Commands
|
|
49
|
+
|
|
50
|
+
### `localrag init <folder>`
|
|
51
|
+
|
|
52
|
+
Add a folder to the watch list and immediately index all supported files inside it.
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
localrag init ~/Documents
|
|
56
|
+
localrag init ~/Desktop/Work
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### `localrag search "<query>"`
|
|
60
|
+
|
|
61
|
+
Semantically search indexed documents. Returns file path, page number, similarity score, and a content snippet.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
localrag search "annual leave policy"
|
|
65
|
+
localrag search "Q3 revenue projections"
|
|
66
|
+
localrag search "meeting notes product roadmap"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Options:
|
|
70
|
+
|
|
71
|
+
| Flag | Description | Default |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| `-t, --top <n>` | Number of results | `10` |
|
|
74
|
+
|
|
75
|
+
### `localrag open <N>`
|
|
76
|
+
|
|
77
|
+
Open the Nth result from the last search using your OS default app.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
localrag open 1
|
|
81
|
+
localrag open 3
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### `localrag start`
|
|
85
|
+
|
|
86
|
+
Start continuous background indexing. Runs in the foreground — press `Ctrl+C` to stop.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
localrag start
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### `localrag status`
|
|
93
|
+
|
|
94
|
+
Display a summary of the current index.
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
localrag status
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Output includes:
|
|
101
|
+
- Watched folders
|
|
102
|
+
- Indexed file count
|
|
103
|
+
- Total chunk count
|
|
104
|
+
- Database size on disk
|
|
105
|
+
- Last indexing activity
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Supported File Types
|
|
110
|
+
|
|
111
|
+
| Extension | Parser |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `.pdf` | pdf-parse (per-page text) |
|
|
114
|
+
| `.docx` | mammoth |
|
|
115
|
+
| `.xlsx` | SheetJS |
|
|
116
|
+
| `.pptx` | adm-zip + XML parsing |
|
|
117
|
+
| `.txt` | fs.readFile |
|
|
118
|
+
| `.md` | fs.readFile |
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Architecture
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
localrag init / start
|
|
126
|
+
│
|
|
127
|
+
▼
|
|
128
|
+
FileScanner / FileWatcher (chokidar)
|
|
129
|
+
│
|
|
130
|
+
▼
|
|
131
|
+
Indexer (orchestrator)
|
|
132
|
+
├── Extractor (PDF / DOCX / XLSX / PPTX / TXT / MD)
|
|
133
|
+
├── ChunkingService (500-char overlapping windows)
|
|
134
|
+
├── EmbeddingService (Transformers.js, all-MiniLM-L6-v2)
|
|
135
|
+
└── LanceDbRepository (vector storage)
|
|
136
|
+
│
|
|
137
|
+
└── ~/.localrag/db/ (LanceDB)
|
|
138
|
+
|
|
139
|
+
localrag search
|
|
140
|
+
│
|
|
141
|
+
▼
|
|
142
|
+
SearchService
|
|
143
|
+
├── EmbeddingService (embed query)
|
|
144
|
+
└── LanceDbRepository (vector search)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Data stored in `~/.localrag/`:**
|
|
148
|
+
|
|
149
|
+
| File | Purpose |
|
|
150
|
+
|---|---|
|
|
151
|
+
| `config.json` | Watched folders, DB path |
|
|
152
|
+
| `documents.json` | Per-file metadata + chunk counts |
|
|
153
|
+
| `last-results.json` | Result cache for `open` command |
|
|
154
|
+
| `db/` | LanceDB vector store |
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Local-First Design
|
|
159
|
+
|
|
160
|
+
- No cloud services
|
|
161
|
+
- No API keys required
|
|
162
|
+
- All embeddings generated locally via ONNX runtime
|
|
163
|
+
- All vectors stored locally in LanceDB
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Extending
|
|
168
|
+
|
|
169
|
+
The extractor layer is designed for easy extension. To add a new file type:
|
|
170
|
+
|
|
171
|
+
1. Create `src/extractors/<type>-extractor.ts` implementing `Extractor`
|
|
172
|
+
2. Register it in `src/extractors/extractor.interface.ts`
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
MIT
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ExtractedChunk } from '../extractors/extractor.interface';
|
|
2
|
+
export interface TextChunk {
|
|
3
|
+
id: string;
|
|
4
|
+
filePath: string;
|
|
5
|
+
page: number;
|
|
6
|
+
text: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class ChunkingService {
|
|
9
|
+
/**
|
|
10
|
+
* Split an array of ExtractedChunks (from any extractor) into smaller,
|
|
11
|
+
* fixed-size overlapping TextChunks suitable for embedding.
|
|
12
|
+
*
|
|
13
|
+
* Each TextChunk retains the source page number from the ExtractedChunk it
|
|
14
|
+
* came from, enabling result display to show the right page.
|
|
15
|
+
*/
|
|
16
|
+
chunk(filePath: string, extracted: ExtractedChunk[]): TextChunk[];
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=chunking-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunking-service.d.ts","sourceRoot":"","sources":["../../src/chunking/chunking-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAInE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAeD,qBAAa,eAAe;IAC1B;;;;;;OAMG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,SAAS,EAAE;CAqBlE"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChunkingService = void 0;
|
|
4
|
+
// ── Config ────────────────────────────────────────────────────────────────
|
|
5
|
+
/** Target character count per chunk. */
|
|
6
|
+
const CHUNK_SIZE = 500;
|
|
7
|
+
/** Overlap between consecutive chunks (preserves context at boundaries). */
|
|
8
|
+
const CHUNK_OVERLAP = 100;
|
|
9
|
+
/** Minimum length to bother embedding. */
|
|
10
|
+
const MIN_CHUNK_LENGTH = 20;
|
|
11
|
+
// ── Service ───────────────────────────────────────────────────────────────
|
|
12
|
+
class ChunkingService {
|
|
13
|
+
/**
|
|
14
|
+
* Split an array of ExtractedChunks (from any extractor) into smaller,
|
|
15
|
+
* fixed-size overlapping TextChunks suitable for embedding.
|
|
16
|
+
*
|
|
17
|
+
* Each TextChunk retains the source page number from the ExtractedChunk it
|
|
18
|
+
* came from, enabling result display to show the right page.
|
|
19
|
+
*/
|
|
20
|
+
chunk(filePath, extracted) {
|
|
21
|
+
const results = [];
|
|
22
|
+
let globalIndex = 0;
|
|
23
|
+
for (const { text, page = 0 } of extracted) {
|
|
24
|
+
if (!text.trim())
|
|
25
|
+
continue;
|
|
26
|
+
const subTexts = splitText(text);
|
|
27
|
+
for (const sub of subTexts) {
|
|
28
|
+
if (sub.trim().length < MIN_CHUNK_LENGTH)
|
|
29
|
+
continue;
|
|
30
|
+
results.push({
|
|
31
|
+
id: `${filePath}::${globalIndex++}`,
|
|
32
|
+
filePath,
|
|
33
|
+
page,
|
|
34
|
+
text: sub.trim(),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return results;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.ChunkingService = ChunkingService;
|
|
42
|
+
// ── Helpers ───────────────────────────────────────────────────────────────
|
|
43
|
+
/**
|
|
44
|
+
* Split a long string into overlapping windows.
|
|
45
|
+
* Tries to break at whitespace boundaries to avoid cutting words.
|
|
46
|
+
*/
|
|
47
|
+
function splitText(text) {
|
|
48
|
+
if (text.length <= CHUNK_SIZE)
|
|
49
|
+
return [text];
|
|
50
|
+
const chunks = [];
|
|
51
|
+
let start = 0;
|
|
52
|
+
while (start < text.length) {
|
|
53
|
+
let end = start + CHUNK_SIZE;
|
|
54
|
+
if (end < text.length) {
|
|
55
|
+
// Extend to the next whitespace so we don't cut mid-word
|
|
56
|
+
const nextSpace = text.indexOf(' ', end);
|
|
57
|
+
if (nextSpace !== -1 && nextSpace - end < 50) {
|
|
58
|
+
end = nextSpace;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
end = text.length;
|
|
63
|
+
}
|
|
64
|
+
chunks.push(text.slice(start, end));
|
|
65
|
+
// Advance by (CHUNK_SIZE - CHUNK_OVERLAP), but always make progress
|
|
66
|
+
const advance = Math.max(1, CHUNK_SIZE - CHUNK_OVERLAP);
|
|
67
|
+
start += advance;
|
|
68
|
+
}
|
|
69
|
+
return chunks;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=chunking-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunking-service.js","sourceRoot":"","sources":["../../src/chunking/chunking-service.ts"],"names":[],"mappings":";;;AAWA,6EAA6E;AAE7E,wCAAwC;AACxC,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB,4EAA4E;AAC5E,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,0CAA0C;AAC1C,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B,6EAA6E;AAE7E,MAAa,eAAe;IAC1B;;;;;;OAMG;IACH,KAAK,CAAC,QAAgB,EAAE,SAA2B;QACjD,MAAM,OAAO,GAAgB,EAAE,CAAC;QAChC,IAAI,WAAW,GAAG,CAAC,CAAC;QAEpB,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,EAAE,IAAI,SAAS,EAAE,CAAC;YAC3C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;gBAAE,SAAS;YAE3B,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YACjC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,gBAAgB;oBAAE,SAAS;gBACnD,OAAO,CAAC,IAAI,CAAC;oBACX,EAAE,EAAE,GAAG,QAAQ,KAAK,WAAW,EAAE,EAAE;oBACnC,QAAQ;oBACR,IAAI;oBACJ,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE;iBACjB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AA7BD,0CA6BC;AAED,6EAA6E;AAE7E;;;GAGG;AACH,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,IAAI,CAAC,MAAM,IAAI,UAAU;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC3B,IAAI,GAAG,GAAG,KAAK,GAAG,UAAU,CAAC;QAE7B,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACtB,yDAAyD;YACzD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACzC,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,SAAS,GAAG,GAAG,GAAG,EAAE,EAAE,CAAC;gBAC7C,GAAG,GAAG,SAAS,CAAC;YAClB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC;QACpB,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QAEpC,oEAAoE;QACpE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC,CAAC;QACxD,KAAK,IAAI,OAAO,CAAC;IACnB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `localrag init <folder>`
|
|
3
|
+
*
|
|
4
|
+
* Adds the given folder to the watched list and immediately performs
|
|
5
|
+
* a full initial scan so results are available right away.
|
|
6
|
+
*/
|
|
7
|
+
export declare function initCommand(folder: string): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2D/D"}
|
|
@@ -0,0 +1,107 @@
|
|
|
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.initCommand = initCommand;
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
+
const ora_1 = __importDefault(require("ora"));
|
|
44
|
+
const config_service_1 = require("../../config/config-service");
|
|
45
|
+
const metadata_service_1 = require("../../metadata/metadata-service");
|
|
46
|
+
const lancedb_repository_1 = require("../../db/lancedb-repository");
|
|
47
|
+
const embedding_service_1 = require("../../embedding/embedding-service");
|
|
48
|
+
const indexer_1 = require("../../indexer/indexer");
|
|
49
|
+
const file_scanner_1 = require("../../scanner/file-scanner");
|
|
50
|
+
/**
|
|
51
|
+
* `localrag init <folder>`
|
|
52
|
+
*
|
|
53
|
+
* Adds the given folder to the watched list and immediately performs
|
|
54
|
+
* a full initial scan so results are available right away.
|
|
55
|
+
*/
|
|
56
|
+
async function initCommand(folder) {
|
|
57
|
+
const absFolder = path.resolve(folder);
|
|
58
|
+
// Validate folder
|
|
59
|
+
if (!fs.existsSync(absFolder)) {
|
|
60
|
+
console.error(chalk_1.default.red(`✗ Folder not found: ${absFolder}`));
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
if (!fs.statSync(absFolder).isDirectory()) {
|
|
64
|
+
console.error(chalk_1.default.red(`✗ Not a directory: ${absFolder}`));
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
const config = new config_service_1.ConfigService();
|
|
68
|
+
const added = config.addWatchedFolder(absFolder);
|
|
69
|
+
if (!added) {
|
|
70
|
+
console.log(chalk_1.default.yellow(`⚠ Folder already watched: ${absFolder}`));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
console.log(chalk_1.default.green(`✓ Added watched folder: ${absFolder}`));
|
|
74
|
+
}
|
|
75
|
+
// Initialise services
|
|
76
|
+
const repo = new lancedb_repository_1.LanceDbRepository();
|
|
77
|
+
await repo.initialize(config.getDbPath());
|
|
78
|
+
const metadata = new metadata_service_1.MetadataService(config);
|
|
79
|
+
const embedder = new embedding_service_1.EmbeddingService();
|
|
80
|
+
const indexer = new indexer_1.Indexer(config, repo, metadata, embedder);
|
|
81
|
+
const scanner = new file_scanner_1.FileScanner(metadata, indexer);
|
|
82
|
+
console.log(chalk_1.default.cyan('\n🔍 Starting initial scan…\n'));
|
|
83
|
+
const spinner = (0, ora_1.default)({ text: 'Scanning…', spinner: 'dots' }).start();
|
|
84
|
+
let indexed = 0;
|
|
85
|
+
let errors = 0;
|
|
86
|
+
const processed = await scanner.scan([absFolder], {
|
|
87
|
+
onProgress: (msg) => {
|
|
88
|
+
spinner.text = msg;
|
|
89
|
+
},
|
|
90
|
+
onError: (filePath, err) => {
|
|
91
|
+
spinner.warn(chalk_1.default.red(`Error: ${path.basename(filePath)} — ${err.message}`));
|
|
92
|
+
spinner.start();
|
|
93
|
+
errors++;
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
indexed = processed;
|
|
97
|
+
spinner.succeed(chalk_1.default.green(`Initial scan complete.`));
|
|
98
|
+
console.log('');
|
|
99
|
+
console.log(` ${chalk_1.default.bold('Indexed:')} ${chalk_1.default.cyan(indexed)} file(s)`);
|
|
100
|
+
if (errors > 0) {
|
|
101
|
+
console.log(` ${chalk_1.default.bold('Errors:')} ${chalk_1.default.red(errors)} file(s) skipped`);
|
|
102
|
+
}
|
|
103
|
+
console.log('');
|
|
104
|
+
console.log(chalk_1.default.dim(`Run ${chalk_1.default.white('localrag start')} to watch for changes.`));
|
|
105
|
+
console.log(chalk_1.default.dim(`Run ${chalk_1.default.white('localrag search "<query>"')} to search.`));
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `localrag open <N>`
|
|
3
|
+
*
|
|
4
|
+
* Opens the Nth result from the last `localrag search` run using the
|
|
5
|
+
* OS-default application (open / xdg-open / start).
|
|
6
|
+
*/
|
|
7
|
+
export declare function openCommand(resultNumber: string): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=open.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/open.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCrE"}
|
|
@@ -0,0 +1,105 @@
|
|
|
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.openCommand = openCommand;
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const childProcess = __importStar(require("child_process"));
|
|
42
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
+
const config_service_1 = require("../../config/config-service");
|
|
44
|
+
const search_service_1 = require("../../search/search-service");
|
|
45
|
+
const lancedb_repository_1 = require("../../db/lancedb-repository");
|
|
46
|
+
const embedding_service_1 = require("../../embedding/embedding-service");
|
|
47
|
+
/**
|
|
48
|
+
* `localrag open <N>`
|
|
49
|
+
*
|
|
50
|
+
* Opens the Nth result from the last `localrag search` run using the
|
|
51
|
+
* OS-default application (open / xdg-open / start).
|
|
52
|
+
*/
|
|
53
|
+
async function openCommand(resultNumber) {
|
|
54
|
+
const n = parseInt(resultNumber, 10);
|
|
55
|
+
if (isNaN(n) || n < 1) {
|
|
56
|
+
console.error(chalk_1.default.red('✗ Please provide a valid result number (e.g. localrag open 1).'));
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
const config = new config_service_1.ConfigService();
|
|
60
|
+
// SearchService exposes getLastResults() which reads last-results.json
|
|
61
|
+
const repo = new lancedb_repository_1.LanceDbRepository();
|
|
62
|
+
// We don't need a full DB connection just to read cached results,
|
|
63
|
+
// but SearchService requires a repo instance. We'll instantiate without
|
|
64
|
+
// calling initialize() to avoid the DB overhead.
|
|
65
|
+
const embedder = new embedding_service_1.EmbeddingService();
|
|
66
|
+
const searchService = new search_service_1.SearchService(config, repo, embedder);
|
|
67
|
+
const results = searchService.getLastResults();
|
|
68
|
+
if (results.length === 0) {
|
|
69
|
+
console.error(chalk_1.default.red('✗ No previous search results found.'));
|
|
70
|
+
console.log(chalk_1.default.dim(`Run ${chalk_1.default.white('localrag search "<query>"')} first.`));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
if (n > results.length) {
|
|
74
|
+
console.error(chalk_1.default.red(`✗ Result ${n} doesn't exist. Last search returned ${results.length} result(s).`));
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
const result = results[n - 1];
|
|
78
|
+
const filePath = result.filePath;
|
|
79
|
+
console.log(chalk_1.default.cyan(`Opening: ${path.basename(filePath)}`));
|
|
80
|
+
console.log(chalk_1.default.dim(filePath));
|
|
81
|
+
openFile(filePath);
|
|
82
|
+
}
|
|
83
|
+
// ── Helpers ───────────────────────────────────────────────────────────────
|
|
84
|
+
function openFile(filePath) {
|
|
85
|
+
const platform = process.platform;
|
|
86
|
+
let cmd;
|
|
87
|
+
if (platform === 'darwin') {
|
|
88
|
+
cmd = `open "${escapePath(filePath)}"`;
|
|
89
|
+
}
|
|
90
|
+
else if (platform === 'win32') {
|
|
91
|
+
cmd = `start "" "${escapePath(filePath)}"`;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
cmd = `xdg-open "${escapePath(filePath)}"`;
|
|
95
|
+
}
|
|
96
|
+
childProcess.exec(cmd, (err) => {
|
|
97
|
+
if (err) {
|
|
98
|
+
console.error(chalk_1.default.red(`✗ Failed to open file: ${err.message}`));
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function escapePath(p) {
|
|
103
|
+
return p.replace(/"/g, '\\"');
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=open.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../../src/cli/commands/open.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `localrag search "<query>"`
|
|
3
|
+
*
|
|
4
|
+
* Embeds the query, runs vector search, and displays ranked results.
|
|
5
|
+
* Results are also saved so `localrag open <N>` can open them by index.
|
|
6
|
+
*/
|
|
7
|
+
export declare function searchCommand(query: string, options: {
|
|
8
|
+
top?: string;
|
|
9
|
+
}): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/search.ts"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqE3F"}
|
|
@@ -0,0 +1,73 @@
|
|
|
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.searchCommand = searchCommand;
|
|
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 lancedb_repository_1 = require("../../db/lancedb-repository");
|
|
11
|
+
const embedding_service_1 = require("../../embedding/embedding-service");
|
|
12
|
+
const search_service_1 = require("../../search/search-service");
|
|
13
|
+
/**
|
|
14
|
+
* `localrag search "<query>"`
|
|
15
|
+
*
|
|
16
|
+
* Embeds the query, runs vector search, and displays ranked results.
|
|
17
|
+
* Results are also saved so `localrag open <N>` can open them by index.
|
|
18
|
+
*/
|
|
19
|
+
async function searchCommand(query, options) {
|
|
20
|
+
const topK = options.top ? parseInt(options.top, 10) : 10;
|
|
21
|
+
if (!query.trim()) {
|
|
22
|
+
console.error(chalk_1.default.red('✗ Query cannot be empty.'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
const config = new config_service_1.ConfigService();
|
|
26
|
+
if (config.getWatchedFolders().length === 0) {
|
|
27
|
+
console.error(chalk_1.default.red('✗ No folders indexed yet.'));
|
|
28
|
+
console.log(chalk_1.default.dim(`Run ${chalk_1.default.white('localrag init <folder>')} first.`));
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
const repo = new lancedb_repository_1.LanceDbRepository();
|
|
32
|
+
await repo.initialize(config.getDbPath());
|
|
33
|
+
const embedder = new embedding_service_1.EmbeddingService();
|
|
34
|
+
const searchService = new search_service_1.SearchService(config, repo, embedder);
|
|
35
|
+
const spinner = (0, ora_1.default)({ text: `Searching for "${query}"…`, spinner: 'dots' }).start();
|
|
36
|
+
let results;
|
|
37
|
+
try {
|
|
38
|
+
results = await searchService.search(query, topK);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
spinner.fail('Search failed.');
|
|
42
|
+
console.error(chalk_1.default.red((err instanceof Error ? err.message : String(err))));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
spinner.stop();
|
|
46
|
+
if (results.length === 0) {
|
|
47
|
+
console.log(chalk_1.default.yellow('\n No results found.\n'));
|
|
48
|
+
console.log(chalk_1.default.dim(' Try indexing more documents with: localrag init <folder>'));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// ── Display results ────────────────────────────────────────────────────
|
|
52
|
+
console.log('');
|
|
53
|
+
console.log(chalk_1.default.bold.cyan(` Search results for: `) + chalk_1.default.bold.white(`"${query}"`) +
|
|
54
|
+
chalk_1.default.dim(` (top ${results.length})`));
|
|
55
|
+
console.log('');
|
|
56
|
+
results.forEach((result, idx) => {
|
|
57
|
+
const num = chalk_1.default.bold.cyan(` [${idx + 1}]`);
|
|
58
|
+
const fileName = chalk_1.default.bold.white(result.fileName);
|
|
59
|
+
const filePath = chalk_1.default.dim(result.filePath);
|
|
60
|
+
const page = result.page > 0
|
|
61
|
+
? chalk_1.default.dim(` Page ${result.page}`)
|
|
62
|
+
: '';
|
|
63
|
+
const score = chalk_1.default.green(` Score: ${(result.score * 100).toFixed(1)}%`);
|
|
64
|
+
const snippet = chalk_1.default.white(` ${result.text}`);
|
|
65
|
+
console.log(`${num} ${fileName}${page}${score}`);
|
|
66
|
+
console.log(` ${filePath}`);
|
|
67
|
+
console.log(` ${snippet}`);
|
|
68
|
+
console.log('');
|
|
69
|
+
});
|
|
70
|
+
console.log(chalk_1.default.dim(` Run ${chalk_1.default.white('localrag open <N>')} to open a result.`));
|
|
71
|
+
console.log('');
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/cli/commands/search.ts"],"names":[],"mappings":";;;;;AAgBA,sCAqEC;AApFD,kDAA0B;AAC1B,8CAAsB;AAEtB,gEAA4D;AAC5D,oEAAgE;AAChE,yEAAqE;AACrE,gEAA4D;AAG5D;;;;;GAKG;AACI,KAAK,UAAU,aAAa,CAAC,KAAa,EAAE,OAAyB;IAC1E,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE1D,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,8BAAa,EAAE,CAAC;IAEnC,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5C,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,OAAO,eAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,SAAS,CAAC,CAAC,CAAC;QAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,sCAAiB,EAAE,CAAC;IACrC,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IAE1C,MAAM,QAAQ,GAAG,IAAI,oCAAgB,EAAE,CAAC;IACxC,MAAM,aAAa,GAAG,IAAI,8BAAa,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAEhE,MAAM,OAAO,GAAG,IAAA,aAAG,EAAC,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAEpF,IAAI,OAAuB,CAAC;IAE5B,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,IAAI,EAAE,CAAC;IAEf,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,yBAAyB,CAAC,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC,CAAC;QACrF,OAAO;IACT,CAAC;IAED,0EAA0E;IAE1E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CACT,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,GAAG,eAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;QAC1E,eAAK,CAAC,GAAG,CAAC,UAAU,OAAO,CAAC,MAAM,GAAG,CAAC,CACvC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QAC9B,MAAM,GAAG,GAAG,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,eAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,eAAK,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,GAAG,CAAC;YAC1B,CAAC,CAAC,eAAK,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,IAAI,EAAE,CAAC;YACpC,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,KAAK,GAAG,eAAK,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC1E,MAAM,OAAO,GAAG,eAAK,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAEhD,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,QAAQ,GAAG,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,QAAQ,QAAQ,EAAE,CAAC,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,QAAQ,OAAO,EAAE,CAAC,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,SAAS,eAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACtF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `localrag start`
|
|
3
|
+
*
|
|
4
|
+
* Performs a startup scan to catch missed changes, then starts a persistent
|
|
5
|
+
* file watcher to keep the index up-to-date in real time.
|
|
6
|
+
*/
|
|
7
|
+
export declare function startCommand(): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=start.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA8ElD"}
|