@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,228 @@
1
+ import { Command } from "commander";
2
+ import { ask } from "../ask/answer.js";
3
+ import { detectProviderFromEnv, initConfig, loadConfig, saveConfig, } from "../core/config.js";
4
+ import { closeDb, openDb } from "../core/db.js";
5
+ import { log, setLogLevel } from "../core/logger.js";
6
+ import { isInitialized, resolveRoot } from "../core/paths.js";
7
+ import { findRelatedFiles } from "../graph/related.js";
8
+ import { runIndex } from "../indexer/indexer.js";
9
+ import { startMcpServer } from "../mcp/server.js";
10
+ import { search } from "../search/search.js";
11
+ import { getStatus } from "../status.js";
12
+ import { printAskResult, printIndexStats, printInitResult, printSearchHits, printStatus, } from "./format.js";
13
+ export function buildProgram() {
14
+ const program = new Command();
15
+ program
16
+ .name("localmind")
17
+ .description("Local knowledge & context engine for developers and AI agents (CLI + MCP)")
18
+ .version("0.1.0")
19
+ .option("-r, --root <path>", "Project root (default: cwd)")
20
+ .option("-q, --quiet", "Less logging", false)
21
+ .option("--verbose", "Debug logging", false)
22
+ .hook("preAction", (thisCommand) => {
23
+ const opts = thisCommand.optsWithGlobals();
24
+ if (opts.verbose)
25
+ setLogLevel("debug");
26
+ else if (opts.quiet)
27
+ setLogLevel("silent");
28
+ });
29
+ program
30
+ .command("init")
31
+ .description("Initialize LocalMind in a project")
32
+ .option("-f, --force", "Overwrite existing config", false)
33
+ .option("-p, --provider <name>", "Provider: none | openai | ollama", "none")
34
+ .action((opts, cmd) => {
35
+ const global = cmd.optsWithGlobals();
36
+ const root = resolveRoot(global.root);
37
+ let provider = (opts.provider ?? "none");
38
+ if (provider === "none") {
39
+ const detected = detectProviderFromEnv();
40
+ if (detected !== "none")
41
+ provider = detected;
42
+ }
43
+ if (!["none", "openai", "ollama"].includes(provider)) {
44
+ log.error(`Invalid provider: ${provider}`);
45
+ process.exitCode = 1;
46
+ return;
47
+ }
48
+ const { config, created } = initConfig({
49
+ root,
50
+ force: opts.force,
51
+ provider,
52
+ });
53
+ // Ensure DB exists
54
+ const db = openDb(config.root);
55
+ closeDb(db);
56
+ printInitResult(config.root, created);
57
+ });
58
+ program
59
+ .command("index")
60
+ .description("Index the project into the local knowledge base")
61
+ .option("--full", "Force full re-index", false)
62
+ .option("--no-embeddings", "Skip embedding generation")
63
+ .action(async (opts, cmd) => {
64
+ const global = cmd.optsWithGlobals();
65
+ const root = resolveRoot(global.root);
66
+ ensureInit(root);
67
+ const config = loadConfig(root);
68
+ log.info(`Indexing ${config.root}…`);
69
+ const stats = await runIndex(config, {
70
+ full: opts.full,
71
+ withEmbeddings: opts.embeddings !== false,
72
+ quiet: global.quiet,
73
+ });
74
+ printIndexStats(stats);
75
+ });
76
+ program
77
+ .command("search")
78
+ .description("Search the index")
79
+ .argument("<query>", "Search query")
80
+ .option("-n, --limit <n>", "Max results", "8")
81
+ .option("-m, --mode <mode>", "bm25 | vector | hybrid", "bm25")
82
+ .option("--json", "JSON output", false)
83
+ .action(async (query, opts, cmd) => {
84
+ const global = cmd.optsWithGlobals();
85
+ const root = resolveRoot(global.root);
86
+ ensureInit(root);
87
+ const config = loadConfig(root);
88
+ const db = openDb(root);
89
+ try {
90
+ const hits = await search(db, query, {
91
+ limit: Number(opts.limit ?? 8),
92
+ mode: (opts.mode ?? "bm25"),
93
+ provider: config.provider,
94
+ });
95
+ if (opts.json) {
96
+ console.log(JSON.stringify(hits, null, 2));
97
+ }
98
+ else {
99
+ printSearchHits(hits);
100
+ }
101
+ }
102
+ finally {
103
+ closeDb(db);
104
+ }
105
+ });
106
+ program
107
+ .command("ask")
108
+ .description("Ask a question about the codebase")
109
+ .argument("<question...>", "Your question")
110
+ .option("-n, --limit <n>", "Context chunks", "6")
111
+ .option("--extractive", "Force extractive (no LLM)", false)
112
+ .option("--json", "JSON output", false)
113
+ .action(async (questionParts, opts, cmd) => {
114
+ const global = cmd.optsWithGlobals();
115
+ const root = resolveRoot(global.root);
116
+ ensureInit(root);
117
+ const config = loadConfig(root);
118
+ const question = questionParts.join(" ");
119
+ const db = openDb(root);
120
+ try {
121
+ const result = await ask(db, config, question, {
122
+ limit: Number(opts.limit ?? 6),
123
+ mode: opts.extractive ? "extractive" : "auto",
124
+ });
125
+ printAskResult(result, opts.json);
126
+ }
127
+ finally {
128
+ closeDb(db);
129
+ }
130
+ });
131
+ program
132
+ .command("related")
133
+ .description("Show files related via the import/link graph")
134
+ .argument("<path>", "File path or module fragment")
135
+ .option("-n, --limit <n>", "Max results", "15")
136
+ .option("--json", "JSON output", false)
137
+ .action((pathArg, opts, cmd) => {
138
+ const global = cmd.optsWithGlobals();
139
+ const root = resolveRoot(global.root);
140
+ ensureInit(root);
141
+ const db = openDb(root);
142
+ try {
143
+ const related = findRelatedFiles(db, pathArg, Number(opts.limit ?? 15));
144
+ if (opts.json) {
145
+ console.log(JSON.stringify(related, null, 2));
146
+ }
147
+ else if (!related.length) {
148
+ console.log("No related files found.");
149
+ }
150
+ else {
151
+ for (const r of related) {
152
+ console.log(`${r.path} ${pcDim(r.relation)} score=${r.score.toFixed(2)}`);
153
+ }
154
+ }
155
+ }
156
+ finally {
157
+ closeDb(db);
158
+ }
159
+ });
160
+ program
161
+ .command("status")
162
+ .description("Show index status")
163
+ .option("--json", "JSON output", false)
164
+ .action((opts, cmd) => {
165
+ const global = cmd.optsWithGlobals();
166
+ const root = resolveRoot(global.root);
167
+ ensureInit(root);
168
+ const status = getStatus(root);
169
+ if (opts.json) {
170
+ console.log(JSON.stringify(status, null, 2));
171
+ }
172
+ else {
173
+ printStatus(status);
174
+ }
175
+ });
176
+ program
177
+ .command("mcp")
178
+ .description("Start MCP server on stdio (for Cursor / Claude / agents)")
179
+ .action(async (_opts, cmd) => {
180
+ const global = cmd.optsWithGlobals();
181
+ const root = resolveRoot(global.root);
182
+ ensureInit(root);
183
+ // MCP uses stdout for protocol — keep logs on stderr only
184
+ setLogLevel("error");
185
+ await startMcpServer({ root });
186
+ });
187
+ program
188
+ .command("config")
189
+ .description("Show or update LocalMind config")
190
+ .option("--provider <name>", "Set provider: none | openai | ollama")
191
+ .option("--json", "JSON output", false)
192
+ .action((opts, cmd) => {
193
+ const global = cmd.optsWithGlobals();
194
+ const root = resolveRoot(global.root);
195
+ ensureInit(root);
196
+ let config = loadConfig(root);
197
+ if (opts.provider) {
198
+ if (!["none", "openai", "ollama"].includes(opts.provider)) {
199
+ log.error(`Invalid provider: ${opts.provider}`);
200
+ process.exitCode = 1;
201
+ return;
202
+ }
203
+ config = { ...config, provider: opts.provider };
204
+ saveConfig(config);
205
+ log.success(`Provider set to ${opts.provider}`);
206
+ }
207
+ if (opts.json || !opts.provider) {
208
+ console.log(JSON.stringify(config, null, 2));
209
+ }
210
+ });
211
+ return program;
212
+ }
213
+ function ensureInit(root) {
214
+ if (!isInitialized(root)) {
215
+ log.error(`Not initialized: ${root}`);
216
+ log.info("Run: localmind init");
217
+ process.exit(1);
218
+ }
219
+ }
220
+ function pcDim(s) {
221
+ // tiny helper to avoid importing picocolors in every line of related
222
+ return `\u001b[2m${s}\u001b[0m`;
223
+ }
224
+ export async function runCli(argv = process.argv) {
225
+ const program = buildProgram();
226
+ await program.parseAsync(argv);
227
+ }
228
+ //# sourceMappingURL=program.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program.js","sourceRoot":"","sources":["../../src/cli/program.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type LocalMindConfig, type ProviderKind } from "../types.js";
2
+ export interface InitOptions {
3
+ root?: string;
4
+ provider?: ProviderKind;
5
+ include?: string[];
6
+ exclude?: string[];
7
+ force?: boolean;
8
+ }
9
+ export declare function createDefaultConfig(root: string, opts?: InitOptions): LocalMindConfig;
10
+ export declare function loadConfig(root?: string): LocalMindConfig;
11
+ export declare function saveConfig(config: LocalMindConfig): void;
12
+ export declare function initConfig(opts?: InitOptions): {
13
+ config: LocalMindConfig;
14
+ created: boolean;
15
+ };
16
+ export declare function detectProviderFromEnv(): ProviderKind;
17
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAOrB,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,eAAe,CAWzF;AAED,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,eAAe,CAYzD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAOxD;AAED,wBAAgB,UAAU,CAAC,IAAI,GAAE,WAAgB,GAAG;IAClD,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;CAClB,CASA;AAED,wBAAgB,qBAAqB,IAAI,YAAY,CAIpD"}
@@ -0,0 +1,55 @@
1
+ import fs from "node:fs";
2
+ import { DEFAULT_CONFIG, } from "../types.js";
3
+ import { configPath, ensureLocalmindDir, resolveRoot } from "./paths.js";
4
+ function nowIso() {
5
+ return new Date().toISOString();
6
+ }
7
+ export function createDefaultConfig(root, opts = {}) {
8
+ const ts = nowIso();
9
+ return {
10
+ ...DEFAULT_CONFIG,
11
+ root,
12
+ provider: opts.provider ?? "none",
13
+ include: opts.include ?? [],
14
+ exclude: opts.exclude ?? [],
15
+ createdAt: ts,
16
+ updatedAt: ts,
17
+ };
18
+ }
19
+ export function loadConfig(root) {
20
+ const resolved = resolveRoot(root);
21
+ const file = configPath(resolved);
22
+ if (!fs.existsSync(file)) {
23
+ throw new Error(`LocalMind is not initialized in ${resolved}. Run: localmind init`);
24
+ }
25
+ const raw = fs.readFileSync(file, "utf8");
26
+ const parsed = JSON.parse(raw);
27
+ // Always trust the actual root we loaded from (portable repos / moves).
28
+ return { ...parsed, root: resolved };
29
+ }
30
+ export function saveConfig(config) {
31
+ ensureLocalmindDir(config.root);
32
+ const next = {
33
+ ...config,
34
+ updatedAt: nowIso(),
35
+ };
36
+ fs.writeFileSync(configPath(config.root), JSON.stringify(next, null, 2) + "\n", "utf8");
37
+ }
38
+ export function initConfig(opts = {}) {
39
+ const root = resolveRoot(opts.root);
40
+ const file = configPath(root);
41
+ if (fs.existsSync(file) && !opts.force) {
42
+ return { config: loadConfig(root), created: false };
43
+ }
44
+ const config = createDefaultConfig(root, opts);
45
+ saveConfig(config);
46
+ return { config, created: true };
47
+ }
48
+ export function detectProviderFromEnv() {
49
+ if (process.env.OPENAI_API_KEY)
50
+ return "openai";
51
+ if (process.env.OLLAMA_BASE_URL || process.env.OLLAMA_HOST)
52
+ return "ollama";
53
+ return "none";
54
+ }
55
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EACL,cAAc,GAGf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzE,SAAS,MAAM;IACb,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAUD,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,OAAoB,EAAE;IACtE,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IACpB,OAAO;QACL,GAAG,cAAc;QACjB,IAAI;QACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,MAAM;QACjC,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;QAC3B,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;QAC3B,SAAS,EAAE,EAAE;QACb,SAAS,EAAE,EAAE;KACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,mCAAmC,QAAQ,uBAAuB,CACnE,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC;IAClD,wEAAwE;IACxE,OAAO,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAuB;IAChD,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,IAAI,GAAoB;QAC5B,GAAG,MAAM;QACT,SAAS,EAAE,MAAM,EAAE;KACpB,CAAC;IACF,EAAE,CAAC,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAoB,EAAE;IAI/C,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACvC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACtD,CAAC;IACD,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/C,UAAU,CAAC,MAAM,CAAC,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,QAAQ,CAAC;IAChD,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW;QAAE,OAAO,QAAQ,CAAC;IAC5E,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ export type Db = DatabaseSync;
3
+ export declare function openDb(root: string): Db;
4
+ export declare function closeDb(db: Db): void;
5
+ export declare function setMeta(db: Db, key: string, value: string): void;
6
+ export declare function getMeta(db: Db, key: string): string | null;
7
+ export declare function getDbSizeBytes(root: string): number;
8
+ export declare function countTable(db: Db, table: string): number;
9
+ export declare function getLastIndexedAt(db: Db): string | null;
10
+ export interface FileRow {
11
+ id: number;
12
+ path: string;
13
+ abs_path: string;
14
+ language: string;
15
+ size: number;
16
+ mtime_ms: number;
17
+ content_hash: string;
18
+ line_count: number;
19
+ indexed_at: string;
20
+ }
21
+ export declare function getFileByPath(db: Db, relPath: string): FileRow | undefined;
22
+ export declare function listAllFilePaths(db: Db): string[];
23
+ export declare function deleteFileByPath(db: Db, relPath: string): void;
24
+ export declare function upsertFile(db: Db, file: {
25
+ path: string;
26
+ absPath: string;
27
+ language: string;
28
+ size: number;
29
+ mtimeMs: number;
30
+ contentHash: string;
31
+ lineCount: number;
32
+ indexedAt: string;
33
+ }): number;
34
+ export declare function clearChunksForFile(db: Db, fileId: number): void;
35
+ export declare function insertChunk(db: Db, chunk: {
36
+ fileId: number;
37
+ chunkIndex: number;
38
+ startLine: number;
39
+ endLine: number;
40
+ content: string;
41
+ contentHash: string;
42
+ tokenCount: number;
43
+ }): number;
44
+ export declare function getOrCreateTermId(db: Db, term: string): number;
45
+ export declare function insertPosting(db: Db, termId: number, chunkId: number, tf: number): void;
46
+ export declare function insertEdge(db: Db, sourceFileId: number, targetPath: string, relation: string): void;
47
+ export declare function insertEmbedding(db: Db, chunkId: number, model: string, vector: Float32Array): void;
48
+ export declare function pruneOrphanTerms(db: Db): void;
49
+ export declare function withTransaction<T>(db: Db, fn: () => T): T;
50
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/core/db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,180 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ import fs from "node:fs";
3
+ import { dbPath, ensureLocalmindDir } from "./paths.js";
4
+ const SCHEMA = `
5
+ PRAGMA journal_mode = WAL;
6
+ PRAGMA foreign_keys = ON;
7
+ PRAGMA synchronous = NORMAL;
8
+
9
+ CREATE TABLE IF NOT EXISTS meta (
10
+ key TEXT PRIMARY KEY,
11
+ value TEXT NOT NULL
12
+ );
13
+
14
+ CREATE TABLE IF NOT EXISTS files (
15
+ id INTEGER PRIMARY KEY,
16
+ path TEXT NOT NULL UNIQUE,
17
+ abs_path TEXT NOT NULL,
18
+ language TEXT NOT NULL DEFAULT 'text',
19
+ size INTEGER NOT NULL,
20
+ mtime_ms INTEGER NOT NULL,
21
+ content_hash TEXT NOT NULL,
22
+ line_count INTEGER NOT NULL,
23
+ indexed_at TEXT NOT NULL
24
+ );
25
+
26
+ CREATE TABLE IF NOT EXISTS chunks (
27
+ id INTEGER PRIMARY KEY,
28
+ file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,
29
+ chunk_index INTEGER NOT NULL,
30
+ start_line INTEGER NOT NULL,
31
+ end_line INTEGER NOT NULL,
32
+ content TEXT NOT NULL,
33
+ content_hash TEXT NOT NULL,
34
+ token_count INTEGER NOT NULL,
35
+ UNIQUE(file_id, chunk_index)
36
+ );
37
+
38
+ CREATE TABLE IF NOT EXISTS terms (
39
+ id INTEGER PRIMARY KEY,
40
+ term TEXT NOT NULL UNIQUE
41
+ );
42
+
43
+ CREATE TABLE IF NOT EXISTS postings (
44
+ term_id INTEGER NOT NULL REFERENCES terms(id) ON DELETE CASCADE,
45
+ chunk_id INTEGER NOT NULL REFERENCES chunks(id) ON DELETE CASCADE,
46
+ tf INTEGER NOT NULL,
47
+ PRIMARY KEY (term_id, chunk_id)
48
+ );
49
+
50
+ CREATE TABLE IF NOT EXISTS edges (
51
+ id INTEGER PRIMARY KEY,
52
+ source_file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,
53
+ target_path TEXT NOT NULL,
54
+ relation TEXT NOT NULL,
55
+ UNIQUE(source_file_id, target_path, relation)
56
+ );
57
+
58
+ CREATE TABLE IF NOT EXISTS embeddings (
59
+ chunk_id INTEGER PRIMARY KEY REFERENCES chunks(id) ON DELETE CASCADE,
60
+ model TEXT NOT NULL,
61
+ dims INTEGER NOT NULL,
62
+ vector BLOB NOT NULL
63
+ );
64
+
65
+ CREATE INDEX IF NOT EXISTS idx_chunks_file ON chunks(file_id);
66
+ CREATE INDEX IF NOT EXISTS idx_postings_chunk ON postings(chunk_id);
67
+ CREATE INDEX IF NOT EXISTS idx_edges_source ON edges(source_file_id);
68
+ CREATE INDEX IF NOT EXISTS idx_edges_target ON edges(target_path);
69
+ CREATE INDEX IF NOT EXISTS idx_files_hash ON files(content_hash);
70
+ `;
71
+ export function openDb(root) {
72
+ ensureLocalmindDir(root);
73
+ const file = dbPath(root);
74
+ const db = new DatabaseSync(file);
75
+ db.exec(SCHEMA);
76
+ setMeta(db, "schema_version", "1");
77
+ return db;
78
+ }
79
+ export function closeDb(db) {
80
+ db.close();
81
+ }
82
+ export function setMeta(db, key, value) {
83
+ db.prepare(`INSERT INTO meta(key, value) VALUES (?, ?)
84
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(key, value);
85
+ }
86
+ export function getMeta(db, key) {
87
+ const row = db.prepare(`SELECT value FROM meta WHERE key = ?`).get(key);
88
+ return row?.value ?? null;
89
+ }
90
+ export function getDbSizeBytes(root) {
91
+ const file = dbPath(root);
92
+ if (!fs.existsSync(file))
93
+ return 0;
94
+ return fs.statSync(file).size;
95
+ }
96
+ export function countTable(db, table) {
97
+ // table names are internal only
98
+ const row = db.prepare(`SELECT COUNT(*) AS c FROM ${table}`).get();
99
+ return Number(row.c);
100
+ }
101
+ export function getLastIndexedAt(db) {
102
+ const row = db
103
+ .prepare(`SELECT MAX(indexed_at) AS t FROM files`)
104
+ .get();
105
+ return row.t ?? null;
106
+ }
107
+ export function getFileByPath(db, relPath) {
108
+ return db.prepare(`SELECT * FROM files WHERE path = ?`).get(relPath);
109
+ }
110
+ export function listAllFilePaths(db) {
111
+ const rows = db.prepare(`SELECT path FROM files`).all();
112
+ return rows.map((r) => r.path);
113
+ }
114
+ export function deleteFileByPath(db, relPath) {
115
+ db.prepare(`DELETE FROM files WHERE path = ?`).run(relPath);
116
+ }
117
+ export function upsertFile(db, file) {
118
+ db.prepare(`INSERT INTO files(path, abs_path, language, size, mtime_ms, content_hash, line_count, indexed_at)
119
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
120
+ ON CONFLICT(path) DO UPDATE SET
121
+ abs_path = excluded.abs_path,
122
+ language = excluded.language,
123
+ size = excluded.size,
124
+ mtime_ms = excluded.mtime_ms,
125
+ content_hash = excluded.content_hash,
126
+ line_count = excluded.line_count,
127
+ indexed_at = excluded.indexed_at`).run(file.path, file.absPath, file.language, file.size, file.mtimeMs, file.contentHash, file.lineCount, file.indexedAt);
128
+ const row = getFileByPath(db, file.path);
129
+ if (!row)
130
+ throw new Error(`Failed to upsert file: ${file.path}`);
131
+ return row.id;
132
+ }
133
+ export function clearChunksForFile(db, fileId) {
134
+ // embeddings & postings cascade via chunk delete if FKs work;
135
+ // postings reference chunks — delete chunks will cascade if ON DELETE CASCADE
136
+ db.prepare(`DELETE FROM chunks WHERE file_id = ?`).run(fileId);
137
+ db.prepare(`DELETE FROM edges WHERE source_file_id = ?`).run(fileId);
138
+ }
139
+ export function insertChunk(db, chunk) {
140
+ const result = db
141
+ .prepare(`INSERT INTO chunks(file_id, chunk_index, start_line, end_line, content, content_hash, token_count)
142
+ VALUES (?, ?, ?, ?, ?, ?, ?)`)
143
+ .run(chunk.fileId, chunk.chunkIndex, chunk.startLine, chunk.endLine, chunk.content, chunk.contentHash, chunk.tokenCount);
144
+ return Number(result.lastInsertRowid);
145
+ }
146
+ export function getOrCreateTermId(db, term) {
147
+ db.prepare(`INSERT OR IGNORE INTO terms(term) VALUES (?)`).run(term);
148
+ const row = db.prepare(`SELECT id FROM terms WHERE term = ?`).get(term);
149
+ if (!row)
150
+ throw new Error(`Failed to create term: ${term}`);
151
+ return row.id;
152
+ }
153
+ export function insertPosting(db, termId, chunkId, tf) {
154
+ db.prepare(`INSERT INTO postings(term_id, chunk_id, tf) VALUES (?, ?, ?)
155
+ ON CONFLICT(term_id, chunk_id) DO UPDATE SET tf = excluded.tf`).run(termId, chunkId, tf);
156
+ }
157
+ export function insertEdge(db, sourceFileId, targetPath, relation) {
158
+ db.prepare(`INSERT OR IGNORE INTO edges(source_file_id, target_path, relation) VALUES (?, ?, ?)`).run(sourceFileId, targetPath, relation);
159
+ }
160
+ export function insertEmbedding(db, chunkId, model, vector) {
161
+ const buf = Buffer.from(vector.buffer, vector.byteOffset, vector.byteLength);
162
+ db.prepare(`INSERT INTO embeddings(chunk_id, model, dims, vector) VALUES (?, ?, ?, ?)
163
+ ON CONFLICT(chunk_id) DO UPDATE SET model = excluded.model, dims = excluded.dims, vector = excluded.vector`).run(chunkId, model, vector.length, buf);
164
+ }
165
+ export function pruneOrphanTerms(db) {
166
+ db.prepare(`DELETE FROM terms WHERE id NOT IN (SELECT DISTINCT term_id FROM postings)`).run();
167
+ }
168
+ export function withTransaction(db, fn) {
169
+ db.exec("BEGIN");
170
+ try {
171
+ const result = fn();
172
+ db.exec("COMMIT");
173
+ return result;
174
+ }
175
+ catch (err) {
176
+ db.exec("ROLLBACK");
177
+ throw err;
178
+ }
179
+ }
180
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/core/db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function sha256(input: string | Buffer): string;
2
+ export declare function shortHash(input: string, length?: number): string;
3
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/core/hash.ts"],"names":[],"mappings":"AAEA,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,SAAK,GAAG,MAAM,CAE5D"}
@@ -0,0 +1,8 @@
1
+ import crypto from "node:crypto";
2
+ export function sha256(input) {
3
+ return crypto.createHash("sha256").update(input).digest("hex");
4
+ }
5
+ export function shortHash(input, length = 12) {
6
+ return sha256(input).slice(0, length);
7
+ }
8
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/core/hash.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,MAAM,UAAU,MAAM,CAAC,KAAsB;IAC3C,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,MAAM,GAAG,EAAE;IAClD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,12 @@
1
+ export type LogLevel = "debug" | "info" | "warn" | "error" | "silent";
2
+ export declare function setLogLevel(level: LogLevel): void;
3
+ export declare function getLogLevel(): LogLevel;
4
+ export declare const log: {
5
+ debug(message: string): void;
6
+ info(message: string): void;
7
+ success(message: string): void;
8
+ warn(message: string): void;
9
+ error(message: string): void;
10
+ plain(message: string): void;
11
+ };
12
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAYtE,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAEjD;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAEtC;AAMD,eAAO,MAAM,GAAG;mBACC,MAAM,GAAG,IAAI;kBAGd,MAAM,GAAG,IAAI;qBAGV,MAAM,GAAG,IAAI;kBAGhB,MAAM,GAAG,IAAI;mBAGZ,MAAM,GAAG,IAAI;mBAGb,MAAM,GAAG,IAAI;CAG7B,CAAC"}
@@ -0,0 +1,45 @@
1
+ import pc from "picocolors";
2
+ const LEVEL_ORDER = {
3
+ debug: 10,
4
+ info: 20,
5
+ warn: 30,
6
+ error: 40,
7
+ silent: 100,
8
+ };
9
+ let currentLevel = "info";
10
+ export function setLogLevel(level) {
11
+ currentLevel = level;
12
+ }
13
+ export function getLogLevel() {
14
+ return currentLevel;
15
+ }
16
+ function shouldLog(level) {
17
+ return LEVEL_ORDER[level] >= LEVEL_ORDER[currentLevel];
18
+ }
19
+ export const log = {
20
+ debug(message) {
21
+ if (shouldLog("debug"))
22
+ console.error(pc.dim(`[debug] ${message}`));
23
+ },
24
+ info(message) {
25
+ if (shouldLog("info"))
26
+ console.error(pc.cyan("ℹ") + " " + message);
27
+ },
28
+ success(message) {
29
+ if (shouldLog("info"))
30
+ console.error(pc.green("✔") + " " + message);
31
+ },
32
+ warn(message) {
33
+ if (shouldLog("warn"))
34
+ console.error(pc.yellow("⚠") + " " + message);
35
+ },
36
+ error(message) {
37
+ if (shouldLog("error"))
38
+ console.error(pc.red("✖") + " " + message);
39
+ },
40
+ plain(message) {
41
+ if (shouldLog("info"))
42
+ console.log(message);
43
+ },
44
+ };
45
+ //# sourceMappingURL=logger.js.map