grepmax 0.17.21 → 0.17.22
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/impact.js +20 -11
- package/dist/commands/search-run.js +227 -0
- package/dist/commands/search-skeletons.js +133 -0
- package/dist/commands/search.js +43 -450
- package/dist/lib/daemon/daemon.js +14 -101
- package/dist/lib/daemon/search-handler.js +159 -0
- package/dist/lib/output/compact-results.js +244 -0
- package/package.json +1 -1
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
|
@@ -62,8 +62,7 @@ const config_1 = require("../../config");
|
|
|
62
62
|
const batch_processor_1 = require("../index/batch-processor");
|
|
63
63
|
const syncer_1 = require("../index/syncer");
|
|
64
64
|
const watcher_1 = require("../index/watcher");
|
|
65
|
-
const
|
|
66
|
-
const retriever_1 = require("../skeleton/retriever");
|
|
65
|
+
const search_handler_1 = require("./search-handler");
|
|
67
66
|
const meta_cache_1 = require("../store/meta-cache");
|
|
68
67
|
const vector_db_1 = require("../store/vector-db");
|
|
69
68
|
const process_1 = require("../utils/process");
|
|
@@ -841,105 +840,19 @@ class Daemon {
|
|
|
841
840
|
}
|
|
842
841
|
search(payload, signal) {
|
|
843
842
|
return __awaiter(this, void 0, void 0, function* () {
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
ok: false,
|
|
858
|
-
error: "project not watched",
|
|
859
|
-
hint: `run: gmax add ${root}`,
|
|
860
|
-
};
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
let searcher = this.searchers.get(root);
|
|
864
|
-
if (!searcher) {
|
|
865
|
-
searcher = new searcher_1.Searcher(this.vectorDb);
|
|
866
|
-
this.searchers.set(root, searcher);
|
|
867
|
-
}
|
|
868
|
-
this.lastActivity = Date.now();
|
|
869
|
-
let result;
|
|
870
|
-
try {
|
|
871
|
-
result = yield searcher.search(payload.query, payload.limit, {
|
|
872
|
-
rerank: payload.rerank === true,
|
|
873
|
-
explain: payload.explain === true,
|
|
874
|
-
seeds: payload.seeds,
|
|
875
|
-
}, payload.filters, payload.pathPrefix, undefined, signal);
|
|
876
|
-
}
|
|
877
|
-
catch (err) {
|
|
878
|
-
if ((err === null || err === void 0 ? void 0 : err.name) === "AbortError") {
|
|
879
|
-
return { ok: false, error: "aborted" };
|
|
880
|
-
}
|
|
881
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
882
|
-
return { ok: false, error: "search_failed", hint: msg };
|
|
883
|
-
}
|
|
884
|
-
const response = { ok: true, data: result.data };
|
|
885
|
-
if ((_b = result.warnings) === null || _b === void 0 ? void 0 : _b.length)
|
|
886
|
-
response.warnings = result.warnings;
|
|
887
|
-
// Annotate partial results when the index is still catching up, so an
|
|
888
|
-
// agent can caveat or retry. Only attached when actually indexing (the
|
|
889
|
-
// formatter suppresses the settled case anyway).
|
|
890
|
-
const idx = this.indexState(root);
|
|
891
|
-
if (idx.indexing)
|
|
892
|
-
response.indexState = idx;
|
|
893
|
-
// --skeleton support: fetch per-file skeletons inline so the CLI doesn't
|
|
894
|
-
// have to open its own VectorDB. getStoredSkeleton is a single LIMIT-1
|
|
895
|
-
// lookup; cheap enough to call for the top N distinct paths.
|
|
896
|
-
if (payload.includeSkeletons && result.data.length > 0) {
|
|
897
|
-
const limit = payload.skeletonLimit && payload.skeletonLimit > 0 ? payload.skeletonLimit : 5;
|
|
898
|
-
const seen = new Set();
|
|
899
|
-
const skeletons = {};
|
|
900
|
-
for (const chunk of result.data) {
|
|
901
|
-
const p = (_c = chunk.path) !== null && _c !== void 0 ? _c : (_d = chunk.metadata) === null || _d === void 0 ? void 0 : _d.path;
|
|
902
|
-
if (!p || seen.has(p))
|
|
903
|
-
continue;
|
|
904
|
-
seen.add(p);
|
|
905
|
-
if (seen.size > limit)
|
|
906
|
-
break;
|
|
907
|
-
try {
|
|
908
|
-
const sk = yield (0, retriever_1.getStoredSkeleton)(this.vectorDb, p);
|
|
909
|
-
if (sk)
|
|
910
|
-
skeletons[p] = sk;
|
|
911
|
-
}
|
|
912
|
-
catch (_e) {
|
|
913
|
-
// best-effort — drop the entry, keep the search result
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
if (Object.keys(skeletons).length > 0)
|
|
917
|
-
response.skeletons = skeletons;
|
|
918
|
-
}
|
|
919
|
-
// --symbol support: build a 1-hop graph using the warm vectorDb. ~5
|
|
920
|
-
// LanceDB queries; doesn't touch the worker pool.
|
|
921
|
-
if (payload.includeGraph) {
|
|
922
|
-
try {
|
|
923
|
-
const { GraphBuilder } = yield Promise.resolve().then(() => __importStar(require("../graph/graph-builder")));
|
|
924
|
-
const builder = new GraphBuilder(this.vectorDb, root);
|
|
925
|
-
response.graph = yield builder.buildGraphMultiHop(payload.query, 1);
|
|
926
|
-
}
|
|
927
|
-
catch (_f) {
|
|
928
|
-
// best-effort — drop graph, keep results
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
// 2 MB cap on the JSON line. Lance can return huge chunks for unusual
|
|
932
|
-
// queries (very long markdown blobs). Above this we fall back to the
|
|
933
|
-
// in-process path which writes to stdout instead of a socket.
|
|
934
|
-
const serialized = JSON.stringify(response);
|
|
935
|
-
if (serialized.length > 2 * 1024 * 1024) {
|
|
936
|
-
return {
|
|
937
|
-
ok: false,
|
|
938
|
-
error: "oversize",
|
|
939
|
-
hint: `${serialized.length} bytes — falling back to in-process search`,
|
|
940
|
-
};
|
|
941
|
-
}
|
|
942
|
-
return response;
|
|
843
|
+
// Search handling lives in search-handler.ts (Phase 12 split). The daemon
|
|
844
|
+
// supplies its warm VectorDB + watcher/index bookkeeping; the handler runs
|
|
845
|
+
// the query and assembles the response.
|
|
846
|
+
return (0, search_handler_1.handleDaemonSearch)({
|
|
847
|
+
vectorDb: this.vectorDb,
|
|
848
|
+
processors: this.processors,
|
|
849
|
+
indexProgress: this.indexProgress,
|
|
850
|
+
searchers: this.searchers,
|
|
851
|
+
getIndexState: (root) => this.indexState(root),
|
|
852
|
+
touchActivity: () => {
|
|
853
|
+
this.lastActivity = Date.now();
|
|
854
|
+
},
|
|
855
|
+
}, payload, signal);
|
|
943
856
|
});
|
|
944
857
|
}
|
|
945
858
|
listProjects() {
|
|
@@ -0,0 +1,159 @@
|
|
|
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
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.handleDaemonSearch = handleDaemonSearch;
|
|
46
|
+
const searcher_1 = require("../search/searcher");
|
|
47
|
+
const retriever_1 = require("../skeleton/retriever");
|
|
48
|
+
const project_registry_1 = require("../utils/project-registry");
|
|
49
|
+
/**
|
|
50
|
+
* Daemon-side search: runs the hybrid+rerank against the already-warm VectorDB
|
|
51
|
+
* and optionally attaches inline skeletons / a 1-hop graph / a partial-index
|
|
52
|
+
* footer. Extracted from Daemon.search() (Phase 12) — behavior-preserving.
|
|
53
|
+
*/
|
|
54
|
+
function handleDaemonSearch(deps, payload, signal) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
var _a, _b, _c, _d;
|
|
57
|
+
const { vectorDb } = deps;
|
|
58
|
+
if (!vectorDb) {
|
|
59
|
+
return { ok: false, error: "daemon not ready" };
|
|
60
|
+
}
|
|
61
|
+
const root = payload.projectRoot;
|
|
62
|
+
if (!deps.processors.has(root)) {
|
|
63
|
+
// A full index (--reset) or the initial index removes/defers the
|
|
64
|
+
// processor while (re)building. The partial index is still queryable, so
|
|
65
|
+
// answer the search and flag it partial (below) rather than erroring —
|
|
66
|
+
// only truly-unwatched, not-indexing projects get "not watched".
|
|
67
|
+
const indexingNow = deps.indexProgress.has(root) || ((_a = (0, project_registry_1.getProject)(root)) === null || _a === void 0 ? void 0 : _a.status) === "pending";
|
|
68
|
+
if (!indexingNow) {
|
|
69
|
+
return {
|
|
70
|
+
ok: false,
|
|
71
|
+
error: "project not watched",
|
|
72
|
+
hint: `run: gmax add ${root}`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
let searcher = deps.searchers.get(root);
|
|
77
|
+
if (!searcher) {
|
|
78
|
+
searcher = new searcher_1.Searcher(vectorDb);
|
|
79
|
+
deps.searchers.set(root, searcher);
|
|
80
|
+
}
|
|
81
|
+
deps.touchActivity();
|
|
82
|
+
let result;
|
|
83
|
+
try {
|
|
84
|
+
result = yield searcher.search(payload.query, payload.limit, {
|
|
85
|
+
rerank: payload.rerank === true,
|
|
86
|
+
explain: payload.explain === true,
|
|
87
|
+
seeds: payload.seeds,
|
|
88
|
+
}, payload.filters, payload.pathPrefix, undefined, signal);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
if ((err === null || err === void 0 ? void 0 : err.name) === "AbortError") {
|
|
92
|
+
return { ok: false, error: "aborted" };
|
|
93
|
+
}
|
|
94
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
95
|
+
return { ok: false, error: "search_failed", hint: msg };
|
|
96
|
+
}
|
|
97
|
+
const response = { ok: true, data: result.data };
|
|
98
|
+
if ((_b = result.warnings) === null || _b === void 0 ? void 0 : _b.length)
|
|
99
|
+
response.warnings = result.warnings;
|
|
100
|
+
// Annotate partial results when the index is still catching up, so an
|
|
101
|
+
// agent can caveat or retry. Only attached when actually indexing (the
|
|
102
|
+
// formatter suppresses the settled case anyway).
|
|
103
|
+
const idx = deps.getIndexState(root);
|
|
104
|
+
if (idx.indexing)
|
|
105
|
+
response.indexState = idx;
|
|
106
|
+
// --skeleton support: fetch per-file skeletons inline so the CLI doesn't
|
|
107
|
+
// have to open its own VectorDB. getStoredSkeleton is a single LIMIT-1
|
|
108
|
+
// lookup; cheap enough to call for the top N distinct paths.
|
|
109
|
+
if (payload.includeSkeletons && result.data.length > 0) {
|
|
110
|
+
const limit = payload.skeletonLimit && payload.skeletonLimit > 0
|
|
111
|
+
? payload.skeletonLimit
|
|
112
|
+
: 5;
|
|
113
|
+
const seen = new Set();
|
|
114
|
+
const skeletons = {};
|
|
115
|
+
for (const chunk of result.data) {
|
|
116
|
+
const p = (_c = chunk.path) !== null && _c !== void 0 ? _c : (_d = chunk.metadata) === null || _d === void 0 ? void 0 : _d.path;
|
|
117
|
+
if (!p || seen.has(p))
|
|
118
|
+
continue;
|
|
119
|
+
seen.add(p);
|
|
120
|
+
if (seen.size > limit)
|
|
121
|
+
break;
|
|
122
|
+
try {
|
|
123
|
+
const sk = yield (0, retriever_1.getStoredSkeleton)(vectorDb, p);
|
|
124
|
+
if (sk)
|
|
125
|
+
skeletons[p] = sk;
|
|
126
|
+
}
|
|
127
|
+
catch (_e) {
|
|
128
|
+
// best-effort — drop the entry, keep the search result
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (Object.keys(skeletons).length > 0)
|
|
132
|
+
response.skeletons = skeletons;
|
|
133
|
+
}
|
|
134
|
+
// --symbol support: build a 1-hop graph using the warm vectorDb. ~5
|
|
135
|
+
// LanceDB queries; doesn't touch the worker pool.
|
|
136
|
+
if (payload.includeGraph) {
|
|
137
|
+
try {
|
|
138
|
+
const { GraphBuilder } = yield Promise.resolve().then(() => __importStar(require("../graph/graph-builder")));
|
|
139
|
+
const builder = new GraphBuilder(vectorDb, root);
|
|
140
|
+
response.graph = yield builder.buildGraphMultiHop(payload.query, 1);
|
|
141
|
+
}
|
|
142
|
+
catch (_f) {
|
|
143
|
+
// best-effort — drop graph, keep results
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// 2 MB cap on the JSON line. Lance can return huge chunks for unusual
|
|
147
|
+
// queries (very long markdown blobs). Above this we fall back to the
|
|
148
|
+
// in-process path which writes to stdout instead of a socket.
|
|
149
|
+
const serialized = JSON.stringify(response);
|
|
150
|
+
if (serialized.length > 2 * 1024 * 1024) {
|
|
151
|
+
return {
|
|
152
|
+
ok: false,
|
|
153
|
+
error: "oversize",
|
|
154
|
+
hint: `${serialized.length} bytes — falling back to in-process search`,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return response;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
@@ -0,0 +1,244 @@
|
|
|
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.toTextResults = toTextResults;
|
|
37
|
+
exports.toCompactHits = toCompactHits;
|
|
38
|
+
exports.formatCompactTable = formatCompactTable;
|
|
39
|
+
exports.resultCountHeader = resultCountHeader;
|
|
40
|
+
const path = __importStar(require("node:path"));
|
|
41
|
+
function toTextResults(data) {
|
|
42
|
+
return data.map((r) => {
|
|
43
|
+
var _a, _b, _c, _d, _e, _f;
|
|
44
|
+
const rawPath = typeof ((_a = r.metadata) === null || _a === void 0 ? void 0 : _a.path) === "string"
|
|
45
|
+
? r.metadata.path
|
|
46
|
+
: "Unknown path";
|
|
47
|
+
const start = typeof ((_b = r.generated_metadata) === null || _b === void 0 ? void 0 : _b.start_line) === "number"
|
|
48
|
+
? r.generated_metadata.start_line
|
|
49
|
+
: 0;
|
|
50
|
+
const end = typeof ((_c = r.generated_metadata) === null || _c === void 0 ? void 0 : _c.end_line) === "number"
|
|
51
|
+
? r.generated_metadata.end_line
|
|
52
|
+
: 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);
|
|
53
|
+
return {
|
|
54
|
+
path: rawPath,
|
|
55
|
+
score: r.score,
|
|
56
|
+
content: r.text || "",
|
|
57
|
+
chunk_type: (_f = r.generated_metadata) === null || _f === void 0 ? void 0 : _f.type,
|
|
58
|
+
start_line: start,
|
|
59
|
+
end_line: end,
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function getPreviewText(chunk) {
|
|
64
|
+
var _a, _b, _c, _d, _e;
|
|
65
|
+
const maxLen = 140;
|
|
66
|
+
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 : [];
|
|
67
|
+
let preview = (_c = lines[0]) !== null && _c !== void 0 ? _c : "";
|
|
68
|
+
if (!preview && ((_d = chunk.defined_symbols) === null || _d === void 0 ? void 0 : _d.length)) {
|
|
69
|
+
preview = (_e = chunk.defined_symbols[0]) !== null && _e !== void 0 ? _e : "";
|
|
70
|
+
}
|
|
71
|
+
if (preview.length > maxLen) {
|
|
72
|
+
preview = `${preview.slice(0, maxLen)}...`;
|
|
73
|
+
}
|
|
74
|
+
return preview;
|
|
75
|
+
}
|
|
76
|
+
function toCompactHits(data) {
|
|
77
|
+
return data.map((chunk) => {
|
|
78
|
+
var _a, _b, _c, _d, _e, _f;
|
|
79
|
+
const rawPath = typeof ((_a = chunk.metadata) === null || _a === void 0 ? void 0 : _a.path) === "string"
|
|
80
|
+
? chunk.metadata.path
|
|
81
|
+
: "Unknown path";
|
|
82
|
+
const start = typeof ((_b = chunk.generated_metadata) === null || _b === void 0 ? void 0 : _b.start_line) === "number"
|
|
83
|
+
? chunk.generated_metadata.start_line
|
|
84
|
+
: 0;
|
|
85
|
+
const end = typeof ((_c = chunk.generated_metadata) === null || _c === void 0 ? void 0 : _c.end_line) === "number"
|
|
86
|
+
? chunk.generated_metadata.end_line
|
|
87
|
+
: 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);
|
|
88
|
+
return {
|
|
89
|
+
path: rawPath,
|
|
90
|
+
range: `${start + 1}-${end + 1}`,
|
|
91
|
+
start_line: start,
|
|
92
|
+
end_line: end,
|
|
93
|
+
role: chunk.role,
|
|
94
|
+
confidence: chunk.confidence,
|
|
95
|
+
score: chunk.score,
|
|
96
|
+
defined: Array.isArray(chunk.defined_symbols)
|
|
97
|
+
? chunk.defined_symbols.slice(0, 3)
|
|
98
|
+
: typeof chunk.defined_symbols === "string"
|
|
99
|
+
? [chunk.defined_symbols]
|
|
100
|
+
: typeof ((_f = chunk.defined_symbols) === null || _f === void 0 ? void 0 : _f.toArray) === "function"
|
|
101
|
+
? chunk.defined_symbols.toArray().slice(0, 3)
|
|
102
|
+
: [],
|
|
103
|
+
preview: getPreviewText(chunk),
|
|
104
|
+
summary: typeof chunk.summary === "string" ? chunk.summary : undefined,
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function compactRole(role) {
|
|
109
|
+
if (!role)
|
|
110
|
+
return "UNK";
|
|
111
|
+
if (role.startsWith("ORCH"))
|
|
112
|
+
return "ORCH";
|
|
113
|
+
if (role.startsWith("DEF"))
|
|
114
|
+
return "DEF";
|
|
115
|
+
if (role.startsWith("IMP"))
|
|
116
|
+
return "IMPL";
|
|
117
|
+
return role.slice(0, 4).toUpperCase();
|
|
118
|
+
}
|
|
119
|
+
function compactConf(conf) {
|
|
120
|
+
if (!conf)
|
|
121
|
+
return "U";
|
|
122
|
+
const c = conf.toUpperCase();
|
|
123
|
+
if (c.startsWith("H"))
|
|
124
|
+
return "H";
|
|
125
|
+
if (c.startsWith("M"))
|
|
126
|
+
return "M";
|
|
127
|
+
if (c.startsWith("L"))
|
|
128
|
+
return "L";
|
|
129
|
+
return "U";
|
|
130
|
+
}
|
|
131
|
+
function compactScore(score) {
|
|
132
|
+
if (typeof score !== "number")
|
|
133
|
+
return "";
|
|
134
|
+
const fixed = score.toFixed(3);
|
|
135
|
+
return fixed
|
|
136
|
+
.replace(/^0\./, ".")
|
|
137
|
+
.replace(/\.?0+$/, (m) => (m.startsWith(".") ? "" : m));
|
|
138
|
+
}
|
|
139
|
+
function truncateEnd(s, max) {
|
|
140
|
+
if (max <= 0)
|
|
141
|
+
return "";
|
|
142
|
+
if (s.length <= max)
|
|
143
|
+
return s;
|
|
144
|
+
if (max <= 3)
|
|
145
|
+
return s.slice(0, max);
|
|
146
|
+
return `${s.slice(0, max - 3)}...`;
|
|
147
|
+
}
|
|
148
|
+
function padR(s, w) {
|
|
149
|
+
const n = Math.max(0, w - s.length);
|
|
150
|
+
return s + " ".repeat(n);
|
|
151
|
+
}
|
|
152
|
+
function padL(s, w) {
|
|
153
|
+
const n = Math.max(0, w - s.length);
|
|
154
|
+
return " ".repeat(n) + s;
|
|
155
|
+
}
|
|
156
|
+
function formatCompactTSV(hits, projectRoot, query) {
|
|
157
|
+
var _a, _b;
|
|
158
|
+
if (!hits.length)
|
|
159
|
+
return "No matches found.";
|
|
160
|
+
const lines = [];
|
|
161
|
+
lines.push(`gmax hits\tquery=${query}\tcount=${hits.length}`);
|
|
162
|
+
lines.push("path\tlines\tscore\trole\tconf\tdefined\tsummary");
|
|
163
|
+
for (const hit of hits) {
|
|
164
|
+
const relPath = path.isAbsolute(hit.path)
|
|
165
|
+
? path.relative(projectRoot, hit.path)
|
|
166
|
+
: hit.path;
|
|
167
|
+
const score = compactScore(hit.score);
|
|
168
|
+
const role = compactRole(hit.role);
|
|
169
|
+
const conf = compactConf(hit.confidence);
|
|
170
|
+
const defs = ((_a = hit.defined) !== null && _a !== void 0 ? _a : []).join(",");
|
|
171
|
+
const summary = (_b = hit.summary) !== null && _b !== void 0 ? _b : "";
|
|
172
|
+
lines.push([relPath, hit.range, score, role, conf, defs, summary].join("\t"));
|
|
173
|
+
}
|
|
174
|
+
return lines.join("\n");
|
|
175
|
+
}
|
|
176
|
+
function formatCompactPretty(hits, projectRoot, query, termWidth, useAnsi) {
|
|
177
|
+
var _a;
|
|
178
|
+
if (!hits.length)
|
|
179
|
+
return "No matches found.";
|
|
180
|
+
const dim = (s) => (useAnsi ? `\x1b[90m${s}\x1b[0m` : s);
|
|
181
|
+
const bold = (s) => (useAnsi ? `\x1b[1m${s}\x1b[0m` : s);
|
|
182
|
+
const wLines = 9;
|
|
183
|
+
const wScore = 6;
|
|
184
|
+
const wRole = 4;
|
|
185
|
+
const wConf = 1;
|
|
186
|
+
const wDef = 20;
|
|
187
|
+
const gutters = 5;
|
|
188
|
+
const fixed = wLines + wScore + wRole + wConf + wDef + gutters;
|
|
189
|
+
const wPath = Math.max(24, Math.min(64, termWidth - fixed));
|
|
190
|
+
const header = `gmax hits count=${hits.length} query="${query}"`;
|
|
191
|
+
const cols = [
|
|
192
|
+
padR("path", wPath),
|
|
193
|
+
padR("lines", wLines),
|
|
194
|
+
padL("score", wScore),
|
|
195
|
+
padR("role", wRole),
|
|
196
|
+
padR("c", wConf),
|
|
197
|
+
padR("defined", wDef),
|
|
198
|
+
].join(" ");
|
|
199
|
+
const out = [];
|
|
200
|
+
out.push(bold(header));
|
|
201
|
+
out.push(dim(cols));
|
|
202
|
+
for (const hit of hits) {
|
|
203
|
+
const relPath = path.isAbsolute(hit.path)
|
|
204
|
+
? path.relative(projectRoot, hit.path)
|
|
205
|
+
: hit.path;
|
|
206
|
+
const score = compactScore(hit.score);
|
|
207
|
+
const role = compactRole(hit.role);
|
|
208
|
+
const conf = compactConf(hit.confidence);
|
|
209
|
+
const defs = ((_a = hit.defined) !== null && _a !== void 0 ? _a : []).join(",") || "-";
|
|
210
|
+
const displayPath = `${relPath}:${hit.start_line + 1}`;
|
|
211
|
+
const paddedPath = padR(displayPath, wPath);
|
|
212
|
+
const row = [
|
|
213
|
+
paddedPath,
|
|
214
|
+
padR(hit.range, wLines),
|
|
215
|
+
padL(score || "", wScore),
|
|
216
|
+
padR(role, wRole),
|
|
217
|
+
padR(conf, wConf),
|
|
218
|
+
padR(truncateEnd(defs, wDef), wDef),
|
|
219
|
+
].join(" ");
|
|
220
|
+
out.push(row);
|
|
221
|
+
}
|
|
222
|
+
return out.join("\n");
|
|
223
|
+
}
|
|
224
|
+
function formatCompactTable(hits, projectRoot, query, opts) {
|
|
225
|
+
var _a;
|
|
226
|
+
if (!hits.length)
|
|
227
|
+
return "No matches found.";
|
|
228
|
+
if (!opts.isTTY || opts.plain) {
|
|
229
|
+
return formatCompactTSV(hits, projectRoot, query);
|
|
230
|
+
}
|
|
231
|
+
const termWidth = Math.max(80, (_a = process.stdout.columns) !== null && _a !== void 0 ? _a : 120);
|
|
232
|
+
return formatCompactPretty(hits, projectRoot, query, termWidth, true);
|
|
233
|
+
}
|
|
234
|
+
function resultCountHeader(results, maxCount) {
|
|
235
|
+
var _a, _b, _c;
|
|
236
|
+
const files = new Set();
|
|
237
|
+
for (const r of results) {
|
|
238
|
+
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 : "";
|
|
239
|
+
if (p)
|
|
240
|
+
files.add(p);
|
|
241
|
+
}
|
|
242
|
+
const showing = results.length < maxCount ? `${results.length}` : `top ${results.length}`;
|
|
243
|
+
return `Found ${results.length} match${results.length === 1 ? "" : "es"} (showing ${showing}) across ${files.size} file${files.size === 1 ? "" : "s"}`;
|
|
244
|
+
}
|
package/package.json
CHANGED