token-goat 2.6.26 → 2.6.27
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 +9 -9
- package/dist/token-goat-hook.mjs +253 -54
- package/dist/token-goat.mjs +269 -59
- package/package.json +3 -3
package/dist/token-goat.mjs
CHANGED
|
@@ -3050,7 +3050,7 @@ var require_commander = __commonJS({
|
|
|
3050
3050
|
import { createRequire } from "node:module";
|
|
3051
3051
|
function resolveVersion() {
|
|
3052
3052
|
if (true) {
|
|
3053
|
-
return "2.6.
|
|
3053
|
+
return "2.6.27";
|
|
3054
3054
|
}
|
|
3055
3055
|
const require2 = createRequire(import.meta.url);
|
|
3056
3056
|
const pkg = require2("../package.json");
|
|
@@ -4720,6 +4720,12 @@ function grepFilteredToEmptyNotice(preFilterCount, grep, nounSingular, nounPlura
|
|
|
4720
4720
|
const verb = preFilterCount === 1 ? "was" : "were";
|
|
4721
4721
|
return ` (all ${preFilterCount} ${noun} ${verb} filtered out by --grep ${grep} -- widen or drop the filter to see them)`;
|
|
4722
4722
|
}
|
|
4723
|
+
function countNoun(count, singular, plural2 = `${singular}s`) {
|
|
4724
|
+
return `${count} ${count === 1 ? singular : plural2}`;
|
|
4725
|
+
}
|
|
4726
|
+
function excludeTestsHiddenNote(count) {
|
|
4727
|
+
return `${count} in test ${count === 1 ? "file" : "files"} hidden by --exclude-tests`;
|
|
4728
|
+
}
|
|
4723
4729
|
function escapeRegExp(s) {
|
|
4724
4730
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4725
4731
|
}
|
|
@@ -20677,6 +20683,33 @@ function dirtyQueuePathFor(dir) {
|
|
|
20677
20683
|
function drainHeartbeatPathFor(dir) {
|
|
20678
20684
|
return path17.join(dir, "queue", "drain-heartbeat");
|
|
20679
20685
|
}
|
|
20686
|
+
function writeDrainHeartbeat(dir, force = false) {
|
|
20687
|
+
const now = Date.now();
|
|
20688
|
+
if (!force && now - (heartbeatWriteTimes.get(dir) ?? 0) < WORKER_HEARTBEAT_REFRESH_MS) return;
|
|
20689
|
+
try {
|
|
20690
|
+
fs12.mkdirSync(path17.dirname(drainHeartbeatPathFor(dir)), { recursive: true });
|
|
20691
|
+
fs12.writeFileSync(drainHeartbeatPathFor(dir), `${process.pid}
|
|
20692
|
+
`);
|
|
20693
|
+
heartbeatWriteTimes.set(dir, now);
|
|
20694
|
+
} catch {
|
|
20695
|
+
}
|
|
20696
|
+
}
|
|
20697
|
+
function hasFreshWorkerHeartbeat(dir, pid) {
|
|
20698
|
+
try {
|
|
20699
|
+
const heartbeatPath = drainHeartbeatPathFor(dir);
|
|
20700
|
+
if (Date.now() - fs12.statSync(heartbeatPath).mtimeMs > WORKER_HEARTBEAT_STALE_MS) return false;
|
|
20701
|
+
return fs12.readFileSync(heartbeatPath, "utf8").trim() === String(pid);
|
|
20702
|
+
} catch {
|
|
20703
|
+
return false;
|
|
20704
|
+
}
|
|
20705
|
+
}
|
|
20706
|
+
function pidFileIsWithinStartupGrace(dir) {
|
|
20707
|
+
try {
|
|
20708
|
+
return Date.now() - fs12.statSync(workerPidPath(dir)).mtimeMs < WORKER_STARTUP_GRACE_MS;
|
|
20709
|
+
} catch {
|
|
20710
|
+
return false;
|
|
20711
|
+
}
|
|
20712
|
+
}
|
|
20680
20713
|
function parseDirtyQueueLines(raw) {
|
|
20681
20714
|
const seen = /* @__PURE__ */ new Set();
|
|
20682
20715
|
const out2 = [];
|
|
@@ -20864,6 +20897,7 @@ function processDirtyBatch(paths, index = makeIndexer(globalDbPath()), remove =
|
|
|
20864
20897
|
let indexed = 0;
|
|
20865
20898
|
for (const p of paths) {
|
|
20866
20899
|
if (!p) continue;
|
|
20900
|
+
writeDrainHeartbeat(dir);
|
|
20867
20901
|
if (isUnderBlockedRoot(p, blockedRoots)) continue;
|
|
20868
20902
|
if (!fs12.existsSync(p)) {
|
|
20869
20903
|
remove(p);
|
|
@@ -20991,11 +21025,7 @@ function drainOnce(dir, index, remove) {
|
|
|
20991
21025
|
}
|
|
20992
21026
|
}
|
|
20993
21027
|
for (const p of deferredRequeues) appendToDirtyQueue(dir, p);
|
|
20994
|
-
|
|
20995
|
-
fs12.mkdirSync(path17.dirname(drainHeartbeatPathFor(dir)), { recursive: true });
|
|
20996
|
-
fs12.writeFileSync(drainHeartbeatPathFor(dir), "");
|
|
20997
|
-
} catch {
|
|
20998
|
-
}
|
|
21028
|
+
writeDrainHeartbeat(dir, true);
|
|
20999
21029
|
return processed;
|
|
21000
21030
|
}
|
|
21001
21031
|
function pidAlive(pid) {
|
|
@@ -21018,7 +21048,7 @@ function readPidFile(dir) {
|
|
|
21018
21048
|
function isWorkerRunning(dir = dataDir()) {
|
|
21019
21049
|
const pid = readPidFile(dir);
|
|
21020
21050
|
if (pid === null) return false;
|
|
21021
|
-
return pidAlive(pid);
|
|
21051
|
+
return pidAlive(pid) && hasFreshWorkerHeartbeat(dir, pid);
|
|
21022
21052
|
}
|
|
21023
21053
|
function workerHealthCheckMarkerPath(dir) {
|
|
21024
21054
|
return path17.join(dir, "worker-healthcheck.marker");
|
|
@@ -21054,8 +21084,8 @@ function ensureWorkerAlive(dir = dataDir()) {
|
|
|
21054
21084
|
function stopWorker(dir = dataDir()) {
|
|
21055
21085
|
const pid = readPidFile(dir);
|
|
21056
21086
|
if (pid === null) return false;
|
|
21057
|
-
const
|
|
21058
|
-
if (
|
|
21087
|
+
const running = isWorkerRunning(dir);
|
|
21088
|
+
if (running) {
|
|
21059
21089
|
try {
|
|
21060
21090
|
process.kill(pid);
|
|
21061
21091
|
} catch {
|
|
@@ -21067,7 +21097,7 @@ function stopWorker(dir = dataDir()) {
|
|
|
21067
21097
|
} catch {
|
|
21068
21098
|
}
|
|
21069
21099
|
}
|
|
21070
|
-
return
|
|
21100
|
+
return running;
|
|
21071
21101
|
}
|
|
21072
21102
|
function claimWorkerPidFile(dir, pid) {
|
|
21073
21103
|
const pidPath = workerPidPath(dir);
|
|
@@ -21079,7 +21109,7 @@ function claimWorkerPidFile(dir, pid) {
|
|
|
21079
21109
|
if (e.code !== "EEXIST") throw e;
|
|
21080
21110
|
}
|
|
21081
21111
|
const existingPid = readPidFile(dir);
|
|
21082
|
-
if (existingPid !== null && pidAlive(existingPid)) {
|
|
21112
|
+
if (existingPid !== null && pidAlive(existingPid) && (hasFreshWorkerHeartbeat(dir, existingPid) || pidFileIsWithinStartupGrace(dir))) {
|
|
21083
21113
|
return false;
|
|
21084
21114
|
}
|
|
21085
21115
|
try {
|
|
@@ -21183,9 +21213,10 @@ function runDetachedWorkerDaemon() {
|
|
|
21183
21213
|
}
|
|
21184
21214
|
}
|
|
21185
21215
|
});
|
|
21216
|
+
writeDrainHeartbeat(dir, true);
|
|
21186
21217
|
void runWorkerLoop(dir, safeInterval);
|
|
21187
21218
|
}
|
|
21188
|
-
var DEFAULT_POLL_INTERVAL_MS, SNAPSHOT_CLEANUP_INTERVAL_MS, PRUNE_EVERY_N_DRAINS, drainCycleCounts, lastKnownProjectRoots, unclearedDrainingSnapshots, MAX_TRANSIENT_RETRIES, WORKER_ERROR_LOG_MAX_BYTES, CORRUPT_QUARANTINE_MAX_AGE_MS, INDEX_FAILED, inFlightEmbeddings, activeEmbedSlots, embedSlotWaiters, WORKER_HEALTHCHECK_MIN_INTERVAL_MS, WorkerAlreadyRunningError, KNOWN_ROOTS_SWEEP_INTERVAL_MS;
|
|
21219
|
+
var DEFAULT_POLL_INTERVAL_MS, WORKER_HEARTBEAT_STALE_MS, WORKER_HEARTBEAT_REFRESH_MS, WORKER_STARTUP_GRACE_MS, SNAPSHOT_CLEANUP_INTERVAL_MS, PRUNE_EVERY_N_DRAINS, drainCycleCounts, heartbeatWriteTimes, lastKnownProjectRoots, unclearedDrainingSnapshots, MAX_TRANSIENT_RETRIES, WORKER_ERROR_LOG_MAX_BYTES, CORRUPT_QUARANTINE_MAX_AGE_MS, INDEX_FAILED, inFlightEmbeddings, activeEmbedSlots, embedSlotWaiters, WORKER_HEALTHCHECK_MIN_INTERVAL_MS, WorkerAlreadyRunningError, KNOWN_ROOTS_SWEEP_INTERVAL_MS;
|
|
21189
21220
|
var init_worker = __esm({
|
|
21190
21221
|
"src/worker.ts"() {
|
|
21191
21222
|
"use strict";
|
|
@@ -21205,9 +21236,13 @@ var init_worker = __esm({
|
|
|
21205
21236
|
init_project();
|
|
21206
21237
|
init_reset();
|
|
21207
21238
|
DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
21239
|
+
WORKER_HEARTBEAT_STALE_MS = 6e4;
|
|
21240
|
+
WORKER_HEARTBEAT_REFRESH_MS = 5e3;
|
|
21241
|
+
WORKER_STARTUP_GRACE_MS = 1e4;
|
|
21208
21242
|
SNAPSHOT_CLEANUP_INTERVAL_MS = 60 * 60 * 1e3;
|
|
21209
21243
|
PRUNE_EVERY_N_DRAINS = 30;
|
|
21210
21244
|
drainCycleCounts = /* @__PURE__ */ new Map();
|
|
21245
|
+
heartbeatWriteTimes = /* @__PURE__ */ new Map();
|
|
21211
21246
|
lastKnownProjectRoots = /* @__PURE__ */ new Map();
|
|
21212
21247
|
unclearedDrainingSnapshots = /* @__PURE__ */ new Map();
|
|
21213
21248
|
MAX_TRANSIENT_RETRIES = 5;
|
|
@@ -23722,6 +23757,12 @@ function didYouMean(candidates) {
|
|
|
23722
23757
|
}
|
|
23723
23758
|
return lines2.join("\n");
|
|
23724
23759
|
}
|
|
23760
|
+
function unknownSymbolSuggestion(name2, rootDir) {
|
|
23761
|
+
const rawSymbols = querySymbols({ limit: FIND_SCAN_LIMIT, rootDir });
|
|
23762
|
+
const candidates = rankSimilarNames(rawSymbols.map((s) => s.name), name2);
|
|
23763
|
+
return candidates.length > 0 ? `
|
|
23764
|
+
${didYouMean(candidates)}` : "";
|
|
23765
|
+
}
|
|
23725
23766
|
function formatBareNameSpecError(command, name2, projectRoot) {
|
|
23726
23767
|
const rootDir = projectRoot ?? resolveProjectRoot({ project: process.cwd() });
|
|
23727
23768
|
const matches2 = querySymbols({ name: name2, limit: 50, rootDir });
|
|
@@ -23795,6 +23836,17 @@ function runSymbol(opts) {
|
|
|
23795
23836
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
23796
23837
|
return { text: `--limit must be a positive number, got: ${opts.limit}`, code: 1 };
|
|
23797
23838
|
}
|
|
23839
|
+
if (opts.name !== void 0 && opts.grep !== void 0) {
|
|
23840
|
+
return {
|
|
23841
|
+
text: "symbol: --grep cannot be combined with a name; drop the name to search by pattern, or drop --grep to search by exact name",
|
|
23842
|
+
code: 1
|
|
23843
|
+
};
|
|
23844
|
+
}
|
|
23845
|
+
if (opts.name === void 0 && opts.grep === void 0) {
|
|
23846
|
+
return { text: "symbol requires a name or --grep <pattern>", code: 1 };
|
|
23847
|
+
}
|
|
23848
|
+
const matchesGrep = opts.grep !== void 0 ? compileGrepMatcher(opts.grep) : void 0;
|
|
23849
|
+
const excludeTests = opts.excludeTests === true;
|
|
23798
23850
|
const queryOpts = {};
|
|
23799
23851
|
if (opts.name !== void 0) queryOpts.name = opts.name;
|
|
23800
23852
|
if (opts.file !== void 0) {
|
|
@@ -23802,11 +23854,36 @@ function runSymbol(opts) {
|
|
|
23802
23854
|
healStaleIndex(queryOpts.filePath);
|
|
23803
23855
|
}
|
|
23804
23856
|
if (opts.kind !== void 0) queryOpts.kind = opts.kind;
|
|
23805
|
-
if (
|
|
23857
|
+
if (matchesGrep !== void 0 || excludeTests) {
|
|
23858
|
+
queryOpts.limit = FIND_SCAN_LIMIT;
|
|
23859
|
+
} else if (opts.limit !== void 0) {
|
|
23860
|
+
queryOpts.limit = opts.limit;
|
|
23861
|
+
}
|
|
23806
23862
|
if (opts.file === void 0 && opts.projectRoot !== void 0) queryOpts.rootDir = opts.projectRoot;
|
|
23807
|
-
const
|
|
23863
|
+
const rawResults = querySymbols(queryOpts);
|
|
23864
|
+
const preFilterCount = rawResults.length;
|
|
23865
|
+
const effectiveLimit = opts.limit ?? 100;
|
|
23866
|
+
const anyClientFilter = matchesGrep !== void 0 || excludeTests;
|
|
23867
|
+
const filtered = anyClientFilter ? rawResults.filter((s) => (matchesGrep === void 0 || matchesGrep(s.name)) && !(excludeTests && isTestFile(s.filePath))) : rawResults;
|
|
23868
|
+
const results = anyClientFilter ? filtered.slice(0, effectiveLimit) : filtered;
|
|
23869
|
+
const hiddenByExcludeTests = excludeTests ? rawResults.filter((s) => (matchesGrep === void 0 || matchesGrep(s.name)) && isTestFile(s.filePath)).length : 0;
|
|
23870
|
+
if (excludeTests && filtered.length === 0 && hiddenByExcludeTests > 0) {
|
|
23871
|
+
const label = opts.name ?? opts.grep ?? "*";
|
|
23872
|
+
const notice = `no non-test matches for '${label}' (${excludeTestsHiddenNote(hiddenByExcludeTests)})`;
|
|
23873
|
+
if (opts.json === true) {
|
|
23874
|
+
return { text: JSON.stringify({ items: [], truncated: false, totalCount: 0 }, null, 2), code: 0 };
|
|
23875
|
+
}
|
|
23876
|
+
return { text: `token-goat: ${notice}`, code: 0 };
|
|
23877
|
+
}
|
|
23878
|
+
if (matchesGrep !== void 0 && filtered.length === 0 && preFilterCount > 0) {
|
|
23879
|
+
if (opts.json === true) {
|
|
23880
|
+
const text2 = JSON.stringify({ items: [], truncated: false, totalCount: 0 }, null, 2);
|
|
23881
|
+
return { text: text2, code: 0 };
|
|
23882
|
+
}
|
|
23883
|
+
return { text: grepFilteredToEmptyNotice(preFilterCount, opts.grep ?? "", "symbol", "symbols"), code: 0 };
|
|
23884
|
+
}
|
|
23808
23885
|
if (results.length === 0) {
|
|
23809
|
-
let text2 = `No matches for '${opts.name ?? "*"}'`;
|
|
23886
|
+
let text2 = `No matches for '${opts.name ?? opts.grep ?? "*"}'`;
|
|
23810
23887
|
const emptyIndexRoot = opts.json !== true ? opts.projectRoot ?? resolveProjectRoot({ project: process.cwd() }) : null;
|
|
23811
23888
|
const indexEmpty = emptyIndexRoot !== null && isIndexEmptyForProject(globalDbPath(), emptyIndexRoot);
|
|
23812
23889
|
if (opts.name !== void 0 && emptyIndexRoot !== null) {
|
|
@@ -23827,11 +23904,19 @@ ${emptyIndexMessage(emptyIndexRoot)}`;
|
|
|
23827
23904
|
const symbolDisplayRoot = getDisplayRoot(opts.projectRoot);
|
|
23828
23905
|
if (opts.json === true) {
|
|
23829
23906
|
const capped = guardJsonRows(results);
|
|
23830
|
-
|
|
23907
|
+
let trueTotal;
|
|
23908
|
+
let truncatedFlag;
|
|
23909
|
+
if (anyClientFilter) {
|
|
23910
|
+
trueTotal = filtered.length;
|
|
23911
|
+
truncatedFlag = capped.truncated || results.length < filtered.length;
|
|
23912
|
+
} else {
|
|
23913
|
+
trueTotal = countSymbols(queryOpts);
|
|
23914
|
+
truncatedFlag = capped.truncated || trueTotal > results.length;
|
|
23915
|
+
}
|
|
23831
23916
|
const items = capped.items.map((s) => ({ ...s, filePath: toDisplayPath(symbolDisplayRoot, s.filePath) }));
|
|
23832
|
-
const payload = { items, truncated:
|
|
23917
|
+
const payload = { items, truncated: truncatedFlag, totalCount: trueTotal };
|
|
23833
23918
|
const text2 = JSON.stringify(payload, null, 2);
|
|
23834
|
-
recordReadStat("symbol_lookup", fullSourceBytes, text2, opts.name ?? opts.file);
|
|
23919
|
+
recordReadStat("symbol_lookup", fullSourceBytes, text2, opts.name ?? opts.file ?? opts.grep);
|
|
23835
23920
|
return { text: text2, code: 0 };
|
|
23836
23921
|
}
|
|
23837
23922
|
const blocks = results.map((sym) => {
|
|
@@ -23843,7 +23928,7 @@ ${preview}` : header;
|
|
|
23843
23928
|
});
|
|
23844
23929
|
const warning = opts.file !== void 0 ? staleWarning(resolveIndexPath(opts.file, opts.projectRoot ?? process.cwd())) : "";
|
|
23845
23930
|
const text = guardText(warning + blocks.join("\n\n"), "symbol");
|
|
23846
|
-
recordReadStat("symbol_lookup", fullSourceBytes, text, opts.name ?? opts.file);
|
|
23931
|
+
recordReadStat("symbol_lookup", fullSourceBytes, text, opts.name ?? opts.file ?? opts.grep);
|
|
23847
23932
|
return { text, code: 0 };
|
|
23848
23933
|
}
|
|
23849
23934
|
function parseReadSpec(spec) {
|
|
@@ -23912,7 +23997,7 @@ function runLineRange(range2, opts) {
|
|
|
23912
23997
|
const allLines = text.split(/\r?\n/);
|
|
23913
23998
|
if (allLines.length > 1 && allLines[allLines.length - 1] === "") allLines.pop();
|
|
23914
23999
|
if (start > allLines.length) {
|
|
23915
|
-
return { text: `Line ${start} is past end of file (${allLines.length
|
|
24000
|
+
return { text: `Line ${start} is past end of file (${countNoun(allLines.length, "line")}): ${file2}`, code: 1 };
|
|
23916
24001
|
}
|
|
23917
24002
|
const clampedEnd = Math.min(end, allLines.length);
|
|
23918
24003
|
const slice = allLines.slice(start - 1, clampedEnd);
|
|
@@ -23948,13 +24033,13 @@ function formatAmbiguity(symbol3, file2, candidates, explicitRoot, commandName =
|
|
|
23948
24033
|
const multiFile = new Set(candidates.map((c) => c.filePath)).size > 1;
|
|
23949
24034
|
const displayRoot = getDisplayRoot(explicitRoot);
|
|
23950
24035
|
const lines2 = [
|
|
23951
|
-
`Ambiguous symbol '${symbol3}' in '${file2}': ${candidates.length}
|
|
24036
|
+
`Ambiguous symbol '${symbol3}' in '${file2}': ${countNoun(candidates.length, "definition")} match. Retry with one of the qualified commands below to pick one:`
|
|
23952
24037
|
];
|
|
23953
24038
|
const fileSymCache = /* @__PURE__ */ new Map();
|
|
23954
24039
|
const getFileSyms = (filePath) => {
|
|
23955
24040
|
let fileSyms = fileSymCache.get(filePath);
|
|
23956
24041
|
if (fileSyms === void 0) {
|
|
23957
|
-
fileSyms = querySymbols({ filePath, limit:
|
|
24042
|
+
fileSyms = querySymbols({ filePath, limit: FIND_SCAN_LIMIT });
|
|
23958
24043
|
fileSymCache.set(filePath, fileSyms);
|
|
23959
24044
|
}
|
|
23960
24045
|
return fileSyms;
|
|
@@ -24340,17 +24425,17 @@ function runRefs(opts) {
|
|
|
24340
24425
|
lines2.push(`${sym}: ${grepFilteredToEmptyNotice(preGrepCount, opts.grep ?? "", "reference", "references").trim()}`);
|
|
24341
24426
|
continue;
|
|
24342
24427
|
}
|
|
24343
|
-
lines2.push(opts.excludeTests === true && suppressed > 0 ? `${sym}: (no non-test references found; ${suppressed}
|
|
24428
|
+
lines2.push(opts.excludeTests === true && suppressed > 0 ? `${sym}: (no non-test references found; ${excludeTestsHiddenNote(suppressed)})` : `${sym}: (no references found)`);
|
|
24344
24429
|
continue;
|
|
24345
24430
|
}
|
|
24346
24431
|
lines2.push(`${sym}:`);
|
|
24347
24432
|
if (opts.top !== void 0) {
|
|
24348
24433
|
lines2.push(...renderTopFilesSummary(results, opts.top, suppressed));
|
|
24349
24434
|
} else if (opts.callers === true) {
|
|
24350
|
-
if (opts.excludeTests === true && suppressed > 0) lines2.push(` ${results.length}
|
|
24435
|
+
if (opts.excludeTests === true && suppressed > 0) lines2.push(` ${countNoun(results.length, "reference")} (${excludeTestsHiddenNote(suppressed)})`);
|
|
24351
24436
|
lines2.push(...renderCallerGroups(results, opts.context ?? 0));
|
|
24352
24437
|
} else {
|
|
24353
|
-
if (opts.excludeTests === true && suppressed > 0) lines2.push(` ${results.length}
|
|
24438
|
+
if (opts.excludeTests === true && suppressed > 0) lines2.push(` ${countNoun(results.length, "reference")} (${excludeTestsHiddenNote(suppressed)})`);
|
|
24354
24439
|
for (const ref2 of results) lines2.push(...renderRefLines(ref2, opts.context ?? 0));
|
|
24355
24440
|
}
|
|
24356
24441
|
}
|
|
@@ -24411,17 +24496,17 @@ function runRefsCrossFile(pairs, opts) {
|
|
|
24411
24496
|
lines2.push(`${key}: ${grepFilteredToEmptyNotice(preGrepCount, opts.grep ?? "", "reference", "references").trim()}`);
|
|
24412
24497
|
continue;
|
|
24413
24498
|
}
|
|
24414
|
-
lines2.push(opts.excludeTests === true && suppressed > 0 ? `${key}: (no non-test references found; ${suppressed}
|
|
24499
|
+
lines2.push(opts.excludeTests === true && suppressed > 0 ? `${key}: (no non-test references found; ${excludeTestsHiddenNote(suppressed)})` : `${key}: (no references found)`);
|
|
24415
24500
|
continue;
|
|
24416
24501
|
}
|
|
24417
24502
|
lines2.push(`${key}:`);
|
|
24418
24503
|
if (opts.top !== void 0) {
|
|
24419
24504
|
lines2.push(...renderTopFilesSummary(results, opts.top, suppressed));
|
|
24420
24505
|
} else if (opts.callers === true) {
|
|
24421
|
-
if (opts.excludeTests === true && suppressed > 0) lines2.push(` ${results.length}
|
|
24506
|
+
if (opts.excludeTests === true && suppressed > 0) lines2.push(` ${countNoun(results.length, "reference")} (${excludeTestsHiddenNote(suppressed)})`);
|
|
24422
24507
|
lines2.push(...renderCallerGroups(results, opts.context ?? 0));
|
|
24423
24508
|
} else {
|
|
24424
|
-
if (opts.excludeTests === true && suppressed > 0) lines2.push(` ${results.length}
|
|
24509
|
+
if (opts.excludeTests === true && suppressed > 0) lines2.push(` ${countNoun(results.length, "reference")} (${excludeTestsHiddenNote(suppressed)})`);
|
|
24425
24510
|
for (const ref2 of results) lines2.push(...renderRefLines(ref2, opts.context ?? 0));
|
|
24426
24511
|
}
|
|
24427
24512
|
}
|
|
@@ -24462,16 +24547,25 @@ function runRefsSingle(opts) {
|
|
|
24462
24547
|
}
|
|
24463
24548
|
if (results.length === 0) {
|
|
24464
24549
|
if (matchesGrep !== void 0 && preGrepCount > 0) {
|
|
24550
|
+
if (opts.json === true) {
|
|
24551
|
+
emit2(JSON.stringify({ items: [], truncated: false, totalCount: 0 }, null, 2));
|
|
24552
|
+
return 0;
|
|
24553
|
+
}
|
|
24465
24554
|
emit2(grepFilteredToEmptyNotice(preGrepCount, opts.grep ?? "", "reference", "references"));
|
|
24466
24555
|
return 0;
|
|
24467
24556
|
}
|
|
24468
24557
|
if (opts.excludeTests === true && suppressed > 0) {
|
|
24469
|
-
emitErr(`No non-test references found for '${symName}' (${suppressed}
|
|
24558
|
+
emitErr(`No non-test references found for '${symName}' (${excludeTestsHiddenNote(suppressed)})`);
|
|
24559
|
+
return 1;
|
|
24560
|
+
}
|
|
24561
|
+
const rootDir = resolveProjectRoot({ project: process.cwd() });
|
|
24562
|
+
if (querySymbols({ name: symName, rootDir, limit: 1 }).length === 0) {
|
|
24563
|
+
emitErr(`Symbol not found: ${symName}${unknownSymbolSuggestion(symName, rootDir)}`);
|
|
24564
|
+
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir)) emitErr(emptyIndexMessage(rootDir));
|
|
24470
24565
|
return 1;
|
|
24471
24566
|
}
|
|
24472
24567
|
emitErr(`No references found for '${symName}'`);
|
|
24473
24568
|
if (opts.json !== true) {
|
|
24474
|
-
const rootDir = resolveProjectRoot({ project: process.cwd() });
|
|
24475
24569
|
if (isIndexEmptyForProject(globalDbPath(), rootDir)) emitErr(emptyIndexMessage(rootDir));
|
|
24476
24570
|
}
|
|
24477
24571
|
return 1;
|
|
@@ -24491,7 +24585,7 @@ function runRefsSingle(opts) {
|
|
|
24491
24585
|
recordReadStat("symbol_read", fullSourceBytes, text2, symName);
|
|
24492
24586
|
return 0;
|
|
24493
24587
|
}
|
|
24494
|
-
const lines2 = opts.top !== void 0 ? renderTopFilesSummary(results, opts.top, suppressed) : opts.callers === true ? [...opts.excludeTests === true && suppressed > 0 ? [`${results.length}
|
|
24588
|
+
const lines2 = 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((ref2) => renderRefLines(ref2, opts.context ?? 0, ""))];
|
|
24495
24589
|
const text = lines2.join("\n");
|
|
24496
24590
|
emitGuarded(text, "symbol");
|
|
24497
24591
|
recordReadStat("symbol_read", fullSourceBytes, text, symName);
|
|
@@ -24509,8 +24603,8 @@ function groupRefsByFile(refs) {
|
|
|
24509
24603
|
function renderTopFilesSummary(refs, topN, suppressed) {
|
|
24510
24604
|
const grouped = groupRefsByFile(refs);
|
|
24511
24605
|
const shown = grouped.slice(0, topN);
|
|
24512
|
-
const suppressedNote = suppressed !== void 0 && suppressed > 0 ? ` (${suppressed}
|
|
24513
|
-
const lines2 = [`${refs.length}
|
|
24606
|
+
const suppressedNote = suppressed !== void 0 && suppressed > 0 ? ` (${excludeTestsHiddenNote(suppressed)})` : "";
|
|
24607
|
+
const lines2 = [`${countNoun(refs.length, "reference")} across ${countNoun(grouped.length, "file")} (showing top ${shown.length})${suppressedNote}`];
|
|
24514
24608
|
for (const { file: file2, count } of shown) lines2.push(` ${count} ${refsDisplayPath(file2)}`);
|
|
24515
24609
|
const omittedFiles = grouped.length - shown.length;
|
|
24516
24610
|
if (omittedFiles > 0) {
|
|
@@ -24659,7 +24753,7 @@ function runSkeleton(opts) {
|
|
|
24659
24753
|
return { text: text2, code: 0 };
|
|
24660
24754
|
}
|
|
24661
24755
|
const totalLines = filtered.length > 0 ? Math.max(...filtered.map((s) => s.lineEnd)) : 0;
|
|
24662
|
-
const lines2 = [`# Skeleton: ${opts.file} (${filtered.length}
|
|
24756
|
+
const lines2 = [`# Skeleton: ${opts.file} (${countNoun(filtered.length, "symbol")}, ${countNoun(totalLines, "line")})`];
|
|
24663
24757
|
if (filtered.length === 0 && preFilterCount > 0) lines2.push(filteredToEmptyNotice(preFilterCount, opts.minLines, opts.grep));
|
|
24664
24758
|
for (const sym of filtered) {
|
|
24665
24759
|
const lineStr = sym.lineStart.toString().padStart(6);
|
|
@@ -24699,7 +24793,7 @@ function runOutline(opts) {
|
|
|
24699
24793
|
recordReadStat("outline", fullSourceBytes, text2, opts.file);
|
|
24700
24794
|
return { text: text2, code: 0 };
|
|
24701
24795
|
}
|
|
24702
|
-
const lines2 = [`# Outline: ${opts.file} (${filtered.length
|
|
24796
|
+
const lines2 = [`# Outline: ${opts.file} (${countNoun(filtered.length, "symbol")})`];
|
|
24703
24797
|
if (filtered.length === 0 && preFilterCount > 0) lines2.push(filteredToEmptyNotice(preFilterCount, opts.minLines, opts.grep));
|
|
24704
24798
|
for (const sym of filtered) {
|
|
24705
24799
|
const rangeStr = `${sym.lineStart.toString().padStart(4)}-${sym.lineEnd.toString().padEnd(6)}`;
|
|
@@ -25406,16 +25500,25 @@ function runFind(opts) {
|
|
|
25406
25500
|
const symbols = rawSymbols.filter(
|
|
25407
25501
|
(s) => s.name.toLowerCase().includes(patternLower)
|
|
25408
25502
|
);
|
|
25409
|
-
|
|
25503
|
+
let fuzzyNames = [];
|
|
25504
|
+
if (symbols.length === 0) {
|
|
25505
|
+
fuzzyNames = rankSimilarNames(rawSymbols.map((s) => s.name), opts.pattern);
|
|
25506
|
+
}
|
|
25507
|
+
const matched = fuzzyNames.length > 0 ? fuzzyNames.flatMap((n) => rawSymbols.filter((s) => s.name === n)) : symbols;
|
|
25508
|
+
const files = [...new Set(matched.map((s) => s.filePath))].slice(0, opts.limit ?? 50);
|
|
25410
25509
|
const truncated = rawSymbols.length === FIND_SCAN_LIMIT;
|
|
25411
25510
|
if (files.length === 0) {
|
|
25412
25511
|
emitErr(`No indexed files match '${opts.pattern}'`);
|
|
25413
25512
|
return 1;
|
|
25414
25513
|
}
|
|
25415
25514
|
if (opts.json === true) {
|
|
25416
|
-
|
|
25515
|
+
const fuzzyPayload = fuzzyNames.length > 0 ? { fuzzy: true, matchedNames: fuzzyNames } : {};
|
|
25516
|
+
emit2(JSON.stringify({ files, truncated, ...fuzzyPayload }, null, 2));
|
|
25417
25517
|
return 0;
|
|
25418
25518
|
}
|
|
25519
|
+
if (fuzzyNames.length > 0) {
|
|
25520
|
+
emitErr(`No symbol name contains '${opts.pattern}'; showing files for the nearest indexed ${fuzzyNames.length === 1 ? "name" : "names"}: ${fuzzyNames.join(", ")}`);
|
|
25521
|
+
}
|
|
25419
25522
|
for (const f of files) {
|
|
25420
25523
|
emit2(toDisplayPath(rootDir, f));
|
|
25421
25524
|
}
|
|
@@ -25519,7 +25622,12 @@ function runChanged(opts = {}) {
|
|
|
25519
25622
|
emitErr(`Could not run git diff against '${ref2}'`);
|
|
25520
25623
|
return 1;
|
|
25521
25624
|
}
|
|
25625
|
+
const emptyEnvelope = () => {
|
|
25626
|
+
emit2(JSON.stringify({ items: [], truncated: false, totalCount: 0 }, null, 2));
|
|
25627
|
+
return 0;
|
|
25628
|
+
};
|
|
25522
25629
|
if (changedFiles.length === 0) {
|
|
25630
|
+
if (opts.json === true) return emptyEnvelope();
|
|
25523
25631
|
emit2("No files changed.");
|
|
25524
25632
|
return 0;
|
|
25525
25633
|
}
|
|
@@ -25527,9 +25635,29 @@ function runChanged(opts = {}) {
|
|
|
25527
25635
|
const matchesGrep = opts.grep !== void 0 ? compileGrepMatcher(opts.grep) : void 0;
|
|
25528
25636
|
if (matchesGrep !== void 0) changedFiles = changedFiles.filter((f) => matchesGrep(f));
|
|
25529
25637
|
if (matchesGrep !== void 0 && changedFiles.length === 0) {
|
|
25638
|
+
if (opts.json === true) return emptyEnvelope();
|
|
25530
25639
|
emit2(grepFilteredToEmptyNotice(preGrepFileCount, opts.grep ?? "", "changed file", "changed files"));
|
|
25531
25640
|
return 0;
|
|
25532
25641
|
}
|
|
25642
|
+
const postGrepFileCount = changedFiles.length;
|
|
25643
|
+
let hiddenTestFiles = 0;
|
|
25644
|
+
if (opts.excludeTests === true) {
|
|
25645
|
+
const kept = changedFiles.filter((f) => !isTestFile(f));
|
|
25646
|
+
hiddenTestFiles = changedFiles.length - kept.length;
|
|
25647
|
+
changedFiles = kept;
|
|
25648
|
+
}
|
|
25649
|
+
if (changedFiles.length === 0 && hiddenTestFiles > 0) {
|
|
25650
|
+
if (opts.json === true) return emptyEnvelope();
|
|
25651
|
+
const grepRemoved = preGrepFileCount - postGrepFileCount;
|
|
25652
|
+
if (matchesGrep !== void 0 && grepRemoved > 0) {
|
|
25653
|
+
emit2(
|
|
25654
|
+
`No non-test files matched --grep ${opts.grep ?? ""} (${excludeTestsHiddenNote(hiddenTestFiles)}; ${countNoun(grepRemoved, "other changed file")} did not match the filter)`
|
|
25655
|
+
);
|
|
25656
|
+
return 0;
|
|
25657
|
+
}
|
|
25658
|
+
emit2(`No non-test files changed (${excludeTestsHiddenNote(hiddenTestFiles)})`);
|
|
25659
|
+
return 0;
|
|
25660
|
+
}
|
|
25533
25661
|
if (opts.symbolMode === true) {
|
|
25534
25662
|
let hunksByFile = /* @__PURE__ */ new Map();
|
|
25535
25663
|
try {
|
|
@@ -25541,12 +25669,13 @@ function runChanged(opts = {}) {
|
|
|
25541
25669
|
}
|
|
25542
25670
|
const allSymbols = [];
|
|
25543
25671
|
for (const f of changedFiles) {
|
|
25544
|
-
const fileSymbols = querySymbols({ filePath: resolveIndexPath(f, projectRoot), limit:
|
|
25672
|
+
const fileSymbols = querySymbols({ filePath: resolveIndexPath(f, projectRoot), limit: FIND_SCAN_LIMIT });
|
|
25545
25673
|
const hunks = hunksByFile.get(f);
|
|
25546
25674
|
const scoped = hunks === void 0 ? fileSymbols : fileSymbols.filter((s) => hunks.some((h) => h.start <= s.lineEnd && h.end >= s.lineStart));
|
|
25547
25675
|
allSymbols.push(...scoped);
|
|
25548
25676
|
}
|
|
25549
25677
|
if (allSymbols.length === 0) {
|
|
25678
|
+
if (opts.json === true) return emptyEnvelope();
|
|
25550
25679
|
emit2("No symbols changed.");
|
|
25551
25680
|
return 0;
|
|
25552
25681
|
}
|
|
@@ -26525,7 +26654,17 @@ async function runSemantic(query, opts) {
|
|
|
26525
26654
|
void 0,
|
|
26526
26655
|
rootDir
|
|
26527
26656
|
);
|
|
26528
|
-
const
|
|
26657
|
+
const matchesGrep = opts.grep !== void 0 ? compileGrepMatcher(opts.grep) : void 0;
|
|
26658
|
+
const mergedHits = mergeNearbyHits(rawHits);
|
|
26659
|
+
const preGrepHitCount = mergedHits.length;
|
|
26660
|
+
const keepHit = (h) => {
|
|
26661
|
+
if (opts.excludeTests === true && isTestFile(h.filePath)) return false;
|
|
26662
|
+
return matchesGrep === void 0 || matchesGrep(toDisplayPath(rootDir, h.filePath));
|
|
26663
|
+
};
|
|
26664
|
+
const anyFilter = matchesGrep !== void 0 || opts.excludeTests === true;
|
|
26665
|
+
const filteredHits = anyFilter ? mergedHits.filter(keepHit) : mergedHits;
|
|
26666
|
+
const suppressedHits = opts.excludeTests === true ? mergedHits.filter((h) => (matchesGrep === void 0 || matchesGrep(toDisplayPath(rootDir, h.filePath))) && isTestFile(h.filePath)).length : 0;
|
|
26667
|
+
const hits = filteredHits.slice(0, n);
|
|
26529
26668
|
if (hits.length > 0) {
|
|
26530
26669
|
const enclosing = hits.map((h) => resolveEnclosingSymbol(h.filePath, h.startLine));
|
|
26531
26670
|
if (opts.json === true) {
|
|
@@ -26553,8 +26692,41 @@ ${previewLines(h.text, 3)}`;
|
|
|
26553
26692
|
recordReadStat("semantic_search", sumFileSizes(hits.map((h) => h.filePath)), text2, query);
|
|
26554
26693
|
return { text: text2, code: 0 };
|
|
26555
26694
|
}
|
|
26556
|
-
|
|
26695
|
+
let results;
|
|
26696
|
+
let preGrepFtsCount = 0;
|
|
26697
|
+
let suppressedFts = 0;
|
|
26698
|
+
if (anyFilter) {
|
|
26699
|
+
const overFetchFts = Math.min(MAX_OVER_FETCH, n * OVER_FETCH_FACTOR);
|
|
26700
|
+
const rawResults = searchSymbolsFts(query, overFetchFts, void 0, rootDir);
|
|
26701
|
+
preGrepFtsCount = rawResults.length;
|
|
26702
|
+
if (opts.excludeTests === true) {
|
|
26703
|
+
suppressedFts = rawResults.filter((s) => (matchesGrep === void 0 || matchesGrep(toDisplayPath(rootDir, s.filePath))) && isTestFile(s.filePath)).length;
|
|
26704
|
+
}
|
|
26705
|
+
results = rawResults.filter(keepHit).slice(0, n);
|
|
26706
|
+
} else {
|
|
26707
|
+
results = searchSymbolsFts(query, n, void 0, rootDir);
|
|
26708
|
+
}
|
|
26557
26709
|
if (results.length === 0) {
|
|
26710
|
+
const preGrepTotal = preGrepHitCount + preGrepFtsCount;
|
|
26711
|
+
if (matchesGrep !== void 0 && preGrepTotal > 0) {
|
|
26712
|
+
const notice = grepFilteredToEmptyNotice(preGrepTotal, opts.grep ?? "", "match", "matches");
|
|
26713
|
+
if (opts.json === true) {
|
|
26714
|
+
const payload = { source: "fts", items: [], truncated: false, totalCount: 0, grepFilteredToEmpty: true, hint: notice.trim() };
|
|
26715
|
+
return { text: JSON.stringify(payload, null, 2), code: 0 };
|
|
26716
|
+
}
|
|
26717
|
+
return { text: `token-goat: ${notice.trim()}`, code: 0 };
|
|
26718
|
+
}
|
|
26719
|
+
if (opts.excludeTests === true) {
|
|
26720
|
+
const suppressedTotal = suppressedHits + suppressedFts;
|
|
26721
|
+
if (suppressedTotal > 0) {
|
|
26722
|
+
const notice = `no non-test matches for '${query}' (${excludeTestsHiddenNote(suppressedTotal)})`;
|
|
26723
|
+
if (opts.json === true) {
|
|
26724
|
+
const payload = { source: "fts", items: [], truncated: false, totalCount: 0, excludeTestsFilteredToEmpty: true, hint: notice };
|
|
26725
|
+
return { text: JSON.stringify(payload, null, 2), code: 0 };
|
|
26726
|
+
}
|
|
26727
|
+
return { text: `token-goat: ${notice}`, code: 0 };
|
|
26728
|
+
}
|
|
26729
|
+
}
|
|
26558
26730
|
const indexEmpty = isIndexEmptyForProject(globalDbPath(), rootDir);
|
|
26559
26731
|
if (opts.json === true) {
|
|
26560
26732
|
const payload = indexEmpty ? { source: "fts", items: [], truncated: false, totalCount: 0, indexEmpty: true, hint: emptyIndexMessage(rootDir) } : { source: "fts", items: [], truncated: false, totalCount: 0 };
|
|
@@ -26814,7 +26986,7 @@ function fileDefinesName(fp, name2, getSyms) {
|
|
|
26814
26986
|
return getSyms(fp).some((s) => s.name === name2);
|
|
26815
26987
|
}
|
|
26816
26988
|
function filterRefsForSymbol(refs, name2, filePath, getSyms) {
|
|
26817
|
-
return refs.filter((ref2) => ref2.filePath === filePath || !fileDefinesName(ref2.filePath, name2, getSyms));
|
|
26989
|
+
return refs.filter((ref2) => foldPath(ref2.filePath) === foldPath(filePath) || !fileDefinesName(ref2.filePath, name2, getSyms));
|
|
26818
26990
|
}
|
|
26819
26991
|
function resolveCallers(name2, limit, filePath, rootDir, excludeTests) {
|
|
26820
26992
|
const resolvedRootDir = rootDir ?? resolveProjectRoot({ project: process.cwd() });
|
|
@@ -26862,7 +27034,12 @@ function runCallers(opts) {
|
|
|
26862
27034
|
return 0;
|
|
26863
27035
|
}
|
|
26864
27036
|
if (opts.excludeTests === true && suppressed > 0) {
|
|
26865
|
-
emitErr2(`No non-test references found for '${opts.symbol}' (${suppressed}
|
|
27037
|
+
emitErr2(`No non-test references found for '${opts.symbol}' (${excludeTestsHiddenNote(suppressed)})`);
|
|
27038
|
+
return 1;
|
|
27039
|
+
}
|
|
27040
|
+
if (querySymbols({ name: name2, rootDir, limit: 1 }).length === 0) {
|
|
27041
|
+
emitErr2(`Symbol not found: ${opts.symbol}${unknownSymbolSuggestion(name2, rootDir)}`);
|
|
27042
|
+
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir)) emitErr2(emptyIndexMessage(rootDir));
|
|
26866
27043
|
return 1;
|
|
26867
27044
|
}
|
|
26868
27045
|
emitErr2(`No references found for '${opts.symbol}'`);
|
|
@@ -26882,7 +27059,7 @@ function runCallers(opts) {
|
|
|
26882
27059
|
return 0;
|
|
26883
27060
|
}
|
|
26884
27061
|
if (opts.excludeTests === true && suppressed > 0) {
|
|
26885
|
-
emit3(`${entries.length}
|
|
27062
|
+
emit3(`${countNoun(entries.length, "caller")} found (${excludeTestsHiddenNote(suppressed)})`);
|
|
26886
27063
|
}
|
|
26887
27064
|
for (const e of entries) {
|
|
26888
27065
|
const displayPath = toDisplayPath(rootDir, e.file);
|
|
@@ -26908,17 +27085,22 @@ function runCallChain(opts) {
|
|
|
26908
27085
|
return 1;
|
|
26909
27086
|
}
|
|
26910
27087
|
} else if (querySymbols({ name: name2, rootDir, limit: 1 }).length === 0) {
|
|
26911
|
-
emitErr2(`Symbol not found: ${opts.symbol}`);
|
|
27088
|
+
emitErr2(`Symbol not found: ${opts.symbol}${unknownSymbolSuggestion(name2, rootDir)}`);
|
|
26912
27089
|
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir)) emitErr2(emptyIndexMessage(rootDir));
|
|
26913
27090
|
return 1;
|
|
26914
27091
|
}
|
|
26915
27092
|
const getSyms = buildFileSymCache();
|
|
27093
|
+
let suppressedCount = 0;
|
|
26916
27094
|
const callersOf = (n) => {
|
|
26917
27095
|
const refs = queryRefs({ name: n, limit: DEFAULT_REF_QUERY_LIMIT, rootDir });
|
|
26918
27096
|
if (refs.length === 0) return [];
|
|
26919
27097
|
const scoped = fileHint !== void 0 && n === name2 ? filterRefsForSymbol(refs, n, fileHint, getSyms) : refs;
|
|
26920
27098
|
const names = /* @__PURE__ */ new Set();
|
|
26921
27099
|
for (const ref2 of scoped) {
|
|
27100
|
+
if (opts.excludeTests === true && isTestFile(ref2.filePath)) {
|
|
27101
|
+
suppressedCount += 1;
|
|
27102
|
+
continue;
|
|
27103
|
+
}
|
|
26922
27104
|
const enc = enclosingSymbol(getSyms(ref2.filePath), ref2.line);
|
|
26923
27105
|
if (enc !== null) names.add(enc.name);
|
|
26924
27106
|
}
|
|
@@ -26930,6 +27112,10 @@ function runCallChain(opts) {
|
|
|
26930
27112
|
return 0;
|
|
26931
27113
|
}
|
|
26932
27114
|
if (chains.length === 1 && chains[0]?.length === 1 && chains[0][0] === name2) {
|
|
27115
|
+
if (opts.excludeTests === true && suppressedCount > 0) {
|
|
27116
|
+
emit3(`${name2} (no non-test callers; ${excludeTestsHiddenNote(suppressedCount)})`);
|
|
27117
|
+
return 0;
|
|
27118
|
+
}
|
|
26933
27119
|
emit3(`${name2} (no callers)`);
|
|
26934
27120
|
return 0;
|
|
26935
27121
|
}
|
|
@@ -26959,6 +27145,7 @@ function runImpact(opts) {
|
|
|
26959
27145
|
const getSyms = buildFileSymCache();
|
|
26960
27146
|
const hops = /* @__PURE__ */ new Map([[rootName, 0]]);
|
|
26961
27147
|
const queue = [[rootName, 0]];
|
|
27148
|
+
let suppressedCount = 0;
|
|
26962
27149
|
while (queue.length > 0) {
|
|
26963
27150
|
const item = queue.shift();
|
|
26964
27151
|
if (item === void 0) break;
|
|
@@ -26967,6 +27154,10 @@ function runImpact(opts) {
|
|
|
26967
27154
|
const refs = queryRefs({ name: name2, limit: DEFAULT_REF_QUERY_LIMIT, rootDir });
|
|
26968
27155
|
const scoped = fileHint !== void 0 && name2 === rootName ? filterRefsForSymbol(refs, name2, fileHint, getSyms) : refs;
|
|
26969
27156
|
for (const ref2 of scoped) {
|
|
27157
|
+
if (opts.excludeTests === true && isTestFile(ref2.filePath)) {
|
|
27158
|
+
suppressedCount += 1;
|
|
27159
|
+
continue;
|
|
27160
|
+
}
|
|
26970
27161
|
const newHop = depth + 1;
|
|
26971
27162
|
const enc = enclosingSymbol(getSyms(ref2.filePath), ref2.line);
|
|
26972
27163
|
if (enc === null) {
|
|
@@ -26986,6 +27177,14 @@ function runImpact(opts) {
|
|
|
26986
27177
|
hops.delete(rootName);
|
|
26987
27178
|
const sorted = [...hops.entries()].sort(compareHopEntries).slice(0, top);
|
|
26988
27179
|
if (sorted.length === 0) {
|
|
27180
|
+
if (opts.excludeTests === true && suppressedCount > 0) {
|
|
27181
|
+
emitErr2(`No non-test impact found for '${opts.symbol}' (${excludeTestsHiddenNote(suppressedCount)})`);
|
|
27182
|
+
return 1;
|
|
27183
|
+
}
|
|
27184
|
+
if (querySymbols({ name: rootName, rootDir, limit: 1 }).length === 0) {
|
|
27185
|
+
emitErr2(`Symbol not found: ${opts.symbol}${unknownSymbolSuggestion(rootName, rootDir)}`);
|
|
27186
|
+
return 1;
|
|
27187
|
+
}
|
|
26989
27188
|
emitErr2(`No callers found for '${opts.symbol}'`);
|
|
26990
27189
|
return 1;
|
|
26991
27190
|
}
|
|
@@ -27082,7 +27281,7 @@ function runDead(opts) {
|
|
|
27082
27281
|
return 0;
|
|
27083
27282
|
}
|
|
27084
27283
|
if (opts.excludeTests === true && suppressed > 0) {
|
|
27085
|
-
emit3(`No dead symbols found (${suppressed}
|
|
27284
|
+
emit3(`No dead symbols found (${excludeTestsHiddenNote(suppressed)}).`);
|
|
27086
27285
|
} else {
|
|
27087
27286
|
emit3("No dead symbols found.");
|
|
27088
27287
|
}
|
|
@@ -27090,7 +27289,7 @@ function runDead(opts) {
|
|
|
27090
27289
|
return 0;
|
|
27091
27290
|
}
|
|
27092
27291
|
if (opts.excludeTests === true && suppressed > 0) {
|
|
27093
|
-
emit3(`${sliced.length
|
|
27292
|
+
emit3(`${countNoun(sliced.length, "dead symbol")} (${excludeTestsHiddenNote(suppressed)})`);
|
|
27094
27293
|
}
|
|
27095
27294
|
for (const r of sliced) {
|
|
27096
27295
|
emit3(`${r.name} ${toDisplayPath(rootDir, r.file)}:${r.line}`);
|
|
@@ -31217,6 +31416,8 @@ function writeGuidance(filePath) {
|
|
|
31217
31416
|
BEGIN,
|
|
31218
31417
|
buildGuidanceBody("VS Code\u2019s supported MCP integration and its built-in file-read tools"),
|
|
31219
31418
|
"",
|
|
31419
|
+
"**Compressed payloads:** a message containing a token-goat payload block (recognizable by a `recovery: token-goat retrieve <id>` line) is compressed text, not an answer. Call the MCP tool `retrieve_text` with that id to recover the original text, then answer the question the message asks using the recovered text. Never present the raw payload to the user as the response; if the `retrieve_text` tool is unavailable (the MCP server is not running, or the chat is not in Agent mode), say so plainly and ask the user to switch to Agent mode or run `token-goat install --vscode`.",
|
|
31420
|
+
"",
|
|
31220
31421
|
"VS Code support: token-goat install --vscode configures a project-local stdio MCP server in .vscode/mcp.json under the servers root key. VS Code may call these MCP tools when selected; MCP does not intercept VS Code\u2019s built-in file reads.",
|
|
31221
31422
|
END
|
|
31222
31423
|
].join("\n");
|
|
@@ -65994,7 +66195,6 @@ function checkSymbolCount(dbPath, rootDir) {
|
|
|
65994
66195
|
}
|
|
65995
66196
|
}
|
|
65996
66197
|
var DIRTY_QUEUE_BACKLOG_WARN_THRESHOLD = 500;
|
|
65997
|
-
var DRAIN_HEARTBEAT_STALE_MS = 6e4;
|
|
65998
66198
|
function checkDirtyQueueHealth(dataDir2) {
|
|
65999
66199
|
let pendingCount = 0;
|
|
66000
66200
|
try {
|
|
@@ -66017,7 +66217,7 @@ function checkDirtyQueueHealth(dataDir2) {
|
|
|
66017
66217
|
heartbeatAgeMs = Date.now() - fs40.statSync(drainHeartbeatPathFor(dataDir2)).mtimeMs;
|
|
66018
66218
|
} catch {
|
|
66019
66219
|
}
|
|
66020
|
-
if (heartbeatAgeMs !== null && heartbeatAgeMs >
|
|
66220
|
+
if (heartbeatAgeMs !== null && heartbeatAgeMs > WORKER_HEARTBEAT_STALE_MS) {
|
|
66021
66221
|
return {
|
|
66022
66222
|
name: "Dirty queue",
|
|
66023
66223
|
status: "warn",
|
|
@@ -82829,7 +83029,12 @@ function requirePositiveInt(flag, raw) {
|
|
|
82829
83029
|
}
|
|
82830
83030
|
async function cmdSemantic(query, opts) {
|
|
82831
83031
|
const limit = opts.limit !== void 0 ? requireNonNegativeInt("--limit", opts.limit) : 20;
|
|
82832
|
-
const { text, code } = await runSemantic(query, {
|
|
83032
|
+
const { text, code } = await runSemantic(query, {
|
|
83033
|
+
limit,
|
|
83034
|
+
...opts.json === true ? { json: true } : {},
|
|
83035
|
+
...opts.grep !== void 0 ? { grep: opts.grep } : {},
|
|
83036
|
+
...opts.excludeTests === true ? { excludeTests: true } : {}
|
|
83037
|
+
});
|
|
82833
83038
|
(opts.json === true || code === 0 ? out : err)(text);
|
|
82834
83039
|
process.exitCode = code;
|
|
82835
83040
|
}
|
|
@@ -84764,7 +84969,7 @@ function buildProgram() {
|
|
|
84764
84969
|
process.exitCode = 1;
|
|
84765
84970
|
}
|
|
84766
84971
|
};
|
|
84767
|
-
program2.command("symbol
|
|
84972
|
+
program2.command("symbol [name]").description("search for a symbol by name, or project-wide by --grep name pattern").option("-l, --limit <n>", "max results").option("-f, --file <path>", "restrict to one file").option("-k, --kind <kind>", "restrict to one kind (function, class, ...)").option("-p, --project [path]", "scope search to one project root instead of the global index (defaults to cwd)").option("-j, --json", "output as JSON").option("--grep <pattern>", "only show symbols whose name matches this regex (literal substring if it is not valid regex); cannot be combined with <name>").option("--exclude-tests", "hide symbols defined in a test file (opt-in; default output is unchanged)").action((name2, opts) => {
|
|
84768
84973
|
let projectRoot;
|
|
84769
84974
|
if (opts.project === true) {
|
|
84770
84975
|
projectRoot = resolveProjectRoot({ project: process.cwd() });
|
|
@@ -84773,12 +84978,14 @@ function buildProgram() {
|
|
|
84773
84978
|
}
|
|
84774
84979
|
return runExitText(
|
|
84775
84980
|
() => runSymbol({
|
|
84776
|
-
name: name2,
|
|
84981
|
+
...name2 !== void 0 ? { name: name2 } : {},
|
|
84777
84982
|
limit: opts.limit !== void 0 ? requireNonNegativeInt("--limit", opts.limit) : 20,
|
|
84778
84983
|
...opts.file !== void 0 ? { file: opts.file } : {},
|
|
84779
84984
|
...opts.kind !== void 0 ? { kind: opts.kind } : {},
|
|
84780
84985
|
...projectRoot !== void 0 ? { projectRoot } : {},
|
|
84781
|
-
...opts.json === true ? { json: true } : {}
|
|
84986
|
+
...opts.json === true ? { json: true } : {},
|
|
84987
|
+
...opts.grep !== void 0 ? { grep: opts.grep } : {},
|
|
84988
|
+
...opts.excludeTests === true ? { excludeTests: true } : {}
|
|
84782
84989
|
})
|
|
84783
84990
|
);
|
|
84784
84991
|
});
|
|
@@ -84811,7 +85018,7 @@ function buildProgram() {
|
|
|
84811
85018
|
).option("-j, --json", "output as JSON").option("--list", "list all section headings in the file instead of reading one").action(
|
|
84812
85019
|
(spec, opts) => opts.list === true ? runExit(() => runListSections({ file: spec, ...opts.json === true ? { json: true } : {} })) : runExitText(() => runSection({ spec, ...opts.json === true ? { json: true } : {} }))
|
|
84813
85020
|
);
|
|
84814
|
-
program2.command("semantic <query>").description("semantic search (falls back to full-text search)").option("-l, --limit <n>", "max results").option("-j, --json", "output as JSON").action(guard(cmdSemantic));
|
|
85021
|
+
program2.command("semantic <query>").description("semantic search (falls back to full-text search)").option("-l, --limit <n>", "max results").option("-j, --json", "output as JSON").option("--grep <pattern>", "filter to hits whose file path matches this regex (literal substring if it is not valid regex); matched against the path as rendered").option("--exclude-tests", "hide hits whose file is a test file (opt-in; default output is unchanged)").action(guard(cmdSemantic));
|
|
84815
85022
|
program2.command("skeleton <file> [more...]").description('list all symbols in a file without bodies (also accepts a comma-separated file list "a,b,c" for one headed block per file)').option("-j, --json", "output as JSON").option("--min-lines <n>", "only show symbols at least N lines long").option("--grep <pattern>", "only show symbols whose name matches this regex (literal substring if it is not valid regex)").option("--force-refresh", "reparse file from disk before querying (ignore stale index)").option("--stats", "add per-symbol reference count and doc-coverage flag").action(
|
|
84816
85023
|
(file2, more, opts) => runExitText(
|
|
84817
85024
|
() => noteExtraFileArgs(
|
|
@@ -84947,21 +85154,23 @@ function buildProgram() {
|
|
|
84947
85154
|
})
|
|
84948
85155
|
)
|
|
84949
85156
|
);
|
|
84950
|
-
program2.command("call-chain <symbol>").description("transitive callers up toward entry points (BFS, cycle-safe; accepts file::symbol to disambiguate which same-named definition is meant)").option("-d, --depth <n>", "max BFS depth (default 8)").option("-j, --json", "output as JSON").action(
|
|
85157
|
+
program2.command("call-chain <symbol>").description("transitive callers up toward entry points (BFS, cycle-safe; accepts file::symbol to disambiguate which same-named definition is meant)").option("-d, --depth <n>", "max BFS depth (default 8)").option("-j, --json", "output as JSON").option("--exclude-tests", "hide callers whose call site lives in a test file (opt-in; default output is unchanged)").action(
|
|
84951
85158
|
(symbol3, opts) => runExit(
|
|
84952
85159
|
() => runCallChain({
|
|
84953
85160
|
symbol: symbol3,
|
|
84954
85161
|
...opts.depth !== void 0 ? { depth: requireInt("--depth", opts.depth) } : {},
|
|
84955
|
-
...opts.json === true ? { json: true } : {}
|
|
85162
|
+
...opts.json === true ? { json: true } : {},
|
|
85163
|
+
...opts.excludeTests === true ? { excludeTests: true } : {}
|
|
84956
85164
|
})
|
|
84957
85165
|
)
|
|
84958
85166
|
);
|
|
84959
|
-
program2.command("impact <symbol>").description("transitive set of callers impacted by a change (with hop depth; accepts file::symbol to disambiguate which same-named definition is meant)").option("--top <n>", "limit output to top N results").option("-j, --json", "output as JSON").action(
|
|
85167
|
+
program2.command("impact <symbol>").description("transitive set of callers impacted by a change (with hop depth; accepts file::symbol to disambiguate which same-named definition is meant)").option("--top <n>", "limit output to top N results").option("-j, --json", "output as JSON").option("--exclude-tests", "hide callers whose call site lives in a test file (opt-in; default output is unchanged)").action(
|
|
84960
85168
|
(symbol3, opts) => runExit(
|
|
84961
85169
|
() => runImpact({
|
|
84962
85170
|
symbol: symbol3,
|
|
84963
85171
|
...opts.top !== void 0 ? { top: requireNonNegativeInt("--top", opts.top) } : {},
|
|
84964
|
-
...opts.json === true ? { json: true } : {}
|
|
85172
|
+
...opts.json === true ? { json: true } : {},
|
|
85173
|
+
...opts.excludeTests === true ? { excludeTests: true } : {}
|
|
84965
85174
|
})
|
|
84966
85175
|
)
|
|
84967
85176
|
);
|
|
@@ -85118,13 +85327,14 @@ function buildProgram() {
|
|
|
85118
85327
|
}))());
|
|
85119
85328
|
program2.command("fetch-image <url>").description("fetch an image URL and shrink it (saves to --out path or a temp file)").option("--out <path>", "output file path").option("-j, --json", "output as JSON").action((url2, opts) => guard(() => cmdFetchImage({ url: url2, ...opts.out !== void 0 ? { out: opts.out } : {}, ...opts.json === true ? { json: true } : {} }))());
|
|
85120
85329
|
program2.command("history").description("show recent session history: bash commands and web fetches (current-session or recent cache)").option("--limit <n>", "max entries to show (default: 30)").option("-j, --json", "output as JSON").action((opts) => guard(() => cmdHistory(opts))());
|
|
85121
|
-
program2.command("changed [ref]").description("list files or symbols changed since a git ref").option("--since <ref>", "git ref to compare against (default: HEAD~5)").option("--symbol", "list symbols instead of files").option("-j, --json", "output as JSON").option("--grep <pattern>", "filter to changed files whose path matches this regex (falls back to a literal substring match when the pattern does not compile); applies to file paths even in --symbol mode").action(
|
|
85330
|
+
program2.command("changed [ref]").description("list files or symbols changed since a git ref").option("--since <ref>", "git ref to compare against (default: HEAD~5)").option("--symbol", "list symbols instead of files").option("-j, --json", "output as JSON").option("--grep <pattern>", "filter to changed files whose path matches this regex (falls back to a literal substring match when the pattern does not compile); applies to file paths even in --symbol mode").option("--exclude-tests", "hide changed files that live in a test file (opt-in; default output is unchanged); applies to file paths even in --symbol mode").action(
|
|
85122
85331
|
(ref2, opts) => runExit(
|
|
85123
85332
|
() => runChanged({
|
|
85124
85333
|
ref: opts.since ?? ref2 ?? "HEAD~5",
|
|
85125
85334
|
...opts.symbol === true ? { symbolMode: true } : {},
|
|
85126
85335
|
...opts.json === true ? { json: true } : {},
|
|
85127
|
-
...opts.grep !== void 0 ? { grep: opts.grep } : {}
|
|
85336
|
+
...opts.grep !== void 0 ? { grep: opts.grep } : {},
|
|
85337
|
+
...opts.excludeTests === true ? { excludeTests: true } : {}
|
|
85128
85338
|
})
|
|
85129
85339
|
)
|
|
85130
85340
|
);
|