grepmax 0.18.1 → 0.20.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/.claude-plugin/marketplace.json +23 -0
- package/README.md +28 -3
- package/dist/commands/add.js +4 -2
- package/dist/commands/claude-code.js +1 -1
- package/dist/commands/codex.js +3 -1
- package/dist/commands/context.js +1 -1
- package/dist/commands/dead.js +2 -6
- package/dist/commands/doctor.js +26 -7
- package/dist/commands/extract.js +3 -5
- package/dist/commands/impact.js +6 -4
- package/dist/commands/index.js +7 -2
- package/dist/commands/log.js +4 -2
- package/dist/commands/mcp.js +594 -722
- package/dist/commands/peek.js +15 -9
- package/dist/commands/plugin.js +36 -22
- package/dist/commands/project.js +16 -6
- package/dist/commands/related.js +8 -9
- package/dist/commands/remove.js +9 -2
- package/dist/commands/review.js +1 -1
- package/dist/commands/setup.js +4 -2
- package/dist/commands/similar.js +4 -4
- package/dist/commands/status.js +6 -4
- package/dist/commands/summarize.js +6 -4
- package/dist/commands/symbols.js +1 -1
- package/dist/commands/test-find.js +2 -2
- package/dist/commands/trace.js +12 -5
- package/dist/commands/watch.js +33 -9
- package/dist/eval-graph-nav.js +4 -1
- package/dist/eval-graph-recovery-probe.js +56 -14
- package/dist/eval-graph-spotcheck.js +10 -2
- package/dist/eval-graph-totals.js +5 -2
- package/dist/eval-oss.js +212 -37
- package/dist/eval-seed.js +13 -4
- package/dist/index.js +9 -9
- package/dist/lib/daemon/daemon.js +32 -13
- package/dist/lib/daemon/ipc-handler.js +24 -5
- package/dist/lib/daemon/mlx-server-manager.js +11 -3
- package/dist/lib/daemon/process-manager.js +1 -2
- package/dist/lib/daemon/watcher-manager.js +22 -6
- package/dist/lib/graph/callsites.js +151 -25
- package/dist/lib/graph/graph-builder.js +2 -2
- package/dist/lib/graph/impact.js +6 -6
- package/dist/lib/index/batch-processor.js +16 -6
- package/dist/lib/index/chunker.js +2 -0
- package/dist/lib/index/syncer.js +22 -10
- package/dist/lib/index/watcher-batch.js +10 -1
- package/dist/lib/llm/config.js +2 -1
- package/dist/lib/llm/diff.js +56 -11
- package/dist/lib/llm/investigate.js +52 -11
- package/dist/lib/llm/review.js +21 -8
- package/dist/lib/llm/server.js +25 -9
- package/dist/lib/llm/tools.js +1 -1
- package/dist/lib/output/agent-search-formatter.js +25 -3
- package/dist/lib/output/index-state-footer.js +1 -1
- package/dist/lib/review/risk.js +2 -4
- package/dist/lib/search/pagerank.js +1 -1
- package/dist/lib/search/searcher.js +43 -17
- package/dist/lib/search/seed-weight.js +4 -1
- package/dist/lib/skeleton/symbol-extractor.js +2 -1
- package/dist/lib/store/vector-db.js +21 -10
- package/dist/lib/utils/cross-project.js +5 -1
- package/dist/lib/utils/daemon-client.js +39 -1
- package/dist/lib/utils/filter-builder.js +22 -0
- package/dist/lib/utils/git.js +10 -2
- package/dist/lib/utils/project-registry.js +3 -2
- package/dist/lib/utils/scope-filter.js +6 -6
- package/dist/lib/utils/watcher-launcher.js +4 -1
- package/dist/lib/utils/watcher-store.js +2 -1
- package/dist/lib/workers/embeddings/granite.js +4 -1
- package/dist/lib/workers/embeddings/mlx-client.js +7 -2
- package/dist/lib/workers/pool.js +30 -7
- package/dist/lib/workers/process-child.js +1 -1
- package/package.json +23 -19
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
- package/plugins/grepmax/hooks/cwd-changed.js +4 -1
- package/plugins/grepmax/hooks/pre-grep.js +2 -1
- package/plugins/grepmax/hooks/start.js +45 -10
- package/plugins/grepmax/hooks/subagent-start.js +1 -4
package/dist/commands/peek.js
CHANGED
|
@@ -53,8 +53,8 @@ const exit_1 = require("../lib/utils/exit");
|
|
|
53
53
|
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
54
54
|
const language_1 = require("../lib/utils/language");
|
|
55
55
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
56
|
-
const stale_hint_1 = require("../lib/utils/stale-hint");
|
|
57
56
|
const project_root_1 = require("../lib/utils/project-root");
|
|
57
|
+
const stale_hint_1 = require("../lib/utils/stale-hint");
|
|
58
58
|
const useColors = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
59
59
|
const style = {
|
|
60
60
|
bold: (s) => (useColors ? `\x1b[1m${s}\x1b[22m` : s),
|
|
@@ -117,8 +117,8 @@ exports.peek = new commander_1.Command("peek")
|
|
|
117
117
|
.argument("<symbol>", "The symbol to peek at")
|
|
118
118
|
.option("-d, --depth <n>", "Caller traversal depth (default 1, max 3)", "1")
|
|
119
119
|
.option("--root <dir>", "Project root directory")
|
|
120
|
-
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) =>
|
|
121
|
-
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) =>
|
|
120
|
+
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) => prev ? [...prev, value] : [value])
|
|
121
|
+
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) => prev ? [...prev, value] : [value])
|
|
122
122
|
.option("--agent", "Compact output for AI agents", false)
|
|
123
123
|
.option("--no-tests", "Suppress the tests footer")
|
|
124
124
|
.action((symbol, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -196,9 +196,7 @@ exports.peek = new commander_1.Command("peek")
|
|
|
196
196
|
return;
|
|
197
197
|
}
|
|
198
198
|
const center = graph.center;
|
|
199
|
-
const rel = (p) => p.startsWith(projectRoot)
|
|
200
|
-
? p.slice(projectRoot.length + 1)
|
|
201
|
-
: p;
|
|
199
|
+
const rel = (p) => p.startsWith(projectRoot) ? p.slice(projectRoot.length + 1) : p;
|
|
202
200
|
// Get chunk metadata for is_exported and end_line
|
|
203
201
|
const table = yield vectorDb.ensureTable();
|
|
204
202
|
const metaRows = yield table
|
|
@@ -208,8 +206,12 @@ exports.peek = new commander_1.Command("peek")
|
|
|
208
206
|
.limit(1)
|
|
209
207
|
.toArray();
|
|
210
208
|
const exported = metaRows.length > 0 && Boolean(metaRows[0].is_exported);
|
|
211
|
-
const startLine = metaRows.length > 0
|
|
212
|
-
|
|
209
|
+
const startLine = metaRows.length > 0
|
|
210
|
+
? Number(metaRows[0].start_line || 0)
|
|
211
|
+
: center.line;
|
|
212
|
+
const endLine = metaRows.length > 0
|
|
213
|
+
? Number(metaRows[0].end_line || 0)
|
|
214
|
+
: center.line;
|
|
213
215
|
// Get multi-hop callers if depth > 1
|
|
214
216
|
let callerList;
|
|
215
217
|
if (depth > 1) {
|
|
@@ -218,7 +220,11 @@ exports.peek = new commander_1.Command("peek")
|
|
|
218
220
|
const flat = [];
|
|
219
221
|
function walkCallers(tree) {
|
|
220
222
|
for (const t of tree) {
|
|
221
|
-
flat.push({
|
|
223
|
+
flat.push({
|
|
224
|
+
symbol: t.node.symbol,
|
|
225
|
+
file: t.node.file,
|
|
226
|
+
line: t.node.line,
|
|
227
|
+
});
|
|
222
228
|
walkCallers(t.callers);
|
|
223
229
|
}
|
|
224
230
|
}
|
package/dist/commands/plugin.js
CHANGED
|
@@ -43,6 +43,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
43
43
|
};
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
exports.plugin = void 0;
|
|
46
|
+
exports.installAll = installAll;
|
|
46
47
|
const node_child_process_1 = require("node:child_process");
|
|
47
48
|
const fs = __importStar(require("node:fs"));
|
|
48
49
|
const os = __importStar(require("node:os"));
|
|
@@ -107,7 +108,7 @@ function getClients() {
|
|
|
107
108
|
isInstalled: () => {
|
|
108
109
|
const p = path.join(os.homedir(), ".codex", "AGENTS.md");
|
|
109
110
|
try {
|
|
110
|
-
return fs.existsSync(p) && fs.readFileSync(p, "utf-8").includes("gmax");
|
|
111
|
+
return (fs.existsSync(p) && fs.readFileSync(p, "utf-8").includes("gmax"));
|
|
111
112
|
}
|
|
112
113
|
catch (_a) {
|
|
113
114
|
return false;
|
|
@@ -139,6 +140,39 @@ function getClients() {
|
|
|
139
140
|
},
|
|
140
141
|
];
|
|
141
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* Install gmax plugins for every detected client; returns the number installed.
|
|
145
|
+
* Deliberately does NOT call gracefulExit — callers decide how to finish. This
|
|
146
|
+
* lets `gmax setup` keep running (and print its outro) after installing, while
|
|
147
|
+
* the `add` subcommand still exits the process itself.
|
|
148
|
+
*/
|
|
149
|
+
function installAll() {
|
|
150
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
151
|
+
const clients = getClients();
|
|
152
|
+
console.log("gmax plugin add — detecting clients...\n");
|
|
153
|
+
let installed = 0;
|
|
154
|
+
for (const client of clients) {
|
|
155
|
+
if (!client.detect()) {
|
|
156
|
+
console.log(` skip ${client.name} — not found`);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
yield client.install();
|
|
161
|
+
installed++;
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
console.error(` FAIL ${client.name} — ${err instanceof Error ? err.message : String(err)}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (installed === 0) {
|
|
168
|
+
console.log("\nNo supported clients found. Install one of: claude, opencode, codex, droid");
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
console.log(`\n${installed} plugin(s) installed.`);
|
|
172
|
+
}
|
|
173
|
+
return installed;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
142
176
|
// --- Subcommands ---
|
|
143
177
|
const addCmd = new commander_1.Command("add")
|
|
144
178
|
.description("Install or update gmax plugins")
|
|
@@ -164,27 +198,7 @@ const addCmd = new commander_1.Command("add")
|
|
|
164
198
|
return;
|
|
165
199
|
}
|
|
166
200
|
// Install all detected
|
|
167
|
-
|
|
168
|
-
let installed = 0;
|
|
169
|
-
for (const client of clients) {
|
|
170
|
-
if (!client.detect()) {
|
|
171
|
-
console.log(` skip ${client.name} — not found`);
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
try {
|
|
175
|
-
yield client.install();
|
|
176
|
-
installed++;
|
|
177
|
-
}
|
|
178
|
-
catch (err) {
|
|
179
|
-
console.error(` FAIL ${client.name} — ${err instanceof Error ? err.message : String(err)}`);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
if (installed === 0) {
|
|
183
|
-
console.log("\nNo supported clients found. Install one of: claude, opencode, codex, droid");
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
console.log(`\n${installed} plugin(s) installed.`);
|
|
187
|
-
}
|
|
201
|
+
yield installAll();
|
|
188
202
|
yield (0, exit_1.gracefulExit)();
|
|
189
203
|
}));
|
|
190
204
|
const removeCmd = new commander_1.Command("remove")
|
package/dist/commands/project.js
CHANGED
|
@@ -47,11 +47,11 @@ const path = __importStar(require("node:path"));
|
|
|
47
47
|
const commander_1 = require("commander");
|
|
48
48
|
const callsites_1 = require("../lib/graph/callsites");
|
|
49
49
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
50
|
-
const
|
|
50
|
+
const arrow_1 = require("../lib/utils/arrow");
|
|
51
51
|
const exit_1 = require("../lib/utils/exit");
|
|
52
|
+
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
52
53
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
53
54
|
const project_root_1 = require("../lib/utils/project-root");
|
|
54
|
-
const arrow_1 = require("../lib/utils/arrow");
|
|
55
55
|
exports.project = new commander_1.Command("project")
|
|
56
56
|
.description("Show project overview — languages, structure, key symbols")
|
|
57
57
|
.option("--root <dir>", "Project root (defaults to current directory)")
|
|
@@ -79,7 +79,7 @@ exports.project = new commander_1.Command("project")
|
|
|
79
79
|
"defined_symbols",
|
|
80
80
|
"referenced_symbols",
|
|
81
81
|
])
|
|
82
|
-
.where(
|
|
82
|
+
.where((0, filter_builder_1.pathStartsWith)(prefix))
|
|
83
83
|
.limit(200000)
|
|
84
84
|
.toArray();
|
|
85
85
|
if (rows.length === 0) {
|
|
@@ -122,7 +122,10 @@ exports.project = new commander_1.Command("project")
|
|
|
122
122
|
definedInProject.add(d);
|
|
123
123
|
for (const ref of refs)
|
|
124
124
|
symbolRefs.set(ref, (symbolRefs.get(ref) || 0) + 1);
|
|
125
|
-
if (exported &&
|
|
125
|
+
if (exported &&
|
|
126
|
+
role === "ORCHESTRATION" &&
|
|
127
|
+
complexity >= 5 &&
|
|
128
|
+
defs.length > 0) {
|
|
126
129
|
const epKey = `${defs[0]}:${p}`;
|
|
127
130
|
if (!seenEntryPoints.has(epKey)) {
|
|
128
131
|
seenEntryPoints.add(epKey);
|
|
@@ -152,12 +155,19 @@ exports.project = new commander_1.Command("project")
|
|
|
152
155
|
console.log(`files\t${files.size}`);
|
|
153
156
|
console.log(`last_indexed\t${(_b = proj === null || proj === void 0 ? void 0 : proj.lastIndexed) !== null && _b !== void 0 ? _b : "unknown"}`);
|
|
154
157
|
console.log(`languages\t${extEntries.map(([ext]) => ext).join(",")}`);
|
|
155
|
-
console.log(`top_dirs\t${Array.from(dirCounts.entries())
|
|
158
|
+
console.log(`top_dirs\t${Array.from(dirCounts.entries())
|
|
159
|
+
.sort((a, b) => b[1].chunks - a[1].chunks)
|
|
160
|
+
.slice(0, 8)
|
|
161
|
+
.map(([d]) => d)
|
|
162
|
+
.join(",")}`);
|
|
156
163
|
if (topSymbols.length > 0) {
|
|
157
164
|
console.log(`key_symbols\t${topSymbols.map(([s]) => s).join(",")}`);
|
|
158
165
|
}
|
|
159
166
|
if (entryPoints.length > 0) {
|
|
160
|
-
console.log(`entry_points\t${entryPoints
|
|
167
|
+
console.log(`entry_points\t${entryPoints
|
|
168
|
+
.slice(0, 10)
|
|
169
|
+
.map((e) => e.symbol)
|
|
170
|
+
.join(",")}`);
|
|
161
171
|
}
|
|
162
172
|
}
|
|
163
173
|
else {
|
package/dist/commands/related.js
CHANGED
|
@@ -47,20 +47,20 @@ const path = __importStar(require("node:path"));
|
|
|
47
47
|
const commander_1 = require("commander");
|
|
48
48
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
49
49
|
const agent_errors_1 = require("../lib/utils/agent-errors");
|
|
50
|
-
const
|
|
50
|
+
const arrow_1 = require("../lib/utils/arrow");
|
|
51
51
|
const exit_1 = require("../lib/utils/exit");
|
|
52
|
+
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
52
53
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
53
54
|
const project_root_1 = require("../lib/utils/project-root");
|
|
54
55
|
const query_timeout_1 = require("../lib/utils/query-timeout");
|
|
55
56
|
const stale_hint_1 = require("../lib/utils/stale-hint");
|
|
56
|
-
const arrow_1 = require("../lib/utils/arrow");
|
|
57
57
|
exports.related = new commander_1.Command("related")
|
|
58
58
|
.description("Find files related by shared symbol references")
|
|
59
59
|
.argument("<file>", "File path relative to project root")
|
|
60
60
|
.option("-l, --limit <n>", "Max results per direction (default 10)", "10")
|
|
61
61
|
.option("--root <dir>", "Project root directory")
|
|
62
|
-
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) =>
|
|
63
|
-
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) =>
|
|
62
|
+
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) => prev ? [...prev, value] : [value])
|
|
63
|
+
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) => prev ? [...prev, value] : [value])
|
|
64
64
|
.option("--agent", "Compact output for AI agents", false)
|
|
65
65
|
.action((file, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
66
|
var _a;
|
|
@@ -158,13 +158,14 @@ exports.related = new commander_1.Command("related")
|
|
|
158
158
|
"common",
|
|
159
159
|
"shared",
|
|
160
160
|
]);
|
|
161
|
-
|
|
161
|
+
const mentions = [];
|
|
162
162
|
let basename = "";
|
|
163
163
|
let basenameRejected = false;
|
|
164
164
|
if (topDeps.length === 0 && topRevs.length === 0) {
|
|
165
165
|
const ext = path.extname(absPath);
|
|
166
166
|
basename = path.basename(absPath, ext);
|
|
167
|
-
if (basename.length < 4 ||
|
|
167
|
+
if (basename.length < 4 ||
|
|
168
|
+
GENERIC_BASENAMES.has(basename.toLowerCase())) {
|
|
168
169
|
basenameRejected = true;
|
|
169
170
|
}
|
|
170
171
|
else {
|
|
@@ -190,9 +191,7 @@ exports.related = new commander_1.Command("related")
|
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
if (opts.agent) {
|
|
193
|
-
const rel = (p) => p.startsWith(`${projectRoot}/`)
|
|
194
|
-
? p.slice(projectRoot.length + 1)
|
|
195
|
-
: p;
|
|
194
|
+
const rel = (p) => p.startsWith(`${projectRoot}/`) ? p.slice(projectRoot.length + 1) : p;
|
|
196
195
|
for (const [p, count] of topDeps) {
|
|
197
196
|
console.log(`dep: ${rel(p)}\t${count}`);
|
|
198
197
|
}
|
package/dist/commands/remove.js
CHANGED
|
@@ -133,10 +133,17 @@ Examples:
|
|
|
133
133
|
(0, watcher_store_1.unregisterWatcher)(watcher.pid);
|
|
134
134
|
}
|
|
135
135
|
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
136
|
+
// Slash-terminate so removing /repo/app can't also delete the sibling
|
|
137
|
+
// /repo/app2 — VectorDB matches `path LIKE prefix%` and MetaCache
|
|
138
|
+
// matches `key.startsWith(prefix)`, both of which bleed across siblings
|
|
139
|
+
// without the trailing slash. Mirrors the daemon remove path.
|
|
140
|
+
const rootPrefix = projectRoot.endsWith("/")
|
|
141
|
+
? projectRoot
|
|
142
|
+
: `${projectRoot}/`;
|
|
136
143
|
vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
|
|
137
|
-
yield vectorDb.deletePathsWithPrefix(
|
|
144
|
+
yield vectorDb.deletePathsWithPrefix(rootPrefix);
|
|
138
145
|
metaCache = new meta_cache_1.MetaCache(paths.lmdbPath);
|
|
139
|
-
const keys = yield metaCache.getKeysWithPrefix(
|
|
146
|
+
const keys = yield metaCache.getKeysWithPrefix(rootPrefix);
|
|
140
147
|
for (const key of keys) {
|
|
141
148
|
metaCache.delete(key);
|
|
142
149
|
}
|
package/dist/commands/review.js
CHANGED
|
@@ -85,7 +85,7 @@ Subcommands:
|
|
|
85
85
|
const { VectorDB } = yield Promise.resolve().then(() => __importStar(require("../lib/store/vector-db")));
|
|
86
86
|
const { GraphBuilder } = yield Promise.resolve().then(() => __importStar(require("../lib/graph/graph-builder")));
|
|
87
87
|
const { ensureProjectPaths } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/project-root")));
|
|
88
|
-
const { gatherRiskInputs, computeRiskTable, formatRiskTable
|
|
88
|
+
const { gatherRiskInputs, computeRiskTable, formatRiskTable } = yield Promise.resolve().then(() => __importStar(require("../lib/review/risk")));
|
|
89
89
|
const paths = ensureProjectPaths(projectRoot);
|
|
90
90
|
const vectorDb = new VectorDB(paths.lancedbDir);
|
|
91
91
|
try {
|
package/dist/commands/setup.js
CHANGED
|
@@ -154,8 +154,10 @@ exports.setup = new commander_1.Command("setup")
|
|
|
154
154
|
initialValue: true,
|
|
155
155
|
});
|
|
156
156
|
if (!p.isCancel(installPlugins) && installPlugins) {
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
// Call installAll() directly, not `plugin` (bare status) or the `add`
|
|
158
|
+
// subcommand — both gracefulExit() before setup's outro can run.
|
|
159
|
+
const { installAll } = yield Promise.resolve().then(() => __importStar(require("./plugin")));
|
|
160
|
+
yield installAll();
|
|
159
161
|
}
|
|
160
162
|
p.outro(`Ready — ${selectedTier.label}, ${embedMode === "gpu" ? "GPU" : "CPU"} mode`);
|
|
161
163
|
yield (0, exit_1.gracefulExit)();
|
package/dist/commands/similar.js
CHANGED
|
@@ -47,20 +47,20 @@ const path = __importStar(require("node:path"));
|
|
|
47
47
|
const commander_1 = require("commander");
|
|
48
48
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
49
49
|
const agent_errors_1 = require("../lib/utils/agent-errors");
|
|
50
|
-
const
|
|
50
|
+
const arrow_1 = require("../lib/utils/arrow");
|
|
51
51
|
const exit_1 = require("../lib/utils/exit");
|
|
52
|
+
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
52
53
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
53
54
|
const project_root_1 = require("../lib/utils/project-root");
|
|
54
55
|
const stale_hint_1 = require("../lib/utils/stale-hint");
|
|
55
|
-
const arrow_1 = require("../lib/utils/arrow");
|
|
56
56
|
exports.similar = new commander_1.Command("similar")
|
|
57
57
|
.description("Find semantically similar code to a symbol or file")
|
|
58
58
|
.argument("<target>", "Symbol name or file path")
|
|
59
59
|
.option("-m, --max-count <n>", "Max results (default 5)", "5")
|
|
60
60
|
.option("--threshold <score>", "Min similarity 0-1 (default 0)")
|
|
61
61
|
.option("--root <dir>", "Project root directory")
|
|
62
|
-
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) =>
|
|
63
|
-
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) =>
|
|
62
|
+
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) => prev ? [...prev, value] : [value])
|
|
63
|
+
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) => prev ? [...prev, value] : [value])
|
|
64
64
|
.option("--agent", "Compact output for AI agents", false)
|
|
65
65
|
.action((target, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
66
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
package/dist/commands/status.js
CHANGED
|
@@ -47,8 +47,8 @@ const os = __importStar(require("node:os"));
|
|
|
47
47
|
const commander_1 = require("commander");
|
|
48
48
|
const config_1 = require("../config");
|
|
49
49
|
const index_config_1 = require("../lib/index/index-config");
|
|
50
|
-
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
51
50
|
const exit_1 = require("../lib/utils/exit");
|
|
51
|
+
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
52
52
|
const lock_1 = require("../lib/utils/lock");
|
|
53
53
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
54
54
|
const project_root_1 = require("../lib/utils/project-root");
|
|
@@ -115,17 +115,19 @@ Examples:
|
|
|
115
115
|
const db = new VectorDB(config_1.PATHS.lancedbDir);
|
|
116
116
|
const table = yield db.ensureTable();
|
|
117
117
|
for (const project of projects) {
|
|
118
|
-
const prefix = project.root.endsWith("/")
|
|
118
|
+
const prefix = project.root.endsWith("/")
|
|
119
|
+
? project.root
|
|
120
|
+
: `${project.root}/`;
|
|
119
121
|
const rows = yield table
|
|
120
122
|
.query()
|
|
121
123
|
.select(["id"])
|
|
122
|
-
.where(
|
|
124
|
+
.where((0, filter_builder_1.pathStartsWith)(prefix))
|
|
123
125
|
.toArray();
|
|
124
126
|
chunkCounts.set(project.root, rows.length);
|
|
125
127
|
}
|
|
126
128
|
yield db.close();
|
|
127
129
|
}
|
|
128
|
-
catch (
|
|
130
|
+
catch (_e) {
|
|
129
131
|
console.warn(`[status] Failed to query LanceDB for live chunk counts, using cached counts`);
|
|
130
132
|
}
|
|
131
133
|
if (projects.length === 0) {
|
|
@@ -56,15 +56,17 @@ exports.summarize = new commander_1.Command("summarize")
|
|
|
56
56
|
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
57
57
|
var _a, _b, _c;
|
|
58
58
|
const paths = (0, project_root_1.ensureProjectPaths)(process.cwd());
|
|
59
|
-
const rootPrefix = options.path
|
|
60
|
-
? `${path.resolve(options.path)}/`
|
|
61
|
-
: "";
|
|
59
|
+
const rootPrefix = options.path ? `${path.resolve(options.path)}/` : "";
|
|
62
60
|
const { spinner } = (0, sync_helpers_1.createIndexingSpinner)("", "Summarizing...");
|
|
63
61
|
const { isDaemonRunning, sendStreamingCommand } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/daemon-client")));
|
|
64
62
|
if (yield isDaemonRunning()) {
|
|
65
63
|
// Daemon mode: IPC streaming
|
|
66
64
|
try {
|
|
67
|
-
const done = yield sendStreamingCommand({
|
|
65
|
+
const done = yield sendStreamingCommand({
|
|
66
|
+
cmd: "summarize",
|
|
67
|
+
root: paths.root,
|
|
68
|
+
pathPrefix: rootPrefix || undefined,
|
|
69
|
+
}, (msg) => {
|
|
68
70
|
var _a, _b;
|
|
69
71
|
spinner.text = `Summarizing... (${(_a = msg.summarized) !== null && _a !== void 0 ? _a : 0}/${(_b = msg.total) !== null && _b !== void 0 ? _b : 0})`;
|
|
70
72
|
});
|
package/dist/commands/symbols.js
CHANGED
|
@@ -86,7 +86,7 @@ function collectSymbols(options) {
|
|
|
86
86
|
const absPrefix = path.isAbsolute(options.pathPrefix)
|
|
87
87
|
? options.pathPrefix
|
|
88
88
|
: path.resolve(options.projectRoot, options.pathPrefix);
|
|
89
|
-
query = query.where(
|
|
89
|
+
query = query.where((0, filter_builder_1.pathStartsWith)((0, filter_builder_1.normalizePath)(absPrefix)));
|
|
90
90
|
}
|
|
91
91
|
const rows = yield query.toArray();
|
|
92
92
|
const map = new Map();
|
|
@@ -56,8 +56,8 @@ exports.testFind = new commander_1.Command("test")
|
|
|
56
56
|
.argument("<target>", "Symbol name or file path")
|
|
57
57
|
.option("-d, --depth <n>", "Caller traversal depth (default 1, max 3)", "1")
|
|
58
58
|
.option("--root <dir>", "Project root directory")
|
|
59
|
-
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) =>
|
|
60
|
-
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) =>
|
|
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])
|
|
61
61
|
.option("--agent", "Compact output for AI agents", false)
|
|
62
62
|
.action((target, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
63
63
|
var _a;
|
package/dist/commands/trace.js
CHANGED
|
@@ -51,8 +51,8 @@ const vector_db_1 = require("../lib/store/vector-db");
|
|
|
51
51
|
const agent_errors_1 = require("../lib/utils/agent-errors");
|
|
52
52
|
const exit_1 = require("../lib/utils/exit");
|
|
53
53
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
54
|
-
const stale_hint_1 = require("../lib/utils/stale-hint");
|
|
55
54
|
const project_root_1 = require("../lib/utils/project-root");
|
|
55
|
+
const stale_hint_1 = require("../lib/utils/stale-hint");
|
|
56
56
|
const useColors = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
57
57
|
const dim = (s) => (useColors ? `\x1b[2m${s}\x1b[22m` : s);
|
|
58
58
|
const bold = (s) => (useColors ? `\x1b[1m${s}\x1b[22m` : s);
|
|
@@ -87,7 +87,12 @@ function formatTraceAgent(graph, projectRoot, raw = false) {
|
|
|
87
87
|
const key = `${t.node.symbol}\t${t.node.file}`;
|
|
88
88
|
let g = groups.get(key);
|
|
89
89
|
if (!g) {
|
|
90
|
-
g = {
|
|
90
|
+
g = {
|
|
91
|
+
symbol: t.node.symbol,
|
|
92
|
+
file: t.node.file,
|
|
93
|
+
lineSet: new Set(),
|
|
94
|
+
sub: [],
|
|
95
|
+
};
|
|
91
96
|
groups.set(key, g);
|
|
92
97
|
order.push(key);
|
|
93
98
|
}
|
|
@@ -149,7 +154,9 @@ function formatInboundAgent(center, tree, projectRoot, withSnippets) {
|
|
|
149
154
|
var _a, _b;
|
|
150
155
|
for (const n of nodes) {
|
|
151
156
|
const prefix = " ".repeat(depth);
|
|
152
|
-
const loc = n.file
|
|
157
|
+
const loc = n.file
|
|
158
|
+
? `${rel(n.file)}:${((_a = n.snippetLine) !== null && _a !== void 0 ? _a : n.line) + 1}`
|
|
159
|
+
: "(not indexed)";
|
|
153
160
|
const cols = withSnippets
|
|
154
161
|
? `${loc}\t${n.symbol}\t${(_b = n.snippet) !== null && _b !== void 0 ? _b : ""}`
|
|
155
162
|
: `${loc}\t${n.symbol}`;
|
|
@@ -202,8 +209,8 @@ exports.trace = new commander_1.Command("trace")
|
|
|
202
209
|
.argument("<symbol>", "The symbol to trace")
|
|
203
210
|
.option("-d, --depth <n>", "Caller traversal depth (default 1, max 3)", "1")
|
|
204
211
|
.option("--root <dir>", "Project root directory")
|
|
205
|
-
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) =>
|
|
206
|
-
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) =>
|
|
212
|
+
.option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) => prev ? [...prev, value] : [value])
|
|
213
|
+
.option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) => prev ? [...prev, value] : [value])
|
|
207
214
|
.option("--agent", "Compact output for AI agents", false)
|
|
208
215
|
.option("--inbound", "Show only callers, with call-site snippets", false)
|
|
209
216
|
.option("--no-snippets", "Suppress call-site snippets in --inbound output")
|
package/dist/commands/watch.js
CHANGED
|
@@ -43,18 +43,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
43
43
|
};
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
exports.watch = void 0;
|
|
46
|
-
const fs = __importStar(require("node:fs"));
|
|
47
46
|
const node_child_process_1 = require("node:child_process");
|
|
47
|
+
const fs = __importStar(require("node:fs"));
|
|
48
48
|
const path = __importStar(require("node:path"));
|
|
49
49
|
const commander_1 = require("commander");
|
|
50
50
|
const config_1 = require("../config");
|
|
51
51
|
const index_config_1 = require("../lib/index/index-config");
|
|
52
|
-
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
53
52
|
const syncer_1 = require("../lib/index/syncer");
|
|
54
53
|
const watcher_1 = require("../lib/index/watcher");
|
|
55
54
|
const meta_cache_1 = require("../lib/store/meta-cache");
|
|
56
55
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
57
56
|
const exit_1 = require("../lib/utils/exit");
|
|
57
|
+
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
58
58
|
const log_rotate_1 = require("../lib/utils/log-rotate");
|
|
59
59
|
const process_1 = require("../lib/utils/process");
|
|
60
60
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
@@ -81,7 +81,7 @@ exports.watch = new commander_1.Command("watch")
|
|
|
81
81
|
// Skip spawn if daemon already running at the same version.
|
|
82
82
|
// If version mismatches (e.g. after npm install -g), shut down the old
|
|
83
83
|
// daemon so we can start a fresh one with the new code.
|
|
84
|
-
const { isDaemonRunning, isDaemonHeartbeatFresh, sendDaemonCommand } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/daemon-client")));
|
|
84
|
+
const { isDaemonRunning, isDaemonHeartbeatFresh, sendDaemonCommand, readDaemonPid, waitForProcessExit, } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/daemon-client")));
|
|
85
85
|
if (yield isDaemonRunning()) {
|
|
86
86
|
const cliVersion = JSON.parse(fs.readFileSync(path.join(__dirname, "../../package.json"), "utf-8")).version;
|
|
87
87
|
const resp = yield sendDaemonCommand({ cmd: "ping" });
|
|
@@ -89,6 +89,12 @@ exports.watch = new commander_1.Command("watch")
|
|
|
89
89
|
process.exit(0);
|
|
90
90
|
}
|
|
91
91
|
console.log(`Daemon version mismatch (${resp.version} → ${cliVersion}), restarting...`);
|
|
92
|
+
// Capture the old PID before shutdown removes the PID file, so we
|
|
93
|
+
// can wait for the process to fully EXIT rather than guessing with a
|
|
94
|
+
// fixed sleep. Spawning the successor while the old daemon is still
|
|
95
|
+
// draining lets the successor's killStaleProcesses() classify it as
|
|
96
|
+
// stale and SIGKILL it mid-cleanup.
|
|
97
|
+
const oldPid = readDaemonPid();
|
|
92
98
|
yield sendDaemonCommand({
|
|
93
99
|
cmd: "shutdown",
|
|
94
100
|
reason: "version-mismatch",
|
|
@@ -97,8 +103,15 @@ exports.watch = new commander_1.Command("watch")
|
|
|
97
103
|
from_version: cliVersion,
|
|
98
104
|
from_argv: process.argv.slice(0, 4),
|
|
99
105
|
});
|
|
100
|
-
|
|
101
|
-
|
|
106
|
+
if (oldPid) {
|
|
107
|
+
const exited = yield waitForProcessExit(oldPid, 20000);
|
|
108
|
+
if (!exited) {
|
|
109
|
+
console.log(`Old daemon (PID ${oldPid}) still draining after 20s — starting anyway`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
yield new Promise((r) => setTimeout(r, 2000));
|
|
114
|
+
}
|
|
102
115
|
}
|
|
103
116
|
else if (isDaemonHeartbeatFresh()) {
|
|
104
117
|
// Ping failed but daemon.lock mtime is fresh — another daemon is
|
|
@@ -131,6 +144,13 @@ exports.watch = new commander_1.Command("watch")
|
|
|
131
144
|
process.exit(0);
|
|
132
145
|
}
|
|
133
146
|
console.error("[daemon] Failed to start:", err);
|
|
147
|
+
// Tear down any half-opened state — the listening socket, PID, and
|
|
148
|
+
// lock — so we don't leave a zombie that answers pings but has no
|
|
149
|
+
// resources. The socket also keeps the event loop alive otherwise.
|
|
150
|
+
try {
|
|
151
|
+
yield daemon.shutdown();
|
|
152
|
+
}
|
|
153
|
+
catch (_c) { }
|
|
134
154
|
process.exitCode = 1;
|
|
135
155
|
return;
|
|
136
156
|
}
|
|
@@ -148,7 +168,7 @@ exports.watch = new commander_1.Command("watch")
|
|
|
148
168
|
// --- Per-project mode ---
|
|
149
169
|
const projectRoot = options.path
|
|
150
170
|
? path.resolve(options.path)
|
|
151
|
-
: (_a = (0, project_root_1.findProjectRoot)(process.cwd())) !== null && _a !== void 0 ? _a : process.cwd();
|
|
171
|
+
: ((_a = (0, project_root_1.findProjectRoot)(process.cwd())) !== null && _a !== void 0 ? _a : process.cwd());
|
|
152
172
|
const projectName = path.basename(projectRoot);
|
|
153
173
|
// Check if watcher already running (exact match or parent covering this dir)
|
|
154
174
|
const existing = (_b = (0, watcher_store_1.getWatcherForProject)(projectRoot)) !== null && _b !== void 0 ? _b : (0, watcher_store_1.getWatcherCoveringPath)(projectRoot);
|
|
@@ -195,11 +215,13 @@ exports.watch = new commander_1.Command("watch")
|
|
|
195
215
|
// Initial sync if this directory isn't indexed yet
|
|
196
216
|
const vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
|
|
197
217
|
const table = yield vectorDb.ensureTable();
|
|
198
|
-
const prefix = projectRoot.endsWith("/")
|
|
218
|
+
const prefix = projectRoot.endsWith("/")
|
|
219
|
+
? projectRoot
|
|
220
|
+
: `${projectRoot}/`;
|
|
199
221
|
const indexed = yield table
|
|
200
222
|
.query()
|
|
201
223
|
.select(["id"])
|
|
202
|
-
.where(
|
|
224
|
+
.where((0, filter_builder_1.pathStartsWith)(prefix))
|
|
203
225
|
.limit(1)
|
|
204
226
|
.toArray();
|
|
205
227
|
if (indexed.length === 0) {
|
|
@@ -325,7 +347,9 @@ exports.watch
|
|
|
325
347
|
let parentCmd = "?";
|
|
326
348
|
try {
|
|
327
349
|
const { execSync } = yield Promise.resolve().then(() => __importStar(require("node:child_process")));
|
|
328
|
-
parentCmd = execSync(`ps -o command= -p ${process.ppid}`, {
|
|
350
|
+
parentCmd = execSync(`ps -o command= -p ${process.ppid}`, {
|
|
351
|
+
encoding: "utf8",
|
|
352
|
+
}).trim();
|
|
329
353
|
}
|
|
330
354
|
catch (_c) { }
|
|
331
355
|
yield sendDaemonCommand({
|
package/dist/eval-graph-nav.js
CHANGED
|
@@ -93,7 +93,10 @@ const SELF = "src/eval-graph-nav.ts"; // exclude from grep + graph (self-referen
|
|
|
93
93
|
// grep can't tell those apart from genuine uses, so they would manufacture
|
|
94
94
|
// phantom "expected callers" that no correct graph ever surfaces. Excluded from
|
|
95
95
|
// both the grep truth and the getCallers set so the exclusion stays symmetric.
|
|
96
|
-
const FIXTURE_FILES = new Set([
|
|
96
|
+
const FIXTURE_FILES = new Set([
|
|
97
|
+
SELF,
|
|
98
|
+
"tests/graph-edges.type-position.test.ts",
|
|
99
|
+
]);
|
|
97
100
|
const rel = (p) => p.replace(`${GMAX_ROOT}/`, "");
|
|
98
101
|
const INBOUND_SYMBOLS = [
|
|
99
102
|
// ── Baselines: called/constructed, so the graph captures them. ──────────────
|