grepmax 0.21.2 → 0.21.3
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/dist/config.js +6 -1
- package/dist/lib/graph/graph-builder.js +23 -3
- package/dist/lib/index/chunker.js +30 -3
- package/dist/lib/store/vector-db.js +32 -17
- package/dist/lib/workers/orchestrator.js +1 -0
- package/package.json +1 -1
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"name": "grepmax",
|
|
11
11
|
"source": "./plugins/grepmax",
|
|
12
12
|
"description": "Semantic code search for Claude Code. Automatically indexes your project and provides intelligent search capabilities.",
|
|
13
|
-
"version": "0.21.
|
|
13
|
+
"version": "0.21.3",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "Robert Owens",
|
|
16
16
|
"email": "robowens@me.com"
|
package/dist/config.js
CHANGED
|
@@ -84,7 +84,7 @@ exports.CONFIG = {
|
|
|
84
84
|
// reindex to take effect. Must equal the latest entry's `v` in
|
|
85
85
|
// CHUNKER_VERSION_HISTORY below — see that list for per-version severity and
|
|
86
86
|
// the user-facing note rendered by `gmax doctor` and the staleness hint.
|
|
87
|
-
CHUNKER_VERSION:
|
|
87
|
+
CHUNKER_VERSION: 4,
|
|
88
88
|
};
|
|
89
89
|
/**
|
|
90
90
|
* Per-version record of what changed in the chunker and how much it matters to
|
|
@@ -105,6 +105,11 @@ exports.CHUNKER_VERSION_HISTORY = [
|
|
|
105
105
|
severity: "additive",
|
|
106
106
|
note: "type-position edges; dead/trace miss type-only callers until reindex.",
|
|
107
107
|
},
|
|
108
|
+
{
|
|
109
|
+
v: 4,
|
|
110
|
+
severity: "additive",
|
|
111
|
+
note: "member-call edges recorded separately (obj.method()); substrate for receiver-aware call resolution, no query effect until reindex.",
|
|
112
|
+
},
|
|
108
113
|
];
|
|
109
114
|
/**
|
|
110
115
|
* Describe the gap between an index's stamped chunker version and the current
|
|
@@ -13,6 +13,7 @@ exports.GraphBuilder = void 0;
|
|
|
13
13
|
const languages_1 = require("../core/languages");
|
|
14
14
|
const filter_builder_1 = require("../utils/filter-builder");
|
|
15
15
|
const query_timeout_1 = require("../utils/query-timeout");
|
|
16
|
+
const callsites_1 = require("./callsites");
|
|
16
17
|
const graph_traversal_1 = require("./graph-traversal");
|
|
17
18
|
class GraphBuilder {
|
|
18
19
|
constructor(db, pathPrefix, excludePrefixes) {
|
|
@@ -130,9 +131,14 @@ class GraphBuilder {
|
|
|
130
131
|
const callers = yield this.getCallers(symbol, anchorFamily);
|
|
131
132
|
// 3. Get Callees — resolve each to a GraphNode with file:line
|
|
132
133
|
const calleeNames = center ? center.calls.slice(0, 15) : [];
|
|
134
|
+
const centerFile = center ? center.file : "";
|
|
133
135
|
const calleeNodes = [];
|
|
134
136
|
for (const name of calleeNames) {
|
|
135
137
|
const esc = (0, filter_builder_1.escapeSqlString)(name);
|
|
138
|
+
// Pull a few candidates (was .limit(1)) so a callee name defined in more
|
|
139
|
+
// than one file can prefer the center's OWN file instead of an arbitrary
|
|
140
|
+
// same-named definition in an unrelated module — the cheapest correct
|
|
141
|
+
// disambiguation, and strictly better than the old first-row guess.
|
|
136
142
|
const rows = yield table
|
|
137
143
|
.query()
|
|
138
144
|
.where(this.scopeWhere(`array_contains(defined_symbols, '${esc}')`))
|
|
@@ -145,12 +151,21 @@ class GraphBuilder {
|
|
|
145
151
|
"parent_symbol",
|
|
146
152
|
"complexity",
|
|
147
153
|
])
|
|
148
|
-
.limit(
|
|
154
|
+
.limit(25)
|
|
149
155
|
.toArray();
|
|
150
156
|
if (rows.length > 0) {
|
|
151
|
-
|
|
157
|
+
// Prefer-self-file: a callee the center also defines locally is almost
|
|
158
|
+
// certainly that local definition. Falls back to the first row when no
|
|
159
|
+
// candidate is in the center's file (unchanged behaviour then).
|
|
160
|
+
const selfRow = rows.find((r) => { var _a; return String((_a = r.path) !== null && _a !== void 0 ? _a : "") === centerFile; });
|
|
161
|
+
calleeNodes.push(this.mapRowToNode((selfRow !== null && selfRow !== void 0 ? selfRow : rows[0]), name, "center"));
|
|
152
162
|
}
|
|
153
|
-
else {
|
|
163
|
+
else if (!(0, callsites_1.isBuiltinCallee)(name)) {
|
|
164
|
+
// Unresolved + a known builtin (.map/.get/forEach) → suppress the
|
|
165
|
+
// phantom callee edge instead of emitting a "(not indexed)" stub.
|
|
166
|
+
// Mirrors the display-layer guard (peek.ts: `c.file || !isBuiltinCallee`):
|
|
167
|
+
// a project symbol that shadows a builtin name still resolves above and
|
|
168
|
+
// is kept, so only genuine builtins are dropped.
|
|
154
169
|
calleeNodes.push({
|
|
155
170
|
symbol: name,
|
|
156
171
|
file: "",
|
|
@@ -274,6 +289,11 @@ class GraphBuilder {
|
|
|
274
289
|
const out = [];
|
|
275
290
|
for (const h of hits) {
|
|
276
291
|
const loc = yield this.resolveLocation(h.symbol, anchorFamily);
|
|
292
|
+
// Drop unresolved builtins (.map/.get/forEach) reached via callee edges —
|
|
293
|
+
// same resolution-aware rule as buildGraph/peek. A neighbor that resolves
|
|
294
|
+
// to an indexed definition is kept even if it shadows a builtin name.
|
|
295
|
+
if (!loc && (0, callsites_1.isBuiltinCallee)(h.symbol))
|
|
296
|
+
continue;
|
|
277
297
|
out.push(Object.assign(Object.assign({}, h), { file: (_a = loc === null || loc === void 0 ? void 0 : loc.file) !== null && _a !== void 0 ? _a : "", line: (_b = loc === null || loc === void 0 ? void 0 : loc.line) !== null && _b !== void 0 ? _b : 0 }));
|
|
278
298
|
}
|
|
279
299
|
return out;
|
|
@@ -571,6 +571,15 @@ class TreeSitterChunker {
|
|
|
571
571
|
typeReferencedSymbols.push(n);
|
|
572
572
|
}
|
|
573
573
|
};
|
|
574
|
+
// Member-call names (`obj.method()`), recorded additively alongside
|
|
575
|
+
// referencedSymbols (see Chunk.memberReferencedSymbols). Deduped, like
|
|
576
|
+
// type refs — a future resolver queries membership, not occurrence count.
|
|
577
|
+
const memberReferencedSymbols = [];
|
|
578
|
+
const addMemberRef = (n) => {
|
|
579
|
+
if (n && !memberReferencedSymbols.includes(n)) {
|
|
580
|
+
memberReferencedSymbols.push(n);
|
|
581
|
+
}
|
|
582
|
+
};
|
|
574
583
|
// Leaf identifier node types across grammars (a bare name with no
|
|
575
584
|
// named children — `ErrorCodes`, not `a.ErrorCodes`).
|
|
576
585
|
const LEAF_ID_TYPES = new Set([
|
|
@@ -677,24 +686,33 @@ class TreeSitterChunker {
|
|
|
677
686
|
: null;
|
|
678
687
|
if (func) {
|
|
679
688
|
let funcName = func.text;
|
|
689
|
+
let isMemberCall = false;
|
|
680
690
|
// Handle member access (obj.method) to extract just 'method'
|
|
681
691
|
if (func.type === "member_expression") {
|
|
682
692
|
// JS/TS: object.property
|
|
683
693
|
const prop = func.childForFieldName
|
|
684
694
|
? func.childForFieldName("property")
|
|
685
695
|
: null;
|
|
686
|
-
if (prop)
|
|
696
|
+
if (prop) {
|
|
687
697
|
funcName = prop.text;
|
|
698
|
+
isMemberCall = true;
|
|
699
|
+
}
|
|
688
700
|
}
|
|
689
701
|
else if (func.type === "attribute") {
|
|
690
702
|
// Python: object.attribute
|
|
691
703
|
const attr = func.childForFieldName
|
|
692
704
|
? func.childForFieldName("attribute")
|
|
693
705
|
: null;
|
|
694
|
-
if (attr)
|
|
706
|
+
if (attr) {
|
|
695
707
|
funcName = attr.text;
|
|
708
|
+
isMemberCall = true;
|
|
709
|
+
}
|
|
696
710
|
}
|
|
697
711
|
referencedSymbols.push(funcName);
|
|
712
|
+
// Additive: member calls ALSO go here. referencedSymbols is left
|
|
713
|
+
// untouched (no recall loss); this just tags which were members.
|
|
714
|
+
if (isMemberCall)
|
|
715
|
+
addMemberRef(funcName);
|
|
698
716
|
}
|
|
699
717
|
else {
|
|
700
718
|
// Swift/Kotlin: call_expression has no "function" field;
|
|
@@ -702,15 +720,20 @@ class TreeSitterChunker {
|
|
|
702
720
|
const firstChild = ((_a = n.namedChildren) !== null && _a !== void 0 ? _a : [])[0];
|
|
703
721
|
if (firstChild) {
|
|
704
722
|
let funcName = firstChild.text;
|
|
723
|
+
let isMemberCall = false;
|
|
705
724
|
if (firstChild.type === "navigation_expression") {
|
|
706
725
|
const suffix = ((_b = firstChild.namedChildren) !== null && _b !== void 0 ? _b : []).find((c) => c.type === "navigation_suffix");
|
|
707
726
|
const methodId = suffix
|
|
708
727
|
? ((_c = suffix.namedChildren) !== null && _c !== void 0 ? _c : []).find((c) => c.type === "simple_identifier")
|
|
709
728
|
: null;
|
|
710
|
-
if (methodId)
|
|
729
|
+
if (methodId) {
|
|
711
730
|
funcName = methodId.text;
|
|
731
|
+
isMemberCall = true;
|
|
732
|
+
}
|
|
712
733
|
}
|
|
713
734
|
referencedSymbols.push(funcName);
|
|
735
|
+
if (isMemberCall)
|
|
736
|
+
addMemberRef(funcName);
|
|
714
737
|
}
|
|
715
738
|
}
|
|
716
739
|
}
|
|
@@ -905,6 +928,7 @@ class TreeSitterChunker {
|
|
|
905
928
|
definedSymbols,
|
|
906
929
|
referencedSymbols,
|
|
907
930
|
typeReferencedSymbols,
|
|
931
|
+
memberReferencedSymbols,
|
|
908
932
|
role,
|
|
909
933
|
parentSymbol: stack.length > 1
|
|
910
934
|
? stack[stack.length - 1].replace(/^(Class|Method|Function|Interface|Type): /, "")
|
|
@@ -990,6 +1014,9 @@ class TreeSitterChunker {
|
|
|
990
1014
|
if (sub.typeReferencedSymbols) {
|
|
991
1015
|
sub.typeReferencedSymbols = sub.typeReferencedSymbols.filter(occurs);
|
|
992
1016
|
}
|
|
1017
|
+
if (sub.memberReferencedSymbols) {
|
|
1018
|
+
sub.memberReferencedSymbols = sub.memberReferencedSymbols.filter(occurs);
|
|
1019
|
+
}
|
|
993
1020
|
return sub;
|
|
994
1021
|
}
|
|
995
1022
|
splitIfTooBig(chunk) {
|
|
@@ -271,6 +271,7 @@ class VectorDB {
|
|
|
271
271
|
defined_symbols: [],
|
|
272
272
|
referenced_symbols: [],
|
|
273
273
|
type_referenced_symbols: [],
|
|
274
|
+
member_referenced_symbols: [],
|
|
274
275
|
imports: [],
|
|
275
276
|
exports: [],
|
|
276
277
|
role: "",
|
|
@@ -340,6 +341,7 @@ class VectorDB {
|
|
|
340
341
|
new apache_arrow_1.Field("defined_symbols", new apache_arrow_1.List(new apache_arrow_1.Field("item", new apache_arrow_1.Utf8(), true)), true),
|
|
341
342
|
new apache_arrow_1.Field("referenced_symbols", new apache_arrow_1.List(new apache_arrow_1.Field("item", new apache_arrow_1.Utf8(), true)), true),
|
|
342
343
|
new apache_arrow_1.Field("type_referenced_symbols", new apache_arrow_1.List(new apache_arrow_1.Field("item", new apache_arrow_1.Utf8(), true)), true),
|
|
344
|
+
new apache_arrow_1.Field("member_referenced_symbols", new apache_arrow_1.List(new apache_arrow_1.Field("item", new apache_arrow_1.Utf8(), true)), true),
|
|
343
345
|
new apache_arrow_1.Field("imports", new apache_arrow_1.List(new apache_arrow_1.Field("item", new apache_arrow_1.Utf8(), true)), true),
|
|
344
346
|
new apache_arrow_1.Field("exports", new apache_arrow_1.List(new apache_arrow_1.Field("item", new apache_arrow_1.Utf8(), true)), true),
|
|
345
347
|
new apache_arrow_1.Field("role", new apache_arrow_1.Utf8(), true),
|
|
@@ -360,16 +362,27 @@ class VectorDB {
|
|
|
360
362
|
return __awaiter(this, void 0, void 0, function* () {
|
|
361
363
|
const schema = yield table.schema();
|
|
362
364
|
const fields = new Set(schema.fields.map((f) => f.name));
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
365
|
+
// Additive list columns that older tables may predate. Each is checked and
|
|
366
|
+
// added INDEPENDENTLY: a single early-return on the first existing column
|
|
367
|
+
// (as this used to do) would permanently strand every table that already has
|
|
368
|
+
// `type_referenced_symbols` — i.e. all of them — without ever gaining a newer
|
|
369
|
+
// column like `member_referenced_symbols`.
|
|
370
|
+
const additiveListColumns = [
|
|
371
|
+
"type_referenced_symbols",
|
|
372
|
+
"member_referenced_symbols",
|
|
373
|
+
];
|
|
374
|
+
for (const col of additiveListColumns) {
|
|
375
|
+
if (fields.has(col))
|
|
376
|
+
continue;
|
|
377
|
+
try {
|
|
378
|
+
yield table.addColumns(new apache_arrow_1.Field(col, new apache_arrow_1.List(new apache_arrow_1.Field("item", new apache_arrow_1.Utf8(), true)), true));
|
|
379
|
+
(0, logger_1.log)("db", `Added ${col} column to existing table`);
|
|
380
|
+
}
|
|
381
|
+
catch (err) {
|
|
382
|
+
// Lost a race with another writer that already added it, or a transient
|
|
383
|
+
// commit conflict — the next ensureTable() re-checks and no-ops.
|
|
384
|
+
(0, logger_1.debug)("vectordb", `evolveSchema ${col} skipped: ${err.message}`);
|
|
385
|
+
}
|
|
373
386
|
}
|
|
374
387
|
});
|
|
375
388
|
}
|
|
@@ -395,7 +408,7 @@ class VectorDB {
|
|
|
395
408
|
}
|
|
396
409
|
insertBatch(records) {
|
|
397
410
|
return __awaiter(this, void 0, void 0, function* () {
|
|
398
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
411
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
399
412
|
if (!records.length)
|
|
400
413
|
return;
|
|
401
414
|
this.ensureDiskOk();
|
|
@@ -473,12 +486,14 @@ class VectorDB {
|
|
|
473
486
|
rec.defined_symbols = (_g = rec.defined_symbols) !== null && _g !== void 0 ? _g : [];
|
|
474
487
|
rec.referenced_symbols = (_h = rec.referenced_symbols) !== null && _h !== void 0 ? _h : [];
|
|
475
488
|
rec.type_referenced_symbols = (_j = rec.type_referenced_symbols) !== null && _j !== void 0 ? _j : [];
|
|
476
|
-
rec.
|
|
477
|
-
|
|
478
|
-
rec.
|
|
479
|
-
rec.
|
|
480
|
-
rec.
|
|
481
|
-
rec.
|
|
489
|
+
rec.member_referenced_symbols =
|
|
490
|
+
(_k = rec.member_referenced_symbols) !== null && _k !== void 0 ? _k : [];
|
|
491
|
+
rec.imports = (_l = rec.imports) !== null && _l !== void 0 ? _l : [];
|
|
492
|
+
rec.exports = (_m = rec.exports) !== null && _m !== void 0 ? _m : [];
|
|
493
|
+
rec.role = (_o = rec.role) !== null && _o !== void 0 ? _o : "";
|
|
494
|
+
rec.parent_symbol = (_p = rec.parent_symbol) !== null && _p !== void 0 ? _p : "";
|
|
495
|
+
rec.file_skeleton = (_q = rec.file_skeleton) !== null && _q !== void 0 ? _q : "";
|
|
496
|
+
rec.summary = (_r = rec.summary) !== null && _r !== void 0 ? _r : null;
|
|
482
497
|
}
|
|
483
498
|
try {
|
|
484
499
|
yield this.withWriteGate(() => table.add(records));
|
|
@@ -227,6 +227,7 @@ class WorkerOrchestrator {
|
|
|
227
227
|
defined_symbols: chunk.definedSymbols,
|
|
228
228
|
referenced_symbols: chunk.referencedSymbols,
|
|
229
229
|
type_referenced_symbols: chunk.typeReferencedSymbols,
|
|
230
|
+
member_referenced_symbols: chunk.memberReferencedSymbols,
|
|
230
231
|
role: chunk.role,
|
|
231
232
|
parent_symbol: chunk.parentSymbol,
|
|
232
233
|
file_skeleton: chunk.isAnchor ? skeleton : undefined,
|
package/package.json
CHANGED