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.
@@ -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
- function toTextResults(data) {
68
- return data.map((r) => {
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, _o, _p;
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
- // Daemon-mediated search: ships query+args over IPC, daemon runs the
647
- // hybrid+rerank against its already-warm VectorDB and worker pool.
648
- // Drops cold-start cost (~17s wall, 6GB RAM in the CLI) to <1s. Falls
649
- // back to in-process on any failure.
650
- let searchResult = null;
651
- let precomputedSkeletons;
652
- let precomputedGraph;
653
- let indexState;
654
- if (!options.sync && !options.dryRun) {
655
- try {
656
- const { isDaemonRunning, sendDaemonCommand } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/daemon-client")));
657
- if (yield isDaemonRunning()) {
658
- const resp = yield sendDaemonCommand({
659
- cmd: "search",
660
- projectRoot: effectiveRoot,
661
- query: pattern,
662
- limit: parseInt(options.m, 10),
663
- filters: Object.keys(searchFilters).length > 0
664
- ? searchFilters
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 (_q) {
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 (_r) { }
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 = (_k = (_h = r.path) !== null && _h !== void 0 ? _h : (_j = r.metadata) === null || _j === void 0 ? void 0 : _j.path) !== null && _k !== void 0 ? _k : "";
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 = (_o = (_l = r.path) !== null && _l !== void 0 ? _l : (_m = r.metadata) === null || _m === void 0 ? void 0 : _m.path) !== null && _o !== void 0 ? _o : "";
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 (_s) {
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: (_p = (0, project_root_1.findProjectRoot)(root)) !== null && _p !== void 0 ? _p : root,
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 (_t) { }
739
+ catch (_r) { }
1144
740
  if (vectorDb) {
1145
741
  try {
1146
742
  yield vectorDb.close();