token-goat 2.9.29 → 2.9.31
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 +53 -42
- package/SECURITY.md +37 -11
- package/THIRD_PARTY_NOTICES.md +41 -4
- package/dist/native/linux-arm64/tg-hook +0 -0
- package/dist/native/linux-x64/tg-hook +0 -0
- package/dist/native/win32-arm64/tg-hook.exe +0 -0
- package/dist/native/win32-x64/tg-hook.exe +0 -0
- package/dist/ort-wasm-simd-threaded.mjs +59 -0
- package/dist/{token-goat-chunk-SE6E4BKJ.mjs → token-goat-chunk-25TRAWET.mjs} +23 -6
- package/dist/token-goat-chunk-2KXO6V2B.mjs +203 -0
- package/dist/{token-goat-chunk-UXSXQQIY.mjs → token-goat-chunk-2M7E4PF7.mjs} +43 -14
- package/dist/token-goat-chunk-2UPZGKKY.mjs +188 -0
- package/dist/token-goat-chunk-2WLPWKHV.mjs +135 -0
- package/dist/token-goat-chunk-2XBMMDBD.mjs +126 -0
- package/dist/token-goat-chunk-32ZOY4N5.mjs +23 -0
- package/dist/token-goat-chunk-3EZRNKTK.mjs +188 -0
- package/dist/token-goat-chunk-4ADZHI7J.mjs +63 -0
- package/dist/token-goat-chunk-4GBVPH3D.mjs +242 -0
- package/dist/{token-goat-chunk-2WOUYWLM.mjs → token-goat-chunk-4GILLLWY.mjs} +34 -7
- package/dist/token-goat-chunk-4NAPX7BA.mjs +90 -0
- package/dist/{token-goat-chunk-NMBWLRHW.mjs → token-goat-chunk-4SC7UJYV.mjs} +9981 -11563
- package/dist/token-goat-chunk-4SMRO4TO.mjs +366 -0
- package/dist/{token-goat-chunk-O6I2XU4P.mjs → token-goat-chunk-4ZBFWLXF.mjs} +310 -441
- package/dist/token-goat-chunk-57BIAXJL.mjs +286 -0
- package/dist/token-goat-chunk-5AC66HNP.mjs +115 -0
- package/dist/token-goat-chunk-5IMLKSOP.mjs +145 -0
- package/dist/token-goat-chunk-5RG5SBL6.mjs +221 -0
- package/dist/{token-goat-chunk-RRNZMM3A.mjs → token-goat-chunk-5Y6ZYL6U.mjs} +21 -2
- package/dist/token-goat-chunk-646E6U44.mjs +398 -0
- package/dist/token-goat-chunk-65N4RHP4.mjs +33 -0
- package/dist/{token-goat-chunk-6AK46ZT7.mjs → token-goat-chunk-6DG6HWP3.mjs} +13 -3
- package/dist/token-goat-chunk-6ENQSNRZ.mjs +573 -0
- package/dist/token-goat-chunk-6ZY4GNF2.mjs +91 -0
- package/dist/{token-goat-chunk-E5TK5DNO.mjs → token-goat-chunk-76FGDLRO.mjs} +574 -340
- package/dist/{token-goat-chunk-TGOXNAHW.mjs → token-goat-chunk-7EZTZOMC.mjs} +780 -767
- package/dist/token-goat-chunk-7MAOA6X4.mjs +3647 -0
- package/dist/token-goat-chunk-7R2ZVVAX.mjs +218 -0
- package/dist/{token-goat-chunk-TCQANXYC.mjs → token-goat-chunk-AM5V6GSX.mjs} +18 -2
- package/dist/token-goat-chunk-AUNGYYQX.mjs +184 -0
- package/dist/token-goat-chunk-AUQYRMMH.mjs +2985 -0
- package/dist/token-goat-chunk-B3PEKBYG.mjs +128 -0
- package/dist/{token-goat-chunk-KOPIR3KZ.mjs → token-goat-chunk-BA4HI6BW.mjs} +1910 -165
- package/dist/{token-goat-chunk-52NSDWYY.mjs → token-goat-chunk-BFCWY73P.mjs} +58 -20
- package/dist/token-goat-chunk-BPGCUMR7.mjs +30 -0
- package/dist/token-goat-chunk-BWGFUZZE.mjs +25 -0
- package/dist/token-goat-chunk-C75NA7PL.mjs +322 -0
- package/dist/token-goat-chunk-CBIQ7WTD.mjs +87 -0
- package/dist/token-goat-chunk-CETM74KC.mjs +307 -0
- package/dist/token-goat-chunk-CIMQ2BB3.mjs +233 -0
- package/dist/{token-goat-chunk-DNSPXQXQ.mjs → token-goat-chunk-CJLS3CDL.mjs} +70 -18
- package/dist/{token-goat-chunk-MELOKFDJ.mjs → token-goat-chunk-CO3UYX6G.mjs} +7 -1
- package/dist/token-goat-chunk-COPNXRJM.mjs +154 -0
- package/dist/token-goat-chunk-CSJ5L3NL.mjs +479 -0
- package/dist/token-goat-chunk-CVCEVUGK.mjs +315 -0
- package/dist/token-goat-chunk-CXHOFN7R.mjs +371 -0
- package/dist/token-goat-chunk-D735C4QM.mjs +603 -0
- package/dist/{token-goat-chunk-E4ZOJIZK.mjs → token-goat-chunk-DGS2LVNA.mjs} +70 -160
- package/dist/{token-goat-chunk-L7H3U27L.mjs → token-goat-chunk-DOWRSMWO.mjs} +1 -1
- package/dist/token-goat-chunk-E45INMY3.mjs +71 -0
- package/dist/token-goat-chunk-EC5F37F4.mjs +244 -0
- package/dist/{token-goat-chunk-XTQAOTSO.mjs → token-goat-chunk-EDBDRVH5.mjs} +4 -1
- package/dist/token-goat-chunk-EELTBKDM.mjs +613 -0
- package/dist/token-goat-chunk-EVMZJ27Z.mjs +147 -0
- package/dist/token-goat-chunk-EXKGNHEG.mjs +2096 -0
- package/dist/{token-goat-chunk-YOOVFPTP.mjs → token-goat-chunk-F4HYL64R.mjs} +12 -2
- package/dist/token-goat-chunk-F6PAUIEK.mjs +624 -0
- package/dist/token-goat-chunk-FDSREWLX.mjs +692 -0
- package/dist/{token-goat-chunk-NMTKNYGF.mjs → token-goat-chunk-FNFBKLRD.mjs} +74 -9
- package/dist/token-goat-chunk-G5PJ7AGM.mjs +36 -0
- package/dist/token-goat-chunk-GGGG7RWB.mjs +236 -0
- package/dist/{token-goat-chunk-TDUT2CL6.mjs → token-goat-chunk-GL3ETKSC.mjs} +276 -19
- package/dist/{token-goat-chunk-7CPMDFGB.mjs → token-goat-chunk-GVB2MUST.mjs} +265 -1567
- package/dist/token-goat-chunk-GWFLAUMQ.mjs +307 -0
- package/dist/token-goat-chunk-HAVAOB3S.mjs +87 -0
- package/dist/token-goat-chunk-HLPW63A7.mjs +48 -0
- package/dist/token-goat-chunk-HU4TORC5.mjs +1377 -0
- package/dist/token-goat-chunk-I7VKZZAW.mjs +35 -0
- package/dist/token-goat-chunk-IA6XSPE3.mjs +218 -0
- package/dist/token-goat-chunk-IAGXMHIK.mjs +863 -0
- package/dist/{token-goat-chunk-435UQTKD.mjs → token-goat-chunk-IK2DRMFX.mjs} +129 -74
- package/dist/{token-goat-chunk-ZER6EAXZ.mjs → token-goat-chunk-INNPTRUX.mjs} +2954 -2783
- package/dist/token-goat-chunk-JJ5BX4F4.mjs +129 -0
- package/dist/token-goat-chunk-JVFSHVFJ.mjs +129 -0
- package/dist/token-goat-chunk-KGEFFSHD.mjs +50 -0
- package/dist/token-goat-chunk-KKUFXAPD.mjs +25 -0
- package/dist/token-goat-chunk-KQBLRPBN.mjs +433 -0
- package/dist/token-goat-chunk-LCNQ2CNN.mjs +497 -0
- package/dist/token-goat-chunk-M3LFJDPU.mjs +58 -0
- package/dist/token-goat-chunk-M52KPT3C.mjs +87 -0
- package/dist/token-goat-chunk-MBEG42H7.mjs +150 -0
- package/dist/{token-goat-chunk-EVC4TOLE.mjs → token-goat-chunk-METECDOH.mjs} +3 -12
- package/dist/{token-goat-chunk-2AWQ2R5X.mjs → token-goat-chunk-MHX7XCC3.mjs} +3 -2
- package/dist/token-goat-chunk-MNWKPRAL.mjs +13 -0
- package/dist/token-goat-chunk-N5LSOVSU.mjs +137 -0
- package/dist/{token-goat-chunk-DPNLUJWB.mjs → token-goat-chunk-N5MMR2IW.mjs} +30 -8
- package/dist/token-goat-chunk-N7B3JQ2C.mjs +160 -0
- package/dist/{token-goat-chunk-VMFWNHGR.mjs → token-goat-chunk-NISNMD7T.mjs} +2545 -2953
- package/dist/token-goat-chunk-NMD42SFQ.mjs +434 -0
- package/dist/token-goat-chunk-NOSS5VWY.mjs +174 -0
- package/dist/token-goat-chunk-NSNSPPBG.mjs +69 -0
- package/dist/token-goat-chunk-OBOFIHKN.mjs +38 -0
- package/dist/token-goat-chunk-OBRFJ5O5.mjs +76 -0
- package/dist/token-goat-chunk-ODBT2USM.mjs +800 -0
- package/dist/token-goat-chunk-OS5EM5PP.mjs +107 -0
- package/dist/token-goat-chunk-OUKDTVNU.mjs +1178 -0
- package/dist/token-goat-chunk-OXFMP75N.mjs +566 -0
- package/dist/{token-goat-chunk-ASLWOQ3I.mjs → token-goat-chunk-OYIYKDDT.mjs} +2 -1
- package/dist/{token-goat-chunk-67BNIKKO.mjs → token-goat-chunk-P6HQSWQ3.mjs} +55 -47
- package/dist/token-goat-chunk-P6VGNTQT.mjs +71 -0
- package/dist/token-goat-chunk-PFWIMH2E.mjs +261 -0
- package/dist/token-goat-chunk-PJZXIS3G.mjs +39 -0
- package/dist/token-goat-chunk-PUO5INXP.mjs +606 -0
- package/dist/token-goat-chunk-PX5PQWTY.mjs +462 -0
- package/dist/token-goat-chunk-Q5QDBC6O.mjs +111 -0
- package/dist/token-goat-chunk-QFNQXSDT.mjs +40 -0
- package/dist/token-goat-chunk-QH7YVYOY.mjs +3957 -0
- package/dist/token-goat-chunk-QLMUHEPB.mjs +43 -0
- package/dist/{token-goat-chunk-PYSUADX4.mjs → token-goat-chunk-QQOJIHL3.mjs} +50 -14
- package/dist/token-goat-chunk-QQTWJY2O.mjs +85 -0
- package/dist/token-goat-chunk-QYHO5CPH.mjs +93 -0
- package/dist/token-goat-chunk-RELAVWAD.mjs +27 -0
- package/dist/token-goat-chunk-RSLPOBKQ.mjs +339 -0
- package/dist/token-goat-chunk-SAMFDIS2.mjs +712 -0
- package/dist/token-goat-chunk-SDELXLDM.mjs +48 -0
- package/dist/{token-goat-chunk-PGTH2U4C.mjs → token-goat-chunk-SOAFZNNZ.mjs} +164 -40
- package/dist/{token-goat-chunk-G23DWHV4.mjs → token-goat-chunk-SRTHT7KV.mjs} +33 -15
- package/dist/token-goat-chunk-T5P5ACNQ.mjs +212 -0
- package/dist/token-goat-chunk-T5YGG4V3.mjs +45 -0
- package/dist/token-goat-chunk-TAUZ4OFS.mjs +110 -0
- package/dist/token-goat-chunk-TM6MC754.mjs +40 -0
- package/dist/token-goat-chunk-TWUKBOMP.mjs +72 -0
- package/dist/token-goat-chunk-U2KSB4SG.mjs +56 -0
- package/dist/token-goat-chunk-U4WHMG6Y.mjs +898 -0
- package/dist/token-goat-chunk-UA5V6P3P.mjs +122 -0
- package/dist/token-goat-chunk-UGJHGR5A.mjs +52 -0
- package/dist/{token-goat-chunk-RQGGMPCR.mjs → token-goat-chunk-UOUDVA5U.mjs} +76 -16
- package/dist/{token-goat-chunk-HNFZZHFW.mjs → token-goat-chunk-URRJ33GR.mjs} +22 -4
- package/dist/token-goat-chunk-UZOROKIS.mjs +165 -0
- package/dist/token-goat-chunk-VIHGGGEI.mjs +4234 -0
- package/dist/token-goat-chunk-VTJLAA7P.mjs +21 -0
- package/dist/token-goat-chunk-VWDXLT4F.mjs +678 -0
- package/dist/token-goat-chunk-VWZA2H4P.mjs +368 -0
- package/dist/{token-goat-chunk-QO3LXVVR.mjs → token-goat-chunk-VXEXMJDL.mjs} +2964 -3153
- package/dist/token-goat-chunk-WBA5SKT4.mjs +547 -0
- package/dist/{token-goat-chunk-ONXH6NZ5.mjs → token-goat-chunk-WDH44VAU.mjs} +19 -22
- package/dist/token-goat-chunk-X2SUP3EI.mjs +107 -0
- package/dist/token-goat-chunk-X3BELZSJ.mjs +125 -0
- package/dist/{token-goat-chunk-RLP6J7WR.mjs → token-goat-chunk-XLRBNZCC.mjs} +40 -21
- package/dist/{token-goat-chunk-S4VSXURL.mjs → token-goat-chunk-XRKUX6CM.mjs} +4 -0
- package/dist/token-goat-chunk-XX6O25RN.mjs +82 -0
- package/dist/token-goat-chunk-XZSUHBVS.mjs +65 -0
- package/dist/token-goat-chunk-Y2ZTQOCL.mjs +35 -0
- package/dist/{token-goat-chunk-UA5BKWWQ.mjs → token-goat-chunk-YB4VMGK2.mjs} +15 -4
- package/dist/token-goat-chunk-YBIIY3HR.mjs +51 -0
- package/dist/{token-goat-chunk-PKRWMHVP.mjs → token-goat-chunk-YHVDKQBR.mjs} +389 -221
- package/dist/token-goat-chunk-YJB5XLWI.mjs +26 -0
- package/dist/{token-goat-chunk-PQ53BSCF.mjs → token-goat-chunk-YKB6AQG3.mjs} +53 -31
- package/dist/token-goat-chunk-YMTG2YA5.mjs +35 -0
- package/dist/token-goat-chunk-YPBZYQRV.mjs +40 -0
- package/dist/{token-goat-chunk-HUYUHODZ.mjs → token-goat-chunk-YY6AVUFL.mjs} +13246 -12247
- package/dist/token-goat-chunk-Z7N5OMMP.mjs +98 -0
- package/dist/{token-goat-chunk-BGHSSJUA.mjs → token-goat-chunk-ZFOBKUWH.mjs} +1 -1
- package/dist/token-goat-chunk-ZMBL6UVV.mjs +110 -0
- package/dist/token-goat-chunk-ZNMNUPAZ.mjs +938 -0
- package/dist/token-goat-hook-client.cjs +87 -23
- package/dist/token-goat-hook-client.mjs +3 -3
- package/dist/token-goat-hook.mjs +76 -31
- package/dist/token-goat.core.mjs +6 -6
- package/docs/C4_RUNTIME_ARCHITECTURE.md +2 -2
- package/docs/cli.md +113 -60
- package/docs/install.md +63 -20
- package/docs/security.md +10 -8
- package/package.json +18 -7
- package/scripts/verify-native-dist.mjs +386 -0
- package/dist/token-goat-chunk-2NNUA2LR.mjs +0 -143
- package/dist/token-goat-chunk-44BM7DDQ.mjs +0 -294
- package/dist/token-goat-chunk-BGYOZ6DO.mjs +0 -24
- package/dist/token-goat-chunk-C5YPNZKQ.mjs +0 -318
- package/dist/token-goat-chunk-CIQ2FTY3.mjs +0 -1990
- package/dist/token-goat-chunk-D4ETHJD6.mjs +0 -246
- package/dist/token-goat-chunk-DNRPXHYH.mjs +0 -1062
- package/dist/token-goat-chunk-EUSDXRXU.mjs +0 -1429
- package/dist/token-goat-chunk-FTP4U4QA.mjs +0 -64
- package/dist/token-goat-chunk-G7IWXCFF.mjs +0 -456
- package/dist/token-goat-chunk-GLXRTTLE.mjs +0 -36
- package/dist/token-goat-chunk-H5J3C56Q.mjs +0 -1511
- package/dist/token-goat-chunk-IVWI2OCK.mjs +0 -368
- package/dist/token-goat-chunk-JTKCQMQA.mjs +0 -418
- package/dist/token-goat-chunk-LZNBQTDK.mjs +0 -26
- package/dist/token-goat-chunk-ORNFMIER.mjs +0 -295
- package/dist/token-goat-chunk-RTMVLHWX.mjs +0 -7113
- package/dist/token-goat-chunk-VQ6F6T7X.mjs +0 -36
- package/dist/token-goat-chunk-VZQEWRVH.mjs +0 -312
- package/dist/token-goat-chunk-XYWPOSCN.mjs +0 -807
- package/dist/token-goat-chunk-YAGLESS3.mjs +0 -23
- package/dist/token-goat-chunk-YKSRAWUU.mjs +0 -33
- package/dist/token-goat-chunk-Z6KBMOBI.mjs +0 -53
|
@@ -1,47 +1,253 @@
|
|
|
1
1
|
import { createRequire as __cjsRequire } from 'node:module';
|
|
2
2
|
const require = __cjsRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
isBlobStale,
|
|
7
|
-
loadBlob,
|
|
8
|
-
storeBlob
|
|
9
|
-
} from "./token-goat-chunk-D4ETHJD6.mjs";
|
|
10
|
-
import {
|
|
11
|
-
hasUnquotedOperator
|
|
12
|
-
} from "./token-goat-chunk-2WOUYWLM.mjs";
|
|
4
|
+
sanitizeFtsQuery
|
|
5
|
+
} from "./token-goat-chunk-IK2DRMFX.mjs";
|
|
13
6
|
import {
|
|
14
|
-
|
|
15
|
-
} from "./token-goat-chunk-
|
|
7
|
+
recordStat
|
|
8
|
+
} from "./token-goat-chunk-U4WHMG6Y.mjs";
|
|
16
9
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
getDb,
|
|
11
|
+
getReadDb
|
|
12
|
+
} from "./token-goat-chunk-GVB2MUST.mjs";
|
|
19
13
|
import {
|
|
20
|
-
|
|
21
|
-
} from "./token-goat-chunk-
|
|
14
|
+
hasUnquotedOperator
|
|
15
|
+
} from "./token-goat-chunk-4GILLLWY.mjs";
|
|
22
16
|
import {
|
|
23
|
-
|
|
24
|
-
} from "./token-goat-chunk-
|
|
17
|
+
stripAnsiEscapes
|
|
18
|
+
} from "./token-goat-chunk-HAVAOB3S.mjs";
|
|
25
19
|
import {
|
|
26
|
-
|
|
27
|
-
} from "./token-goat-chunk-
|
|
20
|
+
redactSerializedJson
|
|
21
|
+
} from "./token-goat-chunk-T5P5ACNQ.mjs";
|
|
28
22
|
import {
|
|
29
|
-
|
|
30
|
-
} from "./token-goat-chunk-
|
|
23
|
+
loadConfig
|
|
24
|
+
} from "./token-goat-chunk-7EZTZOMC.mjs";
|
|
31
25
|
import {
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
atomicWriteText,
|
|
27
|
+
ensureDirSync,
|
|
28
|
+
sanitizeIdForFilename
|
|
29
|
+
} from "./token-goat-chunk-HU4TORC5.mjs";
|
|
34
30
|
import {
|
|
35
|
-
globalDbPath
|
|
36
|
-
|
|
31
|
+
globalDbPath,
|
|
32
|
+
tokenGoatHome
|
|
33
|
+
} from "./token-goat-chunk-CO3UYX6G.mjs";
|
|
37
34
|
import {
|
|
38
35
|
init_define_import_meta_env
|
|
39
36
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
40
37
|
|
|
41
|
-
// src/
|
|
38
|
+
// src/disk_cache.ts
|
|
42
39
|
init_define_import_meta_env();
|
|
43
|
-
import
|
|
44
|
-
import
|
|
40
|
+
import * as fs from "node:fs";
|
|
41
|
+
import * as path from "node:path";
|
|
42
|
+
var DEFAULT_MAX_COUNT = 200;
|
|
43
|
+
var DEFAULT_MAX_AGE_MS = 24 * 3600 * 1e3;
|
|
44
|
+
function sanitizeId(id) {
|
|
45
|
+
return sanitizeIdForFilename(id, 64);
|
|
46
|
+
}
|
|
47
|
+
function blobDir(subdir) {
|
|
48
|
+
return path.join(tokenGoatHome(), subdir);
|
|
49
|
+
}
|
|
50
|
+
function blobPath(subdir, id) {
|
|
51
|
+
const safe = sanitizeId(id);
|
|
52
|
+
if (!safe) return null;
|
|
53
|
+
const dir = blobDir(subdir);
|
|
54
|
+
const candidate = path.join(dir, `${safe}.json`);
|
|
55
|
+
try {
|
|
56
|
+
const rel = path.relative(dir, candidate);
|
|
57
|
+
if (rel.startsWith("..")) return null;
|
|
58
|
+
} catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return candidate;
|
|
62
|
+
}
|
|
63
|
+
function isBlobStale(subdir, id) {
|
|
64
|
+
const p = blobPath(subdir, id);
|
|
65
|
+
if (p === null) return false;
|
|
66
|
+
try {
|
|
67
|
+
const stat = fs.statSync(p);
|
|
68
|
+
return Date.now() - stat.mtimeMs > DEFAULT_MAX_AGE_MS;
|
|
69
|
+
} catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function subdirCacheDefaults(subdir) {
|
|
74
|
+
try {
|
|
75
|
+
if (subdir === "bash_outputs") {
|
|
76
|
+
const bc = loadConfig().bash_compress;
|
|
77
|
+
return { maxCount: bc.cache_max_file_count, maxBytes: bc.cache_max_bytes, maxBytesPerItem: bc.cache_max_bytes_per_output };
|
|
78
|
+
}
|
|
79
|
+
if (subdir === "web_outputs") {
|
|
80
|
+
const wf = loadConfig().webfetch;
|
|
81
|
+
return { maxCount: wf.max_file_count, maxBytes: wf.max_bytes, maxBytesPerItem: Number.POSITIVE_INFINITY };
|
|
82
|
+
}
|
|
83
|
+
} catch {
|
|
84
|
+
}
|
|
85
|
+
return { maxCount: DEFAULT_MAX_COUNT, maxBytes: Number.POSITIVE_INFINITY, maxBytesPerItem: Number.POSITIVE_INFINITY };
|
|
86
|
+
}
|
|
87
|
+
function storeBlob(subdir, id, value, opts = {}) {
|
|
88
|
+
const p = blobPath(subdir, id);
|
|
89
|
+
if (!p) return false;
|
|
90
|
+
const defaults = subdirCacheDefaults(subdir);
|
|
91
|
+
const maxBytesPerItem = opts.maxBytesPerItem ?? defaults.maxBytesPerItem;
|
|
92
|
+
let rawJson;
|
|
93
|
+
try {
|
|
94
|
+
rawJson = JSON.stringify(value);
|
|
95
|
+
} catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
let json;
|
|
99
|
+
try {
|
|
100
|
+
const result = redactSerializedJson(rawJson);
|
|
101
|
+
json = result.text;
|
|
102
|
+
if (result.count > 0) recordStat("secret_redacted", 0, result.count, void 0, subdir);
|
|
103
|
+
} catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
if (Number.isFinite(maxBytesPerItem) && Buffer.byteLength(json, "utf-8") > maxBytesPerItem) return false;
|
|
107
|
+
try {
|
|
108
|
+
const dir = path.dirname(p);
|
|
109
|
+
if (!fs.existsSync(dir)) ensureDirSync(dir);
|
|
110
|
+
atomicWriteText(p, json);
|
|
111
|
+
} catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
pruneBlobs(
|
|
115
|
+
subdir,
|
|
116
|
+
opts.maxCount ?? defaults.maxCount,
|
|
117
|
+
opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS,
|
|
118
|
+
opts.maxBytes ?? defaults.maxBytes,
|
|
119
|
+
p
|
|
120
|
+
);
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
function loadBlob(subdir, id) {
|
|
124
|
+
const p = blobPath(subdir, id);
|
|
125
|
+
if (!p) return null;
|
|
126
|
+
try {
|
|
127
|
+
if (!fs.existsSync(p)) return null;
|
|
128
|
+
return JSON.parse(fs.readFileSync(p, "utf8"));
|
|
129
|
+
} catch {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function listBlobs(subdir) {
|
|
134
|
+
const dir = blobDir(subdir);
|
|
135
|
+
const out = [];
|
|
136
|
+
try {
|
|
137
|
+
if (!fs.existsSync(dir)) return out;
|
|
138
|
+
for (const file of fs.readdirSync(dir)) {
|
|
139
|
+
if (!file.endsWith(".json")) continue;
|
|
140
|
+
const id = file.slice(0, -5);
|
|
141
|
+
let mtime = 0;
|
|
142
|
+
try {
|
|
143
|
+
mtime = fs.statSync(path.join(dir, file)).mtimeMs;
|
|
144
|
+
} catch {
|
|
145
|
+
}
|
|
146
|
+
const value = loadBlob(subdir, id);
|
|
147
|
+
if (value !== null) out.push({ id, mtime, value });
|
|
148
|
+
}
|
|
149
|
+
} catch {
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
function pruneBlobs(subdir, maxCount = DEFAULT_MAX_COUNT, maxAgeMs = DEFAULT_MAX_AGE_MS, maxBytes = Number.POSITIVE_INFINITY, protectedPath) {
|
|
155
|
+
return pruneBlobDir(blobDir(subdir), maxCount, maxAgeMs, maxBytes, protectedPath);
|
|
156
|
+
}
|
|
157
|
+
function pruneBlobDir(dir, maxCount = DEFAULT_MAX_COUNT, maxAgeMs = DEFAULT_MAX_AGE_MS, maxBytes = Number.POSITIVE_INFINITY, protectedPath) {
|
|
158
|
+
let removed = 0;
|
|
159
|
+
try {
|
|
160
|
+
if (!fs.existsSync(dir)) return 0;
|
|
161
|
+
const cutoff = Date.now() - maxAgeMs;
|
|
162
|
+
let kept = [];
|
|
163
|
+
let protectedEntry;
|
|
164
|
+
for (const file of fs.readdirSync(dir)) {
|
|
165
|
+
const full = path.join(dir, file);
|
|
166
|
+
let stat;
|
|
167
|
+
try {
|
|
168
|
+
stat = fs.statSync(full);
|
|
169
|
+
} catch {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (!stat.isFile()) continue;
|
|
173
|
+
if (protectedPath !== void 0 && full === protectedPath) {
|
|
174
|
+
protectedEntry = [full, stat.mtimeMs, stat.size];
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (stat.mtimeMs < cutoff) {
|
|
178
|
+
try {
|
|
179
|
+
fs.unlinkSync(full);
|
|
180
|
+
removed++;
|
|
181
|
+
} catch {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
} else if (file.endsWith(".json")) {
|
|
185
|
+
kept.push([full, stat.mtimeMs, stat.size]);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const countBudget = protectedEntry ? Math.max(0, maxCount - 1) : maxCount;
|
|
189
|
+
if (kept.length > countBudget) {
|
|
190
|
+
kept.sort((a, b) => a[1] - b[1]);
|
|
191
|
+
const excess = kept.slice(0, kept.length - countBudget);
|
|
192
|
+
kept = kept.slice(kept.length - countBudget);
|
|
193
|
+
for (const [full] of excess) {
|
|
194
|
+
try {
|
|
195
|
+
fs.unlinkSync(full);
|
|
196
|
+
removed++;
|
|
197
|
+
} catch {
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (Number.isFinite(maxBytes)) {
|
|
203
|
+
kept.sort((a, b) => a[1] - b[1]);
|
|
204
|
+
let total = kept.reduce((sum, [, , size]) => sum + size, 0) + (protectedEntry ? protectedEntry[2] : 0);
|
|
205
|
+
while (total > maxBytes && kept.length > 0) {
|
|
206
|
+
const oldest = kept.shift();
|
|
207
|
+
if (!oldest) break;
|
|
208
|
+
const [full, , size] = oldest;
|
|
209
|
+
try {
|
|
210
|
+
fs.unlinkSync(full);
|
|
211
|
+
removed++;
|
|
212
|
+
total -= size;
|
|
213
|
+
} catch {
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
} catch {
|
|
219
|
+
return removed;
|
|
220
|
+
}
|
|
221
|
+
return removed;
|
|
222
|
+
}
|
|
223
|
+
var SWEEPABLE_CACHE_SUBDIRS = [
|
|
224
|
+
{ subdir: "bash_outputs", countCapped: true },
|
|
225
|
+
{ subdir: "web_outputs", countCapped: true },
|
|
226
|
+
{ subdir: "mcp_outputs", countCapped: true },
|
|
227
|
+
{ subdir: "sessions", countCapped: false }
|
|
228
|
+
];
|
|
229
|
+
function sweepCacheRoots(extraRoots = []) {
|
|
230
|
+
let removed = 0;
|
|
231
|
+
const roots = [tokenGoatHome(), ...extraRoots];
|
|
232
|
+
const seen = /* @__PURE__ */ new Set();
|
|
233
|
+
for (const root of roots) {
|
|
234
|
+
if (!root || seen.has(root)) continue;
|
|
235
|
+
seen.add(root);
|
|
236
|
+
for (const { subdir, countCapped } of SWEEPABLE_CACHE_SUBDIRS) {
|
|
237
|
+
try {
|
|
238
|
+
const defaults = subdirCacheDefaults(subdir);
|
|
239
|
+
removed += pruneBlobDir(
|
|
240
|
+
path.join(root, subdir),
|
|
241
|
+
countCapped ? defaults.maxCount : Number.POSITIVE_INFINITY,
|
|
242
|
+
DEFAULT_MAX_AGE_MS,
|
|
243
|
+
countCapped ? defaults.maxBytes : Number.POSITIVE_INFINITY
|
|
244
|
+
);
|
|
245
|
+
} catch {
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return removed;
|
|
250
|
+
}
|
|
45
251
|
|
|
46
252
|
// src/hints/lang_patterns.ts
|
|
47
253
|
init_define_import_meta_env();
|
|
@@ -140,7 +346,7 @@ var BUILD_COMMAND_PATTERNS = [
|
|
|
140
346
|
/^\s*(?:gradle|\.\/gradlew|gradlew)\b/i,
|
|
141
347
|
// Python / pip
|
|
142
348
|
/^\s*pip\s+(install|freeze)\b/i,
|
|
143
|
-
// npm audit / npm outdated — read-only reporting commands with no side effects, safe to cache/recall. Each resolves a `lockfile`-scoped fingerprint via bash_output_cache.ts's isNpmAuditCommand/isNpmOutdatedCommand, but that fingerprinting never actually ran outside their own unit tests until this entry, since neither subcommand was recognized by isBuildCommand (the generic cache-reachability gate in hooks_bash.ts). `npm install`/`npm ci`/`npm list`/`npm ls` are deliberately left out — see the negative-case test in lang_patterns.test.ts.
|
|
349
|
+
// npm audit / npm outdated — read-only reporting commands with no side effects, safe to cache/recall. Each resolves a `lockfile`-scoped fingerprint via bash_output_cache.ts's isNpmAuditCommand/isNpmOutdatedCommand, but that fingerprinting never actually ran outside their own unit tests until this entry, since neither subcommand was recognized by isBuildCommand (the generic cache-reachability gate in hooks_bash.ts and hooks_bash_post.ts). `npm install`/`npm ci`/`npm list`/`npm ls` are deliberately left out — see the negative-case test in lang_patterns.test.ts.
|
|
144
350
|
/^\s*npm\s+(audit|outdated)\b/i,
|
|
145
351
|
// Poetry
|
|
146
352
|
/^\s*poetry\s+(install|update)\b/i,
|
|
@@ -225,6 +431,8 @@ var TEST_RUNNER_COMMAND_PATTERNS = [
|
|
|
225
431
|
/^go test(?:\s|$)/i,
|
|
226
432
|
// Rust / Cargo
|
|
227
433
|
/^cargo test(?:\s|$)/i,
|
|
434
|
+
// dotnet test
|
|
435
|
+
/^\s*dotnet\s+test(?:\s|$)/i,
|
|
228
436
|
// npm test / npm run test
|
|
229
437
|
/^npm (?:test|run test)(?:\s|$)/i,
|
|
230
438
|
// yarn test / yarn run test / pnpm test / pnpm run test
|
|
@@ -233,6 +441,20 @@ var TEST_RUNNER_COMMAND_PATTERNS = [
|
|
|
233
441
|
function isTestRunnerCommand(cmd) {
|
|
234
442
|
return TEST_RUNNER_COMMAND_PATTERNS.some((re) => re.test(cmd));
|
|
235
443
|
}
|
|
444
|
+
var DEV_SERVER_COMMAND_PATTERNS = [
|
|
445
|
+
{ pattern: /^(?:npx\s+)?next dev/, recallHint: '--tail 30 --grep "error|warn|ready|compiled"' },
|
|
446
|
+
{ pattern: /^(?:npx\s+)?next build/, recallHint: '--grep "error|warn|Failed|\u2713"' },
|
|
447
|
+
// vite ends at whitespace or the end of the command, not at a word boundary, which a hyphen satisfies: vite-node is another tool, so it is neither recalled nor fingerprinted as a dev server.
|
|
448
|
+
{ pattern: /^(?:npx\s+)?vite(?:\s|$)/, recallHint: '--tail 20 --grep "error|warn|ready"' },
|
|
449
|
+
// nuxt dev ends the same way: `nuxt devtools enable` is another nuxt command.
|
|
450
|
+
{ pattern: /^(?:npx\s+)?nuxt dev(?:\s|$)/, recallHint: '--tail 30 --grep "error|warn|ready"' },
|
|
451
|
+
{ pattern: /^(?:npx\s+)?remix dev/, recallHint: '--tail 20 --grep "error|warn|ready"' },
|
|
452
|
+
{ pattern: /^(?:npx\s+)?astro dev/, recallHint: '--tail 20 --grep "error|warn|ready"' }
|
|
453
|
+
];
|
|
454
|
+
function isDevServerCommand(cmd) {
|
|
455
|
+
const trimmed = cmd.trim();
|
|
456
|
+
return DEV_SERVER_COMMAND_PATTERNS.some(({ pattern }) => pattern.test(trimmed));
|
|
457
|
+
}
|
|
236
458
|
var MONITORING_COMMAND_PATTERNS = [
|
|
237
459
|
// GitHub CI
|
|
238
460
|
{ pattern: /^gh run (?:watch|view|list)/, recallHint: '--grep "fail|error|pass|\u2713|\u2717|conclusion"' },
|
|
@@ -242,16 +464,10 @@ var MONITORING_COMMAND_PATTERNS = [
|
|
|
242
464
|
{ pattern: /^gh pr list/, recallHint: '--grep "OPEN|DRAFT|MERGED|#"' },
|
|
243
465
|
{ pattern: /^gh issue view/, recallHint: '--grep "state|title|label|OPEN|CLOSED"' },
|
|
244
466
|
{ pattern: /^gh workflow (?:run|list|view)/, recallHint: '--grep "completed|failed|in_progress"' },
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
{ pattern: /^(?:npx\s+)?
|
|
248
|
-
{ pattern: /^(?:npx\s+)?
|
|
249
|
-
{ pattern: /^(?:npx\s+)?nuxt dev/, recallHint: '--tail 30 --grep "error|warn|ready"' },
|
|
250
|
-
{ pattern: /^(?:npx\s+)?remix dev/, recallHint: '--tail 20 --grep "error|warn|ready"' },
|
|
251
|
-
{ pattern: /^(?:npx\s+)?astro dev/, recallHint: '--tail 20 --grep "error|warn|ready"' },
|
|
252
|
-
// Test watchers
|
|
253
|
-
{ pattern: /^(?:npx\s+)?vitest(?:\s+run|\s+watch)?/, recallHint: '--grep "FAIL|PASS|Error|\u2713|\u2717"' },
|
|
254
|
-
{ pattern: /^(?:npx\s+)?jest(?:\s+--watch)?/, recallHint: '--grep "FAIL|PASS|Error|Tests:"' },
|
|
467
|
+
...DEV_SERVER_COMMAND_PATTERNS,
|
|
468
|
+
// Test watchers. jest and vitest must be followed by whitespace or the end of the command, as in TEST_RUNNER_COMMAND_PATTERNS, not merely by a word boundary: a cached run goes stale only through the git fingerprint isTestRunnerCommand grants, and a longer name (jest-codemods, vitest-preview) is another tool that predicate rejects.
|
|
469
|
+
{ pattern: /^(?:npx\s+)?vitest(?:\s|$)/, recallHint: '--grep "FAIL|PASS|Error|\u2713|\u2717"' },
|
|
470
|
+
{ pattern: /^(?:npx\s+)?jest(?:\s|$)/, recallHint: '--grep "FAIL|PASS|Error|Tests:"' },
|
|
255
471
|
{ pattern: /^pytest(?:\s|$)/, recallHint: '--grep "FAILED|PASSED|ERROR|passed|failed"' },
|
|
256
472
|
{ pattern: /^(?:cargo\s+test|cargo\s+watch)/, recallHint: '--grep "FAILED|ok|error\\["' },
|
|
257
473
|
{ pattern: /^go test/, recallHint: '--grep "FAIL|ok|---"' },
|
|
@@ -268,7 +484,8 @@ var MONITORING_COMMAND_PATTERNS = [
|
|
|
268
484
|
{ pattern: /^(?:npx\s+)?prettier(?:\s|$)/, recallHint: '--grep "unchanged|reformatted|error"' },
|
|
269
485
|
{ pattern: /^npx\s+tsc(?:\s|$)/, recallHint: '--grep "error TS|Cannot find|Type "' },
|
|
270
486
|
{ pattern: /^ruff(?:\s|$)/, recallHint: '--grep "error|warning|Found"' },
|
|
271
|
-
|
|
487
|
+
// Ends the same way: clippy-driver is clippy's rustc wrapper, run without cargo, so isBuildCommand gives it no fingerprint to go stale by.
|
|
488
|
+
{ pattern: /^(?:cargo\s+)?clippy(?:\s|$)/, recallHint: '--grep "error\\[|warning\\["' },
|
|
272
489
|
// git diff (full diff output — can be very large; excludes --stat which is small)
|
|
273
490
|
{ pattern: /^git diff(?!\s+--stat)(?:\s+HEAD)?(?:\s|$)/, recallHint: '--grep "@@|\\+\\+\\+|---|diff --git"' },
|
|
274
491
|
{ pattern: /^git diff\s+--cached(?!\s+--stat)/, recallHint: '--grep "@@|\\+\\+\\+|---|diff --git"' },
|
|
@@ -318,16 +535,46 @@ function getMonitoringRecallHint(cmd) {
|
|
|
318
535
|
return null;
|
|
319
536
|
}
|
|
320
537
|
|
|
538
|
+
// src/git_porcelain.ts
|
|
539
|
+
init_define_import_meta_env();
|
|
540
|
+
function parsePorcelainZ(stdout) {
|
|
541
|
+
const fields = stdout.split("\0");
|
|
542
|
+
const out = [];
|
|
543
|
+
for (let i = 0; i < fields.length; i++) {
|
|
544
|
+
const field = fields[i] ?? "";
|
|
545
|
+
if (field.length < 4) continue;
|
|
546
|
+
const entry = { path: field.slice(3) };
|
|
547
|
+
if (field.startsWith("??")) entry.untracked = true;
|
|
548
|
+
if (/[RC]/.test(field.slice(0, 2))) {
|
|
549
|
+
i++;
|
|
550
|
+
const orig = fields[i];
|
|
551
|
+
if (orig !== void 0 && orig !== "") entry.origPath = orig;
|
|
552
|
+
}
|
|
553
|
+
out.push(entry);
|
|
554
|
+
}
|
|
555
|
+
return out;
|
|
556
|
+
}
|
|
557
|
+
|
|
321
558
|
// src/recall_index.ts
|
|
322
559
|
init_define_import_meta_env();
|
|
323
|
-
import * as
|
|
560
|
+
import * as fs2 from "node:fs";
|
|
561
|
+
|
|
562
|
+
// src/snippet_window.ts
|
|
563
|
+
init_define_import_meta_env();
|
|
564
|
+
function snippetAround(text, idx, maxLen) {
|
|
565
|
+
const start = Math.max(0, idx - Math.floor(maxLen / 3));
|
|
566
|
+
const end = Math.min(text.length, start + maxLen);
|
|
567
|
+
return (start > 0 ? "..." : "") + text.slice(start, end) + (end < text.length ? "..." : "");
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// src/recall_index.ts
|
|
324
571
|
function subdirForCacheType(cacheType) {
|
|
325
572
|
return cacheType === "web" ? "web_outputs" : "bash_outputs";
|
|
326
573
|
}
|
|
327
574
|
function blobStillExists(cacheType, id) {
|
|
328
575
|
try {
|
|
329
576
|
const p = blobPath(subdirForCacheType(cacheType), id);
|
|
330
|
-
return p !== null &&
|
|
577
|
+
return p !== null && fs2.existsSync(p);
|
|
331
578
|
} catch {
|
|
332
579
|
return false;
|
|
333
580
|
}
|
|
@@ -347,7 +594,8 @@ function indexRecallEntry(cacheType, id, label, content, storedAt) {
|
|
|
347
594
|
label = excluded.label,
|
|
348
595
|
content = excluded.content,
|
|
349
596
|
stored_at = excluded.stored_at`
|
|
350
|
-
|
|
597
|
+
// Stripped so a query spanning a colour boundary matches the text a reader sees; the cached blob itself stays raw.
|
|
598
|
+
).run({ cacheType, id, label: stripAnsiEscapes(label), content: stripAnsiEscapes(content), storedAt });
|
|
351
599
|
} catch {
|
|
352
600
|
}
|
|
353
601
|
pruneCacheRecallRows();
|
|
@@ -364,7 +612,7 @@ var _ftsAvailable = null;
|
|
|
364
612
|
function hasFtsTable() {
|
|
365
613
|
if (_ftsAvailable !== null) return _ftsAvailable;
|
|
366
614
|
try {
|
|
367
|
-
const db =
|
|
615
|
+
const db = getReadDb(globalDbPath());
|
|
368
616
|
const row = db.prepare(`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'cache_recall_fts'`).get();
|
|
369
617
|
_ftsAvailable = row !== void 0;
|
|
370
618
|
} catch {
|
|
@@ -373,7 +621,7 @@ function hasFtsTable() {
|
|
|
373
621
|
return _ftsAvailable;
|
|
374
622
|
}
|
|
375
623
|
function buildSnippet(content, query, maxLen = 160) {
|
|
376
|
-
const flat = content.replace(/\s+/g, " ").trim();
|
|
624
|
+
const flat = stripAnsiEscapes(content).replace(/\s+/g, " ").trim();
|
|
377
625
|
const tokens = query.split(/\s+/).filter(Boolean);
|
|
378
626
|
let idx = -1;
|
|
379
627
|
const lowerFlat = flat.toLowerCase();
|
|
@@ -384,14 +632,7 @@ function buildSnippet(content, query, maxLen = 160) {
|
|
|
384
632
|
break;
|
|
385
633
|
}
|
|
386
634
|
}
|
|
387
|
-
|
|
388
|
-
return flat.length > maxLen ? flat.slice(0, maxLen) + "..." : flat;
|
|
389
|
-
}
|
|
390
|
-
const start = Math.max(0, idx - Math.floor(maxLen / 3));
|
|
391
|
-
const end = Math.min(flat.length, start + maxLen);
|
|
392
|
-
const prefix = start > 0 ? "..." : "";
|
|
393
|
-
const suffix = end < flat.length ? "..." : "";
|
|
394
|
-
return prefix + flat.slice(start, end) + suffix;
|
|
635
|
+
return snippetAround(flat, Math.max(0, idx), maxLen);
|
|
395
636
|
}
|
|
396
637
|
function toFtsMatchExpr(query) {
|
|
397
638
|
if (query.trim().length === 0) return null;
|
|
@@ -410,7 +651,7 @@ function mapRowsToHits(rows, snippetQuery) {
|
|
|
410
651
|
function ftsSearch(query, type, limit) {
|
|
411
652
|
const matchExpr = toFtsMatchExpr(query);
|
|
412
653
|
if (matchExpr === null) return [];
|
|
413
|
-
const db =
|
|
654
|
+
const db = getReadDb(globalDbPath());
|
|
414
655
|
const rows = type !== void 0 ? db.prepare(
|
|
415
656
|
`SELECT c.entry_id AS id, c.cache_type AS cacheType, c.label AS label, c.content AS content, c.stored_at AS storedAt
|
|
416
657
|
FROM cache_recall_fts
|
|
@@ -431,7 +672,7 @@ function ftsSearch(query, type, limit) {
|
|
|
431
672
|
function likeSearch(query, type, limit) {
|
|
432
673
|
const trimmed = query.trim();
|
|
433
674
|
if (!trimmed) return [];
|
|
434
|
-
const db =
|
|
675
|
+
const db = getReadDb(globalDbPath());
|
|
435
676
|
const needle = `%${trimmed.replace(/\\/g, "\\\\").replace(/[%_]/g, (c) => `\\${c}`)}%`;
|
|
436
677
|
const rows = type !== void 0 ? db.prepare(
|
|
437
678
|
`SELECT entry_id AS id, cache_type AS cacheType, label, content, stored_at AS storedAt
|
|
@@ -452,7 +693,7 @@ function listRecentRecall(opts = {}) {
|
|
|
452
693
|
const limit = opts.limit ?? RECALL_DEFAULT_LIMIT;
|
|
453
694
|
const columns = `SELECT entry_id AS id, cache_type AS cacheType, label, content, stored_at AS storedAt FROM cache_recall`;
|
|
454
695
|
try {
|
|
455
|
-
const db =
|
|
696
|
+
const db = getReadDb(globalDbPath());
|
|
456
697
|
const rows = opts.type !== void 0 ? db.prepare(`${columns} WHERE cache_type = ? ORDER BY stored_at DESC LIMIT ?`).all(opts.type, limit) : db.prepare(`${columns} ORDER BY stored_at DESC LIMIT ?`).all(limit);
|
|
457
698
|
return mapRowsToHits(rows, "");
|
|
458
699
|
} catch {
|
|
@@ -476,401 +717,29 @@ function searchRecall(query, opts = {}) {
|
|
|
476
717
|
}
|
|
477
718
|
}
|
|
478
719
|
|
|
479
|
-
// src/bash_output_cache.ts
|
|
480
|
-
var BASH_OUTPUT_SUBDIR = "bash_outputs";
|
|
481
|
-
var _byId = /* @__PURE__ */ new Map();
|
|
482
|
-
var COMMAND_PATTERNS = {
|
|
483
|
-
gitMutable: /^\s*git\s+(diff|status)\b/i,
|
|
484
|
-
gitImmutable: /^\s*git\s+show\s+[0-9a-f]{40}\b/i,
|
|
485
|
-
gitDiffScoped: /\s--\s+\S/,
|
|
486
|
-
dirListing: /^\s*(?:ls|eza|exa|dir|Get-ChildItem|gci)\b/i,
|
|
487
|
-
depList: /^\s*(?:npm\s+(?:--?[a-zA-Z0-9_-]+(?:\s+|=))*(?:ls|list)\b|pip\s+(?:--?[a-zA-Z0-9_-]+(?:\s+|=))*(?:list|freeze)\b|uv\s+pip\s+(?:--?[a-zA-Z0-9_-]+(?:\s+|=))*(?:list|freeze)\b|pnpm\s+(?:--?[a-zA-Z0-9_-]+(?:\s+|=))*(?:list|ls)\b|yarn\s+(?:--?[a-zA-Z0-9_-]+(?:\s+|=))*(?:list)\b|cargo\s+(?:--?[a-zA-Z0-9_-]+(?:\s+|=))*tree\b|bundle\s+(?:--?[a-zA-Z0-9_-]+(?:\s+|=))*(?:list|show)\b|composer\s+(?:--?[a-zA-Z0-9_-]+(?:\s+|=))*show\b)/i,
|
|
488
|
-
npmInstall: /^\s*npm\s+(?:--?[a-zA-Z0-9_-]+(?:\s+|=))*(?:install|ci)\b/i,
|
|
489
|
-
npmAudit: /^\s*npm\s+(?:--?[a-zA-Z0-9_-]+(?:\s+|=))*audit\b(?!.*(?:--fix|fix)\b)/i,
|
|
490
|
-
npmOutdated: /^\s*npm\s+(?:--?[a-zA-Z0-9_-]+(?:\s+|=))*outdated\b/i,
|
|
491
|
-
envProbe: /^\s*(?:node\s+(?:-v|--version)|npm\s+(?:-v|--version)|python3?\s+(?:(?:-V)\b|--?version)|git\s+--version|uv\s+--version|go\s+version|rustc\s+--version|cargo\s+--version|java\s+--version|ruby\s+--version|gem\s+--version|php\s+--version|which\b|where\b)/i,
|
|
492
|
-
npx: /^(?!.*\b(?:install|add|remove|uninstall|i|rm|update|upgrade|set|get|publish|link|ci|audit|shrinkwrap|dedupe|prune|rebuild)\b)\s*npx\s+(?:--?yes\s+)?/i,
|
|
493
|
-
gitPush: /^\s*git\s+push\b/i,
|
|
494
|
-
testRunner: /^\s*(?:npx\s+)?(?:pytest|vitest|jest|go\s+test)\b/i,
|
|
495
|
-
lintCommand: /^\s*(?:(?:npx\s+)?eslint|(?:uv\s+run\s+)?ruff)\b/i,
|
|
496
|
-
npmRunScript: /^\s*npm\s+run(?:-script)?\b/i,
|
|
497
|
-
catCommand: /^\s*cat\b/i
|
|
498
|
-
};
|
|
499
|
-
var DEP_LOCKFILES = {
|
|
500
|
-
npm: ["package-lock.json", "yarn.lock"],
|
|
501
|
-
pip: ["requirements.txt"],
|
|
502
|
-
uv: ["uv.lock", "requirements.txt"],
|
|
503
|
-
pnpm: ["pnpm-lock.yaml"],
|
|
504
|
-
yarn: ["yarn.lock"],
|
|
505
|
-
cargo: ["Cargo.lock"],
|
|
506
|
-
bundle: ["Gemfile.lock"],
|
|
507
|
-
composer: ["composer.lock"]
|
|
508
|
-
};
|
|
509
|
-
function isCommandOfType(cmd, type) {
|
|
510
|
-
const pattern = COMMAND_PATTERNS[type];
|
|
511
|
-
return pattern?.test(cmd) ?? false;
|
|
512
|
-
}
|
|
513
|
-
var isGitMutableCommand = (cmd) => isCommandOfType(cmd, "gitMutable");
|
|
514
|
-
var isDirListingCommand = (cmd) => isCommandOfType(cmd, "dirListing");
|
|
515
|
-
var isDepListCommand = (cmd) => isCommandOfType(cmd, "depList");
|
|
516
|
-
var isNpmInstallCommand = (cmd) => isCommandOfType(cmd, "npmInstall");
|
|
517
|
-
var isNpmAuditCommand = (cmd) => isCommandOfType(cmd, "npmAudit");
|
|
518
|
-
var isNpmOutdatedCommand = (cmd) => isCommandOfType(cmd, "npmOutdated");
|
|
519
|
-
var isGitPushCommand = (cmd) => isCommandOfType(cmd, "gitPush");
|
|
520
|
-
var isTestRunnerCommand2 = (cmd) => isCommandOfType(cmd, "testRunner");
|
|
521
|
-
var isLintCommand = (cmd) => isCommandOfType(cmd, "lintCommand");
|
|
522
|
-
var isNpmRunScriptCommand = (cmd) => isCommandOfType(cmd, "npmRunScript");
|
|
523
|
-
var isCatCommand = (cmd) => isCommandOfType(cmd, "catCommand");
|
|
524
|
-
function isScopedGitStatusOrDiffStatCommand(cmd) {
|
|
525
|
-
if (!isCommandOfType(cmd, "gitMutable")) return false;
|
|
526
|
-
if (!isCommandOfType(cmd, "gitDiffScoped")) return false;
|
|
527
|
-
if (/^\s*git\s+diff\b/i.test(cmd) && !/--stat\b/.test(cmd)) return false;
|
|
528
|
-
return true;
|
|
529
|
-
}
|
|
530
|
-
function gitStateFingerprintSync(cwd) {
|
|
531
|
-
try {
|
|
532
|
-
const headResult = runGit(["rev-parse", "HEAD"], { cwd });
|
|
533
|
-
if (headResult.exitCode !== 0) return null;
|
|
534
|
-
const headSha = headResult.stdout.trim();
|
|
535
|
-
let statusHash = "";
|
|
536
|
-
const statusResult = runGit(["status", "--porcelain"], { cwd });
|
|
537
|
-
if (statusResult.exitCode === 0) {
|
|
538
|
-
statusHash = shortFingerprint(statusResult.stdout);
|
|
539
|
-
}
|
|
540
|
-
const key = `${headSha}\0${statusHash}`;
|
|
541
|
-
return shortFingerprint(key);
|
|
542
|
-
} catch {
|
|
543
|
-
return null;
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
var DIR_FINGERPRINT_LISTING_CAP_ENTRIES = 1e4;
|
|
547
|
-
function dirStateFingerprintSync(path) {
|
|
548
|
-
try {
|
|
549
|
-
const stat = statSync(path);
|
|
550
|
-
if (!stat.isDirectory()) return null;
|
|
551
|
-
const entries = readdirSync(path);
|
|
552
|
-
if (entries.length <= DIR_FINGERPRINT_LISTING_CAP_ENTRIES) {
|
|
553
|
-
return shortFingerprint(entries.slice().sort().join("\0"));
|
|
554
|
-
}
|
|
555
|
-
return shortFingerprint(stat.mtimeMs.toString());
|
|
556
|
-
} catch {
|
|
557
|
-
return null;
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
var FILE_FINGERPRINT_CONTENT_CAP_BYTES = 2 * 1024 * 1024;
|
|
561
|
-
function fileStateFingerprintSync(path) {
|
|
562
|
-
try {
|
|
563
|
-
const stat = statSync(path);
|
|
564
|
-
if (!stat.isFile()) return null;
|
|
565
|
-
if (stat.size <= FILE_FINGERPRINT_CONTENT_CAP_BYTES) {
|
|
566
|
-
return shortFingerprint(readFileSync(path));
|
|
567
|
-
}
|
|
568
|
-
return shortFingerprint(`${stat.mtimeMs}\0${stat.size}`);
|
|
569
|
-
} catch {
|
|
570
|
-
return null;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
function depLockfileFingerprintSync(cmd, cwd) {
|
|
574
|
-
if (!cwd) return null;
|
|
575
|
-
const stripped = cmd.trim();
|
|
576
|
-
const firstToken = stripped.split(/\s+/)[0]?.toLowerCase() || "";
|
|
577
|
-
if (!firstToken) return null;
|
|
578
|
-
const candidates = firstToken === "uv" ? DEP_LOCKFILES["uv"] : DEP_LOCKFILES[firstToken];
|
|
579
|
-
if (!candidates) return null;
|
|
580
|
-
for (const lockfile of candidates) {
|
|
581
|
-
try {
|
|
582
|
-
const content = readFileSync(resolve(cwd, lockfile));
|
|
583
|
-
return shortFingerprint(content);
|
|
584
|
-
} catch {
|
|
585
|
-
continue;
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
return null;
|
|
589
|
-
}
|
|
590
|
-
function normalizeCommandForCacheKey(cmd) {
|
|
591
|
-
const trimmed = cmd.trim();
|
|
592
|
-
const tokens = [];
|
|
593
|
-
let current = "";
|
|
594
|
-
let quoteChar = null;
|
|
595
|
-
const flush = () => {
|
|
596
|
-
if (current.length > 0) {
|
|
597
|
-
tokens.push(current);
|
|
598
|
-
current = "";
|
|
599
|
-
}
|
|
600
|
-
};
|
|
601
|
-
for (let i = 0; i < trimmed.length; i++) {
|
|
602
|
-
const ch = trimmed[i];
|
|
603
|
-
if (quoteChar !== null) {
|
|
604
|
-
current += ch;
|
|
605
|
-
if (ch === quoteChar) quoteChar = null;
|
|
606
|
-
continue;
|
|
607
|
-
}
|
|
608
|
-
if (ch === '"' || ch === "'") {
|
|
609
|
-
quoteChar = ch;
|
|
610
|
-
current += ch;
|
|
611
|
-
continue;
|
|
612
|
-
}
|
|
613
|
-
if (/\s/.test(ch)) {
|
|
614
|
-
flush();
|
|
615
|
-
continue;
|
|
616
|
-
}
|
|
617
|
-
current += ch === "\\" ? "/" : ch;
|
|
618
|
-
}
|
|
619
|
-
flush();
|
|
620
|
-
const normalized_tokens = tokens.map((token) => {
|
|
621
|
-
if (token.startsWith("-") || ["&&", "||", "|", ">", ">>", ";", "&"].includes(token)) {
|
|
622
|
-
return token;
|
|
623
|
-
}
|
|
624
|
-
if (token.startsWith("./") && !token.startsWith("../")) {
|
|
625
|
-
token = token.slice(2);
|
|
626
|
-
}
|
|
627
|
-
if (token.endsWith("/") && token !== "/") {
|
|
628
|
-
token = token.slice(0, -1);
|
|
629
|
-
}
|
|
630
|
-
return token || ".";
|
|
631
|
-
});
|
|
632
|
-
return normalized_tokens.join(" ");
|
|
633
|
-
}
|
|
634
|
-
function commandHashSync(command, cwd = null) {
|
|
635
|
-
const normalized = normalizeCommandForCacheKey(command);
|
|
636
|
-
let key = cwd ? `${normalizePath(cwd)}\0${normalized}` : normalized;
|
|
637
|
-
if (cwd && isGitMutableCommand(command)) {
|
|
638
|
-
const fp = gitStateFingerprintSync(cwd);
|
|
639
|
-
if (fp) key = `${key}\0git:${fp}`;
|
|
640
|
-
}
|
|
641
|
-
if (cwd && isDirListingCommand(command)) {
|
|
642
|
-
const target = extractFirstPathArg(command, cwd, cwd);
|
|
643
|
-
if (target) {
|
|
644
|
-
const fp = dirStateFingerprintSync(target);
|
|
645
|
-
if (fp) key = `${key}\0dir:${fp}`;
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
if (isDepListCommand(command)) {
|
|
649
|
-
const fp = depLockfileFingerprintSync(command, cwd);
|
|
650
|
-
if (fp) key = `${key}\0lockfile:${fp}`;
|
|
651
|
-
}
|
|
652
|
-
if (cwd && (isNpmInstallCommand(command) || isNpmAuditCommand(command) || isNpmOutdatedCommand(command))) {
|
|
653
|
-
const fp = depLockfileFingerprintSync(command, cwd);
|
|
654
|
-
if (fp) key = `${key}\0npm-install:${fp}`;
|
|
655
|
-
}
|
|
656
|
-
return shortFingerprint(key);
|
|
657
|
-
}
|
|
658
|
-
function commandHash(command, cwd = null) {
|
|
659
|
-
return Promise.resolve(commandHashSync(command, cwd));
|
|
660
|
-
}
|
|
661
|
-
function bashOutputIdSync(command, output, cwd = null) {
|
|
662
|
-
return shortFingerprint(`${commandHashSync(command, cwd)}\0${output}`);
|
|
663
|
-
}
|
|
664
|
-
function computeBashFingerprints(command, cwd) {
|
|
665
|
-
const fingerprints = {};
|
|
666
|
-
if (cwd && (isGitMutableCommand(command) || isGitPushCommand(command) || isTestRunnerCommand2(command) || isLintCommand(command) || isBuildCommand(command) || isNpmRunScriptCommand(command))) {
|
|
667
|
-
const fp = gitStateFingerprintSync(cwd);
|
|
668
|
-
if (fp) fingerprints.git = fp;
|
|
669
|
-
}
|
|
670
|
-
if (cwd && isDirListingCommand(command)) {
|
|
671
|
-
const target = extractFirstPathArg(command, cwd, cwd);
|
|
672
|
-
if (target) {
|
|
673
|
-
const fp = dirStateFingerprintSync(target);
|
|
674
|
-
if (fp) fingerprints.dir = fp;
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
if (isDepListCommand(command) || cwd && (isNpmInstallCommand(command) || isNpmAuditCommand(command) || isNpmOutdatedCommand(command))) {
|
|
678
|
-
const fp = depLockfileFingerprintSync(command, cwd);
|
|
679
|
-
if (fp) fingerprints.lockfile = fp;
|
|
680
|
-
}
|
|
681
|
-
if (cwd && isCatCommand(command)) {
|
|
682
|
-
const target = extractFirstPathArg(command, cwd, null);
|
|
683
|
-
if (target) {
|
|
684
|
-
const fp = fileStateFingerprintSync(target);
|
|
685
|
-
if (fp) fingerprints.file = fp;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
return Object.keys(fingerprints).length > 0 ? fingerprints : void 0;
|
|
689
|
-
}
|
|
690
|
-
function isBashEntryStale(entry, command, cwd) {
|
|
691
|
-
const stored = entry.fingerprints;
|
|
692
|
-
if (!stored) return false;
|
|
693
|
-
const current = computeBashFingerprints(command, cwd);
|
|
694
|
-
if (stored.git !== void 0 && stored.git !== current?.git) return true;
|
|
695
|
-
if (stored.dir !== void 0 && stored.dir !== current?.dir) return true;
|
|
696
|
-
if (stored.lockfile !== void 0 && stored.lockfile !== current?.lockfile) return true;
|
|
697
|
-
if (stored.file !== void 0 && stored.file !== current?.file) return true;
|
|
698
|
-
return false;
|
|
699
|
-
}
|
|
700
|
-
function tokenizeShellArgs(cmd) {
|
|
701
|
-
const trimmed = cmd.trim();
|
|
702
|
-
const tokens = [];
|
|
703
|
-
let current = "";
|
|
704
|
-
let quoteChar = null;
|
|
705
|
-
let hasToken = false;
|
|
706
|
-
for (let i = 0; i < trimmed.length; i++) {
|
|
707
|
-
const ch = trimmed[i];
|
|
708
|
-
if (quoteChar !== null) {
|
|
709
|
-
if (ch === quoteChar) {
|
|
710
|
-
quoteChar = null;
|
|
711
|
-
} else {
|
|
712
|
-
current += ch;
|
|
713
|
-
}
|
|
714
|
-
continue;
|
|
715
|
-
}
|
|
716
|
-
if (ch === '"' || ch === "'") {
|
|
717
|
-
quoteChar = ch;
|
|
718
|
-
hasToken = true;
|
|
719
|
-
continue;
|
|
720
|
-
}
|
|
721
|
-
if (/\s/.test(ch)) {
|
|
722
|
-
if (hasToken) {
|
|
723
|
-
tokens.push(current);
|
|
724
|
-
current = "";
|
|
725
|
-
hasToken = false;
|
|
726
|
-
}
|
|
727
|
-
continue;
|
|
728
|
-
}
|
|
729
|
-
current += ch;
|
|
730
|
-
hasToken = true;
|
|
731
|
-
}
|
|
732
|
-
if (hasToken) tokens.push(current);
|
|
733
|
-
return tokens;
|
|
734
|
-
}
|
|
735
|
-
function extractFirstPathArg(cmd, cwd, fallback) {
|
|
736
|
-
const tokens = tokenizeShellArgs(cmd);
|
|
737
|
-
for (let i = 1; i < tokens.length; i++) {
|
|
738
|
-
const token = tokens[i];
|
|
739
|
-
if (!token.startsWith("-")) {
|
|
740
|
-
if (!token.startsWith("/")) {
|
|
741
|
-
return resolve(cwd, token);
|
|
742
|
-
}
|
|
743
|
-
return token;
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
return fallback;
|
|
747
|
-
}
|
|
748
|
-
var ISSUE_LINE_PATTERN = /\b(?:error|fail(?:ed|ure)?|warning)\b/i;
|
|
749
|
-
function summarizeOutputDelta(oldOutput, newOutput) {
|
|
750
|
-
if (oldOutput === newOutput) return null;
|
|
751
|
-
const oldLines = oldOutput.split("\n");
|
|
752
|
-
const newLines = newOutput.split("\n");
|
|
753
|
-
const oldIssueLines = oldLines.filter((l) => ISSUE_LINE_PATTERN.test(l));
|
|
754
|
-
if (oldIssueLines.length > 0) {
|
|
755
|
-
const newIssueLines = newLines.filter((l) => ISSUE_LINE_PATTERN.test(l));
|
|
756
|
-
const priorTotal = oldIssueLines.length;
|
|
757
|
-
const availableCounts = /* @__PURE__ */ new Map();
|
|
758
|
-
for (const l of newIssueLines) availableCounts.set(l, (availableCounts.get(l) ?? 0) + 1);
|
|
759
|
-
let resolved = 0;
|
|
760
|
-
for (const l of oldIssueLines) {
|
|
761
|
-
const avail = availableCounts.get(l) ?? 0;
|
|
762
|
-
if (avail > 0) {
|
|
763
|
-
availableCounts.set(l, avail - 1);
|
|
764
|
-
} else {
|
|
765
|
-
resolved++;
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
const remaining = newIssueLines.length;
|
|
769
|
-
return `[token-goat: delta] ${resolved} of ${priorTotal} prior issues resolved; remaining: ${remaining}`;
|
|
770
|
-
}
|
|
771
|
-
return `[token-goat: delta] output changed: ${oldLines.length} -> ${newLines.length} lines`;
|
|
772
|
-
}
|
|
773
|
-
function storeBashOutputSync(command, output, exitCode, cwd = null) {
|
|
774
|
-
const id = bashOutputIdSync(command, output, cwd);
|
|
775
|
-
const commandKey = commandHashSync(command, cwd);
|
|
776
|
-
const fingerprints = computeBashFingerprints(command, cwd);
|
|
777
|
-
const redactedOutput = redactSecrets(output).text;
|
|
778
|
-
const redactedCommand = redactSecrets(command).text;
|
|
779
|
-
const entry = {
|
|
780
|
-
id,
|
|
781
|
-
command: redactedCommand,
|
|
782
|
-
output: redactedOutput,
|
|
783
|
-
exitCode,
|
|
784
|
-
storedAt: Date.now(),
|
|
785
|
-
sizeBytes: Buffer.byteLength(redactedOutput, "utf-8"),
|
|
786
|
-
...fingerprints ? { fingerprints } : {}
|
|
787
|
-
};
|
|
788
|
-
_byId.set(id, entry);
|
|
789
|
-
_byId.set(commandKey, entry);
|
|
790
|
-
storeBlob(BASH_OUTPUT_SUBDIR, id, entry);
|
|
791
|
-
if (commandKey !== id) storeBlob(BASH_OUTPUT_SUBDIR, commandKey, { latestId: id });
|
|
792
|
-
indexRecallEntry("bash", id, redactedCommand, `${redactedCommand}
|
|
793
|
-
${redactedOutput}`, entry.storedAt);
|
|
794
|
-
return id;
|
|
795
|
-
}
|
|
796
|
-
function coerceBashRedirect(raw) {
|
|
797
|
-
if (raw === null || typeof raw !== "object") return null;
|
|
798
|
-
const latest = raw["latestId"];
|
|
799
|
-
return typeof latest === "string" && latest.length > 0 ? latest : null;
|
|
800
|
-
}
|
|
801
|
-
function storeBashOutput(command, output, exitCode, cwd = null) {
|
|
802
|
-
return Promise.resolve(storeBashOutputSync(command, output, exitCode, cwd));
|
|
803
|
-
}
|
|
804
|
-
function coerceBashEntry(raw) {
|
|
805
|
-
if (raw === null || typeof raw !== "object") return null;
|
|
806
|
-
const o = raw;
|
|
807
|
-
if (typeof o["id"] !== "string" || typeof o["command"] !== "string" || typeof o["output"] !== "string" || typeof o["exitCode"] !== "number" || typeof o["storedAt"] !== "number" || typeof o["sizeBytes"] !== "number") {
|
|
808
|
-
return null;
|
|
809
|
-
}
|
|
810
|
-
const entry = {
|
|
811
|
-
id: o["id"],
|
|
812
|
-
command: o["command"],
|
|
813
|
-
output: o["output"],
|
|
814
|
-
exitCode: o["exitCode"],
|
|
815
|
-
storedAt: o["storedAt"],
|
|
816
|
-
sizeBytes: o["sizeBytes"]
|
|
817
|
-
};
|
|
818
|
-
const rawFingerprints = o["fingerprints"];
|
|
819
|
-
if (rawFingerprints !== null && typeof rawFingerprints === "object") {
|
|
820
|
-
const f = rawFingerprints;
|
|
821
|
-
const fingerprints = {};
|
|
822
|
-
if (typeof f["git"] === "string") fingerprints.git = f["git"];
|
|
823
|
-
if (typeof f["dir"] === "string") fingerprints.dir = f["dir"];
|
|
824
|
-
if (typeof f["lockfile"] === "string") fingerprints.lockfile = f["lockfile"];
|
|
825
|
-
if (typeof f["file"] === "string") fingerprints.file = f["file"];
|
|
826
|
-
if (Object.keys(fingerprints).length > 0) return { ...entry, fingerprints };
|
|
827
|
-
}
|
|
828
|
-
return entry;
|
|
829
|
-
}
|
|
830
|
-
function getBashOutput(id) {
|
|
831
|
-
const hit = _byId.get(id);
|
|
832
|
-
if (hit !== void 0) return hit;
|
|
833
|
-
if (isBlobStale(BASH_OUTPUT_SUBDIR, id)) return null;
|
|
834
|
-
const raw = loadBlob(BASH_OUTPUT_SUBDIR, id);
|
|
835
|
-
const target = coerceBashRedirect(raw);
|
|
836
|
-
if (target !== null) {
|
|
837
|
-
if (isBlobStale(BASH_OUTPUT_SUBDIR, target)) return null;
|
|
838
|
-
const latest = coerceBashEntry(loadBlob(BASH_OUTPUT_SUBDIR, target));
|
|
839
|
-
if (latest === null) return null;
|
|
840
|
-
_byId.set(target, latest);
|
|
841
|
-
_byId.set(id, latest);
|
|
842
|
-
return latest;
|
|
843
|
-
}
|
|
844
|
-
const entry = coerceBashEntry(raw);
|
|
845
|
-
if (entry === null) return null;
|
|
846
|
-
_byId.set(id, entry);
|
|
847
|
-
return entry;
|
|
848
|
-
}
|
|
849
|
-
registerReset(() => {
|
|
850
|
-
_byId = /* @__PURE__ */ new Map();
|
|
851
|
-
}, { perRequest: true });
|
|
852
|
-
|
|
853
720
|
export {
|
|
721
|
+
parsePorcelainZ,
|
|
722
|
+
DEFAULT_MAX_COUNT,
|
|
723
|
+
DEFAULT_MAX_AGE_MS,
|
|
724
|
+
blobPath,
|
|
725
|
+
isBlobStale,
|
|
726
|
+
storeBlob,
|
|
727
|
+
loadBlob,
|
|
728
|
+
listBlobs,
|
|
729
|
+
pruneBlobs,
|
|
730
|
+
sweepCacheRoots,
|
|
854
731
|
isLockFile,
|
|
855
732
|
isManifestFile,
|
|
856
733
|
isInBuildDir,
|
|
857
734
|
isGeneratedFile,
|
|
858
735
|
isBuildCommand,
|
|
859
736
|
isTestRunnerCommand,
|
|
737
|
+
isDevServerCommand,
|
|
860
738
|
getMonitoringRecallHint,
|
|
739
|
+
snippetAround,
|
|
861
740
|
RECALL_DEFAULT_LIMIT,
|
|
862
741
|
isRecallCacheType,
|
|
863
742
|
indexRecallEntry,
|
|
864
743
|
listRecentRecall,
|
|
865
|
-
searchRecall
|
|
866
|
-
BASH_OUTPUT_SUBDIR,
|
|
867
|
-
isScopedGitStatusOrDiffStatCommand,
|
|
868
|
-
normalizeCommandForCacheKey,
|
|
869
|
-
commandHash,
|
|
870
|
-
bashOutputIdSync,
|
|
871
|
-
isBashEntryStale,
|
|
872
|
-
summarizeOutputDelta,
|
|
873
|
-
storeBashOutputSync,
|
|
874
|
-
storeBashOutput,
|
|
875
|
-
getBashOutput
|
|
744
|
+
searchRecall
|
|
876
745
|
};
|