@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,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseMarkdown = parseMarkdown;
|
|
4
|
+
const headerPattern = /^(#{1,6})\s+(.+?)\s*#*\s*$/;
|
|
5
|
+
function buildPath(current) {
|
|
6
|
+
const parts = [];
|
|
7
|
+
let cursor = current;
|
|
8
|
+
while (cursor) {
|
|
9
|
+
parts.unshift(cursor.name);
|
|
10
|
+
cursor = cursor.parent;
|
|
11
|
+
}
|
|
12
|
+
return parts.join(' > ');
|
|
13
|
+
}
|
|
14
|
+
function parseMarkdown(content, filePath) {
|
|
15
|
+
const lines = content.split(/\r?\n/);
|
|
16
|
+
const sections = [];
|
|
17
|
+
const stack = [];
|
|
18
|
+
const pushSection = (level, name, startLine) => {
|
|
19
|
+
while (stack.length > 0 && stack[stack.length - 1].level >= level) {
|
|
20
|
+
const last = stack.pop();
|
|
21
|
+
if (last)
|
|
22
|
+
last.endLine = startLine - 1;
|
|
23
|
+
}
|
|
24
|
+
const parent = stack[stack.length - 1];
|
|
25
|
+
const section = { level, name, startLine, endLine: lines.length, parent };
|
|
26
|
+
sections.push(section);
|
|
27
|
+
stack.push(section);
|
|
28
|
+
};
|
|
29
|
+
for (let i = 0; i < lines.length; i++) {
|
|
30
|
+
const line = lines[i];
|
|
31
|
+
const match = headerPattern.exec(line);
|
|
32
|
+
if (!match)
|
|
33
|
+
continue;
|
|
34
|
+
const level = match[1].length;
|
|
35
|
+
const name = match[2].trim();
|
|
36
|
+
if (!name)
|
|
37
|
+
continue;
|
|
38
|
+
pushSection(level, name, i + 1);
|
|
39
|
+
}
|
|
40
|
+
while (stack.length > 0) {
|
|
41
|
+
const last = stack.pop();
|
|
42
|
+
if (last)
|
|
43
|
+
last.endLine = lines.length;
|
|
44
|
+
}
|
|
45
|
+
const symbols = sections.map((section) => {
|
|
46
|
+
const signature = buildPath(section) || section.name;
|
|
47
|
+
const container = section.parent
|
|
48
|
+
? {
|
|
49
|
+
name: section.parent.name,
|
|
50
|
+
kind: 'section',
|
|
51
|
+
startLine: section.parent.startLine,
|
|
52
|
+
endLine: section.parent.endLine,
|
|
53
|
+
signature: buildPath(section.parent) || section.parent.name,
|
|
54
|
+
}
|
|
55
|
+
: undefined;
|
|
56
|
+
return {
|
|
57
|
+
name: section.name,
|
|
58
|
+
kind: 'section',
|
|
59
|
+
startLine: section.startLine,
|
|
60
|
+
endLine: section.endLine,
|
|
61
|
+
signature,
|
|
62
|
+
...(container ? { container } : {}),
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
if (symbols.length === 0) {
|
|
66
|
+
const name = filePath.split(/[\\/]/).pop() ?? filePath;
|
|
67
|
+
symbols.push({
|
|
68
|
+
name,
|
|
69
|
+
kind: 'document',
|
|
70
|
+
startLine: 1,
|
|
71
|
+
endLine: Math.max(1, lines.length),
|
|
72
|
+
signature: name,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return { symbols, refs: [] };
|
|
76
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
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.PythonAdapter = void 0;
|
|
7
|
+
const tree_sitter_python_1 = __importDefault(require("tree-sitter-python"));
|
|
8
|
+
const utils_1 = require("./utils");
|
|
9
|
+
class PythonAdapter {
|
|
10
|
+
getLanguageId() {
|
|
11
|
+
return 'python';
|
|
12
|
+
}
|
|
13
|
+
getTreeSitterLanguage() {
|
|
14
|
+
return tree_sitter_python_1.default;
|
|
15
|
+
}
|
|
16
|
+
getSupportedFileExtensions() {
|
|
17
|
+
return ['.py'];
|
|
18
|
+
}
|
|
19
|
+
extractSymbolsAndRefs(node) {
|
|
20
|
+
const symbols = [];
|
|
21
|
+
const refs = [];
|
|
22
|
+
const traverse = (n, container) => {
|
|
23
|
+
if (n.type === 'call') {
|
|
24
|
+
const fn = n.childForFieldName('function');
|
|
25
|
+
const nameNode = this.getCallNameNode(fn);
|
|
26
|
+
if (nameNode)
|
|
27
|
+
(0, utils_1.pushRef)(refs, nameNode.text, 'call', nameNode);
|
|
28
|
+
}
|
|
29
|
+
let currentContainer = container;
|
|
30
|
+
if (n.type === 'function_definition') {
|
|
31
|
+
const nameNode = n.childForFieldName('name');
|
|
32
|
+
if (nameNode) {
|
|
33
|
+
const kind = container?.kind === 'class' ? 'method' : 'function';
|
|
34
|
+
const newSymbol = {
|
|
35
|
+
name: nameNode.text,
|
|
36
|
+
kind,
|
|
37
|
+
startLine: n.startPosition.row + 1,
|
|
38
|
+
endLine: n.endPosition.row + 1,
|
|
39
|
+
signature: this.getSignature(n),
|
|
40
|
+
container: container,
|
|
41
|
+
};
|
|
42
|
+
symbols.push(newSymbol);
|
|
43
|
+
currentContainer = newSymbol;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else if (n.type === 'class_definition') {
|
|
47
|
+
const nameNode = n.childForFieldName('name');
|
|
48
|
+
if (nameNode) {
|
|
49
|
+
const newSymbol = {
|
|
50
|
+
name: nameNode.text,
|
|
51
|
+
kind: 'class',
|
|
52
|
+
startLine: n.startPosition.row + 1,
|
|
53
|
+
endLine: n.endPosition.row + 1,
|
|
54
|
+
signature: `class ${nameNode.text}`,
|
|
55
|
+
container: container,
|
|
56
|
+
};
|
|
57
|
+
symbols.push(newSymbol);
|
|
58
|
+
currentContainer = newSymbol;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (let i = 0; i < n.childCount; i++)
|
|
62
|
+
traverse(n.child(i), currentContainer);
|
|
63
|
+
};
|
|
64
|
+
traverse(node, undefined);
|
|
65
|
+
return { symbols, refs };
|
|
66
|
+
}
|
|
67
|
+
getCallNameNode(node) {
|
|
68
|
+
if (!node)
|
|
69
|
+
return null;
|
|
70
|
+
if (node.type === 'identifier')
|
|
71
|
+
return node;
|
|
72
|
+
if (node.type === 'attribute') {
|
|
73
|
+
return node.childForFieldName('attribute');
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
getSignature(node) {
|
|
78
|
+
return node.text.split(':')[0].trim();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.PythonAdapter = PythonAdapter;
|
|
@@ -0,0 +1,103 @@
|
|
|
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.RustAdapter = void 0;
|
|
7
|
+
const tree_sitter_rust_1 = __importDefault(require("tree-sitter-rust"));
|
|
8
|
+
const utils_1 = require("./utils");
|
|
9
|
+
class RustAdapter {
|
|
10
|
+
getLanguageId() {
|
|
11
|
+
return 'rust';
|
|
12
|
+
}
|
|
13
|
+
getTreeSitterLanguage() {
|
|
14
|
+
return tree_sitter_rust_1.default;
|
|
15
|
+
}
|
|
16
|
+
getSupportedFileExtensions() {
|
|
17
|
+
return ['.rs'];
|
|
18
|
+
}
|
|
19
|
+
extractSymbolsAndRefs(node) {
|
|
20
|
+
const symbols = [];
|
|
21
|
+
const refs = [];
|
|
22
|
+
const traverse = (n, container) => {
|
|
23
|
+
if (n.type === 'call_expression') {
|
|
24
|
+
const fn = n.childForFieldName('function');
|
|
25
|
+
const nameNode = this.getCallNameNode(fn);
|
|
26
|
+
if (nameNode)
|
|
27
|
+
(0, utils_1.pushRef)(refs, nameNode.text, 'call', nameNode);
|
|
28
|
+
}
|
|
29
|
+
else if (n.type === 'type_identifier') {
|
|
30
|
+
(0, utils_1.pushRef)(refs, n.text, 'type', n);
|
|
31
|
+
}
|
|
32
|
+
let currentContainer = container;
|
|
33
|
+
if (n.type === 'function_item') {
|
|
34
|
+
const nameNode = n.childForFieldName('name');
|
|
35
|
+
if (nameNode) {
|
|
36
|
+
// If container is class (impl block or struct), it's a method
|
|
37
|
+
const kind = container?.kind === 'class' ? 'method' : 'function';
|
|
38
|
+
const newSymbol = {
|
|
39
|
+
name: nameNode.text,
|
|
40
|
+
kind: kind,
|
|
41
|
+
startLine: n.startPosition.row + 1,
|
|
42
|
+
endLine: n.endPosition.row + 1,
|
|
43
|
+
signature: this.getSignature(n),
|
|
44
|
+
container: container,
|
|
45
|
+
};
|
|
46
|
+
symbols.push(newSymbol);
|
|
47
|
+
currentContainer = newSymbol;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (n.type === 'struct_item' || n.type === 'enum_item' || n.type === 'trait_item') {
|
|
51
|
+
const nameNode = n.childForFieldName('name');
|
|
52
|
+
if (nameNode) {
|
|
53
|
+
const newSymbol = {
|
|
54
|
+
name: nameNode.text,
|
|
55
|
+
kind: 'class',
|
|
56
|
+
startLine: n.startPosition.row + 1,
|
|
57
|
+
endLine: n.endPosition.row + 1,
|
|
58
|
+
signature: `${n.type.replace(/_item$/, '')} ${nameNode.text}`,
|
|
59
|
+
container: container,
|
|
60
|
+
};
|
|
61
|
+
symbols.push(newSymbol);
|
|
62
|
+
currentContainer = newSymbol;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else if (n.type === 'impl_item') {
|
|
66
|
+
const typeNode = n.childForFieldName('type');
|
|
67
|
+
if (typeNode) {
|
|
68
|
+
const newSymbol = {
|
|
69
|
+
name: typeNode.text,
|
|
70
|
+
kind: 'class',
|
|
71
|
+
startLine: n.startPosition.row + 1,
|
|
72
|
+
endLine: n.endPosition.row + 1,
|
|
73
|
+
signature: `impl ${typeNode.text}`,
|
|
74
|
+
container: container
|
|
75
|
+
};
|
|
76
|
+
symbols.push(newSymbol);
|
|
77
|
+
currentContainer = newSymbol;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
for (let i = 0; i < n.childCount; i++)
|
|
81
|
+
traverse(n.child(i), currentContainer);
|
|
82
|
+
};
|
|
83
|
+
traverse(node, undefined);
|
|
84
|
+
return { symbols, refs };
|
|
85
|
+
}
|
|
86
|
+
getCallNameNode(node) {
|
|
87
|
+
if (!node)
|
|
88
|
+
return null;
|
|
89
|
+
if (node.type === 'identifier')
|
|
90
|
+
return node;
|
|
91
|
+
if (node.type === 'scoped_identifier') {
|
|
92
|
+
return node.childForFieldName('name');
|
|
93
|
+
}
|
|
94
|
+
if (node.type === 'field_expression') {
|
|
95
|
+
return node.childForFieldName('field');
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
getSignature(node) {
|
|
100
|
+
return node.text.split('{')[0].trim();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.RustAdapter = RustAdapter;
|
|
@@ -0,0 +1,98 @@
|
|
|
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.TypeScriptAdapter = void 0;
|
|
7
|
+
const tree_sitter_typescript_1 = __importDefault(require("tree-sitter-typescript"));
|
|
8
|
+
const utils_1 = require("./utils");
|
|
9
|
+
class TypeScriptAdapter {
|
|
10
|
+
constructor(isTsx = false) {
|
|
11
|
+
this.isTsx = isTsx;
|
|
12
|
+
}
|
|
13
|
+
getLanguageId() {
|
|
14
|
+
return 'typescript';
|
|
15
|
+
}
|
|
16
|
+
getTreeSitterLanguage() {
|
|
17
|
+
return this.isTsx ? tree_sitter_typescript_1.default.tsx : tree_sitter_typescript_1.default.typescript;
|
|
18
|
+
}
|
|
19
|
+
getSupportedFileExtensions() {
|
|
20
|
+
return this.isTsx ? ['.tsx', '.jsx'] : ['.ts', '.js', '.mjs', '.cjs'];
|
|
21
|
+
}
|
|
22
|
+
extractSymbolsAndRefs(node) {
|
|
23
|
+
const symbols = [];
|
|
24
|
+
const refs = [];
|
|
25
|
+
const extractTsCalleeName = (callee) => {
|
|
26
|
+
if (!callee)
|
|
27
|
+
return null;
|
|
28
|
+
if (callee.type === 'identifier')
|
|
29
|
+
return callee.text;
|
|
30
|
+
if (callee.type === 'member_expression' || callee.type === 'optional_chain') {
|
|
31
|
+
const prop = callee.childForFieldName('property');
|
|
32
|
+
if (prop)
|
|
33
|
+
return prop.text;
|
|
34
|
+
const last = callee.namedChild(callee.namedChildCount - 1);
|
|
35
|
+
if (last)
|
|
36
|
+
return last.text;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
};
|
|
40
|
+
const traverse = (n, container) => {
|
|
41
|
+
if (n.type === 'call_expression') {
|
|
42
|
+
const fn = n.childForFieldName('function') ?? n.namedChild(0);
|
|
43
|
+
const callee = extractTsCalleeName(fn);
|
|
44
|
+
if (callee)
|
|
45
|
+
(0, utils_1.pushRef)(refs, callee, 'call', fn ?? n);
|
|
46
|
+
}
|
|
47
|
+
else if (n.type === 'new_expression') {
|
|
48
|
+
const ctor = n.childForFieldName('constructor') ?? n.namedChild(0);
|
|
49
|
+
const callee = extractTsCalleeName(ctor);
|
|
50
|
+
if (callee)
|
|
51
|
+
(0, utils_1.pushRef)(refs, callee, 'new', ctor ?? n);
|
|
52
|
+
}
|
|
53
|
+
else if (n.type === 'type_identifier') {
|
|
54
|
+
(0, utils_1.pushRef)(refs, n.text, 'type', n);
|
|
55
|
+
}
|
|
56
|
+
let currentContainer = container;
|
|
57
|
+
if (n.type === 'function_declaration' || n.type === 'method_definition') {
|
|
58
|
+
const nameNode = n.childForFieldName('name');
|
|
59
|
+
if (nameNode) {
|
|
60
|
+
const newSymbol = {
|
|
61
|
+
name: nameNode.text,
|
|
62
|
+
kind: n.type === 'method_definition' ? 'method' : 'function',
|
|
63
|
+
startLine: n.startPosition.row + 1,
|
|
64
|
+
endLine: n.endPosition.row + 1,
|
|
65
|
+
signature: n.text.split('{')[0].trim(),
|
|
66
|
+
container: container,
|
|
67
|
+
};
|
|
68
|
+
symbols.push(newSymbol);
|
|
69
|
+
currentContainer = newSymbol;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else if (n.type === 'class_declaration') {
|
|
73
|
+
const nameNode = n.childForFieldName('name');
|
|
74
|
+
if (nameNode) {
|
|
75
|
+
const head = n.text.split('{')[0].trim();
|
|
76
|
+
const heritage = (0, utils_1.parseHeritage)(head);
|
|
77
|
+
const classSym = {
|
|
78
|
+
name: nameNode.text,
|
|
79
|
+
kind: 'class',
|
|
80
|
+
startLine: n.startPosition.row + 1,
|
|
81
|
+
endLine: n.endPosition.row + 1,
|
|
82
|
+
signature: `class ${nameNode.text}`,
|
|
83
|
+
container,
|
|
84
|
+
extends: heritage.extends,
|
|
85
|
+
implements: heritage.implements,
|
|
86
|
+
};
|
|
87
|
+
symbols.push(classSym);
|
|
88
|
+
currentContainer = classSym;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
for (let i = 0; i < n.childCount; i++)
|
|
92
|
+
traverse(n.child(i), currentContainer);
|
|
93
|
+
};
|
|
94
|
+
traverse(node, undefined);
|
|
95
|
+
return { symbols, refs };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.TypeScriptAdapter = TypeScriptAdapter;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseHeritage = exports.findFirstByType = exports.pushRef = void 0;
|
|
4
|
+
const pushRef = (refs, name, refKind, n) => {
|
|
5
|
+
const nm = String(name ?? '').trim();
|
|
6
|
+
if (!nm)
|
|
7
|
+
return;
|
|
8
|
+
refs.push({
|
|
9
|
+
name: nm,
|
|
10
|
+
refKind,
|
|
11
|
+
line: n.startPosition.row + 1,
|
|
12
|
+
column: n.startPosition.column + 1,
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
exports.pushRef = pushRef;
|
|
16
|
+
const findFirstByType = (n, types) => {
|
|
17
|
+
if (types.includes(n.type))
|
|
18
|
+
return n;
|
|
19
|
+
for (let i = 0; i < n.childCount; i++) {
|
|
20
|
+
const c = n.child(i);
|
|
21
|
+
if (!c)
|
|
22
|
+
continue;
|
|
23
|
+
const found = (0, exports.findFirstByType)(c, types);
|
|
24
|
+
if (found)
|
|
25
|
+
return found;
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
};
|
|
29
|
+
exports.findFirstByType = findFirstByType;
|
|
30
|
+
const parseHeritage = (head) => {
|
|
31
|
+
const out = {};
|
|
32
|
+
const extendsMatch = head.match(/\bextends\s+([A-Za-z0-9_$.<>\[\]]+)/);
|
|
33
|
+
if (extendsMatch?.[1])
|
|
34
|
+
out.extends = [extendsMatch[1]];
|
|
35
|
+
const implMatch = head.match(/\bimplements\s+([A-Za-z0-9_$. ,<>\[\]]+)/);
|
|
36
|
+
if (implMatch?.[1]) {
|
|
37
|
+
const raw = implMatch[1];
|
|
38
|
+
const parts = [];
|
|
39
|
+
let current = '';
|
|
40
|
+
let depth = 0;
|
|
41
|
+
for (const char of raw) {
|
|
42
|
+
if (char === '<')
|
|
43
|
+
depth++;
|
|
44
|
+
else if (char === '>')
|
|
45
|
+
depth--;
|
|
46
|
+
if (char === ',' && depth === 0) {
|
|
47
|
+
if (current.trim())
|
|
48
|
+
parts.push(current.trim());
|
|
49
|
+
current = '';
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
current += char;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (current.trim())
|
|
56
|
+
parts.push(current.trim());
|
|
57
|
+
if (parts.length > 0)
|
|
58
|
+
out.implements = parts;
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
};
|
|
62
|
+
exports.parseHeritage = parseHeritage;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseYaml = parseYaml;
|
|
4
|
+
const keyPattern = /^\s*([A-Za-z0-9_.-]+)\s*:/;
|
|
5
|
+
function isConfigPath(filePath) {
|
|
6
|
+
const p = filePath.replace(/\\/g, '/');
|
|
7
|
+
return p.includes('/.agents/') || p.includes('/templates/agents/') || p.includes('/rules/') || p.includes('/skills/');
|
|
8
|
+
}
|
|
9
|
+
function fileBaseName(filePath) {
|
|
10
|
+
const parts = filePath.split(/[\\/]/);
|
|
11
|
+
return parts[parts.length - 1] ?? filePath;
|
|
12
|
+
}
|
|
13
|
+
function parseYaml(content, filePath) {
|
|
14
|
+
const lines = content.split(/\r?\n/);
|
|
15
|
+
const nodes = [];
|
|
16
|
+
for (let i = 0; i < lines.length; i++) {
|
|
17
|
+
const line = lines[i];
|
|
18
|
+
if (!line || line.trimStart().startsWith('#'))
|
|
19
|
+
continue;
|
|
20
|
+
const match = keyPattern.exec(line);
|
|
21
|
+
if (!match)
|
|
22
|
+
continue;
|
|
23
|
+
const name = match[1].trim();
|
|
24
|
+
if (!name)
|
|
25
|
+
continue;
|
|
26
|
+
if (line.trimStart().startsWith('-'))
|
|
27
|
+
continue;
|
|
28
|
+
nodes.push({ name, startLine: i + 1, endLine: lines.length });
|
|
29
|
+
}
|
|
30
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
31
|
+
const next = nodes[i + 1];
|
|
32
|
+
if (next)
|
|
33
|
+
nodes[i].endLine = Math.max(nodes[i].startLine, next.startLine - 1);
|
|
34
|
+
}
|
|
35
|
+
const symbols = nodes.map((node) => ({
|
|
36
|
+
name: node.name,
|
|
37
|
+
kind: 'node',
|
|
38
|
+
startLine: node.startLine,
|
|
39
|
+
endLine: node.endLine,
|
|
40
|
+
signature: node.name,
|
|
41
|
+
}));
|
|
42
|
+
if (symbols.length === 0) {
|
|
43
|
+
const name = fileBaseName(filePath);
|
|
44
|
+
symbols.push({
|
|
45
|
+
name,
|
|
46
|
+
kind: isConfigPath(filePath) ? 'document' : 'node',
|
|
47
|
+
startLine: 1,
|
|
48
|
+
endLine: Math.max(1, lines.length),
|
|
49
|
+
signature: name,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return { symbols, refs: [] };
|
|
53
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
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.CodeParser = void 0;
|
|
7
|
+
const tree_sitter_1 = __importDefault(require("tree-sitter"));
|
|
8
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
+
const typescript_1 = require("./parser/typescript");
|
|
10
|
+
const java_1 = require("./parser/java");
|
|
11
|
+
const c_1 = require("./parser/c");
|
|
12
|
+
const go_1 = require("./parser/go");
|
|
13
|
+
const python_1 = require("./parser/python");
|
|
14
|
+
const rust_1 = require("./parser/rust");
|
|
15
|
+
const markdown_1 = require("./parser/markdown");
|
|
16
|
+
const yaml_1 = require("./parser/yaml");
|
|
17
|
+
class CodeParser {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.parser = new tree_sitter_1.default();
|
|
20
|
+
this.adapters = [
|
|
21
|
+
new typescript_1.TypeScriptAdapter(false),
|
|
22
|
+
new typescript_1.TypeScriptAdapter(true),
|
|
23
|
+
new java_1.JavaAdapter(),
|
|
24
|
+
new c_1.CAdapter(),
|
|
25
|
+
new go_1.GoAdapter(),
|
|
26
|
+
new python_1.PythonAdapter(),
|
|
27
|
+
new rust_1.RustAdapter(),
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
async parseFile(filePath) {
|
|
31
|
+
const content = await fs_extra_1.default.readFile(filePath, 'utf-8');
|
|
32
|
+
if (isMarkdownFile(filePath))
|
|
33
|
+
return (0, markdown_1.parseMarkdown)(content, filePath);
|
|
34
|
+
if (isYamlFile(filePath))
|
|
35
|
+
return (0, yaml_1.parseYaml)(content, filePath);
|
|
36
|
+
const adapter = this.pickAdapter(filePath);
|
|
37
|
+
if (!adapter)
|
|
38
|
+
return { symbols: [], refs: [] };
|
|
39
|
+
try {
|
|
40
|
+
this.parser.setLanguage(adapter.getTreeSitterLanguage());
|
|
41
|
+
const tree = this.parser.parse(content);
|
|
42
|
+
return adapter.extractSymbolsAndRefs(tree.rootNode);
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
const msg = String(e?.message ?? e);
|
|
46
|
+
if (msg.includes('Invalid language object'))
|
|
47
|
+
return { symbols: [], refs: [] };
|
|
48
|
+
if (!msg.includes('Invalid argument'))
|
|
49
|
+
return { symbols: [], refs: [] };
|
|
50
|
+
try {
|
|
51
|
+
const tree = this.parser.parse(content, undefined, { bufferSize: 1024 * 1024 });
|
|
52
|
+
return adapter.extractSymbolsAndRefs(tree.rootNode);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return { symbols: [], refs: [] };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
pickAdapter(filePath) {
|
|
60
|
+
for (const adapter of this.adapters) {
|
|
61
|
+
for (const ext of adapter.getSupportedFileExtensions()) {
|
|
62
|
+
if (filePath.endsWith(ext))
|
|
63
|
+
return adapter;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.CodeParser = CodeParser;
|
|
70
|
+
function isMarkdownFile(filePath) {
|
|
71
|
+
return filePath.endsWith('.md') || filePath.endsWith('.mdx');
|
|
72
|
+
}
|
|
73
|
+
function isYamlFile(filePath) {
|
|
74
|
+
return filePath.endsWith('.yml') || filePath.endsWith('.yaml');
|
|
75
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toPosixPath = toPosixPath;
|
|
4
|
+
exports.splitPosixPath = splitPosixPath;
|
|
5
|
+
function toPosixPath(p) {
|
|
6
|
+
return String(p).replace(/\\/g, '/');
|
|
7
|
+
}
|
|
8
|
+
function splitPosixPath(p) {
|
|
9
|
+
return toPosixPath(p).split('/').filter(Boolean);
|
|
10
|
+
}
|