token-goat 2.9.19 → 2.9.21
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/README.md +3 -1
- package/dist/{token-goat-chunk-JNIFSVWM.mjs → token-goat-chunk-2ZHD3XCD.mjs} +5 -1
- package/dist/{token-goat-chunk-P46RTOAQ.mjs → token-goat-chunk-4IIU3GNS.mjs} +10 -7
- package/dist/{token-goat-chunk-2GTB5RBZ.mjs → token-goat-chunk-4V4OZHHV.mjs} +11 -271
- package/dist/token-goat-chunk-64OEF3UN.mjs +128 -0
- package/dist/{token-goat-chunk-AVRD7SBO.mjs → token-goat-chunk-6AQLZMCO.mjs} +270 -29
- package/dist/{token-goat-chunk-LACH3WKS.mjs → token-goat-chunk-BIEDTF6V.mjs} +3 -3
- package/dist/{token-goat-chunk-PIAESKVU.mjs → token-goat-chunk-BKHJRFDE.mjs} +568 -429
- package/dist/token-goat-chunk-CAHN4QU7.mjs +26 -0
- package/dist/{token-goat-chunk-MU6I4IDI.mjs → token-goat-chunk-CMAJGP3E.mjs} +11 -7
- package/dist/token-goat-chunk-CMHBTXMY.mjs +41 -0
- package/dist/{token-goat-chunk-HPMMLV37.mjs → token-goat-chunk-CZ5ZFJSN.mjs} +256 -341
- package/dist/{token-goat-chunk-7DGTVBWP.mjs → token-goat-chunk-DDP64XR7.mjs} +159 -1863
- package/dist/{token-goat-chunk-FX5DHKGF.mjs → token-goat-chunk-DISVHOW6.mjs} +4 -4
- package/dist/{token-goat-chunk-L2UOJBV4.mjs → token-goat-chunk-FZN77SZD.mjs} +27 -19
- package/dist/{token-goat-chunk-DA6TIDLI.mjs → token-goat-chunk-GO7OWONJ.mjs} +18 -13
- package/dist/{token-goat-chunk-EP7TCWHM.mjs → token-goat-chunk-IAMIQLCV.mjs} +83 -66
- package/dist/{token-goat-chunk-NJKNAC37.mjs → token-goat-chunk-IJUHQX2M.mjs} +1 -1
- package/dist/token-goat-chunk-KQI24O4B.mjs +292 -0
- package/dist/{token-goat-chunk-GYC34EGE.mjs → token-goat-chunk-KRPJIXCT.mjs} +2 -2
- package/dist/token-goat-chunk-KVAXTA2W.mjs +198 -0
- package/dist/{token-goat-chunk-FJZ5MZK7.mjs → token-goat-chunk-LK3YOKDF.mjs} +2 -2
- package/dist/token-goat-chunk-M43UJVYQ.mjs +1816 -0
- package/dist/{token-goat-chunk-SOKAPOOC.mjs → token-goat-chunk-M6CDVASA.mjs} +46 -47
- package/dist/token-goat-chunk-MECDAPXB.mjs +1989 -0
- package/dist/token-goat-chunk-MEKVJZUN.mjs +324 -0
- package/dist/token-goat-chunk-MQACN7VG.mjs +1379 -0
- package/dist/{token-goat-chunk-3W5P673V.mjs → token-goat-chunk-MZQORUX5.mjs} +1 -1
- package/dist/{token-goat-chunk-DHIXE6GV.mjs → token-goat-chunk-ORRDWKLA.mjs} +1 -1
- package/dist/{token-goat-chunk-F24NE3FO.mjs → token-goat-chunk-PCR43MCM.mjs} +2 -2
- package/dist/token-goat-chunk-PDYQA3AP.mjs +248 -0
- package/dist/{token-goat-chunk-S7RFIX4Y.mjs → token-goat-chunk-PHDNWISV.mjs} +45 -14
- package/dist/token-goat-chunk-PPYZS7TI.mjs +304 -0
- package/dist/{token-goat-chunk-BTKDZW7F.mjs → token-goat-chunk-QTIRVK3M.mjs} +1 -1
- package/dist/{token-goat-chunk-62VJ47WN.mjs → token-goat-chunk-QUM3UNWS.mjs} +5 -5
- package/dist/{token-goat-chunk-KWM6KBPA.mjs → token-goat-chunk-SHV6QQAS.mjs} +1 -1
- package/dist/{token-goat-chunk-FQYMZASI.mjs → token-goat-chunk-SMUYPBF5.mjs} +796 -4464
- package/dist/{token-goat-chunk-ZGQXRYKE.mjs → token-goat-chunk-TGBSMHPM.mjs} +1 -1
- package/dist/{token-goat-chunk-EXLLLIC3.mjs → token-goat-chunk-VXKT3W4C.mjs} +3 -3
- package/dist/{token-goat-chunk-WKO5TVNA.mjs → token-goat-chunk-XJUPKJF5.mjs} +544 -576
- package/dist/{token-goat-chunk-IBTFGZBX.mjs → token-goat-chunk-XQSSPX3X.mjs} +2 -2
- package/dist/{token-goat-chunk-VJQBYSXG.mjs → token-goat-chunk-ZJWPJL7O.mjs} +3 -3
- package/dist/token-goat-hook.mjs +17 -11
- package/dist/token-goat.core.mjs +27 -19
- package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
- package/docs/cli.md +13 -12
- package/docs/install.md +1 -1
- package/docs/security.md +2 -2
- package/package.json +3 -2
- package/dist/token-goat-chunk-NYFYIRG3.mjs +0 -35
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
isTextHeavy,
|
|
6
6
|
ocrImage,
|
|
7
7
|
ocrIntegrityFailed
|
|
8
|
-
} from "./token-goat-chunk-
|
|
8
|
+
} from "./token-goat-chunk-PCR43MCM.mjs";
|
|
9
9
|
import {
|
|
10
10
|
formatSqliteQueryTable,
|
|
11
11
|
formatSqliteSchema,
|
|
@@ -20,10 +20,8 @@ import {
|
|
|
20
20
|
NOTEBOOK_CELL_LINES_SUFFIX,
|
|
21
21
|
SKIP_DIRS,
|
|
22
22
|
canShrinkFormat,
|
|
23
|
-
capJsonRows,
|
|
24
23
|
emptyIndexMessage,
|
|
25
24
|
enqueueDirtyPathSafe,
|
|
26
|
-
estimateTokens,
|
|
27
25
|
fenceUntrusted,
|
|
28
26
|
formatSymbolLocation,
|
|
29
27
|
getEmbeddingCoverage,
|
|
@@ -36,16 +34,22 @@ import {
|
|
|
36
34
|
isVirtualIndexedPath,
|
|
37
35
|
parseIpv6Groups,
|
|
38
36
|
probeImageMeta,
|
|
37
|
+
recordKnownRootThrottled,
|
|
39
38
|
resolveLineRegions,
|
|
40
39
|
scanAndRecord,
|
|
41
40
|
searchEvidenceSemantically,
|
|
42
41
|
shrinkImage,
|
|
43
|
-
trimToBudget,
|
|
44
42
|
urlPolicyDenialReason,
|
|
45
43
|
virtualIndexedScopeNote,
|
|
46
44
|
walkProject
|
|
47
|
-
} from "./token-goat-chunk-
|
|
45
|
+
} from "./token-goat-chunk-SMUYPBF5.mjs";
|
|
46
|
+
import {
|
|
47
|
+
capJsonRows,
|
|
48
|
+
estimateTokens,
|
|
49
|
+
trimToBudget
|
|
50
|
+
} from "./token-goat-chunk-MEKVJZUN.mjs";
|
|
48
51
|
import {
|
|
52
|
+
BYTES_PER_TOKEN,
|
|
49
53
|
colorStdout,
|
|
50
54
|
isBlobStale,
|
|
51
55
|
loadBlob,
|
|
@@ -53,8 +57,8 @@ import {
|
|
|
53
57
|
redactSecrets,
|
|
54
58
|
savedTokensFromBytes,
|
|
55
59
|
storeBlob,
|
|
56
|
-
|
|
57
|
-
} from "./token-goat-chunk-
|
|
60
|
+
stripAnsiEscapes
|
|
61
|
+
} from "./token-goat-chunk-PHDNWISV.mjs";
|
|
58
62
|
import {
|
|
59
63
|
extractPdfMeta,
|
|
60
64
|
extractPdfOutline,
|
|
@@ -68,7 +72,7 @@ import {
|
|
|
68
72
|
parseWhereSpecs,
|
|
69
73
|
profileCsv,
|
|
70
74
|
queryCsv
|
|
71
|
-
} from "./token-goat-chunk-
|
|
75
|
+
} from "./token-goat-chunk-SHV6QQAS.mjs";
|
|
72
76
|
import {
|
|
73
77
|
MAX_ZIP_INPUT_BYTES,
|
|
74
78
|
MAX_ZIP_OUTPUT_BYTES,
|
|
@@ -103,7 +107,7 @@ import {
|
|
|
103
107
|
extractSolidity,
|
|
104
108
|
extractThrift,
|
|
105
109
|
stripLeadingAttributes
|
|
106
|
-
} from "./token-goat-chunk-
|
|
110
|
+
} from "./token-goat-chunk-IJUHQX2M.mjs";
|
|
107
111
|
import {
|
|
108
112
|
MAX_OVER_FETCH,
|
|
109
113
|
OVER_FETCH_FACTOR,
|
|
@@ -117,7 +121,7 @@ import {
|
|
|
117
121
|
mergeNearbyHits,
|
|
118
122
|
readSection,
|
|
119
123
|
searchSemantic
|
|
120
|
-
} from "./token-goat-chunk-
|
|
124
|
+
} from "./token-goat-chunk-IAMIQLCV.mjs";
|
|
121
125
|
import {
|
|
122
126
|
DEFAULT_QUERY_LIMIT,
|
|
123
127
|
countRefs,
|
|
@@ -130,7 +134,7 @@ import {
|
|
|
130
134
|
queryRefsByContext,
|
|
131
135
|
querySymbols,
|
|
132
136
|
searchSymbolsFts
|
|
133
|
-
} from "./token-goat-chunk-
|
|
137
|
+
} from "./token-goat-chunk-XQSSPX3X.mjs";
|
|
134
138
|
import {
|
|
135
139
|
FILENAME_LANGUAGE,
|
|
136
140
|
TREE_SITTER_LANGUAGES,
|
|
@@ -149,7 +153,7 @@ import {
|
|
|
149
153
|
partialRefsReason,
|
|
150
154
|
redactIfDotenv,
|
|
151
155
|
unsupportedLanguageName
|
|
152
|
-
} from "./token-goat-chunk-
|
|
156
|
+
} from "./token-goat-chunk-2ZHD3XCD.mjs";
|
|
153
157
|
import {
|
|
154
158
|
fileIsAbsent,
|
|
155
159
|
findProject,
|
|
@@ -159,7 +163,7 @@ import {
|
|
|
159
163
|
loadConfig,
|
|
160
164
|
resolveProjectRoot,
|
|
161
165
|
shortFingerprint
|
|
162
|
-
} from "./token-goat-chunk-
|
|
166
|
+
} from "./token-goat-chunk-M6CDVASA.mjs";
|
|
163
167
|
import {
|
|
164
168
|
registerReset
|
|
165
169
|
} from "./token-goat-chunk-EEIDFMEM.mjs";
|
|
@@ -169,6 +173,7 @@ import {
|
|
|
169
173
|
atomicWriteBytes,
|
|
170
174
|
compileGrepMatcher,
|
|
171
175
|
countNoun,
|
|
176
|
+
dataDir,
|
|
172
177
|
decodeSource,
|
|
173
178
|
ensureNewline,
|
|
174
179
|
escapeRegExp,
|
|
@@ -191,7 +196,7 @@ import {
|
|
|
191
196
|
supportRequestLine,
|
|
192
197
|
windowsCmdQuoteArg,
|
|
193
198
|
withExtension
|
|
194
|
-
} from "./token-goat-chunk-
|
|
199
|
+
} from "./token-goat-chunk-TGBSMHPM.mjs";
|
|
195
200
|
import {
|
|
196
201
|
UNTRUSTED_FILE_TAG,
|
|
197
202
|
UNTRUSTED_GITHUB_TAG,
|
|
@@ -881,6 +886,20 @@ function renderContextWindow(displayFile, matchLine, window, matchSuffix = "", i
|
|
|
881
886
|
);
|
|
882
887
|
}
|
|
883
888
|
|
|
889
|
+
// src/emit.ts
|
|
890
|
+
init_define_import_meta_env();
|
|
891
|
+
function emit(text) {
|
|
892
|
+
const payload = colorStdout() ? text : stripAnsiEscapes(text);
|
|
893
|
+
process.stdout.write(ensureNewline(payload));
|
|
894
|
+
}
|
|
895
|
+
function emitErr(text) {
|
|
896
|
+
process.stderr.write(ensureNewline(text));
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
// src/query_limits.ts
|
|
900
|
+
init_define_import_meta_env();
|
|
901
|
+
var UNBOUNDED_QUERY_LIMIT = -1;
|
|
902
|
+
|
|
884
903
|
// src/ref_blindness.ts
|
|
885
904
|
init_define_import_meta_env();
|
|
886
905
|
var REF_INDEXED_LANGUAGES = /* @__PURE__ */ new Set([
|
|
@@ -935,8 +954,8 @@ import { randomUUID } from "node:crypto";
|
|
|
935
954
|
// src/graph_traversal.ts
|
|
936
955
|
init_define_import_meta_env();
|
|
937
956
|
var DEFAULT_REF_QUERY_LIMIT = 500;
|
|
938
|
-
var ALL_SYMBOLS_IN_FILE_LIMIT =
|
|
939
|
-
var UNBOUNDED_REF_LIMIT =
|
|
957
|
+
var ALL_SYMBOLS_IN_FILE_LIMIT = UNBOUNDED_QUERY_LIMIT;
|
|
958
|
+
var UNBOUNDED_REF_LIMIT = UNBOUNDED_QUERY_LIMIT;
|
|
940
959
|
function enclosingSymbol(symbols, line) {
|
|
941
960
|
let best = null;
|
|
942
961
|
for (const s of symbols) {
|
|
@@ -1276,13 +1295,6 @@ function findCyclesCapped(graph) {
|
|
|
1276
1295
|
init_define_import_meta_env();
|
|
1277
1296
|
import * as fs from "node:fs";
|
|
1278
1297
|
import * as path2 from "node:path";
|
|
1279
|
-
function emit(text) {
|
|
1280
|
-
const payload = colorStdout() ? text : stripAnsi(text);
|
|
1281
|
-
process.stdout.write(ensureNewline(payload));
|
|
1282
|
-
}
|
|
1283
|
-
function emitErr(text) {
|
|
1284
|
-
process.stderr.write(ensureNewline(text));
|
|
1285
|
-
}
|
|
1286
1298
|
function runDead(opts) {
|
|
1287
1299
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
1288
1300
|
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
@@ -1950,21 +1962,14 @@ function renderModules(result, top) {
|
|
|
1950
1962
|
}
|
|
1951
1963
|
|
|
1952
1964
|
// src/graph_analysis.ts
|
|
1953
|
-
function emit2(text) {
|
|
1954
|
-
const payload = colorStdout() ? text : stripAnsi(text);
|
|
1955
|
-
process.stdout.write(ensureNewline(payload));
|
|
1956
|
-
}
|
|
1957
|
-
function emitErr2(text) {
|
|
1958
|
-
process.stderr.write(ensureNewline(text));
|
|
1959
|
-
}
|
|
1960
1965
|
function runSimilar(opts) {
|
|
1961
1966
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
1962
|
-
|
|
1967
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
1963
1968
|
return 1;
|
|
1964
1969
|
}
|
|
1965
1970
|
const sepIdx = opts.spec.lastIndexOf("::");
|
|
1966
1971
|
if (sepIdx < 0) {
|
|
1967
|
-
|
|
1972
|
+
emitErr(`Invalid spec - expected "file::symbol", got: ${opts.spec}`);
|
|
1968
1973
|
return 1;
|
|
1969
1974
|
}
|
|
1970
1975
|
const top = opts.top ?? 10;
|
|
@@ -1977,18 +1982,18 @@ function runSimilar(opts) {
|
|
|
1977
1982
|
const matches = hits.filter((h) => !(h.filePath === anchor.filePath && h.name === anchor.name));
|
|
1978
1983
|
const results = matches.slice(0, top);
|
|
1979
1984
|
if (matches.length > results.length) {
|
|
1980
|
-
|
|
1985
|
+
emitErr(`Showing top ${results.length} of ${matches.length} similar symbols (raise --top to see the rest).`);
|
|
1981
1986
|
}
|
|
1982
1987
|
if (opts.json === true) {
|
|
1983
|
-
|
|
1988
|
+
emit(displaySafeJson(results.map((h) => ({ name: h.name, kind: h.kind, file: h.filePath, line: h.lineStart }))));
|
|
1984
1989
|
return 0;
|
|
1985
1990
|
}
|
|
1986
|
-
for (const h of results)
|
|
1991
|
+
for (const h of results) emit(`${displaySafeText(h.name)} ${displaySafeText(h.kind)} ${formatSymbolLocation(displaySafeText(toDisplayPath(rootDir, h.filePath)), h.lineStart)}`);
|
|
1987
1992
|
return 0;
|
|
1988
1993
|
}
|
|
1989
1994
|
function runContextFor(opts) {
|
|
1990
1995
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
1991
|
-
|
|
1996
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
1992
1997
|
return 1;
|
|
1993
1998
|
}
|
|
1994
1999
|
const top = opts.top ?? 12;
|
|
@@ -1998,7 +2003,7 @@ function runContextFor(opts) {
|
|
|
1998
2003
|
const moreBeyondTop = fetched.length > top;
|
|
1999
2004
|
const hits = fetched.slice(0, top);
|
|
2000
2005
|
if (hits.length === 0) {
|
|
2001
|
-
|
|
2006
|
+
emitErr(`No matches found for '${opts.task}'`);
|
|
2002
2007
|
return 1;
|
|
2003
2008
|
}
|
|
2004
2009
|
const entries = [];
|
|
@@ -2017,19 +2022,19 @@ function runContextFor(opts) {
|
|
|
2017
2022
|
);
|
|
2018
2023
|
}
|
|
2019
2024
|
if (moreBeyondTop) notices.push(`More matches exist beyond --top ${top} (raise it to see them).`);
|
|
2020
|
-
for (const n of notices)
|
|
2025
|
+
for (const n of notices) emitErr(n);
|
|
2021
2026
|
if (opts.json === true) {
|
|
2022
|
-
|
|
2027
|
+
emit(displaySafeJson(entries));
|
|
2023
2028
|
return 0;
|
|
2024
2029
|
}
|
|
2025
|
-
for (const e of entries)
|
|
2030
|
+
for (const e of entries) emit(`token-goat read "${displaySafeText(toDisplayPath(rootDir, e.file))}::${displaySafeText(e.symbol)}@${e.line}"`);
|
|
2026
2031
|
return 0;
|
|
2027
2032
|
}
|
|
2028
2033
|
function runTestFor(opts) {
|
|
2029
2034
|
const filePath = resolveIndexPath(opts.file);
|
|
2030
2035
|
const symbols = querySymbols({ filePath, limit: ALL_SYMBOLS_IN_FILE_LIMIT });
|
|
2031
2036
|
if (!fs3.existsSync(opts.file) && symbols.length === 0) {
|
|
2032
|
-
|
|
2037
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
2033
2038
|
return 1;
|
|
2034
2039
|
}
|
|
2035
2040
|
const rootDir = resolveProjectRoot({ project: process.cwd() });
|
|
@@ -2054,22 +2059,22 @@ function runTestFor(opts) {
|
|
|
2054
2059
|
}
|
|
2055
2060
|
if (opts.json === true) {
|
|
2056
2061
|
const capped = guardJsonRows(results.map((r) => ({ ...r, testFile: toDisplayPath(rootDir, r.testFile) })));
|
|
2057
|
-
|
|
2062
|
+
emit(displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount }));
|
|
2058
2063
|
return 0;
|
|
2059
2064
|
}
|
|
2060
2065
|
if (results.length === 0) {
|
|
2061
|
-
|
|
2066
|
+
emit(`No test files found referencing symbols in '${displaySafeText(opts.file)}'`);
|
|
2062
2067
|
return 0;
|
|
2063
2068
|
}
|
|
2064
2069
|
for (const r of results) {
|
|
2065
|
-
|
|
2066
|
-
for (const fn of r.testFunctions)
|
|
2070
|
+
emit(toDisplayPath(rootDir, r.testFile));
|
|
2071
|
+
for (const fn of r.testFunctions) emit(` ${fn}`);
|
|
2067
2072
|
}
|
|
2068
2073
|
return 0;
|
|
2069
2074
|
}
|
|
2070
2075
|
function runCoverageGaps(opts) {
|
|
2071
2076
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
2072
|
-
|
|
2077
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
2073
2078
|
return 1;
|
|
2074
2079
|
}
|
|
2075
2080
|
const top = opts.top ?? 50;
|
|
@@ -2087,30 +2092,30 @@ function runCoverageGaps(opts) {
|
|
|
2087
2092
|
}
|
|
2088
2093
|
const sliced = gaps.slice(0, top);
|
|
2089
2094
|
if (gaps.length > sliced.length) {
|
|
2090
|
-
|
|
2095
|
+
emitErr(`Showing top ${sliced.length} of ${gaps.length} coverage gaps (raise --top to see the rest).`);
|
|
2091
2096
|
}
|
|
2092
2097
|
if (opts.json === true) {
|
|
2093
|
-
|
|
2098
|
+
emit(displaySafeJson(sliced));
|
|
2094
2099
|
return 0;
|
|
2095
2100
|
}
|
|
2096
2101
|
if (sliced.length === 0) {
|
|
2097
|
-
|
|
2098
|
-
if (isIndexEmptyForProject(globalDbPath(), rootDir))
|
|
2102
|
+
emit("No coverage gaps found.");
|
|
2103
|
+
if (isIndexEmptyForProject(globalDbPath(), rootDir)) emit(emptyIndexMessage(rootDir));
|
|
2099
2104
|
return 0;
|
|
2100
2105
|
}
|
|
2101
|
-
for (const g of sliced)
|
|
2106
|
+
for (const g of sliced) emit(`${displaySafeText(g.name)} ${displaySafeText(g.kind)} ${displaySafeText(toDisplayPath(rootDir, g.file))}:${g.line}`);
|
|
2102
2107
|
return 0;
|
|
2103
2108
|
}
|
|
2104
2109
|
function runArch(opts) {
|
|
2105
2110
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
2106
|
-
|
|
2111
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
2107
2112
|
return 1;
|
|
2108
2113
|
}
|
|
2109
2114
|
const cwd = opts.cwd ?? process.cwd();
|
|
2110
2115
|
const top = opts.top ?? 10;
|
|
2111
2116
|
const { files, graph, importedBy, resolve: resolve8 } = buildImportGraph(cwd);
|
|
2112
2117
|
if (files.length === 0 && opts.json !== true) {
|
|
2113
|
-
|
|
2118
|
+
emit(`no tracked files found under '${toDisplayPath(getDisplayRoot(cwd), cwd)}' (is it a git repo?). Nothing to analyse.`);
|
|
2114
2119
|
return 0;
|
|
2115
2120
|
}
|
|
2116
2121
|
const allHubs = [...importedBy.entries()].sort((a, b) => b[1].size - a[1].size).map(([f, importers]) => ({ file: f, importedBy: importers.size }));
|
|
@@ -2123,22 +2128,22 @@ function runArch(opts) {
|
|
|
2123
2128
|
const moduleResult = opts.modules === true ? detectModules({ files, graph, importedBy, resolve: resolve8 }, cwd, top) : null;
|
|
2124
2129
|
if (opts.json === true) {
|
|
2125
2130
|
const modulePayload = moduleResult === null ? {} : { modules: moduleResult.modules, modulesTotal: moduleResult.modulesTotal, modulesTruncated: moduleResult.modules.length < moduleResult.modulesTotal, modularity: moduleResult.modularity, isolatedCount: moduleResult.isolatedCount, crossImports: moduleResult.crossImports, crossImportsTotal: moduleResult.crossImportsTotal, crossImportsTruncated: moduleResult.crossImports.length < moduleResult.crossImportsTotal, noImportEdges: moduleResult.noEdges };
|
|
2126
|
-
|
|
2131
|
+
emit(displaySafeJson({ hubs, hubsTotal, hubsTruncated: hubs.length < hubsTotal, entryPoints, entryPointsTotal, entryPointsTruncated: entryPoints.length < entryPointsTotal, cycles, ...cyclesTruncated ? { cyclesTruncated: true } : {}, ...modulePayload }));
|
|
2127
2132
|
return 0;
|
|
2128
2133
|
}
|
|
2129
|
-
|
|
2130
|
-
for (const h of hubs)
|
|
2131
|
-
|
|
2132
|
-
for (const e of entryPoints)
|
|
2133
|
-
|
|
2134
|
-
for (const c of cycles)
|
|
2135
|
-
if (moduleResult !== null) for (const line of renderModules(moduleResult, top))
|
|
2134
|
+
emit(hubs.length < hubsTotal ? `hubs (top ${hubs.length} of ${hubsTotal} most-imported):` : `hubs (${hubsTotal} most-imported):`);
|
|
2135
|
+
for (const h of hubs) emit(` ${h.importedBy} importers ${displaySafeText(toDisplayPath(getDisplayRoot(opts.cwd), h.file))}`);
|
|
2136
|
+
emit(entryPoints.length < entryPointsTotal ? `entry points (imported by nobody, top ${entryPoints.length} of ${entryPointsTotal}):` : `entry points (imported by nobody, ${entryPointsTotal} found):`);
|
|
2137
|
+
for (const e of entryPoints) emit(` ${displaySafeText(toDisplayPath(getDisplayRoot(opts.cwd), e.file))}`);
|
|
2138
|
+
emit(cyclesTruncated ? `cycles (first ${cycles.length}, truncated at the ${MAX_CYCLES}-cycle enumeration limit: more cycles exist):` : `cycles (${cycles.length} found):`);
|
|
2139
|
+
for (const c of cycles) emit(` ${c.map((f) => toDisplayPath(getDisplayRoot(opts.cwd), f)).join(" -> ")}`);
|
|
2140
|
+
if (moduleResult !== null) for (const line of renderModules(moduleResult, top)) emit(line);
|
|
2136
2141
|
return 0;
|
|
2137
2142
|
}
|
|
2138
2143
|
function runBlame(opts) {
|
|
2139
2144
|
const sepIdx = opts.spec.lastIndexOf("::");
|
|
2140
2145
|
if (sepIdx < 0) {
|
|
2141
|
-
|
|
2146
|
+
emitErr(`Invalid spec - expected "file::symbol", got: ${displaySafeText(opts.spec)}`);
|
|
2142
2147
|
return 1;
|
|
2143
2148
|
}
|
|
2144
2149
|
const cwd = opts.cwd ?? process.cwd();
|
|
@@ -2151,12 +2156,12 @@ function runBlame(opts) {
|
|
|
2151
2156
|
try {
|
|
2152
2157
|
const result = runGit(["blame", "-L", `${start},${end}`, "--", filePath], { cwd });
|
|
2153
2158
|
if (result.exitCode !== 0) {
|
|
2154
|
-
|
|
2159
|
+
emitErr(`git blame failed: ${displaySafeText(result.stderr)}`);
|
|
2155
2160
|
return 1;
|
|
2156
2161
|
}
|
|
2157
2162
|
raw = result.stdout;
|
|
2158
2163
|
} catch (e) {
|
|
2159
|
-
|
|
2164
|
+
emitErr(`git blame failed: ${extractErrorMessage(e)}`);
|
|
2160
2165
|
return 1;
|
|
2161
2166
|
}
|
|
2162
2167
|
if (opts.json === true) {
|
|
@@ -2165,32 +2170,25 @@ function runBlame(opts) {
|
|
|
2165
2170
|
if (!m) return { raw: l };
|
|
2166
2171
|
return { commit: m[2], boundary: m[1] === "^", author: (m[3] ?? "").trim(), date: (m[4] ?? "").trim(), line: Number.parseInt(m[5] ?? "0", 10), content: m[6] };
|
|
2167
2172
|
});
|
|
2168
|
-
|
|
2173
|
+
emit(displaySafeJson({ symbol: sym.name, file: filePath, lines }));
|
|
2169
2174
|
return 0;
|
|
2170
2175
|
}
|
|
2171
|
-
|
|
2172
|
-
|
|
2176
|
+
emit(`${displaySafeText(sym.name)} ${displaySafeText(toDisplayPath(getDisplayRoot(opts.cwd), filePath))}:${start}-${end}`);
|
|
2177
|
+
emit(fenceUntrusted(raw.trim(), UNTRUSTED_FILE_TAG));
|
|
2173
2178
|
return 0;
|
|
2174
2179
|
}
|
|
2175
2180
|
|
|
2176
2181
|
// src/graph_commands.ts
|
|
2177
|
-
function emit3(text) {
|
|
2178
|
-
const payload = colorStdout() ? text : stripAnsi(text);
|
|
2179
|
-
process.stdout.write(ensureNewline(payload));
|
|
2180
|
-
}
|
|
2181
|
-
function emitErr3(text) {
|
|
2182
|
-
process.stderr.write(ensureNewline(text));
|
|
2183
|
-
}
|
|
2184
2182
|
function runCallers(opts) {
|
|
2185
2183
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
2186
|
-
|
|
2184
|
+
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
2187
2185
|
return 1;
|
|
2188
2186
|
}
|
|
2189
2187
|
const rootDir = resolveProjectRoot({ project: process.cwd() });
|
|
2190
2188
|
const { name, file } = parseGraphSymbolSpec(opts.symbol);
|
|
2191
2189
|
const fileHint = file !== void 0 ? resolveIndexPath(file, rootDir) : void 0;
|
|
2192
2190
|
if (fileHint !== void 0 && querySymbols({ name, filePath: fileHint, limit: 1 }).length === 0) {
|
|
2193
|
-
|
|
2191
|
+
emitErr(`Symbol '${name}' not found in '${file}'`);
|
|
2194
2192
|
return 1;
|
|
2195
2193
|
}
|
|
2196
2194
|
const unbounded = opts.excludeTests === true || opts.grep !== void 0 || fileHint !== void 0;
|
|
@@ -2207,41 +2205,41 @@ function runCallers(opts) {
|
|
|
2207
2205
|
if (entries.length === 0) {
|
|
2208
2206
|
if (matchesGrep !== void 0 && preGrepCount > 0) {
|
|
2209
2207
|
if (opts.json === true) {
|
|
2210
|
-
|
|
2208
|
+
emit(displaySafeJson({ items: [], truncated: false, totalCount: 0, hiddenByGrep: preGrepCount }));
|
|
2211
2209
|
return 0;
|
|
2212
2210
|
}
|
|
2213
|
-
|
|
2211
|
+
emit(grepFilteredToEmptyNotice(preGrepCount, opts.grep ?? "", "caller", "callers"));
|
|
2214
2212
|
return 0;
|
|
2215
2213
|
}
|
|
2216
2214
|
if (opts.excludeTests === true && suppressed > 0) {
|
|
2217
2215
|
if (opts.json === true) {
|
|
2218
|
-
|
|
2216
|
+
emit(displaySafeJson({ items: [], truncated: false, totalCount: 0, hiddenByExcludeTests: suppressed }));
|
|
2219
2217
|
return 1;
|
|
2220
2218
|
}
|
|
2221
|
-
|
|
2219
|
+
emitErr(`No non-test references found for '${opts.symbol}' (${excludeTestsHiddenNote(suppressed)})`);
|
|
2222
2220
|
return 1;
|
|
2223
2221
|
}
|
|
2224
2222
|
const defRows = querySymbols({ name, rootDir, limit: REF_BLIND_DEF_PROBE_LIMIT });
|
|
2225
2223
|
if (defRows.length === 0) {
|
|
2226
|
-
|
|
2227
|
-
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir))
|
|
2224
|
+
emitErr(`Symbol not found: ${opts.symbol}${unknownSymbolSuggestion(name, rootDir)}`);
|
|
2225
|
+
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir)) emitErr(emptyIndexMessage(rootDir));
|
|
2228
2226
|
return 1;
|
|
2229
2227
|
}
|
|
2230
2228
|
const defPaths = fileHint !== void 0 ? [fileHint] : defRows.map((r) => r.filePath);
|
|
2231
2229
|
const firstDefPath = defPaths[0];
|
|
2232
2230
|
if (firstDefPath !== void 0 && defPaths.every((fp) => !isRefIndexedFile(fp))) {
|
|
2233
|
-
|
|
2231
|
+
emitErr(refBlindLanguageNotice(name, detectLanguageOfFile(firstDefPath), toDisplayPath(rootDir, firstDefPath)));
|
|
2234
2232
|
return 1;
|
|
2235
2233
|
}
|
|
2236
2234
|
const kindRows = fileHint !== void 0 ? querySymbols({ name, filePath: fileHint, limit: REF_BLIND_DEF_PROBE_LIMIT }) : defRows;
|
|
2237
2235
|
const kindVerdict = refBlindKindVerdict(kindRows);
|
|
2238
2236
|
if (kindVerdict.allBlind) {
|
|
2239
|
-
|
|
2237
|
+
emitErr(refBlindKindNotice(name, kindVerdict.blindKinds));
|
|
2240
2238
|
return 1;
|
|
2241
2239
|
}
|
|
2242
|
-
|
|
2243
|
-
if (kindVerdict.blindCount > 0)
|
|
2244
|
-
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir))
|
|
2240
|
+
emitErr(`No references found for '${opts.symbol}'`);
|
|
2241
|
+
if (kindVerdict.blindCount > 0) emitErr(refBlindKindPartialNote(name, kindVerdict.blindKinds, kindVerdict.blindCount, kindRows.length));
|
|
2242
|
+
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir)) emitErr(emptyIndexMessage(rootDir));
|
|
2245
2243
|
return 1;
|
|
2246
2244
|
}
|
|
2247
2245
|
const contextLines = opts.context ?? 0;
|
|
@@ -2254,7 +2252,7 @@ function runCallers(opts) {
|
|
|
2254
2252
|
const capped = guardJsonRows(rows);
|
|
2255
2253
|
const limitTruncated = entries.length < filtered.length || sqlTruncated;
|
|
2256
2254
|
const hiddenByGrep = preGrepCount - filtered.length;
|
|
2257
|
-
|
|
2255
|
+
emit(displaySafeJson({
|
|
2258
2256
|
items: capped.items,
|
|
2259
2257
|
truncated: capped.truncated || limitTruncated,
|
|
2260
2258
|
totalCount: filtered.length,
|
|
@@ -2264,24 +2262,24 @@ function runCallers(opts) {
|
|
|
2264
2262
|
return 0;
|
|
2265
2263
|
}
|
|
2266
2264
|
if (opts.excludeTests === true && suppressed > 0) {
|
|
2267
|
-
|
|
2265
|
+
emit(`${countNoun(entries.length, "caller")} found (${excludeTestsHiddenNote(suppressed)})`);
|
|
2268
2266
|
}
|
|
2269
2267
|
const overflowed = sqlTruncated || entries.length < filtered.length;
|
|
2270
2268
|
if (overflowed) {
|
|
2271
2269
|
const totalCallers = sqlTruncated ? countRefs({ name, rootDir }) : filtered.length;
|
|
2272
|
-
|
|
2270
|
+
emitErr(`Showing the first ${entries.length} of ${countNoun(totalCallers, "caller")} (raise --limit to see the rest).`);
|
|
2273
2271
|
}
|
|
2274
2272
|
for (const e of entries) {
|
|
2275
2273
|
const displayPath = toDisplayPath(rootDir, e.file);
|
|
2276
|
-
|
|
2274
|
+
emit(`${e.caller} ${displayPath}:${e.line}`);
|
|
2277
2275
|
const window = buildContextWindow(e.file, e.line, contextLines);
|
|
2278
|
-
if (window !== null) for (const l of renderContextWindow(displayPath, e.line, window, "", " "))
|
|
2276
|
+
if (window !== null) for (const l of renderContextWindow(displayPath, e.line, window, "", " ")) emit(l);
|
|
2279
2277
|
}
|
|
2280
2278
|
return 0;
|
|
2281
2279
|
}
|
|
2282
2280
|
function runCallChain(opts) {
|
|
2283
2281
|
if (opts.depth !== void 0 && opts.depth <= 0) {
|
|
2284
|
-
|
|
2282
|
+
emitErr(`--depth must be a positive number, got: ${opts.depth}`);
|
|
2285
2283
|
return 1;
|
|
2286
2284
|
}
|
|
2287
2285
|
const maxDepth = opts.depth ?? 8;
|
|
@@ -2290,13 +2288,13 @@ function runCallChain(opts) {
|
|
|
2290
2288
|
const fileHint = file !== void 0 ? resolveIndexPath(file, rootDir) : void 0;
|
|
2291
2289
|
if (fileHint !== void 0) {
|
|
2292
2290
|
if (querySymbols({ name, filePath: fileHint, limit: 1 }).length === 0) {
|
|
2293
|
-
|
|
2294
|
-
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir))
|
|
2291
|
+
emitErr(`Symbol '${name}' not found in '${file}'`);
|
|
2292
|
+
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir)) emitErr(emptyIndexMessage(rootDir));
|
|
2295
2293
|
return 1;
|
|
2296
2294
|
}
|
|
2297
2295
|
} else if (querySymbols({ name, rootDir, limit: 1 }).length === 0) {
|
|
2298
|
-
|
|
2299
|
-
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir))
|
|
2296
|
+
emitErr(`Symbol not found: ${opts.symbol}${unknownSymbolSuggestion(name, rootDir)}`);
|
|
2297
|
+
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir)) emitErr(emptyIndexMessage(rootDir));
|
|
2300
2298
|
return 1;
|
|
2301
2299
|
}
|
|
2302
2300
|
const refBlindRootPath = () => {
|
|
@@ -2334,7 +2332,7 @@ function runCallChain(opts) {
|
|
|
2334
2332
|
const refBlindKinds = noCallers ? refBlindRootKinds().blindKinds : [];
|
|
2335
2333
|
const blindRootPath = noCallers ? refBlindRootPath() : void 0;
|
|
2336
2334
|
const refBlindLanguage = blindRootPath !== void 0 ? { language: detectLanguageOfFile(blindRootPath), definedIn: toDisplayPath(rootDir, blindRootPath) } : void 0;
|
|
2337
|
-
|
|
2335
|
+
emit(displaySafeJson({
|
|
2338
2336
|
chains: filteredChains,
|
|
2339
2337
|
...hiddenByGrep > 0 ? { hiddenByGrep } : {},
|
|
2340
2338
|
...hiddenByExcludeTests > 0 ? { hiddenByExcludeTests } : {},
|
|
@@ -2345,37 +2343,37 @@ function runCallChain(opts) {
|
|
|
2345
2343
|
}
|
|
2346
2344
|
if (noCallers) {
|
|
2347
2345
|
if (opts.excludeTests === true && suppressedCount > 0) {
|
|
2348
|
-
|
|
2346
|
+
emit(`${name} (no non-test callers; ${excludeTestsHiddenNote(suppressedCount)})`);
|
|
2349
2347
|
return 0;
|
|
2350
2348
|
}
|
|
2351
2349
|
const blindRoot = refBlindRootPath();
|
|
2352
2350
|
if (blindRoot !== void 0) {
|
|
2353
|
-
|
|
2354
|
-
|
|
2351
|
+
emitErr(refBlindLanguageNotice(name, detectLanguageOfFile(blindRoot), toDisplayPath(rootDir, blindRoot)));
|
|
2352
|
+
emit(`${name} (no callers recorded)`);
|
|
2355
2353
|
return 0;
|
|
2356
2354
|
}
|
|
2357
2355
|
const rootKinds = refBlindRootKinds();
|
|
2358
2356
|
if (rootKinds.allBlind) {
|
|
2359
|
-
|
|
2360
|
-
|
|
2357
|
+
emitErr(refBlindKindNotice(name, rootKinds.blindKinds));
|
|
2358
|
+
emit(`${name} (no callers recorded)`);
|
|
2361
2359
|
return 0;
|
|
2362
2360
|
}
|
|
2363
|
-
|
|
2364
|
-
if (rootKinds.blindCount > 0)
|
|
2361
|
+
emit(`${name} (no callers)`);
|
|
2362
|
+
if (rootKinds.blindCount > 0) emitErr(refBlindKindPartialNote(name, rootKinds.blindKinds, rootKinds.blindCount, rootKinds.total));
|
|
2365
2363
|
return 0;
|
|
2366
2364
|
}
|
|
2367
2365
|
if (matchesGrep !== void 0 && filteredChains.length === 0) {
|
|
2368
|
-
|
|
2366
|
+
emit(grepFilteredToEmptyNotice(chains.length, opts.grep, "chain", "chains"));
|
|
2369
2367
|
return 0;
|
|
2370
2368
|
}
|
|
2371
2369
|
for (const chain of filteredChains) {
|
|
2372
|
-
|
|
2370
|
+
emit(chain.join(" -> "));
|
|
2373
2371
|
}
|
|
2374
2372
|
return 0;
|
|
2375
2373
|
}
|
|
2376
2374
|
function runImpact(opts) {
|
|
2377
2375
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
2378
|
-
|
|
2376
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
2379
2377
|
return 1;
|
|
2380
2378
|
}
|
|
2381
2379
|
const top = opts.top ?? 20;
|
|
@@ -2384,7 +2382,7 @@ function runImpact(opts) {
|
|
|
2384
2382
|
const { name: rootName, file } = parseGraphSymbolSpec(opts.symbol);
|
|
2385
2383
|
const fileHint = file !== void 0 ? resolveIndexPath(file, rootDir) : void 0;
|
|
2386
2384
|
if (fileHint !== void 0 && querySymbols({ name: rootName, filePath: fileHint, limit: 1 }).length === 0) {
|
|
2387
|
-
|
|
2385
|
+
emitErr(`Symbol '${rootName}' not found in '${file}'`);
|
|
2388
2386
|
return 1;
|
|
2389
2387
|
}
|
|
2390
2388
|
const getSyms = buildFileSymCache();
|
|
@@ -2429,64 +2427,64 @@ function runImpact(opts) {
|
|
|
2429
2427
|
const grepped = matchesGrep !== void 0 ? allSorted.filter(([symbol]) => matchesGrep(symbol)) : allSorted;
|
|
2430
2428
|
const sorted = grepped.slice(0, top);
|
|
2431
2429
|
if (depthCapped > 0) {
|
|
2432
|
-
|
|
2430
|
+
emitErr(`Impact truncated at the ${DEPTH_CAP}-hop depth limit: ${depthCapped} symbol${depthCapped === 1 ? "" : "s"} at that depth ${depthCapped === 1 ? "was" : "were"} not expanded, so callers reachable only beyond ${DEPTH_CAP} hops are missing.`);
|
|
2433
2431
|
}
|
|
2434
2432
|
if (grepped.length > sorted.length) {
|
|
2435
|
-
|
|
2433
|
+
emitErr(`Showing top ${sorted.length} of ${grepped.length} impacted symbols (raise --top to see the rest).`);
|
|
2436
2434
|
}
|
|
2437
2435
|
if (matchesGrep !== void 0 && sorted.length === 0 && allSorted.length > 0) {
|
|
2438
2436
|
if (opts.json === true) {
|
|
2439
|
-
|
|
2440
|
-
|
|
2437
|
+
emitErr(grepFilteredToEmptyNotice(allSorted.length, opts.grep, "impacted symbol", "impacted symbols"));
|
|
2438
|
+
emit(displaySafeJson([]));
|
|
2441
2439
|
return 0;
|
|
2442
2440
|
}
|
|
2443
|
-
|
|
2441
|
+
emit(grepFilteredToEmptyNotice(allSorted.length, opts.grep, "impacted symbol", "impacted symbols"));
|
|
2444
2442
|
return 0;
|
|
2445
2443
|
}
|
|
2446
2444
|
if (sorted.length === 0) {
|
|
2447
2445
|
if (opts.excludeTests === true && suppressedCount > 0) {
|
|
2448
2446
|
if (opts.json === true) {
|
|
2449
|
-
|
|
2447
|
+
emit(displaySafeJson([]));
|
|
2450
2448
|
return 1;
|
|
2451
2449
|
}
|
|
2452
|
-
|
|
2450
|
+
emitErr(`No non-test impact found for '${opts.symbol}' (${excludeTestsHiddenNote(suppressedCount)})`);
|
|
2453
2451
|
return 1;
|
|
2454
2452
|
}
|
|
2455
2453
|
const defRows = querySymbols({ name: rootName, rootDir, limit: REF_BLIND_DEF_PROBE_LIMIT });
|
|
2456
2454
|
if (defRows.length === 0) {
|
|
2457
|
-
|
|
2455
|
+
emitErr(`Symbol not found: ${opts.symbol}${unknownSymbolSuggestion(rootName, rootDir)}`);
|
|
2458
2456
|
return 1;
|
|
2459
2457
|
}
|
|
2460
2458
|
const defPaths = fileHint !== void 0 ? [fileHint] : defRows.map((r) => r.filePath);
|
|
2461
2459
|
const firstDefPath = defPaths[0];
|
|
2462
2460
|
if (firstDefPath !== void 0 && defPaths.every((fp) => !isRefIndexedFile(fp))) {
|
|
2463
|
-
|
|
2461
|
+
emitErr(refBlindLanguageNotice(rootName, detectLanguageOfFile(firstDefPath), toDisplayPath(rootDir, firstDefPath)));
|
|
2464
2462
|
return 1;
|
|
2465
2463
|
}
|
|
2466
2464
|
const kindRows = fileHint !== void 0 ? querySymbols({ name: rootName, filePath: fileHint, limit: REF_BLIND_DEF_PROBE_LIMIT }) : defRows;
|
|
2467
2465
|
const kindVerdict = refBlindKindVerdict(kindRows);
|
|
2468
2466
|
if (kindVerdict.allBlind) {
|
|
2469
|
-
|
|
2467
|
+
emitErr(refBlindKindNotice(rootName, kindVerdict.blindKinds));
|
|
2470
2468
|
return 1;
|
|
2471
2469
|
}
|
|
2472
|
-
|
|
2473
|
-
if (kindVerdict.blindCount > 0)
|
|
2470
|
+
emitErr(`No callers found for '${opts.symbol}'`);
|
|
2471
|
+
if (kindVerdict.blindCount > 0) emitErr(refBlindKindPartialNote(rootName, kindVerdict.blindKinds, kindVerdict.blindCount, kindRows.length));
|
|
2474
2472
|
return 1;
|
|
2475
2473
|
}
|
|
2476
2474
|
if (opts.json === true) {
|
|
2477
|
-
|
|
2475
|
+
emit(displaySafeJson(sorted.map(([symbol, h]) => ({ symbol, hops: h }))));
|
|
2478
2476
|
return 0;
|
|
2479
2477
|
}
|
|
2480
2478
|
const MODULE_SCOPE_PREFIX = "(module scope) ";
|
|
2481
2479
|
for (const [symbol, h] of sorted) {
|
|
2482
2480
|
const displaySymbol = symbol.startsWith(MODULE_SCOPE_PREFIX) ? MODULE_SCOPE_PREFIX + toDisplayPath(rootDir, symbol.slice(MODULE_SCOPE_PREFIX.length)) : symbol;
|
|
2483
|
-
|
|
2481
|
+
emit(`${displaySymbol} (hops: ${h})`);
|
|
2484
2482
|
}
|
|
2485
2483
|
return 0;
|
|
2486
2484
|
}
|
|
2487
2485
|
function runAsk(opts) {
|
|
2488
2486
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
2489
|
-
|
|
2487
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
2490
2488
|
return 1;
|
|
2491
2489
|
}
|
|
2492
2490
|
const top = opts.top ?? 8;
|
|
@@ -2495,7 +2493,7 @@ function runAsk(opts) {
|
|
|
2495
2493
|
const moreBeyondTop = fetched.length > top;
|
|
2496
2494
|
const hits = fetched.slice(0, top);
|
|
2497
2495
|
if (moreBeyondTop) {
|
|
2498
|
-
|
|
2496
|
+
emitErr(`Answer is grounded in the top ${countNoun(top, "match", "matches")}; more matched (raise --top to widen the evidence).`);
|
|
2499
2497
|
}
|
|
2500
2498
|
warnIfFilesStale(hits.map((h) => h.filePath));
|
|
2501
2499
|
const BACKEND_ENV = "TOKEN_GOAT_ASK_BACKEND";
|
|
@@ -2503,12 +2501,12 @@ function runAsk(opts) {
|
|
|
2503
2501
|
const entries = hits.map((h) => ({ file: h.filePath, symbol: h.name, kind: h.kind, line: h.lineStart, readCmd: `token-goat read "${h.filePath}::${h.name}@${h.lineStart}"` }));
|
|
2504
2502
|
const degrade = (reason, extraNote) => {
|
|
2505
2503
|
if (opts.json === true) {
|
|
2506
|
-
|
|
2504
|
+
emit(displaySafeJson({ degraded: true, note: reason, ...extraNote !== void 0 ? { hint: extraNote } : {}, context: entries }));
|
|
2507
2505
|
return 0;
|
|
2508
2506
|
}
|
|
2509
|
-
|
|
2510
|
-
if (extraNote !== void 0)
|
|
2511
|
-
for (const e of entries)
|
|
2507
|
+
emit(`[degraded mode - ${reason}]`);
|
|
2508
|
+
if (extraNote !== void 0) emit(extraNote);
|
|
2509
|
+
for (const e of entries) emit(`token-goat read "${displaySafeText(toDisplayPath(rootDir, e.file))}::${displaySafeText(e.symbol)}@${e.line}"`);
|
|
2512
2510
|
return 0;
|
|
2513
2511
|
};
|
|
2514
2512
|
if (!backendLabel) return degrade(`set ${BACKEND_ENV}=claude|codex for LLM synthesis`);
|
|
@@ -2555,9 +2553,9 @@ ANSWER:`;
|
|
|
2555
2553
|
}
|
|
2556
2554
|
if (answer) {
|
|
2557
2555
|
if (opts.json === true) {
|
|
2558
|
-
|
|
2556
|
+
emit(displaySafeJson({ answer, context: entries }));
|
|
2559
2557
|
} else {
|
|
2560
|
-
|
|
2558
|
+
emit(answer);
|
|
2561
2559
|
}
|
|
2562
2560
|
return 0;
|
|
2563
2561
|
}
|
|
@@ -3054,6 +3052,17 @@ async function takeScreenshot(url, destPath, opts) {
|
|
|
3054
3052
|
return { path: finalPath, originalBytes: buffer.length, finalBytes: finalBuffer.length };
|
|
3055
3053
|
}
|
|
3056
3054
|
|
|
3055
|
+
// src/symbol_scan.ts
|
|
3056
|
+
init_define_import_meta_env();
|
|
3057
|
+
var SYMBOL_SCAN_PAGE = 1e4;
|
|
3058
|
+
function forEachSymbol(queryOpts, visit) {
|
|
3059
|
+
for (let offset = 0; ; offset += SYMBOL_SCAN_PAGE) {
|
|
3060
|
+
const rows = querySymbols({ ...queryOpts, limit: SYMBOL_SCAN_PAGE, offset });
|
|
3061
|
+
for (const row of rows) visit(row);
|
|
3062
|
+
if (rows.length < SYMBOL_SCAN_PAGE) return;
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3057
3066
|
// src/ts_refs.ts
|
|
3058
3067
|
init_define_import_meta_env();
|
|
3059
3068
|
import { createRequire } from "node:module";
|
|
@@ -7376,7 +7385,7 @@ function fenceHtmlText(text) {
|
|
|
7376
7385
|
function runCsvQuery(opts) {
|
|
7377
7386
|
const text = readFileText(opts.file);
|
|
7378
7387
|
if (text === null) {
|
|
7379
|
-
|
|
7388
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7380
7389
|
return 1;
|
|
7381
7390
|
}
|
|
7382
7391
|
const columns = opts.columns ? opts.columns.split(",").map((c) => c.trim()).filter(Boolean) : void 0;
|
|
@@ -7384,7 +7393,7 @@ function runCsvQuery(opts) {
|
|
|
7384
7393
|
try {
|
|
7385
7394
|
head = opts.head !== void 0 ? requireNonNegativeStrictInt("--head", opts.head) : void 0;
|
|
7386
7395
|
} catch (e) {
|
|
7387
|
-
|
|
7396
|
+
emitErr(extractErrorMessage(e));
|
|
7388
7397
|
return 1;
|
|
7389
7398
|
}
|
|
7390
7399
|
try {
|
|
@@ -7397,7 +7406,7 @@ function runCsvQuery(opts) {
|
|
|
7397
7406
|
...opts.noHeader === true ? { noHeader: true } : {}
|
|
7398
7407
|
});
|
|
7399
7408
|
if (result.header.length === 0) {
|
|
7400
|
-
|
|
7409
|
+
emit(`No data rows found in ${displaySafeText(opts.file)}`);
|
|
7401
7410
|
return 0;
|
|
7402
7411
|
}
|
|
7403
7412
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
@@ -7406,23 +7415,23 @@ function runCsvQuery(opts) {
|
|
|
7406
7415
|
const headTruncated = result.rows.length < result.totalRows;
|
|
7407
7416
|
const capped = guardJsonRows(rowsJson);
|
|
7408
7417
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated || headTruncated, totalCount: result.totalRows, ...result.totalRows === 0 && result.preFilterRows > 0 ? { filteredFromRows: result.preFilterRows } : {} }, 0);
|
|
7409
|
-
|
|
7418
|
+
emit(jsonText);
|
|
7410
7419
|
recordReadStat("csv_query", fullSourceBytes, jsonText, opts.file);
|
|
7411
7420
|
} else {
|
|
7412
7421
|
const tableText = formatCsvTable(result, (opts.where ?? []).map((w) => `--where ${w}`));
|
|
7413
|
-
|
|
7422
|
+
emit(tableText);
|
|
7414
7423
|
recordReadStat("csv_query", fullSourceBytes, tableText, opts.file);
|
|
7415
7424
|
}
|
|
7416
7425
|
return 0;
|
|
7417
7426
|
} catch (e) {
|
|
7418
|
-
|
|
7427
|
+
emitErr(extractErrorMessage(e));
|
|
7419
7428
|
return 1;
|
|
7420
7429
|
}
|
|
7421
7430
|
}
|
|
7422
7431
|
function runCsvProfile(opts) {
|
|
7423
7432
|
const text = readFileText(opts.file);
|
|
7424
7433
|
if (text === null) {
|
|
7425
|
-
|
|
7434
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7426
7435
|
return 1;
|
|
7427
7436
|
}
|
|
7428
7437
|
try {
|
|
@@ -7431,41 +7440,41 @@ function runCsvProfile(opts) {
|
|
|
7431
7440
|
...opts.noHeader === true ? { noHeader: true } : {}
|
|
7432
7441
|
});
|
|
7433
7442
|
if (profiles.length === 0) {
|
|
7434
|
-
|
|
7443
|
+
emit(`No data rows found in ${displaySafeText(opts.file)}`);
|
|
7435
7444
|
return 0;
|
|
7436
7445
|
}
|
|
7437
7446
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
7438
7447
|
const profileText = formatCsvProfile(profiles);
|
|
7439
|
-
|
|
7448
|
+
emit(profileText);
|
|
7440
7449
|
recordReadStat("csv_profile", fullSourceBytes, profileText, opts.file);
|
|
7441
7450
|
return 0;
|
|
7442
7451
|
} catch (e) {
|
|
7443
|
-
|
|
7452
|
+
emitErr(extractErrorMessage(e));
|
|
7444
7453
|
return 1;
|
|
7445
7454
|
}
|
|
7446
7455
|
}
|
|
7447
7456
|
function runOutlineCommand(opts, parse, formatLabel, kind) {
|
|
7448
7457
|
const text = readFileText(opts.file);
|
|
7449
7458
|
if (text === null) {
|
|
7450
|
-
|
|
7459
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7451
7460
|
return 1;
|
|
7452
7461
|
}
|
|
7453
7462
|
let data;
|
|
7454
7463
|
try {
|
|
7455
7464
|
data = parse(text);
|
|
7456
7465
|
} catch {
|
|
7457
|
-
|
|
7466
|
+
emitErr(`Failed to parse ${formatLabel}: ${opts.file}`);
|
|
7458
7467
|
return 1;
|
|
7459
7468
|
}
|
|
7460
7469
|
const outline = outlineJson(data);
|
|
7461
7470
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
7462
7471
|
if (opts.json === true) {
|
|
7463
7472
|
const jsonText = displaySafeJson(outline, 0);
|
|
7464
|
-
|
|
7473
|
+
emit(jsonText);
|
|
7465
7474
|
recordReadStat(kind, fullSourceBytes, jsonText, opts.file);
|
|
7466
7475
|
} else {
|
|
7467
7476
|
const text2 = formatJsonOutline(outline);
|
|
7468
|
-
|
|
7477
|
+
emit(text2);
|
|
7469
7478
|
recordReadStat(kind, fullSourceBytes, text2, opts.file);
|
|
7470
7479
|
}
|
|
7471
7480
|
return 0;
|
|
@@ -7476,21 +7485,21 @@ function runJsonOutline(opts) {
|
|
|
7476
7485
|
function runQueryCommand(opts, parse, formatLabel, guardTag, kind) {
|
|
7477
7486
|
const text = readFileText(opts.file);
|
|
7478
7487
|
if (text === null) {
|
|
7479
|
-
|
|
7488
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7480
7489
|
return 1;
|
|
7481
7490
|
}
|
|
7482
7491
|
let data;
|
|
7483
7492
|
try {
|
|
7484
7493
|
data = parse(text);
|
|
7485
7494
|
} catch {
|
|
7486
|
-
|
|
7495
|
+
emitErr(`Failed to parse ${formatLabel}: ${opts.file}`);
|
|
7487
7496
|
return 1;
|
|
7488
7497
|
}
|
|
7489
7498
|
let head;
|
|
7490
7499
|
try {
|
|
7491
7500
|
head = opts.head !== void 0 ? requireNonNegativeStrictInt("--head", opts.head) : void 0;
|
|
7492
7501
|
} catch (e) {
|
|
7493
|
-
|
|
7502
|
+
emitErr(extractErrorMessage(e));
|
|
7494
7503
|
return 1;
|
|
7495
7504
|
}
|
|
7496
7505
|
try {
|
|
@@ -7499,7 +7508,7 @@ function runQueryCommand(opts, parse, formatLabel, guardTag, kind) {
|
|
|
7499
7508
|
if (!result.fanned) {
|
|
7500
7509
|
const value = result.items[0];
|
|
7501
7510
|
const valueText = opts.json === true ? displaySafeJson(value, 0) : displaySafeJson(value);
|
|
7502
|
-
|
|
7511
|
+
emit(valueText);
|
|
7503
7512
|
recordReadStat(kind, fullSourceBytes, valueText, opts.file);
|
|
7504
7513
|
return 0;
|
|
7505
7514
|
}
|
|
@@ -7509,7 +7518,7 @@ function runQueryCommand(opts, parse, formatLabel, guardTag, kind) {
|
|
|
7509
7518
|
if (opts.json === true) {
|
|
7510
7519
|
const capped = guardJsonRows(limited);
|
|
7511
7520
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated || headTruncated || result.truncated, totalCount }, 0);
|
|
7512
|
-
|
|
7521
|
+
emit(jsonText);
|
|
7513
7522
|
recordReadStat(kind, fullSourceBytes, jsonText, opts.file);
|
|
7514
7523
|
} else {
|
|
7515
7524
|
const lines = limited.map((item) => displaySafeJson(item, 0));
|
|
@@ -7525,7 +7534,7 @@ function runQueryCommand(opts, parse, formatLabel, guardTag, kind) {
|
|
|
7525
7534
|
}
|
|
7526
7535
|
return 0;
|
|
7527
7536
|
} catch (e) {
|
|
7528
|
-
|
|
7537
|
+
emitErr(extractErrorMessage(e));
|
|
7529
7538
|
return 1;
|
|
7530
7539
|
}
|
|
7531
7540
|
}
|
|
@@ -7567,21 +7576,21 @@ function runYamlQuery(opts) {
|
|
|
7567
7576
|
function runXmlOutline(opts) {
|
|
7568
7577
|
const text = readFileText(opts.file);
|
|
7569
7578
|
if (text === null) {
|
|
7570
|
-
|
|
7579
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7571
7580
|
return 1;
|
|
7572
7581
|
}
|
|
7573
7582
|
let summary;
|
|
7574
7583
|
try {
|
|
7575
7584
|
summary = outlineXml(text, { ...opts.maxDepth !== void 0 ? { maxDepth: opts.maxDepth } : {} });
|
|
7576
7585
|
} catch (e) {
|
|
7577
|
-
|
|
7586
|
+
emitErr(`Failed to parse XML: ${opts.file}
|
|
7578
7587
|
${extractErrorMessage(e)}`);
|
|
7579
7588
|
return 1;
|
|
7580
7589
|
}
|
|
7581
7590
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
7582
7591
|
if (opts.json === true) {
|
|
7583
7592
|
const jsonText = displaySafeJson(summary);
|
|
7584
|
-
|
|
7593
|
+
emit(jsonText);
|
|
7585
7594
|
recordReadStat("xml_outline", fullSourceBytes, jsonText, opts.file);
|
|
7586
7595
|
} else {
|
|
7587
7596
|
const outlineText = formatXmlOutline(summary);
|
|
@@ -7593,19 +7602,19 @@ ${extractErrorMessage(e)}`);
|
|
|
7593
7602
|
function runXmlQuery(opts) {
|
|
7594
7603
|
const text = readFileText(opts.file);
|
|
7595
7604
|
if (text === null) {
|
|
7596
|
-
|
|
7605
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7597
7606
|
return 1;
|
|
7598
7607
|
}
|
|
7599
7608
|
const queryPath = (opts.xpath ?? opts.path ?? "").trim();
|
|
7600
7609
|
if (!queryPath) {
|
|
7601
|
-
|
|
7610
|
+
emitErr("Must provide a path or --xpath <expression>");
|
|
7602
7611
|
return 1;
|
|
7603
7612
|
}
|
|
7604
7613
|
let head;
|
|
7605
7614
|
try {
|
|
7606
7615
|
head = opts.head !== void 0 ? requireNonNegativeStrictInt("--head", opts.head) : void 0;
|
|
7607
7616
|
} catch (e) {
|
|
7608
|
-
|
|
7617
|
+
emitErr(extractErrorMessage(e));
|
|
7609
7618
|
return 1;
|
|
7610
7619
|
}
|
|
7611
7620
|
try {
|
|
@@ -7615,10 +7624,10 @@ function runXmlQuery(opts) {
|
|
|
7615
7624
|
if (result.attributeValues.length === 0) {
|
|
7616
7625
|
if (opts.json === true) {
|
|
7617
7626
|
const jsonText = displaySafeJson({ items: [], truncated: false, totalCount: 0 }, 0);
|
|
7618
|
-
|
|
7627
|
+
emit(jsonText);
|
|
7619
7628
|
recordReadStat("xml_query", fullSourceBytes, jsonText, opts.file);
|
|
7620
7629
|
} else {
|
|
7621
|
-
|
|
7630
|
+
emit(`No attributes matched path: '${displaySafeText(queryPath)}'`);
|
|
7622
7631
|
}
|
|
7623
7632
|
return 0;
|
|
7624
7633
|
}
|
|
@@ -7650,7 +7659,7 @@ ${val}`;
|
|
|
7650
7659
|
outText = val;
|
|
7651
7660
|
}
|
|
7652
7661
|
}
|
|
7653
|
-
|
|
7662
|
+
emit(outText);
|
|
7654
7663
|
recordReadStat("xml_query", fullSourceBytes, outText, opts.file);
|
|
7655
7664
|
return 0;
|
|
7656
7665
|
}
|
|
@@ -7680,7 +7689,7 @@ ${val}`;
|
|
|
7680
7689
|
{ items: capped.items, truncated: capped.truncated || headTruncated2, totalCount: totalCount2 },
|
|
7681
7690
|
0
|
|
7682
7691
|
);
|
|
7683
|
-
|
|
7692
|
+
emit(jsonText);
|
|
7684
7693
|
recordReadStat("xml_query", fullSourceBytes, jsonText, opts.file);
|
|
7685
7694
|
} else {
|
|
7686
7695
|
const lines = [];
|
|
@@ -7710,10 +7719,10 @@ ${val}`);
|
|
|
7710
7719
|
if (result.items.length === 0) {
|
|
7711
7720
|
if (opts.json === true) {
|
|
7712
7721
|
const jsonText = displaySafeJson({ items: [], truncated: false, totalCount: 0 }, 0);
|
|
7713
|
-
|
|
7722
|
+
emit(jsonText);
|
|
7714
7723
|
recordReadStat("xml_query", fullSourceBytes, jsonText, opts.file);
|
|
7715
7724
|
} else {
|
|
7716
|
-
|
|
7725
|
+
emit(`No elements matched path: '${displaySafeText(queryPath)}'`);
|
|
7717
7726
|
}
|
|
7718
7727
|
return 0;
|
|
7719
7728
|
}
|
|
@@ -7725,7 +7734,7 @@ ${val}`);
|
|
|
7725
7734
|
...opts.decodeEmbeddedXml ? { decodeEmbedded: true } : {}
|
|
7726
7735
|
});
|
|
7727
7736
|
const jsonText = displaySafeJson(jsonVal);
|
|
7728
|
-
|
|
7737
|
+
emit(jsonText);
|
|
7729
7738
|
recordReadStat("xml_query", fullSourceBytes, jsonText, opts.file);
|
|
7730
7739
|
} else {
|
|
7731
7740
|
let xmlText = serializeXmlNode(
|
|
@@ -7757,7 +7766,7 @@ ${xmlText}`;
|
|
|
7757
7766
|
{ items: capped.items, truncated: capped.truncated || headTruncated, totalCount },
|
|
7758
7767
|
0
|
|
7759
7768
|
);
|
|
7760
|
-
|
|
7769
|
+
emit(jsonText);
|
|
7761
7770
|
recordReadStat("xml_query", fullSourceBytes, jsonText, opts.file);
|
|
7762
7771
|
} else {
|
|
7763
7772
|
const blocks = limited.map((node) => {
|
|
@@ -7781,21 +7790,21 @@ ${block}`;
|
|
|
7781
7790
|
}
|
|
7782
7791
|
return 0;
|
|
7783
7792
|
} catch (e) {
|
|
7784
|
-
|
|
7793
|
+
emitErr(extractErrorMessage(e));
|
|
7785
7794
|
return 1;
|
|
7786
7795
|
}
|
|
7787
7796
|
}
|
|
7788
7797
|
function runHtmlOutline(opts) {
|
|
7789
7798
|
const text = readFileText(opts.file);
|
|
7790
7799
|
if (text === null) {
|
|
7791
|
-
|
|
7800
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7792
7801
|
return 1;
|
|
7793
7802
|
}
|
|
7794
7803
|
const summary = outlineHtml(text);
|
|
7795
7804
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
7796
7805
|
if (opts.json === true) {
|
|
7797
7806
|
const jsonText = displaySafeJson(summary);
|
|
7798
|
-
|
|
7807
|
+
emit(jsonText);
|
|
7799
7808
|
recordReadStat("html_outline", fullSourceBytes, jsonText, opts.file);
|
|
7800
7809
|
} else {
|
|
7801
7810
|
const outlineText = formatHtmlOutline(summary);
|
|
@@ -7807,14 +7816,14 @@ function runHtmlOutline(opts) {
|
|
|
7807
7816
|
function runHtmlQuery(opts) {
|
|
7808
7817
|
const text = readFileText(opts.file);
|
|
7809
7818
|
if (text === null) {
|
|
7810
|
-
|
|
7819
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7811
7820
|
return 1;
|
|
7812
7821
|
}
|
|
7813
7822
|
let head;
|
|
7814
7823
|
try {
|
|
7815
7824
|
head = opts.head !== void 0 ? requireNonNegativeStrictInt("--head", opts.head) : void 0;
|
|
7816
7825
|
} catch (e) {
|
|
7817
|
-
|
|
7826
|
+
emitErr(extractErrorMessage(e));
|
|
7818
7827
|
return 1;
|
|
7819
7828
|
}
|
|
7820
7829
|
try {
|
|
@@ -7825,10 +7834,10 @@ function runHtmlQuery(opts) {
|
|
|
7825
7834
|
if (result.attributeValues.length === 0) {
|
|
7826
7835
|
if (opts.json === true) {
|
|
7827
7836
|
const jsonText = displaySafeJson({ items: [], truncated: false, totalCount: 0 }, 0);
|
|
7828
|
-
|
|
7837
|
+
emit(jsonText);
|
|
7829
7838
|
recordReadStat("html_query", fullSourceBytes, jsonText, opts.file);
|
|
7830
7839
|
} else {
|
|
7831
|
-
|
|
7840
|
+
emit(`No attributes matched selector: '${displaySafeText(opts.selector)}'`);
|
|
7832
7841
|
}
|
|
7833
7842
|
return 0;
|
|
7834
7843
|
}
|
|
@@ -7838,7 +7847,7 @@ function runHtmlQuery(opts) {
|
|
|
7838
7847
|
if (opts.json === true) {
|
|
7839
7848
|
const capped = guardJsonRows(limited2);
|
|
7840
7849
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated || headTruncated2, totalCount: totalCount2 }, 0);
|
|
7841
|
-
|
|
7850
|
+
emit(jsonText);
|
|
7842
7851
|
recordReadStat("html_query", fullSourceBytes, jsonText, opts.file);
|
|
7843
7852
|
} else {
|
|
7844
7853
|
const lines = limited2.map((item) => item);
|
|
@@ -7854,10 +7863,10 @@ function runHtmlQuery(opts) {
|
|
|
7854
7863
|
if (result.elements.length === 0) {
|
|
7855
7864
|
if (opts.json === true) {
|
|
7856
7865
|
const jsonText = displaySafeJson({ items: [], truncated: false, totalCount: 0 }, 0);
|
|
7857
|
-
|
|
7866
|
+
emit(jsonText);
|
|
7858
7867
|
recordReadStat("html_query", fullSourceBytes, jsonText, opts.file);
|
|
7859
7868
|
} else {
|
|
7860
|
-
|
|
7869
|
+
emit(`No elements matched selector: '${displaySafeText(opts.selector)}'`);
|
|
7861
7870
|
}
|
|
7862
7871
|
return 0;
|
|
7863
7872
|
}
|
|
@@ -7874,7 +7883,7 @@ function runHtmlQuery(opts) {
|
|
|
7874
7883
|
}));
|
|
7875
7884
|
const capped = guardJsonRows(jsonItems);
|
|
7876
7885
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated || headTruncated, totalCount });
|
|
7877
|
-
|
|
7886
|
+
emit(jsonText);
|
|
7878
7887
|
recordReadStat("html_query", fullSourceBytes, jsonText, opts.file);
|
|
7879
7888
|
} else if (opts.text === true) {
|
|
7880
7889
|
const textLines = limited.map((n) => extractNodeText(n, text)).filter(Boolean);
|
|
@@ -7895,24 +7904,24 @@ function runHtmlQuery(opts) {
|
|
|
7895
7904
|
}
|
|
7896
7905
|
return 0;
|
|
7897
7906
|
} catch (e) {
|
|
7898
|
-
|
|
7907
|
+
emitErr(extractErrorMessage(e));
|
|
7899
7908
|
return 1;
|
|
7900
7909
|
}
|
|
7901
7910
|
}
|
|
7902
7911
|
function runHtmlLint(opts) {
|
|
7903
7912
|
const text = readFileText(opts.file);
|
|
7904
7913
|
if (text === null) {
|
|
7905
|
-
|
|
7914
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7906
7915
|
return 1;
|
|
7907
7916
|
}
|
|
7908
7917
|
const report = lintHtml(text);
|
|
7909
7918
|
const isClean = opts.strict ? report.errors.length === 0 && report.warnings.length === 0 : report.errors.length === 0;
|
|
7910
7919
|
if (opts.json === true) {
|
|
7911
|
-
|
|
7920
|
+
emit(displaySafeJson(report));
|
|
7912
7921
|
return isClean ? 0 : 1;
|
|
7913
7922
|
}
|
|
7914
7923
|
if (report.errors.length === 0 && report.warnings.length === 0) {
|
|
7915
|
-
|
|
7924
|
+
emit(`\u2713 ${displaySafeText(opts.file)}: HTML structure is valid (all tags balanced, no duplicate IDs, void elements respected).`);
|
|
7916
7925
|
return 0;
|
|
7917
7926
|
}
|
|
7918
7927
|
const lines = [];
|
|
@@ -7936,20 +7945,20 @@ function runHtmlLint(opts) {
|
|
|
7936
7945
|
lines.push(` <${tag}>: open=${counts.open}, close=${counts.close}, diff=${counts.diff}`);
|
|
7937
7946
|
}
|
|
7938
7947
|
}
|
|
7939
|
-
|
|
7948
|
+
emit(lines.join("\n"));
|
|
7940
7949
|
return isClean ? 0 : 1;
|
|
7941
7950
|
}
|
|
7942
7951
|
function loadOpenApiOperations(file) {
|
|
7943
7952
|
const text = readFileText(file);
|
|
7944
7953
|
if (text === null) {
|
|
7945
|
-
|
|
7954
|
+
emitErr(`Could not read: ${file}`);
|
|
7946
7955
|
return null;
|
|
7947
7956
|
}
|
|
7948
7957
|
let spec;
|
|
7949
7958
|
try {
|
|
7950
7959
|
spec = parseOpenApiSpec(text, file);
|
|
7951
7960
|
} catch {
|
|
7952
|
-
|
|
7961
|
+
emitErr(`Failed to parse OpenAPI spec (not valid JSON or YAML): ${file}`);
|
|
7953
7962
|
return null;
|
|
7954
7963
|
}
|
|
7955
7964
|
return extractOperations(spec);
|
|
@@ -7960,7 +7969,7 @@ function runOpenApiOutline(opts) {
|
|
|
7960
7969
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
7961
7970
|
if (opts.json === true) {
|
|
7962
7971
|
const jsonText = displaySafeJson(operations, 0);
|
|
7963
|
-
|
|
7972
|
+
emit(jsonText);
|
|
7964
7973
|
recordReadStat("openapi_outline", fullSourceBytes, jsonText, opts.file);
|
|
7965
7974
|
} else {
|
|
7966
7975
|
const text = formatOpenApiOutline(operations);
|
|
@@ -7978,13 +7987,13 @@ function runOpenApiOp(opts) {
|
|
|
7978
7987
|
const closes = rankSimilarNames(operations.map(operationLabel), opts.operation);
|
|
7979
7988
|
if (closes.length > 0) messages.push(didYouMean(closes));
|
|
7980
7989
|
else if (operations.length > 0) messages.push(`Try: token-goat openapi-outline ${opts.file}`);
|
|
7981
|
-
|
|
7990
|
+
emitErr(messages.join("\n"));
|
|
7982
7991
|
return 1;
|
|
7983
7992
|
}
|
|
7984
7993
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
7985
7994
|
if (opts.json === true) {
|
|
7986
7995
|
const jsonText = displaySafeJson(match, 0);
|
|
7987
|
-
|
|
7996
|
+
emit(jsonText);
|
|
7988
7997
|
recordReadStat("openapi_op", fullSourceBytes, jsonText, opts.operation);
|
|
7989
7998
|
} else {
|
|
7990
7999
|
const text = formatOperationDetail(match);
|
|
@@ -8003,7 +8012,6 @@ var MIN_WORD_SIMILARITY_LEN = 3;
|
|
|
8003
8012
|
var STRUCTURED_MISS_MAX_BYTES = 128 * 1024;
|
|
8004
8013
|
var STRUCTURED_MISS_MAX_FILES = 12;
|
|
8005
8014
|
var STRUCTURED_MISS_MAX_NODES = 2e4;
|
|
8006
|
-
var FIND_SCAN_LIMIT = 2e4;
|
|
8007
8015
|
function endsWithPathBoundary(full, suffix) {
|
|
8008
8016
|
if (!full.endsWith(suffix)) return false;
|
|
8009
8017
|
if (full.length === suffix.length) return true;
|
|
@@ -8084,8 +8092,9 @@ function didYouMean(candidates) {
|
|
|
8084
8092
|
return lines.join("\n");
|
|
8085
8093
|
}
|
|
8086
8094
|
function unknownSymbolSuggestion(name, rootDir) {
|
|
8087
|
-
const
|
|
8088
|
-
|
|
8095
|
+
const names = /* @__PURE__ */ new Set();
|
|
8096
|
+
forEachSymbol({ rootDir }, (s) => names.add(s.name));
|
|
8097
|
+
const candidates = rankSimilarNames([...names], name);
|
|
8089
8098
|
return candidates.length > 0 ? `
|
|
8090
8099
|
${didYouMean(candidates)}` : "";
|
|
8091
8100
|
}
|
|
@@ -8572,14 +8581,14 @@ ${sub.text}`);
|
|
|
8572
8581
|
}
|
|
8573
8582
|
function runBrief(opts) {
|
|
8574
8583
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
8575
|
-
|
|
8584
|
+
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
8576
8585
|
return 1;
|
|
8577
8586
|
}
|
|
8578
8587
|
const crossFilePairs = parseCrossFileMultiSpec(opts.spec);
|
|
8579
8588
|
if (crossFilePairs !== null) {
|
|
8580
8589
|
const { text: text2, code: code2 } = runBriefCrossFile(crossFilePairs, opts);
|
|
8581
|
-
if (code2 === 0)
|
|
8582
|
-
else
|
|
8590
|
+
if (code2 === 0) emit(text2);
|
|
8591
|
+
else emitErr(text2);
|
|
8583
8592
|
return code2;
|
|
8584
8593
|
}
|
|
8585
8594
|
const { file, symbol } = parseReadSpec(opts.spec);
|
|
@@ -8587,14 +8596,14 @@ function runBrief(opts) {
|
|
|
8587
8596
|
const multiSymbols = symbol.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
8588
8597
|
if (multiSymbols.length > 1) {
|
|
8589
8598
|
const { text: text2, code: code2 } = runBriefMulti(file, multiSymbols, opts);
|
|
8590
|
-
if (code2 === 0)
|
|
8591
|
-
else
|
|
8599
|
+
if (code2 === 0) emit(text2);
|
|
8600
|
+
else emitErr(text2);
|
|
8592
8601
|
return code2;
|
|
8593
8602
|
}
|
|
8594
8603
|
}
|
|
8595
8604
|
const { text, code } = runBriefCore(opts);
|
|
8596
|
-
if (code === 0)
|
|
8597
|
-
else
|
|
8605
|
+
if (code === 0) emit(text);
|
|
8606
|
+
else emitErr(text);
|
|
8598
8607
|
return code;
|
|
8599
8608
|
}
|
|
8600
8609
|
|
|
@@ -8609,7 +8618,7 @@ var OURS_RE = /^<{7}(?:\s+(.*))?$/;
|
|
|
8609
8618
|
var BASE_RE = /^\|{7}(?:\s+(.*))?$/;
|
|
8610
8619
|
var SEP_RE = /^={7}\s*$/;
|
|
8611
8620
|
var THEIRS_RE = /^>{7}(?:\s+(.*))?$/;
|
|
8612
|
-
function parseConflicts(filePath, text) {
|
|
8621
|
+
function parseConflicts(filePath, text, contextLines = 3) {
|
|
8613
8622
|
const lines = text.split(/\r?\n/);
|
|
8614
8623
|
const regions = [];
|
|
8615
8624
|
const warnings = [];
|
|
@@ -8672,13 +8681,29 @@ function parseConflicts(filePath, text) {
|
|
|
8672
8681
|
const theirsMatch = THEIRS_RE.exec(line);
|
|
8673
8682
|
if (theirsMatch !== null) {
|
|
8674
8683
|
const theirsLabel = (theirsMatch[1] ?? "").trim();
|
|
8684
|
+
const beforeContext = [];
|
|
8685
|
+
if (contextLines > 0) {
|
|
8686
|
+
const ctxStart = Math.max(0, startLine - 1 - contextLines);
|
|
8687
|
+
for (let c = ctxStart; c < startLine - 1; c++) {
|
|
8688
|
+
beforeContext.push({ line: c + 1, text: lines[c] ?? "" });
|
|
8689
|
+
}
|
|
8690
|
+
}
|
|
8691
|
+
const afterContext = [];
|
|
8692
|
+
if (contextLines > 0) {
|
|
8693
|
+
const ctxEnd = Math.min(lines.length, lineNo + contextLines);
|
|
8694
|
+
for (let c = lineNo; c < ctxEnd; c++) {
|
|
8695
|
+
afterContext.push({ line: c + 1, text: lines[c] ?? "" });
|
|
8696
|
+
}
|
|
8697
|
+
}
|
|
8675
8698
|
regions.push({
|
|
8676
8699
|
filePath,
|
|
8677
8700
|
lineStart: startLine,
|
|
8678
8701
|
lineEnd: lineNo,
|
|
8679
8702
|
ours: { label: oursLabel, content: oursLines.join("\n") },
|
|
8680
8703
|
base: sawBase ? { label: baseLabel, content: baseLines.join("\n") } : null,
|
|
8681
|
-
theirs: { label: theirsLabel, content: theirsLines.join("\n") }
|
|
8704
|
+
theirs: { label: theirsLabel, content: theirsLines.join("\n") },
|
|
8705
|
+
...beforeContext.length > 0 ? { beforeContext } : {},
|
|
8706
|
+
...afterContext.length > 0 ? { afterContext } : {}
|
|
8682
8707
|
});
|
|
8683
8708
|
resetRegion();
|
|
8684
8709
|
continue;
|
|
@@ -8721,6 +8746,11 @@ function formatSingleFileConflicts(result) {
|
|
|
8721
8746
|
lines.push(`${displaySafeText(result.filePath)} -- ${result.regions.length} conflict${result.regions.length === 1 ? "" : "s"}`);
|
|
8722
8747
|
for (const r of result.regions) {
|
|
8723
8748
|
lines.push(` lines ${r.lineStart}-${r.lineEnd}`);
|
|
8749
|
+
if (r.beforeContext && r.beforeContext.length > 0) {
|
|
8750
|
+
for (const c of r.beforeContext) {
|
|
8751
|
+
lines.push(` ${c.line} | ${displaySafeText(c.text)}`);
|
|
8752
|
+
}
|
|
8753
|
+
}
|
|
8724
8754
|
lines.push(` <<<<<<< ${displaySafeText(r.ours.label || "(ours)")}`);
|
|
8725
8755
|
lines.push(indentBlock(r.ours.content));
|
|
8726
8756
|
if (r.base !== null) {
|
|
@@ -8730,6 +8760,11 @@ function formatSingleFileConflicts(result) {
|
|
|
8730
8760
|
lines.push(" =======");
|
|
8731
8761
|
lines.push(indentBlock(r.theirs.content));
|
|
8732
8762
|
lines.push(` >>>>>>> ${displaySafeText(r.theirs.label || "(theirs)")}`);
|
|
8763
|
+
if (r.afterContext && r.afterContext.length > 0) {
|
|
8764
|
+
for (const c of r.afterContext) {
|
|
8765
|
+
lines.push(` ${c.line} | ${displaySafeText(c.text)}`);
|
|
8766
|
+
}
|
|
8767
|
+
}
|
|
8733
8768
|
}
|
|
8734
8769
|
} else {
|
|
8735
8770
|
lines.push(`${displaySafeText(result.filePath)} -- no conflicts`);
|
|
@@ -8779,23 +8814,24 @@ function runConflicts(opts) {
|
|
|
8779
8814
|
try {
|
|
8780
8815
|
stat = fs8.statSync(abs);
|
|
8781
8816
|
} catch {
|
|
8782
|
-
|
|
8817
|
+
emitErr(`Could not read: ${opts.path}`);
|
|
8783
8818
|
return 1;
|
|
8784
8819
|
}
|
|
8785
8820
|
files = stat.isDirectory() ? walkProject(abs).files : [abs];
|
|
8786
8821
|
}
|
|
8822
|
+
const contextLines = opts.context !== void 0 ? opts.context : 3;
|
|
8787
8823
|
const results = [];
|
|
8788
8824
|
for (const f of files) {
|
|
8789
8825
|
const text = readFileText(f);
|
|
8790
8826
|
if (text === null) continue;
|
|
8791
|
-
const parsed = parseConflicts(f, text);
|
|
8827
|
+
const parsed = parseConflicts(f, text, contextLines);
|
|
8792
8828
|
if (parsed.regions.length > 0 || parsed.warnings.length > 0) results.push(parsed);
|
|
8793
8829
|
}
|
|
8794
8830
|
const fullSourceBytes = sumFileSizes(files);
|
|
8795
8831
|
const detail = opts.path ?? ".";
|
|
8796
8832
|
if (opts.json === true) {
|
|
8797
8833
|
const jsonText = displaySafeJson(opts.summary === true ? results.map(summarizeFileConflicts) : results, 0);
|
|
8798
|
-
|
|
8834
|
+
emit(jsonText);
|
|
8799
8835
|
recordReadStat("conflicts", fullSourceBytes, jsonText, detail);
|
|
8800
8836
|
} else if (opts.summary === true) {
|
|
8801
8837
|
const text = formatConflictSummaries(results.map(summarizeFileConflicts));
|
|
@@ -8873,7 +8909,7 @@ function refIsSafe(ref) {
|
|
|
8873
8909
|
return !ref.startsWith("-");
|
|
8874
8910
|
}
|
|
8875
8911
|
function emitUnsafeRef(ref) {
|
|
8876
|
-
|
|
8912
|
+
emitErr(`Refusing a git ref that starts with '-': ${ref}`);
|
|
8877
8913
|
}
|
|
8878
8914
|
function changedDiffBaselineBytes(cwd, ref, files) {
|
|
8879
8915
|
if (files.length === 0) return 0;
|
|
@@ -8896,25 +8932,25 @@ function runChanged(opts = {}) {
|
|
|
8896
8932
|
try {
|
|
8897
8933
|
const result = runGit(["diff", ref, "--name-only"], { cwd });
|
|
8898
8934
|
if (result.exitCode !== 0) {
|
|
8899
|
-
|
|
8935
|
+
emitErr(`git diff failed: ${result.stderr}`);
|
|
8900
8936
|
const hint = buildChangedRefHint(cwd, ref);
|
|
8901
8937
|
if (hint !== null) {
|
|
8902
|
-
|
|
8938
|
+
emitErr(hint);
|
|
8903
8939
|
}
|
|
8904
8940
|
return 1;
|
|
8905
8941
|
}
|
|
8906
8942
|
changedFiles = result.stdout.trim().split(/\r?\n/).filter(Boolean);
|
|
8907
8943
|
} catch {
|
|
8908
|
-
|
|
8944
|
+
emitErr(`Could not run git diff against '${ref}'`);
|
|
8909
8945
|
return 1;
|
|
8910
8946
|
}
|
|
8911
8947
|
const emptyEnvelope = () => {
|
|
8912
|
-
|
|
8948
|
+
emit(displaySafeJson({ items: [], truncated: false, totalCount: 0 }));
|
|
8913
8949
|
return 0;
|
|
8914
8950
|
};
|
|
8915
8951
|
if (changedFiles.length === 0) {
|
|
8916
8952
|
if (opts.json === true) return emptyEnvelope();
|
|
8917
|
-
|
|
8953
|
+
emit("No files changed.");
|
|
8918
8954
|
return 0;
|
|
8919
8955
|
}
|
|
8920
8956
|
const preGrepFileCount = changedFiles.length;
|
|
@@ -8922,7 +8958,7 @@ function runChanged(opts = {}) {
|
|
|
8922
8958
|
if (matchesGrep !== void 0) changedFiles = changedFiles.filter((f) => matchesGrep(f));
|
|
8923
8959
|
if (matchesGrep !== void 0 && changedFiles.length === 0) {
|
|
8924
8960
|
if (opts.json === true) return emptyEnvelope();
|
|
8925
|
-
|
|
8961
|
+
emit(grepFilteredToEmptyNotice(preGrepFileCount, opts.grep ?? "", "changed file", "changed files"));
|
|
8926
8962
|
return 0;
|
|
8927
8963
|
}
|
|
8928
8964
|
const postGrepFileCount = changedFiles.length;
|
|
@@ -8936,12 +8972,12 @@ function runChanged(opts = {}) {
|
|
|
8936
8972
|
if (opts.json === true) return emptyEnvelope();
|
|
8937
8973
|
const grepRemoved = preGrepFileCount - postGrepFileCount;
|
|
8938
8974
|
if (matchesGrep !== void 0 && grepRemoved > 0) {
|
|
8939
|
-
|
|
8975
|
+
emit(
|
|
8940
8976
|
`No non-test files matched --grep ${opts.grep ?? ""} (${excludeTestsHiddenNote(hiddenTestFiles)}; ${countNoun(grepRemoved, "other changed file")} did not match the filter)`
|
|
8941
8977
|
);
|
|
8942
8978
|
return 0;
|
|
8943
8979
|
}
|
|
8944
|
-
|
|
8980
|
+
emit(`No non-test files changed (${excludeTestsHiddenNote(hiddenTestFiles)})`);
|
|
8945
8981
|
return 0;
|
|
8946
8982
|
}
|
|
8947
8983
|
if (opts.symbolMode === true) {
|
|
@@ -8957,27 +8993,27 @@ function runChanged(opts = {}) {
|
|
|
8957
8993
|
}
|
|
8958
8994
|
const allSymbols = [];
|
|
8959
8995
|
for (const f of changedFiles) {
|
|
8960
|
-
const fileSymbols = querySymbols({ filePath: resolveIndexPath(f, projectRoot), limit:
|
|
8996
|
+
const fileSymbols = querySymbols({ filePath: resolveIndexPath(f, projectRoot), limit: FIND_SCAN_LIMIT });
|
|
8961
8997
|
const hunks = hunksByFile.get(f);
|
|
8962
8998
|
const scoped = hunks === void 0 || isVirtualIndexedPath(f) ? fileSymbols : fileSymbols.filter((s) => hunks.some((h) => h.start <= s.lineEnd && h.end >= s.lineStart));
|
|
8963
8999
|
allSymbols.push(...scoped);
|
|
8964
9000
|
}
|
|
8965
9001
|
if (allSymbols.length === 0) {
|
|
8966
9002
|
if (opts.json === true) return emptyEnvelope();
|
|
8967
|
-
|
|
9003
|
+
emit("No symbols changed.");
|
|
8968
9004
|
return 0;
|
|
8969
9005
|
}
|
|
8970
9006
|
const symbolFullBytes = symbolDiffBaselineBytes;
|
|
8971
9007
|
if (opts.json === true) {
|
|
8972
9008
|
const capped = guardJsonRows(allSymbols);
|
|
8973
9009
|
const text = displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount });
|
|
8974
|
-
|
|
9010
|
+
emit(text);
|
|
8975
9011
|
recordReadStat("changed_lookup", symbolFullBytes, text, ref);
|
|
8976
9012
|
return 0;
|
|
8977
9013
|
}
|
|
8978
9014
|
const symbolText = allSymbols.map((s) => `${s.name} (${s.kind}) \u2014 ${formatSymbolLocation(toDisplayPath(projectRoot, s.filePath), s.lineStart)}`).join("\n");
|
|
8979
9015
|
for (const s of allSymbols) {
|
|
8980
|
-
|
|
9016
|
+
emit(`${displaySafeText(s.name)} (${displaySafeText(s.kind)}) \u2014 ${formatSymbolLocation(displaySafeText(toDisplayPath(projectRoot, s.filePath)), s.lineStart)}`);
|
|
8981
9017
|
}
|
|
8982
9018
|
recordReadStat("changed_lookup", symbolFullBytes, symbolText, ref);
|
|
8983
9019
|
return 0;
|
|
@@ -8986,12 +9022,12 @@ function runChanged(opts = {}) {
|
|
|
8986
9022
|
if (opts.json === true) {
|
|
8987
9023
|
const capped = guardJsonRows(changedFiles);
|
|
8988
9024
|
const text = displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount });
|
|
8989
|
-
|
|
9025
|
+
emit(text);
|
|
8990
9026
|
recordReadStat("changed_lookup", fullBytes, text, ref);
|
|
8991
9027
|
return 0;
|
|
8992
9028
|
}
|
|
8993
9029
|
for (const f of changedFiles) {
|
|
8994
|
-
|
|
9030
|
+
emit(f);
|
|
8995
9031
|
}
|
|
8996
9032
|
recordReadStat("changed_lookup", fullBytes, changedFiles.join("\n"), ref);
|
|
8997
9033
|
return 0;
|
|
@@ -9041,27 +9077,27 @@ function runDiff(opts) {
|
|
|
9041
9077
|
try {
|
|
9042
9078
|
diffResult = runGit(diffArgs, { cwd });
|
|
9043
9079
|
} catch {
|
|
9044
|
-
|
|
9080
|
+
emitErr(`Could not run git diff for '${match.filePath}'`);
|
|
9045
9081
|
return 1;
|
|
9046
9082
|
}
|
|
9047
9083
|
if (diffResult.exitCode !== 0) {
|
|
9048
|
-
|
|
9084
|
+
emitErr(`git diff failed: ${diffResult.stderr}`);
|
|
9049
9085
|
return 1;
|
|
9050
9086
|
}
|
|
9051
9087
|
if (diffResult.stdout.trim() === "") {
|
|
9052
|
-
|
|
9088
|
+
emit(`No changes to '${displaySafeText(match.name)}' in '${displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath))}'.`);
|
|
9053
9089
|
return 0;
|
|
9054
9090
|
}
|
|
9055
9091
|
const { hunks } = splitDiffHunks(diffResult.stdout);
|
|
9056
9092
|
const diffFileScoped = isVirtualIndexedPath(match.filePath);
|
|
9057
9093
|
const overlapping = diffFileScoped ? hunks : hunks.filter((h) => h.start <= match.lineEnd && h.end >= match.lineStart);
|
|
9058
9094
|
if (overlapping.length === 0) {
|
|
9059
|
-
|
|
9095
|
+
emit(`No changes to '${displaySafeText(match.name)}' (lines ${match.lineStart}-${match.lineEnd}) in '${displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath))}'.`);
|
|
9060
9096
|
return 0;
|
|
9061
9097
|
}
|
|
9062
9098
|
if (opts.json === true) {
|
|
9063
9099
|
const capped = guardJsonRows(overlapping.map((h) => ({ start: h.start, end: h.end, text: h.text })));
|
|
9064
|
-
|
|
9100
|
+
emit(
|
|
9065
9101
|
displaySafeJson(
|
|
9066
9102
|
{
|
|
9067
9103
|
symbol: match.name,
|
|
@@ -9078,7 +9114,7 @@ function runDiff(opts) {
|
|
|
9078
9114
|
}
|
|
9079
9115
|
const header = `# ${displaySafeText(match.name)} (${displaySafeText(match.kind)}) \u2014 ${formatSymbolLocation(displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath)), match.lineStart, match.lineEnd)}`;
|
|
9080
9116
|
const diffNote = diffFileScoped ? [virtualIndexedScopeNote(displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath)), "these hunks cover the whole file rather than this symbol alone")] : [];
|
|
9081
|
-
|
|
9117
|
+
emit(guardText([header, ...diffNote, ...overlapping.map((h) => h.text)].join("\n"), "diff"));
|
|
9082
9118
|
return 0;
|
|
9083
9119
|
}
|
|
9084
9120
|
var DEFAULT_LOG_MAX_COUNT = 20;
|
|
@@ -9139,20 +9175,20 @@ function runLog(opts) {
|
|
|
9139
9175
|
try {
|
|
9140
9176
|
logResult = runGit(logArgs, { cwd });
|
|
9141
9177
|
} catch {
|
|
9142
|
-
|
|
9178
|
+
emitErr(`Could not run git log for '${match.filePath}'`);
|
|
9143
9179
|
return 1;
|
|
9144
9180
|
}
|
|
9145
9181
|
if (logResult.exitCode !== 0) {
|
|
9146
|
-
|
|
9182
|
+
emitErr(`git log failed: ${displaySafeText(logResult.stderr)}`);
|
|
9147
9183
|
return 1;
|
|
9148
9184
|
}
|
|
9149
9185
|
if (logResult.stdout.trim() === "") {
|
|
9150
|
-
|
|
9186
|
+
emit(`No history for '${displaySafeText(match.name)}' (lines ${match.lineStart}-${match.lineEnd}) in '${displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath))}'.`);
|
|
9151
9187
|
return 0;
|
|
9152
9188
|
}
|
|
9153
9189
|
if (opts.json === true) {
|
|
9154
9190
|
const capped = guardJsonRows(parseLogDashLOutput(logResult.stdout));
|
|
9155
|
-
|
|
9191
|
+
emit(
|
|
9156
9192
|
displaySafeJson(
|
|
9157
9193
|
{
|
|
9158
9194
|
symbol: match.name,
|
|
@@ -9169,7 +9205,7 @@ function runLog(opts) {
|
|
|
9169
9205
|
}
|
|
9170
9206
|
const header = `# ${displaySafeText(match.name)} (${displaySafeText(match.kind)}) \u2014 ${formatSymbolLocation(displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath)), match.lineStart, match.lineEnd)}`;
|
|
9171
9207
|
const logNote = fileScoped ? [virtualIndexedScopeNote(displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath)), "this history covers the whole file rather than this symbol alone")] : [];
|
|
9172
|
-
|
|
9208
|
+
emit(guardText([header, ...logNote, logResult.stdout].join("\n"), "diff"));
|
|
9173
9209
|
return 0;
|
|
9174
9210
|
}
|
|
9175
9211
|
|
|
@@ -9619,26 +9655,26 @@ async function runZipList(opts) {
|
|
|
9619
9655
|
data = readFileBytes(opts.file);
|
|
9620
9656
|
} catch (err) {
|
|
9621
9657
|
if (err instanceof ZipInputTooLargeError) {
|
|
9622
|
-
|
|
9658
|
+
emitErr(err.message);
|
|
9623
9659
|
return 1;
|
|
9624
9660
|
}
|
|
9625
9661
|
throw err;
|
|
9626
9662
|
}
|
|
9627
9663
|
if (data === null) {
|
|
9628
|
-
|
|
9664
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
9629
9665
|
return 1;
|
|
9630
9666
|
}
|
|
9631
9667
|
let entries;
|
|
9632
9668
|
try {
|
|
9633
9669
|
entries = await listZipEntries(data);
|
|
9634
9670
|
} catch (err) {
|
|
9635
|
-
|
|
9671
|
+
emitErr(archiveReadFailure(err, opts.file));
|
|
9636
9672
|
return 1;
|
|
9637
9673
|
}
|
|
9638
9674
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
9639
9675
|
if (opts.json === true) {
|
|
9640
9676
|
const jsonText = displaySafeJson(entries, 0);
|
|
9641
|
-
|
|
9677
|
+
emit(jsonText);
|
|
9642
9678
|
recordReadStat("zip_list", fullSourceBytes, jsonText, opts.file);
|
|
9643
9679
|
} else {
|
|
9644
9680
|
const text = formatZipList(entries);
|
|
@@ -9653,13 +9689,13 @@ async function runZipRead(opts) {
|
|
|
9653
9689
|
data = readFileBytes(opts.file);
|
|
9654
9690
|
} catch (err) {
|
|
9655
9691
|
if (err instanceof ZipInputTooLargeError) {
|
|
9656
|
-
|
|
9692
|
+
emitErr(err.message);
|
|
9657
9693
|
return 1;
|
|
9658
9694
|
}
|
|
9659
9695
|
throw err;
|
|
9660
9696
|
}
|
|
9661
9697
|
if (data === null) {
|
|
9662
|
-
|
|
9698
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
9663
9699
|
return 1;
|
|
9664
9700
|
}
|
|
9665
9701
|
let entries;
|
|
@@ -9668,12 +9704,12 @@ async function runZipRead(opts) {
|
|
|
9668
9704
|
entries = await listZipEntries(data);
|
|
9669
9705
|
content = await extractZipEntry(data, opts.entry);
|
|
9670
9706
|
} catch (err) {
|
|
9671
|
-
|
|
9707
|
+
emitErr(archiveReadFailure(err, opts.file));
|
|
9672
9708
|
return 1;
|
|
9673
9709
|
}
|
|
9674
9710
|
const matchedEntry = entries.find((e) => e.path === opts.entry);
|
|
9675
9711
|
if (matchedEntry?.isDirectory === true) {
|
|
9676
|
-
|
|
9712
|
+
emitErr(`Entry '${opts.entry}' is a directory, not a file, in '${opts.file}'`);
|
|
9677
9713
|
return 1;
|
|
9678
9714
|
}
|
|
9679
9715
|
if (content === void 0) {
|
|
@@ -9681,7 +9717,7 @@ async function runZipRead(opts) {
|
|
|
9681
9717
|
const closes = rankSimilarNames(entries.map((e) => e.path), opts.entry);
|
|
9682
9718
|
if (closes.length > 0) messages.push(didYouMean(closes));
|
|
9683
9719
|
else if (entries.length > 0) messages.push(`Try: token-goat zip-list ${opts.file}`);
|
|
9684
|
-
|
|
9720
|
+
emitErr(messages.join("\n"));
|
|
9685
9721
|
return 1;
|
|
9686
9722
|
}
|
|
9687
9723
|
const buf = Buffer.from(content);
|
|
@@ -9689,7 +9725,7 @@ async function runZipRead(opts) {
|
|
|
9689
9725
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
9690
9726
|
if (opts.json === true) {
|
|
9691
9727
|
const jsonText = displaySafeJson({ path: opts.entry, text }, 0);
|
|
9692
|
-
|
|
9728
|
+
emit(jsonText);
|
|
9693
9729
|
recordReadStat("zip_read", fullSourceBytes, jsonText, opts.entry);
|
|
9694
9730
|
} else {
|
|
9695
9731
|
emitGuarded(text, "zip-read");
|
|
@@ -9703,16 +9739,16 @@ function runSqliteSchema(opts) {
|
|
|
9703
9739
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
9704
9740
|
if (opts.json === true) {
|
|
9705
9741
|
const jsonText = displaySafeJson(schema, 0);
|
|
9706
|
-
|
|
9742
|
+
emit(jsonText);
|
|
9707
9743
|
recordReadStat("sqlite_schema", fullSourceBytes, jsonText, opts.file);
|
|
9708
9744
|
} else {
|
|
9709
9745
|
const text = formatSqliteSchema(schema);
|
|
9710
|
-
|
|
9746
|
+
emit(text);
|
|
9711
9747
|
recordReadStat("sqlite_schema", fullSourceBytes, text, opts.file);
|
|
9712
9748
|
}
|
|
9713
9749
|
return 0;
|
|
9714
9750
|
} catch (e) {
|
|
9715
|
-
|
|
9751
|
+
emitErr(extractErrorMessage(e));
|
|
9716
9752
|
return 1;
|
|
9717
9753
|
}
|
|
9718
9754
|
}
|
|
@@ -9722,16 +9758,16 @@ function runSqliteTables(opts) {
|
|
|
9722
9758
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
9723
9759
|
if (opts.json === true) {
|
|
9724
9760
|
const jsonText = displaySafeJson(tables, 0);
|
|
9725
|
-
|
|
9761
|
+
emit(jsonText);
|
|
9726
9762
|
recordReadStat("sqlite_tables", fullSourceBytes, jsonText, opts.file);
|
|
9727
9763
|
} else {
|
|
9728
9764
|
const text = formatSqliteTables(tables);
|
|
9729
|
-
|
|
9765
|
+
emit(text);
|
|
9730
9766
|
recordReadStat("sqlite_tables", fullSourceBytes, text, opts.file);
|
|
9731
9767
|
}
|
|
9732
9768
|
return 0;
|
|
9733
9769
|
} catch (e) {
|
|
9734
|
-
|
|
9770
|
+
emitErr(extractErrorMessage(e));
|
|
9735
9771
|
return 1;
|
|
9736
9772
|
}
|
|
9737
9773
|
}
|
|
@@ -9740,7 +9776,7 @@ function runSqliteQuery(opts) {
|
|
|
9740
9776
|
try {
|
|
9741
9777
|
head = opts.head !== void 0 ? requireNonNegativeStrictInt("--head", opts.head) : void 0;
|
|
9742
9778
|
} catch (e) {
|
|
9743
|
-
|
|
9779
|
+
emitErr(extractErrorMessage(e));
|
|
9744
9780
|
return 1;
|
|
9745
9781
|
}
|
|
9746
9782
|
try {
|
|
@@ -9757,7 +9793,7 @@ function runSqliteQuery(opts) {
|
|
|
9757
9793
|
totalCount,
|
|
9758
9794
|
rowCapped: result.rowCapped
|
|
9759
9795
|
}, 0);
|
|
9760
|
-
|
|
9796
|
+
emit(jsonText);
|
|
9761
9797
|
const uncappedFull = guardJsonRows(result.rows);
|
|
9762
9798
|
const baselineJsonText = displaySafeJson({
|
|
9763
9799
|
columns: result.columns,
|
|
@@ -9769,27 +9805,27 @@ function runSqliteQuery(opts) {
|
|
|
9769
9805
|
recordReadStat("sqlite_query", Buffer.byteLength(baselineJsonText, "utf8"), jsonText, opts.file);
|
|
9770
9806
|
} else {
|
|
9771
9807
|
const text = formatSqliteQueryTable({ ...result, rows }, { headTruncated });
|
|
9772
|
-
|
|
9808
|
+
emit(text);
|
|
9773
9809
|
const baselineText = formatSqliteQueryTable({ ...result, rows: result.rows }, { headTruncated: false });
|
|
9774
9810
|
recordReadStat("sqlite_query", Buffer.byteLength(baselineText, "utf8"), text, opts.file);
|
|
9775
9811
|
}
|
|
9776
9812
|
return 0;
|
|
9777
9813
|
} catch (e) {
|
|
9778
|
-
|
|
9814
|
+
emitErr(extractErrorMessage(e));
|
|
9779
9815
|
return 1;
|
|
9780
9816
|
}
|
|
9781
9817
|
}
|
|
9782
9818
|
function runCoverageReportGaps(opts) {
|
|
9783
9819
|
const text = readFileText(opts.file);
|
|
9784
9820
|
if (text === null) {
|
|
9785
|
-
|
|
9821
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
9786
9822
|
return 1;
|
|
9787
9823
|
}
|
|
9788
9824
|
let report;
|
|
9789
9825
|
try {
|
|
9790
9826
|
report = parseCoverageReport(text);
|
|
9791
9827
|
} catch (e) {
|
|
9792
|
-
|
|
9828
|
+
emitErr(`Failed to parse coverage report (not valid LCOV or Istanbul JSON): ${opts.file}
|
|
9793
9829
|
${extractErrorMessage(e)}`);
|
|
9794
9830
|
return 1;
|
|
9795
9831
|
}
|
|
@@ -9797,7 +9833,7 @@ ${extractErrorMessage(e)}`);
|
|
|
9797
9833
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
9798
9834
|
if (opts.json === true) {
|
|
9799
9835
|
const jsonText = displaySafeJson(scoped, 0);
|
|
9800
|
-
|
|
9836
|
+
emit(jsonText);
|
|
9801
9837
|
recordReadStat("coverage_report_gaps", fullSourceBytes, jsonText, opts.file);
|
|
9802
9838
|
} else {
|
|
9803
9839
|
const text2 = formatCoverageGaps(scoped);
|
|
@@ -9875,17 +9911,17 @@ function extractFrontmatter(lines) {
|
|
|
9875
9911
|
function runConfigGet(opts) {
|
|
9876
9912
|
const text = readFileText(opts.file);
|
|
9877
9913
|
if (text === null) {
|
|
9878
|
-
|
|
9914
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
9879
9915
|
return 1;
|
|
9880
9916
|
}
|
|
9881
9917
|
const frontmatterLines = extractFrontmatter(text.split(/\r?\n/));
|
|
9882
9918
|
if (frontmatterLines !== null) {
|
|
9883
9919
|
const value = lookupYaml(frontmatterLines, opts.key);
|
|
9884
9920
|
if (value === null) {
|
|
9885
|
-
|
|
9921
|
+
emitErr(`Key '${opts.key}' not found in ${opts.file}`);
|
|
9886
9922
|
return 1;
|
|
9887
9923
|
}
|
|
9888
|
-
|
|
9924
|
+
emit(value);
|
|
9889
9925
|
return 0;
|
|
9890
9926
|
}
|
|
9891
9927
|
const ext = path10.extname(opts.file).toLowerCase();
|
|
@@ -9894,29 +9930,29 @@ function runConfigGet(opts) {
|
|
|
9894
9930
|
let obj = JSON.parse(text);
|
|
9895
9931
|
for (const part of opts.key.split(".")) {
|
|
9896
9932
|
if (typeof obj !== "object" || obj === null) {
|
|
9897
|
-
|
|
9933
|
+
emitErr(`Key '${opts.key}' not found in ${opts.file}`);
|
|
9898
9934
|
return 1;
|
|
9899
9935
|
}
|
|
9900
9936
|
obj = obj[part];
|
|
9901
9937
|
if (obj === void 0) {
|
|
9902
|
-
|
|
9938
|
+
emitErr(`Key '${opts.key}' not found in ${opts.file}`);
|
|
9903
9939
|
return 1;
|
|
9904
9940
|
}
|
|
9905
9941
|
}
|
|
9906
|
-
|
|
9942
|
+
emit(displaySafeJson(obj, 0));
|
|
9907
9943
|
return 0;
|
|
9908
9944
|
} catch {
|
|
9909
|
-
|
|
9945
|
+
emitErr(`Failed to parse JSON: ${opts.file}`);
|
|
9910
9946
|
return 1;
|
|
9911
9947
|
}
|
|
9912
9948
|
}
|
|
9913
9949
|
if (ext === ".yaml" || ext === ".yml") {
|
|
9914
9950
|
const value = lookupYaml(text.split(/\r?\n/), opts.key);
|
|
9915
9951
|
if (value === null) {
|
|
9916
|
-
|
|
9952
|
+
emitErr(`Key '${opts.key}' not found in ${opts.file}`);
|
|
9917
9953
|
return 1;
|
|
9918
9954
|
}
|
|
9919
|
-
|
|
9955
|
+
emit(value);
|
|
9920
9956
|
return 0;
|
|
9921
9957
|
}
|
|
9922
9958
|
const keyParts = opts.key.split(".");
|
|
@@ -9937,18 +9973,18 @@ function runConfigGet(opts) {
|
|
|
9937
9973
|
if (new RegExp(`^${escapeRegExp(leafKey)}\\s*=`).test(trimmed)) {
|
|
9938
9974
|
const eqIdx = trimmed.indexOf("=");
|
|
9939
9975
|
const rawValue = stripInlineComment(trimmed.slice(eqIdx + 1)).trim();
|
|
9940
|
-
|
|
9976
|
+
emit(stripPairedQuotes(rawValue));
|
|
9941
9977
|
return 0;
|
|
9942
9978
|
}
|
|
9943
9979
|
}
|
|
9944
|
-
|
|
9980
|
+
emitErr(`Key '${opts.key}' not found in ${opts.file}`);
|
|
9945
9981
|
return 1;
|
|
9946
9982
|
}
|
|
9947
9983
|
function runPerFileEmitting(files, label, run) {
|
|
9948
9984
|
let anyOk = false;
|
|
9949
9985
|
files.forEach((file, i) => {
|
|
9950
|
-
if (i > 0)
|
|
9951
|
-
|
|
9986
|
+
if (i > 0) emit("");
|
|
9987
|
+
emit(`# ${label}: ${file}`);
|
|
9952
9988
|
if (run(file) === 0) anyOk = true;
|
|
9953
9989
|
});
|
|
9954
9990
|
return anyOk ? 0 : 1;
|
|
@@ -9958,7 +9994,7 @@ function runExports(opts) {
|
|
|
9958
9994
|
if (multiFiles.length > 1) return runPerFileEmitting(multiFiles, "Exports", (file) => runExports({ ...opts, file }));
|
|
9959
9995
|
const confined = fileConfinementRefusal("This file", opts.file, opts.projectRoot);
|
|
9960
9996
|
if (confined !== null) {
|
|
9961
|
-
|
|
9997
|
+
emitErr(confined);
|
|
9962
9998
|
return 1;
|
|
9963
9999
|
}
|
|
9964
10000
|
const diskPath = resolveAgainstProjectRoot(opts.file, opts.projectRoot);
|
|
@@ -9977,7 +10013,7 @@ function runExports(opts) {
|
|
|
9977
10013
|
const ext = path10.extname(opts.file).toLowerCase();
|
|
9978
10014
|
const text = readFileText(diskPath);
|
|
9979
10015
|
if (text === null && symbols.length === 0) {
|
|
9980
|
-
|
|
10016
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
9981
10017
|
return 1;
|
|
9982
10018
|
}
|
|
9983
10019
|
if (text !== null) {
|
|
@@ -9987,7 +10023,7 @@ function runExports(opts) {
|
|
|
9987
10023
|
for (const n of extractExportNames(text, ext)) if (!names.includes(n)) names.push(n);
|
|
9988
10024
|
}
|
|
9989
10025
|
if (names.length === 0) {
|
|
9990
|
-
|
|
10026
|
+
emit(`No exported symbols found in '${displaySafeText(opts.file)}'`);
|
|
9991
10027
|
return 0;
|
|
9992
10028
|
}
|
|
9993
10029
|
const preFilterCount = names.length;
|
|
@@ -9997,12 +10033,12 @@ function runExports(opts) {
|
|
|
9997
10033
|
if (filteredNames.length === 0) {
|
|
9998
10034
|
if (opts.json === true) {
|
|
9999
10035
|
const jsonText = displaySafeJson([]);
|
|
10000
|
-
|
|
10036
|
+
emit(jsonText);
|
|
10001
10037
|
recordReadStat("exports", fullSourceBytes, jsonText, opts.file);
|
|
10002
10038
|
return 0;
|
|
10003
10039
|
}
|
|
10004
10040
|
const textOut = grepFilteredToEmptyNotice(preFilterCount, opts.grep ?? "", "exported symbol", "exported symbols");
|
|
10005
|
-
|
|
10041
|
+
emit(textOut);
|
|
10006
10042
|
recordReadStat("exports", fullSourceBytes, textOut, opts.file);
|
|
10007
10043
|
return 0;
|
|
10008
10044
|
}
|
|
@@ -10013,7 +10049,7 @@ function runExports(opts) {
|
|
|
10013
10049
|
return { name: n, kind: kindOf(n), lineStart: loc?.lineStart ?? null, lineEnd: loc?.lineEnd ?? null };
|
|
10014
10050
|
})
|
|
10015
10051
|
);
|
|
10016
|
-
|
|
10052
|
+
emit(jsonText);
|
|
10017
10053
|
recordReadStat("exports", fullSourceBytes, jsonText, opts.file);
|
|
10018
10054
|
return 0;
|
|
10019
10055
|
}
|
|
@@ -10023,7 +10059,7 @@ function runExports(opts) {
|
|
|
10023
10059
|
return `${kindOf(n).padEnd(10)} ${n}${locSuffix}`;
|
|
10024
10060
|
});
|
|
10025
10061
|
for (const line of outLines) {
|
|
10026
|
-
|
|
10062
|
+
emit(line);
|
|
10027
10063
|
}
|
|
10028
10064
|
recordReadStat("exports", fullSourceBytes, outLines.join("\n"), opts.file);
|
|
10029
10065
|
return 0;
|
|
@@ -10034,12 +10070,12 @@ function runImports(opts) {
|
|
|
10034
10070
|
const diskPath = resolveAgainstProjectRoot(opts.file, opts.projectRoot);
|
|
10035
10071
|
const text = readFileText(diskPath);
|
|
10036
10072
|
if (text === null) {
|
|
10037
|
-
|
|
10073
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
10038
10074
|
return 1;
|
|
10039
10075
|
}
|
|
10040
10076
|
const imports = extractImports(text, importsExtensionFor(opts.file));
|
|
10041
10077
|
if (imports.length === 0) {
|
|
10042
|
-
|
|
10078
|
+
emit(`No imports found in '${displaySafeText(opts.file)}'`);
|
|
10043
10079
|
return 0;
|
|
10044
10080
|
}
|
|
10045
10081
|
const preFilterCount = imports.length;
|
|
@@ -10049,25 +10085,25 @@ function runImports(opts) {
|
|
|
10049
10085
|
if (filteredImports.length === 0) {
|
|
10050
10086
|
if (opts.json === true) {
|
|
10051
10087
|
const jsonText = displaySafeJson({ items: [], truncated: false, totalCount: 0 });
|
|
10052
|
-
|
|
10088
|
+
emit(jsonText);
|
|
10053
10089
|
recordReadStat("imports", fullSourceBytes, jsonText, opts.file);
|
|
10054
10090
|
return 0;
|
|
10055
10091
|
}
|
|
10056
10092
|
const text2 = grepFilteredToEmptyNotice(preFilterCount, opts.grep ?? "", "import", "imports");
|
|
10057
|
-
|
|
10093
|
+
emit(text2);
|
|
10058
10094
|
recordReadStat("imports", fullSourceBytes, text2, opts.file);
|
|
10059
10095
|
return 0;
|
|
10060
10096
|
}
|
|
10061
10097
|
if (opts.json === true) {
|
|
10062
10098
|
const capped = guardJsonRows(filteredImports);
|
|
10063
10099
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount });
|
|
10064
|
-
|
|
10100
|
+
emit(jsonText);
|
|
10065
10101
|
recordReadStat("imports", fullSourceBytes, jsonText, opts.file);
|
|
10066
10102
|
return 0;
|
|
10067
10103
|
}
|
|
10068
10104
|
const outLines = filteredImports.map((imp) => `import ${imp}`);
|
|
10069
10105
|
for (const line of outLines) {
|
|
10070
|
-
|
|
10106
|
+
emit(line);
|
|
10071
10107
|
}
|
|
10072
10108
|
recordReadStat("imports", fullSourceBytes, outLines.join("\n"), opts.file);
|
|
10073
10109
|
return 0;
|
|
@@ -10165,50 +10201,55 @@ function runNoteList(opts = {}) {
|
|
|
10165
10201
|
}
|
|
10166
10202
|
function runFind(opts) {
|
|
10167
10203
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
10168
|
-
|
|
10204
|
+
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
10169
10205
|
return 1;
|
|
10170
10206
|
}
|
|
10171
10207
|
const rootDir = resolveProjectRoot({ project: process.cwd() });
|
|
10172
10208
|
const patternLower = opts.pattern.toLowerCase();
|
|
10173
|
-
const
|
|
10174
|
-
const
|
|
10175
|
-
|
|
10176
|
-
|
|
10209
|
+
const matchedFiles = /* @__PURE__ */ new Set();
|
|
10210
|
+
const allNames = /* @__PURE__ */ new Set();
|
|
10211
|
+
forEachSymbol({ rootDir }, (s) => {
|
|
10212
|
+
allNames.add(s.name);
|
|
10213
|
+
if (s.name.toLowerCase().includes(patternLower)) matchedFiles.add(s.filePath);
|
|
10214
|
+
});
|
|
10177
10215
|
let fuzzyNames = [];
|
|
10178
|
-
if (
|
|
10179
|
-
fuzzyNames = rankSimilarNames(
|
|
10216
|
+
if (matchedFiles.size === 0) {
|
|
10217
|
+
fuzzyNames = rankSimilarNames([...allNames], opts.pattern);
|
|
10218
|
+
if (fuzzyNames.length > 0) {
|
|
10219
|
+
const byName = new Map(fuzzyNames.map((n) => [n, []]));
|
|
10220
|
+
forEachSymbol({ rootDir }, (s) => {
|
|
10221
|
+
byName.get(s.name)?.push(s.filePath);
|
|
10222
|
+
});
|
|
10223
|
+
for (const n of fuzzyNames) for (const f of byName.get(n) ?? []) matchedFiles.add(f);
|
|
10224
|
+
}
|
|
10180
10225
|
}
|
|
10181
|
-
const
|
|
10182
|
-
const allFiles = [...new Set(matched.map((s) => s.filePath))];
|
|
10226
|
+
const allFiles = [...matchedFiles];
|
|
10183
10227
|
const files = allFiles.slice(0, opts.limit ?? 50);
|
|
10184
10228
|
const limitDropped = allFiles.length - files.length;
|
|
10185
|
-
const truncated =
|
|
10229
|
+
const truncated = limitDropped > 0;
|
|
10186
10230
|
if (files.length === 0) {
|
|
10187
|
-
|
|
10231
|
+
emitErr(`No indexed files match '${opts.pattern}'`);
|
|
10188
10232
|
return 1;
|
|
10189
10233
|
}
|
|
10190
10234
|
if (opts.json === true) {
|
|
10191
10235
|
const fuzzyPayload = fuzzyNames.length > 0 ? { fuzzy: true, matchedNames: fuzzyNames } : {};
|
|
10192
|
-
|
|
10236
|
+
emit(displaySafeJson({ files, truncated, totalCount: allFiles.length, ...fuzzyPayload }));
|
|
10193
10237
|
return 0;
|
|
10194
10238
|
}
|
|
10195
10239
|
if (fuzzyNames.length > 0) {
|
|
10196
|
-
|
|
10240
|
+
emitErr(`No symbol name contains '${opts.pattern}'; showing files for the nearest indexed ${fuzzyNames.length === 1 ? "name" : "names"}: ${fuzzyNames.join(", ")}`);
|
|
10197
10241
|
}
|
|
10198
10242
|
for (const f of files) {
|
|
10199
|
-
|
|
10243
|
+
emit(toDisplayPath(rootDir, f));
|
|
10200
10244
|
}
|
|
10201
10245
|
if (limitDropped > 0) {
|
|
10202
|
-
|
|
10203
|
-
}
|
|
10204
|
-
if (rawSymbols.length === FIND_SCAN_LIMIT2) {
|
|
10205
|
-
emitErr4(`Results may be incomplete; index scan hit limit of ${FIND_SCAN_LIMIT2} symbols`);
|
|
10246
|
+
emitErr(`Showing ${files.length} of ${allFiles.length} matching files; rerun with --limit ${allFiles.length} to see them all`);
|
|
10206
10247
|
}
|
|
10207
10248
|
return 0;
|
|
10208
10249
|
}
|
|
10209
10250
|
function runLocate(opts) {
|
|
10210
10251
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
10211
|
-
|
|
10252
|
+
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
10212
10253
|
return 1;
|
|
10213
10254
|
}
|
|
10214
10255
|
const rootDir = opts.projectRoot ?? resolveProjectRoot({ project: process.cwd() });
|
|
@@ -10219,35 +10260,55 @@ function runLocate(opts) {
|
|
|
10219
10260
|
targetFile = targetSpec.slice(0, colonIdx);
|
|
10220
10261
|
targetSpec = targetSpec.slice(colonIdx + 2);
|
|
10221
10262
|
}
|
|
10222
|
-
const
|
|
10223
|
-
limit: FIND_SCAN_LIMIT2
|
|
10224
|
-
};
|
|
10263
|
+
const scanOpts = {};
|
|
10225
10264
|
if (targetFile !== void 0) {
|
|
10226
|
-
|
|
10227
|
-
healStaleIndex(
|
|
10265
|
+
scanOpts.filePath = resolveIndexPath(targetFile, rootDir);
|
|
10266
|
+
healStaleIndex(scanOpts.filePath);
|
|
10228
10267
|
} else {
|
|
10229
|
-
|
|
10268
|
+
scanOpts.rootDir = rootDir;
|
|
10230
10269
|
}
|
|
10231
|
-
|
|
10270
|
+
const limit = opts.limit ?? 25;
|
|
10271
|
+
const specLower = targetSpec.toLowerCase();
|
|
10272
|
+
const scan = () => {
|
|
10273
|
+
const found2 = { exact: [], exactCount: 0, partial: [], partialCount: 0, names: /* @__PURE__ */ new Set(), files: /* @__PURE__ */ new Set() };
|
|
10274
|
+
forEachSymbol(scanOpts, (s) => {
|
|
10275
|
+
found2.names.add(s.name);
|
|
10276
|
+
found2.files.add(s.filePath);
|
|
10277
|
+
const nameLower = s.name.toLowerCase();
|
|
10278
|
+
if (nameLower === specLower) {
|
|
10279
|
+
found2.exactCount++;
|
|
10280
|
+
if (found2.exact.length < limit) found2.exact.push(s);
|
|
10281
|
+
} else if (nameLower.includes(specLower)) {
|
|
10282
|
+
found2.partialCount++;
|
|
10283
|
+
if (found2.partial.length < limit) found2.partial.push(s);
|
|
10284
|
+
}
|
|
10285
|
+
});
|
|
10286
|
+
return found2;
|
|
10287
|
+
};
|
|
10288
|
+
let found = scan();
|
|
10232
10289
|
if (targetFile === void 0) {
|
|
10233
|
-
const heal = healStaleResultFiles(
|
|
10234
|
-
if (heal.healed)
|
|
10290
|
+
const heal = healStaleResultFiles([...found.files]);
|
|
10291
|
+
if (heal.healed) found = scan();
|
|
10235
10292
|
}
|
|
10236
|
-
|
|
10237
|
-
|
|
10238
|
-
const partialMatches = rawSymbols.filter(
|
|
10239
|
-
(s) => s.name.toLowerCase() !== specLower && s.name.toLowerCase().includes(specLower)
|
|
10240
|
-
);
|
|
10241
|
-
const combined = [...exactMatches, ...partialMatches];
|
|
10293
|
+
let matchCount = found.exactCount + found.partialCount;
|
|
10294
|
+
let combined = [...found.exact, ...found.partial];
|
|
10242
10295
|
let fuzzyNames = [];
|
|
10243
|
-
if (
|
|
10244
|
-
fuzzyNames = rankSimilarNames(
|
|
10296
|
+
if (matchCount === 0) {
|
|
10297
|
+
fuzzyNames = rankSimilarNames([...found.names], targetSpec);
|
|
10298
|
+
if (fuzzyNames.length > 0) {
|
|
10299
|
+
const byName = new Map(fuzzyNames.map((n) => [n, []]));
|
|
10300
|
+
forEachSymbol(scanOpts, (s) => {
|
|
10301
|
+
const bucket = byName.get(s.name);
|
|
10302
|
+
if (bucket === void 0) return;
|
|
10303
|
+
matchCount++;
|
|
10304
|
+
if (bucket.length < limit) bucket.push(s);
|
|
10305
|
+
});
|
|
10306
|
+
combined = fuzzyNames.flatMap((n) => byName.get(n) ?? []);
|
|
10307
|
+
}
|
|
10245
10308
|
}
|
|
10246
|
-
const
|
|
10247
|
-
const limit = opts.limit ?? 25;
|
|
10248
|
-
const shown = matched.slice(0, limit);
|
|
10309
|
+
const shown = combined.slice(0, limit);
|
|
10249
10310
|
if (shown.length === 0) {
|
|
10250
|
-
|
|
10311
|
+
emitErr(`No landmark or symbol located for '${targetSpec}'`);
|
|
10251
10312
|
return 1;
|
|
10252
10313
|
}
|
|
10253
10314
|
const hits = shown.map((s) => ({
|
|
@@ -10259,22 +10320,22 @@ function runLocate(opts) {
|
|
|
10259
10320
|
span: `${s.lineStart}-${s.lineEnd}`
|
|
10260
10321
|
}));
|
|
10261
10322
|
if (opts.json === true) {
|
|
10262
|
-
|
|
10323
|
+
emit(displaySafeJson({
|
|
10263
10324
|
items: hits,
|
|
10264
|
-
totalCount:
|
|
10265
|
-
truncated:
|
|
10325
|
+
totalCount: matchCount,
|
|
10326
|
+
truncated: matchCount > limit,
|
|
10266
10327
|
...fuzzyNames.length > 0 ? { fuzzy: true, matchedNames: fuzzyNames } : {}
|
|
10267
10328
|
}));
|
|
10268
10329
|
return 0;
|
|
10269
10330
|
}
|
|
10270
10331
|
if (fuzzyNames.length > 0) {
|
|
10271
|
-
|
|
10332
|
+
emitErr(`No exact landmark for '${targetSpec}'; nearest matches: ${fuzzyNames.join(", ")}`);
|
|
10272
10333
|
}
|
|
10273
10334
|
for (const hit of hits) {
|
|
10274
|
-
|
|
10335
|
+
emit(`${displaySafeText(hit.filePath)}:${hit.span} [${displaySafeText(hit.kind)}] ${displaySafeText(hit.name)}`);
|
|
10275
10336
|
}
|
|
10276
|
-
if (
|
|
10277
|
-
|
|
10337
|
+
if (matchCount > limit) {
|
|
10338
|
+
emitErr(`Showing ${limit} of ${matchCount} locations; rerun with --limit ${matchCount} to see them all`);
|
|
10278
10339
|
}
|
|
10279
10340
|
return 0;
|
|
10280
10341
|
}
|
|
@@ -10282,10 +10343,10 @@ function runListSections(opts) {
|
|
|
10282
10343
|
const sections = listSections(opts.file);
|
|
10283
10344
|
if (sections.length === 0) {
|
|
10284
10345
|
if (!fileExists(opts.file)) {
|
|
10285
|
-
|
|
10346
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
10286
10347
|
return 1;
|
|
10287
10348
|
}
|
|
10288
|
-
|
|
10349
|
+
emitErr(`No sections found in '${opts.file}'`);
|
|
10289
10350
|
return 1;
|
|
10290
10351
|
}
|
|
10291
10352
|
const preFilterCount = sections.length;
|
|
@@ -10301,19 +10362,19 @@ function runListSections(opts) {
|
|
|
10301
10362
|
const filtered = matchesGrep !== void 0 ? labelled.filter((_, i) => matchesGrep(sections[i] ?? "")) : labelled;
|
|
10302
10363
|
if (filtered.length === 0) {
|
|
10303
10364
|
if (opts.json === true) {
|
|
10304
|
-
|
|
10365
|
+
emit(displaySafeJson({ items: [], truncated: false, totalCount: 0 }));
|
|
10305
10366
|
return 0;
|
|
10306
10367
|
}
|
|
10307
|
-
|
|
10368
|
+
emit(grepFilteredToEmptyNotice(preFilterCount, opts.grep ?? "", "section", "sections"));
|
|
10308
10369
|
return 0;
|
|
10309
10370
|
}
|
|
10310
10371
|
if (opts.json === true) {
|
|
10311
10372
|
const capped = guardJsonRows(filtered);
|
|
10312
|
-
|
|
10373
|
+
emit(displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount }));
|
|
10313
10374
|
return 0;
|
|
10314
10375
|
}
|
|
10315
10376
|
for (const heading of filtered) {
|
|
10316
|
-
|
|
10377
|
+
emit(heading);
|
|
10317
10378
|
}
|
|
10318
10379
|
return 0;
|
|
10319
10380
|
}
|
|
@@ -10392,15 +10453,38 @@ function runSection(opts) {
|
|
|
10392
10453
|
}
|
|
10393
10454
|
const kind = result.redirectedFrom !== void 0 ? "section_replacement" : "section_read";
|
|
10394
10455
|
const fullSourceBytes = sumFileSizes([filePath]);
|
|
10456
|
+
let content = result.content;
|
|
10457
|
+
let lineEnd = result.lineEnd;
|
|
10458
|
+
let truncatedNotice = "";
|
|
10459
|
+
if (opts.maxLines !== void 0 && opts.maxLines > 0) {
|
|
10460
|
+
const lines = content.split("\n");
|
|
10461
|
+
if (lines.length > opts.maxLines) {
|
|
10462
|
+
const remaining = lines.length - opts.maxLines;
|
|
10463
|
+
content = lines.slice(0, opts.maxLines).join("\n");
|
|
10464
|
+
lineEnd = Math.min(result.lineEnd, result.lineStart + opts.maxLines - 1);
|
|
10465
|
+
truncatedNotice = `
|
|
10466
|
+
... (${countNoun(remaining, "more line")} not shown; pass a larger --max-lines or omit to read full section)`;
|
|
10467
|
+
}
|
|
10468
|
+
}
|
|
10395
10469
|
if (opts.json === true) {
|
|
10396
|
-
const
|
|
10470
|
+
const jsonPayload = {
|
|
10471
|
+
...result,
|
|
10472
|
+
content,
|
|
10473
|
+
lineEnd,
|
|
10474
|
+
...opts.maxLines !== void 0 && opts.maxLines > 0 ? {
|
|
10475
|
+
totalLines: result.content.split("\n").length,
|
|
10476
|
+
shownLines: content.split("\n").length,
|
|
10477
|
+
truncated: truncatedNotice.length > 0
|
|
10478
|
+
} : {}
|
|
10479
|
+
};
|
|
10480
|
+
const text2 = displaySafeJson(jsonPayload);
|
|
10397
10481
|
if (opts.suppressStat !== true) recordReadStat(kind, fullSourceBytes, text2, heading);
|
|
10398
10482
|
return { text: text2, code: 0 };
|
|
10399
10483
|
}
|
|
10400
10484
|
const redirectNote = result.redirectedFrom !== void 0 ? ` (redirected from: '${result.redirectedFrom}')` : "";
|
|
10401
10485
|
const text = guardText(
|
|
10402
|
-
`# ${result.heading} \u2014 ${filePath}:${result.lineStart}-${
|
|
10403
|
-
${
|
|
10486
|
+
`# ${result.heading} \u2014 ${filePath}:${result.lineStart}-${lineEnd}${redirectNote}
|
|
10487
|
+
${content}${truncatedNotice}`,
|
|
10404
10488
|
"heading"
|
|
10405
10489
|
);
|
|
10406
10490
|
if (opts.suppressStat !== true) recordReadStat(kind, fullSourceBytes, text, heading);
|
|
@@ -10521,8 +10605,7 @@ ${sub.text}`);
|
|
|
10521
10605
|
// src/read_commands.ts
|
|
10522
10606
|
var SYMBOL_PREVIEW_LINES = 5;
|
|
10523
10607
|
var GREP_MAX_LINES = 200;
|
|
10524
|
-
var
|
|
10525
|
-
var REFS_TOP_SCAN_LIMIT = 2e4;
|
|
10608
|
+
var FIND_SCAN_LIMIT = 2e4;
|
|
10526
10609
|
function fileExists2(p) {
|
|
10527
10610
|
try {
|
|
10528
10611
|
fs12.statSync(p);
|
|
@@ -10597,6 +10680,7 @@ function verifyPin(p, pinned) {
|
|
|
10597
10680
|
verifyPinnedIdentity(p, pinned);
|
|
10598
10681
|
}
|
|
10599
10682
|
function indexFileSyncPinned(resolvedPath, dbPath) {
|
|
10683
|
+
recordKnownRootThrottled(resolvedPath, dataDir(), dbPath);
|
|
10600
10684
|
const pinned = activePins?.get(pinKey(path12.resolve(resolvedPath)));
|
|
10601
10685
|
if (pinned === void 0) {
|
|
10602
10686
|
indexFileSync(resolvedPath, dbPath);
|
|
@@ -10737,15 +10821,8 @@ function warnIfFilesStale(filePaths) {
|
|
|
10737
10821
|
);
|
|
10738
10822
|
}
|
|
10739
10823
|
}
|
|
10740
|
-
function emit4(text) {
|
|
10741
|
-
const out = colorStdout() ? text : stripAnsi(text);
|
|
10742
|
-
process.stdout.write(ensureNewline(out));
|
|
10743
|
-
}
|
|
10744
|
-
function emitErr4(text) {
|
|
10745
|
-
process.stderr.write(ensureNewline(text));
|
|
10746
|
-
}
|
|
10747
10824
|
function emitGuarded(text, command) {
|
|
10748
|
-
|
|
10825
|
+
emit(guardText(text, command));
|
|
10749
10826
|
}
|
|
10750
10827
|
function guardText(text, command) {
|
|
10751
10828
|
const cfg = loadConfig();
|
|
@@ -10800,6 +10877,11 @@ function resolveEnclosingSymbol(filePath, chunkStartLine) {
|
|
|
10800
10877
|
}
|
|
10801
10878
|
return best === null ? null : { name: best.name, kind: best.kind, lineStart: best.lineStart };
|
|
10802
10879
|
}
|
|
10880
|
+
var IMPORT_BIND_BODY_RE = /^\s*(?:const|let|var)\s*\{[^}]*\}\s*=\s*(?:await\s+)?(?:import|require)\s*\(/;
|
|
10881
|
+
function stableSortImportBindsLast(rows) {
|
|
10882
|
+
const isBind = (r) => typeof r.body === "string" && IMPORT_BIND_BODY_RE.test(r.body) ? 1 : 0;
|
|
10883
|
+
return [...rows].sort((a, b) => isBind(a) - isBind(b));
|
|
10884
|
+
}
|
|
10803
10885
|
function runSymbol(opts) {
|
|
10804
10886
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
10805
10887
|
return { text: `--limit must be a positive number, got: ${opts.limit}`, code: 1 };
|
|
@@ -10834,27 +10916,42 @@ function runSymbol(opts) {
|
|
|
10834
10916
|
}
|
|
10835
10917
|
if (opts.name !== void 0) queryOpts.name = queryOpts.filePath !== void 0 ? stripHtmlIdSpelling(opts.name, queryOpts.filePath) : opts.name;
|
|
10836
10918
|
if (opts.kind !== void 0) queryOpts.kind = opts.kind;
|
|
10837
|
-
|
|
10838
|
-
|
|
10839
|
-
|
|
10919
|
+
const anyClientFilter = matchesGrep !== void 0 || excludeTests || excludeVendored;
|
|
10920
|
+
const effectiveLimit = opts.limit ?? DEFAULT_QUERY_LIMIT;
|
|
10921
|
+
if (!anyClientFilter && opts.limit !== void 0) {
|
|
10840
10922
|
queryOpts.limit = opts.limit;
|
|
10841
10923
|
}
|
|
10842
10924
|
if (opts.file === void 0 && opts.projectRoot !== void 0) queryOpts.rootDir = opts.projectRoot;
|
|
10843
10925
|
if (opts.file === void 0 && queryOpts.rootDir === void 0 && confinedRoot !== null) queryOpts.rootDir = confinedRoot;
|
|
10844
|
-
|
|
10926
|
+
const runSweep = () => {
|
|
10927
|
+
const found = { kept: [], keptCount: 0, scanned: 0, hiddenByExcludeTests: 0, files: /* @__PURE__ */ new Set() };
|
|
10928
|
+
const take = (s) => {
|
|
10929
|
+
found.scanned++;
|
|
10930
|
+
found.files.add(s.filePath);
|
|
10931
|
+
const nameKept = matchesGrep === void 0 || matchesGrep(s.name);
|
|
10932
|
+
if (nameKept && !(excludeTests && isTestFile(s.filePath)) && !(excludeVendored && isIgnoredIndexPath(s.filePath))) {
|
|
10933
|
+
found.keptCount++;
|
|
10934
|
+
if (found.kept.length < effectiveLimit) found.kept.push(s);
|
|
10935
|
+
} else if (excludeTests && nameKept && isTestFile(s.filePath)) {
|
|
10936
|
+
found.hiddenByExcludeTests++;
|
|
10937
|
+
}
|
|
10938
|
+
};
|
|
10939
|
+
if (anyClientFilter) forEachSymbol(queryOpts, take);
|
|
10940
|
+
else for (const row of querySymbols(queryOpts)) take(row);
|
|
10941
|
+
return found;
|
|
10942
|
+
};
|
|
10943
|
+
let sweep = runSweep();
|
|
10845
10944
|
let stillStale = EMPTY_PATH_SET;
|
|
10846
10945
|
if (opts.file === void 0) {
|
|
10847
|
-
const heal = healStaleResultFiles(
|
|
10946
|
+
const heal = healStaleResultFiles([...sweep.files]);
|
|
10848
10947
|
stillStale = heal.stillStale;
|
|
10849
|
-
if (heal.healed)
|
|
10948
|
+
if (heal.healed) sweep = runSweep();
|
|
10850
10949
|
}
|
|
10851
|
-
const preFilterCount =
|
|
10852
|
-
const
|
|
10853
|
-
const
|
|
10854
|
-
const
|
|
10855
|
-
|
|
10856
|
-
const hiddenByExcludeTests = excludeTests ? rawResults.filter((s) => (matchesGrep === void 0 || matchesGrep(s.name)) && isTestFile(s.filePath)).length : 0;
|
|
10857
|
-
if (excludeTests && filtered.length === 0 && hiddenByExcludeTests > 0) {
|
|
10950
|
+
const preFilterCount = sweep.scanned;
|
|
10951
|
+
const unordered = sweep.kept.slice(0, effectiveLimit);
|
|
10952
|
+
const results = opts.name === void 0 ? unordered : stableSortImportBindsLast(unordered);
|
|
10953
|
+
const hiddenByExcludeTests = sweep.hiddenByExcludeTests;
|
|
10954
|
+
if (excludeTests && sweep.keptCount === 0 && hiddenByExcludeTests > 0) {
|
|
10858
10955
|
const label = opts.name ?? opts.grep ?? "*";
|
|
10859
10956
|
const notice = `no non-test matches for '${label}' (${excludeTestsHiddenNote(hiddenByExcludeTests)})`;
|
|
10860
10957
|
if (opts.json === true) {
|
|
@@ -10862,7 +10959,7 @@ function runSymbol(opts) {
|
|
|
10862
10959
|
}
|
|
10863
10960
|
return { text: `token-goat: ${notice}`, code: 0 };
|
|
10864
10961
|
}
|
|
10865
|
-
if (matchesGrep !== void 0 &&
|
|
10962
|
+
if (matchesGrep !== void 0 && sweep.keptCount === 0 && preFilterCount > 0) {
|
|
10866
10963
|
if (opts.json === true) {
|
|
10867
10964
|
const text2 = displaySafeJson({ items: [], truncated: false, totalCount: 0 });
|
|
10868
10965
|
return { text: text2, code: 0 };
|
|
@@ -10875,8 +10972,14 @@ function runSymbol(opts) {
|
|
|
10875
10972
|
const indexEmpty = emptyIndexRoot !== null && isIndexEmptyForProject(globalDbPath(), emptyIndexRoot);
|
|
10876
10973
|
if (opts.name !== void 0 && emptyIndexRoot !== null) {
|
|
10877
10974
|
const rootDir = emptyIndexRoot;
|
|
10878
|
-
const
|
|
10879
|
-
const
|
|
10975
|
+
const exactMatches = [];
|
|
10976
|
+
const allNames = /* @__PURE__ */ new Set();
|
|
10977
|
+
const structuredFileSet = /* @__PURE__ */ new Set();
|
|
10978
|
+
forEachSymbol({ rootDir }, (s) => {
|
|
10979
|
+
allNames.add(s.name);
|
|
10980
|
+
structuredFileSet.add(s.filePath);
|
|
10981
|
+
if (s.name === opts.name) exactMatches.push(s);
|
|
10982
|
+
});
|
|
10880
10983
|
if (exactMatches.length > 0) {
|
|
10881
10984
|
const shown = exactMatches.slice(0, DIDYOUMEAN_LIMIT);
|
|
10882
10985
|
const where = shown.map((s) => `${s.kind} at ${formatSymbolLocation(toDisplayPath(rootDir, s.filePath), s.lineStart)}`).join("; ");
|
|
@@ -10886,12 +10989,12 @@ function runSymbol(opts) {
|
|
|
10886
10989
|
text2 += `
|
|
10887
10990
|
'${opts.name}' IS indexed (${where}${more}) -- ${widen}`;
|
|
10888
10991
|
} else {
|
|
10889
|
-
const candidates = rankSimilarNames(
|
|
10992
|
+
const candidates = rankSimilarNames([...allNames], opts.name);
|
|
10890
10993
|
text2 += candidates.length > 0 ? `
|
|
10891
10994
|
${didYouMean(candidates)}` : indexEmpty ? "" : `
|
|
10892
10995
|
Try: token-goat semantic "${opts.name}"`;
|
|
10893
10996
|
}
|
|
10894
|
-
const structuredFiles = [...
|
|
10997
|
+
const structuredFiles = [...structuredFileSet].sort();
|
|
10895
10998
|
const hit = findStructuredKeyPath(opts.name, structuredFiles);
|
|
10896
10999
|
if (hit !== null) {
|
|
10897
11000
|
const display = toDisplayPath(rootDir, hit.filePath);
|
|
@@ -10917,8 +11020,8 @@ ${emptyIndexMessage(emptyIndexRoot)}`;
|
|
|
10917
11020
|
let trueTotal;
|
|
10918
11021
|
let truncatedFlag;
|
|
10919
11022
|
if (anyClientFilter) {
|
|
10920
|
-
trueTotal =
|
|
10921
|
-
truncatedFlag = capped.truncated || results.length <
|
|
11023
|
+
trueTotal = sweep.keptCount;
|
|
11024
|
+
truncatedFlag = capped.truncated || results.length < sweep.keptCount;
|
|
10922
11025
|
} else {
|
|
10923
11026
|
trueTotal = countSymbols(queryOpts);
|
|
10924
11027
|
truncatedFlag = capped.truncated || trueTotal > results.length;
|
|
@@ -10954,7 +11057,7 @@ ${preview}${elided}` : header;
|
|
|
10954
11057
|
const warning = opts.file !== void 0 ? staleWarning(resolveIndexPath(opts.file, opts.projectRoot ?? process.cwd())) : "";
|
|
10955
11058
|
const text = guardText(warning + blocks.join("\n\n"), "symbol");
|
|
10956
11059
|
recordReadStat("symbol_lookup", fullSourceBytes, text, opts.name ?? opts.file ?? opts.grep);
|
|
10957
|
-
const symbolTotal = () => anyClientFilter ? { count:
|
|
11060
|
+
const symbolTotal = () => anyClientFilter ? { count: sweep.keptCount, exact: true } : { count: countSymbols(queryOpts), exact: true };
|
|
10958
11061
|
return { text: text + truncationFooter(results.length, effectiveLimit, symbolTotal, "matches", "--limit"), code: 0 };
|
|
10959
11062
|
}
|
|
10960
11063
|
function truncationFooter(shown, limit, total, plural, flag) {
|
|
@@ -10965,6 +11068,7 @@ token-goat: ${notice}`;
|
|
|
10965
11068
|
}
|
|
10966
11069
|
function refsTotal(clientFiltered, filteredTotal, shown, countExact, preScanCount, scanLimit) {
|
|
10967
11070
|
if (!clientFiltered) return { count: countExact(), exact: true };
|
|
11071
|
+
if (scanLimit < 0) return { count: filteredTotal ?? shown, exact: true };
|
|
10968
11072
|
return { count: filteredTotal ?? shown, exact: preScanCount < scanLimit };
|
|
10969
11073
|
}
|
|
10970
11074
|
function truncationNotice(shown, limit, total, plural, flag) {
|
|
@@ -11017,7 +11121,7 @@ function runRead(opts) {
|
|
|
11017
11121
|
const crossFileLead = formatCrossFileLead("read", symbol, file, opts.projectRoot);
|
|
11018
11122
|
if (crossFileLead !== "") messages.push(crossFileLead);
|
|
11019
11123
|
const resolved = resolveIndexPath(file, opts.projectRoot ?? process.cwd());
|
|
11020
|
-
const scanned = querySymbols({ filePath: resolved, limit:
|
|
11124
|
+
const scanned = querySymbols({ filePath: resolved, limit: FIND_SCAN_LIMIT }).map((s) => s.name);
|
|
11021
11125
|
const closes = rankSimilarNames(scanned, symbol);
|
|
11022
11126
|
if (closes.length > 0) messages.push(didYouMean(closes));
|
|
11023
11127
|
else if (scanned.length > 0) {
|
|
@@ -11186,9 +11290,9 @@ function renderRefsTargets(targets, opts, {
|
|
|
11186
11290
|
const refRows = [];
|
|
11187
11291
|
for (const { file, symbol, key } of targets) {
|
|
11188
11292
|
const queryOpts = { name: symbol };
|
|
11189
|
-
if (opts.excludeTests === true || opts.grep !== void 0) queryOpts.limit =
|
|
11293
|
+
if (opts.excludeTests === true || opts.grep !== void 0) queryOpts.limit = UNBOUNDED_QUERY_LIMIT;
|
|
11190
11294
|
else if (opts.limit !== void 0) queryOpts.limit = opts.limit;
|
|
11191
|
-
else if (opts.top !== void 0) queryOpts.limit =
|
|
11295
|
+
else if (opts.top !== void 0) queryOpts.limit = UNBOUNDED_QUERY_LIMIT;
|
|
11192
11296
|
const rootDir = refsRootDir(opts);
|
|
11193
11297
|
if (rootDir !== void 0) queryOpts.rootDir = rootDir;
|
|
11194
11298
|
const scanned = queryRefs(queryOpts);
|
|
@@ -11258,7 +11362,7 @@ function renderRefsTargets(targets, opts, {
|
|
|
11258
11362
|
const fullSourceBytes = refsSearchBaselineBytes(refRows);
|
|
11259
11363
|
if (opts.json === true) {
|
|
11260
11364
|
const text2 = displaySafeJson(jsonOut);
|
|
11261
|
-
|
|
11365
|
+
emit(text2);
|
|
11262
11366
|
if (anyFound) recordReadStat("symbol_read", fullSourceBytes, text2, opts.spec);
|
|
11263
11367
|
return anyFound ? 0 : 1;
|
|
11264
11368
|
}
|
|
@@ -11269,11 +11373,11 @@ function renderRefsTargets(targets, opts, {
|
|
|
11269
11373
|
}
|
|
11270
11374
|
function runRefs(opts) {
|
|
11271
11375
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
11272
|
-
|
|
11376
|
+
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
11273
11377
|
return 1;
|
|
11274
11378
|
}
|
|
11275
11379
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
11276
|
-
|
|
11380
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
11277
11381
|
return 1;
|
|
11278
11382
|
}
|
|
11279
11383
|
const baseConfined = confinedProjectRoot();
|
|
@@ -11282,13 +11386,13 @@ function runRefs(opts) {
|
|
|
11282
11386
|
const requested = opts.projectRoot;
|
|
11283
11387
|
const projectDenial = requested === void 0 || confinedRoot !== baseConfined ? null : confinementRefusal("--project", requested, baseConfined);
|
|
11284
11388
|
if (projectDenial !== null) {
|
|
11285
|
-
|
|
11389
|
+
emitErr(projectDenial);
|
|
11286
11390
|
return 1;
|
|
11287
11391
|
}
|
|
11288
11392
|
for (const file2 of refsSpecFiles(opts.spec)) {
|
|
11289
11393
|
const denial = confinementRefusal("This file", resolveIndexPath(file2, opts.projectRoot ?? process.cwd()), confinedRoot);
|
|
11290
11394
|
if (denial !== null) {
|
|
11291
|
-
|
|
11395
|
+
emitErr(denial);
|
|
11292
11396
|
return 1;
|
|
11293
11397
|
}
|
|
11294
11398
|
}
|
|
@@ -11319,9 +11423,9 @@ function runRefsSingle(opts) {
|
|
|
11319
11423
|
const symName = symbol ?? file;
|
|
11320
11424
|
const queryOpts = { name: symName };
|
|
11321
11425
|
const defFileHint = symbol !== void 0 ? resolveIndexPath(file, opts.projectRoot ?? process.cwd()) : void 0;
|
|
11322
|
-
if (opts.excludeTests === true || opts.grep !== void 0) queryOpts.limit =
|
|
11426
|
+
if (opts.excludeTests === true || opts.grep !== void 0) queryOpts.limit = UNBOUNDED_QUERY_LIMIT;
|
|
11323
11427
|
else if (opts.limit !== void 0) queryOpts.limit = opts.limit;
|
|
11324
|
-
else if (opts.top !== void 0) queryOpts.limit =
|
|
11428
|
+
else if (opts.top !== void 0) queryOpts.limit = UNBOUNDED_QUERY_LIMIT;
|
|
11325
11429
|
const rootDir = refsRootDir(opts);
|
|
11326
11430
|
if (rootDir !== void 0) queryOpts.rootDir = rootDir;
|
|
11327
11431
|
const scanned = queryRefs(queryOpts);
|
|
@@ -11347,39 +11451,39 @@ function runRefsSingle(opts) {
|
|
|
11347
11451
|
if (results.length === 0) {
|
|
11348
11452
|
if (matchesGrep !== void 0 && preGrepCount > 0) {
|
|
11349
11453
|
if (opts.json === true) {
|
|
11350
|
-
|
|
11454
|
+
emit(displaySafeJson({ items: [], truncated: false, totalCount: 0, hiddenByGrep: preGrepCount }));
|
|
11351
11455
|
return 0;
|
|
11352
11456
|
}
|
|
11353
|
-
|
|
11457
|
+
emit(grepFilteredToEmptyNotice(preGrepCount, opts.grep ?? "", "reference", "references"));
|
|
11354
11458
|
return 0;
|
|
11355
11459
|
}
|
|
11356
11460
|
if (opts.excludeTests === true && suppressed > 0) {
|
|
11357
|
-
|
|
11461
|
+
emitErr(`No non-test references found for '${symName}' (${excludeTestsHiddenNote(suppressed)})`);
|
|
11358
11462
|
return 1;
|
|
11359
11463
|
}
|
|
11360
11464
|
const rootDir2 = opts.projectRoot ?? resolveProjectRoot({ project: process.cwd() });
|
|
11361
11465
|
const defRows = querySymbols({ name: symName, rootDir: rootDir2, limit: REF_BLIND_DEF_PROBE_LIMIT });
|
|
11362
11466
|
if (defRows.length === 0) {
|
|
11363
|
-
|
|
11364
|
-
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir2))
|
|
11467
|
+
emitErr(`Symbol not found: ${symName}${unknownSymbolSuggestion(symName, rootDir2)}`);
|
|
11468
|
+
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir2)) emitErr(emptyIndexMessage(rootDir2));
|
|
11365
11469
|
return 1;
|
|
11366
11470
|
}
|
|
11367
11471
|
const defPaths = defFileHint !== void 0 ? [defFileHint] : defRows.map((r) => r.filePath);
|
|
11368
11472
|
const firstDefPath = defPaths[0];
|
|
11369
11473
|
if (firstDefPath !== void 0 && defPaths.every((fp) => !isRefIndexedFile(fp))) {
|
|
11370
|
-
|
|
11474
|
+
emitErr(refBlindLanguageNotice(symName, detectLanguageOfFile(firstDefPath), refsDisplayPath(firstDefPath)));
|
|
11371
11475
|
return 1;
|
|
11372
11476
|
}
|
|
11373
11477
|
const kindRows = defFileHint !== void 0 ? querySymbols({ name: symName, filePath: defFileHint, rootDir: rootDir2, limit: REF_BLIND_DEF_PROBE_LIMIT }) : defRows;
|
|
11374
11478
|
const kindVerdict = refBlindKindVerdict(kindRows);
|
|
11375
11479
|
if (kindVerdict.allBlind) {
|
|
11376
|
-
|
|
11480
|
+
emitErr(refBlindKindNotice(symName, kindVerdict.blindKinds));
|
|
11377
11481
|
return 1;
|
|
11378
11482
|
}
|
|
11379
|
-
|
|
11380
|
-
if (kindVerdict.blindCount > 0)
|
|
11483
|
+
emitErr(`No references found for '${symName}'`);
|
|
11484
|
+
if (kindVerdict.blindCount > 0) emitErr(refBlindKindPartialNote(symName, kindVerdict.blindKinds, kindVerdict.blindCount, kindRows.length));
|
|
11381
11485
|
if (opts.json !== true) {
|
|
11382
|
-
if (isIndexEmptyForProject(globalDbPath(), rootDir2))
|
|
11486
|
+
if (isIndexEmptyForProject(globalDbPath(), rootDir2)) emitErr(emptyIndexMessage(rootDir2));
|
|
11383
11487
|
}
|
|
11384
11488
|
return 1;
|
|
11385
11489
|
}
|
|
@@ -11396,14 +11500,14 @@ function runRefsSingle(opts) {
|
|
|
11396
11500
|
}
|
|
11397
11501
|
const hiddenByGrep = matchesGrep !== void 0 ? preGrepCount - (filteredTotal ?? results.length) : 0;
|
|
11398
11502
|
const text2 = displaySafeJson({ ...payload, ...hiddenByGrep > 0 ? { hiddenByGrep } : {} });
|
|
11399
|
-
|
|
11503
|
+
emit(text2);
|
|
11400
11504
|
recordReadStat("symbol_read", fullSourceBytes, text2, symName);
|
|
11401
11505
|
return 0;
|
|
11402
11506
|
}
|
|
11403
11507
|
const lines = opts.top !== void 0 ? renderTopFilesSummary(results, opts.top, suppressed) : opts.callers === true ? [...opts.excludeTests === true && suppressed > 0 ? [`${countNoun(results.length, "reference")} (${excludeTestsHiddenNote(suppressed)})`] : [], ...renderCallerGroups(results, opts.context ?? 0)] : [...opts.excludeTests === true && suppressed > 0 ? [`${countNoun(results.length, "reference")} (${excludeTestsHiddenNote(suppressed)})`] : [], ...results.flatMap((ref) => renderRefLines(ref, opts.context ?? 0, ""))];
|
|
11404
11508
|
const refsFooter = opts.top !== void 0 ? "" : truncationFooter(results.length, opts.limit ?? 100, () => refsTotal(clientFiltered, filteredTotal, results.length, () => countRefs(queryOpts), preScanCount, scanLimit), "references", "--limit");
|
|
11405
11509
|
const text = lines.join("\n");
|
|
11406
|
-
|
|
11510
|
+
emit(guardText(text, "symbol") + refsFooter);
|
|
11407
11511
|
recordReadStat("symbol_read", fullSourceBytes, text + refsFooter, symName);
|
|
11408
11512
|
return 0;
|
|
11409
11513
|
}
|
|
@@ -11459,11 +11563,11 @@ function renderCallerGroups(refs, contextLines = 0) {
|
|
|
11459
11563
|
function runPrSlice(opts) {
|
|
11460
11564
|
const parsed = parsePrSliceArg(opts.slice);
|
|
11461
11565
|
if (parsed === null) {
|
|
11462
|
-
|
|
11566
|
+
emitErr(`Invalid slice '${opts.slice}' -- expected one of: files, diff:<path>, comments, description`);
|
|
11463
11567
|
return 1;
|
|
11464
11568
|
}
|
|
11465
11569
|
if (!isGhAvailable()) {
|
|
11466
|
-
|
|
11570
|
+
emitErr("gh (GitHub CLI) not found on PATH -- install it from https://cli.github.com and run `gh auth login`");
|
|
11467
11571
|
return 1;
|
|
11468
11572
|
}
|
|
11469
11573
|
let repo = opts.repo;
|
|
@@ -11477,21 +11581,21 @@ function runPrSlice(opts) {
|
|
|
11477
11581
|
}
|
|
11478
11582
|
const resolved = remoteUrl.length > 0 ? parseGithubRepoFromRemoteUrl(remoteUrl) : null;
|
|
11479
11583
|
if (resolved === null) {
|
|
11480
|
-
|
|
11584
|
+
emitErr("Could not resolve a GitHub repo from the current directory's git remote 'origin' -- pass --repo owner/repo");
|
|
11481
11585
|
return 1;
|
|
11482
11586
|
}
|
|
11483
11587
|
repo = resolved;
|
|
11484
11588
|
}
|
|
11485
11589
|
if (!isSafeRepoSlug(repo)) {
|
|
11486
|
-
|
|
11590
|
+
emitErr(`"${repo}" is not a plain owner/name repository slug -- pass --repo owner/repo`);
|
|
11487
11591
|
return 1;
|
|
11488
11592
|
}
|
|
11489
11593
|
if (!isSafePrNumber(opts.pr)) {
|
|
11490
|
-
|
|
11594
|
+
emitErr(`"${opts.pr}" is not a pull request number`);
|
|
11491
11595
|
return 1;
|
|
11492
11596
|
}
|
|
11493
11597
|
if (!isGhAuthenticated()) {
|
|
11494
|
-
|
|
11598
|
+
emitErr("gh is not authenticated -- run `gh auth login`");
|
|
11495
11599
|
return 1;
|
|
11496
11600
|
}
|
|
11497
11601
|
try {
|
|
@@ -11502,7 +11606,7 @@ function runPrSlice(opts) {
|
|
|
11502
11606
|
if (opts.json === true) {
|
|
11503
11607
|
const capped = guardJsonRows(files);
|
|
11504
11608
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount }, 0);
|
|
11505
|
-
|
|
11609
|
+
emit(jsonText);
|
|
11506
11610
|
recordReadStat("pr_slice", fullSourceBytes, jsonText, `${repo}#${opts.pr} files`);
|
|
11507
11611
|
} else {
|
|
11508
11612
|
const text = formatFilesSlice(files);
|
|
@@ -11515,14 +11619,14 @@ function runPrSlice(opts) {
|
|
|
11515
11619
|
const diffText = fetchPrDiff(opts.pr, repo);
|
|
11516
11620
|
const rawFileDiff = extractFileDiff(diffText, parsed.path);
|
|
11517
11621
|
if (rawFileDiff === null) {
|
|
11518
|
-
|
|
11622
|
+
emitErr(`No diff found for '${parsed.path}' in PR #${opts.pr}`);
|
|
11519
11623
|
return 1;
|
|
11520
11624
|
}
|
|
11521
11625
|
const fileDiff = redactSecrets(rawFileDiff).text;
|
|
11522
11626
|
const fullSourceBytes = Buffer.byteLength(diffText, "utf8");
|
|
11523
11627
|
if (opts.json === true) {
|
|
11524
11628
|
const jsonText = displaySafeJson({ path: parsed.path, diff: fenceGithubFieldIfMatched(fileDiff) }, 0);
|
|
11525
|
-
|
|
11629
|
+
emit(jsonText);
|
|
11526
11630
|
recordReadStat("pr_slice", fullSourceBytes, jsonText, `${repo}#${opts.pr} diff:${parsed.path}`);
|
|
11527
11631
|
} else {
|
|
11528
11632
|
emitGuarded(fenceGithubText(fileDiff), "pr-slice");
|
|
@@ -11542,7 +11646,7 @@ function runPrSlice(opts) {
|
|
|
11542
11646
|
const fencedComments = comments.map((c) => ({ ...c, body: fenceGithubFieldIfMatched(c.body) }));
|
|
11543
11647
|
const capped = guardJsonRows(fencedComments);
|
|
11544
11648
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount }, 0);
|
|
11545
|
-
|
|
11649
|
+
emit(jsonText);
|
|
11546
11650
|
recordReadStat("pr_slice", fullSourceBytes, jsonText, `${repo}#${opts.pr} comments`);
|
|
11547
11651
|
} else {
|
|
11548
11652
|
const text = formatCommentsSlice(comments);
|
|
@@ -11566,7 +11670,7 @@ function runPrSlice(opts) {
|
|
|
11566
11670
|
body: desc.body !== null ? fenceGithubFieldIfMatched(desc.body) : null
|
|
11567
11671
|
};
|
|
11568
11672
|
const jsonText = displaySafeJson(fencedDesc, 0);
|
|
11569
|
-
|
|
11673
|
+
emit(jsonText);
|
|
11570
11674
|
recordReadStat("pr_slice", fullSourceBytes, jsonText, `${repo}#${opts.pr} description`);
|
|
11571
11675
|
} else {
|
|
11572
11676
|
const text = formatDescriptionSlice(desc);
|
|
@@ -11577,7 +11681,7 @@ function runPrSlice(opts) {
|
|
|
11577
11681
|
}
|
|
11578
11682
|
}
|
|
11579
11683
|
} catch (e) {
|
|
11580
|
-
|
|
11684
|
+
emitErr(extractErrorMessage(e));
|
|
11581
11685
|
return 1;
|
|
11582
11686
|
}
|
|
11583
11687
|
}
|
|
@@ -11676,7 +11780,7 @@ function runGrep(opts) {
|
|
|
11676
11780
|
const contextLines = opts.context ?? 0;
|
|
11677
11781
|
const guarded = compileGuardedRegex(opts.pattern);
|
|
11678
11782
|
if (!guarded.ok) {
|
|
11679
|
-
|
|
11783
|
+
emitErr(`Invalid regex: ${opts.pattern} -- ${guarded.reason}`);
|
|
11680
11784
|
return 1;
|
|
11681
11785
|
}
|
|
11682
11786
|
const regex = guarded.re;
|
|
@@ -11762,7 +11866,7 @@ function runGrep(opts) {
|
|
|
11762
11866
|
}
|
|
11763
11867
|
for (const searchPath of searchPaths) {
|
|
11764
11868
|
if (!fileExists2(searchPath)) {
|
|
11765
|
-
|
|
11869
|
+
emitErr(`Path not found: ${searchPath}`);
|
|
11766
11870
|
return 1;
|
|
11767
11871
|
}
|
|
11768
11872
|
const stat = fs12.statSync(searchPath);
|
|
@@ -11789,7 +11893,7 @@ function runGrep(opts) {
|
|
|
11789
11893
|
}
|
|
11790
11894
|
}
|
|
11791
11895
|
if (hits.length === 0) {
|
|
11792
|
-
|
|
11896
|
+
emitErr(`No matches for '${opts.pattern}'`);
|
|
11793
11897
|
return 1;
|
|
11794
11898
|
}
|
|
11795
11899
|
const truncated = hits.slice(0, maxLines);
|
|
@@ -11805,32 +11909,44 @@ function runGrep(opts) {
|
|
|
11805
11909
|
hit.symbol = enc === null ? null : { name: enc.name, kind: enc.kind, lineStart: enc.lineStart, lineEnd: enc.lineEnd };
|
|
11806
11910
|
}
|
|
11807
11911
|
for (const file of new Set(truncated.map((h) => h.file).filter(isVirtualIndexedPath))) {
|
|
11808
|
-
|
|
11912
|
+
emit(virtualIndexedScopeNote(displaySafeText(file), "a match in it cannot be attributed to a symbol and these hits carry no label"));
|
|
11809
11913
|
}
|
|
11810
11914
|
}
|
|
11811
11915
|
if (opts.json === true) {
|
|
11812
11916
|
const payload = { items: truncated, truncated: hits.length > maxLines, totalCount: hits.length };
|
|
11813
|
-
|
|
11917
|
+
emit(displaySafeJson(payload));
|
|
11814
11918
|
return 0;
|
|
11815
11919
|
}
|
|
11816
11920
|
for (const hit of truncated) {
|
|
11817
11921
|
const symbolTag = opts.symbol === true && hit.symbol != null ? ` [${hit.symbol.name} (${hit.symbol.kind})]` : "";
|
|
11818
11922
|
if (hit.context !== void 0) {
|
|
11819
|
-
for (const line of renderContextWindow(hit.file, hit.line, hit.context, symbolTag))
|
|
11923
|
+
for (const line of renderContextWindow(hit.file, hit.line, hit.context, symbolTag)) emit(line);
|
|
11820
11924
|
} else {
|
|
11821
|
-
|
|
11925
|
+
emit(`${displaySafeText(hit.file)}:${hit.line}: ${hit.text}${symbolTag}`);
|
|
11822
11926
|
}
|
|
11823
11927
|
}
|
|
11824
11928
|
if (hits.length > maxLines) {
|
|
11825
|
-
|
|
11826
|
-
|
|
11827
|
-
|
|
11828
|
-
|
|
11829
|
-
|
|
11929
|
+
emitErr(`... (${hits.length - maxLines} more lines omitted)`);
|
|
11930
|
+
emitErr(`Tip: To avoid broad grepping and reduce token expenditure, locate specific symbols with:`);
|
|
11931
|
+
emitErr(` token-goat symbol <name>`);
|
|
11932
|
+
emitErr(` token-goat locate <name>`);
|
|
11933
|
+
emitErr(` token-goat outline <file> / token-goat skeleton <file>`);
|
|
11830
11934
|
}
|
|
11831
11935
|
return 0;
|
|
11832
11936
|
}
|
|
11833
11937
|
var RRF_K = 60;
|
|
11938
|
+
function applyRelevanceFloor(hits, floor) {
|
|
11939
|
+
const kept = [];
|
|
11940
|
+
let nearestRejected = null;
|
|
11941
|
+
for (const h of hits) {
|
|
11942
|
+
if (h.distance <= floor) {
|
|
11943
|
+
kept.push(h);
|
|
11944
|
+
} else if (nearestRejected === null || h.distance < nearestRejected) {
|
|
11945
|
+
nearestRejected = h.distance;
|
|
11946
|
+
}
|
|
11947
|
+
}
|
|
11948
|
+
return { kept, nearestRejected };
|
|
11949
|
+
}
|
|
11834
11950
|
async function runSemantic(query, opts) {
|
|
11835
11951
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
11836
11952
|
const message = `--limit must be a positive number, got: ${opts.limit}`;
|
|
@@ -11919,7 +12035,19 @@ async function runSemantic(query, opts) {
|
|
|
11919
12035
|
}
|
|
11920
12036
|
}
|
|
11921
12037
|
}
|
|
11922
|
-
|
|
12038
|
+
let floorNearestRejected = null;
|
|
12039
|
+
if (rawHits.length > 0) {
|
|
12040
|
+
const floor = loadConfig().semantic.max_distance;
|
|
12041
|
+
const { kept, nearestRejected } = applyRelevanceFloor(rawHits, floor);
|
|
12042
|
+
floorNearestRejected = nearestRejected;
|
|
12043
|
+
if (kept.length === 0 && nearestRejected !== null) {
|
|
12044
|
+
console.warn(
|
|
12045
|
+
`Matching on meaning found nothing within ${floor} (closest was ${nearestRejected.toFixed(3)}); these results come from keyword search alone. Raise semantic.max_distance to see weaker matches.`
|
|
12046
|
+
);
|
|
12047
|
+
}
|
|
12048
|
+
rawHits = kept;
|
|
12049
|
+
}
|
|
12050
|
+
if (rawHits.length === 0 && floorNearestRejected === null && isAvailable() && preflight.status === "ready" && !searchSemanticError) {
|
|
11923
12051
|
try {
|
|
11924
12052
|
const enabled = loadConfig().indexing.embeddings_enabled;
|
|
11925
12053
|
const { indexedFiles, embeddedFiles } = enabled ? getEmbeddingCoverage(globalDbPath(), rootDir) : { indexedFiles: 0, embeddedFiles: 0 };
|
|
@@ -11947,7 +12075,9 @@ async function runSemantic(query, opts) {
|
|
|
11947
12075
|
kind: enclosing?.kind ?? null,
|
|
11948
12076
|
distance: h.distance,
|
|
11949
12077
|
previewText: h.text,
|
|
11950
|
-
rrf: 1 / (RRF_K + denseRank)
|
|
12078
|
+
rrf: 1 / (RRF_K + denseRank),
|
|
12079
|
+
inDense: true,
|
|
12080
|
+
inLexical: false
|
|
11951
12081
|
});
|
|
11952
12082
|
});
|
|
11953
12083
|
ftsRows.forEach((s, ftsRank) => {
|
|
@@ -11955,6 +12085,7 @@ async function runSemantic(query, opts) {
|
|
|
11955
12085
|
const existing = fused.get(key);
|
|
11956
12086
|
if (existing !== void 0) {
|
|
11957
12087
|
existing.rrf += 1 / (RRF_K + ftsRank);
|
|
12088
|
+
existing.inLexical = true;
|
|
11958
12089
|
} else {
|
|
11959
12090
|
fused.set(key, {
|
|
11960
12091
|
filePath: s.filePath,
|
|
@@ -11964,7 +12095,9 @@ async function runSemantic(query, opts) {
|
|
|
11964
12095
|
kind: s.kind,
|
|
11965
12096
|
distance: null,
|
|
11966
12097
|
previewText: s.body,
|
|
11967
|
-
rrf: 1 / (RRF_K + ftsRank)
|
|
12098
|
+
rrf: 1 / (RRF_K + ftsRank),
|
|
12099
|
+
inDense: false,
|
|
12100
|
+
inLexical: true
|
|
11968
12101
|
});
|
|
11969
12102
|
}
|
|
11970
12103
|
});
|
|
@@ -11987,12 +12120,15 @@ async function runSemantic(query, opts) {
|
|
|
11987
12120
|
warnIfFilesStale(hits.map((h) => h.filePath));
|
|
11988
12121
|
if (hits.length > 0) {
|
|
11989
12122
|
if (opts.json === true) {
|
|
11990
|
-
const items = hits.map((h) => ({
|
|
12123
|
+
const items = hits.map((h, i) => ({
|
|
11991
12124
|
filePath: toDisplayPath(rootDir, h.filePath),
|
|
11992
12125
|
name: h.name,
|
|
11993
12126
|
kind: h.kind,
|
|
11994
12127
|
startLine: h.startLine,
|
|
11995
12128
|
endLine: h.endLine,
|
|
12129
|
+
rank: i + 1,
|
|
12130
|
+
rrf: h.rrf,
|
|
12131
|
+
retrieval: h.inDense && h.inLexical ? "both" : h.inDense ? "dense" : "lexical",
|
|
11996
12132
|
distance: h.distance,
|
|
11997
12133
|
preview: previewLines(h.previewText, 3)
|
|
11998
12134
|
}));
|
|
@@ -12016,18 +12152,19 @@ async function runSemantic(query, opts) {
|
|
|
12016
12152
|
recordReadStat("semantic_search", sumFileSizes(hits.map((h) => h.filePath)), text3, query);
|
|
12017
12153
|
return { text: text3, code: 0 };
|
|
12018
12154
|
}
|
|
12019
|
-
const blocks = hits.map((h) => {
|
|
12155
|
+
const blocks = hits.map((h, i) => {
|
|
12156
|
+
const mark = h.inDense && h.inLexical ? ", +keyword" : "";
|
|
12020
12157
|
if (h.distance !== null) {
|
|
12021
12158
|
const suffix = h.name !== null ? ` \u2014 inside ${h.name} (${h.kind})` : "";
|
|
12022
|
-
return `# ${toDisplayPath(rootDir, h.filePath)}:${h.startLine}-${h.endLine} (distance ${h.distance.toFixed(3)})${suffix}
|
|
12159
|
+
return `# ${i + 1}. ${toDisplayPath(rootDir, h.filePath)}:${h.startLine}-${h.endLine} (distance ${h.distance.toFixed(3)}${mark})${suffix}
|
|
12023
12160
|
${previewLines(h.previewText, 3)}`;
|
|
12024
12161
|
}
|
|
12025
|
-
return `# ${h.name} (${h.kind}) \u2014 ${toDisplayPath(rootDir, h.filePath)}:${h.startLine}-${h.endLine}
|
|
12162
|
+
return `# ${i + 1}. ${h.name} (${h.kind}) \u2014 ${toDisplayPath(rootDir, h.filePath)}:${h.startLine}-${h.endLine} (keyword)
|
|
12026
12163
|
${previewLines(h.previewText, 3)}`;
|
|
12027
12164
|
});
|
|
12028
12165
|
const text2 = guardText(blocks.join("\n\n"), "semantic");
|
|
12029
12166
|
if (hits.length < eligibleCount) {
|
|
12030
|
-
|
|
12167
|
+
emitErr(`Showing ${hits.length} of ${candidatesClipped ? "at least " : ""}${countNoun(eligibleCount, "match", "matches")} (raise --limit to see the rest).`);
|
|
12031
12168
|
}
|
|
12032
12169
|
recordReadStat("semantic_search", sumFileSizes(hits.map((h) => h.filePath)), text2, query);
|
|
12033
12170
|
return { text: text2, code: 0 };
|
|
@@ -12127,7 +12264,7 @@ function fileExists3(p) {
|
|
|
12127
12264
|
return false;
|
|
12128
12265
|
}
|
|
12129
12266
|
}
|
|
12130
|
-
var
|
|
12267
|
+
var FIND_SCAN_LIMIT2 = FIND_SCAN_LIMIT;
|
|
12131
12268
|
var PARENT_IDENTIFIER_RE2 = /^[\w$]+$/;
|
|
12132
12269
|
function parseReadSpec(spec) {
|
|
12133
12270
|
const colonIdx = findSpecSeparator(spec);
|
|
@@ -12264,7 +12401,7 @@ function runLineRegion(range, opts) {
|
|
|
12264
12401
|
} else {
|
|
12265
12402
|
healStaleIndex(resolved);
|
|
12266
12403
|
}
|
|
12267
|
-
const symbols = querySymbols({ filePath: resolved, limit:
|
|
12404
|
+
const symbols = querySymbols({ filePath: resolved, limit: FIND_SCAN_LIMIT2 });
|
|
12268
12405
|
const regions = resolveLineRegions(symbols, allLines.length, start, end);
|
|
12269
12406
|
const asked = start === end ? `${start}` : `${start}-${end}`;
|
|
12270
12407
|
if (regions.length === 0) {
|
|
@@ -12328,7 +12465,7 @@ function formatAmbiguity(symbol, file, candidates, explicitRoot, commandName = "
|
|
|
12328
12465
|
const getFileSyms = (filePath) => {
|
|
12329
12466
|
let fileSyms = fileSymCache.get(filePath);
|
|
12330
12467
|
if (fileSyms === void 0) {
|
|
12331
|
-
fileSyms = querySymbols({ filePath, limit:
|
|
12468
|
+
fileSyms = querySymbols({ filePath, limit: FIND_SCAN_LIMIT2 });
|
|
12332
12469
|
fileSymCache.set(filePath, fileSyms);
|
|
12333
12470
|
}
|
|
12334
12471
|
return fileSyms;
|
|
@@ -12456,16 +12593,16 @@ function resolveSymbolSpec(spec, forceRefresh, projectRoot) {
|
|
|
12456
12593
|
function resolveSymbolSpecOrEmitError(commandName, spec, projectRoot) {
|
|
12457
12594
|
const { file, symbol } = parseReadSpec(spec);
|
|
12458
12595
|
if (symbol === void 0 || symbol === "") {
|
|
12459
|
-
|
|
12596
|
+
emitErr(`'token-goat ${commandName}' requires a 'file::symbol' spec (got '${spec}')`);
|
|
12460
12597
|
return null;
|
|
12461
12598
|
}
|
|
12462
12599
|
const resolution = resolveSymbolSpec(spec, void 0, projectRoot);
|
|
12463
12600
|
if (resolution.kind === "confined") {
|
|
12464
|
-
|
|
12601
|
+
emitErr(resolution.message);
|
|
12465
12602
|
return null;
|
|
12466
12603
|
}
|
|
12467
12604
|
if (resolution.kind === "ambiguous") {
|
|
12468
|
-
|
|
12605
|
+
emitErr(
|
|
12469
12606
|
formatAmbiguity(
|
|
12470
12607
|
resolution.symbol,
|
|
12471
12608
|
resolution.file,
|
|
@@ -12481,11 +12618,11 @@ function resolveSymbolSpecOrEmitError(commandName, spec, projectRoot) {
|
|
|
12481
12618
|
const crossFileLead = formatCrossFileLead(commandName, symbol, file, projectRoot);
|
|
12482
12619
|
if (crossFileLead !== "") messages.push(crossFileLead);
|
|
12483
12620
|
const resolved = resolveIndexPath(file, projectRoot ?? process.cwd());
|
|
12484
|
-
const scanned = querySymbols({ filePath: resolved, limit:
|
|
12621
|
+
const scanned = querySymbols({ filePath: resolved, limit: FIND_SCAN_LIMIT2 }).map((s) => s.name);
|
|
12485
12622
|
const closes = rankSimilarNames(scanned, symbol);
|
|
12486
12623
|
if (closes.length > 0) messages.push(didYouMean(closes));
|
|
12487
12624
|
else if (scanned.length > 0) messages.push(`Try: token-goat outline ${file}`);
|
|
12488
|
-
|
|
12625
|
+
emitErr(messages.join("\n"));
|
|
12489
12626
|
return null;
|
|
12490
12627
|
}
|
|
12491
12628
|
return resolution.entry;
|
|
@@ -12500,13 +12637,13 @@ var CONTENT_MAX_ITEMS = 256;
|
|
|
12500
12637
|
var CONTENT_MAX_BYTES = 32 * 1024 * 1024;
|
|
12501
12638
|
var CONTENT_MAX_ITEM_BYTES = CONTENT_MAX_INPUT_CHARS * 7;
|
|
12502
12639
|
var CONTENT_SUBDIR = "content";
|
|
12503
|
-
var TEXT_BYTES_PER_TOKEN =
|
|
12504
|
-
var BASE64URL_BYTES_PER_TOKEN =
|
|
12640
|
+
var TEXT_BYTES_PER_TOKEN = BYTES_PER_TOKEN.text;
|
|
12641
|
+
var BASE64URL_BYTES_PER_TOKEN = BYTES_PER_TOKEN.dense;
|
|
12505
12642
|
function estimateTextTokens(bytes) {
|
|
12506
|
-
return
|
|
12643
|
+
return savedTokensFromBytes(bytes, "text");
|
|
12507
12644
|
}
|
|
12508
12645
|
function estimateBase64urlTokens(bytes) {
|
|
12509
|
-
return
|
|
12646
|
+
return savedTokensFromBytes(bytes, "dense");
|
|
12510
12647
|
}
|
|
12511
12648
|
function assertInput(text) {
|
|
12512
12649
|
if (text.length > CONTENT_MAX_INPUT_CHARS) {
|
|
@@ -12617,6 +12754,8 @@ function resolveHandoff(name, opts = {}) {
|
|
|
12617
12754
|
export {
|
|
12618
12755
|
isAvailable2 as isAvailable,
|
|
12619
12756
|
loadError,
|
|
12757
|
+
emit,
|
|
12758
|
+
emitErr,
|
|
12620
12759
|
ALL_SYMBOLS_IN_FILE_LIMIT,
|
|
12621
12760
|
enclosingSymbol,
|
|
12622
12761
|
runDead,
|