token-goat 2.8.6 → 2.9.2
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 +27 -717
- package/SECURITY.md +1 -1
- package/dist/token-goat-chunk-CGWACYYZ.mjs +79 -0
- package/dist/{token-goat-chunk-XAWIELXH.mjs → token-goat-chunk-FXAPKVRG.mjs} +545 -217
- package/dist/{token-goat-chunk-SHN4UTL4.mjs → token-goat-chunk-JMUBXBG7.mjs} +5 -5
- package/dist/{token-goat-chunk-U7M2LTGP.mjs → token-goat-chunk-KKIB7O3Z.mjs} +854 -283
- package/dist/{token-goat-chunk-ZIPBLIUZ.mjs → token-goat-chunk-LEBYARO3.mjs} +28 -4
- package/dist/{token-goat-chunk-DK4VLLYB.mjs → token-goat-chunk-LJ3CHCTT.mjs} +2061 -3612
- package/dist/{token-goat-chunk-L2XHDICZ.mjs → token-goat-chunk-NY4HYRSK.mjs} +28 -27
- package/dist/{token-goat-chunk-MA5237JN.mjs → token-goat-chunk-Q4LOQY44.mjs} +205 -60
- package/dist/{token-goat-chunk-GUNYAGOZ.mjs → token-goat-chunk-UZ2NFOOZ.mjs} +10103 -117
- package/dist/{token-goat-chunk-TELKICYU.mjs → token-goat-chunk-VCNW7BGU.mjs} +155 -519
- package/dist/{token-goat-chunk-LJEETTER.mjs → token-goat-chunk-ZVN5WHTO.mjs} +5 -5
- package/dist/token-goat-hook.mjs +5 -5
- package/dist/token-goat.core.mjs +5 -5
- package/docs/C4_RUNTIME_ARCHITECTURE.md +303 -0
- package/docs/cli.md +339 -0
- package/docs/install.md +331 -0
- package/docs/security.md +102 -0
- package/package.json +7 -2
- package/dist/token-goat-chunk-2JZ66BBE.mjs +0 -7157
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
formatCsvTable,
|
|
30
30
|
getEmbeddingCoverage,
|
|
31
31
|
getFileEntry,
|
|
32
|
+
getTrackedFiles,
|
|
32
33
|
indexFileSync,
|
|
33
34
|
isAvailable,
|
|
34
35
|
isBlobStale,
|
|
@@ -42,6 +43,7 @@ import {
|
|
|
42
43
|
mergeNearbyHits,
|
|
43
44
|
ocrImage,
|
|
44
45
|
ocrIntegrityFailed,
|
|
46
|
+
parseIpv6Groups,
|
|
45
47
|
parseWhereSpecs,
|
|
46
48
|
pathEqClause,
|
|
47
49
|
probeImageMeta,
|
|
@@ -66,7 +68,7 @@ import {
|
|
|
66
68
|
walkProject,
|
|
67
69
|
yamlLineClosesQuote,
|
|
68
70
|
yamlOpenQuoteAfter
|
|
69
|
-
} from "./token-goat-chunk-
|
|
71
|
+
} from "./token-goat-chunk-LJ3CHCTT.mjs";
|
|
70
72
|
import {
|
|
71
73
|
Database,
|
|
72
74
|
PER_FILE_COUNTERFACTUAL_CEILING,
|
|
@@ -120,36 +122,11 @@ import {
|
|
|
120
122
|
unsupportedLanguageName,
|
|
121
123
|
windowsCmdQuoteArg,
|
|
122
124
|
withExtension
|
|
123
|
-
} from "./token-goat-chunk-
|
|
125
|
+
} from "./token-goat-chunk-UZ2NFOOZ.mjs";
|
|
124
126
|
import {
|
|
125
127
|
registerReset
|
|
126
128
|
} from "./token-goat-chunk-AO2QD2AG.mjs";
|
|
127
129
|
|
|
128
|
-
// src/repomap.ts
|
|
129
|
-
import * as fs from "fs";
|
|
130
|
-
import * as path from "path";
|
|
131
|
-
function getTrackedFiles(cwd = process.cwd()) {
|
|
132
|
-
try {
|
|
133
|
-
let dir = cwd;
|
|
134
|
-
let onlyFile = "";
|
|
135
|
-
try {
|
|
136
|
-
if (fs.statSync(cwd).isFile()) {
|
|
137
|
-
dir = path.dirname(cwd);
|
|
138
|
-
onlyFile = path.basename(cwd);
|
|
139
|
-
}
|
|
140
|
-
} catch {
|
|
141
|
-
}
|
|
142
|
-
const args = onlyFile === "" ? ["ls-files"] : ["ls-files", "--error-unmatch", "--", onlyFile];
|
|
143
|
-
const result = runGit(args, { cwd: dir });
|
|
144
|
-
if (result.exitCode !== 0 || !result.stdout) {
|
|
145
|
-
return [];
|
|
146
|
-
}
|
|
147
|
-
return result.stdout.split("\n").filter((line) => line.trim().length > 0).map((rel) => path.join(dir, rel));
|
|
148
|
-
} catch {
|
|
149
|
-
return [];
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
130
|
// src/section_reader.ts
|
|
154
131
|
import { readFileSync } from "node:fs";
|
|
155
132
|
function parseHeadingSpec(spec, headers) {
|
|
@@ -477,8 +454,8 @@ import { execFileSync, spawnSync as spawnSync2 } from "node:child_process";
|
|
|
477
454
|
import { randomUUID } from "node:crypto";
|
|
478
455
|
|
|
479
456
|
// src/read_commands.ts
|
|
480
|
-
import * as
|
|
481
|
-
import * as
|
|
457
|
+
import * as fs4 from "node:fs";
|
|
458
|
+
import * as path4 from "node:path";
|
|
482
459
|
|
|
483
460
|
// src/json_query.ts
|
|
484
461
|
function jsonType(value) {
|
|
@@ -2371,24 +2348,32 @@ function collectionTagName(state, event, defaultTagName) {
|
|
|
2371
2348
|
function isMappingTag(tag) {
|
|
2372
2349
|
return tag.nodeKind === "mapping";
|
|
2373
2350
|
}
|
|
2351
|
+
function chargeMergeWork(state) {
|
|
2352
|
+
state.totalMergeKeys++;
|
|
2353
|
+
if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) throwError$1(state, `merge keys exceeded maxTotalMergeKeys (${state.maxTotalMergeKeys})`);
|
|
2354
|
+
}
|
|
2374
2355
|
function mergeKeys(state, frame, source, sourceTag) {
|
|
2356
|
+
chargeMergeWork(state);
|
|
2375
2357
|
for (const sourceKey of sourceTag.keys(source)) {
|
|
2376
|
-
|
|
2358
|
+
chargeMergeWork(state);
|
|
2377
2359
|
if (frame.tag.has(frame.value, sourceKey)) continue;
|
|
2378
2360
|
const err = frame.tag.addPair(frame.value, sourceKey, sourceTag.get(source, sourceKey));
|
|
2379
2361
|
if (err) throwError$1(state, err);
|
|
2380
|
-
|
|
2362
|
+
frame.overridable ??= /* @__PURE__ */ new Set();
|
|
2363
|
+
frame.overridable.add(sourceKey);
|
|
2381
2364
|
}
|
|
2382
2365
|
}
|
|
2383
2366
|
function mergeSource(state, frame, source, sourceTag) {
|
|
2384
2367
|
state.position = frame.keyPosition;
|
|
2385
2368
|
if (isMappingTag(sourceTag)) mergeKeys(state, frame, source, sourceTag);
|
|
2386
|
-
else if (sourceTag.nodeKind === "sequence" && Array.isArray(source))
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2369
|
+
else if (sourceTag.nodeKind === "sequence" && Array.isArray(source)) {
|
|
2370
|
+
if (source.length > 100) throwError$1(state, "abnormal merge sequence size");
|
|
2371
|
+
for (const element of source) {
|
|
2372
|
+
const elementTag = state.nodeTags.get(element);
|
|
2373
|
+
if (!elementTag) throwError$1(state, "cannot merge mappings; the provided source object is unacceptable");
|
|
2374
|
+
mergeKeys(state, frame, element, elementTag);
|
|
2375
|
+
}
|
|
2376
|
+
} else throwError$1(state, "cannot merge mappings; the provided source object is unacceptable");
|
|
2392
2377
|
}
|
|
2393
2378
|
function addMappingValue(state, frame, key, value, tag) {
|
|
2394
2379
|
state.position = frame.keyPosition;
|
|
@@ -2731,6 +2716,24 @@ function testDocumentSeparator(state, position = state.position) {
|
|
|
2731
2716
|
}
|
|
2732
2717
|
return false;
|
|
2733
2718
|
}
|
|
2719
|
+
function skipByteOrderMark(state) {
|
|
2720
|
+
if (state.position === state.lineStart && state.input.charCodeAt(state.position) === 65279) {
|
|
2721
|
+
state.position++;
|
|
2722
|
+
state.lineStart = state.position;
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
function testDocumentBoundary(state) {
|
|
2726
|
+
if (state.position !== state.lineStart) return false;
|
|
2727
|
+
if (testDocumentSeparator(state)) return true;
|
|
2728
|
+
if (state.input.charCodeAt(state.position) !== 65279) return false;
|
|
2729
|
+
const snapshot = snapshotState(state);
|
|
2730
|
+
skipByteOrderMark(state);
|
|
2731
|
+
skipSeparationSpace(state, true);
|
|
2732
|
+
const ch = state.input.charCodeAt(state.position);
|
|
2733
|
+
const result = state.position === state.lineStart && (ch === 37 || ch === 45 && testDocumentSeparator(state));
|
|
2734
|
+
restoreState(state, snapshot);
|
|
2735
|
+
return result;
|
|
2736
|
+
}
|
|
2734
2737
|
function skipUntilLineEnd(state) {
|
|
2735
2738
|
let ch = state.input.charCodeAt(state.position);
|
|
2736
2739
|
while (ch !== 0 && !isEol(ch)) ch = state.input.charCodeAt(++state.position);
|
|
@@ -2914,7 +2917,7 @@ function readBlockScalar(state, parentIndent, props) {
|
|
|
2914
2917
|
} else if (column > 0) valueEnd = linePosition + column;
|
|
2915
2918
|
break;
|
|
2916
2919
|
}
|
|
2917
|
-
if (
|
|
2920
|
+
if (testDocumentBoundary(state)) break;
|
|
2918
2921
|
if (!detectedIndent && contentIndent === -1 && isEol(first)) maxLeadingIndent = Math.max(maxLeadingIndent, column);
|
|
2919
2922
|
if (!detectedIndent && contentIndent === -1 && !isEol(first)) {
|
|
2920
2923
|
if (first === 9 && column < parentIndent) {
|
|
@@ -2967,7 +2970,7 @@ function readPlainScalar(state, nodeIndent, nodeContext, props) {
|
|
|
2967
2970
|
const inFlow = nodeContext === CONTEXT_FLOW_IN;
|
|
2968
2971
|
let multiline = false;
|
|
2969
2972
|
while (ch !== 0) {
|
|
2970
|
-
if (
|
|
2973
|
+
if (testDocumentBoundary(state)) break;
|
|
2971
2974
|
if (ch === 58) {
|
|
2972
2975
|
const following = state.input.charCodeAt(state.position + 1);
|
|
2973
2976
|
if (isWsOrEolOrEnd(following) || inFlow && isFlowIndicator(following)) break;
|
|
@@ -3324,7 +3327,7 @@ function readDocument(state) {
|
|
|
3324
3327
|
const documentEvent = state.events[documentEventIndex];
|
|
3325
3328
|
if (documentEvent?.type === EVENT_ID.DOCUMENT) documentEvent.explicitEnd = explicitEnd;
|
|
3326
3329
|
addPopEvent(state);
|
|
3327
|
-
if (!explicitEnd && state.position < state.length && !(state
|
|
3330
|
+
if (!explicitEnd && state.position < state.length && !testDocumentBoundary(state)) throwError(state, "end of the stream or a document separator is expected");
|
|
3328
3331
|
}
|
|
3329
3332
|
function parseEvents(input, options) {
|
|
3330
3333
|
const length = input.length;
|
|
@@ -3345,8 +3348,8 @@ function parseEvents(input, options) {
|
|
|
3345
3348
|
};
|
|
3346
3349
|
const nullpos = input.indexOf("\0");
|
|
3347
3350
|
if (nullpos !== -1) YAMLException.throwAt(input, nullpos, "null byte is not allowed in input", state.filename);
|
|
3348
|
-
if (state.input.charCodeAt(state.position) === 65279) state.position++;
|
|
3349
3351
|
while (state.position < state.length) {
|
|
3352
|
+
skipByteOrderMark(state);
|
|
3350
3353
|
skipSeparationSpace(state, true);
|
|
3351
3354
|
if (state.position >= state.length) break;
|
|
3352
3355
|
const documentStart = state.position;
|
|
@@ -3387,27 +3390,108 @@ function load(input, options) {
|
|
|
3387
3390
|
if (documents.length === 1) return documents[0];
|
|
3388
3391
|
throw new YAMLException("expected a single document in the stream, but found more");
|
|
3389
3392
|
}
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3393
|
+
function hasBit(mask, bit) {
|
|
3394
|
+
return (mask & 1 << bit) !== 0;
|
|
3395
|
+
}
|
|
3396
|
+
var DEFAULT_SCALAR_STYLE_RULES = {
|
|
3397
|
+
applyQuoteFlowKeysOption,
|
|
3398
|
+
doubleQuoteForInvisibles,
|
|
3399
|
+
doubleQuoteWhitespaceOnly,
|
|
3400
|
+
applyForceQuotesOption,
|
|
3401
|
+
tryLongOrMultilineAsBlock,
|
|
3402
|
+
quoteInvalidPlain,
|
|
3403
|
+
fallbackToDoubleQuoted
|
|
3404
|
+
};
|
|
3405
|
+
function _preferredQuotedStyle(layout) {
|
|
3406
|
+
if (layout.presenterOptions.quoteStyle === "single" && hasBit(layout.allowedStylesMask, SCALAR_STYLE.SINGLE_QUOTED)) return SCALAR_STYLE.SINGLE_QUOTED;
|
|
3407
|
+
return SCALAR_STYLE.DOUBLE_QUOTED;
|
|
3408
|
+
}
|
|
3409
|
+
function applyQuoteFlowKeysOption(layout) {
|
|
3410
|
+
if (!layout.presenterOptions.quoteFlowKeys) return;
|
|
3411
|
+
if (!layout.isKey || !layout.flowOnly || layout.style !== SCALAR_STYLE.PLAIN) return;
|
|
3412
|
+
layout.style = SCALAR_STYLE.DOUBLE_QUOTED;
|
|
3413
|
+
}
|
|
3414
|
+
function doubleQuoteForInvisibles(layout) {
|
|
3415
|
+
if (layout.style === SCALAR_STYLE.PLAIN && /[\t\x7F-\xA0\u2028\u2029\uFEFF\uFFFE\uFFFF]/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED;
|
|
3416
|
+
}
|
|
3417
|
+
function doubleQuoteWhitespaceOnly(layout) {
|
|
3418
|
+
if (layout.style === SCALAR_STYLE.PLAIN && /^\s+$/.test(layout.node.value)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED;
|
|
3419
|
+
}
|
|
3420
|
+
function applyForceQuotesOption(layout) {
|
|
3421
|
+
if (!layout.presenterOptions.forceQuotes) return;
|
|
3422
|
+
if (layout.isKey || layout.style !== SCALAR_STYLE.PLAIN) return;
|
|
3423
|
+
layout.style = layout.node.value.includes("\n") ? SCALAR_STYLE.DOUBLE_QUOTED : _preferredQuotedStyle(layout);
|
|
3424
|
+
}
|
|
3425
|
+
function tryLongOrMultilineAsBlock(layout) {
|
|
3426
|
+
if (layout.style !== SCALAR_STYLE.PLAIN || layout.isKey) return;
|
|
3427
|
+
const value = layout.node.value;
|
|
3428
|
+
const multiline = value.indexOf("\n") !== -1;
|
|
3429
|
+
if (!hasBit(layout.allowedStylesMask, SCALAR_STYLE.LITERAL_BLOCK)) {
|
|
3430
|
+
if (multiline) layout.style = SCALAR_STYLE.DOUBLE_QUOTED;
|
|
3431
|
+
return;
|
|
3432
|
+
}
|
|
3433
|
+
const w = layout.presenterOptions.lineWidth;
|
|
3434
|
+
if (w === -1) {
|
|
3435
|
+
if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK;
|
|
3436
|
+
return;
|
|
3437
|
+
}
|
|
3438
|
+
const availableWidth = Math.max(Math.min(w, 40), w - layout.shiftOfContent);
|
|
3439
|
+
let position = 0;
|
|
3440
|
+
let shouldFold = false;
|
|
3441
|
+
while (position <= value.length) {
|
|
3442
|
+
let lineEnd = value.length;
|
|
3443
|
+
const nextLineBreak = value.indexOf("\n", position);
|
|
3444
|
+
if (nextLineBreak !== -1) lineEnd = nextLineBreak;
|
|
3445
|
+
const line = value.slice(position, lineEnd);
|
|
3446
|
+
if (line.length > availableWidth && line[0] !== " " && / [^ \t]/.test(line)) shouldFold = true;
|
|
3447
|
+
if (nextLineBreak === -1) break;
|
|
3448
|
+
position = nextLineBreak + 1;
|
|
3449
|
+
}
|
|
3450
|
+
if (shouldFold) layout.style = SCALAR_STYLE.FOLDED_BLOCK;
|
|
3451
|
+
else if (multiline) layout.style = SCALAR_STYLE.LITERAL_BLOCK;
|
|
3452
|
+
}
|
|
3453
|
+
function quoteInvalidPlain(layout) {
|
|
3454
|
+
if (layout.style === SCALAR_STYLE.PLAIN && !hasBit(layout.allowedStylesMask, SCALAR_STYLE.PLAIN)) layout.style = _preferredQuotedStyle(layout);
|
|
3455
|
+
}
|
|
3456
|
+
function fallbackToDoubleQuoted(layout) {
|
|
3457
|
+
if (!hasBit(layout.allowedStylesMask, layout.style)) layout.style = SCALAR_STYLE.DOUBLE_QUOTED;
|
|
3458
|
+
}
|
|
3459
|
+
var SRC_C_PRINTABLE = "[\\x09\\x0A\\x0D\\x20-\\x7E\\x85\\xA0-\\uD7FF\\uE000-\\uFFFD\\u{10000}-\\u{10FFFF}]";
|
|
3460
|
+
var SRC_B_CHAR = "[\\n\\r]";
|
|
3461
|
+
var SRC_C_BYTE_ORDER_MARK = "\\uFEFF";
|
|
3462
|
+
var SRC_S_WHITE = "[ \\t]";
|
|
3463
|
+
var SRC_NB_CHAR = `(?:(?!(?:${SRC_B_CHAR}|${SRC_C_BYTE_ORDER_MARK}))${SRC_C_PRINTABLE})`;
|
|
3464
|
+
var SRC_NS_CHAR = `(?:(?!${SRC_S_WHITE})${SRC_NB_CHAR})`;
|
|
3465
|
+
var SRC_NB_JSON = "[\\x09\\x20-\\uD7FF\\uE000-\\uFFFF\\u{10000}-\\u{10FFFF}]";
|
|
3466
|
+
var SRC_C_INDICATOR = "[-?:,\\[\\]{}#&*!|>'\"%@`]";
|
|
3467
|
+
var SRC_C_FLOW_INDICATOR = "[,\\[\\]{}]";
|
|
3468
|
+
var SRC_NS_PLAIN_SAFE_FLOW_OUT = SRC_NS_CHAR;
|
|
3469
|
+
var SRC_NS_PLAIN_SAFE_FLOW_IN = `(?:(?!${SRC_C_FLOW_INDICATOR})${SRC_NS_CHAR})`;
|
|
3470
|
+
var SRC_NS_PLAIN_FIRST_FLOW_OUT = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))`;
|
|
3471
|
+
var SRC_NS_PLAIN_FIRST_FLOW_IN = `(?:(?:(?!${SRC_C_INDICATOR})${SRC_NS_CHAR})|[?:-](?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))`;
|
|
3472
|
+
var SRC_NS_PLAIN_CHAR_FLOW_OUT = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_OUT})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_OUT}))#*`;
|
|
3473
|
+
var SRC_NS_PLAIN_CHAR_FLOW_IN = `(?:(?:(?![:#])${SRC_NS_PLAIN_SAFE_FLOW_IN})|:(?=${SRC_NS_PLAIN_SAFE_FLOW_IN}))#*`;
|
|
3474
|
+
var SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_OUT})*`;
|
|
3475
|
+
var SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN = `(?:${SRC_S_WHITE}*${SRC_NS_PLAIN_CHAR_FLOW_IN})*`;
|
|
3476
|
+
var SRC_NS_PLAIN_ONE_LINE_FLOW_OUT = `${SRC_NS_PLAIN_FIRST_FLOW_OUT}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`;
|
|
3477
|
+
var SRC_NS_PLAIN_ONE_LINE_FLOW_IN = `${SRC_NS_PLAIN_FIRST_FLOW_IN}#*${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`;
|
|
3478
|
+
var SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_OUT;
|
|
3479
|
+
var SRC_NS_PLAIN_ONE_LINE_FLOW_KEY = SRC_NS_PLAIN_ONE_LINE_FLOW_IN;
|
|
3480
|
+
var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_OUT}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_OUT}`;
|
|
3481
|
+
var SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN = `\\n+${SRC_NS_PLAIN_CHAR_FLOW_IN}${SRC_NB_NS_PLAIN_IN_LINE_FLOW_IN}`;
|
|
3482
|
+
var SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT = `${SRC_NS_PLAIN_ONE_LINE_FLOW_OUT}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_OUT})*`;
|
|
3483
|
+
var SRC_NS_PLAIN_MULTI_LINE_FLOW_IN = `${SRC_NS_PLAIN_ONE_LINE_FLOW_IN}(?:${SRC_S_NS_PLAIN_NEXT_LINE_FLOW_IN})*`;
|
|
3484
|
+
var NS_PLAIN_FLOW_OUT = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_OUT})$`, "u");
|
|
3485
|
+
var NS_PLAIN_FLOW_IN = new RegExp(`^(?:${SRC_NS_PLAIN_MULTI_LINE_FLOW_IN})$`, "u");
|
|
3486
|
+
var NS_PLAIN_BLOCK_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_BLOCK_KEY})$`, "u");
|
|
3487
|
+
var NS_PLAIN_FLOW_KEY = new RegExp(`^(?:${SRC_NS_PLAIN_ONE_LINE_FLOW_KEY})$`, "u");
|
|
3488
|
+
var NB_SINGLE_ONE_LINE = new RegExp(`^(?:${SRC_NB_JSON})*$`, "u");
|
|
3489
|
+
var NB_SINGLE_MULTI_LINE = new RegExp(`^(?:${SRC_NB_JSON}|\\n)*$`, "u");
|
|
3490
|
+
var BLOCK_SCALAR_CONTENT = new RegExp(`^(?:${SRC_NB_CHAR}|\\n)*$`, "u");
|
|
3406
3491
|
var DEFAULT_PRESENTER_OPTIONS = {
|
|
3407
3492
|
indent: 2,
|
|
3408
3493
|
seqNoIndent: false,
|
|
3409
3494
|
seqInlineFirst: true,
|
|
3410
|
-
sortKeys: false,
|
|
3411
3495
|
lineWidth: 80,
|
|
3412
3496
|
flowBracketPadding: false,
|
|
3413
3497
|
flowSkipCommaSpace: false,
|
|
@@ -3415,6 +3499,7 @@ var DEFAULT_PRESENTER_OPTIONS = {
|
|
|
3415
3499
|
quoteFlowKeys: false,
|
|
3416
3500
|
quoteStyle: "single",
|
|
3417
3501
|
forceQuotes: false,
|
|
3502
|
+
scalarStyleRules: Object.keys(DEFAULT_SCALAR_STYLE_RULES).map((name) => Reflect.get(DEFAULT_SCALAR_STYLE_RULES, name)),
|
|
3418
3503
|
tagBeforeAnchor: false
|
|
3419
3504
|
};
|
|
3420
3505
|
var DEFAULT_DUMP_OPTIONS = {
|
|
@@ -3423,6 +3508,7 @@ var DEFAULT_DUMP_OPTIONS = {
|
|
|
3423
3508
|
skipInvalid: false,
|
|
3424
3509
|
noRefs: false,
|
|
3425
3510
|
flowLevel: -1,
|
|
3511
|
+
sortKeys: false,
|
|
3426
3512
|
transform: () => {
|
|
3427
3513
|
}
|
|
3428
3514
|
};
|
|
@@ -3444,11 +3530,11 @@ var CHOMPING_STRIP = CHOMPING_MODE.STRIP;
|
|
|
3444
3530
|
var CHOMPING_KEEP = CHOMPING_MODE.KEEP;
|
|
3445
3531
|
|
|
3446
3532
|
// src/openapi_query.ts
|
|
3447
|
-
import * as
|
|
3533
|
+
import * as path from "node:path";
|
|
3448
3534
|
var HTTP_METHODS = ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
|
|
3449
3535
|
function parseOpenApiSpec(text, filePath) {
|
|
3450
3536
|
text = stripBom(text);
|
|
3451
|
-
const ext =
|
|
3537
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
3452
3538
|
if (ext === ".yaml" || ext === ".yml") return load(text);
|
|
3453
3539
|
if (ext === ".json") return JSON.parse(text);
|
|
3454
3540
|
try {
|
|
@@ -3802,24 +3888,24 @@ ${c.body}`).join("\n\n");
|
|
|
3802
3888
|
}
|
|
3803
3889
|
|
|
3804
3890
|
// src/sqlite_query.ts
|
|
3805
|
-
import * as
|
|
3891
|
+
import * as fs from "node:fs";
|
|
3806
3892
|
var SQLITE_QUERY_ROW_CAP = 5e3;
|
|
3807
3893
|
var SQLITE_MAGIC = Buffer.from([83, 81, 76, 105, 116, 101, 32, 102, 111, 114, 109, 97, 116, 32, 51, 0]);
|
|
3808
3894
|
function readMagicBytes(filePath) {
|
|
3809
3895
|
let fd;
|
|
3810
3896
|
try {
|
|
3811
|
-
fd =
|
|
3897
|
+
fd = fs.openSync(filePath, "r");
|
|
3812
3898
|
} catch {
|
|
3813
3899
|
return null;
|
|
3814
3900
|
}
|
|
3815
3901
|
try {
|
|
3816
3902
|
const buf = Buffer.alloc(SQLITE_MAGIC.length);
|
|
3817
|
-
const bytesRead =
|
|
3903
|
+
const bytesRead = fs.readSync(fd, buf, 0, buf.length, 0);
|
|
3818
3904
|
return bytesRead === buf.length ? buf : null;
|
|
3819
3905
|
} catch {
|
|
3820
3906
|
return null;
|
|
3821
3907
|
} finally {
|
|
3822
|
-
|
|
3908
|
+
fs.closeSync(fd);
|
|
3823
3909
|
}
|
|
3824
3910
|
}
|
|
3825
3911
|
function isSqliteFile(filePath) {
|
|
@@ -3827,7 +3913,7 @@ function isSqliteFile(filePath) {
|
|
|
3827
3913
|
return magic !== null && magic.equals(SQLITE_MAGIC);
|
|
3828
3914
|
}
|
|
3829
3915
|
function openReadonlySqlite(filePath) {
|
|
3830
|
-
if (!
|
|
3916
|
+
if (!fs.existsSync(filePath)) {
|
|
3831
3917
|
throw new Error(`file not found: ${filePath}`);
|
|
3832
3918
|
}
|
|
3833
3919
|
if (!isSqliteFile(filePath)) {
|
|
@@ -4530,8 +4616,8 @@ function formatConflictSummaries(summaries) {
|
|
|
4530
4616
|
|
|
4531
4617
|
// src/screenshot.ts
|
|
4532
4618
|
import dns from "node:dns/promises";
|
|
4533
|
-
import
|
|
4534
|
-
import
|
|
4619
|
+
import fs2 from "node:fs";
|
|
4620
|
+
import path2 from "node:path";
|
|
4535
4621
|
var loadPuppeteer = createLazyModuleLoader(
|
|
4536
4622
|
async () => await import("puppeteer-core"),
|
|
4537
4623
|
"screenshot disabled (puppeteer-core unavailable)"
|
|
@@ -4540,7 +4626,7 @@ var PLAYWRIGHT_CHROME_SUBDIRS = ["chrome-win64", "chrome-win"];
|
|
|
4540
4626
|
function findPlaywrightChromium(msPlaywrightDir) {
|
|
4541
4627
|
let entries;
|
|
4542
4628
|
try {
|
|
4543
|
-
entries =
|
|
4629
|
+
entries = fs2.readdirSync(msPlaywrightDir);
|
|
4544
4630
|
} catch {
|
|
4545
4631
|
return [];
|
|
4546
4632
|
}
|
|
@@ -4548,7 +4634,7 @@ function findPlaywrightChromium(msPlaywrightDir) {
|
|
|
4548
4634
|
const candidates = [];
|
|
4549
4635
|
for (const m of versioned) {
|
|
4550
4636
|
for (const sub of PLAYWRIGHT_CHROME_SUBDIRS) {
|
|
4551
|
-
candidates.push(
|
|
4637
|
+
candidates.push(path2.join(msPlaywrightDir, m[0], sub, "chrome.exe"));
|
|
4552
4638
|
}
|
|
4553
4639
|
}
|
|
4554
4640
|
return candidates;
|
|
@@ -4559,33 +4645,33 @@ function platformCandidatePaths() {
|
|
|
4559
4645
|
const programFiles = process.env["PROGRAMFILES"];
|
|
4560
4646
|
const programFilesX86 = process.env["PROGRAMFILES(X86)"];
|
|
4561
4647
|
const localAppData = process.env["LOCALAPPDATA"];
|
|
4562
|
-
if (programFiles) candidates2.push(
|
|
4563
|
-
if (programFilesX86) candidates2.push(
|
|
4648
|
+
if (programFiles) candidates2.push(path2.join(programFiles, "Google", "Chrome", "Application", "chrome.exe"));
|
|
4649
|
+
if (programFilesX86) candidates2.push(path2.join(programFilesX86, "Google", "Chrome", "Application", "chrome.exe"));
|
|
4564
4650
|
if (localAppData) {
|
|
4565
|
-
candidates2.push(
|
|
4566
|
-
candidates2.push(...findPlaywrightChromium(
|
|
4651
|
+
candidates2.push(path2.join(localAppData, "Google", "Chrome", "Application", "chrome.exe"));
|
|
4652
|
+
candidates2.push(...findPlaywrightChromium(path2.join(localAppData, "ms-playwright")));
|
|
4567
4653
|
}
|
|
4568
4654
|
return candidates2;
|
|
4569
4655
|
}
|
|
4570
4656
|
if (process.platform === "darwin") {
|
|
4571
4657
|
const home2 = process.env["HOME"];
|
|
4572
4658
|
const candidates2 = ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"];
|
|
4573
|
-
if (home2) candidates2.push(...findPlaywrightChromium(
|
|
4659
|
+
if (home2) candidates2.push(...findPlaywrightChromium(path2.join(home2, "Library", "Caches", "ms-playwright")));
|
|
4574
4660
|
return candidates2;
|
|
4575
4661
|
}
|
|
4576
4662
|
const home = process.env["HOME"];
|
|
4577
4663
|
const candidates = ["/usr/bin/google-chrome-stable", "/usr/bin/google-chrome", "/usr/bin/chromium-browser", "/usr/bin/chromium"];
|
|
4578
|
-
if (home) candidates.push(...findPlaywrightChromium(
|
|
4664
|
+
if (home) candidates.push(...findPlaywrightChromium(path2.join(home, ".cache", "ms-playwright")));
|
|
4579
4665
|
return candidates;
|
|
4580
4666
|
}
|
|
4581
4667
|
function resolveBrowserExecutablePath(explicit) {
|
|
4582
|
-
if (explicit &&
|
|
4668
|
+
if (explicit && fs2.existsSync(explicit)) return explicit;
|
|
4583
4669
|
const cfgPath = loadConfig().screenshot.chrome_path;
|
|
4584
|
-
if (cfgPath &&
|
|
4670
|
+
if (cfgPath && fs2.existsSync(cfgPath)) return cfgPath;
|
|
4585
4671
|
const envPath = process.env["TOKEN_GOAT_CHROME_PATH"];
|
|
4586
|
-
if (envPath &&
|
|
4672
|
+
if (envPath && fs2.existsSync(envPath)) return envPath;
|
|
4587
4673
|
for (const candidate of platformCandidatePaths()) {
|
|
4588
|
-
if (
|
|
4674
|
+
if (fs2.existsSync(candidate)) return candidate;
|
|
4589
4675
|
}
|
|
4590
4676
|
return null;
|
|
4591
4677
|
}
|
|
@@ -4598,43 +4684,6 @@ function isBlockedIpv4Octets(a, b) {
|
|
|
4598
4684
|
if (a === 0) return true;
|
|
4599
4685
|
return false;
|
|
4600
4686
|
}
|
|
4601
|
-
function parseIpv6Groups(text) {
|
|
4602
|
-
let rest = text;
|
|
4603
|
-
const zoneAt = rest.indexOf("%");
|
|
4604
|
-
if (zoneAt !== -1) rest = rest.slice(0, zoneAt);
|
|
4605
|
-
if (!/^[0-9a-f:.]+$/i.test(rest) || !rest.includes(":")) return null;
|
|
4606
|
-
const lastColon = rest.lastIndexOf(":");
|
|
4607
|
-
const tail = rest.slice(lastColon + 1);
|
|
4608
|
-
if (tail.includes(".")) {
|
|
4609
|
-
const quad = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(tail);
|
|
4610
|
-
if (!quad) return null;
|
|
4611
|
-
const octets = [Number(quad[1]), Number(quad[2]), Number(quad[3]), Number(quad[4])];
|
|
4612
|
-
if (octets.some((n) => n > 255)) return null;
|
|
4613
|
-
const hi = octets[0] << 8 | octets[1];
|
|
4614
|
-
const lo = octets[2] << 8 | octets[3];
|
|
4615
|
-
rest = `${rest.slice(0, lastColon + 1)}${hi.toString(16)}:${lo.toString(16)}`;
|
|
4616
|
-
}
|
|
4617
|
-
const parseGroup = (g) => /^[0-9a-f]{1,4}$/i.test(g) ? parseInt(g, 16) : null;
|
|
4618
|
-
const halves = rest.split("::");
|
|
4619
|
-
if (halves.length > 2) return null;
|
|
4620
|
-
let parts;
|
|
4621
|
-
if (halves.length === 2) {
|
|
4622
|
-
const left = halves[0].length > 0 ? halves[0].split(":") : [];
|
|
4623
|
-
const right = halves[1].length > 0 ? halves[1].split(":") : [];
|
|
4624
|
-
if (left.length + right.length > 7) return null;
|
|
4625
|
-
parts = [...left, ...Array(8 - left.length - right.length).fill("0"), ...right];
|
|
4626
|
-
} else {
|
|
4627
|
-
parts = rest.split(":");
|
|
4628
|
-
if (parts.length !== 8) return null;
|
|
4629
|
-
}
|
|
4630
|
-
const groups = [];
|
|
4631
|
-
for (const part of parts) {
|
|
4632
|
-
const value = parseGroup(part);
|
|
4633
|
-
if (value === null) return null;
|
|
4634
|
-
groups.push(value);
|
|
4635
|
-
}
|
|
4636
|
-
return groups;
|
|
4637
|
-
}
|
|
4638
4687
|
function isBlockedIpv6(groups) {
|
|
4639
4688
|
if (groups.every((g) => g === 0)) return true;
|
|
4640
4689
|
if (groups.slice(0, 7).every((g) => g === 0) && groups[7] === 1) return true;
|
|
@@ -4892,7 +4941,7 @@ async function takeScreenshot(url, destPath, opts) {
|
|
|
4892
4941
|
}
|
|
4893
4942
|
|
|
4894
4943
|
// src/notes.ts
|
|
4895
|
-
import * as
|
|
4944
|
+
import * as fs3 from "node:fs";
|
|
4896
4945
|
var WHOLE_FILE_NOTE_SYMBOL = "";
|
|
4897
4946
|
function toNoteRow(row) {
|
|
4898
4947
|
return {
|
|
@@ -4917,7 +4966,7 @@ function resolveSymbolMatch(filePath, symbolName, dbPath = globalDbPath()) {
|
|
|
4917
4966
|
}
|
|
4918
4967
|
function bodyFromSource(entry) {
|
|
4919
4968
|
try {
|
|
4920
|
-
return
|
|
4969
|
+
return fs3.readFileSync(entry.filePath, "utf8").split(/\r?\n/).slice(Math.max(0, entry.lineStart - 1), entry.lineEnd).join("\n");
|
|
4921
4970
|
} catch {
|
|
4922
4971
|
return "";
|
|
4923
4972
|
}
|
|
@@ -4968,7 +5017,7 @@ function isNoteStale(note, dbPath = globalDbPath()) {
|
|
|
4968
5017
|
|
|
4969
5018
|
// src/ts_refs.ts
|
|
4970
5019
|
import { createRequire } from "node:module";
|
|
4971
|
-
import * as
|
|
5020
|
+
import * as path3 from "node:path";
|
|
4972
5021
|
var _require = createRequire(import.meta.url);
|
|
4973
5022
|
var MAX_CANDIDATE_FILES = 50;
|
|
4974
5023
|
var _ts = null;
|
|
@@ -4999,7 +5048,7 @@ registerReset(() => {
|
|
|
4999
5048
|
var TS_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts"]);
|
|
5000
5049
|
var TS_JS_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
5001
5050
|
function isTsPath(filePath) {
|
|
5002
|
-
return TS_EXTENSIONS.has(
|
|
5051
|
+
return TS_EXTENSIONS.has(path3.extname(filePath).toLowerCase());
|
|
5003
5052
|
}
|
|
5004
5053
|
function resolveTypedRefs(input) {
|
|
5005
5054
|
const ts = loadTs();
|
|
@@ -5029,7 +5078,7 @@ function resolveTypedRefs(input) {
|
|
|
5029
5078
|
if (defSymbol === null) return null;
|
|
5030
5079
|
const out = [];
|
|
5031
5080
|
for (const ref of input.candidates) {
|
|
5032
|
-
if (!TS_JS_EXTENSIONS.has(
|
|
5081
|
+
if (!TS_JS_EXTENSIONS.has(path3.extname(ref.filePath).toLowerCase())) {
|
|
5033
5082
|
out.push(ref);
|
|
5034
5083
|
continue;
|
|
5035
5084
|
}
|
|
@@ -5055,12 +5104,12 @@ function buildScopedProgram(ts, rootNames, searchFrom) {
|
|
|
5055
5104
|
resolveJsonModule: true,
|
|
5056
5105
|
esModuleInterop: true
|
|
5057
5106
|
};
|
|
5058
|
-
const configPath = ts.findConfigFile(
|
|
5107
|
+
const configPath = ts.findConfigFile(path3.dirname(searchFrom), ts.sys.fileExists, "tsconfig.json");
|
|
5059
5108
|
if (configPath !== void 0) {
|
|
5060
5109
|
try {
|
|
5061
5110
|
const raw = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
5062
5111
|
if (raw.error === void 0) {
|
|
5063
|
-
const parsed = ts.parseJsonConfigFileContent(raw.config, ts.sys,
|
|
5112
|
+
const parsed = ts.parseJsonConfigFileContent(raw.config, ts.sys, path3.dirname(configPath));
|
|
5064
5113
|
Object.assign(options, parsed.options);
|
|
5065
5114
|
}
|
|
5066
5115
|
} catch {
|
|
@@ -5164,7 +5213,7 @@ var STRUCTURED_MISS_MAX_NODES = 2e4;
|
|
|
5164
5213
|
var REFS_TOP_SCAN_LIMIT = 2e4;
|
|
5165
5214
|
function fileExists(p) {
|
|
5166
5215
|
try {
|
|
5167
|
-
|
|
5216
|
+
fs4.statSync(p);
|
|
5168
5217
|
return true;
|
|
5169
5218
|
} catch {
|
|
5170
5219
|
return false;
|
|
@@ -5195,30 +5244,30 @@ function withPinnedReads(pins, fn) {
|
|
|
5195
5244
|
}
|
|
5196
5245
|
}
|
|
5197
5246
|
function readPinnedBytes(p, pinned) {
|
|
5198
|
-
const fd =
|
|
5247
|
+
const fd = fs4.openSync(p, fs4.constants.O_RDONLY);
|
|
5199
5248
|
try {
|
|
5200
|
-
const actual = fileIdentity(
|
|
5249
|
+
const actual = fileIdentity(fs4.fstatSync(fd, { bigint: true }));
|
|
5201
5250
|
if (actual !== pinned) {
|
|
5202
5251
|
throw new ConfinementIdentityError(
|
|
5203
5252
|
`refused: "${p}" changed identity between validation and read (validated ${pinned}, opened ${actual}). The file was replaced or redirected after the confinement check, so the read was not performed.`
|
|
5204
5253
|
);
|
|
5205
5254
|
}
|
|
5206
|
-
return
|
|
5255
|
+
return fs4.readFileSync(fd);
|
|
5207
5256
|
} finally {
|
|
5208
|
-
|
|
5257
|
+
fs4.closeSync(fd);
|
|
5209
5258
|
}
|
|
5210
5259
|
}
|
|
5211
5260
|
function verifyPinnedIdentity(p, pinned) {
|
|
5212
|
-
const fd =
|
|
5261
|
+
const fd = fs4.openSync(p, fs4.constants.O_RDONLY);
|
|
5213
5262
|
try {
|
|
5214
|
-
const actual = fileIdentity(
|
|
5263
|
+
const actual = fileIdentity(fs4.fstatSync(fd, { bigint: true }));
|
|
5215
5264
|
if (actual !== pinned) {
|
|
5216
5265
|
throw new ConfinementIdentityError(
|
|
5217
5266
|
`refused: "${p}" changed identity between validation and read (validated ${pinned}, opened ${actual}). The file was replaced or redirected after the confinement check, so the read was not performed.`
|
|
5218
5267
|
);
|
|
5219
5268
|
}
|
|
5220
5269
|
} finally {
|
|
5221
|
-
|
|
5270
|
+
fs4.closeSync(fd);
|
|
5222
5271
|
}
|
|
5223
5272
|
}
|
|
5224
5273
|
function verifyStillAbsent(p) {
|
|
@@ -5236,7 +5285,7 @@ function verifyPin(p, pinned) {
|
|
|
5236
5285
|
verifyPinnedIdentity(p, pinned);
|
|
5237
5286
|
}
|
|
5238
5287
|
function indexFileSyncPinned(resolvedPath, dbPath) {
|
|
5239
|
-
const pinned = activePins?.get(pinKey(
|
|
5288
|
+
const pinned = activePins?.get(pinKey(path4.resolve(resolvedPath)));
|
|
5240
5289
|
if (pinned === void 0) {
|
|
5241
5290
|
indexFileSync(resolvedPath, dbPath);
|
|
5242
5291
|
return;
|
|
@@ -5258,21 +5307,21 @@ function indexFileSyncPinned(resolvedPath, dbPath) {
|
|
|
5258
5307
|
indexFileSync(resolvedPath, dbPath, bytes);
|
|
5259
5308
|
}
|
|
5260
5309
|
function readFileText(p) {
|
|
5261
|
-
const pinned = activePins?.get(pinKey(
|
|
5310
|
+
const pinned = activePins?.get(pinKey(path4.resolve(p)));
|
|
5262
5311
|
try {
|
|
5263
5312
|
if (pinned === ABSENT_PIN) {
|
|
5264
5313
|
verifyStillAbsent(p);
|
|
5265
5314
|
return null;
|
|
5266
5315
|
}
|
|
5267
5316
|
if (pinned !== void 0) return redactIfDotenv(p, decodeSource(readPinnedBytes(p, pinned)));
|
|
5268
|
-
return redactIfDotenv(p, decodeSource(
|
|
5317
|
+
return redactIfDotenv(p, decodeSource(fs4.readFileSync(p)));
|
|
5269
5318
|
} catch (err) {
|
|
5270
5319
|
if (err instanceof ConfinementIdentityError) throw err;
|
|
5271
5320
|
return null;
|
|
5272
5321
|
}
|
|
5273
5322
|
}
|
|
5274
5323
|
function readFileBytes(p) {
|
|
5275
|
-
const pinned = activePins?.get(pinKey(
|
|
5324
|
+
const pinned = activePins?.get(pinKey(path4.resolve(p)));
|
|
5276
5325
|
try {
|
|
5277
5326
|
if (pinned === ABSENT_PIN) {
|
|
5278
5327
|
verifyStillAbsent(p);
|
|
@@ -5283,9 +5332,9 @@ function readFileBytes(p) {
|
|
|
5283
5332
|
if (bytes.length > MAX_ZIP_INPUT_BYTES) throw new ZipInputTooLargeError(p, bytes.length, MAX_ZIP_INPUT_BYTES);
|
|
5284
5333
|
return bytes;
|
|
5285
5334
|
}
|
|
5286
|
-
const stat =
|
|
5335
|
+
const stat = fs4.statSync(p);
|
|
5287
5336
|
if (stat.size > MAX_ZIP_INPUT_BYTES) throw new ZipInputTooLargeError(p, stat.size, MAX_ZIP_INPUT_BYTES);
|
|
5288
|
-
return
|
|
5337
|
+
return fs4.readFileSync(p);
|
|
5289
5338
|
} catch (err) {
|
|
5290
5339
|
if (err instanceof ConfinementIdentityError || err instanceof ZipInputTooLargeError) throw err;
|
|
5291
5340
|
return null;
|
|
@@ -5304,7 +5353,7 @@ var STALE_WARNING = "\u26A0 STALE: index is older than the file on disk (worker
|
|
|
5304
5353
|
var DELETED_WARNING = "\u26A0 DELETED: this file is no longer on disk \u2014 what follows is what the index last saw of it";
|
|
5305
5354
|
var DELETED_TAG = "\u26A0 DELETED: file no longer on disk";
|
|
5306
5355
|
function fileIsGone(absPath) {
|
|
5307
|
-
if (!
|
|
5356
|
+
if (!path4.isAbsolute(absPath)) return false;
|
|
5308
5357
|
return fileIsAbsent(absPath);
|
|
5309
5358
|
}
|
|
5310
5359
|
function staleWarning(resolvedPath) {
|
|
@@ -5372,12 +5421,18 @@ function sumFileSizes(filePaths) {
|
|
|
5372
5421
|
let total = 0;
|
|
5373
5422
|
for (const fp of new Set(filePaths)) {
|
|
5374
5423
|
try {
|
|
5375
|
-
total += Math.min(
|
|
5424
|
+
total += Math.min(fs4.statSync(fp).size, PER_FILE_COUNTERFACTUAL_CEILING);
|
|
5376
5425
|
} catch {
|
|
5377
5426
|
}
|
|
5378
5427
|
}
|
|
5379
5428
|
return total;
|
|
5380
5429
|
}
|
|
5430
|
+
function refsSearchBaselineBytes(rows) {
|
|
5431
|
+
let total = 0;
|
|
5432
|
+
for (const ref of rows) total += Buffer.byteLength(`${refsDisplayPath(ref.filePath)}:${ref.line}: ${ref.context}
|
|
5433
|
+
`, "utf8");
|
|
5434
|
+
return total;
|
|
5435
|
+
}
|
|
5381
5436
|
function recordReadStat(kind, fullSourceBytes, emittedText, detail) {
|
|
5382
5437
|
const emittedBytes = Buffer.byteLength(emittedText, "utf8");
|
|
5383
5438
|
const bytesSaved = Math.max(1, fullSourceBytes - emittedBytes);
|
|
@@ -5550,7 +5605,7 @@ function findStructuredKeyPath(name, filePaths) {
|
|
|
5550
5605
|
if (!isYaml && !lower.endsWith(".json")) continue;
|
|
5551
5606
|
let size;
|
|
5552
5607
|
try {
|
|
5553
|
-
size =
|
|
5608
|
+
size = fs4.statSync(filePath).size;
|
|
5554
5609
|
} catch {
|
|
5555
5610
|
continue;
|
|
5556
5611
|
}
|
|
@@ -6088,7 +6143,7 @@ ${sub.text}`);
|
|
|
6088
6143
|
return { text, code: 1 };
|
|
6089
6144
|
}
|
|
6090
6145
|
function resolveAgainstProjectRoot(file, projectRoot) {
|
|
6091
|
-
return projectRoot !== void 0 && !
|
|
6146
|
+
return projectRoot !== void 0 && !path4.isAbsolute(file) ? path4.resolve(projectRoot, file) : file;
|
|
6092
6147
|
}
|
|
6093
6148
|
function literalHeadingExists(filePath, heading) {
|
|
6094
6149
|
const ordinalMatch = /^([^#\r\n]+)#(\d+)$/.exec(heading);
|
|
@@ -6112,7 +6167,7 @@ function runSection(opts) {
|
|
|
6112
6167
|
}
|
|
6113
6168
|
const result = readSection(filePath, heading, readFileText);
|
|
6114
6169
|
if (result === null) {
|
|
6115
|
-
if (!
|
|
6170
|
+
if (!fs4.existsSync(filePath)) {
|
|
6116
6171
|
return { text: `File not found: '${filePath}'`, code: 1 };
|
|
6117
6172
|
}
|
|
6118
6173
|
const ordSpec = /^(.*?)#(\d+)$/.exec(heading);
|
|
@@ -6199,7 +6254,7 @@ function runSectionCrossFile(pairs, opts) {
|
|
|
6199
6254
|
textBlocks.push(`${key}:
|
|
6200
6255
|
${sub.text}`);
|
|
6201
6256
|
}
|
|
6202
|
-
const resolvePath = (f) => opts.projectRoot !== void 0 && !
|
|
6257
|
+
const resolvePath = (f) => opts.projectRoot !== void 0 && !path4.isAbsolute(f) ? path4.resolve(opts.projectRoot, f) : f;
|
|
6203
6258
|
const text = opts.json === true ? JSON.stringify(jsonOut, null, 2) : textBlocks.join("\n\n");
|
|
6204
6259
|
if (anyFound) {
|
|
6205
6260
|
const fullSourceBytes = sumFileSizes(Array.from(distinctFiles, resolvePath));
|
|
@@ -6272,7 +6327,7 @@ function renderRefsTargets(targets, opts, {
|
|
|
6272
6327
|
const jsonOut = {};
|
|
6273
6328
|
let anyFound = false;
|
|
6274
6329
|
const lines = [];
|
|
6275
|
-
const
|
|
6330
|
+
const refRows = [];
|
|
6276
6331
|
for (const { file, symbol, key } of targets) {
|
|
6277
6332
|
const queryOpts = { name: symbol };
|
|
6278
6333
|
if (opts.excludeTests === true || opts.grep !== void 0) queryOpts.limit = REFS_TOP_SCAN_LIMIT;
|
|
@@ -6298,7 +6353,7 @@ function renderRefsTargets(targets, opts, {
|
|
|
6298
6353
|
results = results.slice(0, opts.limit ?? 100);
|
|
6299
6354
|
}
|
|
6300
6355
|
if (results.length > 0) anyFound = true;
|
|
6301
|
-
|
|
6356
|
+
refRows.push(...results);
|
|
6302
6357
|
if (opts.json === true) {
|
|
6303
6358
|
const hiddenByGrep = matchesGrep !== void 0 ? preGrepCount - (filteredTotal ?? results.length) : 0;
|
|
6304
6359
|
const withHidden = (payload) => ({ ...payload, ...annotateHiddenByGrep && hiddenByGrep > 0 ? { hiddenByGrep } : {} });
|
|
@@ -6340,7 +6395,7 @@ function renderRefsTargets(targets, opts, {
|
|
|
6340
6395
|
if (notice !== null) lines.push(` token-goat: ${notice}`);
|
|
6341
6396
|
}
|
|
6342
6397
|
}
|
|
6343
|
-
const fullSourceBytes =
|
|
6398
|
+
const fullSourceBytes = refsSearchBaselineBytes(refRows);
|
|
6344
6399
|
if (opts.json === true) {
|
|
6345
6400
|
const text2 = JSON.stringify(jsonOut, null, 2);
|
|
6346
6401
|
emit(text2);
|
|
@@ -6449,7 +6504,7 @@ function runRefsSingle(opts) {
|
|
|
6449
6504
|
}
|
|
6450
6505
|
return 1;
|
|
6451
6506
|
}
|
|
6452
|
-
const fullSourceBytes =
|
|
6507
|
+
const fullSourceBytes = refsSearchBaselineBytes(results);
|
|
6453
6508
|
if (opts.json === true) {
|
|
6454
6509
|
let payload;
|
|
6455
6510
|
if (opts.top !== void 0) {
|
|
@@ -6522,7 +6577,7 @@ function renderCallerGroups(refs, contextLines = 0) {
|
|
|
6522
6577
|
return lines;
|
|
6523
6578
|
}
|
|
6524
6579
|
function noSymbolsMessage(displayPath, resolvedPath) {
|
|
6525
|
-
if (!
|
|
6580
|
+
if (!fs4.existsSync(resolvedPath)) {
|
|
6526
6581
|
return `Could not read: ${displayPath}`;
|
|
6527
6582
|
}
|
|
6528
6583
|
const lang = unsupportedLanguageName(resolvedPath);
|
|
@@ -7361,10 +7416,10 @@ function runConflicts(opts) {
|
|
|
7361
7416
|
if (opts.path === void 0) {
|
|
7362
7417
|
files = walkProject(process.cwd()).files;
|
|
7363
7418
|
} else {
|
|
7364
|
-
const abs =
|
|
7419
|
+
const abs = path4.resolve(opts.path);
|
|
7365
7420
|
let stat;
|
|
7366
7421
|
try {
|
|
7367
|
-
stat =
|
|
7422
|
+
stat = fs4.statSync(abs);
|
|
7368
7423
|
} catch {
|
|
7369
7424
|
emitErr(`Could not read: ${opts.path}`);
|
|
7370
7425
|
return 1;
|
|
@@ -7399,7 +7454,7 @@ async function runPdfExtractText(file, pagesSpec, layout = false) {
|
|
|
7399
7454
|
if (!fileExists(file)) {
|
|
7400
7455
|
throw new Error(`Could not read: ${file}`);
|
|
7401
7456
|
}
|
|
7402
|
-
const data =
|
|
7457
|
+
const data = fs4.readFileSync(file);
|
|
7403
7458
|
const result = await extractPdfText(new Uint8Array(data), pagesSpec, layout);
|
|
7404
7459
|
return result.text;
|
|
7405
7460
|
}
|
|
@@ -7407,21 +7462,21 @@ async function runPdfOutline(file) {
|
|
|
7407
7462
|
if (!fileExists(file)) {
|
|
7408
7463
|
throw new Error(`Could not read: ${file}`);
|
|
7409
7464
|
}
|
|
7410
|
-
const data =
|
|
7465
|
+
const data = fs4.readFileSync(file);
|
|
7411
7466
|
return extractPdfOutline(new Uint8Array(data));
|
|
7412
7467
|
}
|
|
7413
7468
|
async function runPdfMeta(file) {
|
|
7414
7469
|
if (!fileExists(file)) {
|
|
7415
7470
|
throw new Error(`Could not read: ${file}`);
|
|
7416
7471
|
}
|
|
7417
|
-
const data =
|
|
7472
|
+
const data = fs4.readFileSync(file);
|
|
7418
7473
|
return extractPdfMeta(new Uint8Array(data));
|
|
7419
7474
|
}
|
|
7420
7475
|
async function runPdfLocate(file, pattern, opts) {
|
|
7421
7476
|
if (!fileExists(file)) {
|
|
7422
7477
|
throw new Error(`Could not read: ${file}`);
|
|
7423
7478
|
}
|
|
7424
|
-
const data =
|
|
7479
|
+
const data = fs4.readFileSync(file);
|
|
7425
7480
|
return locatePdfPages(new Uint8Array(data), pattern, opts);
|
|
7426
7481
|
}
|
|
7427
7482
|
async function runImageMeta(file) {
|
|
@@ -7431,7 +7486,7 @@ async function runImageMeta(file) {
|
|
|
7431
7486
|
if (!isImagePath(file)) {
|
|
7432
7487
|
throw new Error(`Not an image file: ${file}`);
|
|
7433
7488
|
}
|
|
7434
|
-
const data =
|
|
7489
|
+
const data = fs4.readFileSync(file);
|
|
7435
7490
|
const bytes = data.length;
|
|
7436
7491
|
let probe;
|
|
7437
7492
|
try {
|
|
@@ -7463,7 +7518,7 @@ async function runImageText(file) {
|
|
|
7463
7518
|
if (!isImagePath(file)) {
|
|
7464
7519
|
throw new Error(`Not an image file: ${file}`);
|
|
7465
7520
|
}
|
|
7466
|
-
const data =
|
|
7521
|
+
const data = fs4.readFileSync(file);
|
|
7467
7522
|
const ocr = await ocrImage(data);
|
|
7468
7523
|
if (ocr === null) {
|
|
7469
7524
|
if (ocrIntegrityFailed()) {
|
|
@@ -8167,7 +8222,7 @@ function runGrep(opts) {
|
|
|
8167
8222
|
if (activePins !== null) {
|
|
8168
8223
|
let realDir;
|
|
8169
8224
|
try {
|
|
8170
|
-
realDir = foldRealpath(
|
|
8225
|
+
realDir = foldRealpath(fs4.realpathSync(dir));
|
|
8171
8226
|
} catch {
|
|
8172
8227
|
return;
|
|
8173
8228
|
}
|
|
@@ -8176,12 +8231,12 @@ function runGrep(opts) {
|
|
|
8176
8231
|
visitedRealDirs.add(realDir);
|
|
8177
8232
|
}
|
|
8178
8233
|
try {
|
|
8179
|
-
for (const entry of
|
|
8234
|
+
for (const entry of fs4.readdirSync(dir)) {
|
|
8180
8235
|
if (entry.startsWith(".")) continue;
|
|
8181
|
-
const full =
|
|
8236
|
+
const full = path4.join(dir, entry);
|
|
8182
8237
|
let lst;
|
|
8183
8238
|
try {
|
|
8184
|
-
lst =
|
|
8239
|
+
lst = fs4.lstatSync(full);
|
|
8185
8240
|
} catch {
|
|
8186
8241
|
continue;
|
|
8187
8242
|
}
|
|
@@ -8189,7 +8244,7 @@ function runGrep(opts) {
|
|
|
8189
8244
|
if (lst.isSymbolicLink()) {
|
|
8190
8245
|
let real;
|
|
8191
8246
|
try {
|
|
8192
|
-
real =
|
|
8247
|
+
real = fs4.realpathSync(full);
|
|
8193
8248
|
} catch {
|
|
8194
8249
|
continue;
|
|
8195
8250
|
}
|
|
@@ -8198,7 +8253,7 @@ function runGrep(opts) {
|
|
|
8198
8253
|
}
|
|
8199
8254
|
let stat;
|
|
8200
8255
|
try {
|
|
8201
|
-
stat =
|
|
8256
|
+
stat = fs4.statSync(target);
|
|
8202
8257
|
} catch {
|
|
8203
8258
|
continue;
|
|
8204
8259
|
}
|
|
@@ -8218,16 +8273,16 @@ function runGrep(opts) {
|
|
|
8218
8273
|
emitErr(`Path not found: ${searchPath}`);
|
|
8219
8274
|
return 1;
|
|
8220
8275
|
}
|
|
8221
|
-
const stat =
|
|
8276
|
+
const stat = fs4.statSync(searchPath);
|
|
8222
8277
|
if (stat.isDirectory()) {
|
|
8223
|
-
const pinned = activePins?.get(pinKey(
|
|
8278
|
+
const pinned = activePins?.get(pinKey(path4.resolve(searchPath)));
|
|
8224
8279
|
if (pinned !== void 0) verifyPin(searchPath, pinned);
|
|
8225
8280
|
let boundaryReal;
|
|
8226
8281
|
try {
|
|
8227
|
-
boundaryReal =
|
|
8282
|
+
boundaryReal = fs4.realpathSync(searchPath);
|
|
8228
8283
|
} catch (err) {
|
|
8229
8284
|
if (pinned === void 0) {
|
|
8230
|
-
boundaryReal =
|
|
8285
|
+
boundaryReal = path4.resolve(searchPath);
|
|
8231
8286
|
} else {
|
|
8232
8287
|
throw new ConfinementIdentityError(
|
|
8233
8288
|
`refused: "${searchPath}" could not be resolved after validation (${String(err)}). The path may have been replaced or redirected after the confinement check, so the search was not performed.`
|
|
@@ -8358,7 +8413,7 @@ function runConfigGet(opts) {
|
|
|
8358
8413
|
emit(value);
|
|
8359
8414
|
return 0;
|
|
8360
8415
|
}
|
|
8361
|
-
const ext =
|
|
8416
|
+
const ext = path4.extname(opts.file).toLowerCase();
|
|
8362
8417
|
if (ext === ".json") {
|
|
8363
8418
|
try {
|
|
8364
8419
|
let obj = JSON.parse(text);
|
|
@@ -8481,7 +8536,7 @@ function runExports(opts) {
|
|
|
8481
8536
|
names.push(s.name);
|
|
8482
8537
|
}
|
|
8483
8538
|
}
|
|
8484
|
-
const ext =
|
|
8539
|
+
const ext = path4.extname(opts.file).toLowerCase();
|
|
8485
8540
|
const text = readFileText(diskPath);
|
|
8486
8541
|
if (text === null && symbols.length === 0) {
|
|
8487
8542
|
emitErr(`Could not read: ${opts.file}`);
|
|
@@ -8818,9 +8873,9 @@ function extractImports(text, ext) {
|
|
|
8818
8873
|
return found;
|
|
8819
8874
|
}
|
|
8820
8875
|
function importsExtensionFor(filePath) {
|
|
8821
|
-
const base =
|
|
8876
|
+
const base = path4.basename(filePath).toLowerCase();
|
|
8822
8877
|
if (base === "makefile" || base === "gnumakefile" || base === "bsdmakefile") return ".mk";
|
|
8823
|
-
return
|
|
8878
|
+
return path4.extname(filePath);
|
|
8824
8879
|
}
|
|
8825
8880
|
function runImports(opts) {
|
|
8826
8881
|
const multiFiles = parseMultiFileSpec(opts.file);
|
|
@@ -8912,7 +8967,7 @@ async function runSemantic(query, opts) {
|
|
|
8912
8967
|
}
|
|
8913
8968
|
const n = opts.limit !== void 0 && Number.isFinite(opts.limit) ? opts.limit : 20;
|
|
8914
8969
|
if (opts.projectRoot !== void 0) {
|
|
8915
|
-
if (!
|
|
8970
|
+
if (!path4.isAbsolute(opts.projectRoot) || !fs4.existsSync(opts.projectRoot) || !fs4.statSync(opts.projectRoot).isDirectory()) {
|
|
8916
8971
|
const message = `token-goat: projectRoot must be an absolute, existing directory, got '${opts.projectRoot}'`;
|
|
8917
8972
|
if (opts.json === true) {
|
|
8918
8973
|
return { text: JSON.stringify({ error: message }, null, 2), code: 1 };
|
|
@@ -9150,6 +9205,318 @@ function runNoteList(opts = {}) {
|
|
|
9150
9205
|
return { text: lines.join("\n"), code: 0 };
|
|
9151
9206
|
}
|
|
9152
9207
|
|
|
9208
|
+
// src/import_graph.ts
|
|
9209
|
+
import * as fs5 from "node:fs";
|
|
9210
|
+
import * as path5 from "node:path";
|
|
9211
|
+
var DIRECT_PROBE_EXTENSIONS = ["", ".ts", ".tsx", ".js", ".jsx", ".mts", ".mjs", ".cjs", ".cts", ".py"];
|
|
9212
|
+
var INDEX_PROBE_EXTENSIONS = [".ts", ".js", ".tsx", ".jsx", ".mts", ".cts"];
|
|
9213
|
+
function buildImportGraph(cwd) {
|
|
9214
|
+
const files = getTrackedFiles(cwd);
|
|
9215
|
+
const filesByFoldedPath = /* @__PURE__ */ new Map();
|
|
9216
|
+
for (const f of files) filesByFoldedPath.set(foldPath(f), f);
|
|
9217
|
+
const resolve5 = (fromFile, spec) => {
|
|
9218
|
+
if (!spec.startsWith(".")) return null;
|
|
9219
|
+
const dir = path5.dirname(fromFile);
|
|
9220
|
+
const strippedSpec = spec.replace(/\.(m?js|cjs)$/, "");
|
|
9221
|
+
const base = path5.resolve(dir, strippedSpec);
|
|
9222
|
+
for (const ext of DIRECT_PROBE_EXTENSIONS) {
|
|
9223
|
+
const match = filesByFoldedPath.get(foldPath(base + ext));
|
|
9224
|
+
if (match !== void 0) return match;
|
|
9225
|
+
}
|
|
9226
|
+
const idx = path5.join(base, "index");
|
|
9227
|
+
for (const ext of INDEX_PROBE_EXTENSIONS) {
|
|
9228
|
+
const match = filesByFoldedPath.get(foldPath(idx + ext));
|
|
9229
|
+
if (match !== void 0) return match;
|
|
9230
|
+
}
|
|
9231
|
+
return null;
|
|
9232
|
+
};
|
|
9233
|
+
const graph = /* @__PURE__ */ new Map();
|
|
9234
|
+
const importedBy = /* @__PURE__ */ new Map();
|
|
9235
|
+
for (const file of files) {
|
|
9236
|
+
let text;
|
|
9237
|
+
try {
|
|
9238
|
+
text = fs5.readFileSync(file, "utf8");
|
|
9239
|
+
} catch {
|
|
9240
|
+
continue;
|
|
9241
|
+
}
|
|
9242
|
+
const internal = [];
|
|
9243
|
+
for (const spec of extractImports(text, importsExtensionFor(file))) {
|
|
9244
|
+
const resolved = resolve5(file, spec);
|
|
9245
|
+
if (resolved === null) continue;
|
|
9246
|
+
internal.push(resolved);
|
|
9247
|
+
let importers = importedBy.get(resolved);
|
|
9248
|
+
if (importers === void 0) {
|
|
9249
|
+
importers = /* @__PURE__ */ new Set();
|
|
9250
|
+
importedBy.set(resolved, importers);
|
|
9251
|
+
}
|
|
9252
|
+
importers.add(file);
|
|
9253
|
+
}
|
|
9254
|
+
graph.set(file, internal);
|
|
9255
|
+
}
|
|
9256
|
+
return { files, graph, importedBy, resolve: resolve5 };
|
|
9257
|
+
}
|
|
9258
|
+
|
|
9259
|
+
// src/modules.ts
|
|
9260
|
+
var WEAK_MODULARITY = 0.3;
|
|
9261
|
+
var MAX_PASSES = 32;
|
|
9262
|
+
var GAIN_EPSILON = 1e-12;
|
|
9263
|
+
function emptyGraph(n) {
|
|
9264
|
+
return { n, adj: Array.from({ length: n }, () => /* @__PURE__ */ new Map()), degree: new Array(n).fill(0), m: 0 };
|
|
9265
|
+
}
|
|
9266
|
+
function addEdge(g, a, b, w) {
|
|
9267
|
+
if (a === b) {
|
|
9268
|
+
g.adj[a].set(a, (g.adj[a].get(a) ?? 0) + w);
|
|
9269
|
+
g.degree[a] += 2 * w;
|
|
9270
|
+
} else {
|
|
9271
|
+
g.adj[a].set(b, (g.adj[a].get(b) ?? 0) + w);
|
|
9272
|
+
g.adj[b].set(a, (g.adj[b].get(a) ?? 0) + w);
|
|
9273
|
+
g.degree[a] += w;
|
|
9274
|
+
g.degree[b] += w;
|
|
9275
|
+
}
|
|
9276
|
+
g.m += w;
|
|
9277
|
+
}
|
|
9278
|
+
function localMoving(g) {
|
|
9279
|
+
const community = Array.from({ length: g.n }, (_, i) => i);
|
|
9280
|
+
const tot = g.degree.slice();
|
|
9281
|
+
const twoM = 2 * g.m;
|
|
9282
|
+
let movedEver = false;
|
|
9283
|
+
if (twoM === 0) return { community, moved: false };
|
|
9284
|
+
for (let pass = 0; pass < MAX_PASSES; pass++) {
|
|
9285
|
+
let improved = false;
|
|
9286
|
+
for (let i = 0; i < g.n; i++) {
|
|
9287
|
+
const ki = g.degree[i];
|
|
9288
|
+
const ci = community[i];
|
|
9289
|
+
const links = /* @__PURE__ */ new Map();
|
|
9290
|
+
for (const [j, w] of g.adj[i]) {
|
|
9291
|
+
if (j === i) continue;
|
|
9292
|
+
const cj = community[j];
|
|
9293
|
+
links.set(cj, (links.get(cj) ?? 0) + w);
|
|
9294
|
+
}
|
|
9295
|
+
tot[ci] = tot[ci] - ki;
|
|
9296
|
+
let bestC = ci;
|
|
9297
|
+
let bestGain = (links.get(ci) ?? 0) - tot[ci] * ki / twoM;
|
|
9298
|
+
for (const c of [...links.keys()].sort((a, b) => a - b)) {
|
|
9299
|
+
if (c === ci) continue;
|
|
9300
|
+
const gain = links.get(c) - tot[c] * ki / twoM;
|
|
9301
|
+
if (gain > bestGain + GAIN_EPSILON) {
|
|
9302
|
+
bestGain = gain;
|
|
9303
|
+
bestC = c;
|
|
9304
|
+
}
|
|
9305
|
+
}
|
|
9306
|
+
tot[bestC] = tot[bestC] + ki;
|
|
9307
|
+
community[i] = bestC;
|
|
9308
|
+
if (bestC !== ci) {
|
|
9309
|
+
improved = true;
|
|
9310
|
+
movedEver = true;
|
|
9311
|
+
}
|
|
9312
|
+
}
|
|
9313
|
+
if (!improved) break;
|
|
9314
|
+
}
|
|
9315
|
+
return { community, moved: movedEver };
|
|
9316
|
+
}
|
|
9317
|
+
function densify(community) {
|
|
9318
|
+
const firstMember = /* @__PURE__ */ new Map();
|
|
9319
|
+
for (let i = 0; i < community.length; i++) {
|
|
9320
|
+
const c = community[i];
|
|
9321
|
+
if (!firstMember.has(c)) firstMember.set(c, i);
|
|
9322
|
+
}
|
|
9323
|
+
const ordered = [...firstMember.entries()].sort((a, b) => a[1] - b[1]).map(([c]) => c);
|
|
9324
|
+
const remap = /* @__PURE__ */ new Map();
|
|
9325
|
+
ordered.forEach((c, idx) => remap.set(c, idx));
|
|
9326
|
+
return { dense: community.map((c) => remap.get(c)), count: ordered.length };
|
|
9327
|
+
}
|
|
9328
|
+
function modularityOf(g, partition) {
|
|
9329
|
+
const twoM = 2 * g.m;
|
|
9330
|
+
if (twoM === 0) return null;
|
|
9331
|
+
const internal = /* @__PURE__ */ new Map();
|
|
9332
|
+
const tot = /* @__PURE__ */ new Map();
|
|
9333
|
+
for (let i = 0; i < g.n; i++) {
|
|
9334
|
+
const ci = partition[i];
|
|
9335
|
+
tot.set(ci, (tot.get(ci) ?? 0) + g.degree[i]);
|
|
9336
|
+
for (const [j, w] of g.adj[i]) {
|
|
9337
|
+
if (j < i) continue;
|
|
9338
|
+
if (partition[j] === ci) internal.set(ci, (internal.get(ci) ?? 0) + w);
|
|
9339
|
+
}
|
|
9340
|
+
}
|
|
9341
|
+
let q = 0;
|
|
9342
|
+
for (const [c, t] of tot) {
|
|
9343
|
+
q += 2 * (internal.get(c) ?? 0) / twoM - (t / twoM) ** 2;
|
|
9344
|
+
}
|
|
9345
|
+
return q;
|
|
9346
|
+
}
|
|
9347
|
+
function louvain(g) {
|
|
9348
|
+
let current = g;
|
|
9349
|
+
let mapping = Array.from({ length: g.n }, (_, i) => i);
|
|
9350
|
+
for (let level = 0; level < MAX_PASSES; level++) {
|
|
9351
|
+
const { community, moved } = localMoving(current);
|
|
9352
|
+
const { dense, count } = densify(community);
|
|
9353
|
+
mapping = mapping.map((c) => dense[c]);
|
|
9354
|
+
if (!moved || count === current.n) break;
|
|
9355
|
+
const next = emptyGraph(count);
|
|
9356
|
+
for (let i = 0; i < current.n; i++) {
|
|
9357
|
+
for (const [j, w] of current.adj[i]) {
|
|
9358
|
+
if (j < i) continue;
|
|
9359
|
+
addEdge(next, dense[i], dense[j], w);
|
|
9360
|
+
}
|
|
9361
|
+
}
|
|
9362
|
+
current = next;
|
|
9363
|
+
}
|
|
9364
|
+
return mapping;
|
|
9365
|
+
}
|
|
9366
|
+
function commonDirLabel(files) {
|
|
9367
|
+
const dirs = new Set(files.map(dirOf));
|
|
9368
|
+
if (dirs.size === 1) {
|
|
9369
|
+
const only = [...dirs][0];
|
|
9370
|
+
return only === "." ? "." : `${only}/`;
|
|
9371
|
+
}
|
|
9372
|
+
const segmentLists = files.map((f) => {
|
|
9373
|
+
const parts = f.split("/");
|
|
9374
|
+
parts.pop();
|
|
9375
|
+
return parts;
|
|
9376
|
+
});
|
|
9377
|
+
const first = segmentLists[0];
|
|
9378
|
+
if (first === void 0) return null;
|
|
9379
|
+
const prefix = [];
|
|
9380
|
+
for (let i = 0; i < first.length; i++) {
|
|
9381
|
+
const seg = first[i];
|
|
9382
|
+
if (!segmentLists.every((s) => s[i] === seg)) break;
|
|
9383
|
+
prefix.push(seg);
|
|
9384
|
+
}
|
|
9385
|
+
return prefix.length === 0 ? null : `${prefix.join("/")}/`;
|
|
9386
|
+
}
|
|
9387
|
+
function dirOf(file) {
|
|
9388
|
+
const idx = file.lastIndexOf("/");
|
|
9389
|
+
return idx === -1 ? "." : file.slice(0, idx);
|
|
9390
|
+
}
|
|
9391
|
+
function detectModules(imports, cwd, top) {
|
|
9392
|
+
const { files, graph } = imports;
|
|
9393
|
+
const root = getDisplayRoot(cwd);
|
|
9394
|
+
const degreeOf = /* @__PURE__ */ new Map();
|
|
9395
|
+
const bump = (f) => {
|
|
9396
|
+
degreeOf.set(f, (degreeOf.get(f) ?? 0) + 1);
|
|
9397
|
+
};
|
|
9398
|
+
for (const [from, targets] of graph) {
|
|
9399
|
+
for (const to of targets) {
|
|
9400
|
+
if (from === to) continue;
|
|
9401
|
+
bump(from);
|
|
9402
|
+
bump(to);
|
|
9403
|
+
}
|
|
9404
|
+
}
|
|
9405
|
+
const connected = files.filter((f) => (degreeOf.get(f) ?? 0) > 0);
|
|
9406
|
+
const isolatedCount = files.length - connected.length;
|
|
9407
|
+
if (connected.length === 0) {
|
|
9408
|
+
return { modules: [], modulesTotal: 0, modularity: null, isolatedCount, crossImports: [], crossImportsTotal: 0, noEdges: true };
|
|
9409
|
+
}
|
|
9410
|
+
const ordered = [...connected].sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
9411
|
+
const idOf = /* @__PURE__ */ new Map();
|
|
9412
|
+
ordered.forEach((f, i) => idOf.set(f, i));
|
|
9413
|
+
const g = emptyGraph(ordered.length);
|
|
9414
|
+
const pairWeight = /* @__PURE__ */ new Map();
|
|
9415
|
+
for (const [from, targets] of graph) {
|
|
9416
|
+
const a = idOf.get(from);
|
|
9417
|
+
if (a === void 0) continue;
|
|
9418
|
+
for (const to of targets) {
|
|
9419
|
+
const b = idOf.get(to);
|
|
9420
|
+
if (b === void 0 || a === b) continue;
|
|
9421
|
+
const key = a < b ? `${a}:${b}` : `${b}:${a}`;
|
|
9422
|
+
pairWeight.set(key, (pairWeight.get(key) ?? 0) + 1);
|
|
9423
|
+
}
|
|
9424
|
+
}
|
|
9425
|
+
for (const key of [...pairWeight.keys()].sort()) {
|
|
9426
|
+
const [a, b] = key.split(":").map(Number);
|
|
9427
|
+
addEdge(g, a, b, pairWeight.get(key));
|
|
9428
|
+
}
|
|
9429
|
+
const partition = louvain(g);
|
|
9430
|
+
const modularity = modularityOf(g, partition);
|
|
9431
|
+
const membersOf = /* @__PURE__ */ new Map();
|
|
9432
|
+
for (let i = 0; i < ordered.length; i++) {
|
|
9433
|
+
const c = partition[i];
|
|
9434
|
+
const list = membersOf.get(c);
|
|
9435
|
+
if (list === void 0) membersOf.set(c, [ordered[i]]);
|
|
9436
|
+
else list.push(ordered[i]);
|
|
9437
|
+
}
|
|
9438
|
+
const inModuleDegree = /* @__PURE__ */ new Map();
|
|
9439
|
+
for (const [from, targets] of graph) {
|
|
9440
|
+
const a = idOf.get(from);
|
|
9441
|
+
if (a === void 0) continue;
|
|
9442
|
+
for (const to of targets) {
|
|
9443
|
+
const b = idOf.get(to);
|
|
9444
|
+
if (b === void 0 || a === b || partition[a] !== partition[b]) continue;
|
|
9445
|
+
inModuleDegree.set(from, (inModuleDegree.get(from) ?? 0) + 1);
|
|
9446
|
+
inModuleDegree.set(to, (inModuleDegree.get(to) ?? 0) + 1);
|
|
9447
|
+
}
|
|
9448
|
+
}
|
|
9449
|
+
const built = [...membersOf.entries()].map(([c, absFiles]) => {
|
|
9450
|
+
const display = absFiles.map((f) => toDisplayPath(root, f)).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
9451
|
+
const coreAbs = [...absFiles].sort((a, b) => (inModuleDegree.get(b) ?? 0) - (inModuleDegree.get(a) ?? 0) || (a < b ? -1 : a > b ? 1 : 0))[0];
|
|
9452
|
+
return { community: c, core: toDisplayPath(root, coreAbs), commonDir: commonDirLabel(display), files: display, directories: new Set(display.map(dirOf)).size };
|
|
9453
|
+
}).sort((a, b) => b.files.length - a.files.length || (a.core < b.core ? -1 : a.core > b.core ? 1 : 0) || (a.files[0] < b.files[0] ? -1 : 1));
|
|
9454
|
+
const indexOfCommunity = /* @__PURE__ */ new Map();
|
|
9455
|
+
built.forEach((m, i) => indexOfCommunity.set(m.community, i + 1));
|
|
9456
|
+
const coreOfIndex = /* @__PURE__ */ new Map();
|
|
9457
|
+
built.forEach((m, i) => coreOfIndex.set(i + 1, m.core));
|
|
9458
|
+
const crossCount = /* @__PURE__ */ new Map();
|
|
9459
|
+
for (const [from, targets] of graph) {
|
|
9460
|
+
const a = idOf.get(from);
|
|
9461
|
+
if (a === void 0) continue;
|
|
9462
|
+
const ca = indexOfCommunity.get(partition[a]);
|
|
9463
|
+
if (ca === void 0) continue;
|
|
9464
|
+
for (const to of targets) {
|
|
9465
|
+
const b = idOf.get(to);
|
|
9466
|
+
if (b === void 0) continue;
|
|
9467
|
+
const cb = indexOfCommunity.get(partition[b]);
|
|
9468
|
+
if (cb === void 0 || ca === cb) continue;
|
|
9469
|
+
const key = `${ca}:${cb}`;
|
|
9470
|
+
crossCount.set(key, (crossCount.get(key) ?? 0) + 1);
|
|
9471
|
+
}
|
|
9472
|
+
}
|
|
9473
|
+
const allCross = [...crossCount.entries()].map(([key, imports2]) => {
|
|
9474
|
+
const [fromIndex, toIndex] = key.split(":").map(Number);
|
|
9475
|
+
return { fromIndex, toIndex, fromCore: coreOfIndex.get(fromIndex), toCore: coreOfIndex.get(toIndex), imports: imports2 };
|
|
9476
|
+
}).sort((a, b) => b.imports - a.imports || a.fromIndex - b.fromIndex || a.toIndex - b.toIndex);
|
|
9477
|
+
const modules = built.slice(0, top).map((m, i) => ({ index: i + 1, core: m.core, commonDir: m.commonDir, files: m.files, size: m.files.length, directories: m.directories }));
|
|
9478
|
+
return {
|
|
9479
|
+
modules,
|
|
9480
|
+
modulesTotal: built.length,
|
|
9481
|
+
modularity,
|
|
9482
|
+
isolatedCount,
|
|
9483
|
+
crossImports: allCross.slice(0, top),
|
|
9484
|
+
crossImportsTotal: allCross.length,
|
|
9485
|
+
noEdges: false
|
|
9486
|
+
};
|
|
9487
|
+
}
|
|
9488
|
+
function renderModules(result, top) {
|
|
9489
|
+
const lines = [];
|
|
9490
|
+
if (result.noEdges) {
|
|
9491
|
+
lines.push(`modules: none. No file in this project imports another by a relative path, so there is nothing to group (${countNoun(result.isolatedCount, "file")} checked).`);
|
|
9492
|
+
return lines;
|
|
9493
|
+
}
|
|
9494
|
+
const q = result.modularity;
|
|
9495
|
+
const strength = q === null ? "" : q < WEAK_MODULARITY ? `, modularity ${q.toFixed(2)} -- weak, so treat this grouping as a hint rather than a finding` : `, modularity ${q.toFixed(2)}`;
|
|
9496
|
+
lines.push(result.modules.length < result.modulesTotal ? `modules (top ${result.modules.length} of ${result.modulesTotal}${strength}):` : `modules (${result.modulesTotal} found${strength}):`);
|
|
9497
|
+
for (const m of result.modules) {
|
|
9498
|
+
const where = m.commonDir === null ? `across ${m.directories} directories` : m.commonDir === "." ? "all in the repository root" : `all in ${m.commonDir}`;
|
|
9499
|
+
lines.push(` #${m.index} ${m.size} files ${m.core} (${where})`);
|
|
9500
|
+
}
|
|
9501
|
+
if (result.isolatedCount > 0) {
|
|
9502
|
+
lines.push(` ${result.isolatedCount} files are in no module (they neither import nor are imported within the project).`);
|
|
9503
|
+
}
|
|
9504
|
+
if (result.crossImportsTotal === 0) {
|
|
9505
|
+
lines.push("cross-module imports: none. Every import stays inside its own module.");
|
|
9506
|
+
} else {
|
|
9507
|
+
lines.push(
|
|
9508
|
+
result.crossImports.length < result.crossImportsTotal ? `cross-module imports (top ${result.crossImports.length} of ${result.crossImportsTotal} pairs):` : `cross-module imports (${result.crossImportsTotal} pairs):`
|
|
9509
|
+
);
|
|
9510
|
+
for (const c of result.crossImports) {
|
|
9511
|
+
lines.push(` ${c.imports} imports #${c.fromIndex} ${c.fromCore} -> #${c.toIndex} ${c.toCore}`);
|
|
9512
|
+
}
|
|
9513
|
+
}
|
|
9514
|
+
if (result.modules.length < result.modulesTotal && result.crossImports.some((c) => c.fromIndex > top || c.toIndex > top)) {
|
|
9515
|
+
lines.push(` (a #N above ${top} refers to a module the --top cap left out; raise --top to see it.)`);
|
|
9516
|
+
}
|
|
9517
|
+
return lines;
|
|
9518
|
+
}
|
|
9519
|
+
|
|
9153
9520
|
// src/graph_commands.ts
|
|
9154
9521
|
var DEFAULT_REF_QUERY_LIMIT = 500;
|
|
9155
9522
|
var ALL_SYMBOLS_IN_FILE_LIMIT = 1e4;
|
|
@@ -10237,53 +10604,11 @@ function runArch(opts) {
|
|
|
10237
10604
|
}
|
|
10238
10605
|
const cwd = opts.cwd ?? process.cwd();
|
|
10239
10606
|
const top = opts.top ?? 10;
|
|
10240
|
-
const files =
|
|
10607
|
+
const { files, graph, importedBy, resolve: resolve5 } = buildImportGraph(cwd);
|
|
10241
10608
|
if (files.length === 0 && opts.json !== true) {
|
|
10242
10609
|
emit2(`no tracked files found under '${toDisplayPath(getDisplayRoot(cwd), cwd)}' (is it a git repo?). Nothing to analyse.`);
|
|
10243
10610
|
return 0;
|
|
10244
10611
|
}
|
|
10245
|
-
const filesByFoldedPath = /* @__PURE__ */ new Map();
|
|
10246
|
-
for (const f of files) filesByFoldedPath.set(foldPath(f), f);
|
|
10247
|
-
const graph = /* @__PURE__ */ new Map();
|
|
10248
|
-
const importedBy = /* @__PURE__ */ new Map();
|
|
10249
|
-
const resolveRelImport = (fromFile, spec) => {
|
|
10250
|
-
if (!spec.startsWith(".")) return null;
|
|
10251
|
-
const dir = path6.dirname(fromFile);
|
|
10252
|
-
const strippedSpec = spec.replace(/\.(m?js|cjs)$/, "");
|
|
10253
|
-
const base = path6.resolve(dir, strippedSpec);
|
|
10254
|
-
for (const ext of ["", ".ts", ".tsx", ".js", ".jsx", ".mts", ".mjs", ".cjs", ".cts", ".py"]) {
|
|
10255
|
-
const candidate = base + ext;
|
|
10256
|
-
const match = filesByFoldedPath.get(foldPath(candidate));
|
|
10257
|
-
if (match !== void 0) return match;
|
|
10258
|
-
}
|
|
10259
|
-
const idx = path6.join(base, "index");
|
|
10260
|
-
for (const ext of [".ts", ".js", ".tsx", ".jsx", ".mts", ".cts"]) {
|
|
10261
|
-
const candidate = idx + ext;
|
|
10262
|
-
const match = filesByFoldedPath.get(foldPath(candidate));
|
|
10263
|
-
if (match !== void 0) return match;
|
|
10264
|
-
}
|
|
10265
|
-
return null;
|
|
10266
|
-
};
|
|
10267
|
-
for (const file of files) {
|
|
10268
|
-
let text;
|
|
10269
|
-
try {
|
|
10270
|
-
text = fs6.readFileSync(file, "utf8");
|
|
10271
|
-
} catch {
|
|
10272
|
-
continue;
|
|
10273
|
-
}
|
|
10274
|
-
const ext = importsExtensionFor(file);
|
|
10275
|
-
const rawImports = extractImports(text, ext);
|
|
10276
|
-
const internal = [];
|
|
10277
|
-
for (const spec of rawImports) {
|
|
10278
|
-
const resolved = resolveRelImport(file, spec);
|
|
10279
|
-
if (resolved !== null) {
|
|
10280
|
-
internal.push(resolved);
|
|
10281
|
-
if (!importedBy.has(resolved)) importedBy.set(resolved, /* @__PURE__ */ new Set());
|
|
10282
|
-
importedBy.get(resolved).add(file);
|
|
10283
|
-
}
|
|
10284
|
-
}
|
|
10285
|
-
graph.set(file, internal);
|
|
10286
|
-
}
|
|
10287
10612
|
const allHubs = [...importedBy.entries()].sort((a, b) => b[1].size - a[1].size).map(([f, importers]) => ({ file: f, importedBy: importers.size }));
|
|
10288
10613
|
const hubsTotal = allHubs.length;
|
|
10289
10614
|
const hubs = allHubs.slice(0, top);
|
|
@@ -10291,8 +10616,10 @@ function runArch(opts) {
|
|
|
10291
10616
|
const entryPointsTotal = allEntryPoints.length;
|
|
10292
10617
|
const entryPoints = allEntryPoints.slice(0, top);
|
|
10293
10618
|
const { cycles, truncated: cyclesTruncated } = findCyclesCapped(graph);
|
|
10619
|
+
const moduleResult = opts.modules === true ? detectModules({ files, graph, importedBy, resolve: resolve5 }, cwd, top) : null;
|
|
10294
10620
|
if (opts.json === true) {
|
|
10295
|
-
|
|
10621
|
+
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 };
|
|
10622
|
+
emit2(JSON.stringify({ hubs, hubsTotal, hubsTruncated: hubs.length < hubsTotal, entryPoints, entryPointsTotal, entryPointsTruncated: entryPoints.length < entryPointsTotal, cycles, ...cyclesTruncated ? { cyclesTruncated: true } : {}, ...modulePayload }, null, 2));
|
|
10296
10623
|
return 0;
|
|
10297
10624
|
}
|
|
10298
10625
|
emit2(hubs.length < hubsTotal ? `hubs (top ${hubs.length} of ${hubsTotal} most-imported):` : `hubs (${hubsTotal} most-imported):`);
|
|
@@ -10301,6 +10628,7 @@ function runArch(opts) {
|
|
|
10301
10628
|
for (const e of entryPoints) emit2(` ${toDisplayPath(getDisplayRoot(opts.cwd), e.file)}`);
|
|
10302
10629
|
emit2(cyclesTruncated ? `cycles (first ${cycles.length}, truncated at the ${MAX_CYCLES}-cycle enumeration limit: more cycles exist):` : `cycles (${cycles.length} found):`);
|
|
10303
10630
|
for (const c of cycles) emit2(` ${c.map((f) => toDisplayPath(getDisplayRoot(opts.cwd), f)).join(" -> ")}`);
|
|
10631
|
+
if (moduleResult !== null) for (const line of renderModules(moduleResult, top)) emit2(line);
|
|
10304
10632
|
return 0;
|
|
10305
10633
|
}
|
|
10306
10634
|
function runBlame(opts) {
|
|
@@ -10556,10 +10884,10 @@ function resolveHandoff(name, opts = {}) {
|
|
|
10556
10884
|
}
|
|
10557
10885
|
|
|
10558
10886
|
export {
|
|
10559
|
-
getTrackedFiles,
|
|
10560
10887
|
extractSection,
|
|
10561
10888
|
readSection,
|
|
10562
10889
|
listSections,
|
|
10890
|
+
buildImportGraph,
|
|
10563
10891
|
ALL_SYMBOLS_IN_FILE_LIMIT,
|
|
10564
10892
|
enclosingSymbol,
|
|
10565
10893
|
runCallers,
|
|
@@ -10651,5 +10979,5 @@ export {
|
|
|
10651
10979
|
/*! Bundled license information:
|
|
10652
10980
|
|
|
10653
10981
|
js-yaml/dist/js-yaml.mjs:
|
|
10654
|
-
(*! js-yaml 5.
|
|
10982
|
+
(*! js-yaml 5.4.1 https://github.com/nodeca/js-yaml @license MIT *)
|
|
10655
10983
|
*/
|