grepmax 0.26.48 → 0.26.50
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 +1 -1
- package/README.md +77 -40
- package/dist/commands/search-output.js +22 -9
- package/dist/commands/search-run.js +6 -2
- package/dist/commands/search.js +10 -1
- package/dist/commands/serve.js +14 -8
- package/dist/eval-oss.js +2 -1
- package/dist/eval-relevance.js +337 -0
- package/dist/eval.js +4 -3
- package/dist/lib/daemon/ipc-handler.js +12 -0
- package/dist/lib/daemon/search-handler.js +14 -2
- package/dist/lib/eval/relevance-baseline.js +174 -0
- package/dist/lib/search/diagnostics.js +95 -0
- package/dist/lib/search/per-file.js +24 -0
- package/dist/lib/search/searcher.js +72 -13
- package/dist/lib/utils/daemon-search.js +34 -0
- package/package.json +3 -2
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SearchDiagnosticCollector = void 0;
|
|
4
|
+
const stages = [
|
|
5
|
+
"vector",
|
|
6
|
+
"fts",
|
|
7
|
+
"rrf",
|
|
8
|
+
"fusion",
|
|
9
|
+
"stage1",
|
|
10
|
+
"pooled",
|
|
11
|
+
"rerank",
|
|
12
|
+
"scored",
|
|
13
|
+
"dedup",
|
|
14
|
+
"final",
|
|
15
|
+
];
|
|
16
|
+
const rankingKeys = [
|
|
17
|
+
"GMAX_PRE_K",
|
|
18
|
+
"GMAX_STAGE1_K",
|
|
19
|
+
"GMAX_STAGE2_K",
|
|
20
|
+
"GMAX_RERANK_TOP",
|
|
21
|
+
"GMAX_RERANK_BLEND",
|
|
22
|
+
"GMAX_MAX_PER_FILE",
|
|
23
|
+
"GMAX_DEF_BOOST",
|
|
24
|
+
"GMAX_CONCENTRATION_THRESHOLD",
|
|
25
|
+
"GMAX_ANCHOR_PENALTY",
|
|
26
|
+
"GMAX_TEST_PENALTY",
|
|
27
|
+
"GMAX_DOC_PENALTY",
|
|
28
|
+
"GMAX_PAGERANK",
|
|
29
|
+
"GMAX_PR_WEIGHT",
|
|
30
|
+
"GMAX_SEED_FILE_W",
|
|
31
|
+
"GMAX_SEED_SYMBOL_DEF_W",
|
|
32
|
+
"GMAX_SEED_SYMBOL_REF_W",
|
|
33
|
+
"GMAX_SEED_MAX_RANK",
|
|
34
|
+
"GMAX_ANN",
|
|
35
|
+
"GMAX_ANN_NPROBES",
|
|
36
|
+
"GMAX_ANN_MAX_NPROBES",
|
|
37
|
+
];
|
|
38
|
+
const key = (r) => r.id || `${r.path}:${r.chunk_index}`;
|
|
39
|
+
/** Request-local pointer trace. No content, vectors or additional database reads. */
|
|
40
|
+
class SearchDiagnosticCollector {
|
|
41
|
+
constructor() {
|
|
42
|
+
this.ranks = new Map();
|
|
43
|
+
this.cohort = [];
|
|
44
|
+
this.total = 0;
|
|
45
|
+
this.fileLimited = new Set();
|
|
46
|
+
}
|
|
47
|
+
noteFileLimit(record) {
|
|
48
|
+
this.fileLimited.add(key(record));
|
|
49
|
+
}
|
|
50
|
+
outcome(record) {
|
|
51
|
+
var _a, _b, _c, _d, _e, _f;
|
|
52
|
+
const id = key(record);
|
|
53
|
+
if ((_a = this.ranks.get("final")) === null || _a === void 0 ? void 0 : _a.has(id))
|
|
54
|
+
return "returned";
|
|
55
|
+
if (!((_b = this.ranks.get("stage1")) === null || _b === void 0 ? void 0 : _b.has(id)))
|
|
56
|
+
return "stage1-cut";
|
|
57
|
+
if (!((_c = this.ranks.get("pooled")) === null || _c === void 0 ? void 0 : _c.has(id)) &&
|
|
58
|
+
!((_d = this.ranks.get("scored")) === null || _d === void 0 ? void 0 : _d.has(id)))
|
|
59
|
+
return "pooled-cut";
|
|
60
|
+
if (!((_e = this.ranks.get("scored")) === null || _e === void 0 ? void 0 : _e.has(id)))
|
|
61
|
+
return "not-scored";
|
|
62
|
+
if (!((_f = this.ranks.get("dedup")) === null || _f === void 0 ? void 0 : _f.has(id)))
|
|
63
|
+
return "deduplicated";
|
|
64
|
+
if (this.fileLimited.has(id))
|
|
65
|
+
return "per-file-limit";
|
|
66
|
+
// After the display window fills, remaining candidates are unexamined.
|
|
67
|
+
return "display-limit";
|
|
68
|
+
}
|
|
69
|
+
capture(stage, records) {
|
|
70
|
+
this.ranks.set(stage, new Map(records.map((r, i) => [key(r), i + 1])));
|
|
71
|
+
if (stage === "fusion") {
|
|
72
|
+
this.total = records.length;
|
|
73
|
+
this.cohort = records.slice(0, 200);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
finish(details) {
|
|
77
|
+
return Object.assign(Object.assign({ schemaVersion: 1 }, details), { rankingEnvironment: Object.fromEntries(rankingKeys.map((name) => { var _a; return [name, (_a = process.env[name]) !== null && _a !== void 0 ? _a : null]; })), stages: Object.fromEntries(stages.map((s) => { var _a; var _b; return [s, (_b = (_a = this.ranks.get(s)) === null || _a === void 0 ? void 0 : _a.size) !== null && _b !== void 0 ? _b : 0]; })), trace: {
|
|
78
|
+
cohort: "post-seed-fusion-head",
|
|
79
|
+
limit: 200,
|
|
80
|
+
total: this.total,
|
|
81
|
+
truncated: this.total > this.cohort.length,
|
|
82
|
+
candidates: this.cohort.map((r) => { var _a; return ({
|
|
83
|
+
id: key(r),
|
|
84
|
+
path: r.path,
|
|
85
|
+
hash: r.hash,
|
|
86
|
+
startLine: r.start_line + 1,
|
|
87
|
+
endLine: r.end_line + 1,
|
|
88
|
+
parentSymbol: (_a = r.parent_symbol) !== null && _a !== void 0 ? _a : "",
|
|
89
|
+
outcome: this.outcome(r),
|
|
90
|
+
ranks: Object.fromEntries(stages.map((s) => { var _a; var _b; return [s, (_b = (_a = this.ranks.get(s)) === null || _a === void 0 ? void 0 : _a.get(key(r))) !== null && _b !== void 0 ? _b : 0]; })),
|
|
91
|
+
}); }),
|
|
92
|
+
} });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.SearchDiagnosticCollector = SearchDiagnosticCollector;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateMaxPerFile = validateMaxPerFile;
|
|
4
|
+
exports.parseCliPerFile = parseCliPerFile;
|
|
5
|
+
/** Omitted requests retain the daemon's configured default. */
|
|
6
|
+
function validateMaxPerFile(value) {
|
|
7
|
+
if (value === undefined)
|
|
8
|
+
return undefined;
|
|
9
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1)
|
|
10
|
+
throw new Error("maxPerFile must be a positive safe integer");
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
function parseCliPerFile(value) {
|
|
14
|
+
if (value === undefined)
|
|
15
|
+
return undefined;
|
|
16
|
+
if (!/^\d+$/.test(value))
|
|
17
|
+
throw new Error("--per-file must be a positive safe integer");
|
|
18
|
+
try {
|
|
19
|
+
return validateMaxPerFile(Number(value));
|
|
20
|
+
}
|
|
21
|
+
catch (_a) {
|
|
22
|
+
throw new Error("--per-file must be a positive safe integer");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -18,8 +18,10 @@ const filter_builder_1 = require("../utils/filter-builder");
|
|
|
18
18
|
const logger_1 = require("../utils/logger");
|
|
19
19
|
const query_timeout_1 = require("../utils/query-timeout");
|
|
20
20
|
const pool_1 = require("../workers/pool");
|
|
21
|
+
const diagnostics_1 = require("./diagnostics");
|
|
21
22
|
const intent_1 = require("./intent");
|
|
22
23
|
const pagerank_1 = require("./pagerank");
|
|
24
|
+
const per_file_1 = require("./per-file");
|
|
23
25
|
const seed_weight_1 = require("./seed-weight");
|
|
24
26
|
// Reads a defined_symbols / referenced_symbols column that may arrive as a plain
|
|
25
27
|
// array or a LanceDB Arrow proxy (.toArray()).
|
|
@@ -396,6 +398,7 @@ class Searcher {
|
|
|
396
398
|
search(query, top_k, _search_options, _filters, pathPrefix, intent, signal) {
|
|
397
399
|
return __awaiter(this, void 0, void 0, function* () {
|
|
398
400
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
401
|
+
const requestedMaxPerFile = (0, per_file_1.validateMaxPerFile)(_search_options === null || _search_options === void 0 ? void 0 : _search_options.maxPerFile);
|
|
399
402
|
const finalLimit = top_k !== null && top_k !== void 0 ? top_k : 10;
|
|
400
403
|
// ColBERT rerank is opt-in as of v0.17.1. On the 97-case eval it
|
|
401
404
|
// regresses MRR@10 by ~3% and doubles query latency; sweep across
|
|
@@ -403,6 +406,14 @@ class Searcher {
|
|
|
403
406
|
// fused scores ~30:1 so blend tuning can't recover the loss.
|
|
404
407
|
let doRerank = (_a = _search_options === null || _search_options === void 0 ? void 0 : _search_options.rerank) !== null && _a !== void 0 ? _a : false;
|
|
405
408
|
const explain = (_b = _search_options === null || _search_options === void 0 ? void 0 : _search_options.explain) !== null && _b !== void 0 ? _b : false;
|
|
409
|
+
const diagnostics = (_search_options === null || _search_options === void 0 ? void 0 : _search_options.diagnostics)
|
|
410
|
+
? new diagnostics_1.SearchDiagnosticCollector()
|
|
411
|
+
: undefined;
|
|
412
|
+
const requestedRerank = doRerank;
|
|
413
|
+
let gateEvaluated = false;
|
|
414
|
+
let gateShare = null;
|
|
415
|
+
let gateActivated = false;
|
|
416
|
+
let rerankInvoked = false;
|
|
406
417
|
// Aider-style seeding (Phase 4): bias candidate generation toward the
|
|
407
418
|
// agent's working context. Inert unless the caller supplied seed files or
|
|
408
419
|
// symbols, so the default search path is unchanged.
|
|
@@ -569,6 +580,9 @@ class Searcher {
|
|
|
569
580
|
.sort((a, b) => b[1] - a[1])
|
|
570
581
|
.map(([key]) => docMap.get(key))
|
|
571
582
|
.filter(Boolean);
|
|
583
|
+
diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.capture("vector", vectorResults);
|
|
584
|
+
diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.capture("fts", ftsResults);
|
|
585
|
+
diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.capture("rrf", fused);
|
|
572
586
|
// Free raw search results — docMap holds the only needed references
|
|
573
587
|
vectorResults.length = 0;
|
|
574
588
|
ftsResults.length = 0;
|
|
@@ -618,16 +632,16 @@ class Searcher {
|
|
|
618
632
|
// pools (express, platform) it regresses. So detect the concentrated regime
|
|
619
633
|
// here and *add* rerank-on for it. This only ever flips doRerank false→true:
|
|
620
634
|
// an explicit GMAX_RERANK=1 (doRerank already true) is never overridden off.
|
|
635
|
+
const envConcThreshold = Number.parseFloat((_f = process.env.GMAX_CONCENTRATION_THRESHOLD) !== null && _f !== void 0 ? _f : "");
|
|
636
|
+
// <= 0 (or NaN with the default) keeps the gate active at 0.7; a value > 1
|
|
637
|
+
// disables it (no possible share reaches it), giving a rerank-fully-off
|
|
638
|
+
// baseline for sweeps without touching the doRerank default. 0.7 is the
|
|
639
|
+
// sweep winner: highest threshold (least spurious firing) that still
|
|
640
|
+
// retains lodash's +0.15 MRR lift while leaving express/platform flat.
|
|
641
|
+
const CONCENTRATION_THRESHOLD = Number.isFinite(envConcThreshold) && envConcThreshold > 0
|
|
642
|
+
? envConcThreshold
|
|
643
|
+
: 0.7;
|
|
621
644
|
if (!doRerank) {
|
|
622
|
-
const envConcThreshold = Number.parseFloat((_f = process.env.GMAX_CONCENTRATION_THRESHOLD) !== null && _f !== void 0 ? _f : "");
|
|
623
|
-
// <= 0 (or NaN with the default) keeps the gate active at 0.7; a value > 1
|
|
624
|
-
// disables it (no possible share reaches it), giving a rerank-fully-off
|
|
625
|
-
// baseline for sweeps without touching the doRerank default. 0.7 is the
|
|
626
|
-
// sweep winner: highest threshold (least spurious firing) that still
|
|
627
|
-
// retains lodash's +0.15 MRR lift while leaving express/platform flat.
|
|
628
|
-
const CONCENTRATION_THRESHOLD = Number.isFinite(envConcThreshold) && envConcThreshold > 0
|
|
629
|
-
? envConcThreshold
|
|
630
|
-
: 0.7;
|
|
631
645
|
// Histogram a fixed top-K window (not finalLimit) so the threshold stays
|
|
632
646
|
// calibrated across callers regardless of the result window they request.
|
|
633
647
|
const CONCENTRATION_K = 10;
|
|
@@ -643,16 +657,21 @@ class Searcher {
|
|
|
643
657
|
maxBucket = count;
|
|
644
658
|
}
|
|
645
659
|
const share = maxBucket / window.length;
|
|
660
|
+
gateEvaluated = true;
|
|
661
|
+
gateShare = share;
|
|
646
662
|
if (share >= CONCENTRATION_THRESHOLD) {
|
|
647
663
|
doRerank = true;
|
|
664
|
+
gateActivated = true;
|
|
648
665
|
}
|
|
649
666
|
}
|
|
650
667
|
}
|
|
668
|
+
diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.capture("fusion", fused);
|
|
651
669
|
// Item 8: Widen PRE_RERANK_K
|
|
652
670
|
// Retrieve a wide set for Stage 1 filtering
|
|
653
671
|
const envStage1 = Number.parseInt((_h = process.env.GMAX_STAGE1_K) !== null && _h !== void 0 ? _h : "", 10);
|
|
654
672
|
const STAGE1_K = Number.isFinite(envStage1) && envStage1 > 0 ? envStage1 : 200;
|
|
655
673
|
const topCandidates = fused.slice(0, STAGE1_K);
|
|
674
|
+
diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.capture("stage1", topCandidates);
|
|
656
675
|
// Free docMap — topCandidates already holds record references
|
|
657
676
|
docMap.clear();
|
|
658
677
|
// Item 9: Two-stage rerank
|
|
@@ -694,11 +713,38 @@ class Searcher {
|
|
|
694
713
|
withScore.sort((a, b) => b.score - a.score);
|
|
695
714
|
stage2Candidates = withScore.slice(0, STAGE2_K).map((x) => x.doc);
|
|
696
715
|
}
|
|
716
|
+
diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.capture("pooled", stage2Candidates);
|
|
717
|
+
const diagnosticDetails = () => ({
|
|
718
|
+
settings: {
|
|
719
|
+
finalLimit,
|
|
720
|
+
preK: PRE_RERANK_K,
|
|
721
|
+
rrfK: RRF_K,
|
|
722
|
+
stage1K: STAGE1_K,
|
|
723
|
+
stage2K: STAGE2_K,
|
|
724
|
+
rerankTop: RERANK_TOP,
|
|
725
|
+
fusedWeight: FUSED_WEIGHT,
|
|
726
|
+
pagerankEnabled,
|
|
727
|
+
seedsActive: seedCtx.active,
|
|
728
|
+
symbolQuery,
|
|
729
|
+
pooledFilterApplied: !!queryPooled && topCandidates.length > STAGE2_K,
|
|
730
|
+
},
|
|
731
|
+
gate: {
|
|
732
|
+
requestedRerank,
|
|
733
|
+
threshold: CONCENTRATION_THRESHOLD,
|
|
734
|
+
evaluated: gateEvaluated,
|
|
735
|
+
share: gateShare,
|
|
736
|
+
activated: gateActivated,
|
|
737
|
+
rerankInvoked,
|
|
738
|
+
},
|
|
739
|
+
fts: { available: this.ftsAvailable, searchFailed: ftsSearchFailed },
|
|
740
|
+
});
|
|
697
741
|
if (stage2Candidates.length === 0) {
|
|
698
|
-
return { data: [] }
|
|
742
|
+
return Object.assign({ data: [] }, (diagnostics
|
|
743
|
+
? { diagnostics: diagnostics.finish(diagnosticDetails()) }
|
|
744
|
+
: {}));
|
|
699
745
|
}
|
|
700
746
|
const envMaxPerFile = Number.parseInt((_m = process.env.GMAX_MAX_PER_FILE) !== null && _m !== void 0 ? _m : "", 10);
|
|
701
|
-
const MAX_PER_FILE = Number.isFinite(envMaxPerFile) && envMaxPerFile > 0 ? envMaxPerFile : 3;
|
|
747
|
+
const MAX_PER_FILE = requestedMaxPerFile !== null && requestedMaxPerFile !== void 0 ? requestedMaxPerFile : (Number.isFinite(envMaxPerFile) && envMaxPerFile > 0 ? envMaxPerFile : 3);
|
|
702
748
|
// Rank the entire bounded candidate pool before trimming the result count.
|
|
703
749
|
// A limit-dependent cut here discarded contenders before structure boosts
|
|
704
750
|
// and dedup, so requesting three results could hide the top match returned
|
|
@@ -735,6 +781,8 @@ class Searcher {
|
|
|
735
781
|
}
|
|
736
782
|
}
|
|
737
783
|
}
|
|
784
|
+
// Selected rerank membership is separate from actual batch execution.
|
|
785
|
+
diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.capture("rerank", rerankCandidates);
|
|
738
786
|
// Phase B: Lazy-load colbert data only for the ~20 rerank candidates
|
|
739
787
|
if (doRerank && rerankCandidates.length > 0) {
|
|
740
788
|
const rerankIds = rerankCandidates
|
|
@@ -761,6 +809,7 @@ class Searcher {
|
|
|
761
809
|
}
|
|
762
810
|
const rerankScoreByKey = new Map();
|
|
763
811
|
if (doRerank && rerankCandidates.length > 0) {
|
|
812
|
+
rerankInvoked = true;
|
|
764
813
|
const scores = yield pool.rerank({
|
|
765
814
|
query: queryMatrixRaw,
|
|
766
815
|
docs: rerankCandidates.map((doc) => { var _a; return ({
|
|
@@ -847,8 +896,10 @@ class Searcher {
|
|
|
847
896
|
}
|
|
848
897
|
// Note: "boosted" was not previously declared -- fix to use "scored"
|
|
849
898
|
scored.sort((a, b) => b.score - a.score);
|
|
899
|
+
diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.capture("scored", scored.map((item) => item.record));
|
|
850
900
|
// Item 11: Intelligent Deduplication
|
|
851
901
|
const uniqueScored = this.deduplicateResults(scored);
|
|
902
|
+
diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.capture("dedup", uniqueScored.map((item) => item.record));
|
|
852
903
|
// Item 10: Per-file diversification
|
|
853
904
|
const seenFiles = new Map();
|
|
854
905
|
const diversified = [];
|
|
@@ -859,9 +910,13 @@ class Searcher {
|
|
|
859
910
|
diversified.push(item);
|
|
860
911
|
seenFiles.set(path, count + 1);
|
|
861
912
|
}
|
|
913
|
+
else {
|
|
914
|
+
diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.noteFileLimit(item.record);
|
|
915
|
+
}
|
|
862
916
|
if (diversified.length >= finalLimit)
|
|
863
917
|
break;
|
|
864
918
|
}
|
|
919
|
+
diagnostics === null || diagnostics === void 0 ? void 0 : diagnostics.capture("final", diversified.map((item) => item.record));
|
|
865
920
|
// Phase C: Lazy-load display columns only for the final ~10 results
|
|
866
921
|
const finalIds = diversified
|
|
867
922
|
.map((item) => item.record.id)
|
|
@@ -898,7 +953,7 @@ class Searcher {
|
|
|
898
953
|
const finalResults = diversified.map((item) => (Object.assign(Object.assign({}, item.record), { _score: item.score, _breakdown: item.breakdown, vector: undefined, colbert: undefined })));
|
|
899
954
|
// Item 12: Score Calibration
|
|
900
955
|
const maxScore = finalResults.length > 0 ? finalResults[0]._score : 1.0;
|
|
901
|
-
return Object.assign({ data: finalResults.map((r) => {
|
|
956
|
+
return Object.assign(Object.assign({ data: finalResults.map((r) => {
|
|
902
957
|
const chunk = this.mapRecordToChunk(r, r._score || 0);
|
|
903
958
|
// Normalize score relative to top result
|
|
904
959
|
const normalized = maxScore > 0 ? r._score / maxScore : 0;
|
|
@@ -913,7 +968,11 @@ class Searcher {
|
|
|
913
968
|
}
|
|
914
969
|
chunk.confidence = confidence;
|
|
915
970
|
return chunk;
|
|
916
|
-
}) }, (
|
|
971
|
+
}) }, (diagnostics
|
|
972
|
+
? {
|
|
973
|
+
diagnostics: diagnostics.finish(Object.assign(Object.assign({}, diagnosticDetails()), { settings: Object.assign(Object.assign({}, diagnosticDetails().settings), { maxPerFile: MAX_PER_FILE, definitionBoost: DEF_MATCH_BOOST }) })),
|
|
974
|
+
}
|
|
975
|
+
: {})), (!this.ftsAvailable || ftsSearchFailed
|
|
917
976
|
? {
|
|
918
977
|
warnings: [
|
|
919
978
|
"Full-text search unavailable — results may be less precise",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.sendSearchCommand = sendSearchCommand;
|
|
13
|
+
const per_file_1 = require("../search/per-file");
|
|
14
|
+
const daemon_client_1 = require("./daemon-client");
|
|
15
|
+
/** An old live daemon must not silently ignore a request-scoped override. */
|
|
16
|
+
function sendSearchCommand(command, options) {
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
var _a;
|
|
19
|
+
const maxPerFile = (0, per_file_1.validateMaxPerFile)(command.maxPerFile);
|
|
20
|
+
if (maxPerFile !== undefined) {
|
|
21
|
+
const ping = yield (0, daemon_client_1.sendDaemonCommand)({ cmd: "ping" }, options);
|
|
22
|
+
if (!ping.ok)
|
|
23
|
+
return ping;
|
|
24
|
+
if (((_a = ping.capabilities) === null || _a === void 0 ? void 0 : _a.perFileSearch) !== 1) {
|
|
25
|
+
return {
|
|
26
|
+
ok: false,
|
|
27
|
+
error: "unsupported per-file retrieval control",
|
|
28
|
+
hint: "run gmax watch restart with the updated CLI",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return (0, daemon_client_1.sendDaemonCommand)(command, options);
|
|
33
|
+
});
|
|
34
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grepmax",
|
|
3
|
-
"version": "0.26.
|
|
3
|
+
"version": "0.26.50",
|
|
4
4
|
"author": "Robert Owens <78518764+reowens@users.noreply.github.com>",
|
|
5
5
|
"homepage": "https://github.com/reowens/grepmax",
|
|
6
6
|
"bugs": {
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"bench:recall:json": "GMAX_EVAL_JSON=1 npx tsx src/eval.ts",
|
|
30
30
|
"bench:oss": "npx tsx src/eval-oss.ts all",
|
|
31
31
|
"bench:oss:json": "GMAX_EVAL_JSON=1 npx tsx src/eval-oss.ts all",
|
|
32
|
+
"bench:relevance": "tsx src/eval-relevance.ts",
|
|
32
33
|
"bench:tokens": "npx tsx src/eval-tokens.ts",
|
|
33
34
|
"bench:tokens:json": "GMAX_EVAL_JSON=1 npx tsx src/eval-tokens.ts",
|
|
34
35
|
"bench:surprises": "npx tsx src/eval-surprising-connections.ts",
|
|
@@ -76,7 +77,7 @@
|
|
|
76
77
|
"NOTICE"
|
|
77
78
|
],
|
|
78
79
|
"license": "Apache-2.0",
|
|
79
|
-
"description": "Semantic code search for coding agents. Local embeddings,
|
|
80
|
+
"description": "Semantic code search for coding agents. Local embeddings, call graph tracing, compact code context.",
|
|
80
81
|
"dependencies": {
|
|
81
82
|
"@clack/prompts": "^1.8.1",
|
|
82
83
|
"@huggingface/transformers": "^4.3.0",
|