grepmax 0.16.0 → 0.16.2
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/dist/commands/context.js +4 -2
- package/dist/commands/diff.js +4 -35
- package/dist/commands/extract.js +36 -6
- package/dist/commands/impact.js +21 -3
- package/dist/commands/investigate.js +4 -2
- package/dist/commands/peek.js +48 -7
- package/dist/commands/project.js +8 -7
- package/dist/commands/recent.js +10 -8
- package/dist/commands/related.js +13 -2
- package/dist/commands/remove.js +20 -3
- package/dist/commands/review.js +10 -3
- package/dist/commands/search.js +64 -37
- package/dist/commands/similar.js +13 -2
- package/dist/commands/skeleton.js +10 -20
- package/dist/commands/symbols.js +4 -1
- package/dist/commands/test-find.js +16 -3
- package/dist/commands/trace.js +13 -3
- package/dist/lib/daemon/daemon.js +16 -2
- package/dist/lib/daemon/ipc-handler.js +4 -0
- package/dist/lib/graph/graph-builder.js +10 -4
- package/dist/lib/graph/impact.js +16 -7
- package/dist/lib/index/chunker.js +8 -0
- package/dist/lib/search/searcher.js +28 -0
- package/dist/lib/utils/language.js +91 -0
- package/dist/lib/utils/project-registry.js +43 -0
- package/dist/lib/utils/scope-filter.js +104 -0
- package/package.json +1 -1
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
- package/plugins/grepmax/hooks/start.js +1 -1
package/dist/commands/context.js
CHANGED
|
@@ -44,13 +44,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
exports.context = void 0;
|
|
46
46
|
const fs = __importStar(require("node:fs"));
|
|
47
|
-
const path = __importStar(require("node:path"));
|
|
48
47
|
const commander_1 = require("commander");
|
|
49
48
|
const searcher_1 = require("../lib/search/searcher");
|
|
50
49
|
const skeleton_1 = require("../lib/skeleton");
|
|
51
50
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
52
51
|
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
53
52
|
const exit_1 = require("../lib/utils/exit");
|
|
53
|
+
const project_registry_1 = require("../lib/utils/project-registry");
|
|
54
54
|
const project_root_1 = require("../lib/utils/project-root");
|
|
55
55
|
const arrow_1 = require("../lib/utils/arrow");
|
|
56
56
|
function estimateTokens(text) {
|
|
@@ -69,7 +69,9 @@ exports.context = new commander_1.Command("context")
|
|
|
69
69
|
const maxResults = Number.parseInt(opts.maxResults || "10", 10) || 10;
|
|
70
70
|
let vectorDb = null;
|
|
71
71
|
try {
|
|
72
|
-
const root =
|
|
72
|
+
const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
|
|
73
|
+
if (root === null)
|
|
74
|
+
return;
|
|
73
75
|
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
|
|
74
76
|
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
75
77
|
vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
|
package/dist/commands/diff.js
CHANGED
|
@@ -1,37 +1,4 @@
|
|
|
1
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
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -43,13 +10,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
43
10
|
};
|
|
44
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
12
|
exports.diff = void 0;
|
|
46
|
-
const path = __importStar(require("node:path"));
|
|
47
13
|
const commander_1 = require("commander");
|
|
48
14
|
const searcher_1 = require("../lib/search/searcher");
|
|
49
15
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
50
16
|
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
51
17
|
const exit_1 = require("../lib/utils/exit");
|
|
52
18
|
const git_1 = require("../lib/utils/git");
|
|
19
|
+
const project_registry_1 = require("../lib/utils/project-registry");
|
|
53
20
|
const project_root_1 = require("../lib/utils/project-root");
|
|
54
21
|
const arrow_1 = require("../lib/utils/arrow");
|
|
55
22
|
exports.diff = new commander_1.Command("diff")
|
|
@@ -65,7 +32,9 @@ exports.diff = new commander_1.Command("diff")
|
|
|
65
32
|
const limit = Math.min(Math.max(Number.parseInt(opts.maxCount || "10", 10), 1), 50);
|
|
66
33
|
let vectorDb = null;
|
|
67
34
|
try {
|
|
68
|
-
const root =
|
|
35
|
+
const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
|
|
36
|
+
if (root === null)
|
|
37
|
+
return;
|
|
69
38
|
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
|
|
70
39
|
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
71
40
|
vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
|
package/dist/commands/extract.js
CHANGED
|
@@ -44,12 +44,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
exports.extract = void 0;
|
|
46
46
|
const fs = __importStar(require("node:fs"));
|
|
47
|
-
const path = __importStar(require("node:path"));
|
|
48
47
|
const commander_1 = require("commander");
|
|
49
48
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
50
49
|
const exit_1 = require("../lib/utils/exit");
|
|
51
50
|
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
52
51
|
const import_extractor_1 = require("../lib/utils/import-extractor");
|
|
52
|
+
const language_1 = require("../lib/utils/language");
|
|
53
|
+
const project_registry_1 = require("../lib/utils/project-registry");
|
|
53
54
|
const project_root_1 = require("../lib/utils/project-root");
|
|
54
55
|
const useColors = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
55
56
|
const style = {
|
|
@@ -63,10 +64,9 @@ const ROLE_PRIORITY = {
|
|
|
63
64
|
DEFINITION: 2,
|
|
64
65
|
IMPLEMENTATION: 1,
|
|
65
66
|
};
|
|
66
|
-
function findSymbolChunks(
|
|
67
|
+
function findSymbolChunks(db, whereClause) {
|
|
67
68
|
return __awaiter(this, void 0, void 0, function* () {
|
|
68
69
|
const table = yield db.ensureTable();
|
|
69
|
-
const prefix = projectRoot.endsWith("/") ? projectRoot : `${projectRoot}/`;
|
|
70
70
|
const rows = yield table
|
|
71
71
|
.query()
|
|
72
72
|
.select([
|
|
@@ -77,7 +77,7 @@ function findSymbolChunks(symbol, db, projectRoot) {
|
|
|
77
77
|
"is_exported",
|
|
78
78
|
"defined_symbols",
|
|
79
79
|
])
|
|
80
|
-
.where(
|
|
80
|
+
.where(whereClause)
|
|
81
81
|
.limit(10)
|
|
82
82
|
.toArray();
|
|
83
83
|
return rows.map((row) => ({
|
|
@@ -106,17 +106,28 @@ exports.extract = new commander_1.Command("extract")
|
|
|
106
106
|
.description("Extract full function/class body by symbol name")
|
|
107
107
|
.argument("<symbol>", "The symbol to extract")
|
|
108
108
|
.option("--root <dir>", "Project root directory")
|
|
109
|
+
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
|
|
110
|
+
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
|
|
109
111
|
.option("--agent", "Compact output for AI agents", false)
|
|
110
112
|
.option("--imports", "Prepend file imports", false)
|
|
111
113
|
.action((symbol, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
112
114
|
var _a;
|
|
113
115
|
let vectorDb = null;
|
|
114
|
-
const root =
|
|
116
|
+
const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
|
|
117
|
+
if (root === null)
|
|
118
|
+
return;
|
|
115
119
|
try {
|
|
116
120
|
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
|
|
117
121
|
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
118
122
|
vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
|
|
119
|
-
const
|
|
123
|
+
const { resolveScope, buildScopeWhere } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/scope-filter")));
|
|
124
|
+
const scope = resolveScope({
|
|
125
|
+
projectRoot,
|
|
126
|
+
in: opts.in,
|
|
127
|
+
exclude: opts.exclude,
|
|
128
|
+
});
|
|
129
|
+
const where = buildScopeWhere(scope, `array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(symbol)}')`);
|
|
130
|
+
const chunks = yield findSymbolChunks(vectorDb, where);
|
|
120
131
|
if (chunks.length === 0) {
|
|
121
132
|
const lines = [
|
|
122
133
|
`Symbol not found: ${opts.agent ? symbol : style.bold(symbol)}`,
|
|
@@ -128,6 +139,25 @@ exports.extract = new commander_1.Command("extract")
|
|
|
128
139
|
process.exitCode = 1;
|
|
129
140
|
return;
|
|
130
141
|
}
|
|
142
|
+
// Cross-language disambiguation: when the symbol is defined in 2+
|
|
143
|
+
// languages, refuse to silently pick one. Listing all matches with a
|
|
144
|
+
// recovery hint avoids the dogfooded failure mode where peek picked
|
|
145
|
+
// Swift but listed TS callers.
|
|
146
|
+
const byLang = (0, language_1.groupByLanguage)(chunks);
|
|
147
|
+
if (byLang.size >= 2) {
|
|
148
|
+
const rel = (p) => p.startsWith(projectRoot) ? p.slice(projectRoot.length + 1) : p;
|
|
149
|
+
const lines = [
|
|
150
|
+
`Symbol '${symbol}' is defined in multiple languages:`,
|
|
151
|
+
];
|
|
152
|
+
for (const [lang, group] of byLang) {
|
|
153
|
+
const c = group[0];
|
|
154
|
+
lines.push(` ${lang.padEnd(6)} ${rel(c.path)}:${c.startLine + 1}`);
|
|
155
|
+
}
|
|
156
|
+
lines.push(`Disambiguate with --root or pin to a path: gmax extract ${symbol} --root <project-root>`);
|
|
157
|
+
console.log(lines.join("\n"));
|
|
158
|
+
process.exitCode = 1;
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
131
161
|
const best = pickBestMatch(chunks, symbol);
|
|
132
162
|
const content = fs.readFileSync(best.path, "utf-8");
|
|
133
163
|
const allLines = content.split("\n");
|
package/dist/commands/impact.js
CHANGED
|
@@ -48,19 +48,24 @@ const commander_1 = require("commander");
|
|
|
48
48
|
const impact_1 = require("../lib/graph/impact");
|
|
49
49
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
50
50
|
const exit_1 = require("../lib/utils/exit");
|
|
51
|
+
const project_registry_1 = require("../lib/utils/project-registry");
|
|
51
52
|
const project_root_1 = require("../lib/utils/project-root");
|
|
52
53
|
exports.impact = new commander_1.Command("impact")
|
|
53
54
|
.description("Analyze change impact: dependents and affected tests")
|
|
54
55
|
.argument("<target>", "Symbol name or file path")
|
|
55
56
|
.option("-d, --depth <n>", "Caller traversal depth (default 1, max 3)", "1")
|
|
56
57
|
.option("--root <dir>", "Project root directory")
|
|
58
|
+
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
|
|
59
|
+
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
|
|
57
60
|
.option("--agent", "Compact output for AI agents", false)
|
|
58
61
|
.action((target, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
59
62
|
var _a;
|
|
60
63
|
const depth = Math.min(Math.max(Number.parseInt(opts.depth || "1", 10), 1), 3);
|
|
61
64
|
let vectorDb = null;
|
|
62
65
|
try {
|
|
63
|
-
const root =
|
|
66
|
+
const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
|
|
67
|
+
if (root === null)
|
|
68
|
+
return;
|
|
64
69
|
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
|
|
65
70
|
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
66
71
|
vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
|
|
@@ -77,10 +82,23 @@ exports.impact = new commander_1.Command("impact")
|
|
|
77
82
|
? (target.startsWith("/") ? target : path.resolve(projectRoot, target))
|
|
78
83
|
: undefined;
|
|
79
84
|
const excludePaths = targetPath ? new Set([targetPath]) : undefined;
|
|
85
|
+
const { resolveScope } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/scope-filter")));
|
|
86
|
+
const scope = resolveScope({
|
|
87
|
+
projectRoot,
|
|
88
|
+
in: opts.in,
|
|
89
|
+
exclude: opts.exclude,
|
|
90
|
+
});
|
|
91
|
+
// Treat --in as an exclude-everything-else when set: any prefix that
|
|
92
|
+
// isn't the --in scope becomes effectively excluded. Today findDependents
|
|
93
|
+
// always queries within projectRoot; passing scope.pathPrefix when --in
|
|
94
|
+
// is set narrows it. Reuse the existing projectRoot semantic when no --in.
|
|
95
|
+
const queryRoot = opts.in && opts.in.length > 0
|
|
96
|
+
? scope.pathPrefix.replace(/\/$/, "")
|
|
97
|
+
: projectRoot;
|
|
80
98
|
// Run dependents and tests in parallel
|
|
81
99
|
const [dependents, tests] = yield Promise.all([
|
|
82
|
-
(0, impact_1.findDependents)(symbols, vectorDb,
|
|
83
|
-
(0, impact_1.findTests)(symbols, vectorDb,
|
|
100
|
+
(0, impact_1.findDependents)(symbols, vectorDb, queryRoot, excludePaths, undefined, scope.excludePrefixes),
|
|
101
|
+
(0, impact_1.findTests)(symbols, vectorDb, queryRoot, depth, scope.excludePrefixes),
|
|
84
102
|
]);
|
|
85
103
|
// Separate test files from non-test dependents
|
|
86
104
|
const nonTestDeps = dependents.filter((d) => !(0, impact_1.isTestPath)(d.file));
|
|
@@ -43,9 +43,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
43
43
|
};
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
exports.investigateCmd = void 0;
|
|
46
|
-
const path = __importStar(require("node:path"));
|
|
47
46
|
const commander_1 = require("commander");
|
|
48
47
|
const exit_1 = require("../lib/utils/exit");
|
|
48
|
+
const project_registry_1 = require("../lib/utils/project-registry");
|
|
49
49
|
const project_root_1 = require("../lib/utils/project-root");
|
|
50
50
|
exports.investigateCmd = new commander_1.Command("investigate")
|
|
51
51
|
.description("Ask a question about the codebase using local LLM + gmax tools")
|
|
@@ -62,7 +62,9 @@ Examples:
|
|
|
62
62
|
.action((question, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
63
63
|
var _a;
|
|
64
64
|
try {
|
|
65
|
-
const root =
|
|
65
|
+
const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
|
|
66
|
+
if (root === null)
|
|
67
|
+
return;
|
|
66
68
|
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
|
|
67
69
|
const maxRounds = Math.min(Math.max(Number.parseInt(opts.rounds || "10", 10), 1), 20);
|
|
68
70
|
// Ensure LLM server is running
|
package/dist/commands/peek.js
CHANGED
|
@@ -44,12 +44,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
exports.peek = void 0;
|
|
46
46
|
const fs = __importStar(require("node:fs"));
|
|
47
|
-
const path = __importStar(require("node:path"));
|
|
48
47
|
const commander_1 = require("commander");
|
|
49
48
|
const graph_builder_1 = require("../lib/graph/graph-builder");
|
|
50
49
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
51
50
|
const exit_1 = require("../lib/utils/exit");
|
|
52
51
|
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
52
|
+
const language_1 = require("../lib/utils/language");
|
|
53
|
+
const project_registry_1 = require("../lib/utils/project-registry");
|
|
53
54
|
const project_root_1 = require("../lib/utils/project-root");
|
|
54
55
|
const useColors = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
55
56
|
const style = {
|
|
@@ -94,17 +95,60 @@ exports.peek = new commander_1.Command("peek")
|
|
|
94
95
|
.argument("<symbol>", "The symbol to peek at")
|
|
95
96
|
.option("-d, --depth <n>", "Caller traversal depth (default 1, max 3)", "1")
|
|
96
97
|
.option("--root <dir>", "Project root directory")
|
|
98
|
+
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
|
|
99
|
+
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
|
|
97
100
|
.option("--agent", "Compact output for AI agents", false)
|
|
98
101
|
.action((symbol, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
99
102
|
var _a;
|
|
100
103
|
let vectorDb = null;
|
|
101
|
-
const root =
|
|
104
|
+
const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
|
|
105
|
+
if (root === null)
|
|
106
|
+
return;
|
|
102
107
|
const depth = Math.min(Math.max(Number.parseInt(opts.depth || "1", 10), 1), 3);
|
|
103
108
|
try {
|
|
104
109
|
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
|
|
105
110
|
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
106
111
|
vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
|
|
107
|
-
const
|
|
112
|
+
const { resolveScope, buildScopeWhere } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/scope-filter")));
|
|
113
|
+
const scope = resolveScope({
|
|
114
|
+
projectRoot,
|
|
115
|
+
in: opts.in,
|
|
116
|
+
exclude: opts.exclude,
|
|
117
|
+
});
|
|
118
|
+
const scopeWhere = (cond) => buildScopeWhere(scope, cond);
|
|
119
|
+
// Cross-language disambiguation: when the symbol is defined in 2+
|
|
120
|
+
// languages, refuse to silently pick one. The graph builder otherwise
|
|
121
|
+
// picks one chunk arbitrarily and lists callers from a different
|
|
122
|
+
// language — verified failure mode.
|
|
123
|
+
{
|
|
124
|
+
const tableForCheck = yield vectorDb.ensureTable();
|
|
125
|
+
const allDefs = yield tableForCheck
|
|
126
|
+
.query()
|
|
127
|
+
.select(["path", "start_line"])
|
|
128
|
+
.where(scopeWhere(`array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(symbol)}')`))
|
|
129
|
+
.limit(20)
|
|
130
|
+
.toArray();
|
|
131
|
+
const chunks = allDefs.map((row) => ({
|
|
132
|
+
path: String(row.path || ""),
|
|
133
|
+
startLine: Number(row.start_line || 0),
|
|
134
|
+
}));
|
|
135
|
+
const byLang = (0, language_1.groupByLanguage)(chunks);
|
|
136
|
+
if (byLang.size >= 2) {
|
|
137
|
+
const rel = (p) => p.startsWith(projectRoot) ? p.slice(projectRoot.length + 1) : p;
|
|
138
|
+
const lines = [
|
|
139
|
+
`Symbol '${symbol}' is defined in multiple languages:`,
|
|
140
|
+
];
|
|
141
|
+
for (const [lang, group] of byLang) {
|
|
142
|
+
const c = group[0];
|
|
143
|
+
lines.push(` ${lang.padEnd(6)} ${rel(c.path)}:${c.startLine + 1}`);
|
|
144
|
+
}
|
|
145
|
+
lines.push(`Disambiguate with --root or pin to a path: gmax peek ${symbol} --root <project-root>`);
|
|
146
|
+
console.log(lines.join("\n"));
|
|
147
|
+
process.exitCode = 1;
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const graphBuilder = new graph_builder_1.GraphBuilder(vectorDb, scope.pathPrefix, scope.excludePrefixes);
|
|
108
152
|
const graph = yield graphBuilder.buildGraph(symbol);
|
|
109
153
|
if (!graph.center) {
|
|
110
154
|
const lines = [
|
|
@@ -123,13 +167,10 @@ exports.peek = new commander_1.Command("peek")
|
|
|
123
167
|
: p;
|
|
124
168
|
// Get chunk metadata for is_exported and end_line
|
|
125
169
|
const table = yield vectorDb.ensureTable();
|
|
126
|
-
const prefix = projectRoot.endsWith("/")
|
|
127
|
-
? projectRoot
|
|
128
|
-
: `${projectRoot}/`;
|
|
129
170
|
const metaRows = yield table
|
|
130
171
|
.query()
|
|
131
172
|
.select(["is_exported", "start_line", "end_line"])
|
|
132
|
-
.where(`array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(symbol)}')
|
|
173
|
+
.where(scopeWhere(`array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(symbol)}')`))
|
|
133
174
|
.limit(1)
|
|
134
175
|
.toArray();
|
|
135
176
|
const exported = metaRows.length > 0 && Boolean(metaRows[0].is_exported);
|
package/dist/commands/project.js
CHANGED
|
@@ -56,12 +56,13 @@ exports.project = new commander_1.Command("project")
|
|
|
56
56
|
.option("--root <dir>", "Project root (defaults to current directory)")
|
|
57
57
|
.option("--agent", "Compact output for AI agents", false)
|
|
58
58
|
.action((opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
59
|
-
var _a, _b, _c
|
|
59
|
+
var _a, _b, _c;
|
|
60
60
|
let vectorDb = null;
|
|
61
61
|
try {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
const resolvedRoot = (0, project_registry_1.resolveRootOrExit)(opts.root);
|
|
63
|
+
if (resolvedRoot === null)
|
|
64
|
+
return;
|
|
65
|
+
const root = (_a = (0, project_root_1.findProjectRoot)(resolvedRoot)) !== null && _a !== void 0 ? _a : resolvedRoot;
|
|
65
66
|
const prefix = root.endsWith("/") ? root : `${root}/`;
|
|
66
67
|
const projectName = path.basename(root);
|
|
67
68
|
const paths = (0, project_root_1.ensureProjectPaths)(root);
|
|
@@ -136,7 +137,7 @@ exports.project = new commander_1.Command("project")
|
|
|
136
137
|
console.log(`root\t${root}`);
|
|
137
138
|
console.log(`chunks\t${rows.length}`);
|
|
138
139
|
console.log(`files\t${files.size}`);
|
|
139
|
-
console.log(`last_indexed\t${(
|
|
140
|
+
console.log(`last_indexed\t${(_b = proj === null || proj === void 0 ? void 0 : proj.lastIndexed) !== null && _b !== void 0 ? _b : "unknown"}`);
|
|
140
141
|
console.log(`languages\t${extEntries.map(([ext]) => ext).join(",")}`);
|
|
141
142
|
console.log(`top_dirs\t${Array.from(dirCounts.entries()).sort((a, b) => b[1].chunks - a[1].chunks).slice(0, 8).map(([d]) => d).join(",")}`);
|
|
142
143
|
if (topSymbols.length > 0) {
|
|
@@ -148,7 +149,7 @@ exports.project = new commander_1.Command("project")
|
|
|
148
149
|
}
|
|
149
150
|
else {
|
|
150
151
|
console.log(`Project: ${projectName} (${root})`);
|
|
151
|
-
console.log(`Last indexed: ${(
|
|
152
|
+
console.log(`Last indexed: ${(_c = proj === null || proj === void 0 ? void 0 : proj.lastIndexed) !== null && _c !== void 0 ? _c : "unknown"} • ${rows.length} chunks • ${files.size} files\n`);
|
|
152
153
|
console.log(`Languages: ${extEntries.map(([ext, count]) => `${ext} (${Math.round((count / rows.length) * 100)}%)`).join(", ")}\n`);
|
|
153
154
|
console.log("Directory structure:");
|
|
154
155
|
for (const [dir, data] of Array.from(dirCounts.entries())
|
|
@@ -182,7 +183,7 @@ exports.project = new commander_1.Command("project")
|
|
|
182
183
|
try {
|
|
183
184
|
yield vectorDb.close();
|
|
184
185
|
}
|
|
185
|
-
catch (
|
|
186
|
+
catch (_d) { }
|
|
186
187
|
}
|
|
187
188
|
yield (0, exit_1.gracefulExit)();
|
|
188
189
|
}
|
package/dist/commands/recent.js
CHANGED
|
@@ -56,6 +56,7 @@ const config_1 = require("../config");
|
|
|
56
56
|
const meta_cache_1 = require("../lib/store/meta-cache");
|
|
57
57
|
const exit_1 = require("../lib/utils/exit");
|
|
58
58
|
const format_helpers_1 = require("../lib/utils/format-helpers");
|
|
59
|
+
const project_registry_1 = require("../lib/utils/project-registry");
|
|
59
60
|
const project_root_1 = require("../lib/utils/project-root");
|
|
60
61
|
exports.recent = new commander_1.Command("recent")
|
|
61
62
|
.description("Show recently modified indexed files")
|
|
@@ -64,20 +65,21 @@ exports.recent = new commander_1.Command("recent")
|
|
|
64
65
|
.option("--agent", "Compact output for AI agents", false)
|
|
65
66
|
.action((opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
67
|
var _a, e_1, _b, _c;
|
|
67
|
-
var _d
|
|
68
|
+
var _d;
|
|
68
69
|
const limit = Math.min(Math.max(Number.parseInt(opts.limit || "20", 10), 1), 50);
|
|
69
70
|
try {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
const resolvedRoot = (0, project_registry_1.resolveRootOrExit)(opts.root);
|
|
72
|
+
if (resolvedRoot === null)
|
|
73
|
+
return;
|
|
74
|
+
const root = (_d = (0, project_root_1.findProjectRoot)(resolvedRoot)) !== null && _d !== void 0 ? _d : resolvedRoot;
|
|
73
75
|
const prefix = root.endsWith("/") ? root : `${root}/`;
|
|
74
76
|
const metaCache = new meta_cache_1.MetaCache(config_1.PATHS.lmdbPath);
|
|
75
77
|
try {
|
|
76
78
|
const files = [];
|
|
77
79
|
try {
|
|
78
|
-
for (var
|
|
79
|
-
_c =
|
|
80
|
-
|
|
80
|
+
for (var _e = true, _f = __asyncValues(metaCache.entries()), _g; _g = yield _f.next(), _a = _g.done, !_a; _e = true) {
|
|
81
|
+
_c = _g.value;
|
|
82
|
+
_e = false;
|
|
81
83
|
const { path: p, entry } = _c;
|
|
82
84
|
if (p.startsWith(prefix)) {
|
|
83
85
|
files.push({ path: p, mtimeMs: entry.mtimeMs });
|
|
@@ -87,7 +89,7 @@ exports.recent = new commander_1.Command("recent")
|
|
|
87
89
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
88
90
|
finally {
|
|
89
91
|
try {
|
|
90
|
-
if (!
|
|
92
|
+
if (!_e && !_a && (_b = _f.return)) yield _b.call(_f);
|
|
91
93
|
}
|
|
92
94
|
finally { if (e_1) throw e_1.error; }
|
|
93
95
|
}
|
package/dist/commands/related.js
CHANGED
|
@@ -48,6 +48,7 @@ const commander_1 = require("commander");
|
|
|
48
48
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
49
49
|
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
50
50
|
const exit_1 = require("../lib/utils/exit");
|
|
51
|
+
const project_registry_1 = require("../lib/utils/project-registry");
|
|
51
52
|
const project_root_1 = require("../lib/utils/project-root");
|
|
52
53
|
const arrow_1 = require("../lib/utils/arrow");
|
|
53
54
|
exports.related = new commander_1.Command("related")
|
|
@@ -55,19 +56,29 @@ exports.related = new commander_1.Command("related")
|
|
|
55
56
|
.argument("<file>", "File path relative to project root")
|
|
56
57
|
.option("-l, --limit <n>", "Max results per direction (default 10)", "10")
|
|
57
58
|
.option("--root <dir>", "Project root directory")
|
|
59
|
+
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
|
|
60
|
+
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
|
|
58
61
|
.option("--agent", "Compact output for AI agents", false)
|
|
59
62
|
.action((file, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
63
|
var _a;
|
|
61
64
|
const limit = Math.min(Math.max(Number.parseInt(opts.limit || "10", 10), 1), 25);
|
|
62
65
|
let vectorDb = null;
|
|
63
66
|
try {
|
|
64
|
-
const root =
|
|
67
|
+
const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
|
|
68
|
+
if (root === null)
|
|
69
|
+
return;
|
|
65
70
|
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
|
|
66
71
|
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
67
72
|
vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
|
|
68
73
|
const absPath = path.resolve(projectRoot, file);
|
|
69
74
|
const table = yield vectorDb.ensureTable();
|
|
70
|
-
const
|
|
75
|
+
const { resolveScope, buildScopeWhere } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/scope-filter")));
|
|
76
|
+
const scope = resolveScope({
|
|
77
|
+
projectRoot,
|
|
78
|
+
in: opts.in,
|
|
79
|
+
exclude: opts.exclude,
|
|
80
|
+
});
|
|
81
|
+
const pathScope = buildScopeWhere(scope);
|
|
71
82
|
const fileChunks = yield table
|
|
72
83
|
.query()
|
|
73
84
|
.select(["defined_symbols", "referenced_symbols"])
|
package/dist/commands/remove.js
CHANGED
|
@@ -68,12 +68,13 @@ function confirm(message) {
|
|
|
68
68
|
}
|
|
69
69
|
exports.remove = new commander_1.Command("remove")
|
|
70
70
|
.description("Remove a project from the gmax index")
|
|
71
|
-
.argument("[dir]", "Directory
|
|
71
|
+
.argument("[dir-or-name]", "Directory or registered project name (defaults to current directory)")
|
|
72
72
|
.option("-f, --force", "Skip confirmation prompt", false)
|
|
73
73
|
.addHelpText("after", `
|
|
74
74
|
Examples:
|
|
75
75
|
gmax remove Remove the current project
|
|
76
|
-
gmax remove ~/projects/app Remove a specific project
|
|
76
|
+
gmax remove ~/projects/app Remove a specific project by path
|
|
77
|
+
gmax remove my-app Remove a registered project by name
|
|
77
78
|
gmax remove --force Skip confirmation
|
|
78
79
|
`)
|
|
79
80
|
.action((dir, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -81,7 +82,23 @@ Examples:
|
|
|
81
82
|
let vectorDb = null;
|
|
82
83
|
let metaCache = null;
|
|
83
84
|
try {
|
|
84
|
-
|
|
85
|
+
// Resolve name → registered root when arg has no path separator and
|
|
86
|
+
// isn't a dir. Avoids the footgun where a typo'd name silently removed
|
|
87
|
+
// the cwd project.
|
|
88
|
+
let targetDir;
|
|
89
|
+
if (dir) {
|
|
90
|
+
try {
|
|
91
|
+
targetDir = (0, project_registry_1.resolveProjectRoot)(dir);
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
95
|
+
process.exitCode = 1;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
targetDir = process.cwd();
|
|
101
|
+
}
|
|
85
102
|
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(targetDir)) !== null && _a !== void 0 ? _a : targetDir;
|
|
86
103
|
const projectName = path.basename(projectRoot);
|
|
87
104
|
const project = (0, project_registry_1.getProject)(projectRoot);
|
package/dist/commands/review.js
CHANGED
|
@@ -48,6 +48,7 @@ const fs = __importStar(require("node:fs"));
|
|
|
48
48
|
const path = __importStar(require("node:path"));
|
|
49
49
|
const commander_1 = require("commander");
|
|
50
50
|
const exit_1 = require("../lib/utils/exit");
|
|
51
|
+
const project_registry_1 = require("../lib/utils/project-registry");
|
|
51
52
|
const project_root_1 = require("../lib/utils/project-root");
|
|
52
53
|
exports.review = new commander_1.Command("review")
|
|
53
54
|
.description("Review code changes using local LLM + codebase context")
|
|
@@ -69,7 +70,9 @@ Subcommands:
|
|
|
69
70
|
.action((opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
70
71
|
var _a;
|
|
71
72
|
try {
|
|
72
|
-
const root =
|
|
73
|
+
const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
|
|
74
|
+
if (root === null)
|
|
75
|
+
return;
|
|
73
76
|
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
|
|
74
77
|
const commitRef = opts.commit;
|
|
75
78
|
if (opts.background) {
|
|
@@ -135,7 +138,9 @@ exports.review
|
|
|
135
138
|
.action((opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
136
139
|
var _a;
|
|
137
140
|
try {
|
|
138
|
-
const root =
|
|
141
|
+
const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
|
|
142
|
+
if (root === null)
|
|
143
|
+
return;
|
|
139
144
|
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
|
|
140
145
|
const { readReport, formatReportText } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/report")));
|
|
141
146
|
const report = readReport(projectRoot);
|
|
@@ -166,7 +171,9 @@ exports.review
|
|
|
166
171
|
.action((opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
167
172
|
var _a;
|
|
168
173
|
try {
|
|
169
|
-
const root =
|
|
174
|
+
const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
|
|
175
|
+
if (root === null)
|
|
176
|
+
return;
|
|
170
177
|
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
|
|
171
178
|
const { clearReport } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/report")));
|
|
172
179
|
clearReport(projectRoot);
|