grepmax 0.17.3 → 0.17.4

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.
@@ -49,6 +49,7 @@ const commander_1 = require("commander");
49
49
  const grammar_loader_1 = require("../lib/index/grammar-loader");
50
50
  const sync_helpers_1 = require("../lib/index/sync-helpers");
51
51
  const syncer_1 = require("../lib/index/syncer");
52
+ const agent_search_formatter_1 = require("../lib/output/agent-search-formatter");
52
53
  const searcher_1 = require("../lib/search/searcher");
53
54
  const setup_helpers_1 = require("../lib/setup/setup-helpers");
54
55
  const skeleton_1 = require("../lib/skeleton");
@@ -346,9 +347,7 @@ function resultCountHeader(results, maxCount) {
346
347
  if (p)
347
348
  files.add(p);
348
349
  }
349
- const showing = results.length < maxCount
350
- ? `${results.length}`
351
- : `top ${results.length}`;
350
+ const showing = results.length < maxCount ? `${results.length}` : `top ${results.length}`;
352
351
  return `Found ${results.length} match${results.length === 1 ? "" : "es"} (showing ${showing}) across ${files.size} file${files.size === 1 ? "" : "s"}`;
353
352
  }
354
353
  exports.search = new commander_1.Command("search")
@@ -368,8 +367,8 @@ exports.search = new commander_1.Command("search")
368
367
  .option("--skeleton", "Show code skeleton for matching files instead of snippets", false)
369
368
  .option("--root <dir>", "Search a different project directory")
370
369
  .option("--file <name>", "Filter to files matching this name (e.g. 'syncer.ts')")
371
- .option("--in <subpath>", "Restrict to a sub-path of the project (repeatable; comma-separated also accepted)", (value, prev) => (prev ? [...prev, value] : [value]))
372
- .option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable; e.g. 'tests/')", (value, prev) => (prev ? [...prev, value] : [value]))
370
+ .option("--in <subpath>", "Restrict to a sub-path of the project (repeatable; comma-separated also accepted)", (value, prev) => prev ? [...prev, value] : [value])
371
+ .option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable; e.g. 'tests/')", (value, prev) => prev ? [...prev, value] : [value])
373
372
  .option("--lang <ext>", "Filter by file extension (e.g. 'ts', 'py')")
374
373
  .option("--role <role>", "Filter by role: ORCHESTRATION, DEFINITION, IMPLEMENTATION")
375
374
  .option("--symbol", "Append call graph after search results", false)
@@ -377,7 +376,7 @@ exports.search = new commander_1.Command("search")
377
376
  .option("--name <regex>", "Filter results by symbol name regex")
378
377
  .option("-C, --context <n>", "Include N lines before/after each result")
379
378
  .option("--agent", "Ultra-compact output for AI agents (one line per result)", false)
380
- .argument("<pattern>", "Natural language query (e.g. \"where do we handle auth?\")")
379
+ .argument("<pattern>", 'Natural language query (e.g. "where do we handle auth?")')
381
380
  .argument("[path]", "Restrict search to this path prefix")
382
381
  .addHelpText("after", `
383
382
  Examples:
@@ -389,7 +388,7 @@ Examples:
389
388
  gmax "handler" --name "handle.*" --exclude tests/
390
389
  `)
391
390
  .action((pattern, exec_path, _options, cmd) => __awaiter(void 0, void 0, void 0, function* () {
392
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9;
391
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
393
392
  const options = cmd.optsWithGlobals();
394
393
  const root = process.cwd();
395
394
  const minScore = Number.isFinite(Number.parseFloat(options.minScore))
@@ -454,6 +453,24 @@ Examples:
454
453
  process.exitCode = 1;
455
454
  return; // EXIT
456
455
  }
456
+ if (options.agent) {
457
+ const importCache = new Map();
458
+ const getImportsForFile = (absPath) => {
459
+ var _a;
460
+ if (!options.imports || !absPath)
461
+ return "";
462
+ if (!importCache.has(absPath)) {
463
+ importCache.set(absPath, (0, import_extractor_1.extractImports)(absPath));
464
+ }
465
+ return (_a = importCache.get(absPath)) !== null && _a !== void 0 ? _a : "";
466
+ };
467
+ console.log((0, agent_search_formatter_1.formatAgentSearchResults)(filteredData, projectRootForServer, {
468
+ includeImports: options.imports,
469
+ getImportsForFile,
470
+ explain: options.explain,
471
+ }));
472
+ return; // EXIT
473
+ }
457
474
  const isTTY = process.stdout.isTTY;
458
475
  const shouldBePlain = options.plain || !isTTY;
459
476
  _searchResultCount = filteredData.length;
@@ -689,7 +706,7 @@ Examples:
689
706
  return defs.some((d) => regex.test(d));
690
707
  });
691
708
  }
692
- catch (_10) {
709
+ catch (_0) {
693
710
  // Invalid regex — skip
694
711
  }
695
712
  }
@@ -712,90 +729,11 @@ Examples:
712
729
  process.exitCode = 1;
713
730
  }
714
731
  else {
715
- // Pre-pass: group by absolute path in first-occurrence order so we
716
- // can collapse same-file repeats under a one-line header. Score
717
- // order is preserved globally for first-of-file; siblings cluster
718
- // under their first hit's rank.
719
- const groups = new Map();
720
- for (const r of filteredData) {
721
- const absP = (_j = (_g = r.path) !== null && _g !== void 0 ? _g : (_h = r.metadata) === null || _h === void 0 ? void 0 : _h.path) !== null && _j !== void 0 ? _j : "";
722
- const arr = groups.get(absP);
723
- if (arr) {
724
- arr.push(r);
725
- }
726
- else {
727
- groups.set(absP, [r]);
728
- }
729
- }
730
- const seenImportFiles = new Set();
731
- for (const [absP, members] of groups) {
732
- const relPath = absP.startsWith(effectiveRoot)
733
- ? absP.slice(effectiveRoot.length + 1)
734
- : absP;
735
- if (options.imports && absP && !seenImportFiles.has(absP)) {
736
- seenImportFiles.add(absP);
737
- const imports = getImportsForFile(absP);
738
- if (imports) {
739
- console.log(`[imports ${relPath}] ${imports.split("\n").join(" | ")}`);
740
- }
741
- }
742
- const grouped = members.length > 1;
743
- if (grouped) {
744
- console.log(`${relPath} (${members.length} hits):`);
745
- }
746
- for (const r of members) {
747
- const startLine = Math.max(1, ((_o = (_l = (_k = r.startLine) !== null && _k !== void 0 ? _k : r.start_line) !== null && _l !== void 0 ? _l : (_m = r.generated_metadata) === null || _m === void 0 ? void 0 : _m.start_line) !== null && _o !== void 0 ? _o : 0) + 1);
748
- const defs = Array.isArray(r.defined_symbols)
749
- ? r.defined_symbols
750
- : [];
751
- const symbol = defs[0] || "";
752
- const role = ((_p = r.role) !== null && _p !== void 0 ? _p : "")
753
- .slice(0, 4)
754
- .toUpperCase();
755
- let hint = "";
756
- if (r.summary) {
757
- hint = ` — ${r.summary}`;
758
- }
759
- else {
760
- // Extract first meaningful signature line from content
761
- const raw = (_r = (_q = r.content) !== null && _q !== void 0 ? _q : r.text) !== null && _r !== void 0 ? _r : "";
762
- const lines = raw.split("\n");
763
- for (const line of lines) {
764
- const trimmed = line.trim();
765
- // Skip empty, comments, imports, braces, and mid-line fragments
766
- if (!trimmed || trimmed.length < 5)
767
- continue;
768
- if (trimmed.startsWith("//") || trimmed.startsWith("/*") || trimmed.startsWith("*"))
769
- continue;
770
- if (trimmed.startsWith("import ") || trimmed.startsWith("#") || trimmed.startsWith("File:"))
771
- continue;
772
- if (trimmed === "{" || trimmed === "}")
773
- continue;
774
- // Skip lines that look like continuations (start with punctuation, closing braces, or spread)
775
- if (/^[.),;:}\]|&(+`'"!~]/.test(trimmed))
776
- continue;
777
- if (trimmed.startsWith("} ") || trimmed.startsWith("- ") || trimmed.startsWith("..."))
778
- continue;
779
- // Skip lines that look like mid-expression fragments (no keyword/declaration prefix)
780
- if (/^[a-z]/.test(trimmed) && !/^(export|function|class|interface|type|const|let|var|async|return|if|for|while|switch|enum|struct|pub |fn |def |impl |mod |use )/.test(trimmed))
781
- continue;
782
- hint = ` — ${trimmed.length > 120 ? trimmed.slice(0, 117) + "..." : trimmed}`;
783
- break;
784
- }
785
- }
786
- const sym = symbol ? ` ${symbol}` : "";
787
- const rl = role ? ` [${role}]` : "";
788
- const score = r.score;
789
- const scoreCol = typeof score === "number" ? `\ts=${score.toFixed(3)}` : "";
790
- const explainSuffix = options.explain && r.scoreBreakdown
791
- ? `\texplain:rerank=${r.scoreBreakdown.rerank.toFixed(3)},fused=${r.scoreBreakdown.fused.toFixed(3)},boost=${r.scoreBreakdown.boost.toFixed(2)}x,score=${r.scoreBreakdown.normalized.toFixed(3)}`
792
- : "";
793
- const locator = grouped
794
- ? ` :${startLine}`
795
- : `${relPath}:${startLine}`;
796
- console.log(`${locator}${scoreCol}${sym}${rl}${hint}${explainSuffix}`);
797
- }
798
- }
732
+ console.log((0, agent_search_formatter_1.formatAgentSearchResults)(filteredData, effectiveRoot, {
733
+ includeImports: options.imports,
734
+ getImportsForFile,
735
+ explain: options.explain,
736
+ }));
799
737
  }
800
738
  // Agent trace (compact)
801
739
  if (options.symbol && filteredData.length > 0) {
@@ -826,7 +764,7 @@ Examples:
826
764
  }
827
765
  }
828
766
  }
829
- catch (_11) { }
767
+ catch (_1) { }
830
768
  }
831
769
  return;
832
770
  }
@@ -858,9 +796,9 @@ Examples:
858
796
  let shown = 0;
859
797
  console.log(resultCountHeader(filteredData, parseInt(options.m, 10)));
860
798
  for (const r of filteredData) {
861
- const absP = (_u = (_s = r.path) !== null && _s !== void 0 ? _s : (_t = r.metadata) === null || _t === void 0 ? void 0 : _t.path) !== null && _u !== void 0 ? _u : "";
862
- const startLine = (_y = (_w = (_v = r.startLine) !== null && _v !== void 0 ? _v : r.start_line) !== null && _w !== void 0 ? _w : (_x = r.generated_metadata) === null || _x === void 0 ? void 0 : _x.start_line) !== null && _y !== void 0 ? _y : 0;
863
- const endLine = (_2 = (_0 = (_z = r.endLine) !== null && _z !== void 0 ? _z : r.end_line) !== null && _0 !== void 0 ? _0 : (_1 = r.generated_metadata) === null || _1 === void 0 ? void 0 : _1.end_line) !== null && _2 !== void 0 ? _2 : startLine;
799
+ const absP = (_j = (_g = r.path) !== null && _g !== void 0 ? _g : (_h = r.metadata) === null || _h === void 0 ? void 0 : _h.path) !== null && _j !== void 0 ? _j : "";
800
+ const startLine = (_o = (_l = (_k = r.startLine) !== null && _k !== void 0 ? _k : r.start_line) !== null && _l !== void 0 ? _l : (_m = r.generated_metadata) === null || _m === void 0 ? void 0 : _m.start_line) !== null && _o !== void 0 ? _o : 0;
801
+ const endLine = (_s = (_q = (_p = r.endLine) !== null && _p !== void 0 ? _p : r.end_line) !== null && _q !== void 0 ? _q : (_r = r.generated_metadata) === null || _r === void 0 ? void 0 : _r.end_line) !== null && _s !== void 0 ? _s : startLine;
864
802
  const relPath = absP.startsWith(projectRoot)
865
803
  ? absP.slice(projectRoot.length + 1)
866
804
  : absP;
@@ -893,7 +831,7 @@ Examples:
893
831
  tokensUsed += blobTokens;
894
832
  shown++;
895
833
  }
896
- catch (_12) {
834
+ catch (_2) {
897
835
  console.log(`\n--- ${relPath} (file not readable) ---`);
898
836
  shown++;
899
837
  }
@@ -910,7 +848,7 @@ Examples:
910
848
  if (options.imports) {
911
849
  const seenFiles = new Set();
912
850
  for (const r of filteredData) {
913
- const absP = (_5 = (_3 = r.path) !== null && _3 !== void 0 ? _3 : (_4 = r.metadata) === null || _4 === void 0 ? void 0 : _4.path) !== null && _5 !== void 0 ? _5 : "";
851
+ const absP = (_v = (_t = r.path) !== null && _t !== void 0 ? _t : (_u = r.metadata) === null || _u === void 0 ? void 0 : _u.path) !== null && _v !== void 0 ? _v : "";
914
852
  if (absP && !seenFiles.has(absP)) {
915
853
  seenFiles.add(absP);
916
854
  const imports = getImportsForFile(absP);
@@ -937,7 +875,7 @@ Examples:
937
875
  for (const r of filteredData) {
938
876
  const b = r.scoreBreakdown;
939
877
  if (b) {
940
- const absP = (_8 = (_6 = r.path) !== null && _6 !== void 0 ? _6 : (_7 = r.metadata) === null || _7 === void 0 ? void 0 : _7.path) !== null && _8 !== void 0 ? _8 : "";
878
+ const absP = (_y = (_w = r.path) !== null && _w !== void 0 ? _w : (_x = r.metadata) === null || _x === void 0 ? void 0 : _x.path) !== null && _y !== void 0 ? _y : "";
941
879
  const relPath = absP.startsWith(projectRoot)
942
880
  ? absP.slice(projectRoot.length + 1)
943
881
  : absP;
@@ -999,7 +937,7 @@ Examples:
999
937
  console.log(lines.join("\n"));
1000
938
  }
1001
939
  }
1002
- catch (_13) {
940
+ catch (_3) {
1003
941
  // Trace failed — skip silently
1004
942
  }
1005
943
  }
@@ -1019,13 +957,13 @@ Examples:
1019
957
  source: "cli",
1020
958
  tool: "search",
1021
959
  query: pattern,
1022
- project: (_9 = (0, project_root_1.findProjectRoot)(root)) !== null && _9 !== void 0 ? _9 : root,
960
+ project: (_z = (0, project_root_1.findProjectRoot)(root)) !== null && _z !== void 0 ? _z : root,
1023
961
  results: _searchResultCount,
1024
962
  ms: Date.now() - _searchStartMs,
1025
963
  error: _searchError,
1026
964
  });
1027
965
  }
1028
- catch (_14) { }
966
+ catch (_4) { }
1029
967
  if (vectorDb) {
1030
968
  try {
1031
969
  yield vectorDb.close();
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.formatAgentSearchResults = formatAgentSearchResults;
37
+ const path = __importStar(require("node:path"));
38
+ function chunkPath(chunk) {
39
+ const metadata = chunk.metadata;
40
+ return String(chunk.path || (metadata === null || metadata === void 0 ? void 0 : metadata.path) || "");
41
+ }
42
+ function chunkStartLine(chunk) {
43
+ var _a, _b, _c, _d;
44
+ return Math.max(1, Number((_d = (_b = (_a = chunk.startLine) !== null && _a !== void 0 ? _a : chunk.start_line) !== null && _b !== void 0 ? _b : (_c = chunk.generated_metadata) === null || _c === void 0 ? void 0 : _c.start_line) !== null && _d !== void 0 ? _d : 0) + 1);
45
+ }
46
+ function definedSymbols(chunk) {
47
+ var _a;
48
+ const raw = (_a = chunk.defined_symbols) !== null && _a !== void 0 ? _a : chunk.definedSymbols;
49
+ if (Array.isArray(raw))
50
+ return raw.filter((v) => typeof v === "string");
51
+ if (raw && typeof raw.toArray === "function") {
52
+ try {
53
+ const arr = raw.toArray();
54
+ if (Array.isArray(arr)) {
55
+ return arr.filter((v) => typeof v === "string");
56
+ }
57
+ }
58
+ catch (_b) { }
59
+ }
60
+ return [];
61
+ }
62
+ function relativePath(projectRoot, absPath) {
63
+ if (!absPath)
64
+ return "";
65
+ return path.isAbsolute(absPath)
66
+ ? path.relative(projectRoot, absPath)
67
+ : absPath;
68
+ }
69
+ function firstSignatureLine(chunk) {
70
+ var _a, _b;
71
+ const raw = (_b = (_a = chunk.content) !== null && _a !== void 0 ? _a : chunk.text) !== null && _b !== void 0 ? _b : "";
72
+ const lines = String(raw).split("\n");
73
+ for (const line of lines) {
74
+ const trimmed = line.trim();
75
+ if (!trimmed || trimmed.length < 5)
76
+ continue;
77
+ if (trimmed.startsWith("//") ||
78
+ trimmed.startsWith("/*") ||
79
+ trimmed.startsWith("*")) {
80
+ continue;
81
+ }
82
+ if (trimmed.startsWith("import ") ||
83
+ trimmed.startsWith("#") ||
84
+ trimmed.startsWith("File:")) {
85
+ continue;
86
+ }
87
+ if (trimmed === "{" || trimmed === "}")
88
+ continue;
89
+ if (/^[.),;:}\]|&(+`'"!~]/.test(trimmed))
90
+ continue;
91
+ if (trimmed.startsWith("} ") ||
92
+ trimmed.startsWith("- ") ||
93
+ trimmed.startsWith("...")) {
94
+ continue;
95
+ }
96
+ if (/^[a-z]/.test(trimmed) &&
97
+ !/^(export|function|class|interface|type|const|let|var|async|return|if|for|while|switch|enum|struct|pub |fn |def |impl |mod |use )/.test(trimmed)) {
98
+ continue;
99
+ }
100
+ return trimmed.length > 120 ? `${trimmed.slice(0, 117)}...` : trimmed;
101
+ }
102
+ return "";
103
+ }
104
+ function hintFor(chunk) {
105
+ if (typeof chunk.summary === "string" && chunk.summary) {
106
+ return chunk.summary;
107
+ }
108
+ return firstSignatureLine(chunk);
109
+ }
110
+ function explainSuffix(chunk, enabled) {
111
+ if (!enabled || !chunk.scoreBreakdown)
112
+ return "";
113
+ const b = chunk.scoreBreakdown;
114
+ return `\texplain:rerank=${b.rerank.toFixed(3)},fused=${b.fused.toFixed(3)},boost=${b.boost.toFixed(2)}x,score=${b.normalized.toFixed(3)}`;
115
+ }
116
+ function formatAgentSearchResults(results, projectRoot, options = {}) {
117
+ var _a, _b;
118
+ if (!results.length)
119
+ return "(none)";
120
+ const groups = new Map();
121
+ for (const result of results) {
122
+ const absPath = chunkPath(result);
123
+ const group = groups.get(absPath);
124
+ if (group)
125
+ group.push(result);
126
+ else
127
+ groups.set(absPath, [result]);
128
+ }
129
+ const lines = [];
130
+ const seenImportFiles = new Set();
131
+ for (const [absPath, members] of groups) {
132
+ const rel = relativePath(projectRoot, absPath);
133
+ if (options.includeImports &&
134
+ absPath &&
135
+ options.getImportsForFile &&
136
+ !seenImportFiles.has(absPath)) {
137
+ seenImportFiles.add(absPath);
138
+ const imports = options.getImportsForFile(absPath);
139
+ if (imports) {
140
+ lines.push(`[imports ${rel}] ${imports.split("\n").join(" | ")}`);
141
+ }
142
+ }
143
+ const grouped = members.length > 1;
144
+ if (grouped) {
145
+ lines.push(`${rel} (${members.length} hits):`);
146
+ }
147
+ for (const result of members) {
148
+ const symbol = (_a = definedSymbols(result)[0]) !== null && _a !== void 0 ? _a : "";
149
+ const role = String((_b = result.role) !== null && _b !== void 0 ? _b : "")
150
+ .slice(0, 4)
151
+ .toUpperCase();
152
+ const score = typeof result.score === "number"
153
+ ? `\ts=${result.score.toFixed(3)}`
154
+ : "";
155
+ const hint = hintFor(result);
156
+ const locator = grouped
157
+ ? ` :${chunkStartLine(result)}`
158
+ : `${rel}:${chunkStartLine(result)}`;
159
+ lines.push(`${locator}${score}${symbol ? ` ${symbol}` : ""}${role ? ` [${role}]` : ""}${hint ? ` — ${hint}` : ""}${explainSuffix(result, options.explain)}`);
160
+ }
161
+ }
162
+ return lines.join("\n");
163
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.17.3",
3
+ "version": "0.17.4",
4
4
  "author": "Robert Owens <78518764+reowens@users.noreply.github.com>",
5
5
  "homepage": "https://github.com/reowens/grepmax",
6
6
  "bugs": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.17.3",
3
+ "version": "0.17.4",
4
4
  "description": "Semantic code search for Claude Code. Automatically indexes your project and provides intelligent search capabilities.",
5
5
  "author": {
6
6
  "name": "Robert Owens",