hillclimb 0.5.3 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +318 -11
- package/dist/pattern-worker.js +18 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2419,6 +2419,48 @@ async function readFileContent(file) {
|
|
|
2419
2419
|
}
|
|
2420
2420
|
}
|
|
2421
2421
|
|
|
2422
|
+
// src/middleware/large-file.ts
|
|
2423
|
+
import { constants as bufferConstants } from "buffer";
|
|
2424
|
+
var MAX_STRINGIFIABLE_BYTES = bufferConstants.MAX_STRING_LENGTH;
|
|
2425
|
+
var largeFileThreshold = MAX_STRINGIFIABLE_BYTES;
|
|
2426
|
+
function getLargeFileThreshold() {
|
|
2427
|
+
return largeFileThreshold;
|
|
2428
|
+
}
|
|
2429
|
+
var NEWLINE = 10;
|
|
2430
|
+
var OVERSIZED_LINE_PLACEHOLDER = '{"_hillclimb_omitted":"line exceeded max string length; dropped to allow redaction"}';
|
|
2431
|
+
function redactBufferByLine(buffer, redactLine, options = {}) {
|
|
2432
|
+
const maxLineBytes = options.maxLineBytes ?? MAX_STRINGIFIABLE_BYTES;
|
|
2433
|
+
const oversizedPlaceholder = options.oversizedPlaceholder ?? OVERSIZED_LINE_PLACEHOLDER;
|
|
2434
|
+
const pieces = [];
|
|
2435
|
+
const newlineBuf = Buffer.from([NEWLINE]);
|
|
2436
|
+
let totalCount = 0;
|
|
2437
|
+
let oversizedLines = 0;
|
|
2438
|
+
let start = 0;
|
|
2439
|
+
let first = true;
|
|
2440
|
+
for (; ; ) {
|
|
2441
|
+
const nl = buffer.indexOf(NEWLINE, start);
|
|
2442
|
+
const end = nl === -1 ? buffer.length : nl;
|
|
2443
|
+
const slice = buffer.subarray(start, end);
|
|
2444
|
+
if (!first) pieces.push(newlineBuf);
|
|
2445
|
+
first = false;
|
|
2446
|
+
if (slice.length > maxLineBytes) {
|
|
2447
|
+
oversizedLines++;
|
|
2448
|
+
pieces.push(Buffer.from(oversizedPlaceholder, "utf-8"));
|
|
2449
|
+
} else {
|
|
2450
|
+
const { value, count } = redactLine(slice.toString("utf-8"));
|
|
2451
|
+
totalCount += count;
|
|
2452
|
+
pieces.push(Buffer.from(value, "utf-8"));
|
|
2453
|
+
}
|
|
2454
|
+
if (nl === -1) break;
|
|
2455
|
+
start = nl + 1;
|
|
2456
|
+
}
|
|
2457
|
+
return {
|
|
2458
|
+
content: Buffer.concat(pieces),
|
|
2459
|
+
count: totalCount,
|
|
2460
|
+
oversizedLines
|
|
2461
|
+
};
|
|
2462
|
+
}
|
|
2463
|
+
|
|
2422
2464
|
// src/middleware/patterns.json
|
|
2423
2465
|
var patterns_default = {
|
|
2424
2466
|
patterns: [
|
|
@@ -10475,6 +10517,22 @@ var patterns_default = {
|
|
|
10475
10517
|
]
|
|
10476
10518
|
};
|
|
10477
10519
|
|
|
10520
|
+
// src/middleware/patterns-local.json
|
|
10521
|
+
var patterns_local_default = {
|
|
10522
|
+
patterns: [
|
|
10523
|
+
{
|
|
10524
|
+
name: "Hugging Face User Access Token",
|
|
10525
|
+
regex: "(?:(?<![A-Za-z0-9])|(?<=\\\\[nrt]))hf_[A-Za-z0-9]{34,40}",
|
|
10526
|
+
confidence: "high"
|
|
10527
|
+
},
|
|
10528
|
+
{
|
|
10529
|
+
name: "Hugging Face Organization API Token",
|
|
10530
|
+
regex: "(?:(?<![A-Za-z0-9])|(?<=\\\\[nrt]))api_org_[A-Za-z0-9]{34,40}",
|
|
10531
|
+
confidence: "high"
|
|
10532
|
+
}
|
|
10533
|
+
]
|
|
10534
|
+
};
|
|
10535
|
+
|
|
10478
10536
|
// src/middleware/pattern-core.ts
|
|
10479
10537
|
var DELIMITER_SUFFIX = /\(=\| =\|:\| :\)$/;
|
|
10480
10538
|
var HAS_VALUE_MATCHER = /[[{+*]|\\[wdWDsS]/;
|
|
@@ -10510,7 +10568,8 @@ function countCaptureGroups(source) {
|
|
|
10510
10568
|
}
|
|
10511
10569
|
function compilePatterns() {
|
|
10512
10570
|
const patterns = [];
|
|
10513
|
-
|
|
10571
|
+
const allPatterns = [...patterns_default.patterns, ...patterns_local_default.patterns];
|
|
10572
|
+
for (const p7 of allPatterns) {
|
|
10514
10573
|
if (p7.confidence !== "high") continue;
|
|
10515
10574
|
if (DELIMITER_SUFFIX.test(p7.regex)) continue;
|
|
10516
10575
|
if (!HAS_VALUE_MATCHER.test(p7.regex)) continue;
|
|
@@ -10641,6 +10700,19 @@ function processFiles(files) {
|
|
|
10641
10700
|
}
|
|
10642
10701
|
|
|
10643
10702
|
// src/middleware/pattern-redact.ts
|
|
10703
|
+
function redactPatternLine(line, patterns, memo, isJsonl) {
|
|
10704
|
+
if (isJsonl) {
|
|
10705
|
+
if (!line.trim()) return { value: line, count: 0 };
|
|
10706
|
+
try {
|
|
10707
|
+
const parsed = JSON.parse(line);
|
|
10708
|
+
const walked = walkAndRedactAll(parsed, patterns, memo);
|
|
10709
|
+
return { value: JSON.stringify(walked.value), count: walked.count };
|
|
10710
|
+
} catch {
|
|
10711
|
+
return redactString(line, patterns);
|
|
10712
|
+
}
|
|
10713
|
+
}
|
|
10714
|
+
return redactString(line, patterns);
|
|
10715
|
+
}
|
|
10644
10716
|
var WORKER_COUNT = Math.min(
|
|
10645
10717
|
os3.availableParallelism?.() ?? os3.cpus().length,
|
|
10646
10718
|
4
|
|
@@ -10669,9 +10741,14 @@ var PatternRedactMiddleware = class {
|
|
|
10669
10741
|
const tasks = [];
|
|
10670
10742
|
const fileMap = /* @__PURE__ */ new Map();
|
|
10671
10743
|
const passThrough = [];
|
|
10744
|
+
const largeResults = /* @__PURE__ */ new Map();
|
|
10672
10745
|
for (let i = 0; i < group.files.length; i++) {
|
|
10673
10746
|
const file = group.files[i];
|
|
10674
10747
|
this.stats.filesScanned++;
|
|
10748
|
+
if (file.content && !file.isBinary && file.content.length > getLargeFileThreshold()) {
|
|
10749
|
+
largeResults.set(i, this.redactLargeFile(file));
|
|
10750
|
+
continue;
|
|
10751
|
+
}
|
|
10675
10752
|
const read = await readFileContent(file);
|
|
10676
10753
|
if (read.kind === "binary") {
|
|
10677
10754
|
this.stats.binaryFiles++;
|
|
@@ -10701,6 +10778,11 @@ var PatternRedactMiddleware = class {
|
|
|
10701
10778
|
}
|
|
10702
10779
|
const newFiles = [];
|
|
10703
10780
|
for (let i = 0; i < group.files.length; i++) {
|
|
10781
|
+
const large = largeResults.get(i);
|
|
10782
|
+
if (large) {
|
|
10783
|
+
newFiles.push(large);
|
|
10784
|
+
continue;
|
|
10785
|
+
}
|
|
10704
10786
|
const pt = passThrough.find((p7) => p7.index === i);
|
|
10705
10787
|
if (pt) {
|
|
10706
10788
|
newFiles.push(pt.file);
|
|
@@ -10722,6 +10804,33 @@ var PatternRedactMiddleware = class {
|
|
|
10722
10804
|
}
|
|
10723
10805
|
return { ...group, files: newFiles };
|
|
10724
10806
|
}
|
|
10807
|
+
// Stream-redact an oversized file straight from its buffer, one line at a time,
|
|
10808
|
+
// so we never build a string larger than a single line. Single-threaded (no
|
|
10809
|
+
// worker pool) — it trades parallelism for bounded memory on the one giant file.
|
|
10810
|
+
redactLargeFile(file) {
|
|
10811
|
+
const buffer = file.content;
|
|
10812
|
+
const isJsonl = file.absolutePath.endsWith(".jsonl");
|
|
10813
|
+
const patterns = compilePatterns();
|
|
10814
|
+
const memo = /* @__PURE__ */ new Map();
|
|
10815
|
+
const { content, count, oversizedLines } = redactBufferByLine(
|
|
10816
|
+
buffer,
|
|
10817
|
+
(line) => redactPatternLine(line, patterns, memo, isJsonl)
|
|
10818
|
+
);
|
|
10819
|
+
if (oversizedLines > 0) {
|
|
10820
|
+
appendLog(
|
|
10821
|
+
"warn",
|
|
10822
|
+
`pattern-redact: dropped ${oversizedLines} oversized line(s) in ${file.absolutePath} (exceeded max string length)`
|
|
10823
|
+
);
|
|
10824
|
+
}
|
|
10825
|
+
if (count > 0) {
|
|
10826
|
+
this.stats.filesRedacted++;
|
|
10827
|
+
this.stats.totalRedactions += count;
|
|
10828
|
+
}
|
|
10829
|
+
if (count > 0 || oversizedLines > 0) {
|
|
10830
|
+
return { ...file, content };
|
|
10831
|
+
}
|
|
10832
|
+
return file;
|
|
10833
|
+
}
|
|
10725
10834
|
async processWithWorkers(tasks) {
|
|
10726
10835
|
const workerPath = resolveWorkerPath();
|
|
10727
10836
|
const sorted = [...tasks].sort(
|
|
@@ -10797,6 +10906,10 @@ var RedactMiddleware = class {
|
|
|
10797
10906
|
for (const file of group.files) {
|
|
10798
10907
|
this.stats.filesScanned++;
|
|
10799
10908
|
regex.lastIndex = 0;
|
|
10909
|
+
if (file.content && !file.isBinary && file.content.length > getLargeFileThreshold()) {
|
|
10910
|
+
newFiles.push(this.redactLargeFile(file, regex));
|
|
10911
|
+
continue;
|
|
10912
|
+
}
|
|
10800
10913
|
const read = await readFileContent(file);
|
|
10801
10914
|
if (read.kind === "binary") {
|
|
10802
10915
|
this.stats.binaryFiles++;
|
|
@@ -10832,6 +10945,47 @@ var RedactMiddleware = class {
|
|
|
10832
10945
|
}
|
|
10833
10946
|
return { ...group, files: newFiles };
|
|
10834
10947
|
}
|
|
10948
|
+
// Stream-redact an oversized file straight from its buffer. Each line is
|
|
10949
|
+
// redacted with the same JSON-aware (or raw) logic as redactJsonl, so the
|
|
10950
|
+
// output matches the in-memory path exactly for files whose lines all fit in a
|
|
10951
|
+
// string — which holds for real transcripts (largest line is a few MiB).
|
|
10952
|
+
redactLargeFile(file, regex) {
|
|
10953
|
+
const buffer = file.content;
|
|
10954
|
+
const isJsonl = file.absolutePath.endsWith(".jsonl");
|
|
10955
|
+
const { content, count, oversizedLines } = redactBufferByLine(
|
|
10956
|
+
buffer,
|
|
10957
|
+
(line) => this.redactLine(line, regex, isJsonl)
|
|
10958
|
+
);
|
|
10959
|
+
if (oversizedLines > 0) {
|
|
10960
|
+
appendLog(
|
|
10961
|
+
"warn",
|
|
10962
|
+
`redact: dropped ${oversizedLines} oversized line(s) in ${file.absolutePath} (exceeded max string length)`
|
|
10963
|
+
);
|
|
10964
|
+
}
|
|
10965
|
+
if (count > 0) {
|
|
10966
|
+
this.stats.filesRedacted++;
|
|
10967
|
+
this.stats.totalRedactions += count;
|
|
10968
|
+
}
|
|
10969
|
+
if (count > 0 || oversizedLines > 0) {
|
|
10970
|
+
return { ...file, content };
|
|
10971
|
+
}
|
|
10972
|
+
return file;
|
|
10973
|
+
}
|
|
10974
|
+
redactLine(line, regex, isJsonl) {
|
|
10975
|
+
if (isJsonl) {
|
|
10976
|
+
if (!line.trim()) return { value: line, count: 0 };
|
|
10977
|
+
try {
|
|
10978
|
+
const parsed = JSON.parse(line);
|
|
10979
|
+
const walked = walkAndRedact(parsed, regex);
|
|
10980
|
+
return { value: JSON.stringify(walked.value), count: walked.count };
|
|
10981
|
+
} catch {
|
|
10982
|
+
const { result: result2, count: count2 } = this.redactString(line, regex);
|
|
10983
|
+
return { value: result2, count: count2 };
|
|
10984
|
+
}
|
|
10985
|
+
}
|
|
10986
|
+
const { result, count } = this.redactString(line, regex);
|
|
10987
|
+
return { value: result, count };
|
|
10988
|
+
}
|
|
10835
10989
|
redactJsonl(content, regex) {
|
|
10836
10990
|
let totalCount = 0;
|
|
10837
10991
|
const lines = content.split("\n");
|
|
@@ -13334,10 +13488,10 @@ var NormalizeMiddleware = class {
|
|
|
13334
13488
|
file.sourceName
|
|
13335
13489
|
))
|
|
13336
13490
|
continue;
|
|
13337
|
-
const content = file.content ? file.content.toString("utf-8") : null;
|
|
13338
|
-
if (!content) continue;
|
|
13339
13491
|
const sessionId = file.metadata?.sessionId ?? (file.sourceName === "codex" ? void 0 : path13.basename(file.absolutePath, ".jsonl"));
|
|
13340
13492
|
try {
|
|
13493
|
+
const content = file.content ? file.content.toString("utf-8") : null;
|
|
13494
|
+
if (!content) continue;
|
|
13341
13495
|
const trajectory = normalizeContent(
|
|
13342
13496
|
file.sourceName,
|
|
13343
13497
|
content,
|
|
@@ -13366,7 +13520,7 @@ var NormalizeMiddleware = class {
|
|
|
13366
13520
|
} catch (err) {
|
|
13367
13521
|
appendLog(
|
|
13368
13522
|
"warn",
|
|
13369
|
-
`normalize:
|
|
13523
|
+
`normalize: skipped ATIF for source=${file.sourceName} session=${sessionId ?? "<unknown>"} file=${file.absolutePath}: ${err instanceof Error ? err.message : String(err)}`
|
|
13370
13524
|
);
|
|
13371
13525
|
}
|
|
13372
13526
|
}
|
|
@@ -14068,7 +14222,7 @@ import { execFileSync as execFileSync3 } from "child_process";
|
|
|
14068
14222
|
import path18 from "path";
|
|
14069
14223
|
|
|
14070
14224
|
// src/git-traces/git-ops.ts
|
|
14071
|
-
import { execFileSync as execFileSync2 } from "child_process";
|
|
14225
|
+
import { execFileSync as execFileSync2, spawnSync } from "child_process";
|
|
14072
14226
|
import fs12 from "fs";
|
|
14073
14227
|
import os7 from "os";
|
|
14074
14228
|
import path16 from "path";
|
|
@@ -14080,11 +14234,155 @@ var EXEC_OPTS = {
|
|
|
14080
14234
|
};
|
|
14081
14235
|
var MAX_ERROR_OUTPUT_CHARS = 2e3;
|
|
14082
14236
|
var MAX_SNAPSHOT_FILE_BYTES = 10 * 1024 * 1024;
|
|
14083
|
-
var
|
|
14237
|
+
var MAX_BINARY_SNAPSHOT_FILE_BYTES = 1024 * 1024;
|
|
14238
|
+
var BINARY_SNIFF_BYTES = 8e3;
|
|
14239
|
+
var EXCLUDED_SNAPSHOT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
14240
|
+
// Documents
|
|
14241
|
+
".pdf",
|
|
14242
|
+
// Raster images
|
|
14243
|
+
".png",
|
|
14244
|
+
".jpg",
|
|
14245
|
+
".jpeg",
|
|
14246
|
+
".gif",
|
|
14247
|
+
".bmp",
|
|
14248
|
+
".tiff",
|
|
14249
|
+
".tif",
|
|
14250
|
+
".webp",
|
|
14251
|
+
".ico",
|
|
14252
|
+
".heic",
|
|
14253
|
+
".heif",
|
|
14254
|
+
".avif",
|
|
14255
|
+
// Video
|
|
14256
|
+
".mp4",
|
|
14257
|
+
".mov",
|
|
14258
|
+
".avi",
|
|
14259
|
+
".mkv",
|
|
14260
|
+
".webm",
|
|
14261
|
+
".m4v",
|
|
14262
|
+
".mpg",
|
|
14263
|
+
".mpeg",
|
|
14264
|
+
".wmv",
|
|
14265
|
+
".flv",
|
|
14266
|
+
// Audio
|
|
14267
|
+
".mp3",
|
|
14268
|
+
".wav",
|
|
14269
|
+
".flac",
|
|
14270
|
+
".ogg",
|
|
14271
|
+
".m4a",
|
|
14272
|
+
".aac",
|
|
14273
|
+
".aiff",
|
|
14274
|
+
// Archives / compressed
|
|
14275
|
+
".zip",
|
|
14276
|
+
".tar",
|
|
14277
|
+
".gz",
|
|
14278
|
+
".tgz",
|
|
14279
|
+
".bz2",
|
|
14280
|
+
".tbz2",
|
|
14281
|
+
".xz",
|
|
14282
|
+
".7z",
|
|
14283
|
+
".rar",
|
|
14284
|
+
".zst",
|
|
14285
|
+
".lz4",
|
|
14286
|
+
// Fonts
|
|
14287
|
+
".woff",
|
|
14288
|
+
".woff2",
|
|
14289
|
+
".ttf",
|
|
14290
|
+
".otf",
|
|
14291
|
+
".eot",
|
|
14292
|
+
// Compiled / native artifacts
|
|
14293
|
+
".so",
|
|
14294
|
+
".dylib",
|
|
14295
|
+
".dll",
|
|
14296
|
+
".a",
|
|
14297
|
+
".o",
|
|
14298
|
+
".lib",
|
|
14299
|
+
".class",
|
|
14300
|
+
".jar",
|
|
14301
|
+
".wasm",
|
|
14302
|
+
".exe",
|
|
14303
|
+
".pyc",
|
|
14304
|
+
".pyd",
|
|
14305
|
+
".node",
|
|
14306
|
+
// Databases
|
|
14307
|
+
".sqlite",
|
|
14308
|
+
".sqlite3",
|
|
14309
|
+
".db",
|
|
14310
|
+
".mdb",
|
|
14311
|
+
// Office / design binaries
|
|
14312
|
+
".doc",
|
|
14313
|
+
".docx",
|
|
14314
|
+
".xls",
|
|
14315
|
+
".xlsx",
|
|
14316
|
+
".ppt",
|
|
14317
|
+
".pptx",
|
|
14318
|
+
".odt",
|
|
14319
|
+
".ods",
|
|
14320
|
+
".odp",
|
|
14321
|
+
".psd",
|
|
14322
|
+
".ai",
|
|
14323
|
+
".sketch",
|
|
14324
|
+
".fig",
|
|
14325
|
+
".blend"
|
|
14326
|
+
]);
|
|
14327
|
+
var EXCLUDED_SNAPSHOT_BASENAMES = /* @__PURE__ */ new Set([
|
|
14328
|
+
".DS_Store",
|
|
14329
|
+
"Thumbs.db",
|
|
14330
|
+
"desktop.ini"
|
|
14331
|
+
]);
|
|
14084
14332
|
var EMPTY_TREE_SHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
14085
|
-
function
|
|
14333
|
+
function isExcludedSnapshotPath(filePath) {
|
|
14334
|
+
if (EXCLUDED_SNAPSHOT_BASENAMES.has(path16.basename(filePath))) return true;
|
|
14086
14335
|
return EXCLUDED_SNAPSHOT_EXTENSIONS.has(path16.extname(filePath).toLowerCase());
|
|
14087
14336
|
}
|
|
14337
|
+
function isBinaryBuffer(buffer) {
|
|
14338
|
+
return buffer.includes(0);
|
|
14339
|
+
}
|
|
14340
|
+
function readTreeBlobHead(repoRoot, sha) {
|
|
14341
|
+
try {
|
|
14342
|
+
const { stdout } = spawnSync("git", ["cat-file", "blob", sha], {
|
|
14343
|
+
cwd: repoRoot,
|
|
14344
|
+
timeout: GIT_COMMAND_TIMEOUT_MS,
|
|
14345
|
+
maxBuffer: BINARY_SNIFF_BYTES
|
|
14346
|
+
});
|
|
14347
|
+
return stdout?.length ? stdout.subarray(0, BINARY_SNIFF_BYTES) : null;
|
|
14348
|
+
} catch {
|
|
14349
|
+
return null;
|
|
14350
|
+
}
|
|
14351
|
+
}
|
|
14352
|
+
function readWorkingFileHead(absPath) {
|
|
14353
|
+
let fd = null;
|
|
14354
|
+
try {
|
|
14355
|
+
fd = fs12.openSync(absPath, "r");
|
|
14356
|
+
const buffer = Buffer.alloc(BINARY_SNIFF_BYTES);
|
|
14357
|
+
const bytesRead = fs12.readSync(fd, buffer, 0, BINARY_SNIFF_BYTES, 0);
|
|
14358
|
+
return buffer.subarray(0, bytesRead);
|
|
14359
|
+
} catch {
|
|
14360
|
+
return null;
|
|
14361
|
+
} finally {
|
|
14362
|
+
if (fd !== null) {
|
|
14363
|
+
try {
|
|
14364
|
+
fs12.closeSync(fd);
|
|
14365
|
+
} catch {
|
|
14366
|
+
}
|
|
14367
|
+
}
|
|
14368
|
+
}
|
|
14369
|
+
}
|
|
14370
|
+
function classifyOmission(filePath, sizeBytes, readHead) {
|
|
14371
|
+
if (isExcludedSnapshotPath(filePath)) return "excluded-extension";
|
|
14372
|
+
if (sizeBytes > MAX_SNAPSHOT_FILE_BYTES) return "file-over-limit";
|
|
14373
|
+
if (sizeBytes > MAX_BINARY_SNAPSHOT_FILE_BYTES) {
|
|
14374
|
+
const head = readHead();
|
|
14375
|
+
if (!head) {
|
|
14376
|
+
appendLog(
|
|
14377
|
+
"warn",
|
|
14378
|
+
`git-traces: binary sniff failed for ${filePath} (${sizeBytes} bytes); keeping it in the snapshot`
|
|
14379
|
+
);
|
|
14380
|
+
return null;
|
|
14381
|
+
}
|
|
14382
|
+
if (isBinaryBuffer(head)) return "binary-over-limit";
|
|
14383
|
+
}
|
|
14384
|
+
return null;
|
|
14385
|
+
}
|
|
14088
14386
|
function quoteGitArg(arg) {
|
|
14089
14387
|
if (/^[A-Za-z0-9_./:=@%+,-]+$/.test(arg)) return arg;
|
|
14090
14388
|
return JSON.stringify(arg);
|
|
@@ -14188,7 +14486,7 @@ function recordOmittedSnapshotFile(omittedFiles, file, options = {}) {
|
|
|
14188
14486
|
omittedFiles?.push(file);
|
|
14189
14487
|
if (options.log === false) return;
|
|
14190
14488
|
const action = file.tracked ? "omitting tracked" : "skipping untracked";
|
|
14191
|
-
const reason = file.reason === "file-over-limit" ? `${file.sizeBytes} bytes > ${MAX_SNAPSHOT_FILE_BYTES} limit` : "excluded extension";
|
|
14489
|
+
const reason = file.reason === "file-over-limit" ? `${file.sizeBytes} bytes > ${MAX_SNAPSHOT_FILE_BYTES} limit` : file.reason === "binary-over-limit" ? `binary ${file.sizeBytes} bytes > ${MAX_BINARY_SNAPSHOT_FILE_BYTES} binary limit` : "excluded extension";
|
|
14192
14490
|
appendLog("warn", `git-traces: ${action} ${file.path} (${reason})`);
|
|
14193
14491
|
}
|
|
14194
14492
|
function parseLsTreeLongZ(output) {
|
|
@@ -14211,7 +14509,11 @@ function listOmittedTreeFiles(repoRoot, treeSha, options = {}) {
|
|
|
14211
14509
|
const output = gitBuffer(repoRoot, ["ls-tree", "-r", "-l", "-z", treeSha]);
|
|
14212
14510
|
const omitted = [];
|
|
14213
14511
|
for (const entry of parseLsTreeLongZ(output)) {
|
|
14214
|
-
const reason =
|
|
14512
|
+
const reason = classifyOmission(
|
|
14513
|
+
entry.path,
|
|
14514
|
+
entry.sizeBytes,
|
|
14515
|
+
() => readTreeBlobHead(repoRoot, entry.sha)
|
|
14516
|
+
);
|
|
14215
14517
|
if (!reason) continue;
|
|
14216
14518
|
const file = {
|
|
14217
14519
|
path: entry.path,
|
|
@@ -14269,8 +14571,13 @@ function buildUntrackedTree(repoRoot, omittedFiles) {
|
|
|
14269
14571
|
for (const relPath of list.split("\0")) {
|
|
14270
14572
|
if (!relPath) continue;
|
|
14271
14573
|
try {
|
|
14272
|
-
const
|
|
14273
|
-
const
|
|
14574
|
+
const absPath = path16.join(repoRoot, relPath);
|
|
14575
|
+
const stat = fs12.lstatSync(absPath);
|
|
14576
|
+
const reason = classifyOmission(
|
|
14577
|
+
relPath,
|
|
14578
|
+
stat.size,
|
|
14579
|
+
() => readWorkingFileHead(absPath)
|
|
14580
|
+
);
|
|
14274
14581
|
if (reason) {
|
|
14275
14582
|
recordOmittedSnapshotFile(omittedFiles, {
|
|
14276
14583
|
path: relPath,
|
package/dist/pattern-worker.js
CHANGED
|
@@ -8057,6 +8057,22 @@ var patterns_default = {
|
|
|
8057
8057
|
]
|
|
8058
8058
|
};
|
|
8059
8059
|
|
|
8060
|
+
// src/middleware/patterns-local.json
|
|
8061
|
+
var patterns_local_default = {
|
|
8062
|
+
patterns: [
|
|
8063
|
+
{
|
|
8064
|
+
name: "Hugging Face User Access Token",
|
|
8065
|
+
regex: "(?:(?<![A-Za-z0-9])|(?<=\\\\[nrt]))hf_[A-Za-z0-9]{34,40}",
|
|
8066
|
+
confidence: "high"
|
|
8067
|
+
},
|
|
8068
|
+
{
|
|
8069
|
+
name: "Hugging Face Organization API Token",
|
|
8070
|
+
regex: "(?:(?<![A-Za-z0-9])|(?<=\\\\[nrt]))api_org_[A-Za-z0-9]{34,40}",
|
|
8071
|
+
confidence: "high"
|
|
8072
|
+
}
|
|
8073
|
+
]
|
|
8074
|
+
};
|
|
8075
|
+
|
|
8060
8076
|
// src/middleware/pattern-core.ts
|
|
8061
8077
|
var DELIMITER_SUFFIX = /\(=\| =\|:\| :\)$/;
|
|
8062
8078
|
var HAS_VALUE_MATCHER = /[[{+*]|\\[wdWDsS]/;
|
|
@@ -8092,7 +8108,8 @@ function countCaptureGroups(source) {
|
|
|
8092
8108
|
}
|
|
8093
8109
|
function compilePatterns() {
|
|
8094
8110
|
const patterns = [];
|
|
8095
|
-
|
|
8111
|
+
const allPatterns = [...patterns_default.patterns, ...patterns_local_default.patterns];
|
|
8112
|
+
for (const p of allPatterns) {
|
|
8096
8113
|
if (p.confidence !== "high") continue;
|
|
8097
8114
|
if (DELIMITER_SUFFIX.test(p.regex)) continue;
|
|
8098
8115
|
if (!HAS_VALUE_MATCHER.test(p.regex)) continue;
|