repomemory 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 (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +227 -0
  3. package/dist/commands/analyze.d.ts +7 -0
  4. package/dist/commands/analyze.d.ts.map +1 -0
  5. package/dist/commands/analyze.js +360 -0
  6. package/dist/commands/analyze.js.map +1 -0
  7. package/dist/commands/init.d.ts +5 -0
  8. package/dist/commands/init.d.ts.map +1 -0
  9. package/dist/commands/init.js +86 -0
  10. package/dist/commands/init.js.map +1 -0
  11. package/dist/commands/serve.d.ts +4 -0
  12. package/dist/commands/serve.d.ts.map +1 -0
  13. package/dist/commands/serve.js +13 -0
  14. package/dist/commands/serve.js.map +1 -0
  15. package/dist/commands/setup.d.ts +4 -0
  16. package/dist/commands/setup.d.ts.map +1 -0
  17. package/dist/commands/setup.js +134 -0
  18. package/dist/commands/setup.js.map +1 -0
  19. package/dist/commands/sync.d.ts +5 -0
  20. package/dist/commands/sync.d.ts.map +1 -0
  21. package/dist/commands/sync.js +77 -0
  22. package/dist/commands/sync.js.map +1 -0
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +109 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/lib/ai-provider.d.ts +18 -0
  28. package/dist/lib/ai-provider.d.ts.map +1 -0
  29. package/dist/lib/ai-provider.js +164 -0
  30. package/dist/lib/ai-provider.js.map +1 -0
  31. package/dist/lib/config.d.ts +29 -0
  32. package/dist/lib/config.d.ts.map +1 -0
  33. package/dist/lib/config.js +103 -0
  34. package/dist/lib/config.js.map +1 -0
  35. package/dist/lib/context-store.d.ts +31 -0
  36. package/dist/lib/context-store.d.ts.map +1 -0
  37. package/dist/lib/context-store.js +150 -0
  38. package/dist/lib/context-store.js.map +1 -0
  39. package/dist/lib/git.d.ts +29 -0
  40. package/dist/lib/git.d.ts.map +1 -0
  41. package/dist/lib/git.js +139 -0
  42. package/dist/lib/git.js.map +1 -0
  43. package/dist/lib/repo-scanner.d.ts +26 -0
  44. package/dist/lib/repo-scanner.d.ts.map +1 -0
  45. package/dist/lib/repo-scanner.js +213 -0
  46. package/dist/lib/repo-scanner.js.map +1 -0
  47. package/dist/lib/search.d.ts +21 -0
  48. package/dist/lib/search.d.ts.map +1 -0
  49. package/dist/lib/search.js +147 -0
  50. package/dist/lib/search.js.map +1 -0
  51. package/dist/mcp/server.d.ts +3 -0
  52. package/dist/mcp/server.d.ts.map +1 -0
  53. package/dist/mcp/server.js +324 -0
  54. package/dist/mcp/server.js.map +1 -0
  55. package/package.json +67 -0
@@ -0,0 +1,139 @@
1
+ import { execSync } from "child_process";
2
+ function exec(cmd, cwd) {
3
+ try {
4
+ return execSync(cmd, { cwd, encoding: "utf-8", timeout: 30_000 }).trim();
5
+ }
6
+ catch {
7
+ return "";
8
+ }
9
+ }
10
+ export function getGitInfo(repoRoot, maxCommits) {
11
+ const isGitRepo = exec("git rev-parse --is-inside-work-tree", repoRoot) === "true";
12
+ if (!isGitRepo) {
13
+ return {
14
+ isGitRepo: false,
15
+ currentBranch: "",
16
+ defaultBranch: "",
17
+ remoteUrl: "",
18
+ totalCommits: 0,
19
+ contributors: [],
20
+ recentCommits: [],
21
+ activeBranches: [],
22
+ lastTagOrRelease: "",
23
+ commitFrequency: "",
24
+ };
25
+ }
26
+ const currentBranch = exec("git branch --show-current", repoRoot);
27
+ // Detect default branch
28
+ let defaultBranch = exec("git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@'", repoRoot);
29
+ if (!defaultBranch) {
30
+ const branches = exec("git branch -a", repoRoot);
31
+ if (branches.includes("main"))
32
+ defaultBranch = "main";
33
+ else if (branches.includes("master"))
34
+ defaultBranch = "master";
35
+ else
36
+ defaultBranch = currentBranch;
37
+ }
38
+ const remoteUrl = exec("git remote get-url origin 2>/dev/null", repoRoot);
39
+ const totalCommitsStr = exec("git rev-list --count HEAD 2>/dev/null", repoRoot);
40
+ const totalCommits = parseInt(totalCommitsStr) || 0;
41
+ // Contributors
42
+ const contributorLines = exec("git shortlog -sn --no-merges HEAD 2>/dev/null | head -20", repoRoot);
43
+ const contributors = contributorLines
44
+ .split("\n")
45
+ .filter(Boolean)
46
+ .map((line) => {
47
+ const match = line.trim().match(/^(\d+)\s+(.+)$/);
48
+ return match
49
+ ? { name: match[2], commits: parseInt(match[1]) }
50
+ : { name: line.trim(), commits: 0 };
51
+ });
52
+ // Recent commits with stats
53
+ const commitLog = exec(`git log --format="%H|%h|%an|%ai|%s" --shortstat -n ${maxCommits} 2>/dev/null`, repoRoot);
54
+ const recentCommits = [];
55
+ const lines = commitLog.split("\n");
56
+ let i = 0;
57
+ while (i < lines.length) {
58
+ const line = lines[i];
59
+ if (!line || !line.includes("|")) {
60
+ i++;
61
+ continue;
62
+ }
63
+ const parts = line.split("|");
64
+ if (parts.length < 5) {
65
+ i++;
66
+ continue;
67
+ }
68
+ let filesChanged = 0, insertions = 0, deletions = 0;
69
+ // Check next non-empty line for stats
70
+ let j = i + 1;
71
+ while (j < lines.length && lines[j] === "")
72
+ j++;
73
+ if (j < lines.length && lines[j].includes("file")) {
74
+ const statsLine = lines[j];
75
+ const filesMatch = statsLine.match(/(\d+) files? changed/);
76
+ const insMatch = statsLine.match(/(\d+) insertions?\(\+\)/);
77
+ const delMatch = statsLine.match(/(\d+) deletions?\(-\)/);
78
+ if (filesMatch)
79
+ filesChanged = parseInt(filesMatch[1]);
80
+ if (insMatch)
81
+ insertions = parseInt(insMatch[1]);
82
+ if (delMatch)
83
+ deletions = parseInt(delMatch[1]);
84
+ i = j + 1;
85
+ }
86
+ else {
87
+ i = j;
88
+ }
89
+ recentCommits.push({
90
+ hash: parts[0],
91
+ shortHash: parts[1],
92
+ author: parts[2],
93
+ date: parts[3],
94
+ message: parts.slice(4).join("|"),
95
+ filesChanged,
96
+ insertions,
97
+ deletions,
98
+ });
99
+ }
100
+ // Active branches
101
+ const branchOutput = exec('git branch -a --sort=-committerdate --format="%(refname:short)" 2>/dev/null | head -15', repoRoot);
102
+ const activeBranches = branchOutput.split("\n").filter(Boolean);
103
+ // Last tag
104
+ const lastTagOrRelease = exec("git describe --tags --abbrev=0 2>/dev/null", repoRoot);
105
+ // Commit frequency
106
+ const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)
107
+ .toISOString()
108
+ .split("T")[0];
109
+ const recentCount = exec(`git rev-list --count --after="${thirtyDaysAgo}" HEAD 2>/dev/null`, repoRoot);
110
+ const commitsPerMonth = parseInt(recentCount) || 0;
111
+ let commitFrequency = "inactive";
112
+ if (commitsPerMonth > 100)
113
+ commitFrequency = "very active (100+/month)";
114
+ else if (commitsPerMonth > 30)
115
+ commitFrequency = "active (30+/month)";
116
+ else if (commitsPerMonth > 10)
117
+ commitFrequency = "moderate (10-30/month)";
118
+ else if (commitsPerMonth > 0)
119
+ commitFrequency = "low (<10/month)";
120
+ return {
121
+ isGitRepo,
122
+ currentBranch,
123
+ defaultBranch,
124
+ remoteUrl,
125
+ totalCommits,
126
+ contributors,
127
+ recentCommits,
128
+ activeBranches,
129
+ lastTagOrRelease,
130
+ commitFrequency,
131
+ };
132
+ }
133
+ export function getGitDiffSummary(repoRoot, since) {
134
+ return exec(`git log --since="${since}" --format="%h %s (%an, %ar)" --no-merges 2>/dev/null`, repoRoot);
135
+ }
136
+ export function getRecentDiffs(repoRoot, count) {
137
+ return exec(`git log -${count} --no-merges --format="--- %h: %s ---" --stat 2>/dev/null`, repoRoot);
138
+ }
139
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/lib/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { RepoContextConfig } from "./config.js";
2
+ export interface RepoFile {
3
+ path: string;
4
+ relativePath: string;
5
+ size: number;
6
+ isKeyFile: boolean;
7
+ }
8
+ export interface RepoScan {
9
+ root: string;
10
+ tree: string;
11
+ keyFiles: {
12
+ path: string;
13
+ content: string;
14
+ }[];
15
+ allFiles: RepoFile[];
16
+ stats: {
17
+ totalFiles: number;
18
+ totalDirs: number;
19
+ languages: Record<string, number>;
20
+ hasMonorepo: boolean;
21
+ packageManagers: string[];
22
+ frameworks: string[];
23
+ };
24
+ }
25
+ export declare function scanRepo(root: string, config: RepoContextConfig): RepoScan;
26
+ //# sourceMappingURL=repo-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-scanner.d.ts","sourceRoot":"","sources":["../../src/lib/repo-scanner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9C,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACrB,KAAK,EAAE;QACL,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClC,WAAW,EAAE,OAAO,CAAC;QACrB,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;CACH;AAwED,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,iBAAiB,GACxB,QAAQ,CAgJV"}
@@ -0,0 +1,213 @@
1
+ import { readdirSync, readFileSync, statSync } from "fs";
2
+ import { join, relative, extname, basename } from "path";
3
+ const LANGUAGE_MAP = {
4
+ ".ts": "TypeScript",
5
+ ".tsx": "TypeScript/React",
6
+ ".js": "JavaScript",
7
+ ".jsx": "JavaScript/React",
8
+ ".py": "Python",
9
+ ".rs": "Rust",
10
+ ".go": "Go",
11
+ ".java": "Java",
12
+ ".rb": "Ruby",
13
+ ".php": "PHP",
14
+ ".swift": "Swift",
15
+ ".kt": "Kotlin",
16
+ ".cs": "C#",
17
+ ".cpp": "C++",
18
+ ".c": "C",
19
+ ".vue": "Vue",
20
+ ".svelte": "Svelte",
21
+ };
22
+ const BINARY_EXTENSIONS = new Set([
23
+ ".png", ".jpg", ".jpeg", ".gif", ".ico", ".svg", ".webp", ".avif",
24
+ ".woff", ".woff2", ".ttf", ".eot", ".otf",
25
+ ".mp3", ".mp4", ".wav", ".webm", ".ogg",
26
+ ".zip", ".tar", ".gz", ".bz2", ".7z", ".rar",
27
+ ".pdf", ".doc", ".docx", ".xls", ".xlsx",
28
+ ".exe", ".dll", ".so", ".dylib",
29
+ ".sqlite", ".db",
30
+ ".wasm",
31
+ ]);
32
+ function shouldIgnore(name, ignorePatterns) {
33
+ return ignorePatterns.some((pattern) => {
34
+ if (pattern.includes("*")) {
35
+ const regex = new RegExp("^" + pattern.replace(/\*/g, ".*").replace(/\?/g, ".") + "$");
36
+ return regex.test(name);
37
+ }
38
+ return name === pattern;
39
+ });
40
+ }
41
+ function isBinaryFile(filePath) {
42
+ return BINARY_EXTENSIONS.has(extname(filePath).toLowerCase());
43
+ }
44
+ function matchesKeyPattern(relativePath, patterns) {
45
+ const name = basename(relativePath);
46
+ return patterns.some((pattern) => {
47
+ if (pattern.includes("**/")) {
48
+ const suffix = pattern.replace("**/", "");
49
+ if (suffix.includes("*")) {
50
+ const regex = new RegExp(suffix.replace(/\*/g, ".*").replace(/\?/g, "."));
51
+ return regex.test(name);
52
+ }
53
+ return relativePath.endsWith(suffix) || name === suffix;
54
+ }
55
+ if (pattern.includes("*")) {
56
+ const regex = new RegExp("^" + pattern.replace(/\*/g, ".*").replace(/\?/g, ".") + "$");
57
+ return regex.test(name);
58
+ }
59
+ return name === pattern || relativePath === pattern;
60
+ });
61
+ }
62
+ export function scanRepo(root, config) {
63
+ const allFiles = [];
64
+ const treeLines = [];
65
+ const languages = {};
66
+ let totalDirs = 0;
67
+ function walk(dir, prefix, depth) {
68
+ if (depth > 6)
69
+ return; // Don't go too deep
70
+ let entries;
71
+ try {
72
+ entries = readdirSync(dir).sort();
73
+ }
74
+ catch {
75
+ return;
76
+ }
77
+ const filtered = entries.filter((e) => !shouldIgnore(e, config.ignorePatterns) && !e.startsWith("."));
78
+ filtered.forEach((entry, idx) => {
79
+ const fullPath = join(dir, entry);
80
+ const relPath = relative(root, fullPath);
81
+ const isLast = idx === filtered.length - 1;
82
+ const connector = isLast ? "└── " : "├── ";
83
+ const childPrefix = isLast ? " " : "│ ";
84
+ try {
85
+ const stat = statSync(fullPath);
86
+ if (stat.isDirectory()) {
87
+ totalDirs++;
88
+ treeLines.push(`${prefix}${connector}${entry}/`);
89
+ walk(fullPath, prefix + childPrefix, depth + 1);
90
+ }
91
+ else {
92
+ // Track file
93
+ const ext = extname(entry).toLowerCase();
94
+ if (LANGUAGE_MAP[ext]) {
95
+ languages[LANGUAGE_MAP[ext]] =
96
+ (languages[LANGUAGE_MAP[ext]] || 0) + 1;
97
+ }
98
+ // Only add to tree at shallow depths
99
+ if (depth <= 3) {
100
+ treeLines.push(`${prefix}${connector}${entry}`);
101
+ }
102
+ allFiles.push({
103
+ path: fullPath,
104
+ relativePath: relPath,
105
+ size: stat.size,
106
+ isKeyFile: matchesKeyPattern(relPath, config.keyFilePatterns),
107
+ });
108
+ }
109
+ }
110
+ catch {
111
+ // Skip files we can't stat
112
+ }
113
+ });
114
+ }
115
+ walk(root, "", 0);
116
+ // Detect frameworks and package managers
117
+ const packageManagers = [];
118
+ const frameworks = [];
119
+ const fileNames = new Set(allFiles.map((f) => basename(f.relativePath)));
120
+ if (fileNames.has("package-lock.json"))
121
+ packageManagers.push("npm");
122
+ if (fileNames.has("yarn.lock"))
123
+ packageManagers.push("yarn");
124
+ if (fileNames.has("pnpm-lock.yaml"))
125
+ packageManagers.push("pnpm");
126
+ if (fileNames.has("bun.lockb"))
127
+ packageManagers.push("bun");
128
+ // Read package.json for framework detection
129
+ const pkgJsonPath = join(root, "package.json");
130
+ try {
131
+ const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
132
+ const allDeps = {
133
+ ...pkg.dependencies,
134
+ ...pkg.devDependencies,
135
+ };
136
+ if (allDeps["next"])
137
+ frameworks.push("Next.js");
138
+ if (allDeps["react"])
139
+ frameworks.push("React");
140
+ if (allDeps["vue"])
141
+ frameworks.push("Vue");
142
+ if (allDeps["svelte"])
143
+ frameworks.push("Svelte");
144
+ if (allDeps["express"])
145
+ frameworks.push("Express");
146
+ if (allDeps["fastify"])
147
+ frameworks.push("Fastify");
148
+ if (allDeps["hono"])
149
+ frameworks.push("Hono");
150
+ if (allDeps["drizzle-orm"])
151
+ frameworks.push("Drizzle ORM");
152
+ if (allDeps["prisma"] || allDeps["@prisma/client"])
153
+ frameworks.push("Prisma");
154
+ if (allDeps["django"])
155
+ frameworks.push("Django");
156
+ if (allDeps["flask"])
157
+ frameworks.push("Flask");
158
+ if (allDeps["@cloudflare/workers-types"])
159
+ frameworks.push("Cloudflare Workers");
160
+ }
161
+ catch {
162
+ // No package.json or can't parse
163
+ }
164
+ // Check for monorepo
165
+ const hasWorkspaces = allFiles.some((f) => f.relativePath === "pnpm-workspace.yaml") ||
166
+ allFiles.some((f) => {
167
+ if (basename(f.relativePath) !== "package.json" || f.relativePath !== "package.json")
168
+ return false;
169
+ try {
170
+ const pkg = JSON.parse(readFileSync(f.path, "utf-8"));
171
+ return pkg.workspaces != null;
172
+ }
173
+ catch {
174
+ return false;
175
+ }
176
+ });
177
+ // Read key files
178
+ const keyFiles = allFiles
179
+ .filter((f) => f.isKeyFile && !isBinaryFile(f.path) && f.size <= config.maxFileSize)
180
+ .sort((a, b) => {
181
+ // Prioritize root-level files
182
+ const aDepth = a.relativePath.split("/").length;
183
+ const bDepth = b.relativePath.split("/").length;
184
+ return aDepth - bDepth;
185
+ })
186
+ .slice(0, config.maxFilesForAnalysis)
187
+ .map((f) => {
188
+ try {
189
+ return {
190
+ path: f.relativePath,
191
+ content: readFileSync(f.path, "utf-8").slice(0, config.maxFileSize),
192
+ };
193
+ }
194
+ catch {
195
+ return { path: f.relativePath, content: "[Could not read file]" };
196
+ }
197
+ });
198
+ return {
199
+ root,
200
+ tree: treeLines.join("\n"),
201
+ keyFiles,
202
+ allFiles,
203
+ stats: {
204
+ totalFiles: allFiles.length,
205
+ totalDirs,
206
+ languages,
207
+ hasMonorepo: hasWorkspaces,
208
+ packageManagers,
209
+ frameworks,
210
+ },
211
+ };
212
+ }
213
+ //# sourceMappingURL=repo-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-scanner.js","sourceRoot":"","sources":["../../src/lib/repo-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { ContextStore, ContextEntry } from "./context-store.js";
2
+ export interface SearchResult {
3
+ category: string;
4
+ filename: string;
5
+ title: string;
6
+ snippet: string;
7
+ score: number;
8
+ relativePath: string;
9
+ }
10
+ export declare class SearchIndex {
11
+ private db;
12
+ private store;
13
+ constructor(contextDir: string, store: ContextStore);
14
+ private init;
15
+ rebuild(): void;
16
+ indexEntry(entry: ContextEntry): void;
17
+ search(query: string, category?: string, limit?: number): SearchResult[];
18
+ private extractSnippet;
19
+ close(): void;
20
+ }
21
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAErE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,KAAK,CAAe;gBAEhB,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY;IAOnD,OAAO,CAAC,IAAI;IAoDZ,OAAO,IAAI,IAAI;IA0Bf,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAkBrC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,YAAY,EAAE;IAqD5E,OAAO,CAAC,cAAc;IA8BtB,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,147 @@
1
+ import Database from "better-sqlite3";
2
+ import { join } from "path";
3
+ export class SearchIndex {
4
+ db;
5
+ store;
6
+ constructor(contextDir, store) {
7
+ const dbPath = join(contextDir, ".search.db");
8
+ this.db = new Database(dbPath);
9
+ this.store = store;
10
+ this.init();
11
+ }
12
+ init() {
13
+ this.db.pragma("journal_mode = WAL");
14
+ this.db.exec(`
15
+ CREATE TABLE IF NOT EXISTS documents (
16
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
17
+ category TEXT NOT NULL,
18
+ filename TEXT NOT NULL,
19
+ title TEXT NOT NULL,
20
+ content TEXT NOT NULL,
21
+ relative_path TEXT NOT NULL,
22
+ updated_at TEXT NOT NULL,
23
+ UNIQUE(category, filename)
24
+ )
25
+ `);
26
+ this.db.exec(`
27
+ CREATE VIRTUAL TABLE IF NOT EXISTS documents_fts USING fts5(
28
+ title,
29
+ content,
30
+ category,
31
+ content=documents,
32
+ content_rowid=id,
33
+ tokenize='porter unicode61'
34
+ )
35
+ `);
36
+ // Triggers to keep FTS in sync
37
+ this.db.exec(`
38
+ CREATE TRIGGER IF NOT EXISTS documents_ai AFTER INSERT ON documents BEGIN
39
+ INSERT INTO documents_fts(rowid, title, content, category)
40
+ VALUES (new.id, new.title, new.content, new.category);
41
+ END
42
+ `);
43
+ this.db.exec(`
44
+ CREATE TRIGGER IF NOT EXISTS documents_ad AFTER DELETE ON documents BEGIN
45
+ INSERT INTO documents_fts(documents_fts, rowid, title, content, category)
46
+ VALUES ('delete', old.id, old.title, old.content, old.category);
47
+ END
48
+ `);
49
+ this.db.exec(`
50
+ CREATE TRIGGER IF NOT EXISTS documents_au AFTER UPDATE ON documents BEGIN
51
+ INSERT INTO documents_fts(documents_fts, rowid, title, content, category)
52
+ VALUES ('delete', old.id, old.title, old.content, old.category);
53
+ INSERT INTO documents_fts(rowid, title, content, category)
54
+ VALUES (new.id, new.title, new.content, new.category);
55
+ END
56
+ `);
57
+ }
58
+ rebuild() {
59
+ // Clear existing data
60
+ this.db.exec("DELETE FROM documents");
61
+ const entries = this.store.listEntries();
62
+ const insert = this.db.prepare(`
63
+ INSERT OR REPLACE INTO documents (category, filename, title, content, relative_path, updated_at)
64
+ VALUES (?, ?, ?, ?, ?, ?)
65
+ `);
66
+ const tx = this.db.transaction((entries) => {
67
+ for (const entry of entries) {
68
+ insert.run(entry.category, entry.filename, entry.title, entry.content, entry.relativePath, entry.lastModified.toISOString());
69
+ }
70
+ });
71
+ tx(entries);
72
+ }
73
+ indexEntry(entry) {
74
+ this.db
75
+ .prepare(`
76
+ INSERT OR REPLACE INTO documents (category, filename, title, content, relative_path, updated_at)
77
+ VALUES (?, ?, ?, ?, ?, ?)
78
+ `)
79
+ .run(entry.category, entry.filename, entry.title, entry.content, entry.relativePath, entry.lastModified.toISOString());
80
+ }
81
+ search(query, category, limit = 10) {
82
+ // Escape special FTS5 characters
83
+ const escapedQuery = query
84
+ .replace(/['"]/g, "")
85
+ .split(/\s+/)
86
+ .filter(Boolean)
87
+ .map((term) => `"${term}"`)
88
+ .join(" OR ");
89
+ if (!escapedQuery)
90
+ return [];
91
+ let sql = `
92
+ SELECT
93
+ d.category,
94
+ d.filename,
95
+ d.title,
96
+ d.content,
97
+ d.relative_path,
98
+ rank * -1 as score
99
+ FROM documents_fts
100
+ JOIN documents d ON d.id = documents_fts.rowid
101
+ WHERE documents_fts MATCH ?
102
+ `;
103
+ const params = [escapedQuery];
104
+ if (category) {
105
+ sql += " AND d.category = ?";
106
+ params.push(category);
107
+ }
108
+ sql += " ORDER BY rank LIMIT ?";
109
+ params.push(limit);
110
+ const rows = this.db.prepare(sql).all(...params);
111
+ return rows.map((row) => ({
112
+ category: row.category,
113
+ filename: row.filename,
114
+ title: row.title,
115
+ snippet: this.extractSnippet(row.content, query),
116
+ score: row.score,
117
+ relativePath: row.relative_path,
118
+ }));
119
+ }
120
+ extractSnippet(content, query, maxLength = 500) {
121
+ const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
122
+ const lines = content.split("\n");
123
+ // Find lines containing query terms
124
+ const matchingLines = [];
125
+ for (let i = 0; i < lines.length; i++) {
126
+ const lower = lines[i].toLowerCase();
127
+ const matchCount = terms.filter((t) => lower.includes(t)).length;
128
+ if (matchCount > 0) {
129
+ matchingLines.push({ line: lines[i], index: i, matchCount });
130
+ }
131
+ }
132
+ if (matchingLines.length === 0) {
133
+ return content.slice(0, maxLength);
134
+ }
135
+ // Sort by match count, take best matches
136
+ matchingLines.sort((a, b) => b.matchCount - a.matchCount);
137
+ // Build snippet from best matching region
138
+ const bestMatch = matchingLines[0];
139
+ const start = Math.max(0, bestMatch.index - 2);
140
+ const end = Math.min(lines.length, bestMatch.index + 5);
141
+ return lines.slice(start, end).join("\n").slice(0, maxLength);
142
+ }
143
+ close() {
144
+ this.db.close();
145
+ }
146
+ }
147
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { RepoContextConfig } from "../lib/config.js";
2
+ export declare function startMcpServer(repoRoot: string, config: RepoContextConfig): Promise<void>;
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,IAAI,CAAC,CAwXf"}