Skip to content

Commit c4fa0dd

Browse files
authored
feat: migrate lib/repo-map from ast-grep to agent-analyzer (#9)
* docs: add CHANGELOG.md from git history in Keep a Changelog format Reconstructed from full commit history. Groups changes into 6 releases (v0.0.1 through v0.4.0) covering the initial lib/ seed, CI/hooks setup, agent-knowledge submodule, binary resolver, git collector, template fixes, and the ANALYZER_MIN_VERSION v0.3.0 bump. * feat: migrate lib/repo-map from ast-grep to agent-analyzer Remove 2717 lines of dead code (runner.js, queries/, concurrency.js, usage-analyzer.js) that wrapped ast-grep. Replace with the agent-analyzer path that auto-downloads the binary on first use. - index.js: calls binary.runAnalyzerAsync(['repo-intel', init|update]) - installer.js: checks agent-analyzer availability, no ast-grep detection - converter.js: translates repo-intel.json format to repo-map.json format - updater.js: stripped to checkStaleness() + git helpers only (490 → 95 lines) - Deleted: runner.js (1364 lines), queries/ (355 lines), concurrency.js (29 lines), usage-analyzer.js (407 lines) - API compat: checkAstGrepInstalled() kept as alias for checkInstalled()
1 parent 6ac0f5a commit c4fa0dd

File tree

14 files changed

+301
-2875
lines changed

14 files changed

+301
-2875
lines changed

lib/repo-map/concurrency.js

Lines changed: 0 additions & 29 deletions
This file was deleted.

lib/repo-map/converter.js

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
'use strict';
2+
3+
/**
4+
* Convert agent-analyzer repo-intel.json format to repo-map.json format.
5+
*
6+
* agent-analyzer outputs: { symbols: { [filePath]: { exports, imports, definitions } } }
7+
* repo-map expects: { files: { [filePath]: { language, symbols, imports } } }
8+
*
9+
* @module lib/repo-map/converter
10+
*/
11+
12+
const path = require('path');
13+
14+
const LANGUAGE_BY_EXTENSION = {
15+
'.js': 'javascript', '.jsx': 'javascript', '.mjs': 'javascript', '.cjs': 'javascript',
16+
'.ts': 'typescript', '.tsx': 'typescript', '.mts': 'typescript', '.cts': 'typescript',
17+
'.py': 'python', '.pyw': 'python',
18+
'.rs': 'rust',
19+
'.go': 'go',
20+
'.java': 'java'
21+
};
22+
23+
// SymbolKind values from agent-analyzer (kebab-case serialized)
24+
const CLASS_KINDS = new Set(['class', 'struct', 'interface', 'enum', 'impl']);
25+
const TYPE_KINDS = new Set(['trait', 'type-alias']);
26+
const FUNCTION_LIKE_KINDS = new Set(['method', 'arrow', 'closure']);
27+
const CONSTANT_KINDS = new Set(['constant', 'variable', 'const', 'field', 'property']);
28+
29+
function detectLanguage(filePath) {
30+
return LANGUAGE_BY_EXTENSION[path.extname(filePath).toLowerCase()] || 'unknown';
31+
}
32+
33+
function detectLanguagesFromFiles(filePaths) {
34+
const langs = new Set();
35+
for (const fp of filePaths) {
36+
const lang = detectLanguage(fp);
37+
if (lang !== 'unknown') langs.add(lang);
38+
}
39+
return Array.from(langs);
40+
}
41+
42+
/**
43+
* Convert a single file's symbols from repo-intel format to repo-map format.
44+
* @param {string} filePath
45+
* @param {Object} fileSym - { exports, imports, definitions }
46+
* @returns {Object} repo-map file entry
47+
*/
48+
function convertFile(filePath, fileSym) {
49+
const exportNames = new Set((fileSym.exports || []).map(e => e.name));
50+
51+
const exports = (fileSym.exports || []).map(e => ({
52+
name: e.name,
53+
kind: e.kind,
54+
line: e.line
55+
}));
56+
57+
const functions = [];
58+
const classes = [];
59+
const types = [];
60+
const constants = [];
61+
62+
for (const def of fileSym.definitions || []) {
63+
const entry = {
64+
name: def.name,
65+
kind: def.kind,
66+
line: def.line,
67+
exported: exportNames.has(def.name)
68+
};
69+
if (def.kind === 'function' || FUNCTION_LIKE_KINDS.has(def.kind)) {
70+
functions.push(entry);
71+
} else if (CLASS_KINDS.has(def.kind)) {
72+
classes.push(entry);
73+
} else if (TYPE_KINDS.has(def.kind)) {
74+
types.push(entry);
75+
} else if (CONSTANT_KINDS.has(def.kind)) {
76+
constants.push(entry);
77+
} else {
78+
// Unknown kind - default to constants for backward compat
79+
constants.push(entry);
80+
}
81+
}
82+
83+
// agent-analyzer imports: [{ from, names }] → repo-map imports: [{ source, kind, names }]
84+
const imports = (fileSym.imports || []).map(imp => ({
85+
source: imp.from,
86+
kind: 'import',
87+
names: imp.names || []
88+
}));
89+
90+
return {
91+
language: detectLanguage(filePath),
92+
symbols: { exports, functions, classes, types, constants },
93+
imports
94+
};
95+
}
96+
97+
/**
98+
* Convert a full repo-intel data object to repo-map format.
99+
* @param {Object} intel - RepoIntelData from agent-analyzer
100+
* @returns {Object} repo-map.json compatible object
101+
*/
102+
function convertIntelToRepoMap(intel) {
103+
const files = {};
104+
let totalSymbols = 0;
105+
let totalImports = 0;
106+
107+
for (const [filePath, fileSym] of Object.entries(intel.symbols || {})) {
108+
files[filePath] = convertFile(filePath, fileSym);
109+
const s = files[filePath].symbols;
110+
totalSymbols += s.functions.length + s.classes.length +
111+
s.types.length + s.constants.length;
112+
totalImports += files[filePath].imports.length;
113+
}
114+
115+
return {
116+
version: '2.0',
117+
generated: intel.generated || new Date().toISOString(),
118+
git: intel.git ? { commit: intel.git.analyzedUpTo } : undefined,
119+
project: { languages: detectLanguagesFromFiles(Object.keys(files)) },
120+
stats: {
121+
totalFiles: Object.keys(files).length,
122+
totalSymbols,
123+
totalImports,
124+
errors: []
125+
},
126+
files
127+
};
128+
}
129+
130+
module.exports = { convertIntelToRepoMap, convertFile, detectLanguage };

0 commit comments

Comments
 (0)