token-goat 2.9.18 → 2.9.20
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 +5 -1
- package/dist/token-goat-chunk-2CLWWRFR.mjs +26 -0
- package/dist/{token-goat-chunk-LTYWLKAG.mjs → token-goat-chunk-2Q3N5KUQ.mjs} +1283 -1012
- package/dist/{token-goat-chunk-6LGVCCMY.mjs → token-goat-chunk-3OGZOFLS.mjs} +26 -16
- package/dist/{token-goat-chunk-QML7ITHJ.mjs → token-goat-chunk-3VTJC7KU.mjs} +693 -438
- package/dist/{token-goat-chunk-QIDLJGXZ.mjs → token-goat-chunk-6LJNM4ZZ.mjs} +29 -5
- package/dist/{token-goat-chunk-CA6V36KW.mjs → token-goat-chunk-74ADIZZX.mjs} +68 -50
- package/dist/{token-goat-chunk-52IMXJ2L.mjs → token-goat-chunk-ASTBLE2R.mjs} +4 -4
- package/dist/token-goat-chunk-AU2K2QHR.mjs +20 -0
- package/dist/token-goat-chunk-BQIC3AVL.mjs +292 -0
- package/dist/token-goat-chunk-CBXLE54Q.mjs +30 -0
- package/dist/{token-goat-chunk-LMFO66YD.mjs → token-goat-chunk-DA43OE7L.mjs} +1 -1
- package/dist/{token-goat-chunk-ARNRFR6M.mjs → token-goat-chunk-DNAF26L4.mjs} +1 -1
- package/dist/{token-goat-chunk-BFEWOMA3.mjs → token-goat-chunk-DPHJU3P7.mjs} +1186 -4573
- package/dist/{token-goat-chunk-OWSJJY5R.mjs → token-goat-chunk-DW4VKU7D.mjs} +5 -5
- package/dist/token-goat-chunk-DYUBZZNP.mjs +198 -0
- package/dist/{token-goat-chunk-W3E65QOW.mjs → token-goat-chunk-ERGHDBC6.mjs} +310 -47
- package/dist/token-goat-chunk-EUZKG7ZO.mjs +304 -0
- package/dist/{token-goat-chunk-5MMJAJF3.mjs → token-goat-chunk-FWYZVS3E.mjs} +324 -31
- package/dist/token-goat-chunk-G6SYQQO7.mjs +41 -0
- package/dist/{token-goat-chunk-YQZE5NS6.mjs → token-goat-chunk-GIPMOGOI.mjs} +6 -6
- package/dist/{token-goat-chunk-BWCRC23L.mjs → token-goat-chunk-H4VC5TR6.mjs} +29 -20
- package/dist/{token-goat-chunk-V3ZWBEHM.mjs → token-goat-chunk-I5PQRHFE.mjs} +103 -24
- package/dist/token-goat-chunk-ITWYDOKP.mjs +341 -0
- package/dist/{token-goat-chunk-I67CPTDD.mjs → token-goat-chunk-K3ZNBN4U.mjs} +19 -14
- package/dist/{token-goat-chunk-HPOFR6QX.mjs → token-goat-chunk-K5XPIUVB.mjs} +222 -61
- package/dist/token-goat-chunk-KT75DZK4.mjs +1989 -0
- package/dist/{token-goat-chunk-H3FONFBO.mjs → token-goat-chunk-MNJWG2ZO.mjs} +3 -3
- package/dist/{token-goat-chunk-GRI6HWX3.mjs → token-goat-chunk-MUJV7BR3.mjs} +1 -1
- package/dist/{token-goat-chunk-ERTXEKB6.mjs → token-goat-chunk-NMTKNYGF.mjs} +2 -0
- package/dist/{token-goat-chunk-LA3O4JGD.mjs → token-goat-chunk-ODF7H7WS.mjs} +3 -3
- package/dist/{token-goat-chunk-K4DG6EEF.mjs → token-goat-chunk-ONMU7BON.mjs} +7 -8
- package/dist/{token-goat-chunk-4EXFN2AW.mjs → token-goat-chunk-OZRSREKR.mjs} +2 -2
- package/dist/{token-goat-chunk-EPXNOKIV.mjs → token-goat-chunk-P4XBHZXU.mjs} +2 -2
- package/dist/{token-goat-chunk-CTOYJ232.mjs → token-goat-chunk-PAVWB4L4.mjs} +173 -1840
- package/dist/{token-goat-chunk-UENEL6KX.mjs → token-goat-chunk-PTW22MRC.mjs} +2 -2
- package/dist/token-goat-chunk-SL454EN5.mjs +1816 -0
- package/dist/token-goat-chunk-SP5QR2HN.mjs +1379 -0
- package/dist/{token-goat-chunk-7VLWNQDQ.mjs → token-goat-chunk-T46UKRFM.mjs} +1 -1
- package/dist/{token-goat-chunk-L7VCX33I.mjs → token-goat-chunk-T63VHOL3.mjs} +40 -10
- package/dist/token-goat-chunk-VSJGPEBB.mjs +248 -0
- package/dist/{token-goat-chunk-HIZXQVNU.mjs → token-goat-chunk-VYXGHGUY.mjs} +4 -4
- package/dist/token-goat-chunk-W6QYCWAT.mjs +128 -0
- package/dist/{token-goat-chunk-WFX2V3OF.mjs → token-goat-chunk-Z4ALQADF.mjs} +579 -422
- package/dist/token-goat-chunk-ZHFM4DHJ.mjs +324 -0
- package/dist/token-goat-hook.mjs +18 -12
- package/dist/token-goat.core.mjs +29 -20
- package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
- package/docs/cli.md +15 -13
- package/docs/install.md +1 -1
- package/docs/security.md +2 -2
- package/package.json +3 -2
- package/dist/token-goat-chunk-2KTZ6J7T.mjs +0 -173
- package/dist/token-goat-chunk-34OUJ2IE.mjs +0 -35
- package/dist/token-goat-chunk-RHHFEXKF.mjs +0 -93
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
isTextHeavy,
|
|
6
6
|
ocrImage,
|
|
7
7
|
ocrIntegrityFailed
|
|
8
|
-
} from "./token-goat-chunk-
|
|
8
|
+
} from "./token-goat-chunk-MNJWG2ZO.mjs";
|
|
9
9
|
import {
|
|
10
10
|
formatSqliteQueryTable,
|
|
11
11
|
formatSqliteSchema,
|
|
@@ -13,37 +13,43 @@ import {
|
|
|
13
13
|
getSqliteSchema,
|
|
14
14
|
getSqliteTables,
|
|
15
15
|
runReadOnlySqliteQuery
|
|
16
|
-
} from "./token-goat-chunk-
|
|
16
|
+
} from "./token-goat-chunk-DA43OE7L.mjs";
|
|
17
17
|
import {
|
|
18
18
|
ImageDecodeError,
|
|
19
|
+
LARGE_SYMBOL_LINE_THRESHOLD,
|
|
19
20
|
NOTEBOOK_CELL_LINES_SUFFIX,
|
|
20
21
|
SKIP_DIRS,
|
|
21
22
|
canShrinkFormat,
|
|
22
|
-
capJsonRows,
|
|
23
23
|
emptyIndexMessage,
|
|
24
24
|
enqueueDirtyPathSafe,
|
|
25
|
-
estimateTokens,
|
|
26
25
|
fenceUntrusted,
|
|
27
26
|
formatSymbolLocation,
|
|
28
27
|
getEmbeddingCoverage,
|
|
29
28
|
getTrackedFiles,
|
|
30
29
|
indexedSourceText,
|
|
31
|
-
|
|
30
|
+
isIgnoredIndexPath,
|
|
32
31
|
isIndexEmptyForProject,
|
|
33
32
|
isPrivateIpv4Octets,
|
|
34
33
|
isPrivateIpv6Groups,
|
|
35
34
|
isVirtualIndexedPath,
|
|
36
35
|
parseIpv6Groups,
|
|
37
36
|
probeImageMeta,
|
|
37
|
+
recordKnownRootThrottled,
|
|
38
|
+
resolveLineRegions,
|
|
38
39
|
scanAndRecord,
|
|
39
40
|
searchEvidenceSemantically,
|
|
40
41
|
shrinkImage,
|
|
41
|
-
trimToBudget,
|
|
42
42
|
urlPolicyDenialReason,
|
|
43
43
|
virtualIndexedScopeNote,
|
|
44
44
|
walkProject
|
|
45
|
-
} from "./token-goat-chunk-
|
|
45
|
+
} from "./token-goat-chunk-DPHJU3P7.mjs";
|
|
46
|
+
import {
|
|
47
|
+
capJsonRows,
|
|
48
|
+
estimateTokens,
|
|
49
|
+
trimToBudget
|
|
50
|
+
} from "./token-goat-chunk-ZHFM4DHJ.mjs";
|
|
46
51
|
import {
|
|
52
|
+
BYTES_PER_TOKEN,
|
|
47
53
|
colorStdout,
|
|
48
54
|
isBlobStale,
|
|
49
55
|
loadBlob,
|
|
@@ -51,8 +57,8 @@ import {
|
|
|
51
57
|
redactSecrets,
|
|
52
58
|
savedTokensFromBytes,
|
|
53
59
|
storeBlob,
|
|
54
|
-
|
|
55
|
-
} from "./token-goat-chunk-
|
|
60
|
+
stripAnsiEscapes
|
|
61
|
+
} from "./token-goat-chunk-K5XPIUVB.mjs";
|
|
56
62
|
import {
|
|
57
63
|
extractPdfMeta,
|
|
58
64
|
extractPdfOutline,
|
|
@@ -66,7 +72,7 @@ import {
|
|
|
66
72
|
parseWhereSpecs,
|
|
67
73
|
profileCsv,
|
|
68
74
|
queryCsv
|
|
69
|
-
} from "./token-goat-chunk-
|
|
75
|
+
} from "./token-goat-chunk-P4XBHZXU.mjs";
|
|
70
76
|
import {
|
|
71
77
|
MAX_ZIP_INPUT_BYTES,
|
|
72
78
|
MAX_ZIP_OUTPUT_BYTES,
|
|
@@ -101,7 +107,7 @@ import {
|
|
|
101
107
|
extractSolidity,
|
|
102
108
|
extractThrift,
|
|
103
109
|
stripLeadingAttributes
|
|
104
|
-
} from "./token-goat-chunk-
|
|
110
|
+
} from "./token-goat-chunk-MUJV7BR3.mjs";
|
|
105
111
|
import {
|
|
106
112
|
MAX_OVER_FETCH,
|
|
107
113
|
OVER_FETCH_FACTOR,
|
|
@@ -109,12 +115,13 @@ import {
|
|
|
109
115
|
findContainingSection,
|
|
110
116
|
indexFileSync,
|
|
111
117
|
isAvailable,
|
|
118
|
+
isImagePath,
|
|
112
119
|
isTreeSitterAvailable,
|
|
113
120
|
listSections,
|
|
114
121
|
mergeNearbyHits,
|
|
115
122
|
readSection,
|
|
116
123
|
searchSemantic
|
|
117
|
-
} from "./token-goat-chunk-
|
|
124
|
+
} from "./token-goat-chunk-ERGHDBC6.mjs";
|
|
118
125
|
import {
|
|
119
126
|
DEFAULT_QUERY_LIMIT,
|
|
120
127
|
countRefs,
|
|
@@ -127,7 +134,7 @@ import {
|
|
|
127
134
|
queryRefsByContext,
|
|
128
135
|
querySymbols,
|
|
129
136
|
searchSymbolsFts
|
|
130
|
-
} from "./token-goat-chunk-
|
|
137
|
+
} from "./token-goat-chunk-K3ZNBN4U.mjs";
|
|
131
138
|
import {
|
|
132
139
|
FILENAME_LANGUAGE,
|
|
133
140
|
TREE_SITTER_LANGUAGES,
|
|
@@ -146,7 +153,7 @@ import {
|
|
|
146
153
|
partialRefsReason,
|
|
147
154
|
redactIfDotenv,
|
|
148
155
|
unsupportedLanguageName
|
|
149
|
-
} from "./token-goat-chunk-
|
|
156
|
+
} from "./token-goat-chunk-T63VHOL3.mjs";
|
|
150
157
|
import {
|
|
151
158
|
fileIsAbsent,
|
|
152
159
|
findProject,
|
|
@@ -156,7 +163,7 @@ import {
|
|
|
156
163
|
loadConfig,
|
|
157
164
|
resolveProjectRoot,
|
|
158
165
|
shortFingerprint
|
|
159
|
-
} from "./token-goat-chunk-
|
|
166
|
+
} from "./token-goat-chunk-74ADIZZX.mjs";
|
|
160
167
|
import {
|
|
161
168
|
registerReset
|
|
162
169
|
} from "./token-goat-chunk-EEIDFMEM.mjs";
|
|
@@ -166,6 +173,7 @@ import {
|
|
|
166
173
|
atomicWriteBytes,
|
|
167
174
|
compileGrepMatcher,
|
|
168
175
|
countNoun,
|
|
176
|
+
dataDir,
|
|
169
177
|
decodeSource,
|
|
170
178
|
ensureNewline,
|
|
171
179
|
escapeRegExp,
|
|
@@ -188,7 +196,7 @@ import {
|
|
|
188
196
|
supportRequestLine,
|
|
189
197
|
windowsCmdQuoteArg,
|
|
190
198
|
withExtension
|
|
191
|
-
} from "./token-goat-chunk-
|
|
199
|
+
} from "./token-goat-chunk-6LJNM4ZZ.mjs";
|
|
192
200
|
import {
|
|
193
201
|
UNTRUSTED_FILE_TAG,
|
|
194
202
|
UNTRUSTED_GITHUB_TAG,
|
|
@@ -200,7 +208,7 @@ import {
|
|
|
200
208
|
normalizePath,
|
|
201
209
|
resolveIndexPath,
|
|
202
210
|
toDisplayPath
|
|
203
|
-
} from "./token-goat-chunk-
|
|
211
|
+
} from "./token-goat-chunk-NMTKNYGF.mjs";
|
|
204
212
|
import {
|
|
205
213
|
compileGuardedRegex
|
|
206
214
|
} from "./token-goat-chunk-GMOUBOX4.mjs";
|
|
@@ -878,6 +886,20 @@ function renderContextWindow(displayFile, matchLine, window, matchSuffix = "", i
|
|
|
878
886
|
);
|
|
879
887
|
}
|
|
880
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
|
+
|
|
881
903
|
// src/ref_blindness.ts
|
|
882
904
|
init_define_import_meta_env();
|
|
883
905
|
var REF_INDEXED_LANGUAGES = /* @__PURE__ */ new Set([
|
|
@@ -932,8 +954,8 @@ import { randomUUID } from "node:crypto";
|
|
|
932
954
|
// src/graph_traversal.ts
|
|
933
955
|
init_define_import_meta_env();
|
|
934
956
|
var DEFAULT_REF_QUERY_LIMIT = 500;
|
|
935
|
-
var ALL_SYMBOLS_IN_FILE_LIMIT =
|
|
936
|
-
var UNBOUNDED_REF_LIMIT =
|
|
957
|
+
var ALL_SYMBOLS_IN_FILE_LIMIT = UNBOUNDED_QUERY_LIMIT;
|
|
958
|
+
var UNBOUNDED_REF_LIMIT = UNBOUNDED_QUERY_LIMIT;
|
|
937
959
|
function enclosingSymbol(symbols, line) {
|
|
938
960
|
let best = null;
|
|
939
961
|
for (const s of symbols) {
|
|
@@ -1273,13 +1295,6 @@ function findCyclesCapped(graph) {
|
|
|
1273
1295
|
init_define_import_meta_env();
|
|
1274
1296
|
import * as fs from "node:fs";
|
|
1275
1297
|
import * as path2 from "node:path";
|
|
1276
|
-
function emit(text) {
|
|
1277
|
-
const payload = colorStdout() ? text : stripAnsi(text);
|
|
1278
|
-
process.stdout.write(ensureNewline(payload));
|
|
1279
|
-
}
|
|
1280
|
-
function emitErr(text) {
|
|
1281
|
-
process.stderr.write(ensureNewline(text));
|
|
1282
|
-
}
|
|
1283
1298
|
function runDead(opts) {
|
|
1284
1299
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
1285
1300
|
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
@@ -1947,21 +1962,14 @@ function renderModules(result, top) {
|
|
|
1947
1962
|
}
|
|
1948
1963
|
|
|
1949
1964
|
// src/graph_analysis.ts
|
|
1950
|
-
function emit2(text) {
|
|
1951
|
-
const payload = colorStdout() ? text : stripAnsi(text);
|
|
1952
|
-
process.stdout.write(ensureNewline(payload));
|
|
1953
|
-
}
|
|
1954
|
-
function emitErr2(text) {
|
|
1955
|
-
process.stderr.write(ensureNewline(text));
|
|
1956
|
-
}
|
|
1957
1965
|
function runSimilar(opts) {
|
|
1958
1966
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
1959
|
-
|
|
1967
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
1960
1968
|
return 1;
|
|
1961
1969
|
}
|
|
1962
1970
|
const sepIdx = opts.spec.lastIndexOf("::");
|
|
1963
1971
|
if (sepIdx < 0) {
|
|
1964
|
-
|
|
1972
|
+
emitErr(`Invalid spec - expected "file::symbol", got: ${opts.spec}`);
|
|
1965
1973
|
return 1;
|
|
1966
1974
|
}
|
|
1967
1975
|
const top = opts.top ?? 10;
|
|
@@ -1974,18 +1982,18 @@ function runSimilar(opts) {
|
|
|
1974
1982
|
const matches = hits.filter((h) => !(h.filePath === anchor.filePath && h.name === anchor.name));
|
|
1975
1983
|
const results = matches.slice(0, top);
|
|
1976
1984
|
if (matches.length > results.length) {
|
|
1977
|
-
|
|
1985
|
+
emitErr(`Showing top ${results.length} of ${matches.length} similar symbols (raise --top to see the rest).`);
|
|
1978
1986
|
}
|
|
1979
1987
|
if (opts.json === true) {
|
|
1980
|
-
|
|
1988
|
+
emit(displaySafeJson(results.map((h) => ({ name: h.name, kind: h.kind, file: h.filePath, line: h.lineStart }))));
|
|
1981
1989
|
return 0;
|
|
1982
1990
|
}
|
|
1983
|
-
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)}`);
|
|
1984
1992
|
return 0;
|
|
1985
1993
|
}
|
|
1986
1994
|
function runContextFor(opts) {
|
|
1987
1995
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
1988
|
-
|
|
1996
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
1989
1997
|
return 1;
|
|
1990
1998
|
}
|
|
1991
1999
|
const top = opts.top ?? 12;
|
|
@@ -1995,7 +2003,7 @@ function runContextFor(opts) {
|
|
|
1995
2003
|
const moreBeyondTop = fetched.length > top;
|
|
1996
2004
|
const hits = fetched.slice(0, top);
|
|
1997
2005
|
if (hits.length === 0) {
|
|
1998
|
-
|
|
2006
|
+
emitErr(`No matches found for '${opts.task}'`);
|
|
1999
2007
|
return 1;
|
|
2000
2008
|
}
|
|
2001
2009
|
const entries = [];
|
|
@@ -2014,19 +2022,19 @@ function runContextFor(opts) {
|
|
|
2014
2022
|
);
|
|
2015
2023
|
}
|
|
2016
2024
|
if (moreBeyondTop) notices.push(`More matches exist beyond --top ${top} (raise it to see them).`);
|
|
2017
|
-
for (const n of notices)
|
|
2025
|
+
for (const n of notices) emitErr(n);
|
|
2018
2026
|
if (opts.json === true) {
|
|
2019
|
-
|
|
2027
|
+
emit(displaySafeJson(entries));
|
|
2020
2028
|
return 0;
|
|
2021
2029
|
}
|
|
2022
|
-
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}"`);
|
|
2023
2031
|
return 0;
|
|
2024
2032
|
}
|
|
2025
2033
|
function runTestFor(opts) {
|
|
2026
2034
|
const filePath = resolveIndexPath(opts.file);
|
|
2027
2035
|
const symbols = querySymbols({ filePath, limit: ALL_SYMBOLS_IN_FILE_LIMIT });
|
|
2028
2036
|
if (!fs3.existsSync(opts.file) && symbols.length === 0) {
|
|
2029
|
-
|
|
2037
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
2030
2038
|
return 1;
|
|
2031
2039
|
}
|
|
2032
2040
|
const rootDir = resolveProjectRoot({ project: process.cwd() });
|
|
@@ -2051,22 +2059,22 @@ function runTestFor(opts) {
|
|
|
2051
2059
|
}
|
|
2052
2060
|
if (opts.json === true) {
|
|
2053
2061
|
const capped = guardJsonRows(results.map((r) => ({ ...r, testFile: toDisplayPath(rootDir, r.testFile) })));
|
|
2054
|
-
|
|
2062
|
+
emit(displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount }));
|
|
2055
2063
|
return 0;
|
|
2056
2064
|
}
|
|
2057
2065
|
if (results.length === 0) {
|
|
2058
|
-
|
|
2066
|
+
emit(`No test files found referencing symbols in '${displaySafeText(opts.file)}'`);
|
|
2059
2067
|
return 0;
|
|
2060
2068
|
}
|
|
2061
2069
|
for (const r of results) {
|
|
2062
|
-
|
|
2063
|
-
for (const fn of r.testFunctions)
|
|
2070
|
+
emit(toDisplayPath(rootDir, r.testFile));
|
|
2071
|
+
for (const fn of r.testFunctions) emit(` ${fn}`);
|
|
2064
2072
|
}
|
|
2065
2073
|
return 0;
|
|
2066
2074
|
}
|
|
2067
2075
|
function runCoverageGaps(opts) {
|
|
2068
2076
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
2069
|
-
|
|
2077
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
2070
2078
|
return 1;
|
|
2071
2079
|
}
|
|
2072
2080
|
const top = opts.top ?? 50;
|
|
@@ -2084,30 +2092,30 @@ function runCoverageGaps(opts) {
|
|
|
2084
2092
|
}
|
|
2085
2093
|
const sliced = gaps.slice(0, top);
|
|
2086
2094
|
if (gaps.length > sliced.length) {
|
|
2087
|
-
|
|
2095
|
+
emitErr(`Showing top ${sliced.length} of ${gaps.length} coverage gaps (raise --top to see the rest).`);
|
|
2088
2096
|
}
|
|
2089
2097
|
if (opts.json === true) {
|
|
2090
|
-
|
|
2098
|
+
emit(displaySafeJson(sliced));
|
|
2091
2099
|
return 0;
|
|
2092
2100
|
}
|
|
2093
2101
|
if (sliced.length === 0) {
|
|
2094
|
-
|
|
2095
|
-
if (isIndexEmptyForProject(globalDbPath(), rootDir))
|
|
2102
|
+
emit("No coverage gaps found.");
|
|
2103
|
+
if (isIndexEmptyForProject(globalDbPath(), rootDir)) emit(emptyIndexMessage(rootDir));
|
|
2096
2104
|
return 0;
|
|
2097
2105
|
}
|
|
2098
|
-
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}`);
|
|
2099
2107
|
return 0;
|
|
2100
2108
|
}
|
|
2101
2109
|
function runArch(opts) {
|
|
2102
2110
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
2103
|
-
|
|
2111
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
2104
2112
|
return 1;
|
|
2105
2113
|
}
|
|
2106
2114
|
const cwd = opts.cwd ?? process.cwd();
|
|
2107
2115
|
const top = opts.top ?? 10;
|
|
2108
2116
|
const { files, graph, importedBy, resolve: resolve8 } = buildImportGraph(cwd);
|
|
2109
2117
|
if (files.length === 0 && opts.json !== true) {
|
|
2110
|
-
|
|
2118
|
+
emit(`no tracked files found under '${toDisplayPath(getDisplayRoot(cwd), cwd)}' (is it a git repo?). Nothing to analyse.`);
|
|
2111
2119
|
return 0;
|
|
2112
2120
|
}
|
|
2113
2121
|
const allHubs = [...importedBy.entries()].sort((a, b) => b[1].size - a[1].size).map(([f, importers]) => ({ file: f, importedBy: importers.size }));
|
|
@@ -2120,22 +2128,22 @@ function runArch(opts) {
|
|
|
2120
2128
|
const moduleResult = opts.modules === true ? detectModules({ files, graph, importedBy, resolve: resolve8 }, cwd, top) : null;
|
|
2121
2129
|
if (opts.json === true) {
|
|
2122
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 };
|
|
2123
|
-
|
|
2131
|
+
emit(displaySafeJson({ hubs, hubsTotal, hubsTruncated: hubs.length < hubsTotal, entryPoints, entryPointsTotal, entryPointsTruncated: entryPoints.length < entryPointsTotal, cycles, ...cyclesTruncated ? { cyclesTruncated: true } : {}, ...modulePayload }));
|
|
2124
2132
|
return 0;
|
|
2125
2133
|
}
|
|
2126
|
-
|
|
2127
|
-
for (const h of hubs)
|
|
2128
|
-
|
|
2129
|
-
for (const e of entryPoints)
|
|
2130
|
-
|
|
2131
|
-
for (const c of cycles)
|
|
2132
|
-
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);
|
|
2133
2141
|
return 0;
|
|
2134
2142
|
}
|
|
2135
2143
|
function runBlame(opts) {
|
|
2136
2144
|
const sepIdx = opts.spec.lastIndexOf("::");
|
|
2137
2145
|
if (sepIdx < 0) {
|
|
2138
|
-
|
|
2146
|
+
emitErr(`Invalid spec - expected "file::symbol", got: ${displaySafeText(opts.spec)}`);
|
|
2139
2147
|
return 1;
|
|
2140
2148
|
}
|
|
2141
2149
|
const cwd = opts.cwd ?? process.cwd();
|
|
@@ -2148,12 +2156,12 @@ function runBlame(opts) {
|
|
|
2148
2156
|
try {
|
|
2149
2157
|
const result = runGit(["blame", "-L", `${start},${end}`, "--", filePath], { cwd });
|
|
2150
2158
|
if (result.exitCode !== 0) {
|
|
2151
|
-
|
|
2159
|
+
emitErr(`git blame failed: ${displaySafeText(result.stderr)}`);
|
|
2152
2160
|
return 1;
|
|
2153
2161
|
}
|
|
2154
2162
|
raw = result.stdout;
|
|
2155
2163
|
} catch (e) {
|
|
2156
|
-
|
|
2164
|
+
emitErr(`git blame failed: ${extractErrorMessage(e)}`);
|
|
2157
2165
|
return 1;
|
|
2158
2166
|
}
|
|
2159
2167
|
if (opts.json === true) {
|
|
@@ -2162,32 +2170,25 @@ function runBlame(opts) {
|
|
|
2162
2170
|
if (!m) return { raw: l };
|
|
2163
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] };
|
|
2164
2172
|
});
|
|
2165
|
-
|
|
2173
|
+
emit(displaySafeJson({ symbol: sym.name, file: filePath, lines }));
|
|
2166
2174
|
return 0;
|
|
2167
2175
|
}
|
|
2168
|
-
|
|
2169
|
-
|
|
2176
|
+
emit(`${displaySafeText(sym.name)} ${displaySafeText(toDisplayPath(getDisplayRoot(opts.cwd), filePath))}:${start}-${end}`);
|
|
2177
|
+
emit(fenceUntrusted(raw.trim(), UNTRUSTED_FILE_TAG));
|
|
2170
2178
|
return 0;
|
|
2171
2179
|
}
|
|
2172
2180
|
|
|
2173
2181
|
// src/graph_commands.ts
|
|
2174
|
-
function emit3(text) {
|
|
2175
|
-
const payload = colorStdout() ? text : stripAnsi(text);
|
|
2176
|
-
process.stdout.write(ensureNewline(payload));
|
|
2177
|
-
}
|
|
2178
|
-
function emitErr3(text) {
|
|
2179
|
-
process.stderr.write(ensureNewline(text));
|
|
2180
|
-
}
|
|
2181
2182
|
function runCallers(opts) {
|
|
2182
2183
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
2183
|
-
|
|
2184
|
+
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
2184
2185
|
return 1;
|
|
2185
2186
|
}
|
|
2186
2187
|
const rootDir = resolveProjectRoot({ project: process.cwd() });
|
|
2187
2188
|
const { name, file } = parseGraphSymbolSpec(opts.symbol);
|
|
2188
2189
|
const fileHint = file !== void 0 ? resolveIndexPath(file, rootDir) : void 0;
|
|
2189
2190
|
if (fileHint !== void 0 && querySymbols({ name, filePath: fileHint, limit: 1 }).length === 0) {
|
|
2190
|
-
|
|
2191
|
+
emitErr(`Symbol '${name}' not found in '${file}'`);
|
|
2191
2192
|
return 1;
|
|
2192
2193
|
}
|
|
2193
2194
|
const unbounded = opts.excludeTests === true || opts.grep !== void 0 || fileHint !== void 0;
|
|
@@ -2204,41 +2205,41 @@ function runCallers(opts) {
|
|
|
2204
2205
|
if (entries.length === 0) {
|
|
2205
2206
|
if (matchesGrep !== void 0 && preGrepCount > 0) {
|
|
2206
2207
|
if (opts.json === true) {
|
|
2207
|
-
|
|
2208
|
+
emit(displaySafeJson({ items: [], truncated: false, totalCount: 0, hiddenByGrep: preGrepCount }));
|
|
2208
2209
|
return 0;
|
|
2209
2210
|
}
|
|
2210
|
-
|
|
2211
|
+
emit(grepFilteredToEmptyNotice(preGrepCount, opts.grep ?? "", "caller", "callers"));
|
|
2211
2212
|
return 0;
|
|
2212
2213
|
}
|
|
2213
2214
|
if (opts.excludeTests === true && suppressed > 0) {
|
|
2214
2215
|
if (opts.json === true) {
|
|
2215
|
-
|
|
2216
|
+
emit(displaySafeJson({ items: [], truncated: false, totalCount: 0, hiddenByExcludeTests: suppressed }));
|
|
2216
2217
|
return 1;
|
|
2217
2218
|
}
|
|
2218
|
-
|
|
2219
|
+
emitErr(`No non-test references found for '${opts.symbol}' (${excludeTestsHiddenNote(suppressed)})`);
|
|
2219
2220
|
return 1;
|
|
2220
2221
|
}
|
|
2221
2222
|
const defRows = querySymbols({ name, rootDir, limit: REF_BLIND_DEF_PROBE_LIMIT });
|
|
2222
2223
|
if (defRows.length === 0) {
|
|
2223
|
-
|
|
2224
|
-
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));
|
|
2225
2226
|
return 1;
|
|
2226
2227
|
}
|
|
2227
2228
|
const defPaths = fileHint !== void 0 ? [fileHint] : defRows.map((r) => r.filePath);
|
|
2228
2229
|
const firstDefPath = defPaths[0];
|
|
2229
2230
|
if (firstDefPath !== void 0 && defPaths.every((fp) => !isRefIndexedFile(fp))) {
|
|
2230
|
-
|
|
2231
|
+
emitErr(refBlindLanguageNotice(name, detectLanguageOfFile(firstDefPath), toDisplayPath(rootDir, firstDefPath)));
|
|
2231
2232
|
return 1;
|
|
2232
2233
|
}
|
|
2233
2234
|
const kindRows = fileHint !== void 0 ? querySymbols({ name, filePath: fileHint, limit: REF_BLIND_DEF_PROBE_LIMIT }) : defRows;
|
|
2234
2235
|
const kindVerdict = refBlindKindVerdict(kindRows);
|
|
2235
2236
|
if (kindVerdict.allBlind) {
|
|
2236
|
-
|
|
2237
|
+
emitErr(refBlindKindNotice(name, kindVerdict.blindKinds));
|
|
2237
2238
|
return 1;
|
|
2238
2239
|
}
|
|
2239
|
-
|
|
2240
|
-
if (kindVerdict.blindCount > 0)
|
|
2241
|
-
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));
|
|
2242
2243
|
return 1;
|
|
2243
2244
|
}
|
|
2244
2245
|
const contextLines = opts.context ?? 0;
|
|
@@ -2251,7 +2252,7 @@ function runCallers(opts) {
|
|
|
2251
2252
|
const capped = guardJsonRows(rows);
|
|
2252
2253
|
const limitTruncated = entries.length < filtered.length || sqlTruncated;
|
|
2253
2254
|
const hiddenByGrep = preGrepCount - filtered.length;
|
|
2254
|
-
|
|
2255
|
+
emit(displaySafeJson({
|
|
2255
2256
|
items: capped.items,
|
|
2256
2257
|
truncated: capped.truncated || limitTruncated,
|
|
2257
2258
|
totalCount: filtered.length,
|
|
@@ -2261,19 +2262,24 @@ function runCallers(opts) {
|
|
|
2261
2262
|
return 0;
|
|
2262
2263
|
}
|
|
2263
2264
|
if (opts.excludeTests === true && suppressed > 0) {
|
|
2264
|
-
|
|
2265
|
+
emit(`${countNoun(entries.length, "caller")} found (${excludeTestsHiddenNote(suppressed)})`);
|
|
2266
|
+
}
|
|
2267
|
+
const overflowed = sqlTruncated || entries.length < filtered.length;
|
|
2268
|
+
if (overflowed) {
|
|
2269
|
+
const totalCallers = sqlTruncated ? countRefs({ name, rootDir }) : filtered.length;
|
|
2270
|
+
emitErr(`Showing the first ${entries.length} of ${countNoun(totalCallers, "caller")} (raise --limit to see the rest).`);
|
|
2265
2271
|
}
|
|
2266
2272
|
for (const e of entries) {
|
|
2267
2273
|
const displayPath = toDisplayPath(rootDir, e.file);
|
|
2268
|
-
|
|
2274
|
+
emit(`${e.caller} ${displayPath}:${e.line}`);
|
|
2269
2275
|
const window = buildContextWindow(e.file, e.line, contextLines);
|
|
2270
|
-
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);
|
|
2271
2277
|
}
|
|
2272
2278
|
return 0;
|
|
2273
2279
|
}
|
|
2274
2280
|
function runCallChain(opts) {
|
|
2275
2281
|
if (opts.depth !== void 0 && opts.depth <= 0) {
|
|
2276
|
-
|
|
2282
|
+
emitErr(`--depth must be a positive number, got: ${opts.depth}`);
|
|
2277
2283
|
return 1;
|
|
2278
2284
|
}
|
|
2279
2285
|
const maxDepth = opts.depth ?? 8;
|
|
@@ -2282,13 +2288,13 @@ function runCallChain(opts) {
|
|
|
2282
2288
|
const fileHint = file !== void 0 ? resolveIndexPath(file, rootDir) : void 0;
|
|
2283
2289
|
if (fileHint !== void 0) {
|
|
2284
2290
|
if (querySymbols({ name, filePath: fileHint, limit: 1 }).length === 0) {
|
|
2285
|
-
|
|
2286
|
-
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));
|
|
2287
2293
|
return 1;
|
|
2288
2294
|
}
|
|
2289
2295
|
} else if (querySymbols({ name, rootDir, limit: 1 }).length === 0) {
|
|
2290
|
-
|
|
2291
|
-
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));
|
|
2292
2298
|
return 1;
|
|
2293
2299
|
}
|
|
2294
2300
|
const refBlindRootPath = () => {
|
|
@@ -2326,7 +2332,7 @@ function runCallChain(opts) {
|
|
|
2326
2332
|
const refBlindKinds = noCallers ? refBlindRootKinds().blindKinds : [];
|
|
2327
2333
|
const blindRootPath = noCallers ? refBlindRootPath() : void 0;
|
|
2328
2334
|
const refBlindLanguage = blindRootPath !== void 0 ? { language: detectLanguageOfFile(blindRootPath), definedIn: toDisplayPath(rootDir, blindRootPath) } : void 0;
|
|
2329
|
-
|
|
2335
|
+
emit(displaySafeJson({
|
|
2330
2336
|
chains: filteredChains,
|
|
2331
2337
|
...hiddenByGrep > 0 ? { hiddenByGrep } : {},
|
|
2332
2338
|
...hiddenByExcludeTests > 0 ? { hiddenByExcludeTests } : {},
|
|
@@ -2337,37 +2343,37 @@ function runCallChain(opts) {
|
|
|
2337
2343
|
}
|
|
2338
2344
|
if (noCallers) {
|
|
2339
2345
|
if (opts.excludeTests === true && suppressedCount > 0) {
|
|
2340
|
-
|
|
2346
|
+
emit(`${name} (no non-test callers; ${excludeTestsHiddenNote(suppressedCount)})`);
|
|
2341
2347
|
return 0;
|
|
2342
2348
|
}
|
|
2343
2349
|
const blindRoot = refBlindRootPath();
|
|
2344
2350
|
if (blindRoot !== void 0) {
|
|
2345
|
-
|
|
2346
|
-
|
|
2351
|
+
emitErr(refBlindLanguageNotice(name, detectLanguageOfFile(blindRoot), toDisplayPath(rootDir, blindRoot)));
|
|
2352
|
+
emit(`${name} (no callers recorded)`);
|
|
2347
2353
|
return 0;
|
|
2348
2354
|
}
|
|
2349
2355
|
const rootKinds = refBlindRootKinds();
|
|
2350
2356
|
if (rootKinds.allBlind) {
|
|
2351
|
-
|
|
2352
|
-
|
|
2357
|
+
emitErr(refBlindKindNotice(name, rootKinds.blindKinds));
|
|
2358
|
+
emit(`${name} (no callers recorded)`);
|
|
2353
2359
|
return 0;
|
|
2354
2360
|
}
|
|
2355
|
-
|
|
2356
|
-
if (rootKinds.blindCount > 0)
|
|
2361
|
+
emit(`${name} (no callers)`);
|
|
2362
|
+
if (rootKinds.blindCount > 0) emitErr(refBlindKindPartialNote(name, rootKinds.blindKinds, rootKinds.blindCount, rootKinds.total));
|
|
2357
2363
|
return 0;
|
|
2358
2364
|
}
|
|
2359
2365
|
if (matchesGrep !== void 0 && filteredChains.length === 0) {
|
|
2360
|
-
|
|
2366
|
+
emit(grepFilteredToEmptyNotice(chains.length, opts.grep, "chain", "chains"));
|
|
2361
2367
|
return 0;
|
|
2362
2368
|
}
|
|
2363
2369
|
for (const chain of filteredChains) {
|
|
2364
|
-
|
|
2370
|
+
emit(chain.join(" -> "));
|
|
2365
2371
|
}
|
|
2366
2372
|
return 0;
|
|
2367
2373
|
}
|
|
2368
2374
|
function runImpact(opts) {
|
|
2369
2375
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
2370
|
-
|
|
2376
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
2371
2377
|
return 1;
|
|
2372
2378
|
}
|
|
2373
2379
|
const top = opts.top ?? 20;
|
|
@@ -2376,7 +2382,7 @@ function runImpact(opts) {
|
|
|
2376
2382
|
const { name: rootName, file } = parseGraphSymbolSpec(opts.symbol);
|
|
2377
2383
|
const fileHint = file !== void 0 ? resolveIndexPath(file, rootDir) : void 0;
|
|
2378
2384
|
if (fileHint !== void 0 && querySymbols({ name: rootName, filePath: fileHint, limit: 1 }).length === 0) {
|
|
2379
|
-
|
|
2385
|
+
emitErr(`Symbol '${rootName}' not found in '${file}'`);
|
|
2380
2386
|
return 1;
|
|
2381
2387
|
}
|
|
2382
2388
|
const getSyms = buildFileSymCache();
|
|
@@ -2421,64 +2427,64 @@ function runImpact(opts) {
|
|
|
2421
2427
|
const grepped = matchesGrep !== void 0 ? allSorted.filter(([symbol]) => matchesGrep(symbol)) : allSorted;
|
|
2422
2428
|
const sorted = grepped.slice(0, top);
|
|
2423
2429
|
if (depthCapped > 0) {
|
|
2424
|
-
|
|
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.`);
|
|
2425
2431
|
}
|
|
2426
2432
|
if (grepped.length > sorted.length) {
|
|
2427
|
-
|
|
2433
|
+
emitErr(`Showing top ${sorted.length} of ${grepped.length} impacted symbols (raise --top to see the rest).`);
|
|
2428
2434
|
}
|
|
2429
2435
|
if (matchesGrep !== void 0 && sorted.length === 0 && allSorted.length > 0) {
|
|
2430
2436
|
if (opts.json === true) {
|
|
2431
|
-
|
|
2432
|
-
|
|
2437
|
+
emitErr(grepFilteredToEmptyNotice(allSorted.length, opts.grep, "impacted symbol", "impacted symbols"));
|
|
2438
|
+
emit(displaySafeJson([]));
|
|
2433
2439
|
return 0;
|
|
2434
2440
|
}
|
|
2435
|
-
|
|
2441
|
+
emit(grepFilteredToEmptyNotice(allSorted.length, opts.grep, "impacted symbol", "impacted symbols"));
|
|
2436
2442
|
return 0;
|
|
2437
2443
|
}
|
|
2438
2444
|
if (sorted.length === 0) {
|
|
2439
2445
|
if (opts.excludeTests === true && suppressedCount > 0) {
|
|
2440
2446
|
if (opts.json === true) {
|
|
2441
|
-
|
|
2447
|
+
emit(displaySafeJson([]));
|
|
2442
2448
|
return 1;
|
|
2443
2449
|
}
|
|
2444
|
-
|
|
2450
|
+
emitErr(`No non-test impact found for '${opts.symbol}' (${excludeTestsHiddenNote(suppressedCount)})`);
|
|
2445
2451
|
return 1;
|
|
2446
2452
|
}
|
|
2447
2453
|
const defRows = querySymbols({ name: rootName, rootDir, limit: REF_BLIND_DEF_PROBE_LIMIT });
|
|
2448
2454
|
if (defRows.length === 0) {
|
|
2449
|
-
|
|
2455
|
+
emitErr(`Symbol not found: ${opts.symbol}${unknownSymbolSuggestion(rootName, rootDir)}`);
|
|
2450
2456
|
return 1;
|
|
2451
2457
|
}
|
|
2452
2458
|
const defPaths = fileHint !== void 0 ? [fileHint] : defRows.map((r) => r.filePath);
|
|
2453
2459
|
const firstDefPath = defPaths[0];
|
|
2454
2460
|
if (firstDefPath !== void 0 && defPaths.every((fp) => !isRefIndexedFile(fp))) {
|
|
2455
|
-
|
|
2461
|
+
emitErr(refBlindLanguageNotice(rootName, detectLanguageOfFile(firstDefPath), toDisplayPath(rootDir, firstDefPath)));
|
|
2456
2462
|
return 1;
|
|
2457
2463
|
}
|
|
2458
2464
|
const kindRows = fileHint !== void 0 ? querySymbols({ name: rootName, filePath: fileHint, limit: REF_BLIND_DEF_PROBE_LIMIT }) : defRows;
|
|
2459
2465
|
const kindVerdict = refBlindKindVerdict(kindRows);
|
|
2460
2466
|
if (kindVerdict.allBlind) {
|
|
2461
|
-
|
|
2467
|
+
emitErr(refBlindKindNotice(rootName, kindVerdict.blindKinds));
|
|
2462
2468
|
return 1;
|
|
2463
2469
|
}
|
|
2464
|
-
|
|
2465
|
-
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));
|
|
2466
2472
|
return 1;
|
|
2467
2473
|
}
|
|
2468
2474
|
if (opts.json === true) {
|
|
2469
|
-
|
|
2475
|
+
emit(displaySafeJson(sorted.map(([symbol, h]) => ({ symbol, hops: h }))));
|
|
2470
2476
|
return 0;
|
|
2471
2477
|
}
|
|
2472
2478
|
const MODULE_SCOPE_PREFIX = "(module scope) ";
|
|
2473
2479
|
for (const [symbol, h] of sorted) {
|
|
2474
2480
|
const displaySymbol = symbol.startsWith(MODULE_SCOPE_PREFIX) ? MODULE_SCOPE_PREFIX + toDisplayPath(rootDir, symbol.slice(MODULE_SCOPE_PREFIX.length)) : symbol;
|
|
2475
|
-
|
|
2481
|
+
emit(`${displaySymbol} (hops: ${h})`);
|
|
2476
2482
|
}
|
|
2477
2483
|
return 0;
|
|
2478
2484
|
}
|
|
2479
2485
|
function runAsk(opts) {
|
|
2480
2486
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
2481
|
-
|
|
2487
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
2482
2488
|
return 1;
|
|
2483
2489
|
}
|
|
2484
2490
|
const top = opts.top ?? 8;
|
|
@@ -2487,7 +2493,7 @@ function runAsk(opts) {
|
|
|
2487
2493
|
const moreBeyondTop = fetched.length > top;
|
|
2488
2494
|
const hits = fetched.slice(0, top);
|
|
2489
2495
|
if (moreBeyondTop) {
|
|
2490
|
-
|
|
2496
|
+
emitErr(`Answer is grounded in the top ${countNoun(top, "match", "matches")}; more matched (raise --top to widen the evidence).`);
|
|
2491
2497
|
}
|
|
2492
2498
|
warnIfFilesStale(hits.map((h) => h.filePath));
|
|
2493
2499
|
const BACKEND_ENV = "TOKEN_GOAT_ASK_BACKEND";
|
|
@@ -2495,12 +2501,12 @@ function runAsk(opts) {
|
|
|
2495
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}"` }));
|
|
2496
2502
|
const degrade = (reason, extraNote) => {
|
|
2497
2503
|
if (opts.json === true) {
|
|
2498
|
-
|
|
2504
|
+
emit(displaySafeJson({ degraded: true, note: reason, ...extraNote !== void 0 ? { hint: extraNote } : {}, context: entries }));
|
|
2499
2505
|
return 0;
|
|
2500
2506
|
}
|
|
2501
|
-
|
|
2502
|
-
if (extraNote !== void 0)
|
|
2503
|
-
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}"`);
|
|
2504
2510
|
return 0;
|
|
2505
2511
|
};
|
|
2506
2512
|
if (!backendLabel) return degrade(`set ${BACKEND_ENV}=claude|codex for LLM synthesis`);
|
|
@@ -2547,9 +2553,9 @@ ANSWER:`;
|
|
|
2547
2553
|
}
|
|
2548
2554
|
if (answer) {
|
|
2549
2555
|
if (opts.json === true) {
|
|
2550
|
-
|
|
2556
|
+
emit(displaySafeJson({ answer, context: entries }));
|
|
2551
2557
|
} else {
|
|
2552
|
-
|
|
2558
|
+
emit(answer);
|
|
2553
2559
|
}
|
|
2554
2560
|
return 0;
|
|
2555
2561
|
}
|
|
@@ -3046,6 +3052,17 @@ async function takeScreenshot(url, destPath, opts) {
|
|
|
3046
3052
|
return { path: finalPath, originalBytes: buffer.length, finalBytes: finalBuffer.length };
|
|
3047
3053
|
}
|
|
3048
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
|
+
|
|
3049
3066
|
// src/ts_refs.ts
|
|
3050
3067
|
init_define_import_meta_env();
|
|
3051
3068
|
import { createRequire } from "node:module";
|
|
@@ -7368,7 +7385,7 @@ function fenceHtmlText(text) {
|
|
|
7368
7385
|
function runCsvQuery(opts) {
|
|
7369
7386
|
const text = readFileText(opts.file);
|
|
7370
7387
|
if (text === null) {
|
|
7371
|
-
|
|
7388
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7372
7389
|
return 1;
|
|
7373
7390
|
}
|
|
7374
7391
|
const columns = opts.columns ? opts.columns.split(",").map((c) => c.trim()).filter(Boolean) : void 0;
|
|
@@ -7376,7 +7393,7 @@ function runCsvQuery(opts) {
|
|
|
7376
7393
|
try {
|
|
7377
7394
|
head = opts.head !== void 0 ? requireNonNegativeStrictInt("--head", opts.head) : void 0;
|
|
7378
7395
|
} catch (e) {
|
|
7379
|
-
|
|
7396
|
+
emitErr(extractErrorMessage(e));
|
|
7380
7397
|
return 1;
|
|
7381
7398
|
}
|
|
7382
7399
|
try {
|
|
@@ -7389,7 +7406,7 @@ function runCsvQuery(opts) {
|
|
|
7389
7406
|
...opts.noHeader === true ? { noHeader: true } : {}
|
|
7390
7407
|
});
|
|
7391
7408
|
if (result.header.length === 0) {
|
|
7392
|
-
|
|
7409
|
+
emit(`No data rows found in ${displaySafeText(opts.file)}`);
|
|
7393
7410
|
return 0;
|
|
7394
7411
|
}
|
|
7395
7412
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
@@ -7398,23 +7415,23 @@ function runCsvQuery(opts) {
|
|
|
7398
7415
|
const headTruncated = result.rows.length < result.totalRows;
|
|
7399
7416
|
const capped = guardJsonRows(rowsJson);
|
|
7400
7417
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated || headTruncated, totalCount: result.totalRows, ...result.totalRows === 0 && result.preFilterRows > 0 ? { filteredFromRows: result.preFilterRows } : {} }, 0);
|
|
7401
|
-
|
|
7418
|
+
emit(jsonText);
|
|
7402
7419
|
recordReadStat("csv_query", fullSourceBytes, jsonText, opts.file);
|
|
7403
7420
|
} else {
|
|
7404
7421
|
const tableText = formatCsvTable(result, (opts.where ?? []).map((w) => `--where ${w}`));
|
|
7405
|
-
|
|
7422
|
+
emit(tableText);
|
|
7406
7423
|
recordReadStat("csv_query", fullSourceBytes, tableText, opts.file);
|
|
7407
7424
|
}
|
|
7408
7425
|
return 0;
|
|
7409
7426
|
} catch (e) {
|
|
7410
|
-
|
|
7427
|
+
emitErr(extractErrorMessage(e));
|
|
7411
7428
|
return 1;
|
|
7412
7429
|
}
|
|
7413
7430
|
}
|
|
7414
7431
|
function runCsvProfile(opts) {
|
|
7415
7432
|
const text = readFileText(opts.file);
|
|
7416
7433
|
if (text === null) {
|
|
7417
|
-
|
|
7434
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7418
7435
|
return 1;
|
|
7419
7436
|
}
|
|
7420
7437
|
try {
|
|
@@ -7423,41 +7440,41 @@ function runCsvProfile(opts) {
|
|
|
7423
7440
|
...opts.noHeader === true ? { noHeader: true } : {}
|
|
7424
7441
|
});
|
|
7425
7442
|
if (profiles.length === 0) {
|
|
7426
|
-
|
|
7443
|
+
emit(`No data rows found in ${displaySafeText(opts.file)}`);
|
|
7427
7444
|
return 0;
|
|
7428
7445
|
}
|
|
7429
7446
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
7430
7447
|
const profileText = formatCsvProfile(profiles);
|
|
7431
|
-
|
|
7448
|
+
emit(profileText);
|
|
7432
7449
|
recordReadStat("csv_profile", fullSourceBytes, profileText, opts.file);
|
|
7433
7450
|
return 0;
|
|
7434
7451
|
} catch (e) {
|
|
7435
|
-
|
|
7452
|
+
emitErr(extractErrorMessage(e));
|
|
7436
7453
|
return 1;
|
|
7437
7454
|
}
|
|
7438
7455
|
}
|
|
7439
7456
|
function runOutlineCommand(opts, parse, formatLabel, kind) {
|
|
7440
7457
|
const text = readFileText(opts.file);
|
|
7441
7458
|
if (text === null) {
|
|
7442
|
-
|
|
7459
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7443
7460
|
return 1;
|
|
7444
7461
|
}
|
|
7445
7462
|
let data;
|
|
7446
7463
|
try {
|
|
7447
7464
|
data = parse(text);
|
|
7448
7465
|
} catch {
|
|
7449
|
-
|
|
7466
|
+
emitErr(`Failed to parse ${formatLabel}: ${opts.file}`);
|
|
7450
7467
|
return 1;
|
|
7451
7468
|
}
|
|
7452
7469
|
const outline = outlineJson(data);
|
|
7453
7470
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
7454
7471
|
if (opts.json === true) {
|
|
7455
7472
|
const jsonText = displaySafeJson(outline, 0);
|
|
7456
|
-
|
|
7473
|
+
emit(jsonText);
|
|
7457
7474
|
recordReadStat(kind, fullSourceBytes, jsonText, opts.file);
|
|
7458
7475
|
} else {
|
|
7459
7476
|
const text2 = formatJsonOutline(outline);
|
|
7460
|
-
|
|
7477
|
+
emit(text2);
|
|
7461
7478
|
recordReadStat(kind, fullSourceBytes, text2, opts.file);
|
|
7462
7479
|
}
|
|
7463
7480
|
return 0;
|
|
@@ -7468,21 +7485,21 @@ function runJsonOutline(opts) {
|
|
|
7468
7485
|
function runQueryCommand(opts, parse, formatLabel, guardTag, kind) {
|
|
7469
7486
|
const text = readFileText(opts.file);
|
|
7470
7487
|
if (text === null) {
|
|
7471
|
-
|
|
7488
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7472
7489
|
return 1;
|
|
7473
7490
|
}
|
|
7474
7491
|
let data;
|
|
7475
7492
|
try {
|
|
7476
7493
|
data = parse(text);
|
|
7477
7494
|
} catch {
|
|
7478
|
-
|
|
7495
|
+
emitErr(`Failed to parse ${formatLabel}: ${opts.file}`);
|
|
7479
7496
|
return 1;
|
|
7480
7497
|
}
|
|
7481
7498
|
let head;
|
|
7482
7499
|
try {
|
|
7483
7500
|
head = opts.head !== void 0 ? requireNonNegativeStrictInt("--head", opts.head) : void 0;
|
|
7484
7501
|
} catch (e) {
|
|
7485
|
-
|
|
7502
|
+
emitErr(extractErrorMessage(e));
|
|
7486
7503
|
return 1;
|
|
7487
7504
|
}
|
|
7488
7505
|
try {
|
|
@@ -7491,7 +7508,7 @@ function runQueryCommand(opts, parse, formatLabel, guardTag, kind) {
|
|
|
7491
7508
|
if (!result.fanned) {
|
|
7492
7509
|
const value = result.items[0];
|
|
7493
7510
|
const valueText = opts.json === true ? displaySafeJson(value, 0) : displaySafeJson(value);
|
|
7494
|
-
|
|
7511
|
+
emit(valueText);
|
|
7495
7512
|
recordReadStat(kind, fullSourceBytes, valueText, opts.file);
|
|
7496
7513
|
return 0;
|
|
7497
7514
|
}
|
|
@@ -7501,7 +7518,7 @@ function runQueryCommand(opts, parse, formatLabel, guardTag, kind) {
|
|
|
7501
7518
|
if (opts.json === true) {
|
|
7502
7519
|
const capped = guardJsonRows(limited);
|
|
7503
7520
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated || headTruncated || result.truncated, totalCount }, 0);
|
|
7504
|
-
|
|
7521
|
+
emit(jsonText);
|
|
7505
7522
|
recordReadStat(kind, fullSourceBytes, jsonText, opts.file);
|
|
7506
7523
|
} else {
|
|
7507
7524
|
const lines = limited.map((item) => displaySafeJson(item, 0));
|
|
@@ -7517,7 +7534,7 @@ function runQueryCommand(opts, parse, formatLabel, guardTag, kind) {
|
|
|
7517
7534
|
}
|
|
7518
7535
|
return 0;
|
|
7519
7536
|
} catch (e) {
|
|
7520
|
-
|
|
7537
|
+
emitErr(extractErrorMessage(e));
|
|
7521
7538
|
return 1;
|
|
7522
7539
|
}
|
|
7523
7540
|
}
|
|
@@ -7559,21 +7576,21 @@ function runYamlQuery(opts) {
|
|
|
7559
7576
|
function runXmlOutline(opts) {
|
|
7560
7577
|
const text = readFileText(opts.file);
|
|
7561
7578
|
if (text === null) {
|
|
7562
|
-
|
|
7579
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7563
7580
|
return 1;
|
|
7564
7581
|
}
|
|
7565
7582
|
let summary;
|
|
7566
7583
|
try {
|
|
7567
7584
|
summary = outlineXml(text, { ...opts.maxDepth !== void 0 ? { maxDepth: opts.maxDepth } : {} });
|
|
7568
7585
|
} catch (e) {
|
|
7569
|
-
|
|
7586
|
+
emitErr(`Failed to parse XML: ${opts.file}
|
|
7570
7587
|
${extractErrorMessage(e)}`);
|
|
7571
7588
|
return 1;
|
|
7572
7589
|
}
|
|
7573
7590
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
7574
7591
|
if (opts.json === true) {
|
|
7575
7592
|
const jsonText = displaySafeJson(summary);
|
|
7576
|
-
|
|
7593
|
+
emit(jsonText);
|
|
7577
7594
|
recordReadStat("xml_outline", fullSourceBytes, jsonText, opts.file);
|
|
7578
7595
|
} else {
|
|
7579
7596
|
const outlineText = formatXmlOutline(summary);
|
|
@@ -7585,19 +7602,19 @@ ${extractErrorMessage(e)}`);
|
|
|
7585
7602
|
function runXmlQuery(opts) {
|
|
7586
7603
|
const text = readFileText(opts.file);
|
|
7587
7604
|
if (text === null) {
|
|
7588
|
-
|
|
7605
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7589
7606
|
return 1;
|
|
7590
7607
|
}
|
|
7591
7608
|
const queryPath = (opts.xpath ?? opts.path ?? "").trim();
|
|
7592
7609
|
if (!queryPath) {
|
|
7593
|
-
|
|
7610
|
+
emitErr("Must provide a path or --xpath <expression>");
|
|
7594
7611
|
return 1;
|
|
7595
7612
|
}
|
|
7596
7613
|
let head;
|
|
7597
7614
|
try {
|
|
7598
7615
|
head = opts.head !== void 0 ? requireNonNegativeStrictInt("--head", opts.head) : void 0;
|
|
7599
7616
|
} catch (e) {
|
|
7600
|
-
|
|
7617
|
+
emitErr(extractErrorMessage(e));
|
|
7601
7618
|
return 1;
|
|
7602
7619
|
}
|
|
7603
7620
|
try {
|
|
@@ -7607,10 +7624,10 @@ function runXmlQuery(opts) {
|
|
|
7607
7624
|
if (result.attributeValues.length === 0) {
|
|
7608
7625
|
if (opts.json === true) {
|
|
7609
7626
|
const jsonText = displaySafeJson({ items: [], truncated: false, totalCount: 0 }, 0);
|
|
7610
|
-
|
|
7627
|
+
emit(jsonText);
|
|
7611
7628
|
recordReadStat("xml_query", fullSourceBytes, jsonText, opts.file);
|
|
7612
7629
|
} else {
|
|
7613
|
-
|
|
7630
|
+
emit(`No attributes matched path: '${displaySafeText(queryPath)}'`);
|
|
7614
7631
|
}
|
|
7615
7632
|
return 0;
|
|
7616
7633
|
}
|
|
@@ -7642,7 +7659,7 @@ ${val}`;
|
|
|
7642
7659
|
outText = val;
|
|
7643
7660
|
}
|
|
7644
7661
|
}
|
|
7645
|
-
|
|
7662
|
+
emit(outText);
|
|
7646
7663
|
recordReadStat("xml_query", fullSourceBytes, outText, opts.file);
|
|
7647
7664
|
return 0;
|
|
7648
7665
|
}
|
|
@@ -7672,7 +7689,7 @@ ${val}`;
|
|
|
7672
7689
|
{ items: capped.items, truncated: capped.truncated || headTruncated2, totalCount: totalCount2 },
|
|
7673
7690
|
0
|
|
7674
7691
|
);
|
|
7675
|
-
|
|
7692
|
+
emit(jsonText);
|
|
7676
7693
|
recordReadStat("xml_query", fullSourceBytes, jsonText, opts.file);
|
|
7677
7694
|
} else {
|
|
7678
7695
|
const lines = [];
|
|
@@ -7702,10 +7719,10 @@ ${val}`);
|
|
|
7702
7719
|
if (result.items.length === 0) {
|
|
7703
7720
|
if (opts.json === true) {
|
|
7704
7721
|
const jsonText = displaySafeJson({ items: [], truncated: false, totalCount: 0 }, 0);
|
|
7705
|
-
|
|
7722
|
+
emit(jsonText);
|
|
7706
7723
|
recordReadStat("xml_query", fullSourceBytes, jsonText, opts.file);
|
|
7707
7724
|
} else {
|
|
7708
|
-
|
|
7725
|
+
emit(`No elements matched path: '${displaySafeText(queryPath)}'`);
|
|
7709
7726
|
}
|
|
7710
7727
|
return 0;
|
|
7711
7728
|
}
|
|
@@ -7717,7 +7734,7 @@ ${val}`);
|
|
|
7717
7734
|
...opts.decodeEmbeddedXml ? { decodeEmbedded: true } : {}
|
|
7718
7735
|
});
|
|
7719
7736
|
const jsonText = displaySafeJson(jsonVal);
|
|
7720
|
-
|
|
7737
|
+
emit(jsonText);
|
|
7721
7738
|
recordReadStat("xml_query", fullSourceBytes, jsonText, opts.file);
|
|
7722
7739
|
} else {
|
|
7723
7740
|
let xmlText = serializeXmlNode(
|
|
@@ -7749,7 +7766,7 @@ ${xmlText}`;
|
|
|
7749
7766
|
{ items: capped.items, truncated: capped.truncated || headTruncated, totalCount },
|
|
7750
7767
|
0
|
|
7751
7768
|
);
|
|
7752
|
-
|
|
7769
|
+
emit(jsonText);
|
|
7753
7770
|
recordReadStat("xml_query", fullSourceBytes, jsonText, opts.file);
|
|
7754
7771
|
} else {
|
|
7755
7772
|
const blocks = limited.map((node) => {
|
|
@@ -7773,21 +7790,21 @@ ${block}`;
|
|
|
7773
7790
|
}
|
|
7774
7791
|
return 0;
|
|
7775
7792
|
} catch (e) {
|
|
7776
|
-
|
|
7793
|
+
emitErr(extractErrorMessage(e));
|
|
7777
7794
|
return 1;
|
|
7778
7795
|
}
|
|
7779
7796
|
}
|
|
7780
7797
|
function runHtmlOutline(opts) {
|
|
7781
7798
|
const text = readFileText(opts.file);
|
|
7782
7799
|
if (text === null) {
|
|
7783
|
-
|
|
7800
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7784
7801
|
return 1;
|
|
7785
7802
|
}
|
|
7786
7803
|
const summary = outlineHtml(text);
|
|
7787
7804
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
7788
7805
|
if (opts.json === true) {
|
|
7789
7806
|
const jsonText = displaySafeJson(summary);
|
|
7790
|
-
|
|
7807
|
+
emit(jsonText);
|
|
7791
7808
|
recordReadStat("html_outline", fullSourceBytes, jsonText, opts.file);
|
|
7792
7809
|
} else {
|
|
7793
7810
|
const outlineText = formatHtmlOutline(summary);
|
|
@@ -7799,14 +7816,14 @@ function runHtmlOutline(opts) {
|
|
|
7799
7816
|
function runHtmlQuery(opts) {
|
|
7800
7817
|
const text = readFileText(opts.file);
|
|
7801
7818
|
if (text === null) {
|
|
7802
|
-
|
|
7819
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7803
7820
|
return 1;
|
|
7804
7821
|
}
|
|
7805
7822
|
let head;
|
|
7806
7823
|
try {
|
|
7807
7824
|
head = opts.head !== void 0 ? requireNonNegativeStrictInt("--head", opts.head) : void 0;
|
|
7808
7825
|
} catch (e) {
|
|
7809
|
-
|
|
7826
|
+
emitErr(extractErrorMessage(e));
|
|
7810
7827
|
return 1;
|
|
7811
7828
|
}
|
|
7812
7829
|
try {
|
|
@@ -7817,10 +7834,10 @@ function runHtmlQuery(opts) {
|
|
|
7817
7834
|
if (result.attributeValues.length === 0) {
|
|
7818
7835
|
if (opts.json === true) {
|
|
7819
7836
|
const jsonText = displaySafeJson({ items: [], truncated: false, totalCount: 0 }, 0);
|
|
7820
|
-
|
|
7837
|
+
emit(jsonText);
|
|
7821
7838
|
recordReadStat("html_query", fullSourceBytes, jsonText, opts.file);
|
|
7822
7839
|
} else {
|
|
7823
|
-
|
|
7840
|
+
emit(`No attributes matched selector: '${displaySafeText(opts.selector)}'`);
|
|
7824
7841
|
}
|
|
7825
7842
|
return 0;
|
|
7826
7843
|
}
|
|
@@ -7830,7 +7847,7 @@ function runHtmlQuery(opts) {
|
|
|
7830
7847
|
if (opts.json === true) {
|
|
7831
7848
|
const capped = guardJsonRows(limited2);
|
|
7832
7849
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated || headTruncated2, totalCount: totalCount2 }, 0);
|
|
7833
|
-
|
|
7850
|
+
emit(jsonText);
|
|
7834
7851
|
recordReadStat("html_query", fullSourceBytes, jsonText, opts.file);
|
|
7835
7852
|
} else {
|
|
7836
7853
|
const lines = limited2.map((item) => item);
|
|
@@ -7846,10 +7863,10 @@ function runHtmlQuery(opts) {
|
|
|
7846
7863
|
if (result.elements.length === 0) {
|
|
7847
7864
|
if (opts.json === true) {
|
|
7848
7865
|
const jsonText = displaySafeJson({ items: [], truncated: false, totalCount: 0 }, 0);
|
|
7849
|
-
|
|
7866
|
+
emit(jsonText);
|
|
7850
7867
|
recordReadStat("html_query", fullSourceBytes, jsonText, opts.file);
|
|
7851
7868
|
} else {
|
|
7852
|
-
|
|
7869
|
+
emit(`No elements matched selector: '${displaySafeText(opts.selector)}'`);
|
|
7853
7870
|
}
|
|
7854
7871
|
return 0;
|
|
7855
7872
|
}
|
|
@@ -7866,7 +7883,7 @@ function runHtmlQuery(opts) {
|
|
|
7866
7883
|
}));
|
|
7867
7884
|
const capped = guardJsonRows(jsonItems);
|
|
7868
7885
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated || headTruncated, totalCount });
|
|
7869
|
-
|
|
7886
|
+
emit(jsonText);
|
|
7870
7887
|
recordReadStat("html_query", fullSourceBytes, jsonText, opts.file);
|
|
7871
7888
|
} else if (opts.text === true) {
|
|
7872
7889
|
const textLines = limited.map((n) => extractNodeText(n, text)).filter(Boolean);
|
|
@@ -7887,24 +7904,24 @@ function runHtmlQuery(opts) {
|
|
|
7887
7904
|
}
|
|
7888
7905
|
return 0;
|
|
7889
7906
|
} catch (e) {
|
|
7890
|
-
|
|
7907
|
+
emitErr(extractErrorMessage(e));
|
|
7891
7908
|
return 1;
|
|
7892
7909
|
}
|
|
7893
7910
|
}
|
|
7894
7911
|
function runHtmlLint(opts) {
|
|
7895
7912
|
const text = readFileText(opts.file);
|
|
7896
7913
|
if (text === null) {
|
|
7897
|
-
|
|
7914
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
7898
7915
|
return 1;
|
|
7899
7916
|
}
|
|
7900
7917
|
const report = lintHtml(text);
|
|
7901
7918
|
const isClean = opts.strict ? report.errors.length === 0 && report.warnings.length === 0 : report.errors.length === 0;
|
|
7902
7919
|
if (opts.json === true) {
|
|
7903
|
-
|
|
7920
|
+
emit(displaySafeJson(report));
|
|
7904
7921
|
return isClean ? 0 : 1;
|
|
7905
7922
|
}
|
|
7906
7923
|
if (report.errors.length === 0 && report.warnings.length === 0) {
|
|
7907
|
-
|
|
7924
|
+
emit(`\u2713 ${displaySafeText(opts.file)}: HTML structure is valid (all tags balanced, no duplicate IDs, void elements respected).`);
|
|
7908
7925
|
return 0;
|
|
7909
7926
|
}
|
|
7910
7927
|
const lines = [];
|
|
@@ -7928,20 +7945,20 @@ function runHtmlLint(opts) {
|
|
|
7928
7945
|
lines.push(` <${tag}>: open=${counts.open}, close=${counts.close}, diff=${counts.diff}`);
|
|
7929
7946
|
}
|
|
7930
7947
|
}
|
|
7931
|
-
|
|
7948
|
+
emit(lines.join("\n"));
|
|
7932
7949
|
return isClean ? 0 : 1;
|
|
7933
7950
|
}
|
|
7934
7951
|
function loadOpenApiOperations(file) {
|
|
7935
7952
|
const text = readFileText(file);
|
|
7936
7953
|
if (text === null) {
|
|
7937
|
-
|
|
7954
|
+
emitErr(`Could not read: ${file}`);
|
|
7938
7955
|
return null;
|
|
7939
7956
|
}
|
|
7940
7957
|
let spec;
|
|
7941
7958
|
try {
|
|
7942
7959
|
spec = parseOpenApiSpec(text, file);
|
|
7943
7960
|
} catch {
|
|
7944
|
-
|
|
7961
|
+
emitErr(`Failed to parse OpenAPI spec (not valid JSON or YAML): ${file}`);
|
|
7945
7962
|
return null;
|
|
7946
7963
|
}
|
|
7947
7964
|
return extractOperations(spec);
|
|
@@ -7952,7 +7969,7 @@ function runOpenApiOutline(opts) {
|
|
|
7952
7969
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
7953
7970
|
if (opts.json === true) {
|
|
7954
7971
|
const jsonText = displaySafeJson(operations, 0);
|
|
7955
|
-
|
|
7972
|
+
emit(jsonText);
|
|
7956
7973
|
recordReadStat("openapi_outline", fullSourceBytes, jsonText, opts.file);
|
|
7957
7974
|
} else {
|
|
7958
7975
|
const text = formatOpenApiOutline(operations);
|
|
@@ -7970,13 +7987,13 @@ function runOpenApiOp(opts) {
|
|
|
7970
7987
|
const closes = rankSimilarNames(operations.map(operationLabel), opts.operation);
|
|
7971
7988
|
if (closes.length > 0) messages.push(didYouMean(closes));
|
|
7972
7989
|
else if (operations.length > 0) messages.push(`Try: token-goat openapi-outline ${opts.file}`);
|
|
7973
|
-
|
|
7990
|
+
emitErr(messages.join("\n"));
|
|
7974
7991
|
return 1;
|
|
7975
7992
|
}
|
|
7976
7993
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
7977
7994
|
if (opts.json === true) {
|
|
7978
7995
|
const jsonText = displaySafeJson(match, 0);
|
|
7979
|
-
|
|
7996
|
+
emit(jsonText);
|
|
7980
7997
|
recordReadStat("openapi_op", fullSourceBytes, jsonText, opts.operation);
|
|
7981
7998
|
} else {
|
|
7982
7999
|
const text = formatOperationDetail(match);
|
|
@@ -7995,7 +8012,6 @@ var MIN_WORD_SIMILARITY_LEN = 3;
|
|
|
7995
8012
|
var STRUCTURED_MISS_MAX_BYTES = 128 * 1024;
|
|
7996
8013
|
var STRUCTURED_MISS_MAX_FILES = 12;
|
|
7997
8014
|
var STRUCTURED_MISS_MAX_NODES = 2e4;
|
|
7998
|
-
var FIND_SCAN_LIMIT = 2e4;
|
|
7999
8015
|
function endsWithPathBoundary(full, suffix) {
|
|
8000
8016
|
if (!full.endsWith(suffix)) return false;
|
|
8001
8017
|
if (full.length === suffix.length) return true;
|
|
@@ -8076,8 +8092,9 @@ function didYouMean(candidates) {
|
|
|
8076
8092
|
return lines.join("\n");
|
|
8077
8093
|
}
|
|
8078
8094
|
function unknownSymbolSuggestion(name, rootDir) {
|
|
8079
|
-
const
|
|
8080
|
-
|
|
8095
|
+
const names = /* @__PURE__ */ new Set();
|
|
8096
|
+
forEachSymbol({ rootDir }, (s) => names.add(s.name));
|
|
8097
|
+
const candidates = rankSimilarNames([...names], name);
|
|
8081
8098
|
return candidates.length > 0 ? `
|
|
8082
8099
|
${didYouMean(candidates)}` : "";
|
|
8083
8100
|
}
|
|
@@ -8564,14 +8581,14 @@ ${sub.text}`);
|
|
|
8564
8581
|
}
|
|
8565
8582
|
function runBrief(opts) {
|
|
8566
8583
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
8567
|
-
|
|
8584
|
+
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
8568
8585
|
return 1;
|
|
8569
8586
|
}
|
|
8570
8587
|
const crossFilePairs = parseCrossFileMultiSpec(opts.spec);
|
|
8571
8588
|
if (crossFilePairs !== null) {
|
|
8572
8589
|
const { text: text2, code: code2 } = runBriefCrossFile(crossFilePairs, opts);
|
|
8573
|
-
if (code2 === 0)
|
|
8574
|
-
else
|
|
8590
|
+
if (code2 === 0) emit(text2);
|
|
8591
|
+
else emitErr(text2);
|
|
8575
8592
|
return code2;
|
|
8576
8593
|
}
|
|
8577
8594
|
const { file, symbol } = parseReadSpec(opts.spec);
|
|
@@ -8579,14 +8596,14 @@ function runBrief(opts) {
|
|
|
8579
8596
|
const multiSymbols = symbol.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
8580
8597
|
if (multiSymbols.length > 1) {
|
|
8581
8598
|
const { text: text2, code: code2 } = runBriefMulti(file, multiSymbols, opts);
|
|
8582
|
-
if (code2 === 0)
|
|
8583
|
-
else
|
|
8599
|
+
if (code2 === 0) emit(text2);
|
|
8600
|
+
else emitErr(text2);
|
|
8584
8601
|
return code2;
|
|
8585
8602
|
}
|
|
8586
8603
|
}
|
|
8587
8604
|
const { text, code } = runBriefCore(opts);
|
|
8588
|
-
if (code === 0)
|
|
8589
|
-
else
|
|
8605
|
+
if (code === 0) emit(text);
|
|
8606
|
+
else emitErr(text);
|
|
8590
8607
|
return code;
|
|
8591
8608
|
}
|
|
8592
8609
|
|
|
@@ -8601,7 +8618,7 @@ var OURS_RE = /^<{7}(?:\s+(.*))?$/;
|
|
|
8601
8618
|
var BASE_RE = /^\|{7}(?:\s+(.*))?$/;
|
|
8602
8619
|
var SEP_RE = /^={7}\s*$/;
|
|
8603
8620
|
var THEIRS_RE = /^>{7}(?:\s+(.*))?$/;
|
|
8604
|
-
function parseConflicts(filePath, text) {
|
|
8621
|
+
function parseConflicts(filePath, text, contextLines = 3) {
|
|
8605
8622
|
const lines = text.split(/\r?\n/);
|
|
8606
8623
|
const regions = [];
|
|
8607
8624
|
const warnings = [];
|
|
@@ -8664,13 +8681,29 @@ function parseConflicts(filePath, text) {
|
|
|
8664
8681
|
const theirsMatch = THEIRS_RE.exec(line);
|
|
8665
8682
|
if (theirsMatch !== null) {
|
|
8666
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
|
+
}
|
|
8667
8698
|
regions.push({
|
|
8668
8699
|
filePath,
|
|
8669
8700
|
lineStart: startLine,
|
|
8670
8701
|
lineEnd: lineNo,
|
|
8671
8702
|
ours: { label: oursLabel, content: oursLines.join("\n") },
|
|
8672
8703
|
base: sawBase ? { label: baseLabel, content: baseLines.join("\n") } : null,
|
|
8673
|
-
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 } : {}
|
|
8674
8707
|
});
|
|
8675
8708
|
resetRegion();
|
|
8676
8709
|
continue;
|
|
@@ -8713,6 +8746,11 @@ function formatSingleFileConflicts(result) {
|
|
|
8713
8746
|
lines.push(`${displaySafeText(result.filePath)} -- ${result.regions.length} conflict${result.regions.length === 1 ? "" : "s"}`);
|
|
8714
8747
|
for (const r of result.regions) {
|
|
8715
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
|
+
}
|
|
8716
8754
|
lines.push(` <<<<<<< ${displaySafeText(r.ours.label || "(ours)")}`);
|
|
8717
8755
|
lines.push(indentBlock(r.ours.content));
|
|
8718
8756
|
if (r.base !== null) {
|
|
@@ -8722,6 +8760,11 @@ function formatSingleFileConflicts(result) {
|
|
|
8722
8760
|
lines.push(" =======");
|
|
8723
8761
|
lines.push(indentBlock(r.theirs.content));
|
|
8724
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
|
+
}
|
|
8725
8768
|
}
|
|
8726
8769
|
} else {
|
|
8727
8770
|
lines.push(`${displaySafeText(result.filePath)} -- no conflicts`);
|
|
@@ -8771,23 +8814,24 @@ function runConflicts(opts) {
|
|
|
8771
8814
|
try {
|
|
8772
8815
|
stat = fs8.statSync(abs);
|
|
8773
8816
|
} catch {
|
|
8774
|
-
|
|
8817
|
+
emitErr(`Could not read: ${opts.path}`);
|
|
8775
8818
|
return 1;
|
|
8776
8819
|
}
|
|
8777
8820
|
files = stat.isDirectory() ? walkProject(abs).files : [abs];
|
|
8778
8821
|
}
|
|
8822
|
+
const contextLines = opts.context !== void 0 ? opts.context : 3;
|
|
8779
8823
|
const results = [];
|
|
8780
8824
|
for (const f of files) {
|
|
8781
8825
|
const text = readFileText(f);
|
|
8782
8826
|
if (text === null) continue;
|
|
8783
|
-
const parsed = parseConflicts(f, text);
|
|
8827
|
+
const parsed = parseConflicts(f, text, contextLines);
|
|
8784
8828
|
if (parsed.regions.length > 0 || parsed.warnings.length > 0) results.push(parsed);
|
|
8785
8829
|
}
|
|
8786
8830
|
const fullSourceBytes = sumFileSizes(files);
|
|
8787
8831
|
const detail = opts.path ?? ".";
|
|
8788
8832
|
if (opts.json === true) {
|
|
8789
8833
|
const jsonText = displaySafeJson(opts.summary === true ? results.map(summarizeFileConflicts) : results, 0);
|
|
8790
|
-
|
|
8834
|
+
emit(jsonText);
|
|
8791
8835
|
recordReadStat("conflicts", fullSourceBytes, jsonText, detail);
|
|
8792
8836
|
} else if (opts.summary === true) {
|
|
8793
8837
|
const text = formatConflictSummaries(results.map(summarizeFileConflicts));
|
|
@@ -8865,7 +8909,7 @@ function refIsSafe(ref) {
|
|
|
8865
8909
|
return !ref.startsWith("-");
|
|
8866
8910
|
}
|
|
8867
8911
|
function emitUnsafeRef(ref) {
|
|
8868
|
-
|
|
8912
|
+
emitErr(`Refusing a git ref that starts with '-': ${ref}`);
|
|
8869
8913
|
}
|
|
8870
8914
|
function changedDiffBaselineBytes(cwd, ref, files) {
|
|
8871
8915
|
if (files.length === 0) return 0;
|
|
@@ -8888,25 +8932,25 @@ function runChanged(opts = {}) {
|
|
|
8888
8932
|
try {
|
|
8889
8933
|
const result = runGit(["diff", ref, "--name-only"], { cwd });
|
|
8890
8934
|
if (result.exitCode !== 0) {
|
|
8891
|
-
|
|
8935
|
+
emitErr(`git diff failed: ${result.stderr}`);
|
|
8892
8936
|
const hint = buildChangedRefHint(cwd, ref);
|
|
8893
8937
|
if (hint !== null) {
|
|
8894
|
-
|
|
8938
|
+
emitErr(hint);
|
|
8895
8939
|
}
|
|
8896
8940
|
return 1;
|
|
8897
8941
|
}
|
|
8898
8942
|
changedFiles = result.stdout.trim().split(/\r?\n/).filter(Boolean);
|
|
8899
8943
|
} catch {
|
|
8900
|
-
|
|
8944
|
+
emitErr(`Could not run git diff against '${ref}'`);
|
|
8901
8945
|
return 1;
|
|
8902
8946
|
}
|
|
8903
8947
|
const emptyEnvelope = () => {
|
|
8904
|
-
|
|
8948
|
+
emit(displaySafeJson({ items: [], truncated: false, totalCount: 0 }));
|
|
8905
8949
|
return 0;
|
|
8906
8950
|
};
|
|
8907
8951
|
if (changedFiles.length === 0) {
|
|
8908
8952
|
if (opts.json === true) return emptyEnvelope();
|
|
8909
|
-
|
|
8953
|
+
emit("No files changed.");
|
|
8910
8954
|
return 0;
|
|
8911
8955
|
}
|
|
8912
8956
|
const preGrepFileCount = changedFiles.length;
|
|
@@ -8914,7 +8958,7 @@ function runChanged(opts = {}) {
|
|
|
8914
8958
|
if (matchesGrep !== void 0) changedFiles = changedFiles.filter((f) => matchesGrep(f));
|
|
8915
8959
|
if (matchesGrep !== void 0 && changedFiles.length === 0) {
|
|
8916
8960
|
if (opts.json === true) return emptyEnvelope();
|
|
8917
|
-
|
|
8961
|
+
emit(grepFilteredToEmptyNotice(preGrepFileCount, opts.grep ?? "", "changed file", "changed files"));
|
|
8918
8962
|
return 0;
|
|
8919
8963
|
}
|
|
8920
8964
|
const postGrepFileCount = changedFiles.length;
|
|
@@ -8928,12 +8972,12 @@ function runChanged(opts = {}) {
|
|
|
8928
8972
|
if (opts.json === true) return emptyEnvelope();
|
|
8929
8973
|
const grepRemoved = preGrepFileCount - postGrepFileCount;
|
|
8930
8974
|
if (matchesGrep !== void 0 && grepRemoved > 0) {
|
|
8931
|
-
|
|
8975
|
+
emit(
|
|
8932
8976
|
`No non-test files matched --grep ${opts.grep ?? ""} (${excludeTestsHiddenNote(hiddenTestFiles)}; ${countNoun(grepRemoved, "other changed file")} did not match the filter)`
|
|
8933
8977
|
);
|
|
8934
8978
|
return 0;
|
|
8935
8979
|
}
|
|
8936
|
-
|
|
8980
|
+
emit(`No non-test files changed (${excludeTestsHiddenNote(hiddenTestFiles)})`);
|
|
8937
8981
|
return 0;
|
|
8938
8982
|
}
|
|
8939
8983
|
if (opts.symbolMode === true) {
|
|
@@ -8949,27 +8993,27 @@ function runChanged(opts = {}) {
|
|
|
8949
8993
|
}
|
|
8950
8994
|
const allSymbols = [];
|
|
8951
8995
|
for (const f of changedFiles) {
|
|
8952
|
-
const fileSymbols = querySymbols({ filePath: resolveIndexPath(f, projectRoot), limit:
|
|
8996
|
+
const fileSymbols = querySymbols({ filePath: resolveIndexPath(f, projectRoot), limit: FIND_SCAN_LIMIT });
|
|
8953
8997
|
const hunks = hunksByFile.get(f);
|
|
8954
8998
|
const scoped = hunks === void 0 || isVirtualIndexedPath(f) ? fileSymbols : fileSymbols.filter((s) => hunks.some((h) => h.start <= s.lineEnd && h.end >= s.lineStart));
|
|
8955
8999
|
allSymbols.push(...scoped);
|
|
8956
9000
|
}
|
|
8957
9001
|
if (allSymbols.length === 0) {
|
|
8958
9002
|
if (opts.json === true) return emptyEnvelope();
|
|
8959
|
-
|
|
9003
|
+
emit("No symbols changed.");
|
|
8960
9004
|
return 0;
|
|
8961
9005
|
}
|
|
8962
9006
|
const symbolFullBytes = symbolDiffBaselineBytes;
|
|
8963
9007
|
if (opts.json === true) {
|
|
8964
9008
|
const capped = guardJsonRows(allSymbols);
|
|
8965
9009
|
const text = displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount });
|
|
8966
|
-
|
|
9010
|
+
emit(text);
|
|
8967
9011
|
recordReadStat("changed_lookup", symbolFullBytes, text, ref);
|
|
8968
9012
|
return 0;
|
|
8969
9013
|
}
|
|
8970
9014
|
const symbolText = allSymbols.map((s) => `${s.name} (${s.kind}) \u2014 ${formatSymbolLocation(toDisplayPath(projectRoot, s.filePath), s.lineStart)}`).join("\n");
|
|
8971
9015
|
for (const s of allSymbols) {
|
|
8972
|
-
|
|
9016
|
+
emit(`${displaySafeText(s.name)} (${displaySafeText(s.kind)}) \u2014 ${formatSymbolLocation(displaySafeText(toDisplayPath(projectRoot, s.filePath)), s.lineStart)}`);
|
|
8973
9017
|
}
|
|
8974
9018
|
recordReadStat("changed_lookup", symbolFullBytes, symbolText, ref);
|
|
8975
9019
|
return 0;
|
|
@@ -8978,12 +9022,12 @@ function runChanged(opts = {}) {
|
|
|
8978
9022
|
if (opts.json === true) {
|
|
8979
9023
|
const capped = guardJsonRows(changedFiles);
|
|
8980
9024
|
const text = displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount });
|
|
8981
|
-
|
|
9025
|
+
emit(text);
|
|
8982
9026
|
recordReadStat("changed_lookup", fullBytes, text, ref);
|
|
8983
9027
|
return 0;
|
|
8984
9028
|
}
|
|
8985
9029
|
for (const f of changedFiles) {
|
|
8986
|
-
|
|
9030
|
+
emit(f);
|
|
8987
9031
|
}
|
|
8988
9032
|
recordReadStat("changed_lookup", fullBytes, changedFiles.join("\n"), ref);
|
|
8989
9033
|
return 0;
|
|
@@ -9033,27 +9077,27 @@ function runDiff(opts) {
|
|
|
9033
9077
|
try {
|
|
9034
9078
|
diffResult = runGit(diffArgs, { cwd });
|
|
9035
9079
|
} catch {
|
|
9036
|
-
|
|
9080
|
+
emitErr(`Could not run git diff for '${match.filePath}'`);
|
|
9037
9081
|
return 1;
|
|
9038
9082
|
}
|
|
9039
9083
|
if (diffResult.exitCode !== 0) {
|
|
9040
|
-
|
|
9084
|
+
emitErr(`git diff failed: ${diffResult.stderr}`);
|
|
9041
9085
|
return 1;
|
|
9042
9086
|
}
|
|
9043
9087
|
if (diffResult.stdout.trim() === "") {
|
|
9044
|
-
|
|
9088
|
+
emit(`No changes to '${displaySafeText(match.name)}' in '${displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath))}'.`);
|
|
9045
9089
|
return 0;
|
|
9046
9090
|
}
|
|
9047
9091
|
const { hunks } = splitDiffHunks(diffResult.stdout);
|
|
9048
9092
|
const diffFileScoped = isVirtualIndexedPath(match.filePath);
|
|
9049
9093
|
const overlapping = diffFileScoped ? hunks : hunks.filter((h) => h.start <= match.lineEnd && h.end >= match.lineStart);
|
|
9050
9094
|
if (overlapping.length === 0) {
|
|
9051
|
-
|
|
9095
|
+
emit(`No changes to '${displaySafeText(match.name)}' (lines ${match.lineStart}-${match.lineEnd}) in '${displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath))}'.`);
|
|
9052
9096
|
return 0;
|
|
9053
9097
|
}
|
|
9054
9098
|
if (opts.json === true) {
|
|
9055
9099
|
const capped = guardJsonRows(overlapping.map((h) => ({ start: h.start, end: h.end, text: h.text })));
|
|
9056
|
-
|
|
9100
|
+
emit(
|
|
9057
9101
|
displaySafeJson(
|
|
9058
9102
|
{
|
|
9059
9103
|
symbol: match.name,
|
|
@@ -9070,7 +9114,7 @@ function runDiff(opts) {
|
|
|
9070
9114
|
}
|
|
9071
9115
|
const header = `# ${displaySafeText(match.name)} (${displaySafeText(match.kind)}) \u2014 ${formatSymbolLocation(displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath)), match.lineStart, match.lineEnd)}`;
|
|
9072
9116
|
const diffNote = diffFileScoped ? [virtualIndexedScopeNote(displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath)), "these hunks cover the whole file rather than this symbol alone")] : [];
|
|
9073
|
-
|
|
9117
|
+
emit(guardText([header, ...diffNote, ...overlapping.map((h) => h.text)].join("\n"), "diff"));
|
|
9074
9118
|
return 0;
|
|
9075
9119
|
}
|
|
9076
9120
|
var DEFAULT_LOG_MAX_COUNT = 20;
|
|
@@ -9131,20 +9175,20 @@ function runLog(opts) {
|
|
|
9131
9175
|
try {
|
|
9132
9176
|
logResult = runGit(logArgs, { cwd });
|
|
9133
9177
|
} catch {
|
|
9134
|
-
|
|
9178
|
+
emitErr(`Could not run git log for '${match.filePath}'`);
|
|
9135
9179
|
return 1;
|
|
9136
9180
|
}
|
|
9137
9181
|
if (logResult.exitCode !== 0) {
|
|
9138
|
-
|
|
9182
|
+
emitErr(`git log failed: ${displaySafeText(logResult.stderr)}`);
|
|
9139
9183
|
return 1;
|
|
9140
9184
|
}
|
|
9141
9185
|
if (logResult.stdout.trim() === "") {
|
|
9142
|
-
|
|
9186
|
+
emit(`No history for '${displaySafeText(match.name)}' (lines ${match.lineStart}-${match.lineEnd}) in '${displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath))}'.`);
|
|
9143
9187
|
return 0;
|
|
9144
9188
|
}
|
|
9145
9189
|
if (opts.json === true) {
|
|
9146
9190
|
const capped = guardJsonRows(parseLogDashLOutput(logResult.stdout));
|
|
9147
|
-
|
|
9191
|
+
emit(
|
|
9148
9192
|
displaySafeJson(
|
|
9149
9193
|
{
|
|
9150
9194
|
symbol: match.name,
|
|
@@ -9161,7 +9205,7 @@ function runLog(opts) {
|
|
|
9161
9205
|
}
|
|
9162
9206
|
const header = `# ${displaySafeText(match.name)} (${displaySafeText(match.kind)}) \u2014 ${formatSymbolLocation(displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath)), match.lineStart, match.lineEnd)}`;
|
|
9163
9207
|
const logNote = fileScoped ? [virtualIndexedScopeNote(displaySafeText(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath)), "this history covers the whole file rather than this symbol alone")] : [];
|
|
9164
|
-
|
|
9208
|
+
emit(guardText([header, ...logNote, logResult.stdout].join("\n"), "diff"));
|
|
9165
9209
|
return 0;
|
|
9166
9210
|
}
|
|
9167
9211
|
|
|
@@ -9611,26 +9655,26 @@ async function runZipList(opts) {
|
|
|
9611
9655
|
data = readFileBytes(opts.file);
|
|
9612
9656
|
} catch (err) {
|
|
9613
9657
|
if (err instanceof ZipInputTooLargeError) {
|
|
9614
|
-
|
|
9658
|
+
emitErr(err.message);
|
|
9615
9659
|
return 1;
|
|
9616
9660
|
}
|
|
9617
9661
|
throw err;
|
|
9618
9662
|
}
|
|
9619
9663
|
if (data === null) {
|
|
9620
|
-
|
|
9664
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
9621
9665
|
return 1;
|
|
9622
9666
|
}
|
|
9623
9667
|
let entries;
|
|
9624
9668
|
try {
|
|
9625
9669
|
entries = await listZipEntries(data);
|
|
9626
9670
|
} catch (err) {
|
|
9627
|
-
|
|
9671
|
+
emitErr(archiveReadFailure(err, opts.file));
|
|
9628
9672
|
return 1;
|
|
9629
9673
|
}
|
|
9630
9674
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
9631
9675
|
if (opts.json === true) {
|
|
9632
9676
|
const jsonText = displaySafeJson(entries, 0);
|
|
9633
|
-
|
|
9677
|
+
emit(jsonText);
|
|
9634
9678
|
recordReadStat("zip_list", fullSourceBytes, jsonText, opts.file);
|
|
9635
9679
|
} else {
|
|
9636
9680
|
const text = formatZipList(entries);
|
|
@@ -9645,13 +9689,13 @@ async function runZipRead(opts) {
|
|
|
9645
9689
|
data = readFileBytes(opts.file);
|
|
9646
9690
|
} catch (err) {
|
|
9647
9691
|
if (err instanceof ZipInputTooLargeError) {
|
|
9648
|
-
|
|
9692
|
+
emitErr(err.message);
|
|
9649
9693
|
return 1;
|
|
9650
9694
|
}
|
|
9651
9695
|
throw err;
|
|
9652
9696
|
}
|
|
9653
9697
|
if (data === null) {
|
|
9654
|
-
|
|
9698
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
9655
9699
|
return 1;
|
|
9656
9700
|
}
|
|
9657
9701
|
let entries;
|
|
@@ -9660,12 +9704,12 @@ async function runZipRead(opts) {
|
|
|
9660
9704
|
entries = await listZipEntries(data);
|
|
9661
9705
|
content = await extractZipEntry(data, opts.entry);
|
|
9662
9706
|
} catch (err) {
|
|
9663
|
-
|
|
9707
|
+
emitErr(archiveReadFailure(err, opts.file));
|
|
9664
9708
|
return 1;
|
|
9665
9709
|
}
|
|
9666
9710
|
const matchedEntry = entries.find((e) => e.path === opts.entry);
|
|
9667
9711
|
if (matchedEntry?.isDirectory === true) {
|
|
9668
|
-
|
|
9712
|
+
emitErr(`Entry '${opts.entry}' is a directory, not a file, in '${opts.file}'`);
|
|
9669
9713
|
return 1;
|
|
9670
9714
|
}
|
|
9671
9715
|
if (content === void 0) {
|
|
@@ -9673,7 +9717,7 @@ async function runZipRead(opts) {
|
|
|
9673
9717
|
const closes = rankSimilarNames(entries.map((e) => e.path), opts.entry);
|
|
9674
9718
|
if (closes.length > 0) messages.push(didYouMean(closes));
|
|
9675
9719
|
else if (entries.length > 0) messages.push(`Try: token-goat zip-list ${opts.file}`);
|
|
9676
|
-
|
|
9720
|
+
emitErr(messages.join("\n"));
|
|
9677
9721
|
return 1;
|
|
9678
9722
|
}
|
|
9679
9723
|
const buf = Buffer.from(content);
|
|
@@ -9681,7 +9725,7 @@ async function runZipRead(opts) {
|
|
|
9681
9725
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
9682
9726
|
if (opts.json === true) {
|
|
9683
9727
|
const jsonText = displaySafeJson({ path: opts.entry, text }, 0);
|
|
9684
|
-
|
|
9728
|
+
emit(jsonText);
|
|
9685
9729
|
recordReadStat("zip_read", fullSourceBytes, jsonText, opts.entry);
|
|
9686
9730
|
} else {
|
|
9687
9731
|
emitGuarded(text, "zip-read");
|
|
@@ -9695,16 +9739,16 @@ function runSqliteSchema(opts) {
|
|
|
9695
9739
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
9696
9740
|
if (opts.json === true) {
|
|
9697
9741
|
const jsonText = displaySafeJson(schema, 0);
|
|
9698
|
-
|
|
9742
|
+
emit(jsonText);
|
|
9699
9743
|
recordReadStat("sqlite_schema", fullSourceBytes, jsonText, opts.file);
|
|
9700
9744
|
} else {
|
|
9701
9745
|
const text = formatSqliteSchema(schema);
|
|
9702
|
-
|
|
9746
|
+
emit(text);
|
|
9703
9747
|
recordReadStat("sqlite_schema", fullSourceBytes, text, opts.file);
|
|
9704
9748
|
}
|
|
9705
9749
|
return 0;
|
|
9706
9750
|
} catch (e) {
|
|
9707
|
-
|
|
9751
|
+
emitErr(extractErrorMessage(e));
|
|
9708
9752
|
return 1;
|
|
9709
9753
|
}
|
|
9710
9754
|
}
|
|
@@ -9714,16 +9758,16 @@ function runSqliteTables(opts) {
|
|
|
9714
9758
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
9715
9759
|
if (opts.json === true) {
|
|
9716
9760
|
const jsonText = displaySafeJson(tables, 0);
|
|
9717
|
-
|
|
9761
|
+
emit(jsonText);
|
|
9718
9762
|
recordReadStat("sqlite_tables", fullSourceBytes, jsonText, opts.file);
|
|
9719
9763
|
} else {
|
|
9720
9764
|
const text = formatSqliteTables(tables);
|
|
9721
|
-
|
|
9765
|
+
emit(text);
|
|
9722
9766
|
recordReadStat("sqlite_tables", fullSourceBytes, text, opts.file);
|
|
9723
9767
|
}
|
|
9724
9768
|
return 0;
|
|
9725
9769
|
} catch (e) {
|
|
9726
|
-
|
|
9770
|
+
emitErr(extractErrorMessage(e));
|
|
9727
9771
|
return 1;
|
|
9728
9772
|
}
|
|
9729
9773
|
}
|
|
@@ -9732,7 +9776,7 @@ function runSqliteQuery(opts) {
|
|
|
9732
9776
|
try {
|
|
9733
9777
|
head = opts.head !== void 0 ? requireNonNegativeStrictInt("--head", opts.head) : void 0;
|
|
9734
9778
|
} catch (e) {
|
|
9735
|
-
|
|
9779
|
+
emitErr(extractErrorMessage(e));
|
|
9736
9780
|
return 1;
|
|
9737
9781
|
}
|
|
9738
9782
|
try {
|
|
@@ -9749,7 +9793,7 @@ function runSqliteQuery(opts) {
|
|
|
9749
9793
|
totalCount,
|
|
9750
9794
|
rowCapped: result.rowCapped
|
|
9751
9795
|
}, 0);
|
|
9752
|
-
|
|
9796
|
+
emit(jsonText);
|
|
9753
9797
|
const uncappedFull = guardJsonRows(result.rows);
|
|
9754
9798
|
const baselineJsonText = displaySafeJson({
|
|
9755
9799
|
columns: result.columns,
|
|
@@ -9761,27 +9805,27 @@ function runSqliteQuery(opts) {
|
|
|
9761
9805
|
recordReadStat("sqlite_query", Buffer.byteLength(baselineJsonText, "utf8"), jsonText, opts.file);
|
|
9762
9806
|
} else {
|
|
9763
9807
|
const text = formatSqliteQueryTable({ ...result, rows }, { headTruncated });
|
|
9764
|
-
|
|
9808
|
+
emit(text);
|
|
9765
9809
|
const baselineText = formatSqliteQueryTable({ ...result, rows: result.rows }, { headTruncated: false });
|
|
9766
9810
|
recordReadStat("sqlite_query", Buffer.byteLength(baselineText, "utf8"), text, opts.file);
|
|
9767
9811
|
}
|
|
9768
9812
|
return 0;
|
|
9769
9813
|
} catch (e) {
|
|
9770
|
-
|
|
9814
|
+
emitErr(extractErrorMessage(e));
|
|
9771
9815
|
return 1;
|
|
9772
9816
|
}
|
|
9773
9817
|
}
|
|
9774
9818
|
function runCoverageReportGaps(opts) {
|
|
9775
9819
|
const text = readFileText(opts.file);
|
|
9776
9820
|
if (text === null) {
|
|
9777
|
-
|
|
9821
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
9778
9822
|
return 1;
|
|
9779
9823
|
}
|
|
9780
9824
|
let report;
|
|
9781
9825
|
try {
|
|
9782
9826
|
report = parseCoverageReport(text);
|
|
9783
9827
|
} catch (e) {
|
|
9784
|
-
|
|
9828
|
+
emitErr(`Failed to parse coverage report (not valid LCOV or Istanbul JSON): ${opts.file}
|
|
9785
9829
|
${extractErrorMessage(e)}`);
|
|
9786
9830
|
return 1;
|
|
9787
9831
|
}
|
|
@@ -9789,7 +9833,7 @@ ${extractErrorMessage(e)}`);
|
|
|
9789
9833
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
9790
9834
|
if (opts.json === true) {
|
|
9791
9835
|
const jsonText = displaySafeJson(scoped, 0);
|
|
9792
|
-
|
|
9836
|
+
emit(jsonText);
|
|
9793
9837
|
recordReadStat("coverage_report_gaps", fullSourceBytes, jsonText, opts.file);
|
|
9794
9838
|
} else {
|
|
9795
9839
|
const text2 = formatCoverageGaps(scoped);
|
|
@@ -9867,17 +9911,17 @@ function extractFrontmatter(lines) {
|
|
|
9867
9911
|
function runConfigGet(opts) {
|
|
9868
9912
|
const text = readFileText(opts.file);
|
|
9869
9913
|
if (text === null) {
|
|
9870
|
-
|
|
9914
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
9871
9915
|
return 1;
|
|
9872
9916
|
}
|
|
9873
9917
|
const frontmatterLines = extractFrontmatter(text.split(/\r?\n/));
|
|
9874
9918
|
if (frontmatterLines !== null) {
|
|
9875
9919
|
const value = lookupYaml(frontmatterLines, opts.key);
|
|
9876
9920
|
if (value === null) {
|
|
9877
|
-
|
|
9921
|
+
emitErr(`Key '${opts.key}' not found in ${opts.file}`);
|
|
9878
9922
|
return 1;
|
|
9879
9923
|
}
|
|
9880
|
-
|
|
9924
|
+
emit(value);
|
|
9881
9925
|
return 0;
|
|
9882
9926
|
}
|
|
9883
9927
|
const ext = path10.extname(opts.file).toLowerCase();
|
|
@@ -9886,29 +9930,29 @@ function runConfigGet(opts) {
|
|
|
9886
9930
|
let obj = JSON.parse(text);
|
|
9887
9931
|
for (const part of opts.key.split(".")) {
|
|
9888
9932
|
if (typeof obj !== "object" || obj === null) {
|
|
9889
|
-
|
|
9933
|
+
emitErr(`Key '${opts.key}' not found in ${opts.file}`);
|
|
9890
9934
|
return 1;
|
|
9891
9935
|
}
|
|
9892
9936
|
obj = obj[part];
|
|
9893
9937
|
if (obj === void 0) {
|
|
9894
|
-
|
|
9938
|
+
emitErr(`Key '${opts.key}' not found in ${opts.file}`);
|
|
9895
9939
|
return 1;
|
|
9896
9940
|
}
|
|
9897
9941
|
}
|
|
9898
|
-
|
|
9942
|
+
emit(displaySafeJson(obj, 0));
|
|
9899
9943
|
return 0;
|
|
9900
9944
|
} catch {
|
|
9901
|
-
|
|
9945
|
+
emitErr(`Failed to parse JSON: ${opts.file}`);
|
|
9902
9946
|
return 1;
|
|
9903
9947
|
}
|
|
9904
9948
|
}
|
|
9905
9949
|
if (ext === ".yaml" || ext === ".yml") {
|
|
9906
9950
|
const value = lookupYaml(text.split(/\r?\n/), opts.key);
|
|
9907
9951
|
if (value === null) {
|
|
9908
|
-
|
|
9952
|
+
emitErr(`Key '${opts.key}' not found in ${opts.file}`);
|
|
9909
9953
|
return 1;
|
|
9910
9954
|
}
|
|
9911
|
-
|
|
9955
|
+
emit(value);
|
|
9912
9956
|
return 0;
|
|
9913
9957
|
}
|
|
9914
9958
|
const keyParts = opts.key.split(".");
|
|
@@ -9929,18 +9973,18 @@ function runConfigGet(opts) {
|
|
|
9929
9973
|
if (new RegExp(`^${escapeRegExp(leafKey)}\\s*=`).test(trimmed)) {
|
|
9930
9974
|
const eqIdx = trimmed.indexOf("=");
|
|
9931
9975
|
const rawValue = stripInlineComment(trimmed.slice(eqIdx + 1)).trim();
|
|
9932
|
-
|
|
9976
|
+
emit(stripPairedQuotes(rawValue));
|
|
9933
9977
|
return 0;
|
|
9934
9978
|
}
|
|
9935
9979
|
}
|
|
9936
|
-
|
|
9980
|
+
emitErr(`Key '${opts.key}' not found in ${opts.file}`);
|
|
9937
9981
|
return 1;
|
|
9938
9982
|
}
|
|
9939
9983
|
function runPerFileEmitting(files, label, run) {
|
|
9940
9984
|
let anyOk = false;
|
|
9941
9985
|
files.forEach((file, i) => {
|
|
9942
|
-
if (i > 0)
|
|
9943
|
-
|
|
9986
|
+
if (i > 0) emit("");
|
|
9987
|
+
emit(`# ${label}: ${file}`);
|
|
9944
9988
|
if (run(file) === 0) anyOk = true;
|
|
9945
9989
|
});
|
|
9946
9990
|
return anyOk ? 0 : 1;
|
|
@@ -9950,7 +9994,7 @@ function runExports(opts) {
|
|
|
9950
9994
|
if (multiFiles.length > 1) return runPerFileEmitting(multiFiles, "Exports", (file) => runExports({ ...opts, file }));
|
|
9951
9995
|
const confined = fileConfinementRefusal("This file", opts.file, opts.projectRoot);
|
|
9952
9996
|
if (confined !== null) {
|
|
9953
|
-
|
|
9997
|
+
emitErr(confined);
|
|
9954
9998
|
return 1;
|
|
9955
9999
|
}
|
|
9956
10000
|
const diskPath = resolveAgainstProjectRoot(opts.file, opts.projectRoot);
|
|
@@ -9969,7 +10013,7 @@ function runExports(opts) {
|
|
|
9969
10013
|
const ext = path10.extname(opts.file).toLowerCase();
|
|
9970
10014
|
const text = readFileText(diskPath);
|
|
9971
10015
|
if (text === null && symbols.length === 0) {
|
|
9972
|
-
|
|
10016
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
9973
10017
|
return 1;
|
|
9974
10018
|
}
|
|
9975
10019
|
if (text !== null) {
|
|
@@ -9979,7 +10023,7 @@ function runExports(opts) {
|
|
|
9979
10023
|
for (const n of extractExportNames(text, ext)) if (!names.includes(n)) names.push(n);
|
|
9980
10024
|
}
|
|
9981
10025
|
if (names.length === 0) {
|
|
9982
|
-
|
|
10026
|
+
emit(`No exported symbols found in '${displaySafeText(opts.file)}'`);
|
|
9983
10027
|
return 0;
|
|
9984
10028
|
}
|
|
9985
10029
|
const preFilterCount = names.length;
|
|
@@ -9989,12 +10033,12 @@ function runExports(opts) {
|
|
|
9989
10033
|
if (filteredNames.length === 0) {
|
|
9990
10034
|
if (opts.json === true) {
|
|
9991
10035
|
const jsonText = displaySafeJson([]);
|
|
9992
|
-
|
|
10036
|
+
emit(jsonText);
|
|
9993
10037
|
recordReadStat("exports", fullSourceBytes, jsonText, opts.file);
|
|
9994
10038
|
return 0;
|
|
9995
10039
|
}
|
|
9996
10040
|
const textOut = grepFilteredToEmptyNotice(preFilterCount, opts.grep ?? "", "exported symbol", "exported symbols");
|
|
9997
|
-
|
|
10041
|
+
emit(textOut);
|
|
9998
10042
|
recordReadStat("exports", fullSourceBytes, textOut, opts.file);
|
|
9999
10043
|
return 0;
|
|
10000
10044
|
}
|
|
@@ -10005,7 +10049,7 @@ function runExports(opts) {
|
|
|
10005
10049
|
return { name: n, kind: kindOf(n), lineStart: loc?.lineStart ?? null, lineEnd: loc?.lineEnd ?? null };
|
|
10006
10050
|
})
|
|
10007
10051
|
);
|
|
10008
|
-
|
|
10052
|
+
emit(jsonText);
|
|
10009
10053
|
recordReadStat("exports", fullSourceBytes, jsonText, opts.file);
|
|
10010
10054
|
return 0;
|
|
10011
10055
|
}
|
|
@@ -10015,7 +10059,7 @@ function runExports(opts) {
|
|
|
10015
10059
|
return `${kindOf(n).padEnd(10)} ${n}${locSuffix}`;
|
|
10016
10060
|
});
|
|
10017
10061
|
for (const line of outLines) {
|
|
10018
|
-
|
|
10062
|
+
emit(line);
|
|
10019
10063
|
}
|
|
10020
10064
|
recordReadStat("exports", fullSourceBytes, outLines.join("\n"), opts.file);
|
|
10021
10065
|
return 0;
|
|
@@ -10026,12 +10070,12 @@ function runImports(opts) {
|
|
|
10026
10070
|
const diskPath = resolveAgainstProjectRoot(opts.file, opts.projectRoot);
|
|
10027
10071
|
const text = readFileText(diskPath);
|
|
10028
10072
|
if (text === null) {
|
|
10029
|
-
|
|
10073
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
10030
10074
|
return 1;
|
|
10031
10075
|
}
|
|
10032
10076
|
const imports = extractImports(text, importsExtensionFor(opts.file));
|
|
10033
10077
|
if (imports.length === 0) {
|
|
10034
|
-
|
|
10078
|
+
emit(`No imports found in '${displaySafeText(opts.file)}'`);
|
|
10035
10079
|
return 0;
|
|
10036
10080
|
}
|
|
10037
10081
|
const preFilterCount = imports.length;
|
|
@@ -10041,25 +10085,25 @@ function runImports(opts) {
|
|
|
10041
10085
|
if (filteredImports.length === 0) {
|
|
10042
10086
|
if (opts.json === true) {
|
|
10043
10087
|
const jsonText = displaySafeJson({ items: [], truncated: false, totalCount: 0 });
|
|
10044
|
-
|
|
10088
|
+
emit(jsonText);
|
|
10045
10089
|
recordReadStat("imports", fullSourceBytes, jsonText, opts.file);
|
|
10046
10090
|
return 0;
|
|
10047
10091
|
}
|
|
10048
10092
|
const text2 = grepFilteredToEmptyNotice(preFilterCount, opts.grep ?? "", "import", "imports");
|
|
10049
|
-
|
|
10093
|
+
emit(text2);
|
|
10050
10094
|
recordReadStat("imports", fullSourceBytes, text2, opts.file);
|
|
10051
10095
|
return 0;
|
|
10052
10096
|
}
|
|
10053
10097
|
if (opts.json === true) {
|
|
10054
10098
|
const capped = guardJsonRows(filteredImports);
|
|
10055
10099
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount });
|
|
10056
|
-
|
|
10100
|
+
emit(jsonText);
|
|
10057
10101
|
recordReadStat("imports", fullSourceBytes, jsonText, opts.file);
|
|
10058
10102
|
return 0;
|
|
10059
10103
|
}
|
|
10060
10104
|
const outLines = filteredImports.map((imp) => `import ${imp}`);
|
|
10061
10105
|
for (const line of outLines) {
|
|
10062
|
-
|
|
10106
|
+
emit(line);
|
|
10063
10107
|
}
|
|
10064
10108
|
recordReadStat("imports", fullSourceBytes, outLines.join("\n"), opts.file);
|
|
10065
10109
|
return 0;
|
|
@@ -10157,50 +10201,55 @@ function runNoteList(opts = {}) {
|
|
|
10157
10201
|
}
|
|
10158
10202
|
function runFind(opts) {
|
|
10159
10203
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
10160
|
-
|
|
10204
|
+
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
10161
10205
|
return 1;
|
|
10162
10206
|
}
|
|
10163
10207
|
const rootDir = resolveProjectRoot({ project: process.cwd() });
|
|
10164
10208
|
const patternLower = opts.pattern.toLowerCase();
|
|
10165
|
-
const
|
|
10166
|
-
const
|
|
10167
|
-
|
|
10168
|
-
|
|
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
|
+
});
|
|
10169
10215
|
let fuzzyNames = [];
|
|
10170
|
-
if (
|
|
10171
|
-
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
|
+
}
|
|
10172
10225
|
}
|
|
10173
|
-
const
|
|
10174
|
-
const allFiles = [...new Set(matched.map((s) => s.filePath))];
|
|
10226
|
+
const allFiles = [...matchedFiles];
|
|
10175
10227
|
const files = allFiles.slice(0, opts.limit ?? 50);
|
|
10176
10228
|
const limitDropped = allFiles.length - files.length;
|
|
10177
|
-
const truncated =
|
|
10229
|
+
const truncated = limitDropped > 0;
|
|
10178
10230
|
if (files.length === 0) {
|
|
10179
|
-
|
|
10231
|
+
emitErr(`No indexed files match '${opts.pattern}'`);
|
|
10180
10232
|
return 1;
|
|
10181
10233
|
}
|
|
10182
10234
|
if (opts.json === true) {
|
|
10183
10235
|
const fuzzyPayload = fuzzyNames.length > 0 ? { fuzzy: true, matchedNames: fuzzyNames } : {};
|
|
10184
|
-
|
|
10236
|
+
emit(displaySafeJson({ files, truncated, totalCount: allFiles.length, ...fuzzyPayload }));
|
|
10185
10237
|
return 0;
|
|
10186
10238
|
}
|
|
10187
10239
|
if (fuzzyNames.length > 0) {
|
|
10188
|
-
|
|
10240
|
+
emitErr(`No symbol name contains '${opts.pattern}'; showing files for the nearest indexed ${fuzzyNames.length === 1 ? "name" : "names"}: ${fuzzyNames.join(", ")}`);
|
|
10189
10241
|
}
|
|
10190
10242
|
for (const f of files) {
|
|
10191
|
-
|
|
10243
|
+
emit(toDisplayPath(rootDir, f));
|
|
10192
10244
|
}
|
|
10193
10245
|
if (limitDropped > 0) {
|
|
10194
|
-
|
|
10195
|
-
}
|
|
10196
|
-
if (rawSymbols.length === FIND_SCAN_LIMIT2) {
|
|
10197
|
-
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`);
|
|
10198
10247
|
}
|
|
10199
10248
|
return 0;
|
|
10200
10249
|
}
|
|
10201
10250
|
function runLocate(opts) {
|
|
10202
10251
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
10203
|
-
|
|
10252
|
+
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
10204
10253
|
return 1;
|
|
10205
10254
|
}
|
|
10206
10255
|
const rootDir = opts.projectRoot ?? resolveProjectRoot({ project: process.cwd() });
|
|
@@ -10211,35 +10260,55 @@ function runLocate(opts) {
|
|
|
10211
10260
|
targetFile = targetSpec.slice(0, colonIdx);
|
|
10212
10261
|
targetSpec = targetSpec.slice(colonIdx + 2);
|
|
10213
10262
|
}
|
|
10214
|
-
const
|
|
10215
|
-
limit: FIND_SCAN_LIMIT2
|
|
10216
|
-
};
|
|
10263
|
+
const scanOpts = {};
|
|
10217
10264
|
if (targetFile !== void 0) {
|
|
10218
|
-
|
|
10219
|
-
healStaleIndex(
|
|
10265
|
+
scanOpts.filePath = resolveIndexPath(targetFile, rootDir);
|
|
10266
|
+
healStaleIndex(scanOpts.filePath);
|
|
10220
10267
|
} else {
|
|
10221
|
-
|
|
10268
|
+
scanOpts.rootDir = rootDir;
|
|
10222
10269
|
}
|
|
10223
|
-
|
|
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();
|
|
10224
10289
|
if (targetFile === void 0) {
|
|
10225
|
-
const heal = healStaleResultFiles(
|
|
10226
|
-
if (heal.healed)
|
|
10290
|
+
const heal = healStaleResultFiles([...found.files]);
|
|
10291
|
+
if (heal.healed) found = scan();
|
|
10227
10292
|
}
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
const partialMatches = rawSymbols.filter(
|
|
10231
|
-
(s) => s.name.toLowerCase() !== specLower && s.name.toLowerCase().includes(specLower)
|
|
10232
|
-
);
|
|
10233
|
-
const combined = [...exactMatches, ...partialMatches];
|
|
10293
|
+
let matchCount = found.exactCount + found.partialCount;
|
|
10294
|
+
let combined = [...found.exact, ...found.partial];
|
|
10234
10295
|
let fuzzyNames = [];
|
|
10235
|
-
if (
|
|
10236
|
-
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
|
+
}
|
|
10237
10308
|
}
|
|
10238
|
-
const
|
|
10239
|
-
const limit = opts.limit ?? 25;
|
|
10240
|
-
const shown = matched.slice(0, limit);
|
|
10309
|
+
const shown = combined.slice(0, limit);
|
|
10241
10310
|
if (shown.length === 0) {
|
|
10242
|
-
|
|
10311
|
+
emitErr(`No landmark or symbol located for '${targetSpec}'`);
|
|
10243
10312
|
return 1;
|
|
10244
10313
|
}
|
|
10245
10314
|
const hits = shown.map((s) => ({
|
|
@@ -10251,22 +10320,22 @@ function runLocate(opts) {
|
|
|
10251
10320
|
span: `${s.lineStart}-${s.lineEnd}`
|
|
10252
10321
|
}));
|
|
10253
10322
|
if (opts.json === true) {
|
|
10254
|
-
|
|
10323
|
+
emit(displaySafeJson({
|
|
10255
10324
|
items: hits,
|
|
10256
|
-
totalCount:
|
|
10257
|
-
truncated:
|
|
10325
|
+
totalCount: matchCount,
|
|
10326
|
+
truncated: matchCount > limit,
|
|
10258
10327
|
...fuzzyNames.length > 0 ? { fuzzy: true, matchedNames: fuzzyNames } : {}
|
|
10259
10328
|
}));
|
|
10260
10329
|
return 0;
|
|
10261
10330
|
}
|
|
10262
10331
|
if (fuzzyNames.length > 0) {
|
|
10263
|
-
|
|
10332
|
+
emitErr(`No exact landmark for '${targetSpec}'; nearest matches: ${fuzzyNames.join(", ")}`);
|
|
10264
10333
|
}
|
|
10265
10334
|
for (const hit of hits) {
|
|
10266
|
-
|
|
10335
|
+
emit(`${displaySafeText(hit.filePath)}:${hit.span} [${displaySafeText(hit.kind)}] ${displaySafeText(hit.name)}`);
|
|
10267
10336
|
}
|
|
10268
|
-
if (
|
|
10269
|
-
|
|
10337
|
+
if (matchCount > limit) {
|
|
10338
|
+
emitErr(`Showing ${limit} of ${matchCount} locations; rerun with --limit ${matchCount} to see them all`);
|
|
10270
10339
|
}
|
|
10271
10340
|
return 0;
|
|
10272
10341
|
}
|
|
@@ -10274,10 +10343,10 @@ function runListSections(opts) {
|
|
|
10274
10343
|
const sections = listSections(opts.file);
|
|
10275
10344
|
if (sections.length === 0) {
|
|
10276
10345
|
if (!fileExists(opts.file)) {
|
|
10277
|
-
|
|
10346
|
+
emitErr(`Could not read: ${opts.file}`);
|
|
10278
10347
|
return 1;
|
|
10279
10348
|
}
|
|
10280
|
-
|
|
10349
|
+
emitErr(`No sections found in '${opts.file}'`);
|
|
10281
10350
|
return 1;
|
|
10282
10351
|
}
|
|
10283
10352
|
const preFilterCount = sections.length;
|
|
@@ -10293,19 +10362,19 @@ function runListSections(opts) {
|
|
|
10293
10362
|
const filtered = matchesGrep !== void 0 ? labelled.filter((_, i) => matchesGrep(sections[i] ?? "")) : labelled;
|
|
10294
10363
|
if (filtered.length === 0) {
|
|
10295
10364
|
if (opts.json === true) {
|
|
10296
|
-
|
|
10365
|
+
emit(displaySafeJson({ items: [], truncated: false, totalCount: 0 }));
|
|
10297
10366
|
return 0;
|
|
10298
10367
|
}
|
|
10299
|
-
|
|
10368
|
+
emit(grepFilteredToEmptyNotice(preFilterCount, opts.grep ?? "", "section", "sections"));
|
|
10300
10369
|
return 0;
|
|
10301
10370
|
}
|
|
10302
10371
|
if (opts.json === true) {
|
|
10303
10372
|
const capped = guardJsonRows(filtered);
|
|
10304
|
-
|
|
10373
|
+
emit(displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount }));
|
|
10305
10374
|
return 0;
|
|
10306
10375
|
}
|
|
10307
10376
|
for (const heading of filtered) {
|
|
10308
|
-
|
|
10377
|
+
emit(heading);
|
|
10309
10378
|
}
|
|
10310
10379
|
return 0;
|
|
10311
10380
|
}
|
|
@@ -10314,6 +10383,16 @@ function runListSections(opts) {
|
|
|
10314
10383
|
init_define_import_meta_env();
|
|
10315
10384
|
import * as fs11 from "node:fs";
|
|
10316
10385
|
import * as path11 from "node:path";
|
|
10386
|
+
function htmlIdSectionFallback(filePath, heading) {
|
|
10387
|
+
if (detectLanguage(filePath) !== "html") return null;
|
|
10388
|
+
healStaleIndex(filePath);
|
|
10389
|
+
const hit = querySymbols({ name: stripHtmlIdSpelling(heading, filePath), filePath, kind: "html_id", limit: 1 })[0];
|
|
10390
|
+
if (hit === void 0) return null;
|
|
10391
|
+
const text = readFileText(filePath);
|
|
10392
|
+
if (text === null) return null;
|
|
10393
|
+
const lines = text.split("\n");
|
|
10394
|
+
return { heading: hit.name, content: lines.slice(hit.lineStart - 1, hit.lineEnd).join("\n"), lineStart: hit.lineStart, lineEnd: hit.lineEnd };
|
|
10395
|
+
}
|
|
10317
10396
|
var AMBIGUOUS_HEADING_LIMIT = 10;
|
|
10318
10397
|
function literalHeadingExists(filePath, heading) {
|
|
10319
10398
|
const ordinalMatch = /^([^#\r\n]+)#(\d+)$/.exec(heading);
|
|
@@ -10335,7 +10414,7 @@ function runSection(opts) {
|
|
|
10335
10414
|
const multiHeadings = heading.split(",").map((h) => h.trim()).filter((h) => h.length > 0);
|
|
10336
10415
|
if (multiHeadings.length > 1) return runSectionMulti(specFilePath, filePath, multiHeadings, opts);
|
|
10337
10416
|
}
|
|
10338
|
-
const result = readSection(filePath, heading, readFileText);
|
|
10417
|
+
const result = readSection(filePath, heading, readFileText) ?? htmlIdSectionFallback(filePath, heading);
|
|
10339
10418
|
if (result === null) {
|
|
10340
10419
|
if (!fs11.existsSync(filePath)) {
|
|
10341
10420
|
return { text: `File not found: '${filePath}'`, code: 1 };
|
|
@@ -10374,15 +10453,38 @@ function runSection(opts) {
|
|
|
10374
10453
|
}
|
|
10375
10454
|
const kind = result.redirectedFrom !== void 0 ? "section_replacement" : "section_read";
|
|
10376
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
|
+
}
|
|
10377
10469
|
if (opts.json === true) {
|
|
10378
|
-
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);
|
|
10379
10481
|
if (opts.suppressStat !== true) recordReadStat(kind, fullSourceBytes, text2, heading);
|
|
10380
10482
|
return { text: text2, code: 0 };
|
|
10381
10483
|
}
|
|
10382
10484
|
const redirectNote = result.redirectedFrom !== void 0 ? ` (redirected from: '${result.redirectedFrom}')` : "";
|
|
10383
10485
|
const text = guardText(
|
|
10384
|
-
`# ${result.heading} \u2014 ${filePath}:${result.lineStart}-${
|
|
10385
|
-
${
|
|
10486
|
+
`# ${result.heading} \u2014 ${filePath}:${result.lineStart}-${lineEnd}${redirectNote}
|
|
10487
|
+
${content}${truncatedNotice}`,
|
|
10386
10488
|
"heading"
|
|
10387
10489
|
);
|
|
10388
10490
|
if (opts.suppressStat !== true) recordReadStat(kind, fullSourceBytes, text, heading);
|
|
@@ -10503,8 +10605,7 @@ ${sub.text}`);
|
|
|
10503
10605
|
// src/read_commands.ts
|
|
10504
10606
|
var SYMBOL_PREVIEW_LINES = 5;
|
|
10505
10607
|
var GREP_MAX_LINES = 200;
|
|
10506
|
-
var
|
|
10507
|
-
var REFS_TOP_SCAN_LIMIT = 2e4;
|
|
10608
|
+
var FIND_SCAN_LIMIT = 2e4;
|
|
10508
10609
|
function fileExists2(p) {
|
|
10509
10610
|
try {
|
|
10510
10611
|
fs12.statSync(p);
|
|
@@ -10579,6 +10680,7 @@ function verifyPin(p, pinned) {
|
|
|
10579
10680
|
verifyPinnedIdentity(p, pinned);
|
|
10580
10681
|
}
|
|
10581
10682
|
function indexFileSyncPinned(resolvedPath, dbPath) {
|
|
10683
|
+
recordKnownRootThrottled(resolvedPath, dataDir(), dbPath);
|
|
10582
10684
|
const pinned = activePins?.get(pinKey(path12.resolve(resolvedPath)));
|
|
10583
10685
|
if (pinned === void 0) {
|
|
10584
10686
|
indexFileSync(resolvedPath, dbPath);
|
|
@@ -10719,15 +10821,8 @@ function warnIfFilesStale(filePaths) {
|
|
|
10719
10821
|
);
|
|
10720
10822
|
}
|
|
10721
10823
|
}
|
|
10722
|
-
function emit4(text) {
|
|
10723
|
-
const out = colorStdout() ? text : stripAnsi(text);
|
|
10724
|
-
process.stdout.write(ensureNewline(out));
|
|
10725
|
-
}
|
|
10726
|
-
function emitErr4(text) {
|
|
10727
|
-
process.stderr.write(ensureNewline(text));
|
|
10728
|
-
}
|
|
10729
10824
|
function emitGuarded(text, command) {
|
|
10730
|
-
|
|
10825
|
+
emit(guardText(text, command));
|
|
10731
10826
|
}
|
|
10732
10827
|
function guardText(text, command) {
|
|
10733
10828
|
const cfg = loadConfig();
|
|
@@ -10782,6 +10877,11 @@ function resolveEnclosingSymbol(filePath, chunkStartLine) {
|
|
|
10782
10877
|
}
|
|
10783
10878
|
return best === null ? null : { name: best.name, kind: best.kind, lineStart: best.lineStart };
|
|
10784
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
|
+
}
|
|
10785
10885
|
function runSymbol(opts) {
|
|
10786
10886
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
10787
10887
|
return { text: `--limit must be a positive number, got: ${opts.limit}`, code: 1 };
|
|
@@ -10797,6 +10897,7 @@ function runSymbol(opts) {
|
|
|
10797
10897
|
}
|
|
10798
10898
|
const matchesGrep = opts.grep !== void 0 ? compileGrepMatcher(opts.grep) : void 0;
|
|
10799
10899
|
const excludeTests = opts.excludeTests === true;
|
|
10900
|
+
const excludeVendored = opts.excludeVendored === true;
|
|
10800
10901
|
const baseConfined = confinedProjectRoot();
|
|
10801
10902
|
const confinedRoot = opts.projectRoot !== void 0 && baseConfined !== null && isProjectRootAllowed(opts.projectRoot, baseConfined) ? confinedProjectRoot(opts.projectRoot) ?? baseConfined : baseConfined;
|
|
10802
10903
|
if (baseConfined !== null) {
|
|
@@ -10809,33 +10910,48 @@ function runSymbol(opts) {
|
|
|
10809
10910
|
}
|
|
10810
10911
|
}
|
|
10811
10912
|
const queryOpts = {};
|
|
10812
|
-
if (opts.name !== void 0) queryOpts.name = opts.name;
|
|
10813
10913
|
if (opts.file !== void 0) {
|
|
10814
10914
|
queryOpts.filePath = resolveIndexPath(opts.file, opts.projectRoot ?? process.cwd());
|
|
10815
10915
|
healStaleIndex(queryOpts.filePath);
|
|
10816
10916
|
}
|
|
10917
|
+
if (opts.name !== void 0) queryOpts.name = queryOpts.filePath !== void 0 ? stripHtmlIdSpelling(opts.name, queryOpts.filePath) : opts.name;
|
|
10817
10918
|
if (opts.kind !== void 0) queryOpts.kind = opts.kind;
|
|
10818
|
-
|
|
10819
|
-
|
|
10820
|
-
|
|
10919
|
+
const anyClientFilter = matchesGrep !== void 0 || excludeTests || excludeVendored;
|
|
10920
|
+
const effectiveLimit = opts.limit ?? DEFAULT_QUERY_LIMIT;
|
|
10921
|
+
if (!anyClientFilter && opts.limit !== void 0) {
|
|
10821
10922
|
queryOpts.limit = opts.limit;
|
|
10822
10923
|
}
|
|
10823
10924
|
if (opts.file === void 0 && opts.projectRoot !== void 0) queryOpts.rootDir = opts.projectRoot;
|
|
10824
10925
|
if (opts.file === void 0 && queryOpts.rootDir === void 0 && confinedRoot !== null) queryOpts.rootDir = confinedRoot;
|
|
10825
|
-
|
|
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();
|
|
10826
10944
|
let stillStale = EMPTY_PATH_SET;
|
|
10827
10945
|
if (opts.file === void 0) {
|
|
10828
|
-
const heal = healStaleResultFiles(
|
|
10946
|
+
const heal = healStaleResultFiles([...sweep.files]);
|
|
10829
10947
|
stillStale = heal.stillStale;
|
|
10830
|
-
if (heal.healed)
|
|
10831
|
-
}
|
|
10832
|
-
const preFilterCount =
|
|
10833
|
-
const
|
|
10834
|
-
const
|
|
10835
|
-
const
|
|
10836
|
-
|
|
10837
|
-
const hiddenByExcludeTests = excludeTests ? rawResults.filter((s) => (matchesGrep === void 0 || matchesGrep(s.name)) && isTestFile(s.filePath)).length : 0;
|
|
10838
|
-
if (excludeTests && filtered.length === 0 && hiddenByExcludeTests > 0) {
|
|
10948
|
+
if (heal.healed) sweep = runSweep();
|
|
10949
|
+
}
|
|
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) {
|
|
10839
10955
|
const label = opts.name ?? opts.grep ?? "*";
|
|
10840
10956
|
const notice = `no non-test matches for '${label}' (${excludeTestsHiddenNote(hiddenByExcludeTests)})`;
|
|
10841
10957
|
if (opts.json === true) {
|
|
@@ -10843,7 +10959,7 @@ function runSymbol(opts) {
|
|
|
10843
10959
|
}
|
|
10844
10960
|
return { text: `token-goat: ${notice}`, code: 0 };
|
|
10845
10961
|
}
|
|
10846
|
-
if (matchesGrep !== void 0 &&
|
|
10962
|
+
if (matchesGrep !== void 0 && sweep.keptCount === 0 && preFilterCount > 0) {
|
|
10847
10963
|
if (opts.json === true) {
|
|
10848
10964
|
const text2 = displaySafeJson({ items: [], truncated: false, totalCount: 0 });
|
|
10849
10965
|
return { text: text2, code: 0 };
|
|
@@ -10856,8 +10972,14 @@ function runSymbol(opts) {
|
|
|
10856
10972
|
const indexEmpty = emptyIndexRoot !== null && isIndexEmptyForProject(globalDbPath(), emptyIndexRoot);
|
|
10857
10973
|
if (opts.name !== void 0 && emptyIndexRoot !== null) {
|
|
10858
10974
|
const rootDir = emptyIndexRoot;
|
|
10859
|
-
const
|
|
10860
|
-
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
|
+
});
|
|
10861
10983
|
if (exactMatches.length > 0) {
|
|
10862
10984
|
const shown = exactMatches.slice(0, DIDYOUMEAN_LIMIT);
|
|
10863
10985
|
const where = shown.map((s) => `${s.kind} at ${formatSymbolLocation(toDisplayPath(rootDir, s.filePath), s.lineStart)}`).join("; ");
|
|
@@ -10867,12 +10989,12 @@ function runSymbol(opts) {
|
|
|
10867
10989
|
text2 += `
|
|
10868
10990
|
'${opts.name}' IS indexed (${where}${more}) -- ${widen}`;
|
|
10869
10991
|
} else {
|
|
10870
|
-
const candidates = rankSimilarNames(
|
|
10992
|
+
const candidates = rankSimilarNames([...allNames], opts.name);
|
|
10871
10993
|
text2 += candidates.length > 0 ? `
|
|
10872
10994
|
${didYouMean(candidates)}` : indexEmpty ? "" : `
|
|
10873
10995
|
Try: token-goat semantic "${opts.name}"`;
|
|
10874
10996
|
}
|
|
10875
|
-
const structuredFiles = [...
|
|
10997
|
+
const structuredFiles = [...structuredFileSet].sort();
|
|
10876
10998
|
const hit = findStructuredKeyPath(opts.name, structuredFiles);
|
|
10877
10999
|
if (hit !== null) {
|
|
10878
11000
|
const display = toDisplayPath(rootDir, hit.filePath);
|
|
@@ -10898,8 +11020,8 @@ ${emptyIndexMessage(emptyIndexRoot)}`;
|
|
|
10898
11020
|
let trueTotal;
|
|
10899
11021
|
let truncatedFlag;
|
|
10900
11022
|
if (anyClientFilter) {
|
|
10901
|
-
trueTotal =
|
|
10902
|
-
truncatedFlag = capped.truncated || results.length <
|
|
11023
|
+
trueTotal = sweep.keptCount;
|
|
11024
|
+
truncatedFlag = capped.truncated || results.length < sweep.keptCount;
|
|
10903
11025
|
} else {
|
|
10904
11026
|
trueTotal = countSymbols(queryOpts);
|
|
10905
11027
|
truncatedFlag = capped.truncated || trueTotal > results.length;
|
|
@@ -10935,7 +11057,7 @@ ${preview}${elided}` : header;
|
|
|
10935
11057
|
const warning = opts.file !== void 0 ? staleWarning(resolveIndexPath(opts.file, opts.projectRoot ?? process.cwd())) : "";
|
|
10936
11058
|
const text = guardText(warning + blocks.join("\n\n"), "symbol");
|
|
10937
11059
|
recordReadStat("symbol_lookup", fullSourceBytes, text, opts.name ?? opts.file ?? opts.grep);
|
|
10938
|
-
const symbolTotal = () => anyClientFilter ? { count:
|
|
11060
|
+
const symbolTotal = () => anyClientFilter ? { count: sweep.keptCount, exact: true } : { count: countSymbols(queryOpts), exact: true };
|
|
10939
11061
|
return { text: text + truncationFooter(results.length, effectiveLimit, symbolTotal, "matches", "--limit"), code: 0 };
|
|
10940
11062
|
}
|
|
10941
11063
|
function truncationFooter(shown, limit, total, plural, flag) {
|
|
@@ -10946,6 +11068,7 @@ token-goat: ${notice}`;
|
|
|
10946
11068
|
}
|
|
10947
11069
|
function refsTotal(clientFiltered, filteredTotal, shown, countExact, preScanCount, scanLimit) {
|
|
10948
11070
|
if (!clientFiltered) return { count: countExact(), exact: true };
|
|
11071
|
+
if (scanLimit < 0) return { count: filteredTotal ?? shown, exact: true };
|
|
10949
11072
|
return { count: filteredTotal ?? shown, exact: preScanCount < scanLimit };
|
|
10950
11073
|
}
|
|
10951
11074
|
function truncationNotice(shown, limit, total, plural, flag) {
|
|
@@ -10957,6 +11080,8 @@ function truncationNotice(shown, limit, total, plural, flag) {
|
|
|
10957
11080
|
function runRead(opts) {
|
|
10958
11081
|
const range = parseLineRange(opts.spec);
|
|
10959
11082
|
if (range !== null) return runLineRange(range, opts);
|
|
11083
|
+
const region = parseColonLineSpec(opts.spec);
|
|
11084
|
+
if (region !== null) return runLineRegion(region, opts);
|
|
10960
11085
|
const crossFilePairs = parseCrossFileMultiSpec(opts.spec);
|
|
10961
11086
|
if (crossFilePairs !== null) return runReadMulti(crossFilePairs, opts);
|
|
10962
11087
|
const { file, symbol } = parseReadSpec(opts.spec);
|
|
@@ -10996,7 +11121,7 @@ function runRead(opts) {
|
|
|
10996
11121
|
const crossFileLead = formatCrossFileLead("read", symbol, file, opts.projectRoot);
|
|
10997
11122
|
if (crossFileLead !== "") messages.push(crossFileLead);
|
|
10998
11123
|
const resolved = resolveIndexPath(file, opts.projectRoot ?? process.cwd());
|
|
10999
|
-
const scanned = querySymbols({ filePath: resolved, limit:
|
|
11124
|
+
const scanned = querySymbols({ filePath: resolved, limit: FIND_SCAN_LIMIT }).map((s) => s.name);
|
|
11000
11125
|
const closes = rankSimilarNames(scanned, symbol);
|
|
11001
11126
|
if (closes.length > 0) messages.push(didYouMean(closes));
|
|
11002
11127
|
else if (scanned.length > 0) {
|
|
@@ -11046,8 +11171,7 @@ Query subtree: token-goat json-query ${file} '<path>'`);
|
|
|
11046
11171
|
{
|
|
11047
11172
|
...match,
|
|
11048
11173
|
body: resolveBody(match),
|
|
11049
|
-
// The text branch below prepends staleWarning's DELETED line; without this the JSON form
|
|
11050
|
-
// would be the one surface that still passes a deleted file's body off as a live read.
|
|
11174
|
+
// The text branch below prepends staleWarning's DELETED line; without this the JSON form would be the one surface that still passes a deleted file's body off as a live read.
|
|
11051
11175
|
...fileIsGone(match.filePath) ? { deleted: true } : {},
|
|
11052
11176
|
...refCounts !== void 0 ? { refCount: refCounts.get(match.name) ?? 0 } : {}
|
|
11053
11177
|
}
|
|
@@ -11063,7 +11187,9 @@ Query subtree: token-goat json-query ${file} '<path>'`);
|
|
|
11063
11187
|
body
|
|
11064
11188
|
];
|
|
11065
11189
|
const warning = staleWarning(match.filePath);
|
|
11066
|
-
const
|
|
11190
|
+
const narrowerSliceHint = bodyLen > LARGE_SYMBOL_LINE_THRESHOLD ? `
|
|
11191
|
+
# for a narrower slice: token-goat grep "<pattern>" ${file} -C 15 --symbol` : "";
|
|
11192
|
+
const text = guardText(warning + trimBlankLines(lines).join("\n"), "symbol") + narrowerSliceHint;
|
|
11067
11193
|
if (opts.suppressStat !== true) recordReadStat("read_replacement", fullSourceBytes, text, opts.spec);
|
|
11068
11194
|
return { text, code: 0 };
|
|
11069
11195
|
}
|
|
@@ -11164,9 +11290,9 @@ function renderRefsTargets(targets, opts, {
|
|
|
11164
11290
|
const refRows = [];
|
|
11165
11291
|
for (const { file, symbol, key } of targets) {
|
|
11166
11292
|
const queryOpts = { name: symbol };
|
|
11167
|
-
if (opts.excludeTests === true || opts.grep !== void 0) queryOpts.limit =
|
|
11293
|
+
if (opts.excludeTests === true || opts.grep !== void 0) queryOpts.limit = UNBOUNDED_QUERY_LIMIT;
|
|
11168
11294
|
else if (opts.limit !== void 0) queryOpts.limit = opts.limit;
|
|
11169
|
-
else if (opts.top !== void 0) queryOpts.limit =
|
|
11295
|
+
else if (opts.top !== void 0) queryOpts.limit = UNBOUNDED_QUERY_LIMIT;
|
|
11170
11296
|
const rootDir = refsRootDir(opts);
|
|
11171
11297
|
if (rootDir !== void 0) queryOpts.rootDir = rootDir;
|
|
11172
11298
|
const scanned = queryRefs(queryOpts);
|
|
@@ -11236,7 +11362,7 @@ function renderRefsTargets(targets, opts, {
|
|
|
11236
11362
|
const fullSourceBytes = refsSearchBaselineBytes(refRows);
|
|
11237
11363
|
if (opts.json === true) {
|
|
11238
11364
|
const text2 = displaySafeJson(jsonOut);
|
|
11239
|
-
|
|
11365
|
+
emit(text2);
|
|
11240
11366
|
if (anyFound) recordReadStat("symbol_read", fullSourceBytes, text2, opts.spec);
|
|
11241
11367
|
return anyFound ? 0 : 1;
|
|
11242
11368
|
}
|
|
@@ -11247,11 +11373,11 @@ function renderRefsTargets(targets, opts, {
|
|
|
11247
11373
|
}
|
|
11248
11374
|
function runRefs(opts) {
|
|
11249
11375
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
11250
|
-
|
|
11376
|
+
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
11251
11377
|
return 1;
|
|
11252
11378
|
}
|
|
11253
11379
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
11254
|
-
|
|
11380
|
+
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
11255
11381
|
return 1;
|
|
11256
11382
|
}
|
|
11257
11383
|
const baseConfined = confinedProjectRoot();
|
|
@@ -11260,13 +11386,13 @@ function runRefs(opts) {
|
|
|
11260
11386
|
const requested = opts.projectRoot;
|
|
11261
11387
|
const projectDenial = requested === void 0 || confinedRoot !== baseConfined ? null : confinementRefusal("--project", requested, baseConfined);
|
|
11262
11388
|
if (projectDenial !== null) {
|
|
11263
|
-
|
|
11389
|
+
emitErr(projectDenial);
|
|
11264
11390
|
return 1;
|
|
11265
11391
|
}
|
|
11266
11392
|
for (const file2 of refsSpecFiles(opts.spec)) {
|
|
11267
11393
|
const denial = confinementRefusal("This file", resolveIndexPath(file2, opts.projectRoot ?? process.cwd()), confinedRoot);
|
|
11268
11394
|
if (denial !== null) {
|
|
11269
|
-
|
|
11395
|
+
emitErr(denial);
|
|
11270
11396
|
return 1;
|
|
11271
11397
|
}
|
|
11272
11398
|
}
|
|
@@ -11297,9 +11423,9 @@ function runRefsSingle(opts) {
|
|
|
11297
11423
|
const symName = symbol ?? file;
|
|
11298
11424
|
const queryOpts = { name: symName };
|
|
11299
11425
|
const defFileHint = symbol !== void 0 ? resolveIndexPath(file, opts.projectRoot ?? process.cwd()) : void 0;
|
|
11300
|
-
if (opts.excludeTests === true || opts.grep !== void 0) queryOpts.limit =
|
|
11426
|
+
if (opts.excludeTests === true || opts.grep !== void 0) queryOpts.limit = UNBOUNDED_QUERY_LIMIT;
|
|
11301
11427
|
else if (opts.limit !== void 0) queryOpts.limit = opts.limit;
|
|
11302
|
-
else if (opts.top !== void 0) queryOpts.limit =
|
|
11428
|
+
else if (opts.top !== void 0) queryOpts.limit = UNBOUNDED_QUERY_LIMIT;
|
|
11303
11429
|
const rootDir = refsRootDir(opts);
|
|
11304
11430
|
if (rootDir !== void 0) queryOpts.rootDir = rootDir;
|
|
11305
11431
|
const scanned = queryRefs(queryOpts);
|
|
@@ -11325,39 +11451,39 @@ function runRefsSingle(opts) {
|
|
|
11325
11451
|
if (results.length === 0) {
|
|
11326
11452
|
if (matchesGrep !== void 0 && preGrepCount > 0) {
|
|
11327
11453
|
if (opts.json === true) {
|
|
11328
|
-
|
|
11454
|
+
emit(displaySafeJson({ items: [], truncated: false, totalCount: 0, hiddenByGrep: preGrepCount }));
|
|
11329
11455
|
return 0;
|
|
11330
11456
|
}
|
|
11331
|
-
|
|
11457
|
+
emit(grepFilteredToEmptyNotice(preGrepCount, opts.grep ?? "", "reference", "references"));
|
|
11332
11458
|
return 0;
|
|
11333
11459
|
}
|
|
11334
11460
|
if (opts.excludeTests === true && suppressed > 0) {
|
|
11335
|
-
|
|
11461
|
+
emitErr(`No non-test references found for '${symName}' (${excludeTestsHiddenNote(suppressed)})`);
|
|
11336
11462
|
return 1;
|
|
11337
11463
|
}
|
|
11338
11464
|
const rootDir2 = opts.projectRoot ?? resolveProjectRoot({ project: process.cwd() });
|
|
11339
11465
|
const defRows = querySymbols({ name: symName, rootDir: rootDir2, limit: REF_BLIND_DEF_PROBE_LIMIT });
|
|
11340
11466
|
if (defRows.length === 0) {
|
|
11341
|
-
|
|
11342
|
-
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));
|
|
11343
11469
|
return 1;
|
|
11344
11470
|
}
|
|
11345
11471
|
const defPaths = defFileHint !== void 0 ? [defFileHint] : defRows.map((r) => r.filePath);
|
|
11346
11472
|
const firstDefPath = defPaths[0];
|
|
11347
11473
|
if (firstDefPath !== void 0 && defPaths.every((fp) => !isRefIndexedFile(fp))) {
|
|
11348
|
-
|
|
11474
|
+
emitErr(refBlindLanguageNotice(symName, detectLanguageOfFile(firstDefPath), refsDisplayPath(firstDefPath)));
|
|
11349
11475
|
return 1;
|
|
11350
11476
|
}
|
|
11351
11477
|
const kindRows = defFileHint !== void 0 ? querySymbols({ name: symName, filePath: defFileHint, rootDir: rootDir2, limit: REF_BLIND_DEF_PROBE_LIMIT }) : defRows;
|
|
11352
11478
|
const kindVerdict = refBlindKindVerdict(kindRows);
|
|
11353
11479
|
if (kindVerdict.allBlind) {
|
|
11354
|
-
|
|
11480
|
+
emitErr(refBlindKindNotice(symName, kindVerdict.blindKinds));
|
|
11355
11481
|
return 1;
|
|
11356
11482
|
}
|
|
11357
|
-
|
|
11358
|
-
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));
|
|
11359
11485
|
if (opts.json !== true) {
|
|
11360
|
-
if (isIndexEmptyForProject(globalDbPath(), rootDir2))
|
|
11486
|
+
if (isIndexEmptyForProject(globalDbPath(), rootDir2)) emitErr(emptyIndexMessage(rootDir2));
|
|
11361
11487
|
}
|
|
11362
11488
|
return 1;
|
|
11363
11489
|
}
|
|
@@ -11374,14 +11500,14 @@ function runRefsSingle(opts) {
|
|
|
11374
11500
|
}
|
|
11375
11501
|
const hiddenByGrep = matchesGrep !== void 0 ? preGrepCount - (filteredTotal ?? results.length) : 0;
|
|
11376
11502
|
const text2 = displaySafeJson({ ...payload, ...hiddenByGrep > 0 ? { hiddenByGrep } : {} });
|
|
11377
|
-
|
|
11503
|
+
emit(text2);
|
|
11378
11504
|
recordReadStat("symbol_read", fullSourceBytes, text2, symName);
|
|
11379
11505
|
return 0;
|
|
11380
11506
|
}
|
|
11381
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, ""))];
|
|
11382
11508
|
const refsFooter = opts.top !== void 0 ? "" : truncationFooter(results.length, opts.limit ?? 100, () => refsTotal(clientFiltered, filteredTotal, results.length, () => countRefs(queryOpts), preScanCount, scanLimit), "references", "--limit");
|
|
11383
11509
|
const text = lines.join("\n");
|
|
11384
|
-
|
|
11510
|
+
emit(guardText(text, "symbol") + refsFooter);
|
|
11385
11511
|
recordReadStat("symbol_read", fullSourceBytes, text + refsFooter, symName);
|
|
11386
11512
|
return 0;
|
|
11387
11513
|
}
|
|
@@ -11437,11 +11563,11 @@ function renderCallerGroups(refs, contextLines = 0) {
|
|
|
11437
11563
|
function runPrSlice(opts) {
|
|
11438
11564
|
const parsed = parsePrSliceArg(opts.slice);
|
|
11439
11565
|
if (parsed === null) {
|
|
11440
|
-
|
|
11566
|
+
emitErr(`Invalid slice '${opts.slice}' -- expected one of: files, diff:<path>, comments, description`);
|
|
11441
11567
|
return 1;
|
|
11442
11568
|
}
|
|
11443
11569
|
if (!isGhAvailable()) {
|
|
11444
|
-
|
|
11570
|
+
emitErr("gh (GitHub CLI) not found on PATH -- install it from https://cli.github.com and run `gh auth login`");
|
|
11445
11571
|
return 1;
|
|
11446
11572
|
}
|
|
11447
11573
|
let repo = opts.repo;
|
|
@@ -11455,21 +11581,21 @@ function runPrSlice(opts) {
|
|
|
11455
11581
|
}
|
|
11456
11582
|
const resolved = remoteUrl.length > 0 ? parseGithubRepoFromRemoteUrl(remoteUrl) : null;
|
|
11457
11583
|
if (resolved === null) {
|
|
11458
|
-
|
|
11584
|
+
emitErr("Could not resolve a GitHub repo from the current directory's git remote 'origin' -- pass --repo owner/repo");
|
|
11459
11585
|
return 1;
|
|
11460
11586
|
}
|
|
11461
11587
|
repo = resolved;
|
|
11462
11588
|
}
|
|
11463
11589
|
if (!isSafeRepoSlug(repo)) {
|
|
11464
|
-
|
|
11590
|
+
emitErr(`"${repo}" is not a plain owner/name repository slug -- pass --repo owner/repo`);
|
|
11465
11591
|
return 1;
|
|
11466
11592
|
}
|
|
11467
11593
|
if (!isSafePrNumber(opts.pr)) {
|
|
11468
|
-
|
|
11594
|
+
emitErr(`"${opts.pr}" is not a pull request number`);
|
|
11469
11595
|
return 1;
|
|
11470
11596
|
}
|
|
11471
11597
|
if (!isGhAuthenticated()) {
|
|
11472
|
-
|
|
11598
|
+
emitErr("gh is not authenticated -- run `gh auth login`");
|
|
11473
11599
|
return 1;
|
|
11474
11600
|
}
|
|
11475
11601
|
try {
|
|
@@ -11480,7 +11606,7 @@ function runPrSlice(opts) {
|
|
|
11480
11606
|
if (opts.json === true) {
|
|
11481
11607
|
const capped = guardJsonRows(files);
|
|
11482
11608
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount }, 0);
|
|
11483
|
-
|
|
11609
|
+
emit(jsonText);
|
|
11484
11610
|
recordReadStat("pr_slice", fullSourceBytes, jsonText, `${repo}#${opts.pr} files`);
|
|
11485
11611
|
} else {
|
|
11486
11612
|
const text = formatFilesSlice(files);
|
|
@@ -11493,14 +11619,14 @@ function runPrSlice(opts) {
|
|
|
11493
11619
|
const diffText = fetchPrDiff(opts.pr, repo);
|
|
11494
11620
|
const rawFileDiff = extractFileDiff(diffText, parsed.path);
|
|
11495
11621
|
if (rawFileDiff === null) {
|
|
11496
|
-
|
|
11622
|
+
emitErr(`No diff found for '${parsed.path}' in PR #${opts.pr}`);
|
|
11497
11623
|
return 1;
|
|
11498
11624
|
}
|
|
11499
11625
|
const fileDiff = redactSecrets(rawFileDiff).text;
|
|
11500
11626
|
const fullSourceBytes = Buffer.byteLength(diffText, "utf8");
|
|
11501
11627
|
if (opts.json === true) {
|
|
11502
11628
|
const jsonText = displaySafeJson({ path: parsed.path, diff: fenceGithubFieldIfMatched(fileDiff) }, 0);
|
|
11503
|
-
|
|
11629
|
+
emit(jsonText);
|
|
11504
11630
|
recordReadStat("pr_slice", fullSourceBytes, jsonText, `${repo}#${opts.pr} diff:${parsed.path}`);
|
|
11505
11631
|
} else {
|
|
11506
11632
|
emitGuarded(fenceGithubText(fileDiff), "pr-slice");
|
|
@@ -11520,7 +11646,7 @@ function runPrSlice(opts) {
|
|
|
11520
11646
|
const fencedComments = comments.map((c) => ({ ...c, body: fenceGithubFieldIfMatched(c.body) }));
|
|
11521
11647
|
const capped = guardJsonRows(fencedComments);
|
|
11522
11648
|
const jsonText = displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount }, 0);
|
|
11523
|
-
|
|
11649
|
+
emit(jsonText);
|
|
11524
11650
|
recordReadStat("pr_slice", fullSourceBytes, jsonText, `${repo}#${opts.pr} comments`);
|
|
11525
11651
|
} else {
|
|
11526
11652
|
const text = formatCommentsSlice(comments);
|
|
@@ -11544,7 +11670,7 @@ function runPrSlice(opts) {
|
|
|
11544
11670
|
body: desc.body !== null ? fenceGithubFieldIfMatched(desc.body) : null
|
|
11545
11671
|
};
|
|
11546
11672
|
const jsonText = displaySafeJson(fencedDesc, 0);
|
|
11547
|
-
|
|
11673
|
+
emit(jsonText);
|
|
11548
11674
|
recordReadStat("pr_slice", fullSourceBytes, jsonText, `${repo}#${opts.pr} description`);
|
|
11549
11675
|
} else {
|
|
11550
11676
|
const text = formatDescriptionSlice(desc);
|
|
@@ -11555,7 +11681,7 @@ function runPrSlice(opts) {
|
|
|
11555
11681
|
}
|
|
11556
11682
|
}
|
|
11557
11683
|
} catch (e) {
|
|
11558
|
-
|
|
11684
|
+
emitErr(extractErrorMessage(e));
|
|
11559
11685
|
return 1;
|
|
11560
11686
|
}
|
|
11561
11687
|
}
|
|
@@ -11654,7 +11780,7 @@ function runGrep(opts) {
|
|
|
11654
11780
|
const contextLines = opts.context ?? 0;
|
|
11655
11781
|
const guarded = compileGuardedRegex(opts.pattern);
|
|
11656
11782
|
if (!guarded.ok) {
|
|
11657
|
-
|
|
11783
|
+
emitErr(`Invalid regex: ${opts.pattern} -- ${guarded.reason}`);
|
|
11658
11784
|
return 1;
|
|
11659
11785
|
}
|
|
11660
11786
|
const regex = guarded.re;
|
|
@@ -11740,7 +11866,7 @@ function runGrep(opts) {
|
|
|
11740
11866
|
}
|
|
11741
11867
|
for (const searchPath of searchPaths) {
|
|
11742
11868
|
if (!fileExists2(searchPath)) {
|
|
11743
|
-
|
|
11869
|
+
emitErr(`Path not found: ${searchPath}`);
|
|
11744
11870
|
return 1;
|
|
11745
11871
|
}
|
|
11746
11872
|
const stat = fs12.statSync(searchPath);
|
|
@@ -11767,7 +11893,7 @@ function runGrep(opts) {
|
|
|
11767
11893
|
}
|
|
11768
11894
|
}
|
|
11769
11895
|
if (hits.length === 0) {
|
|
11770
|
-
|
|
11896
|
+
emitErr(`No matches for '${opts.pattern}'`);
|
|
11771
11897
|
return 1;
|
|
11772
11898
|
}
|
|
11773
11899
|
const truncated = hits.slice(0, maxLines);
|
|
@@ -11783,32 +11909,44 @@ function runGrep(opts) {
|
|
|
11783
11909
|
hit.symbol = enc === null ? null : { name: enc.name, kind: enc.kind, lineStart: enc.lineStart, lineEnd: enc.lineEnd };
|
|
11784
11910
|
}
|
|
11785
11911
|
for (const file of new Set(truncated.map((h) => h.file).filter(isVirtualIndexedPath))) {
|
|
11786
|
-
|
|
11912
|
+
emit(virtualIndexedScopeNote(displaySafeText(file), "a match in it cannot be attributed to a symbol and these hits carry no label"));
|
|
11787
11913
|
}
|
|
11788
11914
|
}
|
|
11789
11915
|
if (opts.json === true) {
|
|
11790
11916
|
const payload = { items: truncated, truncated: hits.length > maxLines, totalCount: hits.length };
|
|
11791
|
-
|
|
11917
|
+
emit(displaySafeJson(payload));
|
|
11792
11918
|
return 0;
|
|
11793
11919
|
}
|
|
11794
11920
|
for (const hit of truncated) {
|
|
11795
11921
|
const symbolTag = opts.symbol === true && hit.symbol != null ? ` [${hit.symbol.name} (${hit.symbol.kind})]` : "";
|
|
11796
11922
|
if (hit.context !== void 0) {
|
|
11797
|
-
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);
|
|
11798
11924
|
} else {
|
|
11799
|
-
|
|
11925
|
+
emit(`${displaySafeText(hit.file)}:${hit.line}: ${hit.text}${symbolTag}`);
|
|
11800
11926
|
}
|
|
11801
11927
|
}
|
|
11802
11928
|
if (hits.length > maxLines) {
|
|
11803
|
-
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
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>`);
|
|
11808
11934
|
}
|
|
11809
11935
|
return 0;
|
|
11810
11936
|
}
|
|
11811
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
|
+
}
|
|
11812
11950
|
async function runSemantic(query, opts) {
|
|
11813
11951
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
11814
11952
|
const message = `--limit must be a positive number, got: ${opts.limit}`;
|
|
@@ -11897,7 +12035,19 @@ async function runSemantic(query, opts) {
|
|
|
11897
12035
|
}
|
|
11898
12036
|
}
|
|
11899
12037
|
}
|
|
11900
|
-
|
|
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) {
|
|
11901
12051
|
try {
|
|
11902
12052
|
const enabled = loadConfig().indexing.embeddings_enabled;
|
|
11903
12053
|
const { indexedFiles, embeddedFiles } = enabled ? getEmbeddingCoverage(globalDbPath(), rootDir) : { indexedFiles: 0, embeddedFiles: 0 };
|
|
@@ -11925,7 +12075,9 @@ async function runSemantic(query, opts) {
|
|
|
11925
12075
|
kind: enclosing?.kind ?? null,
|
|
11926
12076
|
distance: h.distance,
|
|
11927
12077
|
previewText: h.text,
|
|
11928
|
-
rrf: 1 / (RRF_K + denseRank)
|
|
12078
|
+
rrf: 1 / (RRF_K + denseRank),
|
|
12079
|
+
inDense: true,
|
|
12080
|
+
inLexical: false
|
|
11929
12081
|
});
|
|
11930
12082
|
});
|
|
11931
12083
|
ftsRows.forEach((s, ftsRank) => {
|
|
@@ -11933,6 +12085,7 @@ async function runSemantic(query, opts) {
|
|
|
11933
12085
|
const existing = fused.get(key);
|
|
11934
12086
|
if (existing !== void 0) {
|
|
11935
12087
|
existing.rrf += 1 / (RRF_K + ftsRank);
|
|
12088
|
+
existing.inLexical = true;
|
|
11936
12089
|
} else {
|
|
11937
12090
|
fused.set(key, {
|
|
11938
12091
|
filePath: s.filePath,
|
|
@@ -11942,7 +12095,9 @@ async function runSemantic(query, opts) {
|
|
|
11942
12095
|
kind: s.kind,
|
|
11943
12096
|
distance: null,
|
|
11944
12097
|
previewText: s.body,
|
|
11945
|
-
rrf: 1 / (RRF_K + ftsRank)
|
|
12098
|
+
rrf: 1 / (RRF_K + ftsRank),
|
|
12099
|
+
inDense: false,
|
|
12100
|
+
inLexical: true
|
|
11946
12101
|
});
|
|
11947
12102
|
}
|
|
11948
12103
|
});
|
|
@@ -11965,12 +12120,15 @@ async function runSemantic(query, opts) {
|
|
|
11965
12120
|
warnIfFilesStale(hits.map((h) => h.filePath));
|
|
11966
12121
|
if (hits.length > 0) {
|
|
11967
12122
|
if (opts.json === true) {
|
|
11968
|
-
const items = hits.map((h) => ({
|
|
12123
|
+
const items = hits.map((h, i) => ({
|
|
11969
12124
|
filePath: toDisplayPath(rootDir, h.filePath),
|
|
11970
12125
|
name: h.name,
|
|
11971
12126
|
kind: h.kind,
|
|
11972
12127
|
startLine: h.startLine,
|
|
11973
12128
|
endLine: h.endLine,
|
|
12129
|
+
rank: i + 1,
|
|
12130
|
+
rrf: h.rrf,
|
|
12131
|
+
retrieval: h.inDense && h.inLexical ? "both" : h.inDense ? "dense" : "lexical",
|
|
11974
12132
|
distance: h.distance,
|
|
11975
12133
|
preview: previewLines(h.previewText, 3)
|
|
11976
12134
|
}));
|
|
@@ -11994,18 +12152,19 @@ async function runSemantic(query, opts) {
|
|
|
11994
12152
|
recordReadStat("semantic_search", sumFileSizes(hits.map((h) => h.filePath)), text3, query);
|
|
11995
12153
|
return { text: text3, code: 0 };
|
|
11996
12154
|
}
|
|
11997
|
-
const blocks = hits.map((h) => {
|
|
12155
|
+
const blocks = hits.map((h, i) => {
|
|
12156
|
+
const mark = h.inDense && h.inLexical ? ", +keyword" : "";
|
|
11998
12157
|
if (h.distance !== null) {
|
|
11999
12158
|
const suffix = h.name !== null ? ` \u2014 inside ${h.name} (${h.kind})` : "";
|
|
12000
|
-
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}
|
|
12001
12160
|
${previewLines(h.previewText, 3)}`;
|
|
12002
12161
|
}
|
|
12003
|
-
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)
|
|
12004
12163
|
${previewLines(h.previewText, 3)}`;
|
|
12005
12164
|
});
|
|
12006
12165
|
const text2 = guardText(blocks.join("\n\n"), "semantic");
|
|
12007
12166
|
if (hits.length < eligibleCount) {
|
|
12008
|
-
|
|
12167
|
+
emitErr(`Showing ${hits.length} of ${candidatesClipped ? "at least " : ""}${countNoun(eligibleCount, "match", "matches")} (raise --limit to see the rest).`);
|
|
12009
12168
|
}
|
|
12010
12169
|
recordReadStat("semantic_search", sumFileSizes(hits.map((h) => h.filePath)), text2, query);
|
|
12011
12170
|
return { text: text2, code: 0 };
|
|
@@ -12105,7 +12264,7 @@ function fileExists3(p) {
|
|
|
12105
12264
|
return false;
|
|
12106
12265
|
}
|
|
12107
12266
|
}
|
|
12108
|
-
var
|
|
12267
|
+
var FIND_SCAN_LIMIT2 = FIND_SCAN_LIMIT;
|
|
12109
12268
|
var PARENT_IDENTIFIER_RE2 = /^[\w$]+$/;
|
|
12110
12269
|
function parseReadSpec(spec) {
|
|
12111
12270
|
const colonIdx = findSpecSeparator(spec);
|
|
@@ -12142,7 +12301,7 @@ function parseMultiFileSpec(spec) {
|
|
|
12142
12301
|
function extraFileArgsNote(command, first, extras, opts = {}) {
|
|
12143
12302
|
const noun = opts.noun ?? "file";
|
|
12144
12303
|
const head = `Note: ${extras.length} extra ${noun} argument(s) ignored (${extras.join(", ")}).`;
|
|
12145
|
-
if (opts.mergeable === false) return `${head} ${command}
|
|
12304
|
+
if (opts.mergeable === false) return `${head} Run ${command} once per ${noun}.`;
|
|
12146
12305
|
return `${head} ${command} reads one ${noun}, or a comma-separated list: token-goat ${command} "${[first, ...extras].join(",")}"`;
|
|
12147
12306
|
}
|
|
12148
12307
|
function parseLineRange(spec) {
|
|
@@ -12154,6 +12313,22 @@ function parseLineRange(spec) {
|
|
|
12154
12313
|
const end = m[3] !== void 0 ? parseInt(m[3], 10) : start;
|
|
12155
12314
|
return { file: m[1], start, end };
|
|
12156
12315
|
}
|
|
12316
|
+
function parseColonLineSpec(spec) {
|
|
12317
|
+
const colonIdx = spec.lastIndexOf(":");
|
|
12318
|
+
if (colonIdx <= 0) return null;
|
|
12319
|
+
const suffix = spec.slice(colonIdx + 1);
|
|
12320
|
+
if (!/^\d+(?:-\d+)?$/.test(suffix)) return null;
|
|
12321
|
+
const file = spec.slice(0, colonIdx);
|
|
12322
|
+
if (file === "") return null;
|
|
12323
|
+
if (/^[A-Za-z]$/.test(file)) return null;
|
|
12324
|
+
const pastDrive = /^[A-Za-z]:/.test(file) ? file.slice(2) : file;
|
|
12325
|
+
if (pastDrive === "" || pastDrive.includes(":")) return null;
|
|
12326
|
+
if (fileExists3(spec)) return null;
|
|
12327
|
+
const dash = suffix.indexOf("-");
|
|
12328
|
+
const start = parseInt(dash === -1 ? suffix : suffix.slice(0, dash), 10);
|
|
12329
|
+
const end = dash === -1 ? start : parseInt(suffix.slice(dash + 1), 10);
|
|
12330
|
+
return { file, start, end };
|
|
12331
|
+
}
|
|
12157
12332
|
function parseColonLineRange(symbol) {
|
|
12158
12333
|
const m = /^(\d+)(?:[-:,](\d+))?$/.exec(symbol);
|
|
12159
12334
|
if (m === null) return null;
|
|
@@ -12161,6 +12336,19 @@ function parseColonLineRange(symbol) {
|
|
|
12161
12336
|
const end = m[2] !== void 0 ? parseInt(m[2], 10) : start;
|
|
12162
12337
|
return { start, end };
|
|
12163
12338
|
}
|
|
12339
|
+
function readSpecsMergeable(specs) {
|
|
12340
|
+
if (specs.length < 2) return true;
|
|
12341
|
+
const joined = specs.join(",");
|
|
12342
|
+
if (parseLineRange(joined) !== null) return false;
|
|
12343
|
+
if (parseColonLineSpec(joined) !== null) return false;
|
|
12344
|
+
if (parseCrossFileMultiSpec(joined) !== null) return true;
|
|
12345
|
+
const { symbol } = parseReadSpec(joined);
|
|
12346
|
+
return symbol !== void 0 && symbol !== "" && symbol.includes(",") && parseColonLineRange(symbol) === null;
|
|
12347
|
+
}
|
|
12348
|
+
function namedSpecsMergeable(specs) {
|
|
12349
|
+
if (specs.length < 2) return true;
|
|
12350
|
+
return specs.every((spec) => spec.includes("::"));
|
|
12351
|
+
}
|
|
12164
12352
|
function runLineRange(range, opts) {
|
|
12165
12353
|
const { file, start, end } = range;
|
|
12166
12354
|
const diskPath = resolveAgainstProjectRoot(file, opts.projectRoot);
|
|
@@ -12193,6 +12381,64 @@ function runLineRange(range, opts) {
|
|
|
12193
12381
|
code: 0
|
|
12194
12382
|
};
|
|
12195
12383
|
}
|
|
12384
|
+
function runLineRegion(range, opts) {
|
|
12385
|
+
const { file, start, end } = range;
|
|
12386
|
+
if (start < 1) return { text: `Invalid line range: start must be >= 1 (got ${start})`, code: 1 };
|
|
12387
|
+
if (end < start) return { text: `Invalid line range: end (${end}) is before start (${start})`, code: 1 };
|
|
12388
|
+
const resolved = resolveIndexPath(file, opts.projectRoot ?? process.cwd());
|
|
12389
|
+
const confined = confinementRefusal("This file", resolved, confinedProjectRoot(opts.projectRoot));
|
|
12390
|
+
if (confined !== null) return { text: confined, code: 1 };
|
|
12391
|
+
const text = readFileText(resolveAgainstProjectRoot(file, opts.projectRoot));
|
|
12392
|
+
if (text === null) return { text: `Could not read: ${file}`, code: 1 };
|
|
12393
|
+
const allLines = text.split(/\r?\n/);
|
|
12394
|
+
if (allLines.length > 1 && allLines[allLines.length - 1] === "") allLines.pop();
|
|
12395
|
+
if (start > allLines.length) {
|
|
12396
|
+
return { text: `Line ${start} is past end of file (${countNoun(allLines.length, "line")}): ${file}`, code: 1 };
|
|
12397
|
+
}
|
|
12398
|
+
if (opts.forceRefresh === true) {
|
|
12399
|
+
indexFileSyncPinned(resolved, globalDbPath());
|
|
12400
|
+
enqueueDirtyPathSafe(resolved, { alreadyResolved: true });
|
|
12401
|
+
} else {
|
|
12402
|
+
healStaleIndex(resolved);
|
|
12403
|
+
}
|
|
12404
|
+
const symbols = querySymbols({ filePath: resolved, limit: FIND_SCAN_LIMIT2 });
|
|
12405
|
+
const regions = resolveLineRegions(symbols, allLines.length, start, end);
|
|
12406
|
+
const asked = start === end ? `${start}` : `${start}-${end}`;
|
|
12407
|
+
if (regions.length === 0) {
|
|
12408
|
+
return {
|
|
12409
|
+
text: `No indexed symbols in '${file}', so line ${asked} cannot be resolved to a region.
|
|
12410
|
+
Read the raw lines instead: token-goat read "${file}@${asked}"`,
|
|
12411
|
+
code: 1
|
|
12412
|
+
};
|
|
12413
|
+
}
|
|
12414
|
+
const slice = (r) => allLines.slice(r.start - 1, Math.min(r.end, allLines.length)).join("\n");
|
|
12415
|
+
if (opts.json === true) {
|
|
12416
|
+
return {
|
|
12417
|
+
text: displaySafeJson({
|
|
12418
|
+
file,
|
|
12419
|
+
requested: { start, end },
|
|
12420
|
+
regions: regions.map((r) => ({
|
|
12421
|
+
kind: r.kind,
|
|
12422
|
+
label: r.label,
|
|
12423
|
+
start: r.start,
|
|
12424
|
+
end: Math.min(r.end, allLines.length),
|
|
12425
|
+
lines: allLines.slice(r.start - 1, Math.min(r.end, allLines.length))
|
|
12426
|
+
}))
|
|
12427
|
+
}),
|
|
12428
|
+
code: 0
|
|
12429
|
+
};
|
|
12430
|
+
}
|
|
12431
|
+
const blocks = [];
|
|
12432
|
+
if (regions.length > 1) blocks.push(`# ${file}:${asked} -> ${countNoun(regions.length, "region")}`);
|
|
12433
|
+
regions.forEach((r, i) => {
|
|
12434
|
+
const body = slice(r);
|
|
12435
|
+
const tag = regions.length > 1 ? `[${i + 1}/${regions.length}] ` : `${file}:${asked} -> `;
|
|
12436
|
+
const span = `lines ${r.start}-${Math.min(r.end, allLines.length)} of ${allLines.length}`;
|
|
12437
|
+
blocks.push(`# ${tag}${r.label} ${span} (~${Math.ceil(body.length / 4)} tok)
|
|
12438
|
+
${body}`);
|
|
12439
|
+
});
|
|
12440
|
+
return { text: guardText(staleWarning(resolved) + blocks.join("\n\n"), "lines"), code: 0 };
|
|
12441
|
+
}
|
|
12196
12442
|
function findParentName(entry, fileSymbols) {
|
|
12197
12443
|
let best = null;
|
|
12198
12444
|
for (const s of fileSymbols) {
|
|
@@ -12219,7 +12465,7 @@ function formatAmbiguity(symbol, file, candidates, explicitRoot, commandName = "
|
|
|
12219
12465
|
const getFileSyms = (filePath) => {
|
|
12220
12466
|
let fileSyms = fileSymCache.get(filePath);
|
|
12221
12467
|
if (fileSyms === void 0) {
|
|
12222
|
-
fileSyms = querySymbols({ filePath, limit:
|
|
12468
|
+
fileSyms = querySymbols({ filePath, limit: FIND_SCAN_LIMIT2 });
|
|
12223
12469
|
fileSymCache.set(filePath, fileSyms);
|
|
12224
12470
|
}
|
|
12225
12471
|
return fileSyms;
|
|
@@ -12267,13 +12513,17 @@ function fileConfinementRefusal(label, file, projectRoot) {
|
|
|
12267
12513
|
if (root === null) return null;
|
|
12268
12514
|
return confinementRefusal(label, resolveIndexPath(file, projectRoot ?? process.cwd()), root);
|
|
12269
12515
|
}
|
|
12516
|
+
function stripHtmlIdSpelling(name, filePath) {
|
|
12517
|
+
return name.startsWith("#") && detectLanguage(filePath) === "html" ? name.slice(1) : name;
|
|
12518
|
+
}
|
|
12270
12519
|
function resolveSymbolSpec(spec, forceRefresh, projectRoot) {
|
|
12271
12520
|
const { file, symbol: rawSymbol } = parseReadSpec(spec);
|
|
12272
12521
|
if (rawSymbol === void 0 || rawSymbol === "") return { kind: "none" };
|
|
12273
12522
|
const anchorMatch = /^(.+)@(\d+)$/.exec(rawSymbol);
|
|
12274
|
-
const
|
|
12523
|
+
const anchorSymbol = anchorMatch !== null ? anchorMatch[1] : rawSymbol;
|
|
12275
12524
|
const lineAnchor = anchorMatch !== null ? parseInt(anchorMatch[2], 10) : void 0;
|
|
12276
12525
|
const resolved = resolveIndexPath(file, projectRoot ?? process.cwd());
|
|
12526
|
+
const symbol = stripHtmlIdSpelling(anchorSymbol, resolved);
|
|
12277
12527
|
const confined = confinementRefusal("This file", resolved, confinedProjectRoot(projectRoot));
|
|
12278
12528
|
if (confined !== null) return { kind: "confined", message: confined };
|
|
12279
12529
|
if (forceRefresh === true) {
|
|
@@ -12343,16 +12593,16 @@ function resolveSymbolSpec(spec, forceRefresh, projectRoot) {
|
|
|
12343
12593
|
function resolveSymbolSpecOrEmitError(commandName, spec, projectRoot) {
|
|
12344
12594
|
const { file, symbol } = parseReadSpec(spec);
|
|
12345
12595
|
if (symbol === void 0 || symbol === "") {
|
|
12346
|
-
|
|
12596
|
+
emitErr(`'token-goat ${commandName}' requires a 'file::symbol' spec (got '${spec}')`);
|
|
12347
12597
|
return null;
|
|
12348
12598
|
}
|
|
12349
12599
|
const resolution = resolveSymbolSpec(spec, void 0, projectRoot);
|
|
12350
12600
|
if (resolution.kind === "confined") {
|
|
12351
|
-
|
|
12601
|
+
emitErr(resolution.message);
|
|
12352
12602
|
return null;
|
|
12353
12603
|
}
|
|
12354
12604
|
if (resolution.kind === "ambiguous") {
|
|
12355
|
-
|
|
12605
|
+
emitErr(
|
|
12356
12606
|
formatAmbiguity(
|
|
12357
12607
|
resolution.symbol,
|
|
12358
12608
|
resolution.file,
|
|
@@ -12368,11 +12618,11 @@ function resolveSymbolSpecOrEmitError(commandName, spec, projectRoot) {
|
|
|
12368
12618
|
const crossFileLead = formatCrossFileLead(commandName, symbol, file, projectRoot);
|
|
12369
12619
|
if (crossFileLead !== "") messages.push(crossFileLead);
|
|
12370
12620
|
const resolved = resolveIndexPath(file, projectRoot ?? process.cwd());
|
|
12371
|
-
const scanned = querySymbols({ filePath: resolved, limit:
|
|
12621
|
+
const scanned = querySymbols({ filePath: resolved, limit: FIND_SCAN_LIMIT2 }).map((s) => s.name);
|
|
12372
12622
|
const closes = rankSimilarNames(scanned, symbol);
|
|
12373
12623
|
if (closes.length > 0) messages.push(didYouMean(closes));
|
|
12374
12624
|
else if (scanned.length > 0) messages.push(`Try: token-goat outline ${file}`);
|
|
12375
|
-
|
|
12625
|
+
emitErr(messages.join("\n"));
|
|
12376
12626
|
return null;
|
|
12377
12627
|
}
|
|
12378
12628
|
return resolution.entry;
|
|
@@ -12387,13 +12637,13 @@ var CONTENT_MAX_ITEMS = 256;
|
|
|
12387
12637
|
var CONTENT_MAX_BYTES = 32 * 1024 * 1024;
|
|
12388
12638
|
var CONTENT_MAX_ITEM_BYTES = CONTENT_MAX_INPUT_CHARS * 7;
|
|
12389
12639
|
var CONTENT_SUBDIR = "content";
|
|
12390
|
-
var TEXT_BYTES_PER_TOKEN =
|
|
12391
|
-
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;
|
|
12392
12642
|
function estimateTextTokens(bytes) {
|
|
12393
|
-
return
|
|
12643
|
+
return savedTokensFromBytes(bytes, "text");
|
|
12394
12644
|
}
|
|
12395
12645
|
function estimateBase64urlTokens(bytes) {
|
|
12396
|
-
return
|
|
12646
|
+
return savedTokensFromBytes(bytes, "dense");
|
|
12397
12647
|
}
|
|
12398
12648
|
function assertInput(text) {
|
|
12399
12649
|
if (text.length > CONTENT_MAX_INPUT_CHARS) {
|
|
@@ -12504,6 +12754,8 @@ function resolveHandoff(name, opts = {}) {
|
|
|
12504
12754
|
export {
|
|
12505
12755
|
isAvailable2 as isAvailable,
|
|
12506
12756
|
loadError,
|
|
12757
|
+
emit,
|
|
12758
|
+
emitErr,
|
|
12507
12759
|
ALL_SYMBOLS_IN_FILE_LIMIT,
|
|
12508
12760
|
enclosingSymbol,
|
|
12509
12761
|
runDead,
|
|
@@ -12541,6 +12793,9 @@ export {
|
|
|
12541
12793
|
didYouMean,
|
|
12542
12794
|
extraFileArgsNote,
|
|
12543
12795
|
parseLineRange,
|
|
12796
|
+
parseColonLineSpec,
|
|
12797
|
+
readSpecsMergeable,
|
|
12798
|
+
namedSpecsMergeable,
|
|
12544
12799
|
runSkeleton,
|
|
12545
12800
|
runOutline,
|
|
12546
12801
|
runBrief,
|