grepmax 0.17.21 → 0.17.23
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/add.js +3 -2
- package/dist/commands/audit.js +19 -2
- package/dist/commands/context.js +34 -2
- package/dist/commands/doctor.js +18 -0
- package/dist/commands/impact.js +24 -14
- package/dist/commands/index.js +16 -6
- package/dist/commands/mcp.js +2 -0
- package/dist/commands/peek.js +94 -17
- package/dist/commands/project.js +17 -4
- package/dist/commands/related.js +5 -3
- package/dist/commands/search-run.js +227 -0
- package/dist/commands/search-skeletons.js +133 -0
- package/dist/commands/search.js +46 -450
- package/dist/commands/test-find.js +8 -14
- package/dist/commands/trace.js +2 -29
- package/dist/config.js +5 -0
- package/dist/eval-like-limit-probe.js +62 -0
- package/dist/lib/daemon/daemon.js +15 -102
- package/dist/lib/daemon/search-handler.js +159 -0
- package/dist/lib/graph/callsites.js +148 -0
- package/dist/lib/graph/graph-builder.js +7 -3
- package/dist/lib/graph/impact.js +24 -11
- package/dist/lib/graph/test-hits.js +54 -0
- package/dist/lib/help/agent-cheatsheet.js +5 -0
- package/dist/lib/index/chunker.js +36 -2
- package/dist/lib/output/agent-search-formatter.js +59 -3
- package/dist/lib/output/compact-results.js +244 -0
- package/dist/lib/search/searcher.js +2 -1
- package/dist/lib/utils/query-timeout.js +52 -0
- package/package.json +2 -2
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
package/dist/commands/search.js
CHANGED
|
@@ -43,315 +43,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
43
43
|
};
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
exports.search = void 0;
|
|
46
|
-
const fs = __importStar(require("node:fs"));
|
|
47
46
|
const path = __importStar(require("node:path"));
|
|
48
47
|
const commander_1 = require("commander");
|
|
49
|
-
const grammar_loader_1 = require("../lib/index/grammar-loader");
|
|
50
|
-
const sync_helpers_1 = require("../lib/index/sync-helpers");
|
|
51
|
-
const syncer_1 = require("../lib/index/syncer");
|
|
52
48
|
const agent_search_formatter_1 = require("../lib/output/agent-search-formatter");
|
|
49
|
+
const compact_results_1 = require("../lib/output/compact-results");
|
|
53
50
|
const index_state_footer_1 = require("../lib/output/index-state-footer");
|
|
54
|
-
const searcher_1 = require("../lib/search/searcher");
|
|
55
51
|
const setup_helpers_1 = require("../lib/setup/setup-helpers");
|
|
56
|
-
const skeleton_1 = require("../lib/skeleton");
|
|
57
|
-
const retriever_1 = require("../lib/skeleton/retriever");
|
|
58
|
-
const vector_db_1 = require("../lib/store/vector-db");
|
|
59
52
|
const cross_project_1 = require("../lib/utils/cross-project");
|
|
60
53
|
const exit_1 = require("../lib/utils/exit");
|
|
61
54
|
const formatter_1 = require("../lib/utils/formatter");
|
|
62
55
|
const import_extractor_1 = require("../lib/utils/import-extractor");
|
|
63
|
-
const lock_1 = require("../lib/utils/lock");
|
|
64
56
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
65
57
|
const project_root_1 = require("../lib/utils/project-root");
|
|
66
58
|
const server_registry_1 = require("../lib/utils/server-registry");
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
var _a, _b, _c, _d, _e, _f;
|
|
70
|
-
const rawPath = typeof ((_a = r.metadata) === null || _a === void 0 ? void 0 : _a.path) === "string"
|
|
71
|
-
? r.metadata.path
|
|
72
|
-
: "Unknown path";
|
|
73
|
-
const start = typeof ((_b = r.generated_metadata) === null || _b === void 0 ? void 0 : _b.start_line) === "number"
|
|
74
|
-
? r.generated_metadata.start_line
|
|
75
|
-
: 0;
|
|
76
|
-
const end = typeof ((_c = r.generated_metadata) === null || _c === void 0 ? void 0 : _c.end_line) === "number"
|
|
77
|
-
? r.generated_metadata.end_line
|
|
78
|
-
: start + Math.max(0, ((_e = (_d = r.generated_metadata) === null || _d === void 0 ? void 0 : _d.num_lines) !== null && _e !== void 0 ? _e : 1) - 1);
|
|
79
|
-
return {
|
|
80
|
-
path: rawPath,
|
|
81
|
-
score: r.score,
|
|
82
|
-
content: r.text || "",
|
|
83
|
-
chunk_type: (_f = r.generated_metadata) === null || _f === void 0 ? void 0 : _f.type,
|
|
84
|
-
start_line: start,
|
|
85
|
-
end_line: end,
|
|
86
|
-
};
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
function getPreviewText(chunk) {
|
|
90
|
-
var _a, _b, _c, _d, _e;
|
|
91
|
-
const maxLen = 140;
|
|
92
|
-
const lines = (_b = (_a = chunk.text) === null || _a === void 0 ? void 0 : _a.split("\n").map((l) => l.trim()).filter(Boolean)) !== null && _b !== void 0 ? _b : [];
|
|
93
|
-
let preview = (_c = lines[0]) !== null && _c !== void 0 ? _c : "";
|
|
94
|
-
if (!preview && ((_d = chunk.defined_symbols) === null || _d === void 0 ? void 0 : _d.length)) {
|
|
95
|
-
preview = (_e = chunk.defined_symbols[0]) !== null && _e !== void 0 ? _e : "";
|
|
96
|
-
}
|
|
97
|
-
if (preview.length > maxLen) {
|
|
98
|
-
preview = `${preview.slice(0, maxLen)}...`;
|
|
99
|
-
}
|
|
100
|
-
return preview;
|
|
101
|
-
}
|
|
102
|
-
function toCompactHits(data) {
|
|
103
|
-
return data.map((chunk) => {
|
|
104
|
-
var _a, _b, _c, _d, _e, _f;
|
|
105
|
-
const rawPath = typeof ((_a = chunk.metadata) === null || _a === void 0 ? void 0 : _a.path) === "string"
|
|
106
|
-
? chunk.metadata.path
|
|
107
|
-
: "Unknown path";
|
|
108
|
-
const start = typeof ((_b = chunk.generated_metadata) === null || _b === void 0 ? void 0 : _b.start_line) === "number"
|
|
109
|
-
? chunk.generated_metadata.start_line
|
|
110
|
-
: 0;
|
|
111
|
-
const end = typeof ((_c = chunk.generated_metadata) === null || _c === void 0 ? void 0 : _c.end_line) === "number"
|
|
112
|
-
? chunk.generated_metadata.end_line
|
|
113
|
-
: start + Math.max(0, ((_e = (_d = chunk.generated_metadata) === null || _d === void 0 ? void 0 : _d.num_lines) !== null && _e !== void 0 ? _e : 1) - 1);
|
|
114
|
-
return {
|
|
115
|
-
path: rawPath,
|
|
116
|
-
range: `${start + 1}-${end + 1}`,
|
|
117
|
-
start_line: start,
|
|
118
|
-
end_line: end,
|
|
119
|
-
role: chunk.role,
|
|
120
|
-
confidence: chunk.confidence,
|
|
121
|
-
score: chunk.score,
|
|
122
|
-
defined: Array.isArray(chunk.defined_symbols)
|
|
123
|
-
? chunk.defined_symbols.slice(0, 3)
|
|
124
|
-
: typeof chunk.defined_symbols === "string"
|
|
125
|
-
? [chunk.defined_symbols]
|
|
126
|
-
: typeof ((_f = chunk.defined_symbols) === null || _f === void 0 ? void 0 : _f.toArray) === "function"
|
|
127
|
-
? chunk.defined_symbols.toArray().slice(0, 3)
|
|
128
|
-
: [],
|
|
129
|
-
preview: getPreviewText(chunk),
|
|
130
|
-
summary: typeof chunk.summary === "string" ? chunk.summary : undefined,
|
|
131
|
-
};
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
function compactRole(role) {
|
|
135
|
-
if (!role)
|
|
136
|
-
return "UNK";
|
|
137
|
-
if (role.startsWith("ORCH"))
|
|
138
|
-
return "ORCH";
|
|
139
|
-
if (role.startsWith("DEF"))
|
|
140
|
-
return "DEF";
|
|
141
|
-
if (role.startsWith("IMP"))
|
|
142
|
-
return "IMPL";
|
|
143
|
-
return role.slice(0, 4).toUpperCase();
|
|
144
|
-
}
|
|
145
|
-
function compactConf(conf) {
|
|
146
|
-
if (!conf)
|
|
147
|
-
return "U";
|
|
148
|
-
const c = conf.toUpperCase();
|
|
149
|
-
if (c.startsWith("H"))
|
|
150
|
-
return "H";
|
|
151
|
-
if (c.startsWith("M"))
|
|
152
|
-
return "M";
|
|
153
|
-
if (c.startsWith("L"))
|
|
154
|
-
return "L";
|
|
155
|
-
return "U";
|
|
156
|
-
}
|
|
157
|
-
function compactScore(score) {
|
|
158
|
-
if (typeof score !== "number")
|
|
159
|
-
return "";
|
|
160
|
-
const fixed = score.toFixed(3);
|
|
161
|
-
return fixed
|
|
162
|
-
.replace(/^0\./, ".")
|
|
163
|
-
.replace(/\.?0+$/, (m) => (m.startsWith(".") ? "" : m));
|
|
164
|
-
}
|
|
165
|
-
function truncateEnd(s, max) {
|
|
166
|
-
if (max <= 0)
|
|
167
|
-
return "";
|
|
168
|
-
if (s.length <= max)
|
|
169
|
-
return s;
|
|
170
|
-
if (max <= 3)
|
|
171
|
-
return s.slice(0, max);
|
|
172
|
-
return `${s.slice(0, max - 3)}...`;
|
|
173
|
-
}
|
|
174
|
-
function padR(s, w) {
|
|
175
|
-
const n = Math.max(0, w - s.length);
|
|
176
|
-
return s + " ".repeat(n);
|
|
177
|
-
}
|
|
178
|
-
function padL(s, w) {
|
|
179
|
-
const n = Math.max(0, w - s.length);
|
|
180
|
-
return " ".repeat(n) + s;
|
|
181
|
-
}
|
|
182
|
-
function formatCompactTSV(hits, projectRoot, query) {
|
|
183
|
-
var _a, _b;
|
|
184
|
-
if (!hits.length)
|
|
185
|
-
return "No matches found.";
|
|
186
|
-
const lines = [];
|
|
187
|
-
lines.push(`gmax hits\tquery=${query}\tcount=${hits.length}`);
|
|
188
|
-
lines.push("path\tlines\tscore\trole\tconf\tdefined\tsummary");
|
|
189
|
-
for (const hit of hits) {
|
|
190
|
-
const relPath = path.isAbsolute(hit.path)
|
|
191
|
-
? path.relative(projectRoot, hit.path)
|
|
192
|
-
: hit.path;
|
|
193
|
-
const score = compactScore(hit.score);
|
|
194
|
-
const role = compactRole(hit.role);
|
|
195
|
-
const conf = compactConf(hit.confidence);
|
|
196
|
-
const defs = ((_a = hit.defined) !== null && _a !== void 0 ? _a : []).join(",");
|
|
197
|
-
const summary = (_b = hit.summary) !== null && _b !== void 0 ? _b : "";
|
|
198
|
-
lines.push([relPath, hit.range, score, role, conf, defs, summary].join("\t"));
|
|
199
|
-
}
|
|
200
|
-
return lines.join("\n");
|
|
201
|
-
}
|
|
202
|
-
function formatCompactPretty(hits, projectRoot, query, termWidth, useAnsi) {
|
|
203
|
-
var _a;
|
|
204
|
-
if (!hits.length)
|
|
205
|
-
return "No matches found.";
|
|
206
|
-
const dim = (s) => (useAnsi ? `\x1b[90m${s}\x1b[0m` : s);
|
|
207
|
-
const bold = (s) => (useAnsi ? `\x1b[1m${s}\x1b[0m` : s);
|
|
208
|
-
const wLines = 9;
|
|
209
|
-
const wScore = 6;
|
|
210
|
-
const wRole = 4;
|
|
211
|
-
const wConf = 1;
|
|
212
|
-
const wDef = 20;
|
|
213
|
-
const gutters = 5;
|
|
214
|
-
const fixed = wLines + wScore + wRole + wConf + wDef + gutters;
|
|
215
|
-
const wPath = Math.max(24, Math.min(64, termWidth - fixed));
|
|
216
|
-
const header = `gmax hits count=${hits.length} query="${query}"`;
|
|
217
|
-
const cols = [
|
|
218
|
-
padR("path", wPath),
|
|
219
|
-
padR("lines", wLines),
|
|
220
|
-
padL("score", wScore),
|
|
221
|
-
padR("role", wRole),
|
|
222
|
-
padR("c", wConf),
|
|
223
|
-
padR("defined", wDef),
|
|
224
|
-
].join(" ");
|
|
225
|
-
const out = [];
|
|
226
|
-
out.push(bold(header));
|
|
227
|
-
out.push(dim(cols));
|
|
228
|
-
for (const hit of hits) {
|
|
229
|
-
const relPath = path.isAbsolute(hit.path)
|
|
230
|
-
? path.relative(projectRoot, hit.path)
|
|
231
|
-
: hit.path;
|
|
232
|
-
const score = compactScore(hit.score);
|
|
233
|
-
const role = compactRole(hit.role);
|
|
234
|
-
const conf = compactConf(hit.confidence);
|
|
235
|
-
const defs = ((_a = hit.defined) !== null && _a !== void 0 ? _a : []).join(",") || "-";
|
|
236
|
-
const displayPath = `${relPath}:${hit.start_line + 1}`;
|
|
237
|
-
const paddedPath = padR(displayPath, wPath);
|
|
238
|
-
const row = [
|
|
239
|
-
paddedPath,
|
|
240
|
-
padR(hit.range, wLines),
|
|
241
|
-
padL(score || "", wScore),
|
|
242
|
-
padR(role, wRole),
|
|
243
|
-
padR(conf, wConf),
|
|
244
|
-
padR(truncateEnd(defs, wDef), wDef),
|
|
245
|
-
].join(" ");
|
|
246
|
-
out.push(row);
|
|
247
|
-
}
|
|
248
|
-
return out.join("\n");
|
|
249
|
-
}
|
|
250
|
-
function formatCompactTable(hits, projectRoot, query, opts) {
|
|
251
|
-
var _a;
|
|
252
|
-
if (!hits.length)
|
|
253
|
-
return "No matches found.";
|
|
254
|
-
if (!opts.isTTY || opts.plain) {
|
|
255
|
-
return formatCompactTSV(hits, projectRoot, query);
|
|
256
|
-
}
|
|
257
|
-
const termWidth = Math.max(80, (_a = process.stdout.columns) !== null && _a !== void 0 ? _a : 120);
|
|
258
|
-
return formatCompactPretty(hits, projectRoot, query, termWidth, true);
|
|
259
|
-
}
|
|
260
|
-
// Reuse Skeletonizer instance
|
|
261
|
-
let globalSkeletonizer = null;
|
|
262
|
-
function outputSkeletons(results, projectRoot, limit, db, precomputed) {
|
|
263
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
264
|
-
var _a, _b;
|
|
265
|
-
const seenPaths = new Set();
|
|
266
|
-
const filesToProcess = [];
|
|
267
|
-
for (const result of results) {
|
|
268
|
-
const p = (_a = result.metadata) === null || _a === void 0 ? void 0 : _a.path;
|
|
269
|
-
if (typeof p === "string" && !seenPaths.has(p)) {
|
|
270
|
-
seenPaths.add(p);
|
|
271
|
-
filesToProcess.push(p);
|
|
272
|
-
if (filesToProcess.length >= limit)
|
|
273
|
-
break;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
if (filesToProcess.length === 0) {
|
|
277
|
-
console.log("No skeleton matches found.");
|
|
278
|
-
console.log("\nTry: broaden your query, or use `gmax skeleton <path>` to view a specific file's structure.");
|
|
279
|
-
process.exitCode = 1;
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
// Reuse or init skeletonizer for fallbacks
|
|
283
|
-
if (!globalSkeletonizer) {
|
|
284
|
-
globalSkeletonizer = new skeleton_1.Skeletonizer();
|
|
285
|
-
// Lazy init only if we actually fallback
|
|
286
|
-
}
|
|
287
|
-
const skeletonOpts = { includeSummary: true };
|
|
288
|
-
const skeletonResults = [];
|
|
289
|
-
for (const filePath of filesToProcess) {
|
|
290
|
-
// Paths from search results are now absolute (centralized index)
|
|
291
|
-
const absPath = path.isAbsolute(filePath)
|
|
292
|
-
? filePath
|
|
293
|
-
: path.resolve(projectRoot, filePath);
|
|
294
|
-
// 0. Daemon-supplied (preferred — already-warm DB lookup, no cold open)
|
|
295
|
-
const fromDaemon = (_b = precomputed === null || precomputed === void 0 ? void 0 : precomputed[absPath]) !== null && _b !== void 0 ? _b : precomputed === null || precomputed === void 0 ? void 0 : precomputed[filePath];
|
|
296
|
-
if (fromDaemon) {
|
|
297
|
-
skeletonResults.push({
|
|
298
|
-
file: filePath,
|
|
299
|
-
skeleton: fromDaemon,
|
|
300
|
-
tokens: Math.ceil(fromDaemon.length / 4),
|
|
301
|
-
});
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
304
|
-
// 1. Try DB cache
|
|
305
|
-
if (db) {
|
|
306
|
-
const cached = yield (0, retriever_1.getStoredSkeleton)(db, absPath);
|
|
307
|
-
if (cached) {
|
|
308
|
-
skeletonResults.push({
|
|
309
|
-
file: filePath,
|
|
310
|
-
skeleton: cached,
|
|
311
|
-
tokens: Math.ceil(cached.length / 4), // Rough estimate
|
|
312
|
-
});
|
|
313
|
-
continue;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
// 2. Fallback to fresh generation
|
|
317
|
-
yield globalSkeletonizer.init();
|
|
318
|
-
if (!fs.existsSync(absPath)) {
|
|
319
|
-
skeletonResults.push({
|
|
320
|
-
file: filePath,
|
|
321
|
-
skeleton: `// File not found: ${filePath}`,
|
|
322
|
-
tokens: 0,
|
|
323
|
-
error: "File not found",
|
|
324
|
-
});
|
|
325
|
-
continue;
|
|
326
|
-
}
|
|
327
|
-
const content = fs.readFileSync(absPath, "utf-8");
|
|
328
|
-
const res = yield globalSkeletonizer.skeletonizeFile(absPath, content, skeletonOpts);
|
|
329
|
-
skeletonResults.push({
|
|
330
|
-
file: filePath,
|
|
331
|
-
skeleton: res.skeleton,
|
|
332
|
-
tokens: res.tokenEstimate,
|
|
333
|
-
error: res.error,
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
// Since search doesn't support --json explicitly yet, we just print text.
|
|
337
|
-
// But if we ever add it, we have the structure.
|
|
338
|
-
for (const res of skeletonResults) {
|
|
339
|
-
console.log(res.skeleton);
|
|
340
|
-
console.log(""); // Separator
|
|
341
|
-
}
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
function resultCountHeader(results, maxCount) {
|
|
345
|
-
var _a, _b, _c;
|
|
346
|
-
const files = new Set();
|
|
347
|
-
for (const r of results) {
|
|
348
|
-
const p = (_c = (_a = r.path) !== null && _a !== void 0 ? _a : (_b = r.metadata) === null || _b === void 0 ? void 0 : _b.path) !== null && _c !== void 0 ? _c : "";
|
|
349
|
-
if (p)
|
|
350
|
-
files.add(p);
|
|
351
|
-
}
|
|
352
|
-
const showing = results.length < maxCount ? `${results.length}` : `top ${results.length}`;
|
|
353
|
-
return `Found ${results.length} match${results.length === 1 ? "" : "es"} (showing ${showing}) across ${files.size} file${files.size === 1 ? "" : "s"}`;
|
|
354
|
-
}
|
|
59
|
+
const search_run_1 = require("./search-run");
|
|
60
|
+
const search_skeletons_1 = require("./search-skeletons");
|
|
355
61
|
exports.search = new commander_1.Command("search")
|
|
356
62
|
.description("Search code by meaning (default command)")
|
|
357
63
|
.option("-m <max_count>, --max-count <max_count>", "The maximum number of results to return (total)", "5")
|
|
@@ -397,7 +103,7 @@ Examples:
|
|
|
397
103
|
gmax "auth middleware" --projects api,gateway --plain
|
|
398
104
|
`)
|
|
399
105
|
.action((pattern, exec_path, _options, cmd) => __awaiter(void 0, void 0, void 0, function* () {
|
|
400
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m
|
|
106
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
401
107
|
const options = cmd.optsWithGlobals();
|
|
402
108
|
const root = process.cwd();
|
|
403
109
|
const minScore = Number.isFinite(Number.parseFloat(options.minScore))
|
|
@@ -465,7 +171,7 @@ Examples:
|
|
|
465
171
|
const searchResult = { data: body.results };
|
|
466
172
|
const filteredData = searchResult.data.filter((r) => typeof r.score !== "number" || r.score >= minScore);
|
|
467
173
|
if (options.skeleton) {
|
|
468
|
-
yield outputSkeletons(filteredData, projectRootForServer, parseInt(options.m, 10),
|
|
174
|
+
yield (0, search_skeletons_1.outputSkeletons)(filteredData, projectRootForServer, parseInt(options.m, 10),
|
|
469
175
|
// Server doesn't easily expose DB instance here in HTTP client mode,
|
|
470
176
|
// but we are in client. Wait, this text implies "Server Search" block.
|
|
471
177
|
// Client talks to server. The server returns JSON.
|
|
@@ -476,7 +182,7 @@ Examples:
|
|
|
476
182
|
return;
|
|
477
183
|
}
|
|
478
184
|
const compactHits = options.compact
|
|
479
|
-
? toCompactHits(filteredData)
|
|
185
|
+
? (0, compact_results_1.toCompactHits)(filteredData)
|
|
480
186
|
: [];
|
|
481
187
|
if (options.compact) {
|
|
482
188
|
if (!compactHits.length) {
|
|
@@ -485,7 +191,7 @@ Examples:
|
|
|
485
191
|
process.exitCode = 1;
|
|
486
192
|
}
|
|
487
193
|
else {
|
|
488
|
-
console.log(formatCompactTable(compactHits, projectRootForServer, pattern, {
|
|
194
|
+
console.log((0, compact_results_1.formatCompactTable)(compactHits, projectRootForServer, pattern, {
|
|
489
195
|
isTTY: !!process.stdout.isTTY,
|
|
490
196
|
plain: !!options.plain,
|
|
491
197
|
}));
|
|
@@ -511,6 +217,7 @@ Examples:
|
|
|
511
217
|
};
|
|
512
218
|
console.log((0, agent_search_formatter_1.formatAgentSearchResults)(filteredData, projectRootForServer, {
|
|
513
219
|
includeImports: options.imports,
|
|
220
|
+
query: pattern,
|
|
514
221
|
getImportsForFile,
|
|
515
222
|
explain: options.explain,
|
|
516
223
|
}));
|
|
@@ -520,11 +227,11 @@ Examples:
|
|
|
520
227
|
const shouldBePlain = options.plain || !isTTY;
|
|
521
228
|
_searchResultCount = filteredData.length;
|
|
522
229
|
if (!options.agent && !options.compact) {
|
|
523
|
-
console.log(resultCountHeader(filteredData, parseInt(options.m, 10)));
|
|
230
|
+
console.log((0, compact_results_1.resultCountHeader)(filteredData, parseInt(options.m, 10)));
|
|
524
231
|
console.log();
|
|
525
232
|
}
|
|
526
233
|
if (shouldBePlain) {
|
|
527
|
-
const mappedResults = toTextResults(filteredData);
|
|
234
|
+
const mappedResults = (0, compact_results_1.toTextResults)(filteredData);
|
|
528
235
|
const output = (0, formatter_1.formatTextResults)(mappedResults, pattern, projectRootForServer, {
|
|
529
236
|
isPlain: true,
|
|
530
237
|
compact: options.compact,
|
|
@@ -643,138 +350,25 @@ Examples:
|
|
|
643
350
|
const seedFiles = splitSeeds(options.seedFile);
|
|
644
351
|
const seedSymbols = splitSeeds(options.seedSymbol);
|
|
645
352
|
const seeds = seedFiles || seedSymbols ? { files: seedFiles, symbols: seedSymbols } : undefined;
|
|
646
|
-
//
|
|
647
|
-
//
|
|
648
|
-
//
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
: undefined,
|
|
666
|
-
pathPrefix: pathFilter,
|
|
667
|
-
rerank: process.env.GMAX_RERANK === "1",
|
|
668
|
-
explain: options.explain,
|
|
669
|
-
seeds,
|
|
670
|
-
includeSkeletons: options.skeleton,
|
|
671
|
-
includeGraph: options.symbol,
|
|
672
|
-
}, { timeoutMs: 60000 });
|
|
673
|
-
if (resp.ok) {
|
|
674
|
-
searchResult = {
|
|
675
|
-
data: resp.data,
|
|
676
|
-
warnings: resp.warnings,
|
|
677
|
-
};
|
|
678
|
-
precomputedSkeletons = resp.skeletons;
|
|
679
|
-
precomputedGraph = resp.graph;
|
|
680
|
-
indexState = resp.indexState;
|
|
681
|
-
}
|
|
682
|
-
else if (process.env.GMAX_DEBUG === "1") {
|
|
683
|
-
console.error(`[search] daemon path unavailable: ${(_e = resp.error) !== null && _e !== void 0 ? _e : "unknown"}`);
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
catch (err) {
|
|
688
|
-
if (process.env.GMAX_DEBUG === "1") {
|
|
689
|
-
console.error("[search] daemon attempt threw:", err);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
// In-process fallback: open VectorDB, ensure index, run Searcher.
|
|
694
|
-
// Only entered when the daemon path didn't produce results.
|
|
695
|
-
if (!searchResult) {
|
|
696
|
-
vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
|
|
697
|
-
// Check for active indexing lock and warn if present
|
|
698
|
-
const locked = (0, lock_1.isLocked)(paths.dataDir);
|
|
699
|
-
if (!options.agent && locked) {
|
|
700
|
-
console.warn("⚠️ Warning: Indexing in progress... search results may be incomplete.");
|
|
701
|
-
}
|
|
702
|
-
// No daemon here, so no precise pending count — surface the coarse
|
|
703
|
-
// signal (active lock or initial index not yet complete) so agent mode
|
|
704
|
-
// still gets a partial-index footer.
|
|
705
|
-
if (!indexState && (locked || project.status === "pending")) {
|
|
706
|
-
indexState = { indexing: true, pendingFiles: 0 };
|
|
707
|
-
}
|
|
708
|
-
const hasRows = yield vectorDb.hasAnyRows();
|
|
709
|
-
const needsSync = options.sync || !hasRows;
|
|
710
|
-
if (needsSync) {
|
|
711
|
-
const isTTY = process.stdout.isTTY;
|
|
712
|
-
let abortController;
|
|
713
|
-
let signal;
|
|
714
|
-
if (!isTTY) {
|
|
715
|
-
abortController = new AbortController();
|
|
716
|
-
signal = abortController.signal;
|
|
717
|
-
setTimeout(() => {
|
|
718
|
-
abortController === null || abortController === void 0 ? void 0 : abortController.abort();
|
|
719
|
-
}, 60000); // 60 seconds timeout for non-TTY auto-indexing
|
|
720
|
-
}
|
|
721
|
-
const { spinner, onProgress } = (0, sync_helpers_1.createIndexingSpinner)(projectRoot, options.sync ? "Indexing..." : "Indexing repository (first run)...");
|
|
722
|
-
try {
|
|
723
|
-
yield (0, grammar_loader_1.ensureGrammars)(console.log, { silent: true });
|
|
724
|
-
const result = yield (0, syncer_1.initialSync)({
|
|
725
|
-
projectRoot,
|
|
726
|
-
dryRun: options.dryRun,
|
|
727
|
-
onProgress,
|
|
728
|
-
signal,
|
|
729
|
-
});
|
|
730
|
-
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
731
|
-
spinner.warn(`Indexing timed out (${result.processed}/${result.total}). Results may be partial.`);
|
|
732
|
-
}
|
|
733
|
-
if (options.dryRun) {
|
|
734
|
-
spinner.succeed(`Dry run complete (${result.processed}/${result.total}) • would have indexed ${result.indexed}`);
|
|
735
|
-
console.log((0, sync_helpers_1.formatDryRunSummary)(result, {
|
|
736
|
-
actionDescription: "would have indexed",
|
|
737
|
-
includeTotal: true,
|
|
738
|
-
}));
|
|
739
|
-
return;
|
|
740
|
-
}
|
|
741
|
-
yield vectorDb.createFTSIndex();
|
|
742
|
-
// Update registry after sync
|
|
743
|
-
const { readGlobalConfig } = yield Promise.resolve().then(() => __importStar(require("../lib/index/index-config")));
|
|
744
|
-
const { registerProject } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/project-registry")));
|
|
745
|
-
const gc = readGlobalConfig();
|
|
746
|
-
registerProject({
|
|
747
|
-
root: projectRoot,
|
|
748
|
-
name: path.basename(projectRoot),
|
|
749
|
-
vectorDim: gc.vectorDim,
|
|
750
|
-
modelTier: gc.modelTier,
|
|
751
|
-
embedMode: gc.embedMode,
|
|
752
|
-
lastIndexed: new Date().toISOString(),
|
|
753
|
-
chunkCount: result.indexed,
|
|
754
|
-
status: "indexed",
|
|
755
|
-
});
|
|
756
|
-
const failedSuffix = result.failedFiles > 0 ? ` • ${result.failedFiles} failed` : "";
|
|
757
|
-
spinner.succeed(`${options.sync ? "Indexing" : "Initial indexing"} complete (${result.processed}/${result.total}) • indexed ${result.indexed}${failedSuffix}`);
|
|
758
|
-
}
|
|
759
|
-
catch (e) {
|
|
760
|
-
spinner.fail("Indexing failed");
|
|
761
|
-
throw e;
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
// Ensure a watcher is running for live reindexing
|
|
765
|
-
if (!process.env.VITEST && !((_f = process.env.NODE_ENV) === null || _f === void 0 ? void 0 : _f.includes("test"))) {
|
|
766
|
-
const { launchWatcher } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/watcher-launcher")));
|
|
767
|
-
const launched = yield launchWatcher(projectRoot);
|
|
768
|
-
if (!launched.ok && launched.reason === "spawn-failed") {
|
|
769
|
-
console.warn(`[search] ${launched.message}`);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
const searcher = new searcher_1.Searcher(vectorDb);
|
|
773
|
-
searchResult = yield searcher.search(pattern, parseInt(options.m, 10), { rerank: process.env.GMAX_RERANK === "1", explain: options.explain, seeds }, Object.keys(searchFilters).length > 0
|
|
774
|
-
? searchFilters
|
|
775
|
-
: undefined, pathFilter);
|
|
776
|
-
} // end if (!searchResult) — in-process fallback
|
|
777
|
-
if (!options.agent && ((_g = searchResult.warnings) === null || _g === void 0 ? void 0 : _g.length)) {
|
|
353
|
+
// Acquire results: daemon-mediated first, in-process fallback otherwise.
|
|
354
|
+
// The render stage below is shared across both. `runSearch` reports the
|
|
355
|
+
// VectorDB it opens via the callback so the `finally` can close it.
|
|
356
|
+
const acquired = yield (0, search_run_1.runSearch)({
|
|
357
|
+
pattern,
|
|
358
|
+
options,
|
|
359
|
+
projectRoot,
|
|
360
|
+
effectiveRoot,
|
|
361
|
+
paths,
|
|
362
|
+
projectStatus: project.status,
|
|
363
|
+
searchFilters,
|
|
364
|
+
pathFilter,
|
|
365
|
+
seeds,
|
|
366
|
+
});
|
|
367
|
+
vectorDb = acquired.vectorDb;
|
|
368
|
+
if (acquired.kind === "dry-run")
|
|
369
|
+
return;
|
|
370
|
+
const { searchResult, precomputedSkeletons, precomputedGraph, indexState } = acquired;
|
|
371
|
+
if (!options.agent && ((_e = searchResult.warnings) === null || _e === void 0 ? void 0 : _e.length)) {
|
|
778
372
|
for (const w of searchResult.warnings) {
|
|
779
373
|
console.warn(`Warning: ${w}`);
|
|
780
374
|
}
|
|
@@ -799,7 +393,7 @@ Examples:
|
|
|
799
393
|
return defs.some((d) => regex.test(d));
|
|
800
394
|
});
|
|
801
395
|
}
|
|
802
|
-
catch (
|
|
396
|
+
catch (_o) {
|
|
803
397
|
// Invalid regex — skip
|
|
804
398
|
}
|
|
805
399
|
}
|
|
@@ -851,18 +445,19 @@ Examples:
|
|
|
851
445
|
if (options.agent) {
|
|
852
446
|
body = (0, agent_search_formatter_1.formatAgentSearchResults)(g.items, g.root, {
|
|
853
447
|
includeImports: options.imports,
|
|
448
|
+
query: pattern,
|
|
854
449
|
getImportsForFile,
|
|
855
450
|
explain: options.explain,
|
|
856
451
|
});
|
|
857
452
|
}
|
|
858
453
|
else if (options.compact) {
|
|
859
|
-
body = formatCompactTable(toCompactHits(g.items), g.root, pattern, {
|
|
454
|
+
body = (0, compact_results_1.formatCompactTable)((0, compact_results_1.toCompactHits)(g.items), g.root, pattern, {
|
|
860
455
|
isTTY: !!isTTY,
|
|
861
456
|
plain: !!options.plain,
|
|
862
457
|
});
|
|
863
458
|
}
|
|
864
459
|
else if (shouldBePlain) {
|
|
865
|
-
body = (0, formatter_1.formatTextResults)(toTextResults(g.items), pattern, g.root, {
|
|
460
|
+
body = (0, formatter_1.formatTextResults)((0, compact_results_1.toTextResults)(g.items), pattern, g.root, {
|
|
866
461
|
isPlain: true,
|
|
867
462
|
compact: options.compact,
|
|
868
463
|
content: options.content,
|
|
@@ -894,6 +489,7 @@ Examples:
|
|
|
894
489
|
else {
|
|
895
490
|
console.log((0, agent_search_formatter_1.formatAgentSearchResults)(filteredData, effectiveRoot, {
|
|
896
491
|
includeImports: options.imports,
|
|
492
|
+
query: pattern,
|
|
897
493
|
getImportsForFile,
|
|
898
494
|
explain: options.explain,
|
|
899
495
|
}));
|
|
@@ -927,7 +523,7 @@ Examples:
|
|
|
927
523
|
}
|
|
928
524
|
}
|
|
929
525
|
}
|
|
930
|
-
catch (
|
|
526
|
+
catch (_p) { }
|
|
931
527
|
}
|
|
932
528
|
// Partial-index footer last, so it's the final line the agent reads —
|
|
933
529
|
// and emitted even on "(none)", where an empty result may just mean the
|
|
@@ -938,7 +534,7 @@ Examples:
|
|
|
938
534
|
return;
|
|
939
535
|
}
|
|
940
536
|
if (options.skeleton) {
|
|
941
|
-
yield outputSkeletons(filteredData, projectRoot, parseInt(options.m, 10), vectorDb, precomputedSkeletons);
|
|
537
|
+
yield (0, search_skeletons_1.outputSkeletons)(filteredData, projectRoot, parseInt(options.m, 10), vectorDb, precomputedSkeletons);
|
|
942
538
|
return;
|
|
943
539
|
}
|
|
944
540
|
if (!filteredData.length) {
|
|
@@ -948,8 +544,8 @@ Examples:
|
|
|
948
544
|
return;
|
|
949
545
|
}
|
|
950
546
|
if (options.compact) {
|
|
951
|
-
const compactHits = toCompactHits(filteredData);
|
|
952
|
-
console.log(formatCompactTable(compactHits, projectRoot, pattern, {
|
|
547
|
+
const compactHits = (0, compact_results_1.toCompactHits)(filteredData);
|
|
548
|
+
console.log((0, compact_results_1.formatCompactTable)(compactHits, projectRoot, pattern, {
|
|
953
549
|
isTTY: !!process.stdout.isTTY,
|
|
954
550
|
plain: !!options.plain,
|
|
955
551
|
}));
|
|
@@ -962,7 +558,7 @@ Examples:
|
|
|
962
558
|
const { extractImportsFromContent } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/import-extractor")));
|
|
963
559
|
const { packByBudget } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/budget-pack")));
|
|
964
560
|
const budget = parseInt(options.budget, 10) || 8000;
|
|
965
|
-
console.log(resultCountHeader(filteredData, parseInt(options.m, 10)));
|
|
561
|
+
console.log((0, compact_results_1.resultCountHeader)(filteredData, parseInt(options.m, 10)));
|
|
966
562
|
// Build every candidate blob up front (token cost needs the rendered
|
|
967
563
|
// text), then pack to budget. Token-aware packing skips an oversized
|
|
968
564
|
// chunk and keeps filling with smaller, still-relevant ones rather than
|
|
@@ -1018,14 +614,14 @@ Examples:
|
|
|
1018
614
|
const isTTY = process.stdout.isTTY;
|
|
1019
615
|
const shouldBePlain = options.plain || !isTTY;
|
|
1020
616
|
if (!options.agent && !options.compact) {
|
|
1021
|
-
console.log(resultCountHeader(filteredData, parseInt(options.m, 10)));
|
|
617
|
+
console.log((0, compact_results_1.resultCountHeader)(filteredData, parseInt(options.m, 10)));
|
|
1022
618
|
console.log();
|
|
1023
619
|
}
|
|
1024
620
|
// Print imports per unique file before results when --imports is used
|
|
1025
621
|
if (options.imports) {
|
|
1026
622
|
const seenFiles = new Set();
|
|
1027
623
|
for (const r of filteredData) {
|
|
1028
|
-
const absP = (
|
|
624
|
+
const absP = (_h = (_f = r.path) !== null && _f !== void 0 ? _f : (_g = r.metadata) === null || _g === void 0 ? void 0 : _g.path) !== null && _h !== void 0 ? _h : "";
|
|
1029
625
|
if (absP && !seenFiles.has(absP)) {
|
|
1030
626
|
seenFiles.add(absP);
|
|
1031
627
|
const imports = getImportsForFile(absP);
|
|
@@ -1039,7 +635,7 @@ Examples:
|
|
|
1039
635
|
}
|
|
1040
636
|
}
|
|
1041
637
|
if (shouldBePlain) {
|
|
1042
|
-
const mappedResults = toTextResults(filteredData);
|
|
638
|
+
const mappedResults = (0, compact_results_1.toTextResults)(filteredData);
|
|
1043
639
|
const output = (0, formatter_1.formatTextResults)(mappedResults, pattern, projectRoot, {
|
|
1044
640
|
isPlain: true,
|
|
1045
641
|
compact: options.compact,
|
|
@@ -1052,7 +648,7 @@ Examples:
|
|
|
1052
648
|
for (const r of filteredData) {
|
|
1053
649
|
const b = r.scoreBreakdown;
|
|
1054
650
|
if (b) {
|
|
1055
|
-
const absP = (
|
|
651
|
+
const absP = (_l = (_j = r.path) !== null && _j !== void 0 ? _j : (_k = r.metadata) === null || _k === void 0 ? void 0 : _k.path) !== null && _l !== void 0 ? _l : "";
|
|
1056
652
|
const relPath = absP.startsWith(projectRoot)
|
|
1057
653
|
? absP.slice(projectRoot.length + 1)
|
|
1058
654
|
: absP;
|
|
@@ -1114,7 +710,7 @@ Examples:
|
|
|
1114
710
|
console.log(lines.join("\n"));
|
|
1115
711
|
}
|
|
1116
712
|
}
|
|
1117
|
-
catch (
|
|
713
|
+
catch (_q) {
|
|
1118
714
|
// Trace failed — skip silently
|
|
1119
715
|
}
|
|
1120
716
|
}
|
|
@@ -1134,13 +730,13 @@ Examples:
|
|
|
1134
730
|
source: "cli",
|
|
1135
731
|
tool: "search",
|
|
1136
732
|
query: pattern,
|
|
1137
|
-
project: (
|
|
733
|
+
project: (_m = (0, project_root_1.findProjectRoot)(root)) !== null && _m !== void 0 ? _m : root,
|
|
1138
734
|
results: _searchResultCount,
|
|
1139
735
|
ms: Date.now() - _searchStartMs,
|
|
1140
736
|
error: _searchError,
|
|
1141
737
|
});
|
|
1142
738
|
}
|
|
1143
|
-
catch (
|
|
739
|
+
catch (_r) { }
|
|
1144
740
|
if (vectorDb) {
|
|
1145
741
|
try {
|
|
1146
742
|
yield vectorDb.close();
|