@ixxrllg/localmind 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/LICENSE +21 -0
- package/README.md +290 -0
- package/dist/ask/answer.d.ts +9 -0
- package/dist/ask/answer.d.ts.map +1 -0
- package/dist/ask/answer.js +183 -0
- package/dist/ask/answer.js.map +1 -0
- package/dist/bin/localmind.d.ts +3 -0
- package/dist/bin/localmind.d.ts.map +1 -0
- package/dist/bin/localmind.js +11 -0
- package/dist/bin/localmind.js.map +1 -0
- package/dist/cli/format.d.ts +7 -0
- package/dist/cli/format.d.ts.map +1 -0
- package/dist/cli/format.js +67 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/program.d.ts +4 -0
- package/dist/cli/program.d.ts.map +1 -0
- package/dist/cli/program.js +228 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/core/config.d.ts +17 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +55 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/db.d.ts +50 -0
- package/dist/core/db.d.ts.map +1 -0
- package/dist/core/db.js +180 -0
- package/dist/core/db.js.map +1 -0
- package/dist/core/hash.d.ts +3 -0
- package/dist/core/hash.d.ts.map +1 -0
- package/dist/core/hash.js +8 -0
- package/dist/core/hash.js.map +1 -0
- package/dist/core/logger.d.ts +12 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +45 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/paths.d.ts +16 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +43 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/graph/related.d.ts +11 -0
- package/dist/graph/related.d.ts.map +1 -0
- package/dist/graph/related.js +144 -0
- package/dist/graph/related.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/chunker.d.ts +16 -0
- package/dist/indexer/chunker.d.ts.map +1 -0
- package/dist/indexer/chunker.js +76 -0
- package/dist/indexer/chunker.js.map +1 -0
- package/dist/indexer/ignore.d.ts +6 -0
- package/dist/indexer/ignore.d.ts.map +1 -0
- package/dist/indexer/ignore.js +71 -0
- package/dist/indexer/ignore.js.map +1 -0
- package/dist/indexer/indexer.d.ts +11 -0
- package/dist/indexer/indexer.d.ts.map +1 -0
- package/dist/indexer/indexer.js +182 -0
- package/dist/indexer/indexer.js.map +1 -0
- package/dist/indexer/languages.d.ts +5 -0
- package/dist/indexer/languages.d.ts.map +1 -0
- package/dist/indexer/languages.js +144 -0
- package/dist/indexer/languages.js.map +1 -0
- package/dist/indexer/relations.d.ts +9 -0
- package/dist/indexer/relations.d.ts.map +1 -0
- package/dist/indexer/relations.js +81 -0
- package/dist/indexer/relations.js.map +1 -0
- package/dist/indexer/walker.d.ts +21 -0
- package/dist/indexer/walker.d.ts.map +1 -0
- package/dist/indexer/walker.js +86 -0
- package/dist/indexer/walker.js.map +1 -0
- package/dist/mcp/server.d.ts +5 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +291 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/search/bm25.d.ts +9 -0
- package/dist/search/bm25.d.ts.map +1 -0
- package/dist/search/bm25.js +109 -0
- package/dist/search/bm25.js.map +1 -0
- package/dist/search/embeddings.d.ts +15 -0
- package/dist/search/embeddings.d.ts.map +1 -0
- package/dist/search/embeddings.js +193 -0
- package/dist/search/embeddings.js.map +1 -0
- package/dist/search/search.d.ts +9 -0
- package/dist/search/search.d.ts.map +1 -0
- package/dist/search/search.js +47 -0
- package/dist/search/search.js.map +1 -0
- package/dist/search/tokenize.d.ts +6 -0
- package/dist/search/tokenize.d.ts.map +1 -0
- package/dist/search/tokenize.js +163 -0
- package/dist/search/tokenize.js.map +1 -0
- package/dist/status.d.ts +4 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +33 -0
- package/dist/status.js.map +1 -0
- package/dist/types.d.ts +105 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5B,MAAM,WAAW,GAA6B;IAC5C,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;IACT,MAAM,EAAE,GAAG;CACZ,CAAC;AAEF,IAAI,YAAY,GAAa,MAAM,CAAC;AAEpC,MAAM,UAAU,WAAW,CAAC,KAAe;IACzC,YAAY,GAAG,KAAK,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,SAAS,SAAS,CAAC,KAAe;IAChC,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,YAAY,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,KAAK,CAAC,OAAe;QACnB,IAAI,SAAS,CAAC,OAAO,CAAC;YAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,CAAC,OAAe;QAClB,IAAI,SAAS,CAAC,MAAM,CAAC;YAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,OAAO,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,CAAC,OAAe;QACrB,IAAI,SAAS,CAAC,MAAM,CAAC;YAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,OAAO,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,CAAC,OAAe;QAClB,IAAI,SAAS,CAAC,MAAM,CAAC;YAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,OAAO,CAAC,CAAC;IACvE,CAAC;IACD,KAAK,CAAC,OAAe;QACnB,IAAI,SAAS,CAAC,OAAO,CAAC;YAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,OAAO,CAAC,CAAC;IACrE,CAAC;IACD,KAAK,CAAC,OAAe;QACnB,IAAI,SAAS,CAAC,MAAM,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const LOCALMIND_DIR = ".localmind";
|
|
2
|
+
export declare const CONFIG_FILE = "config.json";
|
|
3
|
+
export declare const DB_FILE = "localmind.db";
|
|
4
|
+
/** Normalize to posix-style relative path (stable across OS). */
|
|
5
|
+
export declare function toPosix(p: string): string;
|
|
6
|
+
/** Resolve and normalize an absolute path. */
|
|
7
|
+
export declare function resolveRoot(input?: string): string;
|
|
8
|
+
export declare function localmindDir(root: string): string;
|
|
9
|
+
export declare function configPath(root: string): string;
|
|
10
|
+
export declare function dbPath(root: string): string;
|
|
11
|
+
export declare function ensureLocalmindDir(root: string): string;
|
|
12
|
+
/** Relative posix path of absPath under root, or null if outside. */
|
|
13
|
+
export declare function relativePosix(root: string, absPath: string): string | null;
|
|
14
|
+
export declare function absFromRelative(root: string, relPosix: string): string;
|
|
15
|
+
export declare function isInitialized(root: string): boolean;
|
|
16
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,aAAa,eAAe,CAAC;AAC1C,eAAO,MAAM,WAAW,gBAAgB,CAAC;AACzC,eAAO,MAAM,OAAO,iBAAiB,CAAC;AAEtC,iEAAiE;AACjE,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED,8CAA8C;AAC9C,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIvD;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM1E;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGtE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export const LOCALMIND_DIR = ".localmind";
|
|
4
|
+
export const CONFIG_FILE = "config.json";
|
|
5
|
+
export const DB_FILE = "localmind.db";
|
|
6
|
+
/** Normalize to posix-style relative path (stable across OS). */
|
|
7
|
+
export function toPosix(p) {
|
|
8
|
+
return p.replace(/\\/g, "/");
|
|
9
|
+
}
|
|
10
|
+
/** Resolve and normalize an absolute path. */
|
|
11
|
+
export function resolveRoot(input) {
|
|
12
|
+
return path.resolve(input ?? process.cwd());
|
|
13
|
+
}
|
|
14
|
+
export function localmindDir(root) {
|
|
15
|
+
return path.join(root, LOCALMIND_DIR);
|
|
16
|
+
}
|
|
17
|
+
export function configPath(root) {
|
|
18
|
+
return path.join(localmindDir(root), CONFIG_FILE);
|
|
19
|
+
}
|
|
20
|
+
export function dbPath(root) {
|
|
21
|
+
return path.join(localmindDir(root), DB_FILE);
|
|
22
|
+
}
|
|
23
|
+
export function ensureLocalmindDir(root) {
|
|
24
|
+
const dir = localmindDir(root);
|
|
25
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
26
|
+
return dir;
|
|
27
|
+
}
|
|
28
|
+
/** Relative posix path of absPath under root, or null if outside. */
|
|
29
|
+
export function relativePosix(root, absPath) {
|
|
30
|
+
const rel = path.relative(root, absPath);
|
|
31
|
+
if (!rel || rel.startsWith("..") || path.isAbsolute(rel)) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return toPosix(rel);
|
|
35
|
+
}
|
|
36
|
+
export function absFromRelative(root, relPosix) {
|
|
37
|
+
const parts = relPosix.split("/").filter(Boolean);
|
|
38
|
+
return path.join(root, ...parts);
|
|
39
|
+
}
|
|
40
|
+
export function isInitialized(root) {
|
|
41
|
+
return fs.existsSync(configPath(root)) && fs.existsSync(dbPath(root));
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,aAAa,GAAG,YAAY,CAAC;AAC1C,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC;AACzC,MAAM,CAAC,MAAM,OAAO,GAAG,cAAc,CAAC;AAEtC,iEAAiE;AACjE,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/B,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAAe;IACzD,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,QAAgB;IAC5D,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Db } from "../core/db.js";
|
|
2
|
+
import type { RelatedFile } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Find files related via import/link graph edges.
|
|
5
|
+
*/
|
|
6
|
+
export declare function findRelatedFiles(db: Db, pathOrFragment: string, limit?: number): RelatedFile[];
|
|
7
|
+
export declare function listGraphStats(db: Db): {
|
|
8
|
+
edges: number;
|
|
9
|
+
filesWithEdges: number;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=related.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"related.d.ts","sourceRoot":"","sources":["../../src/graph/related.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,EAAE,EACN,cAAc,EAAE,MAAM,EACtB,KAAK,SAAK,GACT,WAAW,EAAE,CA4Gf;AA+DD,wBAAgB,cAAc,CAAC,EAAE,EAAE,EAAE,GAAG;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;CACxB,CAQA"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find files related via import/link graph edges.
|
|
3
|
+
*/
|
|
4
|
+
export function findRelatedFiles(db, pathOrFragment, limit = 15) {
|
|
5
|
+
const q = pathOrFragment.trim().replace(/\\/g, "/");
|
|
6
|
+
if (!q)
|
|
7
|
+
return [];
|
|
8
|
+
const files = db
|
|
9
|
+
.prepare(`SELECT id, path FROM files
|
|
10
|
+
WHERE path = ? OR path LIKE ? OR path LIKE ?
|
|
11
|
+
ORDER BY CASE WHEN path = ? THEN 0 ELSE 1 END, length(path)
|
|
12
|
+
LIMIT 20`)
|
|
13
|
+
.all(q, `%/${q}`, `%${q}%`, q);
|
|
14
|
+
const scores = new Map();
|
|
15
|
+
const bump = (path, relation, amount) => {
|
|
16
|
+
const prev = scores.get(path);
|
|
17
|
+
scores.set(path, {
|
|
18
|
+
path,
|
|
19
|
+
relation: prev ? `${prev.relation}, ${relation}` : relation,
|
|
20
|
+
score: (prev?.score ?? 0) + amount,
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
const seedPaths = new Set(files.map((f) => f.path));
|
|
24
|
+
// If no file matched, still search edges by raw target fragment
|
|
25
|
+
if (!files.length) {
|
|
26
|
+
const edges = db
|
|
27
|
+
.prepare(`SELECT f.path AS source_path, e.target_path AS target_path, e.relation AS relation
|
|
28
|
+
FROM edges e
|
|
29
|
+
JOIN files f ON f.id = e.source_file_id
|
|
30
|
+
WHERE e.target_path LIKE ?
|
|
31
|
+
LIMIT ?`)
|
|
32
|
+
.all(`%${q}%`, limit);
|
|
33
|
+
return edges.map((e, i) => ({
|
|
34
|
+
path: e.source_path,
|
|
35
|
+
relation: `${e.relation} → ${e.target_path}`,
|
|
36
|
+
score: 1 / (i + 1),
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
// Outgoing edges from matched files
|
|
40
|
+
for (const file of files) {
|
|
41
|
+
const outgoing = db
|
|
42
|
+
.prepare(`SELECT target_path, relation FROM edges WHERE source_file_id = ?`)
|
|
43
|
+
.all(file.id);
|
|
44
|
+
for (const e of outgoing) {
|
|
45
|
+
const resolved = resolveImportToFile(db, file.path, e.target_path);
|
|
46
|
+
const key = resolved ?? e.target_path;
|
|
47
|
+
if (seedPaths.has(key))
|
|
48
|
+
continue;
|
|
49
|
+
bump(key, e.relation, 1);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Incoming: any file whose resolved import points at a seed file
|
|
53
|
+
const allEdges = db
|
|
54
|
+
.prepare(`SELECT f.path AS source_path, e.target_path AS target_path, e.relation AS relation
|
|
55
|
+
FROM edges e
|
|
56
|
+
JOIN files f ON f.id = e.source_file_id`)
|
|
57
|
+
.all();
|
|
58
|
+
for (const e of allEdges) {
|
|
59
|
+
if (seedPaths.has(e.source_path))
|
|
60
|
+
continue;
|
|
61
|
+
const resolved = resolveImportToFile(db, e.source_path, e.target_path);
|
|
62
|
+
if (resolved && seedPaths.has(resolved)) {
|
|
63
|
+
bump(e.source_path, `imported_by (${e.relation})`, 1.2);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// Fallback: basename / path fragment match on unresolved targets
|
|
67
|
+
for (const seed of seedPaths) {
|
|
68
|
+
const base = fileStem(seed);
|
|
69
|
+
const target = e.target_path.replace(/\\/g, "/");
|
|
70
|
+
if (target.includes(seed) ||
|
|
71
|
+
target.endsWith(base) ||
|
|
72
|
+
target.endsWith(`${base}.js`) ||
|
|
73
|
+
target.endsWith(`${base}.ts`) ||
|
|
74
|
+
target.endsWith(`/${base}`) ||
|
|
75
|
+
target.endsWith(`/${base}.js`) ||
|
|
76
|
+
target.endsWith(`/${base}.ts`)) {
|
|
77
|
+
bump(e.source_path, `imported_by (${e.relation})`, 1.0);
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return [...scores.values()]
|
|
83
|
+
.sort((a, b) => b.score - a.score)
|
|
84
|
+
.slice(0, limit);
|
|
85
|
+
}
|
|
86
|
+
function fileStem(filePath) {
|
|
87
|
+
const base = filePath.includes("/")
|
|
88
|
+
? filePath.slice(filePath.lastIndexOf("/") + 1)
|
|
89
|
+
: filePath;
|
|
90
|
+
const dot = base.lastIndexOf(".");
|
|
91
|
+
return dot > 0 ? base.slice(0, dot) : base;
|
|
92
|
+
}
|
|
93
|
+
function resolveImportToFile(db, fromPath, target) {
|
|
94
|
+
// Only resolve relative imports
|
|
95
|
+
if (!target.startsWith("."))
|
|
96
|
+
return null;
|
|
97
|
+
const fromDir = fromPath.includes("/")
|
|
98
|
+
? fromPath.slice(0, fromPath.lastIndexOf("/"))
|
|
99
|
+
: "";
|
|
100
|
+
const joined = normalizeRel(`${fromDir}/${target}`);
|
|
101
|
+
const withoutExt = joined.replace(/\.(js|jsx|mjs|cjs|ts|tsx)$/i, "");
|
|
102
|
+
const candidates = [
|
|
103
|
+
joined,
|
|
104
|
+
withoutExt,
|
|
105
|
+
`${withoutExt}.ts`,
|
|
106
|
+
`${withoutExt}.tsx`,
|
|
107
|
+
`${withoutExt}.js`,
|
|
108
|
+
`${withoutExt}.jsx`,
|
|
109
|
+
`${withoutExt}.mjs`,
|
|
110
|
+
`${withoutExt}.cjs`,
|
|
111
|
+
`${withoutExt}.json`,
|
|
112
|
+
`${withoutExt}/index.ts`,
|
|
113
|
+
`${withoutExt}/index.js`,
|
|
114
|
+
`${withoutExt}/index.tsx`,
|
|
115
|
+
];
|
|
116
|
+
for (const c of candidates) {
|
|
117
|
+
const row = db.prepare(`SELECT path FROM files WHERE path = ?`).get(c);
|
|
118
|
+
if (row)
|
|
119
|
+
return row.path;
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
function normalizeRel(p) {
|
|
124
|
+
const parts = p.replace(/\\/g, "/").split("/");
|
|
125
|
+
const stack = [];
|
|
126
|
+
for (const part of parts) {
|
|
127
|
+
if (!part || part === ".")
|
|
128
|
+
continue;
|
|
129
|
+
if (part === "..") {
|
|
130
|
+
stack.pop();
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
stack.push(part);
|
|
134
|
+
}
|
|
135
|
+
return stack.join("/");
|
|
136
|
+
}
|
|
137
|
+
export function listGraphStats(db) {
|
|
138
|
+
const edges = db.prepare(`SELECT COUNT(*) AS c FROM edges`).get();
|
|
139
|
+
const files = db
|
|
140
|
+
.prepare(`SELECT COUNT(DISTINCT source_file_id) AS c FROM edges`)
|
|
141
|
+
.get();
|
|
142
|
+
return { edges: Number(edges.c), filesWithEdges: Number(files.c) };
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=related.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"related.js","sourceRoot":"","sources":["../../src/graph/related.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalMind public API — use from scripts or embed in tools.
|
|
3
|
+
*/
|
|
4
|
+
export { ask } from "./ask/answer.js";
|
|
5
|
+
export { createDefaultConfig, detectProviderFromEnv, initConfig, loadConfig, saveConfig, } from "./core/config.js";
|
|
6
|
+
export { closeDb, openDb } from "./core/db.js";
|
|
7
|
+
export { configPath, dbPath, isInitialized, localmindDir, resolveRoot, } from "./core/paths.js";
|
|
8
|
+
export { findRelatedFiles } from "./graph/related.js";
|
|
9
|
+
export { chunkText } from "./indexer/chunker.js";
|
|
10
|
+
export { runIndex } from "./indexer/indexer.js";
|
|
11
|
+
export { startMcpServer } from "./mcp/server.js";
|
|
12
|
+
export { search } from "./search/search.js";
|
|
13
|
+
export { bm25Search } from "./search/bm25.js";
|
|
14
|
+
export { tokenize } from "./search/tokenize.js";
|
|
15
|
+
export { formatBytes, getStatus } from "./status.js";
|
|
16
|
+
export type { AskResult, IndexStats, LocalMindConfig, ProviderKind, RelatedFile, SearchHit, SearchMode, StatusInfo, } from "./types.js";
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACtC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,UAAU,EACV,UAAU,EACV,UAAU,GACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EACL,UAAU,EACV,MAAM,EACN,aAAa,EACb,YAAY,EACZ,WAAW,GACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACrD,YAAY,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,YAAY,EACZ,WAAW,EACX,SAAS,EACT,UAAU,EACV,UAAU,GACX,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalMind public API — use from scripts or embed in tools.
|
|
3
|
+
*/
|
|
4
|
+
export { ask } from "./ask/answer.js";
|
|
5
|
+
export { createDefaultConfig, detectProviderFromEnv, initConfig, loadConfig, saveConfig, } from "./core/config.js";
|
|
6
|
+
export { closeDb, openDb } from "./core/db.js";
|
|
7
|
+
export { configPath, dbPath, isInitialized, localmindDir, resolveRoot, } from "./core/paths.js";
|
|
8
|
+
export { findRelatedFiles } from "./graph/related.js";
|
|
9
|
+
export { chunkText } from "./indexer/chunker.js";
|
|
10
|
+
export { runIndex } from "./indexer/indexer.js";
|
|
11
|
+
export { startMcpServer } from "./mcp/server.js";
|
|
12
|
+
export { search } from "./search/search.js";
|
|
13
|
+
export { bm25Search } from "./search/bm25.js";
|
|
14
|
+
export { tokenize } from "./search/tokenize.js";
|
|
15
|
+
export { formatBytes, getStatus } from "./status.js";
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACtC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,UAAU,EACV,UAAU,EACV,UAAU,GACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EACL,UAAU,EACV,MAAM,EACN,aAAa,EACb,YAAY,EACZ,WAAW,GACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface TextChunk {
|
|
2
|
+
chunkIndex: number;
|
|
3
|
+
startLine: number;
|
|
4
|
+
endLine: number;
|
|
5
|
+
content: string;
|
|
6
|
+
contentHash: string;
|
|
7
|
+
tokenCount: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Split source into overlapping line-aware chunks.
|
|
11
|
+
* Prefers breaking on blank lines near the soft limit.
|
|
12
|
+
*/
|
|
13
|
+
export declare function chunkText(text: string, chunkSize: number, chunkOverlap: number): TextChunk[];
|
|
14
|
+
/** Rough token estimate (~4 chars / token for code). */
|
|
15
|
+
export declare function estimateTokens(text: string): number;
|
|
16
|
+
//# sourceMappingURL=chunker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunker.d.ts","sourceRoot":"","sources":["../../src/indexer/chunker.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,SAAS,EAAE,CAqEb;AAED,wDAAwD;AACxD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { sha256 } from "../core/hash.js";
|
|
2
|
+
/**
|
|
3
|
+
* Split source into overlapping line-aware chunks.
|
|
4
|
+
* Prefers breaking on blank lines near the soft limit.
|
|
5
|
+
*/
|
|
6
|
+
export function chunkText(text, chunkSize, chunkOverlap) {
|
|
7
|
+
const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
8
|
+
if (!normalized.trim())
|
|
9
|
+
return [];
|
|
10
|
+
const lines = normalized.split("\n");
|
|
11
|
+
const chunks = [];
|
|
12
|
+
let startIdx = 0;
|
|
13
|
+
let chunkIndex = 0;
|
|
14
|
+
while (startIdx < lines.length) {
|
|
15
|
+
let charCount = 0;
|
|
16
|
+
let endIdx = startIdx;
|
|
17
|
+
while (endIdx < lines.length) {
|
|
18
|
+
const lineLen = (lines[endIdx]?.length ?? 0) + 1;
|
|
19
|
+
if (endIdx > startIdx && charCount + lineLen > chunkSize)
|
|
20
|
+
break;
|
|
21
|
+
charCount += lineLen;
|
|
22
|
+
endIdx++;
|
|
23
|
+
// hard ceiling for pathological long lines
|
|
24
|
+
if (charCount >= chunkSize * 1.5)
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
if (endIdx === startIdx) {
|
|
28
|
+
// Single enormous line — force include
|
|
29
|
+
endIdx = startIdx + 1;
|
|
30
|
+
}
|
|
31
|
+
// Prefer blank-line boundary in the second half of the chunk
|
|
32
|
+
if (endIdx < lines.length) {
|
|
33
|
+
const windowStart = startIdx + Math.floor((endIdx - startIdx) * 0.5);
|
|
34
|
+
for (let i = endIdx - 1; i >= windowStart; i--) {
|
|
35
|
+
if ((lines[i] ?? "").trim() === "") {
|
|
36
|
+
endIdx = i + 1;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const slice = lines.slice(startIdx, endIdx).join("\n");
|
|
42
|
+
const content = slice.trimEnd();
|
|
43
|
+
if (content.trim().length > 0) {
|
|
44
|
+
chunks.push({
|
|
45
|
+
chunkIndex,
|
|
46
|
+
startLine: startIdx + 1,
|
|
47
|
+
endLine: endIdx,
|
|
48
|
+
content,
|
|
49
|
+
contentHash: sha256(content),
|
|
50
|
+
tokenCount: estimateTokens(content),
|
|
51
|
+
});
|
|
52
|
+
chunkIndex++;
|
|
53
|
+
}
|
|
54
|
+
if (endIdx >= lines.length)
|
|
55
|
+
break;
|
|
56
|
+
// Overlap: step back enough lines to cover ~chunkOverlap chars
|
|
57
|
+
let overlapChars = 0;
|
|
58
|
+
let nextStart = endIdx;
|
|
59
|
+
for (let i = endIdx - 1; i > startIdx; i--) {
|
|
60
|
+
overlapChars += (lines[i]?.length ?? 0) + 1;
|
|
61
|
+
nextStart = i;
|
|
62
|
+
if (overlapChars >= chunkOverlap)
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
// Always advance to avoid infinite loop
|
|
66
|
+
if (nextStart <= startIdx)
|
|
67
|
+
nextStart = startIdx + 1;
|
|
68
|
+
startIdx = nextStart;
|
|
69
|
+
}
|
|
70
|
+
return chunks;
|
|
71
|
+
}
|
|
72
|
+
/** Rough token estimate (~4 chars / token for code). */
|
|
73
|
+
export function estimateTokens(text) {
|
|
74
|
+
return Math.max(1, Math.ceil(text.length / 4));
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=chunker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunker.js","sourceRoot":"","sources":["../../src/indexer/chunker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Ignore } from "ignore";
|
|
2
|
+
/** Always-excluded paths — never index LocalMind state or common junk. */
|
|
3
|
+
export declare const DEFAULT_EXCLUDES: string[];
|
|
4
|
+
export declare function buildIgnoreFilter(root: string, extraExclude?: string[]): Ignore;
|
|
5
|
+
export declare function shouldIgnore(ig: Ignore, relPosix: string, isDirectory?: boolean): boolean;
|
|
6
|
+
//# sourceMappingURL=ignore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore.d.ts","sourceRoot":"","sources":["../../src/indexer/ignore.ts"],"names":[],"mappings":"AAEA,OAAe,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAG7C,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,UAwC5B,CAAC;AAWF,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,YAAY,GAAE,MAAM,EAAO,GAC1B,MAAM,CAWR;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,OAAO,CAGvF"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import ignore, {} from "ignore";
|
|
4
|
+
import { toPosix } from "../core/paths.js";
|
|
5
|
+
/** Always-excluded paths — never index LocalMind state or common junk. */
|
|
6
|
+
export const DEFAULT_EXCLUDES = [
|
|
7
|
+
".localmind/",
|
|
8
|
+
".git/",
|
|
9
|
+
".svn/",
|
|
10
|
+
".hg/",
|
|
11
|
+
"node_modules/",
|
|
12
|
+
"dist/",
|
|
13
|
+
"build/",
|
|
14
|
+
"out/",
|
|
15
|
+
"target/",
|
|
16
|
+
"coverage/",
|
|
17
|
+
".next/",
|
|
18
|
+
".nuxt/",
|
|
19
|
+
".output/",
|
|
20
|
+
".turbo/",
|
|
21
|
+
".cache/",
|
|
22
|
+
".venv/",
|
|
23
|
+
"venv/",
|
|
24
|
+
"__pycache__/",
|
|
25
|
+
".pytest_cache/",
|
|
26
|
+
".mypy_cache/",
|
|
27
|
+
".tox/",
|
|
28
|
+
".idea/",
|
|
29
|
+
".vscode/",
|
|
30
|
+
"*.min.js",
|
|
31
|
+
"*.min.css",
|
|
32
|
+
"*.map",
|
|
33
|
+
"*.lock",
|
|
34
|
+
"package-lock.json",
|
|
35
|
+
"yarn.lock",
|
|
36
|
+
"pnpm-lock.yaml",
|
|
37
|
+
"bun.lockb",
|
|
38
|
+
"Cargo.lock",
|
|
39
|
+
"poetry.lock",
|
|
40
|
+
"composer.lock",
|
|
41
|
+
"*.db",
|
|
42
|
+
"*.sqlite",
|
|
43
|
+
"*.sqlite3",
|
|
44
|
+
".DS_Store",
|
|
45
|
+
"Thumbs.db",
|
|
46
|
+
];
|
|
47
|
+
function readIgnoreFile(filePath) {
|
|
48
|
+
if (!fs.existsSync(filePath))
|
|
49
|
+
return [];
|
|
50
|
+
return fs
|
|
51
|
+
.readFileSync(filePath, "utf8")
|
|
52
|
+
.split(/\r?\n/)
|
|
53
|
+
.map((l) => l.trim())
|
|
54
|
+
.filter((l) => l.length > 0 && !l.startsWith("#"));
|
|
55
|
+
}
|
|
56
|
+
export function buildIgnoreFilter(root, extraExclude = []) {
|
|
57
|
+
const ig = ignore();
|
|
58
|
+
ig.add(DEFAULT_EXCLUDES);
|
|
59
|
+
ig.add(extraExclude);
|
|
60
|
+
for (const name of [".gitignore", ".localmindignore"]) {
|
|
61
|
+
const patterns = readIgnoreFile(path.join(root, name));
|
|
62
|
+
if (patterns.length)
|
|
63
|
+
ig.add(patterns);
|
|
64
|
+
}
|
|
65
|
+
return ig;
|
|
66
|
+
}
|
|
67
|
+
export function shouldIgnore(ig, relPosix, isDirectory = false) {
|
|
68
|
+
const candidate = isDirectory && !relPosix.endsWith("/") ? `${relPosix}/` : relPosix;
|
|
69
|
+
return ig.ignores(toPosix(candidate));
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=ignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore.js","sourceRoot":"","sources":["../../src/indexer/ignore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,EAAE,EAAe,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,0EAA0E;AAC1E,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,aAAa;IACb,OAAO;IACP,OAAO;IACP,MAAM;IACN,eAAe;IACf,OAAO;IACP,QAAQ;IACR,MAAM;IACN,SAAS;IACT,WAAW;IACX,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,SAAS;IACT,SAAS;IACT,QAAQ;IACR,OAAO;IACP,cAAc;IACd,gBAAgB;IAChB,cAAc;IACd,OAAO;IACP,QAAQ;IACR,UAAU;IACV,UAAU;IACV,WAAW;IACX,OAAO;IACP,QAAQ;IACR,mBAAmB;IACnB,WAAW;IACX,gBAAgB;IAChB,WAAW;IACX,YAAY;IACZ,aAAa;IACb,eAAe;IACf,MAAM;IACN,UAAU;IACV,WAAW;IACX,WAAW;IACX,WAAW;CACZ,CAAC;AAEF,SAAS,cAAc,CAAC,QAAgB;IACtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,OAAO,EAAE;SACN,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC;SAC9B,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,IAAY,EACZ,eAAyB,EAAE;IAE3B,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IACpB,EAAE,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACzB,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAErB,KAAK,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC,EAAE,CAAC;QACtD,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACvD,IAAI,QAAQ,CAAC,MAAM;YAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAU,EAAE,QAAgB,EAAE,WAAW,GAAG,KAAK;IAC5E,MAAM,SAAS,GAAG,WAAW,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrF,OAAO,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Db } from "../core/db.js";
|
|
2
|
+
import type { IndexStats, LocalMindConfig } from "../types.js";
|
|
3
|
+
export interface IndexOptions {
|
|
4
|
+
full?: boolean;
|
|
5
|
+
withEmbeddings?: boolean;
|
|
6
|
+
quiet?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function runIndex(config: LocalMindConfig, options?: IndexOptions): Promise<IndexStats>;
|
|
9
|
+
/** Index a single relative path (used by tests / future watch mode). */
|
|
10
|
+
export declare function indexSingleFile(db: Db, config: LocalMindConfig, absPath: string, relPath: string): number;
|
|
11
|
+
//# sourceMappingURL=indexer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../../src/indexer/indexer.ts"],"names":[],"mappings":"AACA,OAAO,EAcL,KAAK,EAAE,EACR,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAY/D,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,UAAU,CAAC,CA0JrB;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAC7B,EAAE,EAAE,EAAE,EACN,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,MAAM,CA2CR"}
|