@mars167/git-ai 2.3.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 +22 -0
- package/README.md +364 -0
- package/README.zh-CN.md +361 -0
- package/assets/hooks/post-checkout +28 -0
- package/assets/hooks/post-merge +28 -0
- package/assets/hooks/pre-commit +17 -0
- package/assets/hooks/pre-push +29 -0
- package/dist/bin/git-ai.js +62 -0
- package/dist/src/commands/ai.js +30 -0
- package/dist/src/commands/checkIndex.js +19 -0
- package/dist/src/commands/dsr.js +156 -0
- package/dist/src/commands/graph.js +203 -0
- package/dist/src/commands/hooks.js +125 -0
- package/dist/src/commands/index.js +92 -0
- package/dist/src/commands/pack.js +31 -0
- package/dist/src/commands/query.js +139 -0
- package/dist/src/commands/semantic.js +134 -0
- package/dist/src/commands/serve.js +14 -0
- package/dist/src/commands/status.js +78 -0
- package/dist/src/commands/trae.js +75 -0
- package/dist/src/commands/unpack.js +28 -0
- package/dist/src/core/archive.js +91 -0
- package/dist/src/core/astGraph.js +127 -0
- package/dist/src/core/astGraphQuery.js +142 -0
- package/dist/src/core/cozo.js +266 -0
- package/dist/src/core/cpg/astLayer.js +56 -0
- package/dist/src/core/cpg/callGraph.js +483 -0
- package/dist/src/core/cpg/cfgLayer.js +490 -0
- package/dist/src/core/cpg/dfgLayer.js +237 -0
- package/dist/src/core/cpg/index.js +80 -0
- package/dist/src/core/cpg/types.js +108 -0
- package/dist/src/core/crypto.js +10 -0
- package/dist/src/core/dsr/generate.js +308 -0
- package/dist/src/core/dsr/gitContext.js +74 -0
- package/dist/src/core/dsr/indexMaterialize.js +106 -0
- package/dist/src/core/dsr/paths.js +26 -0
- package/dist/src/core/dsr/query.js +73 -0
- package/dist/src/core/dsr/snapshotParser.js +73 -0
- package/dist/src/core/dsr/state.js +27 -0
- package/dist/src/core/dsr/types.js +2 -0
- package/dist/src/core/embedding/fusion.js +52 -0
- package/dist/src/core/embedding/index.js +43 -0
- package/dist/src/core/embedding/parser.js +14 -0
- package/dist/src/core/embedding/semantic.js +254 -0
- package/dist/src/core/embedding/structural.js +97 -0
- package/dist/src/core/embedding/symbolic.js +117 -0
- package/dist/src/core/embedding/tokenizer.js +91 -0
- package/dist/src/core/embedding/types.js +2 -0
- package/dist/src/core/embedding.js +36 -0
- package/dist/src/core/git.js +49 -0
- package/dist/src/core/gitDiff.js +73 -0
- package/dist/src/core/indexCheck.js +131 -0
- package/dist/src/core/indexer.js +185 -0
- package/dist/src/core/indexerIncremental.js +303 -0
- package/dist/src/core/indexing/config.js +51 -0
- package/dist/src/core/indexing/hnsw.js +568 -0
- package/dist/src/core/indexing/index.js +17 -0
- package/dist/src/core/indexing/monitor.js +82 -0
- package/dist/src/core/indexing/parallel.js +252 -0
- package/dist/src/core/lancedb.js +111 -0
- package/dist/src/core/lfs.js +27 -0
- package/dist/src/core/log.js +62 -0
- package/dist/src/core/manifest.js +88 -0
- package/dist/src/core/parser/adapter.js +2 -0
- package/dist/src/core/parser/c.js +93 -0
- package/dist/src/core/parser/chunkRelations.js +178 -0
- package/dist/src/core/parser/chunker.js +274 -0
- package/dist/src/core/parser/go.js +98 -0
- package/dist/src/core/parser/java.js +80 -0
- package/dist/src/core/parser/markdown.js +76 -0
- package/dist/src/core/parser/python.js +81 -0
- package/dist/src/core/parser/rust.js +103 -0
- package/dist/src/core/parser/typescript.js +98 -0
- package/dist/src/core/parser/utils.js +62 -0
- package/dist/src/core/parser/yaml.js +53 -0
- package/dist/src/core/parser.js +75 -0
- package/dist/src/core/paths.js +10 -0
- package/dist/src/core/repoMap.js +164 -0
- package/dist/src/core/retrieval/cache.js +31 -0
- package/dist/src/core/retrieval/classifier.js +74 -0
- package/dist/src/core/retrieval/expander.js +80 -0
- package/dist/src/core/retrieval/fuser.js +40 -0
- package/dist/src/core/retrieval/index.js +32 -0
- package/dist/src/core/retrieval/reranker.js +304 -0
- package/dist/src/core/retrieval/types.js +2 -0
- package/dist/src/core/retrieval/weights.js +42 -0
- package/dist/src/core/search.js +41 -0
- package/dist/src/core/sq8.js +65 -0
- package/dist/src/core/symbolSearch.js +143 -0
- package/dist/src/core/types.js +2 -0
- package/dist/src/core/workspace.js +116 -0
- package/dist/src/mcp/server.js +794 -0
- package/docs/README.md +44 -0
- package/docs/cross-encoder.md +157 -0
- package/docs/embedding.md +158 -0
- package/docs/logo.png +0 -0
- package/docs/windows-setup.md +67 -0
- package/docs/zh-CN/DESIGN.md +102 -0
- package/docs/zh-CN/README.md +46 -0
- package/docs/zh-CN/advanced.md +26 -0
- package/docs/zh-CN/architecture_explained.md +116 -0
- package/docs/zh-CN/cli.md +109 -0
- package/docs/zh-CN/dsr.md +91 -0
- package/docs/zh-CN/graph_scenarios.md +173 -0
- package/docs/zh-CN/hooks.md +14 -0
- package/docs/zh-CN/manifests.md +136 -0
- package/docs/zh-CN/mcp.md +205 -0
- package/docs/zh-CN/quickstart.md +35 -0
- package/docs/zh-CN/rules.md +7 -0
- package/docs/zh-CN/technical-details.md +454 -0
- package/docs/zh-CN/troubleshooting.md +19 -0
- package/docs/zh-CN/windows-setup.md +67 -0
- package/install.sh +183 -0
- package/package.json +97 -0
- package/skills/git-ai-mcp/SKILL.md +86 -0
- package/skills/git-ai-mcp/references/constraints.md +143 -0
- package/skills/git-ai-mcp/references/tools.md +263 -0
- package/templates/agents/common/documents/Fix EISDIR error and enable multi-language indexing.md +14 -0
- package/templates/agents/common/documents/Fix git-ai index error in CodaGraph directory.md +13 -0
- package/templates/agents/common/skills/git-ai-mcp/SKILL.md +86 -0
- package/templates/agents/common/skills/git-ai-mcp/references/constraints.md +143 -0
- package/templates/agents/common/skills/git-ai-mcp/references/tools.md +263 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hashEmbedding = hashEmbedding;
|
|
4
|
+
const crypto_1 = require("./crypto");
|
|
5
|
+
function tokenise(text) {
|
|
6
|
+
return (text || '')
|
|
7
|
+
.toLowerCase()
|
|
8
|
+
.split(/[^a-z0-9_]+/g)
|
|
9
|
+
.filter(Boolean);
|
|
10
|
+
}
|
|
11
|
+
function hashToUint32(hex) {
|
|
12
|
+
return parseInt(hex.slice(0, 8), 16) >>> 0;
|
|
13
|
+
}
|
|
14
|
+
function hashEmbedding(text, options) {
|
|
15
|
+
const dim = options.dim;
|
|
16
|
+
const vec = new Float32Array(dim);
|
|
17
|
+
const tokens = tokenise(text);
|
|
18
|
+
if (tokens.length === 0)
|
|
19
|
+
return Array.from(vec);
|
|
20
|
+
for (const t of tokens) {
|
|
21
|
+
const h = (0, crypto_1.sha256Hex)(t);
|
|
22
|
+
const u = hashToUint32(h);
|
|
23
|
+
const idx = u % dim;
|
|
24
|
+
const sign = (u & 1) === 0 ? 1 : -1;
|
|
25
|
+
vec[idx] += sign;
|
|
26
|
+
}
|
|
27
|
+
let norm = 0;
|
|
28
|
+
for (let i = 0; i < dim; i++)
|
|
29
|
+
norm += vec[i] * vec[i];
|
|
30
|
+
norm = Math.sqrt(norm);
|
|
31
|
+
if (norm > 0) {
|
|
32
|
+
for (let i = 0; i < dim; i++)
|
|
33
|
+
vec[i] = vec[i] / norm;
|
|
34
|
+
}
|
|
35
|
+
return Array.from(vec);
|
|
36
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveGitRoot = resolveGitRoot;
|
|
7
|
+
exports.inferScanRoot = inferScanRoot;
|
|
8
|
+
exports.inferWorkspaceRoot = inferWorkspaceRoot;
|
|
9
|
+
exports.getCurrentCommitHash = getCurrentCommitHash;
|
|
10
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
async function resolveGitRoot(startDir) {
|
|
13
|
+
const resolved = path_1.default.resolve(startDir);
|
|
14
|
+
try {
|
|
15
|
+
const git = (0, simple_git_1.default)(resolved);
|
|
16
|
+
const root = await git.raw(['rev-parse', '--show-toplevel']);
|
|
17
|
+
return root.trim();
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return resolved;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function inferScanRoot(repoRoot) {
|
|
24
|
+
return path_1.default.resolve(repoRoot);
|
|
25
|
+
}
|
|
26
|
+
function inferWorkspaceRoot(repoRoot) {
|
|
27
|
+
const resolved = path_1.default.resolve(repoRoot);
|
|
28
|
+
const parts = resolved.split(path_1.default.sep).filter(Boolean);
|
|
29
|
+
const repoIdx = parts.lastIndexOf('.repo');
|
|
30
|
+
if (repoIdx >= 0 && repoIdx + 1 < parts.length) {
|
|
31
|
+
const next = parts[repoIdx + 1];
|
|
32
|
+
if (next === 'manifests' || next === 'manifests.git') {
|
|
33
|
+
const prefixParts = parts.slice(0, repoIdx);
|
|
34
|
+
const prefix = prefixParts.length === 0 ? path_1.default.parse(resolved).root : path_1.default.join(path_1.default.parse(resolved).root, ...prefixParts);
|
|
35
|
+
return prefix;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
async function getCurrentCommitHash(repoRoot) {
|
|
41
|
+
try {
|
|
42
|
+
const git = (0, simple_git_1.default)(repoRoot);
|
|
43
|
+
const hash = await git.raw(['rev-parse', 'HEAD']);
|
|
44
|
+
return hash.trim();
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getStagedNameStatus = getStagedNameStatus;
|
|
7
|
+
exports.getWorktreeNameStatus = getWorktreeNameStatus;
|
|
8
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
9
|
+
function splitZ(raw) {
|
|
10
|
+
return raw.split('\0').map((s) => s.trim()).filter(Boolean);
|
|
11
|
+
}
|
|
12
|
+
async function getStagedNameStatus(repoRoot) {
|
|
13
|
+
const git = (0, simple_git_1.default)(repoRoot);
|
|
14
|
+
const raw = await git.raw(['diff', '--cached', '--name-status', '-z', '--find-renames']);
|
|
15
|
+
const parts = splitZ(raw);
|
|
16
|
+
const out = [];
|
|
17
|
+
for (let i = 0; i < parts.length; i++) {
|
|
18
|
+
const entry = parts[i] ?? '';
|
|
19
|
+
if (!entry)
|
|
20
|
+
continue;
|
|
21
|
+
const tabIdx = entry.indexOf('\t');
|
|
22
|
+
const statusRaw = tabIdx >= 0 ? entry.slice(0, tabIdx) : entry;
|
|
23
|
+
const rest = tabIdx >= 0 ? entry.slice(tabIdx + 1) : '';
|
|
24
|
+
const statusLetter = statusRaw[0] ?? '';
|
|
25
|
+
if (statusLetter === 'R') {
|
|
26
|
+
const oldPath = rest;
|
|
27
|
+
const newPath = parts[i + 1] ?? '';
|
|
28
|
+
i += 1;
|
|
29
|
+
if (oldPath && newPath)
|
|
30
|
+
out.push({ status: 'R', oldPath, path: newPath });
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (statusLetter === 'A' || statusLetter === 'M' || statusLetter === 'D') {
|
|
34
|
+
const p = rest;
|
|
35
|
+
if (p)
|
|
36
|
+
out.push({ status: statusLetter, path: p });
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
out.sort((a, b) => `${a.status}\t${a.oldPath ?? ''}\t${a.path}`.localeCompare(`${b.status}\t${b.oldPath ?? ''}\t${b.path}`));
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
async function getWorktreeNameStatus(repoRoot) {
|
|
44
|
+
const git = (0, simple_git_1.default)(repoRoot);
|
|
45
|
+
const raw = await git.raw(['diff', '--name-status', '-z', '--find-renames']);
|
|
46
|
+
const parts = splitZ(raw);
|
|
47
|
+
const out = [];
|
|
48
|
+
for (let i = 0; i < parts.length; i++) {
|
|
49
|
+
const entry = parts[i] ?? '';
|
|
50
|
+
if (!entry)
|
|
51
|
+
continue;
|
|
52
|
+
const tabIdx = entry.indexOf('\t');
|
|
53
|
+
const statusRaw = tabIdx >= 0 ? entry.slice(0, tabIdx) : entry;
|
|
54
|
+
const rest = tabIdx >= 0 ? entry.slice(tabIdx + 1) : '';
|
|
55
|
+
const statusLetter = statusRaw[0] ?? '';
|
|
56
|
+
if (statusLetter === 'R') {
|
|
57
|
+
const oldPath = rest;
|
|
58
|
+
const newPath = parts[i + 1] ?? '';
|
|
59
|
+
i += 1;
|
|
60
|
+
if (oldPath && newPath)
|
|
61
|
+
out.push({ status: 'R', oldPath, path: newPath });
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (statusLetter === 'A' || statusLetter === 'M' || statusLetter === 'D') {
|
|
65
|
+
const p = rest;
|
|
66
|
+
if (p)
|
|
67
|
+
out.push({ status: statusLetter, path: p });
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
out.sort((a, b) => `${a.status}\t${a.oldPath ?? ''}\t${a.path}`.localeCompare(`${b.status}\t${b.oldPath ?? ''}\t${b.path}`));
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.EXPECTED_INDEX_SCHEMA_VERSION = void 0;
|
|
40
|
+
exports.resolveLangs = resolveLangs;
|
|
41
|
+
exports.checkIndex = checkIndex;
|
|
42
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
43
|
+
const path_1 = __importDefault(require("path"));
|
|
44
|
+
const lancedb = __importStar(require("@lancedb/lancedb"));
|
|
45
|
+
const lancedb_1 = require("./lancedb");
|
|
46
|
+
const git_1 = require("./git");
|
|
47
|
+
exports.EXPECTED_INDEX_SCHEMA_VERSION = 3;
|
|
48
|
+
function requiredTablesForLang(lang) {
|
|
49
|
+
return [`chunks_${lang}`, `refs_${lang}`];
|
|
50
|
+
}
|
|
51
|
+
function resolveLangs(meta, selector) {
|
|
52
|
+
const raw = Array.isArray(meta?.languages) ? meta.languages.map((v) => String(v)) : [];
|
|
53
|
+
const filtered = raw.filter((l) => lancedb_1.ALL_INDEX_LANGS.includes(l));
|
|
54
|
+
const available = filtered.length > 0 ? filtered : ['java', 'ts'];
|
|
55
|
+
if (selector === 'all')
|
|
56
|
+
return available;
|
|
57
|
+
if (selector !== 'auto')
|
|
58
|
+
return available.includes(selector) ? [selector] : [];
|
|
59
|
+
const preferred = ['java', 'ts', 'python', 'go', 'rust', 'c', 'markdown', 'yaml'];
|
|
60
|
+
for (const lang of preferred) {
|
|
61
|
+
if (available.includes(lang))
|
|
62
|
+
return [lang];
|
|
63
|
+
}
|
|
64
|
+
return available.slice(0, 1);
|
|
65
|
+
}
|
|
66
|
+
async function checkIndex(repoRoot) {
|
|
67
|
+
const metaPath = path_1.default.join(repoRoot, '.git-ai', 'meta.json');
|
|
68
|
+
const lancedbDir = path_1.default.join(repoRoot, '.git-ai', 'lancedb');
|
|
69
|
+
const astGraphDbPath = path_1.default.join(repoRoot, '.git-ai', 'ast-graph.sqlite');
|
|
70
|
+
const problems = [];
|
|
71
|
+
const warnings = [];
|
|
72
|
+
const meta = await fs_extra_1.default.pathExists(metaPath) ? await fs_extra_1.default.readJSON(metaPath).catch(() => null) : null;
|
|
73
|
+
const currentCommitHash = await (0, git_1.getCurrentCommitHash)(repoRoot);
|
|
74
|
+
if (!meta) {
|
|
75
|
+
problems.push('missing_or_unreadable_meta_json');
|
|
76
|
+
}
|
|
77
|
+
else if (meta.index_schema_version !== exports.EXPECTED_INDEX_SCHEMA_VERSION) {
|
|
78
|
+
problems.push(`index_schema_version_mismatch(found=${String(meta.index_schema_version ?? 'null')}, expected=${exports.EXPECTED_INDEX_SCHEMA_VERSION})`);
|
|
79
|
+
}
|
|
80
|
+
// Check if index commit hash matches current HEAD
|
|
81
|
+
if (meta && currentCommitHash) {
|
|
82
|
+
if (meta.commit_hash && meta.commit_hash !== currentCommitHash) {
|
|
83
|
+
warnings.push(`index_commit_mismatch(index=${meta.commit_hash.slice(0, 7)}, head=${currentCommitHash.slice(0, 7)})`);
|
|
84
|
+
}
|
|
85
|
+
else if (!meta.commit_hash) {
|
|
86
|
+
warnings.push('index_commit_hash_not_recorded');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
let lancedbTables;
|
|
90
|
+
if (await fs_extra_1.default.pathExists(lancedbDir)) {
|
|
91
|
+
try {
|
|
92
|
+
const db = await lancedb.connect(lancedbDir);
|
|
93
|
+
lancedbTables = await db.tableNames();
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
problems.push('lancedb_open_failed');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
problems.push('missing_lancedb_dir');
|
|
101
|
+
}
|
|
102
|
+
const astGraphDbExists = await fs_extra_1.default.pathExists(astGraphDbPath);
|
|
103
|
+
if (!astGraphDbExists)
|
|
104
|
+
problems.push('missing_ast_graph_db');
|
|
105
|
+
if (meta && lancedbTables) {
|
|
106
|
+
const raw = Array.isArray(meta.languages) ? meta.languages.map((v) => String(v)) : [];
|
|
107
|
+
const langs = raw.filter((l) => lancedb_1.ALL_INDEX_LANGS.includes(l));
|
|
108
|
+
const expectedTables = langs.flatMap(requiredTablesForLang);
|
|
109
|
+
for (const t of expectedTables) {
|
|
110
|
+
if (!lancedbTables.includes(t))
|
|
111
|
+
problems.push(`missing_lancedb_table(${t})`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const ok = problems.length === 0;
|
|
115
|
+
return {
|
|
116
|
+
ok,
|
|
117
|
+
problems,
|
|
118
|
+
warnings,
|
|
119
|
+
expected: { index_schema_version: exports.EXPECTED_INDEX_SCHEMA_VERSION },
|
|
120
|
+
found: {
|
|
121
|
+
metaPath,
|
|
122
|
+
meta,
|
|
123
|
+
lancedbDir,
|
|
124
|
+
lancedbTables,
|
|
125
|
+
astGraphDbPath,
|
|
126
|
+
astGraphDbExists,
|
|
127
|
+
currentCommitHash,
|
|
128
|
+
},
|
|
129
|
+
hint: ok ? 'ok' : 'Rebuild index: git-ai ai index --overwrite',
|
|
130
|
+
};
|
|
131
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.IndexerV2 = void 0;
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const glob_1 = require("glob");
|
|
10
|
+
const config_1 = require("./indexing/config");
|
|
11
|
+
const parallel_1 = require("./indexing/parallel");
|
|
12
|
+
const lancedb_1 = require("./lancedb");
|
|
13
|
+
const astGraph_1 = require("./astGraph");
|
|
14
|
+
const git_1 = require("./git");
|
|
15
|
+
async function loadIgnorePatterns(repoRoot, fileName) {
|
|
16
|
+
const ignorePath = path_1.default.join(repoRoot, fileName);
|
|
17
|
+
if (!await fs_extra_1.default.pathExists(ignorePath))
|
|
18
|
+
return [];
|
|
19
|
+
const raw = await fs_extra_1.default.readFile(ignorePath, 'utf-8');
|
|
20
|
+
return raw
|
|
21
|
+
.split('\n')
|
|
22
|
+
.map(l => l.trim())
|
|
23
|
+
.map((l) => {
|
|
24
|
+
if (l.length === 0)
|
|
25
|
+
return null;
|
|
26
|
+
if (l.startsWith('#'))
|
|
27
|
+
return null;
|
|
28
|
+
if (l.startsWith('!'))
|
|
29
|
+
return null;
|
|
30
|
+
const withoutLeadingSlash = l.startsWith('/') ? l.slice(1) : l;
|
|
31
|
+
if (withoutLeadingSlash.endsWith('/'))
|
|
32
|
+
return `${withoutLeadingSlash}**`;
|
|
33
|
+
return withoutLeadingSlash;
|
|
34
|
+
})
|
|
35
|
+
.filter((l) => Boolean(l));
|
|
36
|
+
}
|
|
37
|
+
function inferIndexLang(file) {
|
|
38
|
+
if (file.endsWith('.md') || file.endsWith('.mdx'))
|
|
39
|
+
return 'markdown';
|
|
40
|
+
if (file.endsWith('.yml') || file.endsWith('.yaml'))
|
|
41
|
+
return 'yaml';
|
|
42
|
+
if (file.endsWith('.java'))
|
|
43
|
+
return 'java';
|
|
44
|
+
if (file.endsWith('.c') || file.endsWith('.h'))
|
|
45
|
+
return 'c';
|
|
46
|
+
if (file.endsWith('.go'))
|
|
47
|
+
return 'go';
|
|
48
|
+
if (file.endsWith('.py'))
|
|
49
|
+
return 'python';
|
|
50
|
+
if (file.endsWith('.rs'))
|
|
51
|
+
return 'rust';
|
|
52
|
+
return 'ts';
|
|
53
|
+
}
|
|
54
|
+
class IndexerV2 {
|
|
55
|
+
constructor(options) {
|
|
56
|
+
this.repoRoot = path_1.default.resolve(options.repoRoot);
|
|
57
|
+
this.scanRoot = path_1.default.resolve(options.scanRoot ?? options.repoRoot);
|
|
58
|
+
this.dim = options.dim;
|
|
59
|
+
this.overwrite = options.overwrite;
|
|
60
|
+
this.onProgress = options.onProgress;
|
|
61
|
+
this.config = (0, config_1.mergeRuntimeConfig)(options.config);
|
|
62
|
+
}
|
|
63
|
+
async run() {
|
|
64
|
+
const gitAiDir = path_1.default.join(this.repoRoot, '.git-ai');
|
|
65
|
+
await fs_extra_1.default.ensureDir(gitAiDir);
|
|
66
|
+
const dbDir = (0, lancedb_1.defaultDbDir)(this.repoRoot);
|
|
67
|
+
const aiIgnore = await loadIgnorePatterns(this.repoRoot, '.aiignore');
|
|
68
|
+
const gitIgnore = await loadIgnorePatterns(this.repoRoot, '.gitignore');
|
|
69
|
+
const files = await (0, glob_1.glob)('**/*.{ts,tsx,js,jsx,java,c,h,go,py,rs,md,mdx,yml,yaml}', {
|
|
70
|
+
cwd: this.scanRoot,
|
|
71
|
+
nodir: true,
|
|
72
|
+
ignore: [
|
|
73
|
+
'node_modules/**',
|
|
74
|
+
'**/node_modules/**',
|
|
75
|
+
'.git/**',
|
|
76
|
+
'**/.git/**',
|
|
77
|
+
'.git-ai/**',
|
|
78
|
+
'**/.git-ai/**',
|
|
79
|
+
'.repo/**',
|
|
80
|
+
'**/.repo/**',
|
|
81
|
+
'dist/**',
|
|
82
|
+
'target/**',
|
|
83
|
+
'**/target/**',
|
|
84
|
+
'build/**',
|
|
85
|
+
'**/build/**',
|
|
86
|
+
'.gradle/**',
|
|
87
|
+
'**/.gradle/**',
|
|
88
|
+
...aiIgnore,
|
|
89
|
+
...gitIgnore,
|
|
90
|
+
],
|
|
91
|
+
});
|
|
92
|
+
const languages = Array.from(new Set(files.map(inferIndexLang)));
|
|
93
|
+
const { byLang } = await (0, lancedb_1.openTablesByLang)({
|
|
94
|
+
dbDir,
|
|
95
|
+
dim: this.dim,
|
|
96
|
+
mode: this.overwrite ? 'overwrite' : 'create_if_missing',
|
|
97
|
+
languages,
|
|
98
|
+
});
|
|
99
|
+
const existingChunkIdsByLang = {};
|
|
100
|
+
if (!this.overwrite) {
|
|
101
|
+
for (const lang of languages) {
|
|
102
|
+
const t = byLang[lang];
|
|
103
|
+
if (!t)
|
|
104
|
+
continue;
|
|
105
|
+
const set = new Set();
|
|
106
|
+
const existing = await t.chunks.query().select(['content_hash']).limit(1000000).toArray();
|
|
107
|
+
for (const row of existing) {
|
|
108
|
+
const id = String(row.content_hash ?? '');
|
|
109
|
+
if (id)
|
|
110
|
+
set.add(id);
|
|
111
|
+
}
|
|
112
|
+
existingChunkIdsByLang[lang] = set;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const parallelResult = await (0, parallel_1.runParallelIndexing)({
|
|
116
|
+
repoRoot: this.repoRoot,
|
|
117
|
+
scanRoot: this.scanRoot,
|
|
118
|
+
dim: this.dim,
|
|
119
|
+
files,
|
|
120
|
+
indexing: this.config.indexing,
|
|
121
|
+
errorHandling: this.config.errorHandling,
|
|
122
|
+
existingChunkIdsByLang,
|
|
123
|
+
onProgress: this.onProgress,
|
|
124
|
+
});
|
|
125
|
+
const chunkRowsByLang = parallelResult.chunkRowsByLang;
|
|
126
|
+
const refRowsByLang = parallelResult.refRowsByLang;
|
|
127
|
+
const astFiles = parallelResult.astFiles;
|
|
128
|
+
const astSymbols = parallelResult.astSymbols;
|
|
129
|
+
const astContains = parallelResult.astContains;
|
|
130
|
+
const astExtendsName = parallelResult.astExtendsName;
|
|
131
|
+
const astImplementsName = parallelResult.astImplementsName;
|
|
132
|
+
const astRefsName = parallelResult.astRefsName;
|
|
133
|
+
const astCallsName = parallelResult.astCallsName;
|
|
134
|
+
const addedByLang = {};
|
|
135
|
+
for (const lang of languages) {
|
|
136
|
+
const t = byLang[lang];
|
|
137
|
+
if (!t)
|
|
138
|
+
continue;
|
|
139
|
+
const chunkRows = chunkRowsByLang[lang] ?? [];
|
|
140
|
+
const refRows = refRowsByLang[lang] ?? [];
|
|
141
|
+
if (chunkRows.length > 0)
|
|
142
|
+
await t.chunks.add(chunkRows);
|
|
143
|
+
if (refRows.length > 0)
|
|
144
|
+
await t.refs.add(refRows);
|
|
145
|
+
addedByLang[lang] = { chunksAdded: chunkRows.length, refsAdded: refRows.length };
|
|
146
|
+
}
|
|
147
|
+
const astGraph = await (0, astGraph_1.writeAstGraphToCozo)(this.repoRoot, {
|
|
148
|
+
files: astFiles,
|
|
149
|
+
symbols: astSymbols,
|
|
150
|
+
contains: astContains,
|
|
151
|
+
extends_name: astExtendsName,
|
|
152
|
+
implements_name: astImplementsName,
|
|
153
|
+
refs_name: astRefsName,
|
|
154
|
+
calls_name: astCallsName,
|
|
155
|
+
});
|
|
156
|
+
const commitHash = await (0, git_1.getCurrentCommitHash)(this.repoRoot);
|
|
157
|
+
const meta = {
|
|
158
|
+
version: '2.1',
|
|
159
|
+
index_schema_version: 3,
|
|
160
|
+
dim: this.dim,
|
|
161
|
+
files: files.length,
|
|
162
|
+
chunksAdded: Object.values(addedByLang).reduce((a, b) => a + b.chunksAdded, 0),
|
|
163
|
+
refsAdded: Object.values(addedByLang).reduce((a, b) => a + b.refsAdded, 0),
|
|
164
|
+
byLang: addedByLang,
|
|
165
|
+
languages,
|
|
166
|
+
dbDir: path_1.default.relative(this.repoRoot, dbDir),
|
|
167
|
+
scanRoot: path_1.default.relative(this.repoRoot, this.scanRoot),
|
|
168
|
+
...(commitHash ? { commit_hash: commitHash } : {}),
|
|
169
|
+
astGraph: astGraph.enabled
|
|
170
|
+
? {
|
|
171
|
+
backend: 'cozo',
|
|
172
|
+
engine: astGraph.engine,
|
|
173
|
+
dbPath: astGraph.dbPath ? path_1.default.relative(this.repoRoot, astGraph.dbPath) : undefined,
|
|
174
|
+
counts: astGraph.counts,
|
|
175
|
+
}
|
|
176
|
+
: {
|
|
177
|
+
backend: 'cozo',
|
|
178
|
+
enabled: false,
|
|
179
|
+
skippedReason: astGraph.skippedReason,
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
await fs_extra_1.default.writeJSON(path_1.default.join(gitAiDir, 'meta.json'), meta, { spaces: 2 });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
exports.IndexerV2 = IndexerV2;
|