@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.
Files changed (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +290 -0
  3. package/dist/ask/answer.d.ts +9 -0
  4. package/dist/ask/answer.d.ts.map +1 -0
  5. package/dist/ask/answer.js +183 -0
  6. package/dist/ask/answer.js.map +1 -0
  7. package/dist/bin/localmind.d.ts +3 -0
  8. package/dist/bin/localmind.d.ts.map +1 -0
  9. package/dist/bin/localmind.js +11 -0
  10. package/dist/bin/localmind.js.map +1 -0
  11. package/dist/cli/format.d.ts +7 -0
  12. package/dist/cli/format.d.ts.map +1 -0
  13. package/dist/cli/format.js +67 -0
  14. package/dist/cli/format.js.map +1 -0
  15. package/dist/cli/program.d.ts +4 -0
  16. package/dist/cli/program.d.ts.map +1 -0
  17. package/dist/cli/program.js +228 -0
  18. package/dist/cli/program.js.map +1 -0
  19. package/dist/core/config.d.ts +17 -0
  20. package/dist/core/config.d.ts.map +1 -0
  21. package/dist/core/config.js +55 -0
  22. package/dist/core/config.js.map +1 -0
  23. package/dist/core/db.d.ts +50 -0
  24. package/dist/core/db.d.ts.map +1 -0
  25. package/dist/core/db.js +180 -0
  26. package/dist/core/db.js.map +1 -0
  27. package/dist/core/hash.d.ts +3 -0
  28. package/dist/core/hash.d.ts.map +1 -0
  29. package/dist/core/hash.js +8 -0
  30. package/dist/core/hash.js.map +1 -0
  31. package/dist/core/logger.d.ts +12 -0
  32. package/dist/core/logger.d.ts.map +1 -0
  33. package/dist/core/logger.js +45 -0
  34. package/dist/core/logger.js.map +1 -0
  35. package/dist/core/paths.d.ts +16 -0
  36. package/dist/core/paths.d.ts.map +1 -0
  37. package/dist/core/paths.js +43 -0
  38. package/dist/core/paths.js.map +1 -0
  39. package/dist/graph/related.d.ts +11 -0
  40. package/dist/graph/related.d.ts.map +1 -0
  41. package/dist/graph/related.js +144 -0
  42. package/dist/graph/related.js.map +1 -0
  43. package/dist/index.d.ts +17 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +16 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/indexer/chunker.d.ts +16 -0
  48. package/dist/indexer/chunker.d.ts.map +1 -0
  49. package/dist/indexer/chunker.js +76 -0
  50. package/dist/indexer/chunker.js.map +1 -0
  51. package/dist/indexer/ignore.d.ts +6 -0
  52. package/dist/indexer/ignore.d.ts.map +1 -0
  53. package/dist/indexer/ignore.js +71 -0
  54. package/dist/indexer/ignore.js.map +1 -0
  55. package/dist/indexer/indexer.d.ts +11 -0
  56. package/dist/indexer/indexer.d.ts.map +1 -0
  57. package/dist/indexer/indexer.js +182 -0
  58. package/dist/indexer/indexer.js.map +1 -0
  59. package/dist/indexer/languages.d.ts +5 -0
  60. package/dist/indexer/languages.d.ts.map +1 -0
  61. package/dist/indexer/languages.js +144 -0
  62. package/dist/indexer/languages.js.map +1 -0
  63. package/dist/indexer/relations.d.ts +9 -0
  64. package/dist/indexer/relations.d.ts.map +1 -0
  65. package/dist/indexer/relations.js +81 -0
  66. package/dist/indexer/relations.js.map +1 -0
  67. package/dist/indexer/walker.d.ts +21 -0
  68. package/dist/indexer/walker.d.ts.map +1 -0
  69. package/dist/indexer/walker.js +86 -0
  70. package/dist/indexer/walker.js.map +1 -0
  71. package/dist/mcp/server.d.ts +5 -0
  72. package/dist/mcp/server.d.ts.map +1 -0
  73. package/dist/mcp/server.js +291 -0
  74. package/dist/mcp/server.js.map +1 -0
  75. package/dist/search/bm25.d.ts +9 -0
  76. package/dist/search/bm25.d.ts.map +1 -0
  77. package/dist/search/bm25.js +109 -0
  78. package/dist/search/bm25.js.map +1 -0
  79. package/dist/search/embeddings.d.ts +15 -0
  80. package/dist/search/embeddings.d.ts.map +1 -0
  81. package/dist/search/embeddings.js +193 -0
  82. package/dist/search/embeddings.js.map +1 -0
  83. package/dist/search/search.d.ts +9 -0
  84. package/dist/search/search.d.ts.map +1 -0
  85. package/dist/search/search.js +47 -0
  86. package/dist/search/search.js.map +1 -0
  87. package/dist/search/tokenize.d.ts +6 -0
  88. package/dist/search/tokenize.d.ts.map +1 -0
  89. package/dist/search/tokenize.js +163 -0
  90. package/dist/search/tokenize.js.map +1 -0
  91. package/dist/status.d.ts +4 -0
  92. package/dist/status.d.ts.map +1 -0
  93. package/dist/status.js +33 -0
  94. package/dist/status.js.map +1 -0
  95. package/dist/types.d.ts +105 -0
  96. package/dist/types.d.ts.map +1 -0
  97. package/dist/types.js +11 -0
  98. package/dist/types.js.map +1 -0
  99. package/package.json +72 -0
@@ -0,0 +1,9 @@
1
+ import type { Db } from "../core/db.js";
2
+ import type { ProviderKind, SearchHit, SearchMode } from "../types.js";
3
+ export interface SearchOptions {
4
+ limit?: number;
5
+ mode?: SearchMode;
6
+ provider?: ProviderKind;
7
+ }
8
+ export declare function search(db: Db, query: string, options?: SearchOptions): Promise<SearchHit[]>;
9
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/search/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQvE,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAED,wBAAsB,MAAM,CAC1B,EAAE,EAAE,EAAE,EACN,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,SAAS,EAAE,CAAC,CAyCtB"}
@@ -0,0 +1,47 @@
1
+ import { bm25Search, literalSearch } from "./bm25.js";
2
+ import { createEmbedder, mergeHybrid, vectorSearch, } from "./embeddings.js";
3
+ export async function search(db, query, options = {}) {
4
+ const limit = options.limit ?? 8;
5
+ const mode = options.mode ?? "bm25";
6
+ const q = query.trim();
7
+ if (!q)
8
+ return [];
9
+ if (mode === "bm25") {
10
+ const hits = bm25Search(db, q, limit);
11
+ if (hits.length)
12
+ return hits;
13
+ return literalSearch(db, q, limit);
14
+ }
15
+ const embedder = createEmbedder(options.provider ?? "none");
16
+ if (!embedder) {
17
+ const hits = bm25Search(db, q, limit);
18
+ return hits.length ? hits : literalSearch(db, q, limit);
19
+ }
20
+ if (mode === "vector") {
21
+ try {
22
+ const hits = await vectorSearch(db, embedder, q, limit);
23
+ if (hits.length)
24
+ return hits;
25
+ }
26
+ catch {
27
+ // fall through
28
+ }
29
+ return bm25Search(db, q, limit);
30
+ }
31
+ // hybrid
32
+ const bm25Hits = bm25Search(db, q, limit * 2);
33
+ let vectorHits = [];
34
+ try {
35
+ vectorHits = await vectorSearch(db, embedder, q, limit * 2);
36
+ }
37
+ catch {
38
+ vectorHits = [];
39
+ }
40
+ if (!vectorHits.length) {
41
+ return bm25Hits.slice(0, limit).map((h, i) => ({ ...h, rank: i + 1 }));
42
+ }
43
+ if (!bm25Hits.length)
44
+ return vectorHits.slice(0, limit);
45
+ return mergeHybrid(bm25Hits, vectorHits, limit);
46
+ }
47
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/search/search.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EACL,cAAc,EACd,WAAW,EACX,YAAY,GACb,MAAM,iBAAiB,CAAC;AAQzB,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,EAAM,EACN,KAAa,EACb,UAAyB,EAAE;IAE3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC;IACpC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACvB,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QACtC,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC7B,OAAO,aAAa,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC,CAAC;IAC5D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;YACxD,IAAI,IAAI,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;QACD,OAAO,UAAU,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,SAAS;IACT,MAAM,QAAQ,GAAG,UAAU,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAC9C,IAAI,UAAU,GAAgB,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,UAAU,GAAG,MAAM,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,UAAU,GAAG,EAAE,CAAC;IAClB,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QACvB,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,MAAM;QAAE,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACxD,OAAO,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Tokenize text for BM25. Keeps identifiers split on camelCase / snake_case.
3
+ */
4
+ export declare function tokenize(text: string): string[];
5
+ export declare function termFrequencies(tokens: string[]): Map<string, number>;
6
+ //# sourceMappingURL=tokenize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenize.d.ts","sourceRoot":"","sources":["../../src/search/tokenize.ts"],"names":[],"mappings":"AAoGA;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB/C;AAkCD,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAMrE"}
@@ -0,0 +1,163 @@
1
+ /** Minimal stopword set for code/docs search. */
2
+ const STOPWORDS = new Set([
3
+ "a",
4
+ "an",
5
+ "the",
6
+ "and",
7
+ "or",
8
+ "but",
9
+ "if",
10
+ "then",
11
+ "else",
12
+ "when",
13
+ "at",
14
+ "by",
15
+ "for",
16
+ "with",
17
+ "about",
18
+ "against",
19
+ "between",
20
+ "into",
21
+ "through",
22
+ "during",
23
+ "before",
24
+ "after",
25
+ "above",
26
+ "below",
27
+ "to",
28
+ "from",
29
+ "up",
30
+ "down",
31
+ "in",
32
+ "out",
33
+ "on",
34
+ "off",
35
+ "over",
36
+ "under",
37
+ "again",
38
+ "further",
39
+ "once",
40
+ "here",
41
+ "there",
42
+ "all",
43
+ "any",
44
+ "both",
45
+ "each",
46
+ "few",
47
+ "more",
48
+ "most",
49
+ "other",
50
+ "some",
51
+ "such",
52
+ "no",
53
+ "nor",
54
+ "not",
55
+ "only",
56
+ "own",
57
+ "same",
58
+ "so",
59
+ "than",
60
+ "too",
61
+ "very",
62
+ "can",
63
+ "will",
64
+ "just",
65
+ "don",
66
+ "should",
67
+ "now",
68
+ "is",
69
+ "are",
70
+ "was",
71
+ "were",
72
+ "be",
73
+ "been",
74
+ "being",
75
+ "have",
76
+ "has",
77
+ "had",
78
+ "do",
79
+ "does",
80
+ "did",
81
+ "of",
82
+ "as",
83
+ "it",
84
+ "its",
85
+ "this",
86
+ "that",
87
+ "these",
88
+ "those",
89
+ "i",
90
+ "you",
91
+ "he",
92
+ "she",
93
+ "we",
94
+ "they",
95
+ "me",
96
+ "my",
97
+ "your",
98
+ "our",
99
+ ]);
100
+ /**
101
+ * Tokenize text for BM25. Keeps identifiers split on camelCase / snake_case.
102
+ */
103
+ export function tokenize(text) {
104
+ const raw = text
105
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
106
+ .replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2")
107
+ .replace(/[_\-./\\]+/g, " ")
108
+ .toLowerCase();
109
+ const tokens = [];
110
+ const re = /[a-z0-9]{2,}/g;
111
+ let m;
112
+ while ((m = re.exec(raw))) {
113
+ let t = m[0];
114
+ if (STOPWORDS.has(t))
115
+ continue;
116
+ if (/^\d+$/.test(t))
117
+ continue;
118
+ t = lightStem(t);
119
+ if (t.length < 2 || STOPWORDS.has(t))
120
+ continue;
121
+ tokens.push(t);
122
+ }
123
+ return tokens;
124
+ }
125
+ /** Very light English stemmer — enough for code/docs search without a dependency. */
126
+ function lightStem(term) {
127
+ if (term.length <= 3)
128
+ return term;
129
+ if (term.endsWith("ies") && term.length > 5)
130
+ return term.slice(0, -3) + "y";
131
+ if (term.endsWith("ing") && term.length > 5) {
132
+ const base = term.slice(0, -3);
133
+ // running -> runn -> run; indexing -> index
134
+ if (base.length >= 4 && base[base.length - 1] === base[base.length - 2]) {
135
+ return base.slice(0, -1);
136
+ }
137
+ return base;
138
+ }
139
+ if (term.endsWith("ed") && term.length > 4) {
140
+ const base = term.slice(0, -2);
141
+ if (base.length >= 4 && base[base.length - 1] === base[base.length - 2]) {
142
+ return base.slice(0, -1);
143
+ }
144
+ return base;
145
+ }
146
+ // Simple plural: tokens -> token, values -> value (avoid stripping "es" alone)
147
+ if (term.endsWith("s") &&
148
+ !term.endsWith("ss") &&
149
+ !term.endsWith("us") &&
150
+ !term.endsWith("is") &&
151
+ term.length > 3) {
152
+ return term.slice(0, -1);
153
+ }
154
+ return term;
155
+ }
156
+ export function termFrequencies(tokens) {
157
+ const tf = new Map();
158
+ for (const t of tokens) {
159
+ tf.set(t, (tf.get(t) ?? 0) + 1);
160
+ }
161
+ return tf;
162
+ }
163
+ //# sourceMappingURL=tokenize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenize.js","sourceRoot":"","sources":["../../src/search/tokenize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { StatusInfo } from "./types.js";
2
+ export declare function getStatus(rootInput?: string): StatusInfo;
3
+ export declare function formatBytes(n: number): string;
4
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,wBAAgB,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,CAoBxD;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAI7C"}
package/dist/status.js ADDED
@@ -0,0 +1,33 @@
1
+ import { closeDb, countTable, getDbSizeBytes, getLastIndexedAt, openDb, } from "./core/db.js";
2
+ import { loadConfig } from "./core/config.js";
3
+ import { dbPath, resolveRoot } from "./core/paths.js";
4
+ export function getStatus(rootInput) {
5
+ const root = resolveRoot(rootInput);
6
+ const config = loadConfig(root);
7
+ const db = openDb(root);
8
+ try {
9
+ return {
10
+ root,
11
+ dbPath: dbPath(root),
12
+ config,
13
+ fileCount: countTable(db, "files"),
14
+ chunkCount: countTable(db, "chunks"),
15
+ termCount: countTable(db, "terms"),
16
+ edgeCount: countTable(db, "edges"),
17
+ embeddingCount: countTable(db, "embeddings"),
18
+ lastIndexedAt: getLastIndexedAt(db),
19
+ dbSizeBytes: getDbSizeBytes(root),
20
+ };
21
+ }
22
+ finally {
23
+ closeDb(db);
24
+ }
25
+ }
26
+ export function formatBytes(n) {
27
+ if (n < 1024)
28
+ return `${n} B`;
29
+ if (n < 1024 * 1024)
30
+ return `${(n / 1024).toFixed(1)} KB`;
31
+ return `${(n / (1024 * 1024)).toFixed(2)} MB`;
32
+ }
33
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,MAAM,GACP,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGtD,MAAM,UAAU,SAAS,CAAC,SAAkB;IAC1C,MAAM,IAAI,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACxB,IAAI,CAAC;QACH,OAAO;YACL,IAAI;YACJ,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC;YACpB,MAAM;YACN,SAAS,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC;YAClC,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,QAAQ,CAAC;YACpC,SAAS,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC;YAClC,SAAS,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC;YAClC,cAAc,EAAE,UAAU,CAAC,EAAE,EAAE,YAAY,CAAC;YAC5C,aAAa,EAAE,gBAAgB,CAAC,EAAE,CAAC;YACnC,WAAW,EAAE,cAAc,CAAC,IAAI,CAAC;SAClC,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,EAAE,CAAC,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,IAAI,CAAC,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC;IAC9B,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAC1D,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AAChD,CAAC"}
@@ -0,0 +1,105 @@
1
+ /** Supported embedding / answer providers. */
2
+ export type ProviderKind = "none" | "openai" | "ollama";
3
+ /** How search ranks results. */
4
+ export type SearchMode = "bm25" | "vector" | "hybrid";
5
+ export interface LocalMindConfig {
6
+ /** Schema version for migrations. */
7
+ version: number;
8
+ /** Absolute path to the project root. */
9
+ root: string;
10
+ /** Relative paths (posix) to include; empty = whole root. */
11
+ include: string[];
12
+ /** Extra gitignore-style patterns. */
13
+ exclude: string[];
14
+ /** Max file size to index (bytes). */
15
+ maxFileBytes: number;
16
+ /** Target chunk size in characters. */
17
+ chunkSize: number;
18
+ /** Overlap between consecutive chunks in characters. */
19
+ chunkOverlap: number;
20
+ /** Preferred answer provider. */
21
+ provider: ProviderKind;
22
+ /** Embedding model id when provider supports it. */
23
+ embeddingModel?: string;
24
+ /** Chat model id when provider supports it. */
25
+ chatModel?: string;
26
+ /** When true, re-index only changed files by default. */
27
+ incremental: boolean;
28
+ createdAt: string;
29
+ updatedAt: string;
30
+ }
31
+ export interface FileRecord {
32
+ id: number;
33
+ path: string;
34
+ absPath: string;
35
+ language: string;
36
+ size: number;
37
+ mtimeMs: number;
38
+ contentHash: string;
39
+ lineCount: number;
40
+ indexedAt: string;
41
+ }
42
+ export interface ChunkRecord {
43
+ id: number;
44
+ fileId: number;
45
+ chunkIndex: number;
46
+ startLine: number;
47
+ endLine: number;
48
+ content: string;
49
+ contentHash: string;
50
+ tokenCount: number;
51
+ path?: string;
52
+ language?: string;
53
+ }
54
+ export interface SearchHit {
55
+ chunkId: number;
56
+ fileId: number;
57
+ path: string;
58
+ language: string;
59
+ startLine: number;
60
+ endLine: number;
61
+ content: string;
62
+ score: number;
63
+ rank: number;
64
+ }
65
+ export interface AskResult {
66
+ question: string;
67
+ answer: string;
68
+ mode: "extractive" | "generative";
69
+ provider: ProviderKind;
70
+ hits: SearchHit[];
71
+ tookMs: number;
72
+ }
73
+ export interface IndexStats {
74
+ filesScanned: number;
75
+ filesIndexed: number;
76
+ filesSkipped: number;
77
+ filesRemoved: number;
78
+ chunksCreated: number;
79
+ durationMs: number;
80
+ }
81
+ export interface StatusInfo {
82
+ root: string;
83
+ dbPath: string;
84
+ config: LocalMindConfig;
85
+ fileCount: number;
86
+ chunkCount: number;
87
+ termCount: number;
88
+ edgeCount: number;
89
+ embeddingCount: number;
90
+ lastIndexedAt: string | null;
91
+ dbSizeBytes: number;
92
+ }
93
+ export interface GraphEdge {
94
+ id: number;
95
+ sourcePath: string;
96
+ targetPath: string;
97
+ relation: string;
98
+ }
99
+ export interface RelatedFile {
100
+ path: string;
101
+ relation: string;
102
+ score: number;
103
+ }
104
+ export declare const DEFAULT_CONFIG: Omit<LocalMindConfig, "root" | "createdAt" | "updatedAt">;
105
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,11 @@
1
+ export const DEFAULT_CONFIG = {
2
+ version: 1,
3
+ include: [],
4
+ exclude: [],
5
+ maxFileBytes: 512 * 1024,
6
+ chunkSize: 1200,
7
+ chunkOverlap: 150,
8
+ provider: "none",
9
+ incremental: true,
10
+ };
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAkHA,MAAM,CAAC,MAAM,cAAc,GAA8D;IACvF,OAAO,EAAE,CAAC;IACV,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;IACX,YAAY,EAAE,GAAG,GAAG,IAAI;IACxB,SAAS,EAAE,IAAI;IACf,YAAY,EAAE,GAAG;IACjB,QAAQ,EAAE,MAAM;IAChB,WAAW,EAAE,IAAI;CAClB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@ixxrllg/localmind",
3
+ "version": "0.1.0",
4
+ "description": "Give every AI agent perfect memory of your codebase — offline. Local knowledge + context engine with CLI and MCP.",
5
+ "type": "module",
6
+ "bin": {
7
+ "localmind": "dist/bin/localmind.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc -p tsconfig.json",
24
+ "dev": "tsx src/bin/localmind.ts",
25
+ "start": "node dist/bin/localmind.js",
26
+ "typecheck": "tsc -p tsconfig.json --noEmit",
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
29
+ "prepublishOnly": "npm run build && npm test"
30
+ },
31
+ "engines": {
32
+ "node": ">=22.5.0"
33
+ },
34
+ "keywords": [
35
+ "localmind",
36
+ "mcp",
37
+ "rag",
38
+ "codebase",
39
+ "ai-agent",
40
+ "embeddings",
41
+ "bm25",
42
+ "self-hosted",
43
+ "cli",
44
+ "context-engine"
45
+ ],
46
+ "author": "ixxrllg",
47
+ "license": "MIT",
48
+ "homepage": "https://github.com/ixxrllg/localmind#readme",
49
+ "bugs": {
50
+ "url": "https://github.com/ixxrllg/localmind/issues"
51
+ },
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "git+https://github.com/ixxrllg/localmind.git"
55
+ },
56
+ "publishConfig": {
57
+ "access": "public"
58
+ },
59
+ "dependencies": {
60
+ "@modelcontextprotocol/sdk": "^1.12.1",
61
+ "commander": "^13.1.0",
62
+ "ignore": "^7.0.4",
63
+ "picocolors": "^1.1.1",
64
+ "zod": "^3.24.2"
65
+ },
66
+ "devDependencies": {
67
+ "@types/node": "^22.13.10",
68
+ "tsx": "^4.19.3",
69
+ "typescript": "^5.8.2",
70
+ "vitest": "^3.0.9"
71
+ }
72
+ }