token-goat 2.9.30 → 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 +24 -7
- package/SECURITY.md +10 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- 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/{token-goat-chunk-QSBRTGM2.mjs → token-goat-chunk-25TRAWET.mjs} +17 -7
- package/dist/token-goat-chunk-2KXO6V2B.mjs +203 -0
- package/dist/{token-goat-chunk-IVKIZWAB.mjs → token-goat-chunk-2M7E4PF7.mjs} +41 -12
- package/dist/{token-goat-chunk-SMVRN2HU.mjs → token-goat-chunk-2UPZGKKY.mjs} +2 -2
- 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-KWPNJBDH.mjs → token-goat-chunk-4GILLLWY.mjs} +7 -4
- package/dist/{token-goat-chunk-67TQJ76B.mjs → token-goat-chunk-4NAPX7BA.mjs} +36 -3
- package/dist/{token-goat-chunk-PU7V3FD6.mjs → token-goat-chunk-4SC7UJYV.mjs} +3354 -2553
- package/dist/token-goat-chunk-4SMRO4TO.mjs +366 -0
- package/dist/{token-goat-chunk-AFLYLHDH.mjs → token-goat-chunk-4ZBFWLXF.mjs} +283 -427
- package/dist/{token-goat-chunk-JDWCRD6M.mjs → token-goat-chunk-57BIAXJL.mjs} +73 -40
- package/dist/token-goat-chunk-5AC66HNP.mjs +115 -0
- package/dist/token-goat-chunk-5IMLKSOP.mjs +145 -0
- package/dist/token-goat-chunk-646E6U44.mjs +398 -0
- package/dist/token-goat-chunk-65N4RHP4.mjs +33 -0
- package/dist/{token-goat-chunk-JN4XMLSD.mjs → token-goat-chunk-6DG6HWP3.mjs} +8 -2
- package/dist/token-goat-chunk-6ENQSNRZ.mjs +573 -0
- package/dist/token-goat-chunk-6ZY4GNF2.mjs +91 -0
- package/dist/{token-goat-chunk-VPBBTSJR.mjs → token-goat-chunk-76FGDLRO.mjs} +262 -255
- package/dist/{token-goat-chunk-7IN2MKDS.mjs → token-goat-chunk-7EZTZOMC.mjs} +121 -289
- package/dist/{token-goat-chunk-OJBNYTJP.mjs → token-goat-chunk-7MAOA6X4.mjs} +640 -80
- package/dist/token-goat-chunk-7R2ZVVAX.mjs +218 -0
- package/dist/{token-goat-chunk-PD5VKH46.mjs → token-goat-chunk-AUNGYYQX.mjs} +2 -2
- package/dist/{token-goat-chunk-HG45AF2B.mjs → token-goat-chunk-AUQYRMMH.mjs} +794 -37
- package/dist/token-goat-chunk-B3PEKBYG.mjs +128 -0
- package/dist/{token-goat-chunk-A3CK6N5Z.mjs → token-goat-chunk-BA4HI6BW.mjs} +1309 -110
- package/dist/{token-goat-chunk-JB6QN6VF.mjs → token-goat-chunk-BFCWY73P.mjs} +59 -23
- package/dist/{token-goat-chunk-B45VMIIH.mjs → token-goat-chunk-BWGFUZZE.mjs} +7 -5
- package/dist/{token-goat-chunk-P4QMM4WK.mjs → token-goat-chunk-C75NA7PL.mjs} +50 -23
- package/dist/token-goat-chunk-CBIQ7WTD.mjs +87 -0
- package/dist/token-goat-chunk-CETM74KC.mjs +307 -0
- package/dist/{token-goat-chunk-H2PHHGM5.mjs → token-goat-chunk-CIMQ2BB3.mjs} +57 -12
- package/dist/{token-goat-chunk-N2NMER56.mjs → token-goat-chunk-CJLS3CDL.mjs} +46 -4
- package/dist/{token-goat-chunk-VES7EL7O.mjs → token-goat-chunk-CO3UYX6G.mjs} +1 -1
- package/dist/token-goat-chunk-COPNXRJM.mjs +154 -0
- package/dist/token-goat-chunk-CSJ5L3NL.mjs +479 -0
- package/dist/{token-goat-chunk-4LCCNRTG.mjs → token-goat-chunk-CVCEVUGK.mjs} +8 -6
- package/dist/{token-goat-chunk-B2RZZCSS.mjs → token-goat-chunk-CXHOFN7R.mjs} +37 -20
- package/dist/token-goat-chunk-D735C4QM.mjs +603 -0
- package/dist/{token-goat-chunk-APGZXSPS.mjs → token-goat-chunk-DGS2LVNA.mjs} +47 -30
- package/dist/{token-goat-chunk-54K3EUV3.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-5BCIJXMO.mjs → token-goat-chunk-EELTBKDM.mjs} +14 -10
- package/dist/{token-goat-chunk-W3QCJS6G.mjs → token-goat-chunk-F4HYL64R.mjs} +8 -6
- package/dist/token-goat-chunk-F6PAUIEK.mjs +624 -0
- package/dist/token-goat-chunk-FDSREWLX.mjs +692 -0
- package/dist/token-goat-chunk-GGGG7RWB.mjs +236 -0
- package/dist/{token-goat-chunk-C63JQV5K.mjs → token-goat-chunk-GL3ETKSC.mjs} +233 -15
- package/dist/token-goat-chunk-GVB2MUST.mjs +1298 -0
- package/dist/token-goat-chunk-GWFLAUMQ.mjs +307 -0
- package/dist/{token-goat-chunk-ZEJVMUQH.mjs → token-goat-chunk-HLPW63A7.mjs} +2 -2
- package/dist/{token-goat-chunk-GOLEOXZP.mjs → token-goat-chunk-HU4TORC5.mjs} +44 -26
- package/dist/{token-goat-chunk-Z57YODA2.mjs → token-goat-chunk-I7VKZZAW.mjs} +2 -2
- package/dist/{token-goat-chunk-NYKZLXMK.mjs → token-goat-chunk-IA6XSPE3.mjs} +6 -6
- package/dist/{token-goat-chunk-E3OQX2XT.mjs → token-goat-chunk-IAGXMHIK.mjs} +81 -42
- package/dist/{token-goat-chunk-HYBFA5X3.mjs → token-goat-chunk-IK2DRMFX.mjs} +24 -68
- package/dist/{token-goat-chunk-COBQGL5S.mjs → token-goat-chunk-INNPTRUX.mjs} +249 -299
- package/dist/{token-goat-chunk-7NADEDKJ.mjs → token-goat-chunk-JJ5BX4F4.mjs} +6 -1
- package/dist/{token-goat-chunk-PEPTHRFF.mjs → token-goat-chunk-JVFSHVFJ.mjs} +6 -6
- package/dist/token-goat-chunk-KGEFFSHD.mjs +50 -0
- package/dist/token-goat-chunk-KQBLRPBN.mjs +433 -0
- package/dist/{token-goat-chunk-Q5VTGRH7.mjs → token-goat-chunk-LCNQ2CNN.mjs} +55 -319
- 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-T4FK7VOV.mjs → token-goat-chunk-MHX7XCC3.mjs} +2 -1
- package/dist/token-goat-chunk-N5LSOVSU.mjs +137 -0
- package/dist/{token-goat-chunk-LOBGHXPB.mjs → token-goat-chunk-N5MMR2IW.mjs} +1 -1
- package/dist/token-goat-chunk-N7B3JQ2C.mjs +160 -0
- package/dist/{token-goat-chunk-RHXKCZX3.mjs → token-goat-chunk-NISNMD7T.mjs} +2182 -2959
- package/dist/token-goat-chunk-NMD42SFQ.mjs +434 -0
- package/dist/token-goat-chunk-NOSS5VWY.mjs +174 -0
- package/dist/{token-goat-chunk-KQNZDCBD.mjs → token-goat-chunk-NSNSPPBG.mjs} +25 -3
- package/dist/token-goat-chunk-OBOFIHKN.mjs +38 -0
- package/dist/token-goat-chunk-OBRFJ5O5.mjs +76 -0
- package/dist/{token-goat-chunk-JTQQGXZH.mjs → token-goat-chunk-ODBT2USM.mjs} +124 -57
- 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-DZX2YDPT.mjs → token-goat-chunk-OYIYKDDT.mjs} +2 -2
- package/dist/{token-goat-chunk-QCLDAQTS.mjs → token-goat-chunk-P6HQSWQ3.mjs} +50 -53
- package/dist/token-goat-chunk-P6VGNTQT.mjs +71 -0
- package/dist/{token-goat-chunk-7BXSNBY5.mjs → token-goat-chunk-PFWIMH2E.mjs} +23 -15
- package/dist/token-goat-chunk-PJZXIS3G.mjs +39 -0
- package/dist/token-goat-chunk-PUO5INXP.mjs +606 -0
- package/dist/{token-goat-chunk-GFBSN7BD.mjs → token-goat-chunk-PX5PQWTY.mjs} +22 -250
- package/dist/token-goat-chunk-Q5QDBC6O.mjs +111 -0
- package/dist/token-goat-chunk-QFNQXSDT.mjs +40 -0
- package/dist/{token-goat-chunk-FBNQNSJK.mjs → token-goat-chunk-QH7YVYOY.mjs} +2198 -2782
- package/dist/{token-goat-chunk-64FBPDTK.mjs → token-goat-chunk-QLMUHEPB.mjs} +12 -9
- package/dist/{token-goat-chunk-RZRTDST7.mjs → token-goat-chunk-QQOJIHL3.mjs} +37 -11
- package/dist/{token-goat-chunk-XKI4SEMX.mjs → token-goat-chunk-QQTWJY2O.mjs} +19 -0
- package/dist/{token-goat-chunk-U4N3BN2W.mjs → token-goat-chunk-QYHO5CPH.mjs} +3 -2
- package/dist/token-goat-chunk-RELAVWAD.mjs +27 -0
- package/dist/{token-goat-chunk-ETBHVDB6.mjs → token-goat-chunk-RSLPOBKQ.mjs} +22 -11
- package/dist/token-goat-chunk-SAMFDIS2.mjs +712 -0
- package/dist/token-goat-chunk-SDELXLDM.mjs +48 -0
- package/dist/{token-goat-chunk-4JJS54TR.mjs → token-goat-chunk-SOAFZNNZ.mjs} +161 -38
- package/dist/{token-goat-chunk-664RTTUV.mjs → token-goat-chunk-SRTHT7KV.mjs} +21 -16
- package/dist/{token-goat-chunk-4FVIAHSI.mjs → token-goat-chunk-T5P5ACNQ.mjs} +7 -6
- package/dist/token-goat-chunk-T5YGG4V3.mjs +45 -0
- package/dist/token-goat-chunk-TAUZ4OFS.mjs +110 -0
- package/dist/{token-goat-chunk-COTXZHTS.mjs → token-goat-chunk-TM6MC754.mjs} +4 -3
- package/dist/token-goat-chunk-TWUKBOMP.mjs +72 -0
- package/dist/{token-goat-chunk-3CHUNJ2O.mjs → token-goat-chunk-U2KSB4SG.mjs} +8 -5
- package/dist/{token-goat-chunk-3Z5S4KGM.mjs → token-goat-chunk-U4WHMG6Y.mjs} +29 -49
- package/dist/{token-goat-chunk-PY533T7F.mjs → token-goat-chunk-UGJHGR5A.mjs} +21 -15
- package/dist/{token-goat-chunk-CYCEYAEO.mjs → token-goat-chunk-UOUDVA5U.mjs} +1 -1
- package/dist/{token-goat-chunk-JDHE26RP.mjs → token-goat-chunk-URRJ33GR.mjs} +16 -5
- package/dist/{token-goat-chunk-56EIMS3E.mjs → token-goat-chunk-UZOROKIS.mjs} +23 -17
- package/dist/{token-goat-chunk-CZ3LUXYZ.mjs → token-goat-chunk-VIHGGGEI.mjs} +427 -308
- package/dist/token-goat-chunk-VTJLAA7P.mjs +21 -0
- package/dist/token-goat-chunk-VWDXLT4F.mjs +678 -0
- package/dist/{token-goat-chunk-YARZFCZS.mjs → token-goat-chunk-VWZA2H4P.mjs} +62 -53
- package/dist/{token-goat-chunk-SQSSNQPE.mjs → token-goat-chunk-VXEXMJDL.mjs} +3979 -4745
- package/dist/token-goat-chunk-WBA5SKT4.mjs +547 -0
- package/dist/{token-goat-chunk-SJHWVNDQ.mjs → token-goat-chunk-WDH44VAU.mjs} +7 -4
- package/dist/token-goat-chunk-X2SUP3EI.mjs +107 -0
- package/dist/token-goat-chunk-X3BELZSJ.mjs +125 -0
- package/dist/{token-goat-chunk-FZ3NEW5O.mjs → token-goat-chunk-XLRBNZCC.mjs} +13 -8
- package/dist/{token-goat-chunk-Z44YO3QZ.mjs → token-goat-chunk-XRKUX6CM.mjs} +1 -1
- package/dist/token-goat-chunk-XX6O25RN.mjs +82 -0
- package/dist/token-goat-chunk-XZSUHBVS.mjs +65 -0
- package/dist/{token-goat-chunk-WY3L4DVT.mjs → token-goat-chunk-Y2ZTQOCL.mjs} +13 -8
- package/dist/{token-goat-chunk-UQ5UK2T7.mjs → token-goat-chunk-YB4VMGK2.mjs} +1 -1
- package/dist/token-goat-chunk-YBIIY3HR.mjs +51 -0
- package/dist/{token-goat-chunk-ZQSJMO2R.mjs → token-goat-chunk-YHVDKQBR.mjs} +105 -105
- package/dist/{token-goat-chunk-H2K3QP6H.mjs → token-goat-chunk-YJB5XLWI.mjs} +8 -6
- package/dist/{token-goat-chunk-ZCDTCVIS.mjs → token-goat-chunk-YKB6AQG3.mjs} +5 -2
- package/dist/token-goat-chunk-YMTG2YA5.mjs +35 -0
- package/dist/token-goat-chunk-YPBZYQRV.mjs +40 -0
- package/dist/{token-goat-chunk-HOJLCGDP.mjs → token-goat-chunk-YY6AVUFL.mjs} +2033 -2251
- package/dist/token-goat-chunk-Z7N5OMMP.mjs +98 -0
- package/dist/token-goat-chunk-ZNMNUPAZ.mjs +938 -0
- package/dist/token-goat-hook-client.cjs +1 -1
- package/dist/token-goat-hook-client.mjs +3 -3
- package/dist/token-goat-hook.mjs +67 -38
- package/dist/token-goat.core.mjs +4 -4
- package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
- package/docs/cli.md +40 -21
- package/docs/install.md +19 -9
- package/docs/security.md +5 -3
- package/package.json +2 -1
- package/dist/token-goat-chunk-5KDMCMF2.mjs +0 -362
- package/dist/token-goat-chunk-6QMAS7AB.mjs +0 -42
- package/dist/token-goat-chunk-7F2UBPD3.mjs +0 -397
- package/dist/token-goat-chunk-ARDNEC2U.mjs +0 -248
- package/dist/token-goat-chunk-ATCPY7EQ.mjs +0 -134
- package/dist/token-goat-chunk-EFHMMIGP.mjs +0 -68
- package/dist/token-goat-chunk-IVALLT3S.mjs +0 -48
- package/dist/token-goat-chunk-JDU3EXSU.mjs +0 -65
- package/dist/token-goat-chunk-MKPF4CL5.mjs +0 -37
- package/dist/token-goat-chunk-RC35RBUL.mjs +0 -312
- package/dist/token-goat-chunk-USILZ3T3.mjs +0 -53
- package/dist/token-goat-chunk-VL3YIFHZ.mjs +0 -2975
- package/dist/token-goat-chunk-XU4P6Z24.mjs +0 -133
- package/dist/token-goat-chunk-Y776AENC.mjs +0 -1597
|
@@ -7,28 +7,35 @@ import {
|
|
|
7
7
|
getSqliteSchema,
|
|
8
8
|
getSqliteTables,
|
|
9
9
|
runReadOnlySqliteQuery
|
|
10
|
-
} from "./token-goat-chunk-
|
|
10
|
+
} from "./token-goat-chunk-YKB6AQG3.mjs";
|
|
11
11
|
import {
|
|
12
|
+
WHOLE_FILE_NOTE_SYMBOL,
|
|
13
|
+
getNote,
|
|
14
|
+
isNoteStale,
|
|
15
|
+
listNotes
|
|
16
|
+
} from "./token-goat-chunk-COPNXRJM.mjs";
|
|
17
|
+
import {
|
|
18
|
+
CORE_SYMBOL_KINDS,
|
|
12
19
|
DELETED_TAG,
|
|
13
20
|
DIDYOUMEAN_LIMIT,
|
|
14
21
|
FIND_SCAN_LIMIT,
|
|
15
22
|
FirstRows,
|
|
16
23
|
REF_BLIND_DEF_PROBE_LIMIT,
|
|
17
24
|
UNBOUNDED_QUERY_LIMIT,
|
|
18
|
-
WHOLE_FILE_NOTE_SYMBOL,
|
|
19
25
|
buildContextWindow,
|
|
20
26
|
compareBinary,
|
|
21
27
|
confinedProjectRoot,
|
|
22
28
|
confinementRefusal,
|
|
29
|
+
couldNotReadError,
|
|
23
30
|
didYouMean,
|
|
24
|
-
|
|
25
|
-
emitErr,
|
|
31
|
+
docCommentLines,
|
|
26
32
|
emitGuarded,
|
|
27
33
|
extractExportNames,
|
|
28
34
|
extractImports,
|
|
29
35
|
fileConfinementRefusal,
|
|
30
36
|
fileExists,
|
|
31
37
|
fileIsGone,
|
|
38
|
+
fileNotFoundError,
|
|
32
39
|
filterSimilarHeadings,
|
|
33
40
|
findSpecSeparator,
|
|
34
41
|
findStructuredKeyPath,
|
|
@@ -37,7 +44,6 @@ import {
|
|
|
37
44
|
formatAmbiguity,
|
|
38
45
|
formatBareNameSpecError,
|
|
39
46
|
formatStatsSuffix,
|
|
40
|
-
getNote,
|
|
41
47
|
guardJsonRows,
|
|
42
48
|
guardText,
|
|
43
49
|
hasRealDocstring,
|
|
@@ -46,17 +52,17 @@ import {
|
|
|
46
52
|
importsExtensionFor,
|
|
47
53
|
indexFileSyncPinned,
|
|
48
54
|
indexFreshness,
|
|
49
|
-
isNoteStale,
|
|
50
55
|
isRefIndexedFile,
|
|
51
56
|
isValidUtf8,
|
|
52
57
|
largestFileSize,
|
|
53
|
-
listNotes,
|
|
54
58
|
nearNamesSkippedNote,
|
|
55
59
|
nearSymbolNames,
|
|
56
60
|
noSymbolsMessage,
|
|
57
61
|
parseCrossFileMultiSpec,
|
|
58
62
|
parseMultiFileSpec,
|
|
59
63
|
parseReadSpec,
|
|
64
|
+
parseYamlDocument,
|
|
65
|
+
parseYamlDocumentAsWritten,
|
|
60
66
|
previewLines,
|
|
61
67
|
projectStructuredFiles,
|
|
62
68
|
rankSimilarNames,
|
|
@@ -90,10 +96,27 @@ import {
|
|
|
90
96
|
typedRefsForDef,
|
|
91
97
|
unknownSymbolSuggestion,
|
|
92
98
|
warnIfFilesStale
|
|
93
|
-
} from "./token-goat-chunk-
|
|
99
|
+
} from "./token-goat-chunk-4SC7UJYV.mjs";
|
|
94
100
|
import {
|
|
101
|
+
emit,
|
|
102
|
+
emitErr,
|
|
95
103
|
parseJsonOrJsonc
|
|
96
|
-
} from "./token-goat-chunk-
|
|
104
|
+
} from "./token-goat-chunk-QQTWJY2O.mjs";
|
|
105
|
+
import {
|
|
106
|
+
emptyIndexMessage,
|
|
107
|
+
getEmbeddingCoverage,
|
|
108
|
+
isIgnoredIndexPath,
|
|
109
|
+
isIndexEmptyForProject,
|
|
110
|
+
walkProject
|
|
111
|
+
} from "./token-goat-chunk-ZNMNUPAZ.mjs";
|
|
112
|
+
import {
|
|
113
|
+
capListField,
|
|
114
|
+
guardAndFenceFileText
|
|
115
|
+
} from "./token-goat-chunk-M52KPT3C.mjs";
|
|
116
|
+
import {
|
|
117
|
+
filtersFilteredToEmptyNotice,
|
|
118
|
+
grepFilteredToEmptyNotice
|
|
119
|
+
} from "./token-goat-chunk-CJLS3CDL.mjs";
|
|
97
120
|
import {
|
|
98
121
|
MODEL_DOWNLOAD_HOST,
|
|
99
122
|
RUNTIME_DOWNLOAD_HOST,
|
|
@@ -101,34 +124,42 @@ import {
|
|
|
101
124
|
isExplicitDownload,
|
|
102
125
|
lastDownloadFailure,
|
|
103
126
|
withExplicitDownload
|
|
104
|
-
} from "./token-goat-chunk-
|
|
127
|
+
} from "./token-goat-chunk-2UPZGKKY.mjs";
|
|
105
128
|
import {
|
|
106
129
|
commentSyntaxFor
|
|
107
130
|
} from "./token-goat-chunk-5RG5SBL6.mjs";
|
|
108
131
|
import {
|
|
109
132
|
deliveredOutputBytes
|
|
110
|
-
} from "./token-goat-chunk-
|
|
133
|
+
} from "./token-goat-chunk-DOWRSMWO.mjs";
|
|
111
134
|
import {
|
|
112
135
|
NOTEBOOK_CELL_LINES_SUFFIX,
|
|
113
|
-
emptyIndexMessage,
|
|
114
136
|
formatSymbolLocation,
|
|
115
|
-
|
|
116
|
-
isIgnoredIndexPath,
|
|
117
|
-
isIndexEmptyForProject,
|
|
137
|
+
indexedSourceText,
|
|
118
138
|
isVirtualIndexedPath,
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
139
|
+
virtualIndexedScopeNote
|
|
140
|
+
} from "./token-goat-chunk-QH7YVYOY.mjs";
|
|
141
|
+
import {
|
|
142
|
+
searchEvidenceSemantically
|
|
143
|
+
} from "./token-goat-chunk-NOSS5VWY.mjs";
|
|
123
144
|
import {
|
|
124
145
|
enqueueDirtyPathSafe
|
|
125
|
-
} from "./token-goat-chunk-
|
|
146
|
+
} from "./token-goat-chunk-CIMQ2BB3.mjs";
|
|
126
147
|
import {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
148
|
+
isBlobStale,
|
|
149
|
+
loadBlob,
|
|
150
|
+
storeBlob
|
|
151
|
+
} from "./token-goat-chunk-4ZBFWLXF.mjs";
|
|
152
|
+
import {
|
|
153
|
+
CliError,
|
|
154
|
+
formatCommandError,
|
|
155
|
+
formatFailedResultText,
|
|
156
|
+
formatGitFailure
|
|
157
|
+
} from "./token-goat-chunk-CBIQ7WTD.mjs";
|
|
158
|
+
import {
|
|
159
|
+
findContainingSection,
|
|
160
|
+
listSections,
|
|
161
|
+
readSection
|
|
162
|
+
} from "./token-goat-chunk-OXFMP75N.mjs";
|
|
132
163
|
import {
|
|
133
164
|
MAX_OVER_FETCH,
|
|
134
165
|
NATIVE_RUNTIME_INSTALL,
|
|
@@ -139,15 +170,12 @@ import {
|
|
|
139
170
|
checkEmbeddingPreflight,
|
|
140
171
|
eachUnfencedLine,
|
|
141
172
|
embeddingBackendLoadError,
|
|
142
|
-
findContainingSection,
|
|
143
173
|
isAvailable,
|
|
144
|
-
listSections,
|
|
145
174
|
modelDir,
|
|
146
175
|
modelFilesPresent,
|
|
147
|
-
readSection,
|
|
148
176
|
searchSemantic,
|
|
149
177
|
wasmBinaryPresent
|
|
150
|
-
} from "./token-goat-chunk-
|
|
178
|
+
} from "./token-goat-chunk-NISNMD7T.mjs";
|
|
151
179
|
import {
|
|
152
180
|
ATX_CLASS_BREAK_RE,
|
|
153
181
|
matchAtxHeading
|
|
@@ -156,48 +184,61 @@ import {
|
|
|
156
184
|
DEFAULT_QUERY_LIMIT,
|
|
157
185
|
countRefs,
|
|
158
186
|
countSymbols,
|
|
187
|
+
distinctSymbolKinds,
|
|
159
188
|
queryRefCounts,
|
|
160
189
|
queryRefs,
|
|
161
190
|
querySymbols,
|
|
162
191
|
searchSymbolsFts
|
|
163
|
-
} from "./token-goat-chunk-
|
|
192
|
+
} from "./token-goat-chunk-IK2DRMFX.mjs";
|
|
164
193
|
import {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
} from "./token-goat-chunk-ARDNEC2U.mjs";
|
|
194
|
+
fenceFileFieldIfMatched,
|
|
195
|
+
fenceJsonStrings
|
|
196
|
+
} from "./token-goat-chunk-4NAPX7BA.mjs";
|
|
169
197
|
import {
|
|
170
|
-
|
|
171
|
-
getGlobalDb,
|
|
198
|
+
readGlobalDb,
|
|
172
199
|
recordStat,
|
|
173
200
|
savedTokensFromBytes,
|
|
174
201
|
withTelemetryWriteDb
|
|
175
|
-
} from "./token-goat-chunk-
|
|
202
|
+
} from "./token-goat-chunk-U4WHMG6Y.mjs";
|
|
176
203
|
import {
|
|
177
204
|
detectLanguage,
|
|
178
205
|
detectLanguageOfFile,
|
|
179
|
-
|
|
180
|
-
} from "./token-goat-chunk-
|
|
206
|
+
getReadDb
|
|
207
|
+
} from "./token-goat-chunk-GVB2MUST.mjs";
|
|
208
|
+
import {
|
|
209
|
+
forClient
|
|
210
|
+
} from "./token-goat-chunk-KGEFFSHD.mjs";
|
|
211
|
+
import {
|
|
212
|
+
BYTES_PER_TOKEN
|
|
213
|
+
} from "./token-goat-chunk-XX6O25RN.mjs";
|
|
214
|
+
import {
|
|
215
|
+
ensureWorkerAlive,
|
|
216
|
+
fetchBypassesProxy,
|
|
217
|
+
nodeFetchHonoursEnvProxy,
|
|
218
|
+
proxyConfigured
|
|
219
|
+
} from "./token-goat-chunk-F6PAUIEK.mjs";
|
|
181
220
|
import {
|
|
182
221
|
redactSecrets
|
|
183
|
-
} from "./token-goat-chunk-
|
|
222
|
+
} from "./token-goat-chunk-T5P5ACNQ.mjs";
|
|
184
223
|
import {
|
|
185
|
-
findProject,
|
|
186
|
-
getDisplayRoot,
|
|
187
224
|
getProjectConfigInfo,
|
|
188
225
|
loadConfig,
|
|
189
226
|
parse,
|
|
227
|
+
resolveConfigKeyLayer
|
|
228
|
+
} from "./token-goat-chunk-7EZTZOMC.mjs";
|
|
229
|
+
import {
|
|
230
|
+
findProject,
|
|
231
|
+
getDisplayRoot,
|
|
190
232
|
projectHash,
|
|
191
|
-
resolveConfigKeyLayer,
|
|
192
233
|
resolveProjectRoot,
|
|
193
234
|
shortFingerprint
|
|
194
|
-
} from "./token-goat-chunk-
|
|
235
|
+
} from "./token-goat-chunk-4GBVPH3D.mjs";
|
|
195
236
|
import {
|
|
196
237
|
MAX_ZIP_OUTPUT_BYTES,
|
|
197
238
|
ZipInputTooLargeError,
|
|
198
239
|
ZipOutputTooLargeError,
|
|
199
240
|
unzipBounded
|
|
200
|
-
} from "./token-goat-chunk-
|
|
241
|
+
} from "./token-goat-chunk-EDBDRVH5.mjs";
|
|
201
242
|
import {
|
|
202
243
|
createLazyModuleLoader
|
|
203
244
|
} from "./token-goat-chunk-AH6QILZM.mjs";
|
|
@@ -207,13 +248,17 @@ import {
|
|
|
207
248
|
escapeRegExp,
|
|
208
249
|
excludeTestsHiddenNote,
|
|
209
250
|
extractErrorMessage,
|
|
210
|
-
filtersFilteredToEmptyNotice,
|
|
211
|
-
grepFilteredToEmptyNotice,
|
|
212
251
|
isTestFile,
|
|
213
252
|
requireNonNegativeStrictInt,
|
|
214
253
|
runGit,
|
|
215
254
|
stripBom
|
|
216
|
-
} from "./token-goat-chunk-
|
|
255
|
+
} from "./token-goat-chunk-HU4TORC5.mjs";
|
|
256
|
+
import {
|
|
257
|
+
canQuoteArg,
|
|
258
|
+
echoedValue,
|
|
259
|
+
fencedCommand,
|
|
260
|
+
quotedArg
|
|
261
|
+
} from "./token-goat-chunk-GGGG7RWB.mjs";
|
|
217
262
|
import {
|
|
218
263
|
foldPath
|
|
219
264
|
} from "./token-goat-chunk-AM5V6GSX.mjs";
|
|
@@ -227,7 +272,7 @@ import {
|
|
|
227
272
|
import {
|
|
228
273
|
SKELETON_SYMBOL_CAP,
|
|
229
274
|
globalDbPath
|
|
230
|
-
} from "./token-goat-chunk-
|
|
275
|
+
} from "./token-goat-chunk-CO3UYX6G.mjs";
|
|
231
276
|
import {
|
|
232
277
|
init_define_import_meta_env
|
|
233
278
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
@@ -301,7 +346,7 @@ function explainModelDownload(result, now = Date.now()) {
|
|
|
301
346
|
}
|
|
302
347
|
if (result.status === "load_error" || !modelMissing) return result;
|
|
303
348
|
if (result.status === "no_embeddings") {
|
|
304
|
-
const message = `The embedding model (about ${MODEL_MB} MB, once) is not downloaded yet. It downloads by itself in the background, and this project's ${result.indexedFiles
|
|
349
|
+
const message = `The embedding model (about ${MODEL_MB} MB, once) is not downloaded yet. It downloads by itself in the background, and this project's ${countNoun(result.indexedFiles, "indexed file")} are embedded after it.`;
|
|
305
350
|
return rebuild("missing_model_files", false, message, `Nothing to do. To download it now instead, run \`${WARM_COMMAND}\`.`, void 0);
|
|
306
351
|
}
|
|
307
352
|
return rebuild("ready", true, `Semantic search is ready. The embedding model (about ${MODEL_MB} MB) is not downloaded yet; it is fetched on first use.`, void 0, void 0);
|
|
@@ -314,7 +359,7 @@ function offlineEmbedNotice(fileCount, rootDir) {
|
|
|
314
359
|
if (!cfg.network.offline) return null;
|
|
315
360
|
const state = resolveConfigKeyLayer("network.offline", cfg.network.offline, cfg, getProjectConfigInfo(rootDir));
|
|
316
361
|
const holder = state.layer === "env" || state.layer === "env-invalid" ? `${state.envVar} is set in your environment` : state.layer === "project" ? `${displaySafeText(state.path)} sets network.offline` : "network.offline is on in config.toml";
|
|
317
|
-
return `token-goat: index: ${fileCount} not embedded: the embedding model is not downloaded and ${holder}, so nothing will download it. symbol, read, outline and section work now; semantic falls back to keyword search. To embed them, unset it so the
|
|
362
|
+
return `token-goat: index: ${fileCount} not embedded: the embedding model is not downloaded and ${holder}, so nothing will download it. symbol, read, outline and section work now; semantic falls back to keyword search. To embed them, unset it so the model can be downloaded, or copy the pinned model files into ${modelDir()}; then run \`token-goat index\` again.`;
|
|
318
363
|
}
|
|
319
364
|
|
|
320
365
|
// src/read_symbol.ts
|
|
@@ -329,7 +374,7 @@ function stableSortImportBindsLast(rows) {
|
|
|
329
374
|
}
|
|
330
375
|
function runSymbol(opts) {
|
|
331
376
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
332
|
-
return { text: `--limit must be a positive number, got: ${opts.limit}`, code: 1 };
|
|
377
|
+
return { text: `--limit must be a positive number, got: ${echoedValue(String(opts.limit))}`, code: 1 };
|
|
333
378
|
}
|
|
334
379
|
if (opts.name !== void 0 && opts.grep !== void 0) {
|
|
335
380
|
return {
|
|
@@ -429,7 +474,7 @@ function runSymbol(opts) {
|
|
|
429
474
|
const hiddenByExcludeTests = sweep.hiddenByExcludeTests;
|
|
430
475
|
if (excludeTests && sweep.keptCount === 0 && hiddenByExcludeTests > 0) {
|
|
431
476
|
const label = opts.name ?? opts.grep ?? "*";
|
|
432
|
-
const notice = `no non-test matches for
|
|
477
|
+
const notice = `no non-test matches for ${echoedValue(label)} (${excludeTestsHiddenNote(hiddenByExcludeTests)})`;
|
|
433
478
|
if (opts.json === true) {
|
|
434
479
|
return { text: displaySafeJson({ items: [], truncated: false, totalCount: 0 }), code: 0 };
|
|
435
480
|
}
|
|
@@ -446,7 +491,19 @@ function runSymbol(opts) {
|
|
|
446
491
|
if (opts.json === true) {
|
|
447
492
|
return { text: displaySafeJson({ items: [], truncated: false, totalCount: 0 }), code: 0 };
|
|
448
493
|
}
|
|
449
|
-
let text2 = `No matches for
|
|
494
|
+
let text2 = `No matches for ${echoedValue(opts.name ?? opts.grep ?? "*")}`;
|
|
495
|
+
if (opts.kind !== void 0 && !CORE_SYMBOL_KINDS.includes(opts.kind)) {
|
|
496
|
+
const storedKinds = distinctSymbolKinds(opts.projectRoot);
|
|
497
|
+
if (!storedKinds.includes(opts.kind)) {
|
|
498
|
+
text2 += `
|
|
499
|
+
no indexed symbol has kind ${echoedValue(opts.kind)}`;
|
|
500
|
+
const lower = opts.kind.toLowerCase();
|
|
501
|
+
const recased = [.../* @__PURE__ */ new Set([...storedKinds, ...CORE_SYMBOL_KINDS])].filter((k) => k.toLowerCase() === lower);
|
|
502
|
+
const closes = recased.length > 0 ? recased : rankSimilarNames(storedKinds, opts.kind);
|
|
503
|
+
if (closes.length > 0) text2 += `
|
|
504
|
+
${didYouMean(closes)}`;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
450
507
|
const emptyIndexRoot = opts.projectRoot ?? resolveProjectRoot({ project: process.cwd() });
|
|
451
508
|
const indexEmpty = isIndexEmptyForProject(globalDbPath(), emptyIndexRoot);
|
|
452
509
|
if (opts.name !== void 0) {
|
|
@@ -459,11 +516,11 @@ function runSymbol(opts) {
|
|
|
459
516
|
const flags = [opts.kind !== void 0 ? "--kind" : null, opts.file !== void 0 ? "--file" : null].filter((f) => f !== null);
|
|
460
517
|
const widen = flags.length > 0 ? `drop ${flags.join("/")} to see it` : "widen the search scope to see it";
|
|
461
518
|
text2 += `
|
|
462
|
-
|
|
519
|
+
${echoedValue(opts.name)} IS indexed (${where}${more}) -- ${widen}`;
|
|
463
520
|
} else {
|
|
464
521
|
const near = nearSymbolNames(opts.name, rootDir);
|
|
465
|
-
const semanticHint = indexEmpty ? "" : `
|
|
466
|
-
Try: token-goat semantic
|
|
522
|
+
const semanticHint = indexEmpty || !canQuoteArg(opts.name) ? "" : `
|
|
523
|
+
Try: token-goat semantic ${quotedArg(opts.name)}`;
|
|
467
524
|
if (near.skipped) text2 += `
|
|
468
525
|
${nearNamesSkippedNote()}${semanticHint}`;
|
|
469
526
|
else text2 += near.candidates.length > 0 ? `
|
|
@@ -474,7 +531,7 @@ ${didYouMean(near.candidates)}` : semanticHint;
|
|
|
474
531
|
if (hit !== null) {
|
|
475
532
|
const display = toDisplayPath(rootDir, hit.filePath);
|
|
476
533
|
text2 += `
|
|
477
|
-
|
|
534
|
+
${echoedValue(opts.name)} is a key in ${display} at ${hit.dotPath} -- JSON/YAML keys below the top level are not symbols; read it with: ${fencedCommand(`token-goat ${hit.command} ${quotedArg(display)} ${quotedArg(hit.dotPath)}`)}`;
|
|
478
535
|
}
|
|
479
536
|
}
|
|
480
537
|
if (indexEmpty) {
|
|
@@ -519,13 +576,15 @@ ${emptyIndexMessage(emptyIndexRoot)}`;
|
|
|
519
576
|
const statsStr = formatStatsSuffix(refCounts, sym);
|
|
520
577
|
const goneTag = fileIsGone(sym.filePath) ? ` ${DELETED_TAG}` : "";
|
|
521
578
|
const staleTag = stillStale.has(sym.filePath) ? ` ${STALE_TAG}` : "";
|
|
522
|
-
const
|
|
579
|
+
const doc = docCommentLines(sym);
|
|
580
|
+
const docLabel = doc.length > 0 ? ` + ${doc.length}-line doc comment` : "";
|
|
581
|
+
const header = `# ${displaySafeText(sym.name)} (${sym.kind}) \u2014 ${formatSymbolLocation(displaySafeText(toDisplayPath(symbolDisplayRoot, sym.filePath)), sym.lineStart, sym.lineEnd)}${docLabel}${statsStr}${goneTag}${staleTag}`;
|
|
523
582
|
const body = resolveBody(sym);
|
|
524
583
|
const bodyLines = body.split(/\r?\n/);
|
|
525
|
-
const preview = bodyLines.slice(0, SYMBOL_PREVIEW_LINES).join("\n");
|
|
584
|
+
const preview = [...doc, ...bodyLines.slice(0, SYMBOL_PREVIEW_LINES)].join("\n");
|
|
526
585
|
const dropped = bodyLines.length - SYMBOL_PREVIEW_LINES;
|
|
527
|
-
const elided = dropped > 0 ? `
|
|
528
|
-
...(${countNoun(dropped, "more line")}; full body: token-goat read "
|
|
586
|
+
const elided = dropped > 0 ? forClient(`
|
|
587
|
+
...(${countNoun(dropped, "more line")}; full body: ${fencedCommand("token-goat read " + quotedArg(`${displaySafeText(toDisplayPath(symbolDisplayRoot, sym.filePath))}::${displaySafeText(sym.name)}`))})`) : "";
|
|
529
588
|
return preview.trim() !== "" ? `${header}
|
|
530
589
|
${preview}${elided}` : header;
|
|
531
590
|
});
|
|
@@ -570,11 +629,11 @@ function runBriefCore(opts) {
|
|
|
570
629
|
if (opts.json !== true) {
|
|
571
630
|
const rootDir2 = resolveProjectRoot({ project: opts.projectRoot ?? process.cwd() });
|
|
572
631
|
if (isIndexEmptyForProject(globalDbPath(), rootDir2)) {
|
|
573
|
-
return { text: `Symbol not found: ${opts.spec}
|
|
632
|
+
return { text: `Symbol not found: ${echoedValue(opts.spec)}
|
|
574
633
|
${emptyIndexMessage(rootDir2)}`, code: 1 };
|
|
575
634
|
}
|
|
576
635
|
}
|
|
577
|
-
return { text: `Symbol not found: ${opts.spec}`, code: 1 };
|
|
636
|
+
return { text: `Symbol not found: ${echoedValue(opts.spec)}`, code: 1 };
|
|
578
637
|
}
|
|
579
638
|
const match = resolution.entry;
|
|
580
639
|
const rootDir = specScopeRoot(opts.spec, resolveProjectRoot({ project: opts.projectRoot ?? process.cwd() })).root;
|
|
@@ -627,8 +686,8 @@ ${emptyIndexMessage(rootDir2)}`, code: 1 };
|
|
|
627
686
|
lines.push(callers.length === 0 && hiddenNote !== "" ? `Callers (0): no non-test callers${hiddenNote}` : `Callers (${totalCallers}):${hiddenNote}`);
|
|
628
687
|
}
|
|
629
688
|
for (const c of shown) {
|
|
630
|
-
const callerDisplayPath = toDisplayPath(rootDir, c.file);
|
|
631
|
-
lines.push(` ${c.caller} ${callerDisplayPath}:${c.line}`);
|
|
689
|
+
const callerDisplayPath = displaySafeText(toDisplayPath(rootDir, c.file));
|
|
690
|
+
lines.push(` ${displaySafeText(c.caller)} ${callerDisplayPath}:${c.line}`);
|
|
632
691
|
const window = buildContextWindow(c.file, c.line, opts.context ?? 0);
|
|
633
692
|
if (window !== null) lines.push(...renderContextWindow(callerDisplayPath, c.line, window, "", " "));
|
|
634
693
|
}
|
|
@@ -686,14 +745,14 @@ ${sub.text}`);
|
|
|
686
745
|
}
|
|
687
746
|
function runBrief(opts) {
|
|
688
747
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
689
|
-
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
748
|
+
emitErr(formatCommandError(`--limit must be a positive number, got: ${echoedValue(String(opts.limit))}`));
|
|
690
749
|
return 1;
|
|
691
750
|
}
|
|
692
751
|
const crossFilePairs = parseCrossFileMultiSpec(opts.spec);
|
|
693
752
|
if (crossFilePairs !== null) {
|
|
694
753
|
const { text: text2, code: code2 } = runBriefCrossFile(crossFilePairs, opts);
|
|
695
754
|
if (code2 === 0) emit(text2);
|
|
696
|
-
else emitErr(text2);
|
|
755
|
+
else emitErr(formatFailedResultText(text2));
|
|
697
756
|
return code2;
|
|
698
757
|
}
|
|
699
758
|
const { file, symbol } = parseReadSpec(opts.spec);
|
|
@@ -702,13 +761,13 @@ function runBrief(opts) {
|
|
|
702
761
|
if (multiSymbols.length > 1) {
|
|
703
762
|
const { text: text2, code: code2 } = runBriefMulti(file, multiSymbols, opts);
|
|
704
763
|
if (code2 === 0) emit(text2);
|
|
705
|
-
else emitErr(text2);
|
|
764
|
+
else emitErr(formatFailedResultText(text2));
|
|
706
765
|
return code2;
|
|
707
766
|
}
|
|
708
767
|
}
|
|
709
768
|
const { text, code } = runBriefCore(opts);
|
|
710
769
|
if (code === 0) emit(text);
|
|
711
|
-
else emitErr(text);
|
|
770
|
+
else emitErr(formatFailedResultText(text));
|
|
712
771
|
return code;
|
|
713
772
|
}
|
|
714
773
|
|
|
@@ -785,7 +844,7 @@ function runSection(opts) {
|
|
|
785
844
|
const result = readSection(filePath, heading, readFileText) ?? htmlIdSectionFallback(filePath, heading);
|
|
786
845
|
if (result === null) {
|
|
787
846
|
if (!fs.existsSync(filePath)) {
|
|
788
|
-
return { text:
|
|
847
|
+
return { text: fileNotFoundError(filePath).message, code: 1 };
|
|
789
848
|
}
|
|
790
849
|
const ordSpec = /^(.*?)#(\d+)$/.exec(heading);
|
|
791
850
|
const ordBase = ordSpec?.[1]?.trim();
|
|
@@ -794,25 +853,25 @@ function runSection(opts) {
|
|
|
794
853
|
if (baseResult !== null) {
|
|
795
854
|
const total = baseResult.occurrences?.length ?? 1;
|
|
796
855
|
return {
|
|
797
|
-
text: `Heading
|
|
856
|
+
text: `Heading ${quotedArg(ordBase)} has ${countNoun(total, "occurrence")} in ${quotedArg(specFilePath)}; valid ordinals are #1 to #${total}`,
|
|
798
857
|
code: 1
|
|
799
858
|
};
|
|
800
859
|
}
|
|
801
860
|
}
|
|
802
|
-
const messages = [`Section
|
|
861
|
+
const messages = [`Section ${quotedArg(heading)} not found in ${quotedArg(filePath)}`];
|
|
803
862
|
const allHeadings = listSections(filePath, readFileText);
|
|
804
863
|
const available = filterSimilarHeadings(allHeadings, heading);
|
|
805
864
|
if (available.length > 0) messages.push(didYouMean(available));
|
|
806
|
-
else if (allHeadings.length === 0) messages.push(
|
|
807
|
-
else messages.push(`Try: token-goat outline ${specFilePath}`);
|
|
865
|
+
else if (allHeadings.length === 0) messages.push(`${quotedArg(specFilePath)} has no headings`);
|
|
866
|
+
else messages.push(`Try: token-goat outline ${quotedArg(specFilePath)}`);
|
|
808
867
|
return { text: messages.join("\n"), code: 1 };
|
|
809
868
|
}
|
|
810
869
|
if (result.occurrences !== void 0) {
|
|
811
870
|
const lines = [
|
|
812
|
-
`Ambiguous heading
|
|
871
|
+
`Ambiguous heading ${quotedArg(heading)} in ${quotedArg(specFilePath)}: ${countNoun(result.occurrences.length, "heading")} match. Retry with one of the qualified commands below to pick one:`
|
|
813
872
|
];
|
|
814
873
|
for (const [i, line] of result.occurrences.slice(0, AMBIGUOUS_HEADING_LIMIT).entries()) {
|
|
815
|
-
lines.push(` - line ${line} -> token-goat section
|
|
874
|
+
lines.push(` - line ${line} -> token-goat section ${quotedArg(`${specFilePath}::${heading}#${i + 1}`)}`);
|
|
816
875
|
}
|
|
817
876
|
if (result.occurrences.length > AMBIGUOUS_HEADING_LIMIT) {
|
|
818
877
|
lines.push(` (${result.occurrences.length - AMBIGUOUS_HEADING_LIMIT} more not shown)`);
|
|
@@ -860,7 +919,7 @@ ${filtered.matched} of ${filtered.total} lines matched`;
|
|
|
860
919
|
if (opts.suppressStat !== true) recordReadStat(kind, fullSourceBytes, text2, heading);
|
|
861
920
|
return { text: text2, code: 0 };
|
|
862
921
|
}
|
|
863
|
-
const redirectNote = result.redirectedFrom !== void 0 ? ` (redirected from:
|
|
922
|
+
const redirectNote = result.redirectedFrom !== void 0 ? ` (redirected from: ${echoedValue(result.redirectedFrom)})` : "";
|
|
864
923
|
const text = guardText(
|
|
865
924
|
`# ${result.heading} \u2014 ${filePath}:${result.lineStart}-${lineEnd}${redirectNote}${content.length > 0 ? `
|
|
866
925
|
${content}` : ""}${truncatedNotice}${grepNote}`,
|
|
@@ -882,7 +941,7 @@ function runSectionMulti(specFilePath, resolvedFilePath, headings, opts) {
|
|
|
882
941
|
);
|
|
883
942
|
if (parent !== void 0) {
|
|
884
943
|
anyFound = true;
|
|
885
|
-
const notice = `(already included in section
|
|
944
|
+
const notice = `(already included in section ${quotedArg(parent.heading)}, lines ${sectionResult.lineStart}-${sectionResult.lineEnd})`;
|
|
886
945
|
if (opts.json === true) {
|
|
887
946
|
jsonOut[heading] = {
|
|
888
947
|
heading: sectionResult.heading,
|
|
@@ -938,7 +997,7 @@ function runSectionCrossFile(pairs, opts) {
|
|
|
938
997
|
);
|
|
939
998
|
if (parent !== void 0) {
|
|
940
999
|
anyFound = true;
|
|
941
|
-
const notice = `(already included in section
|
|
1000
|
+
const notice = `(already included in section ${quotedArg(parent.heading)}, lines ${sectionResult.lineStart}-${sectionResult.lineEnd})`;
|
|
942
1001
|
if (opts.json === true) {
|
|
943
1002
|
jsonOut[key] = {
|
|
944
1003
|
heading: sectionResult.heading,
|
|
@@ -1331,9 +1390,10 @@ function formatCoverageGaps(report) {
|
|
|
1331
1390
|
}
|
|
1332
1391
|
|
|
1333
1392
|
// src/read_inspect.ts
|
|
1393
|
+
var BINARY_ENTRY_ELIDED = "[binary content elided by token-goat]";
|
|
1334
1394
|
function archiveReadFailure(err, file) {
|
|
1335
1395
|
if (err instanceof ArchiveDependencyMissingError || err instanceof ZipOutputTooLargeError) return err.message;
|
|
1336
|
-
return `Failed to read archive (not a valid zip-format file): ${file}`;
|
|
1396
|
+
return `Failed to read archive (not a valid zip-format file): ${echoedValue(file)}`;
|
|
1337
1397
|
}
|
|
1338
1398
|
async function runZipList(opts) {
|
|
1339
1399
|
let data;
|
|
@@ -1341,30 +1401,30 @@ async function runZipList(opts) {
|
|
|
1341
1401
|
data = readFileBytes(opts.file);
|
|
1342
1402
|
} catch (err) {
|
|
1343
1403
|
if (err instanceof ZipInputTooLargeError) {
|
|
1344
|
-
emitErr(err.message);
|
|
1404
|
+
emitErr(formatCommandError(err.message));
|
|
1345
1405
|
return 1;
|
|
1346
1406
|
}
|
|
1347
1407
|
throw err;
|
|
1348
1408
|
}
|
|
1349
1409
|
if (data === null) {
|
|
1350
|
-
emitErr(
|
|
1410
|
+
emitErr(formatCommandError(couldNotReadError(opts.file)));
|
|
1351
1411
|
return 1;
|
|
1352
1412
|
}
|
|
1353
1413
|
let entries;
|
|
1354
1414
|
try {
|
|
1355
1415
|
entries = await listZipEntries(data);
|
|
1356
1416
|
} catch (err) {
|
|
1357
|
-
emitErr(archiveReadFailure(err, opts.file));
|
|
1417
|
+
emitErr(formatCommandError(archiveReadFailure(err, opts.file)));
|
|
1358
1418
|
return 1;
|
|
1359
1419
|
}
|
|
1360
1420
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
1361
1421
|
if (opts.json === true) {
|
|
1362
|
-
const jsonText = displaySafeJson(entries, 0);
|
|
1422
|
+
const jsonText = displaySafeJson(entries.map((e) => ({ ...e, path: fenceFileFieldIfMatched(e.path) })), 0);
|
|
1363
1423
|
emit(jsonText);
|
|
1364
1424
|
recordReadStat("zip_list", fullSourceBytes, jsonText, opts.file);
|
|
1365
1425
|
} else {
|
|
1366
|
-
const text = formatZipList(entries);
|
|
1367
|
-
|
|
1426
|
+
const text = guardAndFenceFileText(formatZipList(entries), "zip-list");
|
|
1427
|
+
emit(text);
|
|
1368
1428
|
recordReadStat("zip_list", fullSourceBytes, text, opts.file);
|
|
1369
1429
|
}
|
|
1370
1430
|
return 0;
|
|
@@ -1375,13 +1435,13 @@ async function runZipRead(opts) {
|
|
|
1375
1435
|
data = readFileBytes(opts.file);
|
|
1376
1436
|
} catch (err) {
|
|
1377
1437
|
if (err instanceof ZipInputTooLargeError) {
|
|
1378
|
-
emitErr(err.message);
|
|
1438
|
+
emitErr(formatCommandError(err.message));
|
|
1379
1439
|
return 1;
|
|
1380
1440
|
}
|
|
1381
1441
|
throw err;
|
|
1382
1442
|
}
|
|
1383
1443
|
if (data === null) {
|
|
1384
|
-
emitErr(
|
|
1444
|
+
emitErr(formatCommandError(couldNotReadError(opts.file)));
|
|
1385
1445
|
return 1;
|
|
1386
1446
|
}
|
|
1387
1447
|
let entries;
|
|
@@ -1390,32 +1450,33 @@ async function runZipRead(opts) {
|
|
|
1390
1450
|
entries = await listZipEntries(data);
|
|
1391
1451
|
content = await extractZipEntry(data, opts.entry);
|
|
1392
1452
|
} catch (err) {
|
|
1393
|
-
emitErr(archiveReadFailure(err, opts.file));
|
|
1453
|
+
emitErr(formatCommandError(archiveReadFailure(err, opts.file)));
|
|
1394
1454
|
return 1;
|
|
1395
1455
|
}
|
|
1396
1456
|
const matchedEntry = entries.find((e) => e.path === opts.entry);
|
|
1397
1457
|
if (matchedEntry?.isDirectory === true) {
|
|
1398
|
-
emitErr(`Entry
|
|
1458
|
+
emitErr(formatCommandError(`Entry ${echoedValue(opts.entry)} is a directory, not a file, in ${echoedValue(opts.file)}`));
|
|
1399
1459
|
return 1;
|
|
1400
1460
|
}
|
|
1401
1461
|
if (content === void 0) {
|
|
1402
|
-
const messages = [`Entry
|
|
1462
|
+
const messages = [`Entry ${echoedValue(opts.entry)} not found in ${echoedValue(opts.file)}`];
|
|
1403
1463
|
const closes = rankSimilarNames(entries.map((e) => e.path), opts.entry);
|
|
1404
1464
|
if (closes.length > 0) messages.push(didYouMean(closes));
|
|
1405
|
-
else if (entries.length > 0) messages.push(`Try: token-goat zip-list ${opts.file}`);
|
|
1406
|
-
emitErr(messages
|
|
1465
|
+
else if (entries.length > 0) messages.push(`Try: token-goat zip-list ${quotedArg(opts.file)}`);
|
|
1466
|
+
emitErr(formatCommandError(new CliError(messages)));
|
|
1407
1467
|
return 1;
|
|
1408
1468
|
}
|
|
1409
1469
|
const buf = Buffer.from(content);
|
|
1410
|
-
const text = isValidUtf8(buf) ? buf.toString("utf-8") :
|
|
1470
|
+
const text = isValidUtf8(buf) ? buf.toString("utf-8") : null;
|
|
1411
1471
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
1412
1472
|
if (opts.json === true) {
|
|
1413
|
-
const jsonText = displaySafeJson({ path: opts.entry, text }, 0);
|
|
1473
|
+
const jsonText = displaySafeJson({ path: opts.entry, text: text === null ? BINARY_ENTRY_ELIDED : fenceFileFieldIfMatched(text) }, 0);
|
|
1414
1474
|
emit(jsonText);
|
|
1415
1475
|
recordReadStat("zip_read", fullSourceBytes, jsonText, opts.entry);
|
|
1416
1476
|
} else {
|
|
1417
|
-
|
|
1418
|
-
|
|
1477
|
+
const printed = text === null ? BINARY_ENTRY_ELIDED : guardAndFenceFileText(text, "zip-read");
|
|
1478
|
+
emit(printed);
|
|
1479
|
+
recordReadStat("zip_read", fullSourceBytes, printed, opts.entry);
|
|
1419
1480
|
}
|
|
1420
1481
|
return 0;
|
|
1421
1482
|
}
|
|
@@ -1424,17 +1485,17 @@ function runSqliteSchema(opts) {
|
|
|
1424
1485
|
const schema = getSqliteSchema(opts.file);
|
|
1425
1486
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
1426
1487
|
if (opts.json === true) {
|
|
1427
|
-
const jsonText =
|
|
1488
|
+
const jsonText = capListField(schema, "tables", (o) => displaySafeJson(fenceJsonStrings(o, fenceFileFieldIfMatched), 0));
|
|
1428
1489
|
emit(jsonText);
|
|
1429
1490
|
recordReadStat("sqlite_schema", fullSourceBytes, jsonText, opts.file);
|
|
1430
1491
|
} else {
|
|
1431
|
-
const text = formatSqliteSchema(schema);
|
|
1492
|
+
const text = guardAndFenceFileText(formatSqliteSchema(schema), "sqlite-schema");
|
|
1432
1493
|
emit(text);
|
|
1433
1494
|
recordReadStat("sqlite_schema", fullSourceBytes, text, opts.file);
|
|
1434
1495
|
}
|
|
1435
1496
|
return 0;
|
|
1436
1497
|
} catch (e) {
|
|
1437
|
-
emitErr(
|
|
1498
|
+
emitErr(formatCommandError(e));
|
|
1438
1499
|
return 1;
|
|
1439
1500
|
}
|
|
1440
1501
|
}
|
|
@@ -1443,17 +1504,21 @@ function runSqliteTables(opts) {
|
|
|
1443
1504
|
const tables = getSqliteTables(opts.file);
|
|
1444
1505
|
const fullSourceBytes = sumFileSizes([opts.file]);
|
|
1445
1506
|
if (opts.json === true) {
|
|
1446
|
-
const jsonText =
|
|
1507
|
+
const jsonText = capListField({ items: tables }, "items", (o) => displaySafeJson(fenceJsonStrings(o.truncated === true ? o : o.items, fenceFileFieldIfMatched), 0));
|
|
1508
|
+
if (jsonText.startsWith("{")) {
|
|
1509
|
+
const cut = JSON.parse(jsonText);
|
|
1510
|
+
emitErr(`token-goat: sqlite-tables --json shows ${cut.items.length} of ${cut.totalCount} tables, the most that fit overflow_guard.max_tokens; list fewer with sqlite-query.`);
|
|
1511
|
+
}
|
|
1447
1512
|
emit(jsonText);
|
|
1448
1513
|
recordReadStat("sqlite_tables", fullSourceBytes, jsonText, opts.file);
|
|
1449
1514
|
} else {
|
|
1450
|
-
const text = formatSqliteTables(tables);
|
|
1515
|
+
const text = guardAndFenceFileText(formatSqliteTables(tables), "sqlite-tables");
|
|
1451
1516
|
emit(text);
|
|
1452
1517
|
recordReadStat("sqlite_tables", fullSourceBytes, text, opts.file);
|
|
1453
1518
|
}
|
|
1454
1519
|
return 0;
|
|
1455
1520
|
} catch (e) {
|
|
1456
|
-
emitErr(
|
|
1521
|
+
emitErr(formatCommandError(e));
|
|
1457
1522
|
return 1;
|
|
1458
1523
|
}
|
|
1459
1524
|
}
|
|
@@ -1462,7 +1527,7 @@ function runSqliteQuery(opts) {
|
|
|
1462
1527
|
try {
|
|
1463
1528
|
head = opts.head !== void 0 ? requireNonNegativeStrictInt("--head", opts.head) : void 0;
|
|
1464
1529
|
} catch (e) {
|
|
1465
|
-
emitErr(
|
|
1530
|
+
emitErr(formatCommandError(e));
|
|
1466
1531
|
return 1;
|
|
1467
1532
|
}
|
|
1468
1533
|
try {
|
|
@@ -1471,9 +1536,9 @@ function runSqliteQuery(opts) {
|
|
|
1471
1536
|
const headTruncated = head !== void 0 && result.rows.length > head;
|
|
1472
1537
|
const rows = head !== void 0 ? result.rows.slice(0, head) : result.rows;
|
|
1473
1538
|
if (opts.json === true) {
|
|
1474
|
-
const capped = guardJsonRows(rows);
|
|
1539
|
+
const capped = guardJsonRows(rows.map((r) => fenceJsonStrings(r, fenceFileFieldIfMatched)));
|
|
1475
1540
|
const jsonText = displaySafeJson({
|
|
1476
|
-
columns: result.columns,
|
|
1541
|
+
columns: result.columns.map(fenceFileFieldIfMatched),
|
|
1477
1542
|
items: capped.items,
|
|
1478
1543
|
truncated: capped.truncated || headTruncated || result.rowCapped,
|
|
1479
1544
|
totalCount,
|
|
@@ -1490,29 +1555,28 @@ function runSqliteQuery(opts) {
|
|
|
1490
1555
|
}, 0);
|
|
1491
1556
|
recordReadStat("sqlite_query", Buffer.byteLength(baselineJsonText, "utf8"), jsonText, opts.file);
|
|
1492
1557
|
} else {
|
|
1493
|
-
const text = formatSqliteQueryTable({ ...result, rows }, { headTruncated });
|
|
1558
|
+
const text = guardAndFenceFileText(formatSqliteQueryTable({ ...result, rows }, { headTruncated }), "sqlite-query");
|
|
1494
1559
|
emit(text);
|
|
1495
1560
|
const baselineText = formatSqliteQueryTable({ ...result, rows: result.rows }, { headTruncated: false });
|
|
1496
1561
|
recordReadStat("sqlite_query", Buffer.byteLength(baselineText, "utf8"), text, opts.file);
|
|
1497
1562
|
}
|
|
1498
1563
|
return 0;
|
|
1499
1564
|
} catch (e) {
|
|
1500
|
-
emitErr(
|
|
1565
|
+
emitErr(formatCommandError(e));
|
|
1501
1566
|
return 1;
|
|
1502
1567
|
}
|
|
1503
1568
|
}
|
|
1504
1569
|
function runCoverageReportGaps(opts) {
|
|
1505
1570
|
const text = readFileText(opts.file);
|
|
1506
1571
|
if (text === null) {
|
|
1507
|
-
emitErr(
|
|
1572
|
+
emitErr(formatCommandError(couldNotReadError(opts.file)));
|
|
1508
1573
|
return 1;
|
|
1509
1574
|
}
|
|
1510
1575
|
let report;
|
|
1511
1576
|
try {
|
|
1512
1577
|
report = parseCoverageReport(text);
|
|
1513
1578
|
} catch (e) {
|
|
1514
|
-
emitErr(`Failed to parse coverage report (not valid LCOV or Istanbul JSON): ${opts.file}
|
|
1515
|
-
${extractErrorMessage(e)}`);
|
|
1579
|
+
emitErr(formatCommandError(new CliError([`Failed to parse coverage report (not valid LCOV or Istanbul JSON): ${opts.file}`, extractErrorMessage(e)])));
|
|
1516
1580
|
return 1;
|
|
1517
1581
|
}
|
|
1518
1582
|
const scoped = opts.fileFilter !== void 0 ? filterCoverageGapsByFile(report, opts.fileFilter) : report;
|
|
@@ -1560,30 +1624,22 @@ function stripPairedQuotes(s) {
|
|
|
1560
1624
|
}
|
|
1561
1625
|
return s;
|
|
1562
1626
|
}
|
|
1563
|
-
function lookupYaml(
|
|
1564
|
-
|
|
1565
|
-
let
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
const indent = line.length - line.trimStart().length;
|
|
1572
|
-
if (depth > 0 && indent <= parentIndent) return null;
|
|
1573
|
-
if (childIndent !== -1 && indent !== childIndent) continue;
|
|
1574
|
-
const colon = trimmed.indexOf(":");
|
|
1575
|
-
if (colon < 0) continue;
|
|
1576
|
-
if (childIndent === -1) childIndent = indent;
|
|
1577
|
-
const k = trimmed.slice(0, colon).trim();
|
|
1578
|
-
if (k !== parts[depth]) continue;
|
|
1579
|
-
if (depth === parts.length - 1) {
|
|
1580
|
-
return stripPairedQuotes(trimmed.slice(colon + 1).trim());
|
|
1581
|
-
}
|
|
1582
|
-
parentIndent = indent;
|
|
1583
|
-
childIndent = -1;
|
|
1584
|
-
depth++;
|
|
1627
|
+
function lookupYaml(text, key) {
|
|
1628
|
+
let typed;
|
|
1629
|
+
let written;
|
|
1630
|
+
try {
|
|
1631
|
+
typed = parseYamlDocument(text);
|
|
1632
|
+
written = parseYamlDocumentAsWritten(text);
|
|
1633
|
+
} catch {
|
|
1634
|
+
return void 0;
|
|
1585
1635
|
}
|
|
1586
|
-
|
|
1636
|
+
const parts = key.split(".").map((name) => ({ name, joinable: true }));
|
|
1637
|
+
const found = resolveConfigKey(typed, parts);
|
|
1638
|
+
if (found === void 0) return null;
|
|
1639
|
+
if (found === null) return "null";
|
|
1640
|
+
if (typeof found === "object" && !(found instanceof Date)) return displaySafeJson(found, 0);
|
|
1641
|
+
const asWritten = resolveConfigKey(written, parts);
|
|
1642
|
+
return typeof asWritten === "string" ? asWritten : String(found);
|
|
1587
1643
|
}
|
|
1588
1644
|
function extractFrontmatter(lines) {
|
|
1589
1645
|
if (lines[0]?.trim() !== "---") return null;
|
|
@@ -1597,14 +1653,18 @@ function extractFrontmatter(lines) {
|
|
|
1597
1653
|
function runConfigGet(opts) {
|
|
1598
1654
|
const text = readFileText(opts.file);
|
|
1599
1655
|
if (text === null) {
|
|
1600
|
-
emitErr(
|
|
1656
|
+
emitErr(formatCommandError(couldNotReadError(opts.file)));
|
|
1601
1657
|
return 1;
|
|
1602
1658
|
}
|
|
1603
1659
|
const frontmatterLines = extractFrontmatter(text.split(/\r?\n/));
|
|
1604
1660
|
if (frontmatterLines !== null) {
|
|
1605
|
-
const value = lookupYaml(frontmatterLines, opts.key);
|
|
1661
|
+
const value = lookupYaml(frontmatterLines.join("\n"), opts.key);
|
|
1662
|
+
if (value === void 0) {
|
|
1663
|
+
emitErr(formatCommandError(`Failed to parse YAML frontmatter: ${echoedValue(opts.file)}`));
|
|
1664
|
+
return 1;
|
|
1665
|
+
}
|
|
1606
1666
|
if (value === null) {
|
|
1607
|
-
emitErr(`Key
|
|
1667
|
+
emitErr(formatCommandError(`Key ${echoedValue(opts.key)} not found in ${echoedValue(opts.file)}`));
|
|
1608
1668
|
return 1;
|
|
1609
1669
|
}
|
|
1610
1670
|
emit(value);
|
|
@@ -1616,26 +1676,30 @@ function runConfigGet(opts) {
|
|
|
1616
1676
|
let obj = parseJsonOrJsonc(text);
|
|
1617
1677
|
for (const part of opts.key.split(".")) {
|
|
1618
1678
|
if (typeof obj !== "object" || obj === null) {
|
|
1619
|
-
emitErr(`Key
|
|
1679
|
+
emitErr(formatCommandError(`Key ${echoedValue(opts.key)} not found in ${echoedValue(opts.file)}`));
|
|
1620
1680
|
return 1;
|
|
1621
1681
|
}
|
|
1622
1682
|
obj = obj[part];
|
|
1623
1683
|
if (obj === void 0) {
|
|
1624
|
-
emitErr(`Key
|
|
1684
|
+
emitErr(formatCommandError(`Key ${echoedValue(opts.key)} not found in ${echoedValue(opts.file)}`));
|
|
1625
1685
|
return 1;
|
|
1626
1686
|
}
|
|
1627
1687
|
}
|
|
1628
1688
|
emit(displaySafeJson(obj, 0));
|
|
1629
1689
|
return 0;
|
|
1630
1690
|
} catch {
|
|
1631
|
-
emitErr(`Failed to parse JSON: ${opts.file}`);
|
|
1691
|
+
emitErr(formatCommandError(`Failed to parse JSON: ${echoedValue(opts.file)}`));
|
|
1632
1692
|
return 1;
|
|
1633
1693
|
}
|
|
1634
1694
|
}
|
|
1635
1695
|
if (ext === ".yaml" || ext === ".yml") {
|
|
1636
|
-
const value = lookupYaml(text
|
|
1696
|
+
const value = lookupYaml(text, opts.key);
|
|
1697
|
+
if (value === void 0) {
|
|
1698
|
+
emitErr(formatCommandError(`Failed to parse YAML: ${echoedValue(opts.file)}`));
|
|
1699
|
+
return 1;
|
|
1700
|
+
}
|
|
1637
1701
|
if (value === null) {
|
|
1638
|
-
emitErr(`Key
|
|
1702
|
+
emitErr(formatCommandError(`Key ${echoedValue(opts.key)} not found in ${echoedValue(opts.file)}`));
|
|
1639
1703
|
return 1;
|
|
1640
1704
|
}
|
|
1641
1705
|
emit(value);
|
|
@@ -1645,7 +1709,7 @@ function runConfigGet(opts) {
|
|
|
1645
1709
|
const toml = lookupToml(text, opts.key);
|
|
1646
1710
|
if (toml !== void 0) {
|
|
1647
1711
|
if (toml === null) {
|
|
1648
|
-
emitErr(`Key
|
|
1712
|
+
emitErr(formatCommandError(`Key ${echoedValue(opts.key)} not found in ${echoedValue(opts.file)}`));
|
|
1649
1713
|
return 1;
|
|
1650
1714
|
}
|
|
1651
1715
|
emit(toml);
|
|
@@ -1661,14 +1725,14 @@ function runConfigGet(opts) {
|
|
|
1661
1725
|
const value = lookupFlatKey(lines, attempt.section, attempt.leaf, flavour);
|
|
1662
1726
|
if (value !== null) {
|
|
1663
1727
|
if (ext === ".toml" && isTomlFragment(value)) {
|
|
1664
|
-
emitErr(`Key
|
|
1728
|
+
emitErr(formatCommandError(`Key ${echoedValue(opts.key)} in ${echoedValue(opts.file)} spans several lines and the file is not valid TOML, so it cannot be read whole`));
|
|
1665
1729
|
return 1;
|
|
1666
1730
|
}
|
|
1667
1731
|
emit(value);
|
|
1668
1732
|
return 0;
|
|
1669
1733
|
}
|
|
1670
1734
|
}
|
|
1671
|
-
emitErr(`Key
|
|
1735
|
+
emitErr(formatCommandError(`Key ${echoedValue(opts.key)} not found in ${echoedValue(opts.file)}`));
|
|
1672
1736
|
return 1;
|
|
1673
1737
|
}
|
|
1674
1738
|
function isTomlFragment(v) {
|
|
@@ -1698,7 +1762,7 @@ function tomlProbePath(key, value) {
|
|
|
1698
1762
|
return null;
|
|
1699
1763
|
}
|
|
1700
1764
|
}
|
|
1701
|
-
function
|
|
1765
|
+
function resolveConfigKey(node, parts) {
|
|
1702
1766
|
if (parts.length === 0) return node;
|
|
1703
1767
|
if (typeof node !== "object" || node === null || Array.isArray(node) || node instanceof Date) return void 0;
|
|
1704
1768
|
const table = node;
|
|
@@ -1706,7 +1770,7 @@ function resolveTomlKey(node, parts) {
|
|
|
1706
1770
|
if (n > 1 && !(parts[0].joinable && parts[n - 1].joinable)) break;
|
|
1707
1771
|
const head = parts.slice(0, n).map((p) => p.name).join(".");
|
|
1708
1772
|
if (!Object.hasOwn(table, head)) continue;
|
|
1709
|
-
const found =
|
|
1773
|
+
const found = resolveConfigKey(table[head], parts.slice(n));
|
|
1710
1774
|
if (found !== void 0) return found;
|
|
1711
1775
|
}
|
|
1712
1776
|
return void 0;
|
|
@@ -1718,7 +1782,7 @@ function lookupToml(text, key) {
|
|
|
1718
1782
|
} catch {
|
|
1719
1783
|
return void 0;
|
|
1720
1784
|
}
|
|
1721
|
-
const found =
|
|
1785
|
+
const found = resolveConfigKey(doc, splitTomlKeyPath(key));
|
|
1722
1786
|
if (found === void 0) return null;
|
|
1723
1787
|
if (typeof found === "string") return found;
|
|
1724
1788
|
if (typeof found === "object" && found !== null && !(found instanceof Date)) {
|
|
@@ -1766,7 +1830,7 @@ function runExports(opts) {
|
|
|
1766
1830
|
if (multiFiles.length > 1) return runPerFileEmitting(multiFiles, "Exports", (file) => runExports({ ...opts, file }));
|
|
1767
1831
|
const confined = fileConfinementRefusal("This file", opts.file, opts.projectRoot);
|
|
1768
1832
|
if (confined !== null) {
|
|
1769
|
-
emitErr(confined);
|
|
1833
|
+
emitErr(formatCommandError(confined));
|
|
1770
1834
|
return 1;
|
|
1771
1835
|
}
|
|
1772
1836
|
const diskPath = resolveAgainstProjectRoot(opts.file, opts.projectRoot);
|
|
@@ -1785,7 +1849,7 @@ function runExports(opts) {
|
|
|
1785
1849
|
const ext = path.extname(opts.file).toLowerCase();
|
|
1786
1850
|
const text = readFileText(diskPath);
|
|
1787
1851
|
if (text === null && symbols.length === 0) {
|
|
1788
|
-
emitErr(
|
|
1852
|
+
emitErr(formatCommandError(couldNotReadError(opts.file)));
|
|
1789
1853
|
return 1;
|
|
1790
1854
|
}
|
|
1791
1855
|
if (text !== null) {
|
|
@@ -1795,7 +1859,7 @@ function runExports(opts) {
|
|
|
1795
1859
|
for (const n of extractExportNames(text, ext)) if (!names.includes(n)) names.push(n);
|
|
1796
1860
|
}
|
|
1797
1861
|
if (names.length === 0) {
|
|
1798
|
-
emit(`No exported symbols found in
|
|
1862
|
+
emit(`No exported symbols found in ${echoedValue(opts.file)}`);
|
|
1799
1863
|
return 0;
|
|
1800
1864
|
}
|
|
1801
1865
|
const preFilterCount = names.length;
|
|
@@ -1828,7 +1892,7 @@ function runExports(opts) {
|
|
|
1828
1892
|
const outLines = filteredNames.map((n) => {
|
|
1829
1893
|
const loc = locOf(n);
|
|
1830
1894
|
const locSuffix = loc === null ? "" : ` (${loc.lineStart}-${loc.lineEnd})`;
|
|
1831
|
-
return `${kindOf(n).padEnd(10)} ${n}${locSuffix}`;
|
|
1895
|
+
return `${kindOf(n).padEnd(10)} ${displaySafeText(n)}${locSuffix}`;
|
|
1832
1896
|
});
|
|
1833
1897
|
for (const line of outLines) {
|
|
1834
1898
|
emit(line);
|
|
@@ -1842,12 +1906,12 @@ function runImports(opts) {
|
|
|
1842
1906
|
const diskPath = resolveAgainstProjectRoot(opts.file, opts.projectRoot);
|
|
1843
1907
|
const text = readFileText(diskPath);
|
|
1844
1908
|
if (text === null) {
|
|
1845
|
-
emitErr(
|
|
1909
|
+
emitErr(formatCommandError(couldNotReadError(opts.file)));
|
|
1846
1910
|
return 1;
|
|
1847
1911
|
}
|
|
1848
1912
|
const imports = extractImports(text, importsExtensionFor(opts.file));
|
|
1849
1913
|
if (imports.length === 0) {
|
|
1850
|
-
emit(`No imports found in
|
|
1914
|
+
emit(`No imports found in ${echoedValue(opts.file)}`);
|
|
1851
1915
|
return 0;
|
|
1852
1916
|
}
|
|
1853
1917
|
const preFilterCount = imports.length;
|
|
@@ -1918,8 +1982,8 @@ function runNoteGet(opts) {
|
|
|
1918
1982
|
const symbol = opts.symbol ?? WHOLE_FILE_NOTE_SYMBOL;
|
|
1919
1983
|
const note = getNote(resolvedPath, symbol);
|
|
1920
1984
|
if (note === null) {
|
|
1921
|
-
const where = opts.symbol !== void 0 ? ` for symbol
|
|
1922
|
-
return { text: `No note found for
|
|
1985
|
+
const where = opts.symbol !== void 0 ? ` for symbol ${echoedValue(opts.symbol)}` : " (whole-file note)";
|
|
1986
|
+
return { text: `No note found for ${echoedValue(opts.file)}${where}`, code: 1 };
|
|
1923
1987
|
}
|
|
1924
1988
|
const stale = isNoteStale(note);
|
|
1925
1989
|
if (opts.json === true) {
|
|
@@ -1973,7 +2037,7 @@ function runNoteList(opts = {}) {
|
|
|
1973
2037
|
}
|
|
1974
2038
|
function runFind(opts) {
|
|
1975
2039
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
1976
|
-
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
2040
|
+
emitErr(formatCommandError(`--limit must be a positive number, got: ${echoedValue(String(opts.limit))}`));
|
|
1977
2041
|
return 1;
|
|
1978
2042
|
}
|
|
1979
2043
|
const rootDir = resolveProjectRoot({ project: process.cwd() });
|
|
@@ -2001,7 +2065,7 @@ function runFind(opts) {
|
|
|
2001
2065
|
const limitDropped = allFiles.length - files.length;
|
|
2002
2066
|
const truncated = limitDropped > 0;
|
|
2003
2067
|
if (files.length === 0) {
|
|
2004
|
-
emitErr(`No indexed files match
|
|
2068
|
+
emitErr(formatCommandError(`No indexed files match ${echoedValue(opts.pattern)}`));
|
|
2005
2069
|
return 1;
|
|
2006
2070
|
}
|
|
2007
2071
|
if (opts.json === true) {
|
|
@@ -2010,10 +2074,10 @@ function runFind(opts) {
|
|
|
2010
2074
|
return 0;
|
|
2011
2075
|
}
|
|
2012
2076
|
if (fuzzyNames.length > 0) {
|
|
2013
|
-
emitErr(`No symbol name contains
|
|
2077
|
+
emitErr(`No symbol name contains ${echoedValue(opts.pattern)}; showing files for the nearest indexed ${fuzzyNames.length === 1 ? "name" : "names"}: ${fuzzyNames.map(displaySafeText).join(", ")}`);
|
|
2014
2078
|
}
|
|
2015
2079
|
for (const f of files) {
|
|
2016
|
-
emit(toDisplayPath(rootDir, f));
|
|
2080
|
+
emit(displaySafeText(toDisplayPath(rootDir, f)));
|
|
2017
2081
|
}
|
|
2018
2082
|
if (limitDropped > 0) {
|
|
2019
2083
|
emitErr(`Showing ${files.length} of ${allFiles.length} matching files; rerun with --limit ${allFiles.length} to see them all`);
|
|
@@ -2022,7 +2086,7 @@ function runFind(opts) {
|
|
|
2022
2086
|
}
|
|
2023
2087
|
function runLocate(opts) {
|
|
2024
2088
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
2025
|
-
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
2089
|
+
emitErr(formatCommandError(`--limit must be a positive number, got: ${echoedValue(String(opts.limit))}`));
|
|
2026
2090
|
return 1;
|
|
2027
2091
|
}
|
|
2028
2092
|
const rootDir = opts.projectRoot ?? resolveProjectRoot({ project: process.cwd() });
|
|
@@ -2081,7 +2145,7 @@ function runLocate(opts) {
|
|
|
2081
2145
|
}
|
|
2082
2146
|
const shown = sinkGoneRows(combined, (s) => s.filePath).slice(0, limit);
|
|
2083
2147
|
if (shown.length === 0) {
|
|
2084
|
-
emitErr(`No landmark or symbol located for
|
|
2148
|
+
emitErr(formatCommandError(`No landmark or symbol located for ${echoedValue(targetSpec)}`));
|
|
2085
2149
|
return 1;
|
|
2086
2150
|
}
|
|
2087
2151
|
warnIfFilesStale(shown.map((s) => s.filePath), "locate");
|
|
@@ -2104,7 +2168,7 @@ function runLocate(opts) {
|
|
|
2104
2168
|
return 0;
|
|
2105
2169
|
}
|
|
2106
2170
|
if (fuzzyNames.length > 0) {
|
|
2107
|
-
emitErr(`No exact landmark for
|
|
2171
|
+
emitErr(`No exact landmark for ${echoedValue(targetSpec)}; nearest matches: ${fuzzyNames.map(displaySafeText).join(", ")}`);
|
|
2108
2172
|
}
|
|
2109
2173
|
for (const hit of hits) {
|
|
2110
2174
|
emit(`${displaySafeText(hit.filePath)}:${hit.span} [${displaySafeText(hit.kind)}] ${displaySafeText(hit.name)}${hit.deleted === true ? ` ${DELETED_TAG}` : ""}`);
|
|
@@ -2118,10 +2182,10 @@ function runListSections(opts) {
|
|
|
2118
2182
|
const sections = listSections(opts.file);
|
|
2119
2183
|
if (sections.length === 0) {
|
|
2120
2184
|
if (!fileExists(opts.file)) {
|
|
2121
|
-
emitErr(
|
|
2185
|
+
emitErr(formatCommandError(couldNotReadError(opts.file)));
|
|
2122
2186
|
return 1;
|
|
2123
2187
|
}
|
|
2124
|
-
emitErr(`No sections found in
|
|
2188
|
+
emitErr(formatCommandError(`No sections found in ${echoedValue(opts.file)}`));
|
|
2125
2189
|
return 1;
|
|
2126
2190
|
}
|
|
2127
2191
|
const preFilterCount = sections.length;
|
|
@@ -2156,6 +2220,7 @@ function runListSections(opts) {
|
|
|
2156
2220
|
|
|
2157
2221
|
// src/read_outline.ts
|
|
2158
2222
|
init_define_import_meta_env();
|
|
2223
|
+
import * as fs2 from "node:fs";
|
|
2159
2224
|
var DOC_SUMMARY_MAX_CHARS = 140;
|
|
2160
2225
|
function firstSentenceEnd(line) {
|
|
2161
2226
|
const MIN_SENTENCE_CHARS = 30;
|
|
@@ -2169,12 +2234,24 @@ function firstSentenceEnd(line) {
|
|
|
2169
2234
|
}
|
|
2170
2235
|
return null;
|
|
2171
2236
|
}
|
|
2172
|
-
function
|
|
2237
|
+
function fileLineCount(resolved, symbolExtent) {
|
|
2238
|
+
try {
|
|
2239
|
+
const text = indexedSourceText(resolved, fs2.readFileSync(resolved, "utf8"));
|
|
2240
|
+
if (text === "") return symbolExtent;
|
|
2241
|
+
const lines = text.split("\n");
|
|
2242
|
+
return Math.max(symbolExtent, text.endsWith("\n") ? lines.length - 1 : lines.length);
|
|
2243
|
+
} catch {
|
|
2244
|
+
return symbolExtent;
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
function clipDocSummary(docstring) {
|
|
2248
|
+
const [firstLine = "", ...rest] = docstring.split("\n");
|
|
2249
|
+
const more = rest.some((l) => l.trim() !== "") ? "\u2026" : "";
|
|
2173
2250
|
const sentence = firstSentenceEnd(firstLine);
|
|
2174
2251
|
if (sentence !== null && sentence <= DOC_SUMMARY_MAX_CHARS) {
|
|
2175
|
-
return sentence === firstLine.length ? firstLine : `${firstLine.slice(0, sentence)}\u2026`;
|
|
2252
|
+
return sentence === firstLine.length ? `${firstLine}${more}` : `${firstLine.slice(0, sentence)}\u2026`;
|
|
2176
2253
|
}
|
|
2177
|
-
if (firstLine.length <= DOC_SUMMARY_MAX_CHARS) return firstLine
|
|
2254
|
+
if (firstLine.length <= DOC_SUMMARY_MAX_CHARS) return `${firstLine}${more}`;
|
|
2178
2255
|
const cut = firstLine.lastIndexOf(" ", DOC_SUMMARY_MAX_CHARS);
|
|
2179
2256
|
return `${firstLine.slice(0, cut > 40 ? cut : DOC_SUMMARY_MAX_CHARS).trimEnd()}\u2026`;
|
|
2180
2257
|
}
|
|
@@ -2222,7 +2299,7 @@ function prepareSymbolListing(file, opts) {
|
|
|
2222
2299
|
const symbolsTruncated = matchesTruncated;
|
|
2223
2300
|
const refCounts = opts.stats === true ? queryRefCounts(filtered.map((s) => s.name), globalDbPath(), resolveProjectRoot({ project: opts.projectRoot ?? process.cwd() })) : void 0;
|
|
2224
2301
|
const fullSourceBytes = sumFileSizes([resolved]);
|
|
2225
|
-
return { kind: "ok", resolved, displayRoot: getDisplayRoot(opts.projectRoot), filtered, preFilterCount: scanned, refCounts, fullSourceBytes, symbolsTruncated, trueSymbolCount, totalLines };
|
|
2302
|
+
return { kind: "ok", resolved, displayRoot: getDisplayRoot(opts.projectRoot), filtered, preFilterCount: scanned, refCounts, fullSourceBytes, symbolsTruncated, trueSymbolCount, totalLines: fileLineCount(resolved, totalLines) };
|
|
2226
2303
|
}
|
|
2227
2304
|
function runPerFileListing(files, run, json = false) {
|
|
2228
2305
|
const blocks = [];
|
|
@@ -2292,12 +2369,12 @@ function runSkeleton(opts) {
|
|
|
2292
2369
|
recordReadStat("stub_view", fullSourceBytes, text2, opts.file);
|
|
2293
2370
|
return { text: text2, code: 0 };
|
|
2294
2371
|
}
|
|
2295
|
-
const lines = [`# Skeleton: ${opts.file} (${symbolCountLabel(filtered.length, symbolsTruncated, trueSymbolCount)}, ${countNoun(totalLines, "line")})`];
|
|
2372
|
+
const lines = [`# Skeleton: ${displaySafeText(opts.file)} (${symbolCountLabel(filtered.length, symbolsTruncated, trueSymbolCount)}, ${countNoun(totalLines, "line")})`];
|
|
2296
2373
|
if (filtered.length === 0 && preFilterCount > 0) lines.push(filteredToEmptyNotice(preFilterCount, opts.minLines, opts.grep));
|
|
2297
2374
|
for (const sym of filtered) {
|
|
2298
2375
|
const lineStr = sym.lineStart.toString().padStart(6);
|
|
2299
2376
|
const statsStr = formatStatsSuffix(refCounts, sym);
|
|
2300
|
-
lines.push(` ${lineStr} ${sym.kind.padEnd(10)} ${sym.name} ${firstBodyLine(sym.body)}${statsStr}`);
|
|
2377
|
+
lines.push(` ${lineStr} ${sym.kind.padEnd(10)} ${displaySafeText(sym.name)} ${displaySafeText(firstBodyLine(sym.body))}${statsStr}`);
|
|
2301
2378
|
}
|
|
2302
2379
|
const text = guardText(staleWarning(resolved, "skeleton") + lines.join("\n"), "symbol");
|
|
2303
2380
|
recordReadStat("stub_view", fullSourceBytes, text, opts.file);
|
|
@@ -2334,16 +2411,16 @@ function runOutline(opts) {
|
|
|
2334
2411
|
recordReadStat("outline", fullSourceBytes, text2, opts.file);
|
|
2335
2412
|
return { text: text2, code: 0 };
|
|
2336
2413
|
}
|
|
2337
|
-
const lines = [`# Outline: ${opts.file} (${symbolCountLabel(filtered.length, symbolsTruncated, trueSymbolCount)})`];
|
|
2414
|
+
const lines = [`# Outline: ${displaySafeText(opts.file)} (${symbolCountLabel(filtered.length, symbolsTruncated, trueSymbolCount)})`];
|
|
2338
2415
|
if (filtered.length === 0 && preFilterCount > 0) lines.push(filteredToEmptyNotice(preFilterCount, opts.minLines, opts.grep));
|
|
2339
2416
|
for (const sym of filtered) {
|
|
2340
2417
|
const rangeStr = `${sym.lineStart.toString().padStart(4)}-${sym.lineEnd.toString().padEnd(6)}`;
|
|
2341
2418
|
const kindStr = sym.kind.padEnd(14);
|
|
2342
2419
|
const bodyLen = sym.lineEnd - sym.lineStart + 1;
|
|
2343
|
-
const docFirst = hasRealDocstring(sym.docstring) ? ` # ${clipDocSummary(sym.docstring
|
|
2420
|
+
const docFirst = hasRealDocstring(sym.docstring) ? ` # ${displaySafeText(clipDocSummary(sym.docstring))}` : "";
|
|
2344
2421
|
const statsStr = formatStatsSuffix(refCounts, sym);
|
|
2345
2422
|
const notebookSuffix = isVirtualIndexedPath(sym.filePath) ? NOTEBOOK_CELL_LINES_SUFFIX : "";
|
|
2346
|
-
lines.push(` ${rangeStr} ${kindStr} ${sym.name} (${bodyLen}\u2113)${docFirst}${statsStr}${notebookSuffix}`);
|
|
2423
|
+
lines.push(` ${rangeStr} ${kindStr} ${displaySafeText(sym.name)} (${bodyLen}\u2113)${docFirst}${statsStr}${notebookSuffix}`);
|
|
2347
2424
|
}
|
|
2348
2425
|
const text = guardText(staleWarning(resolved, "outline") + lines.join("\n"), "symbol");
|
|
2349
2426
|
recordReadStat("outline", fullSourceBytes, text, opts.file);
|
|
@@ -2375,9 +2452,9 @@ function summarizeDistances(rows, weakDistance) {
|
|
|
2375
2452
|
};
|
|
2376
2453
|
}
|
|
2377
2454
|
function formatDistanceReport(summary, thresholds, scope = "this project") {
|
|
2378
|
-
const lines = [`Recorded semantic queries (${scope}): ${summary.total
|
|
2455
|
+
const lines = [`Recorded semantic queries (${scope}): ${countNoun(summary.total, "query", "queries")}`, `Current semantic.weak_distance: ${thresholds.weakDistance} semantic.max_distance: ${thresholds.maxDistance}`];
|
|
2379
2456
|
if (summary.total < MIN_QUERIES_FOR_ADVICE) {
|
|
2380
|
-
lines.push(`Only ${summary.total} recorded, which is fewer than ${MIN_QUERIES_FOR_ADVICE}: too few to judge a threshold from. Run more semantic queries and check again.`);
|
|
2457
|
+
lines.push(`${summary.total === 0 ? "None" : `Only ${summary.total}`} recorded, which is fewer than ${MIN_QUERIES_FOR_ADVICE}: too few to judge a threshold from. Run more semantic queries and check again.`);
|
|
2381
2458
|
return lines.join("\n");
|
|
2382
2459
|
}
|
|
2383
2460
|
if (summary.percentiles !== null) {
|
|
@@ -2399,7 +2476,7 @@ function recordSemanticQuery(row) {
|
|
|
2399
2476
|
}
|
|
2400
2477
|
function runSemanticDistances(opts) {
|
|
2401
2478
|
const { weak_distance: weakDistance, max_distance: maxDistance } = loadConfig().semantic;
|
|
2402
|
-
const db =
|
|
2479
|
+
const db = readGlobalDb();
|
|
2403
2480
|
const rows = opts.all === true ? db.prepare("SELECT closest_distance FROM semantic_queries").all() : db.prepare("SELECT closest_distance FROM semantic_queries WHERE project_hash = ?").all(projectHash(resolveProjectRoot({ project: process.cwd() })));
|
|
2404
2481
|
const scope = opts.all === true ? "all projects" : "this project";
|
|
2405
2482
|
return { text: formatDistanceReport(summarizeDistances(rows, weakDistance), { weakDistance, maxDistance }, scope), code: 0 };
|
|
@@ -2407,7 +2484,7 @@ function runSemanticDistances(opts) {
|
|
|
2407
2484
|
|
|
2408
2485
|
// src/read_semantic.ts
|
|
2409
2486
|
init_define_import_meta_env();
|
|
2410
|
-
import * as
|
|
2487
|
+
import * as fs3 from "node:fs";
|
|
2411
2488
|
import * as path2 from "node:path";
|
|
2412
2489
|
|
|
2413
2490
|
// src/semantic_merge.ts
|
|
@@ -2469,6 +2546,36 @@ function mergeNearbyHits(hits, proximity = 20) {
|
|
|
2469
2546
|
return merged;
|
|
2470
2547
|
}
|
|
2471
2548
|
|
|
2549
|
+
// src/semantic_relevance.ts
|
|
2550
|
+
init_define_import_meta_env();
|
|
2551
|
+
function applyRelevanceFloor(hits, floor) {
|
|
2552
|
+
const kept = [];
|
|
2553
|
+
let nearestRejected = null;
|
|
2554
|
+
for (const h of hits) {
|
|
2555
|
+
if (h.distance <= floor) {
|
|
2556
|
+
kept.push(h);
|
|
2557
|
+
} else if (nearestRejected === null || h.distance < nearestRejected) {
|
|
2558
|
+
nearestRejected = h.distance;
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
return { kept, nearestRejected };
|
|
2562
|
+
}
|
|
2563
|
+
function assessDenseRelevance(hits) {
|
|
2564
|
+
const { max_distance: floor, weak_distance: weakDistance } = loadConfig().semantic;
|
|
2565
|
+
const { kept, nearestRejected } = applyRelevanceFloor(hits, floor);
|
|
2566
|
+
const closestDistance = kept.reduce((best, h) => best === null || h.distance < best ? h.distance : best, null);
|
|
2567
|
+
const weakClosestDistance = closestDistance !== null && closestDistance > weakDistance ? closestDistance : null;
|
|
2568
|
+
return { kept, floor, nearestRejected, closestDistance, weakDistance, weakClosestDistance };
|
|
2569
|
+
}
|
|
2570
|
+
function floorEmptiedPhrase(r) {
|
|
2571
|
+
if (r.kept.length > 0 || r.nearestRejected === null) return null;
|
|
2572
|
+
return `nothing within ${r.floor} (closest was ${r.nearestRejected.toFixed(3)})`;
|
|
2573
|
+
}
|
|
2574
|
+
function weakMatchPhrase(r) {
|
|
2575
|
+
if (r.weakClosestDistance === null) return null;
|
|
2576
|
+
return `closest was ${r.weakClosestDistance.toFixed(3)}, weak above ${r.weakDistance}`;
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2472
2579
|
// src/read_semantic.ts
|
|
2473
2580
|
function resolveEnclosingSymbol(filePath, chunkStartLine, chunkEndLine, linesOf) {
|
|
2474
2581
|
const symbols = querySymbols({ filePath, limit: -1 }, globalDbPath());
|
|
@@ -2508,18 +2615,6 @@ function onlyBlankOrComment(lines, syntax) {
|
|
|
2508
2615
|
return true;
|
|
2509
2616
|
}
|
|
2510
2617
|
var RRF_K = 60;
|
|
2511
|
-
function applyRelevanceFloor(hits, floor) {
|
|
2512
|
-
const kept = [];
|
|
2513
|
-
let nearestRejected = null;
|
|
2514
|
-
for (const h of hits) {
|
|
2515
|
-
if (h.distance <= floor) {
|
|
2516
|
-
kept.push(h);
|
|
2517
|
-
} else if (nearestRejected === null || h.distance < nearestRejected) {
|
|
2518
|
-
nearestRejected = h.distance;
|
|
2519
|
-
}
|
|
2520
|
-
}
|
|
2521
|
-
return { kept, nearestRejected };
|
|
2522
|
-
}
|
|
2523
2618
|
function semanticDegradedFields(preflight, searchSemanticError) {
|
|
2524
2619
|
if (preflight.status !== "ready") {
|
|
2525
2620
|
return {
|
|
@@ -2535,20 +2630,20 @@ function semanticDegradedFields(preflight, searchSemanticError) {
|
|
|
2535
2630
|
}
|
|
2536
2631
|
async function runSemantic(query, opts) {
|
|
2537
2632
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
2538
|
-
const message = `--limit must be a positive number, got: ${
|
|
2633
|
+
const message = (shown) => `--limit must be a positive number, got: ${shown}`;
|
|
2539
2634
|
if (opts.json === true) {
|
|
2540
|
-
return { text: displaySafeJson({ error: message }), code: 1 };
|
|
2635
|
+
return { text: displaySafeJson({ error: message(String(opts.limit)) }), code: 1 };
|
|
2541
2636
|
}
|
|
2542
|
-
return { text: message, code: 1 };
|
|
2637
|
+
return { text: message(echoedValue(String(opts.limit))), code: 1 };
|
|
2543
2638
|
}
|
|
2544
2639
|
const n = opts.limit !== void 0 && Number.isFinite(opts.limit) ? opts.limit : 20;
|
|
2545
2640
|
if (opts.projectRoot !== void 0) {
|
|
2546
|
-
if (!path2.isAbsolute(opts.projectRoot) || !
|
|
2547
|
-
const message = `
|
|
2641
|
+
if (!path2.isAbsolute(opts.projectRoot) || !fs3.existsSync(opts.projectRoot) || !fs3.statSync(opts.projectRoot).isDirectory()) {
|
|
2642
|
+
const message = (shown) => `projectRoot must be an absolute, existing directory, got ${shown}`;
|
|
2548
2643
|
if (opts.json === true) {
|
|
2549
|
-
return { text: displaySafeJson({ error: message }), code: 1 };
|
|
2644
|
+
return { text: displaySafeJson({ error: message(opts.projectRoot) }), code: 1 };
|
|
2550
2645
|
}
|
|
2551
|
-
return { text: message, code: 1 };
|
|
2646
|
+
return { text: message(echoedValue(opts.projectRoot)), code: 1 };
|
|
2552
2647
|
}
|
|
2553
2648
|
}
|
|
2554
2649
|
const projectDenial = resolveProjectConfinement(opts.projectRoot).denial;
|
|
@@ -2615,7 +2710,7 @@ async function runSemantic(query, opts) {
|
|
|
2615
2710
|
if (embeddingsEnabled && !deferred) {
|
|
2616
2711
|
try {
|
|
2617
2712
|
rawHits = await searchSemantic(
|
|
2618
|
-
|
|
2713
|
+
getReadDb(globalDbPath()),
|
|
2619
2714
|
query,
|
|
2620
2715
|
overFetchForMerge,
|
|
2621
2716
|
void 0,
|
|
@@ -2631,21 +2726,18 @@ async function runSemantic(query, opts) {
|
|
|
2631
2726
|
}
|
|
2632
2727
|
}
|
|
2633
2728
|
}
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
`Matching on meaning found nothing within ${floor} (closest was ${nearestRejected.toFixed(3)}); these results come from keyword search alone. Raise semantic.max_distance to see weaker matches.`
|
|
2642
|
-
);
|
|
2643
|
-
}
|
|
2644
|
-
rawHits = kept;
|
|
2729
|
+
const relevance = assessDenseRelevance(rawHits);
|
|
2730
|
+
const floorNearestRejected = relevance.nearestRejected;
|
|
2731
|
+
const floorEmptied = floorEmptiedPhrase(relevance);
|
|
2732
|
+
if (floorEmptied !== null) {
|
|
2733
|
+
console.warn(
|
|
2734
|
+
`Matching on meaning found ${floorEmptied}; these results come from keyword search alone. Raise semantic.max_distance to see weaker matches.`
|
|
2735
|
+
);
|
|
2645
2736
|
}
|
|
2646
|
-
|
|
2647
|
-
const
|
|
2648
|
-
const
|
|
2737
|
+
rawHits = relevance.kept;
|
|
2738
|
+
const closestDense = relevance.closestDistance;
|
|
2739
|
+
const { weakDistance, weakClosestDistance } = relevance;
|
|
2740
|
+
const weakPhrase = weakMatchPhrase(relevance);
|
|
2649
2741
|
if (closestDense !== null || preflight.status === "ready" && !searchSemanticError) {
|
|
2650
2742
|
recordSemanticQuery({ projectRoot: rootDir, closestDistance: closestDense, floorRejectedMin: floorNearestRejected, weak: weakClosestDistance !== null });
|
|
2651
2743
|
}
|
|
@@ -2655,7 +2747,7 @@ async function runSemantic(query, opts) {
|
|
|
2655
2747
|
const { indexedFiles, embeddedFiles } = enabled ? getEmbeddingCoverage(globalDbPath(), rootDir) : { indexedFiles: 0, embeddedFiles: 0 };
|
|
2656
2748
|
if (indexedFiles > 0 && embeddedFiles < indexedFiles) {
|
|
2657
2749
|
console.warn(
|
|
2658
|
-
`Matching on meaning found nothing, and only ${embeddedFiles} of ${indexedFiles
|
|
2750
|
+
`Matching on meaning found nothing, and only ${embeddedFiles} of ${countNoun(indexedFiles, "indexed file")} in this project have embeddings \u2014 these results come from keyword search alone. Run \`token-goat doctor\` for why.`
|
|
2659
2751
|
);
|
|
2660
2752
|
}
|
|
2661
2753
|
} catch {
|
|
@@ -2770,9 +2862,9 @@ ${previewLines(h.previewText, 3)}`;
|
|
|
2770
2862
|
if (hits.length < eligibleCount) {
|
|
2771
2863
|
emitErr(`Showing ${hits.length} of ${candidatesClipped ? "at least " : ""}${countNoun(eligibleCount, "match", "matches")} (raise --limit to see the rest).`);
|
|
2772
2864
|
}
|
|
2773
|
-
if (
|
|
2865
|
+
if (weakPhrase !== null) {
|
|
2774
2866
|
console.warn(
|
|
2775
|
-
`Matching on meaning found nothing close for
|
|
2867
|
+
`Matching on meaning found nothing close for ${echoedValue(query)} (${weakPhrase}); these results may be unrelated. For a known name try token-goat symbol --grep <pattern> or rg, or rephrase the query.`
|
|
2776
2868
|
);
|
|
2777
2869
|
}
|
|
2778
2870
|
recordReadStat("semantic_search", largestFileSize(hits.map((h) => h.filePath)), text2, query);
|
|
@@ -2787,12 +2879,12 @@ ${previewLines(h.previewText, 3)}`;
|
|
|
2787
2879
|
return { text: `token-goat: ${notice.trim()}`, code: 0 };
|
|
2788
2880
|
}
|
|
2789
2881
|
if (opts.excludeTests === true && suppressedTotal > 0) {
|
|
2790
|
-
const
|
|
2882
|
+
const hidden = excludeTestsHiddenNote(suppressedTotal);
|
|
2791
2883
|
if (opts.json === true) {
|
|
2792
|
-
const payload = { source: "fts", items: [], truncated: false, totalCount: 0, excludeTestsFilteredToEmpty: true, hint:
|
|
2884
|
+
const payload = { source: "fts", items: [], truncated: false, totalCount: 0, excludeTestsFilteredToEmpty: true, hint: `no non-test matches for "${query}" (${hidden})` };
|
|
2793
2885
|
return { text: displaySafeJson(payload), code: 0 };
|
|
2794
2886
|
}
|
|
2795
|
-
return { text: `token-goat: ${
|
|
2887
|
+
return { text: `token-goat: no non-test matches for ${echoedValue(query)} (${hidden})`, code: 0 };
|
|
2796
2888
|
}
|
|
2797
2889
|
if (!anyFilter) {
|
|
2798
2890
|
const evidenceHits = await searchEvidenceSemantically(rootDir, query, n);
|
|
@@ -2848,15 +2940,15 @@ ${previewLines(entry.text, 3)}`).join("\n\n"),
|
|
|
2848
2940
|
totalCount: 0,
|
|
2849
2941
|
...semanticDegradedFields(preflight, searchSemanticError),
|
|
2850
2942
|
...!indexEmpty && isIdentifier2 ? {
|
|
2851
|
-
symbolSuggestion: `token-goat symbol
|
|
2943
|
+
symbolSuggestion: `token-goat symbol ${quotedArg(trimmedQuery2)}`,
|
|
2852
2944
|
...symFound ? { indexedSymbolFound: true } : {}
|
|
2853
2945
|
} : {}
|
|
2854
2946
|
};
|
|
2855
2947
|
const text2 = displaySafeJson(payload);
|
|
2856
2948
|
return { text: text2, code: 1 };
|
|
2857
2949
|
}
|
|
2858
|
-
let text = indexEmpty ? `
|
|
2859
|
-
${emptyIndexMessage(rootDir)}` : `
|
|
2950
|
+
let text = indexEmpty ? `no matches for ${echoedValue(query)}
|
|
2951
|
+
${emptyIndexMessage(rootDir)}` : `no matches for ${echoedValue(query)}`;
|
|
2860
2952
|
const trimmedQuery = query.trim();
|
|
2861
2953
|
const isIdentifier = /^[A-Za-z0-9_.:-]+$/.test(trimmedQuery);
|
|
2862
2954
|
if (!indexEmpty && isIdentifier) {
|
|
@@ -2869,11 +2961,11 @@ ${emptyIndexMessage(rootDir)}` : `token-goat: no matches for '${query}'`;
|
|
|
2869
2961
|
} catch {
|
|
2870
2962
|
}
|
|
2871
2963
|
if (symFound) {
|
|
2872
|
-
text += `
|
|
2873
|
-
(note:
|
|
2964
|
+
text += forClient(`
|
|
2965
|
+
(note: ${echoedValue(trimmedQuery)} is an indexed symbol name; use: ${fencedCommand("token-goat symbol " + quotedArg(trimmedQuery))})`);
|
|
2874
2966
|
} else {
|
|
2875
|
-
text += `
|
|
2876
|
-
Try: token-goat symbol
|
|
2967
|
+
text += forClient(`
|
|
2968
|
+
Try: token-goat symbol ${quotedArg(trimmedQuery)}`);
|
|
2877
2969
|
}
|
|
2878
2970
|
}
|
|
2879
2971
|
if (preflight.status !== "ready") {
|
|
@@ -2898,7 +2990,7 @@ async function runSemanticMulti(queries, opts) {
|
|
|
2898
2990
|
entries.push({ query, ...JSON.parse(sub.text) });
|
|
2899
2991
|
continue;
|
|
2900
2992
|
}
|
|
2901
|
-
blocks.push(
|
|
2993
|
+
blocks.push(`${echoedValue(query)}:
|
|
2902
2994
|
${sub.text}`);
|
|
2903
2995
|
}
|
|
2904
2996
|
return { text: opts.json === true ? displaySafeJson(entries) : blocks.join("\n\n"), code: anyOk ? 0 : 1 };
|
|
@@ -2925,7 +3017,7 @@ function renderRefLines(ref, contextLines, indent = " ") {
|
|
|
2925
3017
|
const base = `${indent}${displaySafeText(displayPath)}:${ref.line}: ${displaySafeText(ref.context)}${goneSuffix(ref.filePath)}`;
|
|
2926
3018
|
const window = buildContextWindow(ref.filePath, ref.line, contextLines);
|
|
2927
3019
|
if (window === null) return [base];
|
|
2928
|
-
return [base, ...renderContextWindow(displayPath, ref.line, window, "", `${indent} `)];
|
|
3020
|
+
return [base, ...renderContextWindow(displaySafeText(displayPath), ref.line, window, "", `${indent} `)];
|
|
2929
3021
|
}
|
|
2930
3022
|
function withContextLines(items, contextLines) {
|
|
2931
3023
|
if (!(contextLines > 0)) return items;
|
|
@@ -3002,27 +3094,27 @@ function refsSearchBaselineBytes(rows) {
|
|
|
3002
3094
|
`, "utf8");
|
|
3003
3095
|
return deliveredOutputBytes(total);
|
|
3004
3096
|
}
|
|
3005
|
-
function renderRefsTargets(targets, opts
|
|
3006
|
-
annotateHiddenByGrep
|
|
3007
|
-
}) {
|
|
3097
|
+
function renderRefsTargets(targets, opts) {
|
|
3008
3098
|
for (const { file, symbol } of targets) {
|
|
3009
3099
|
if (file === void 0 || !symbol.includes(".")) continue;
|
|
3010
3100
|
const qualified = resolveQualifiedSpec(`${file}::${symbol}`, opts.projectRoot ?? process.cwd());
|
|
3011
3101
|
if (qualified?.kind !== "ambiguous") continue;
|
|
3012
|
-
emitErr(formatAmbiguity(qualified.symbol, qualified.file, qualified.candidates, opts.projectRoot, "refs"));
|
|
3102
|
+
emitErr(formatCommandError(new CliError(formatAmbiguity(qualified.symbol, qualified.file, qualified.candidates, opts.projectRoot, "refs").split("\n"))));
|
|
3013
3103
|
return 1;
|
|
3014
3104
|
}
|
|
3015
3105
|
const jsonOut = {};
|
|
3016
3106
|
let anyFound = false;
|
|
3107
|
+
let anyFilteredByGrep = false;
|
|
3017
3108
|
const lines = [];
|
|
3018
3109
|
const refRows = [];
|
|
3019
3110
|
for (const { file, symbol, key } of targets) {
|
|
3020
3111
|
const { queryOpts, results, preScanCount, scanLimit, suppressed, preGrepCount, clientFiltered, filteredTotal } = collectRefs(symbol, file, opts);
|
|
3021
3112
|
if (results.length > 0) anyFound = true;
|
|
3113
|
+
else if (opts.grep !== void 0 && preGrepCount > 0) anyFilteredByGrep = true;
|
|
3022
3114
|
refRows.push(...results);
|
|
3023
3115
|
if (opts.json === true) {
|
|
3024
3116
|
const hiddenByGrep = opts.grep !== void 0 ? preGrepCount - (filteredTotal ?? results.length) : 0;
|
|
3025
|
-
const withHidden = (payload) => ({ ...payload, ...
|
|
3117
|
+
const withHidden = (payload) => ({ ...payload, ...hiddenByGrep > 0 ? { hiddenByGrep } : {} });
|
|
3026
3118
|
if (opts.top !== void 0) {
|
|
3027
3119
|
jsonOut[key] = withHidden(topFilesJsonPayload(results, opts.top));
|
|
3028
3120
|
} else {
|
|
@@ -3067,32 +3159,36 @@ function renderRefsTargets(targets, opts, {
|
|
|
3067
3159
|
const text2 = displaySafeJson(jsonOut);
|
|
3068
3160
|
emit(text2);
|
|
3069
3161
|
if (anyFound) recordReadStat("symbol_read", fullSourceBytes, text2, opts.spec);
|
|
3070
|
-
return anyFound ? 0 : 1;
|
|
3162
|
+
return anyFound || anyFilteredByGrep ? 0 : 1;
|
|
3163
|
+
}
|
|
3164
|
+
if (!anyFound && !anyFilteredByGrep) {
|
|
3165
|
+
emitErr(formatCommandError(new CliError(lines)));
|
|
3166
|
+
return 1;
|
|
3071
3167
|
}
|
|
3072
3168
|
const text = lines.join("\n");
|
|
3073
3169
|
emitGuarded(text, "symbol");
|
|
3074
3170
|
if (anyFound) recordReadStat("symbol_read", fullSourceBytes, text, opts.spec);
|
|
3075
|
-
return
|
|
3171
|
+
return 0;
|
|
3076
3172
|
}
|
|
3077
3173
|
function runRefs(opts) {
|
|
3078
3174
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
3079
|
-
emitErr(`--limit must be a positive number, got: ${opts.limit}`);
|
|
3175
|
+
emitErr(formatCommandError(`--limit must be a positive number, got: ${echoedValue(String(opts.limit))}`));
|
|
3080
3176
|
return 1;
|
|
3081
3177
|
}
|
|
3082
3178
|
if (opts.top !== void 0 && opts.top <= 0) {
|
|
3083
|
-
emitErr(`--top must be a positive number, got: ${opts.top}`);
|
|
3179
|
+
emitErr(formatCommandError(`--top must be a positive number, got: ${echoedValue(String(opts.top))}`));
|
|
3084
3180
|
return 1;
|
|
3085
3181
|
}
|
|
3086
3182
|
const { root: confinedRoot, denial: projectDenial } = resolveProjectConfinement(opts.projectRoot);
|
|
3087
3183
|
if (projectDenial !== null) {
|
|
3088
|
-
emitErr(projectDenial);
|
|
3184
|
+
emitErr(formatCommandError(projectDenial));
|
|
3089
3185
|
return 1;
|
|
3090
3186
|
}
|
|
3091
3187
|
if (confinedRoot !== null) {
|
|
3092
3188
|
for (const file2 of refsSpecFiles(opts.spec)) {
|
|
3093
3189
|
const denial = confinementRefusal("This file", resolveSpecPath(file2, opts.projectRoot ?? process.cwd()), confinedRoot);
|
|
3094
3190
|
if (denial !== null) {
|
|
3095
|
-
emitErr(denial);
|
|
3191
|
+
emitErr(formatCommandError(denial));
|
|
3096
3192
|
return 1;
|
|
3097
3193
|
}
|
|
3098
3194
|
}
|
|
@@ -3103,8 +3199,7 @@ function runRefs(opts) {
|
|
|
3103
3199
|
if (symbols.length <= 1) return runRefsSingle(opts);
|
|
3104
3200
|
return renderRefsTargets(
|
|
3105
3201
|
symbols.map((symbol) => ({ file, symbol, key: symbol })),
|
|
3106
|
-
opts
|
|
3107
|
-
{ annotateHiddenByGrep: true }
|
|
3202
|
+
opts
|
|
3108
3203
|
);
|
|
3109
3204
|
}
|
|
3110
3205
|
function runRefsCrossFile(pairs, opts) {
|
|
@@ -3112,16 +3207,14 @@ function runRefsCrossFile(pairs, opts) {
|
|
|
3112
3207
|
const keyFor = (p) => distinctFiles.size === 1 ? p.symbol : `${p.file}::${p.symbol}`;
|
|
3113
3208
|
return renderRefsTargets(
|
|
3114
3209
|
pairs.map((p) => ({ file: p.file, symbol: p.symbol, key: keyFor(p) })),
|
|
3115
|
-
opts
|
|
3116
|
-
// Not annotated today; renderRefsTargets's own option doc explains why that is a preserved divergence rather than a decision.
|
|
3117
|
-
{ annotateHiddenByGrep: false }
|
|
3210
|
+
opts
|
|
3118
3211
|
);
|
|
3119
3212
|
}
|
|
3120
3213
|
function runRefsSingle(opts) {
|
|
3121
3214
|
const { file, symbol } = parseReadSpec(opts.spec);
|
|
3122
3215
|
const qualified = resolveQualifiedSpec(opts.spec, opts.projectRoot ?? process.cwd());
|
|
3123
3216
|
if (qualified?.kind === "ambiguous") {
|
|
3124
|
-
emitErr(formatAmbiguity(qualified.symbol, qualified.file, qualified.candidates, opts.projectRoot, "refs"));
|
|
3217
|
+
emitErr(formatCommandError(new CliError(formatAmbiguity(qualified.symbol, qualified.file, qualified.candidates, opts.projectRoot, "refs").split("\n"))));
|
|
3125
3218
|
return 1;
|
|
3126
3219
|
}
|
|
3127
3220
|
const qualifiedDef = qualified?.kind === "ok" ? qualified.entry : void 0;
|
|
@@ -3137,29 +3230,29 @@ function runRefsSingle(opts) {
|
|
|
3137
3230
|
return 0;
|
|
3138
3231
|
}
|
|
3139
3232
|
if (opts.excludeTests === true && suppressed > 0) {
|
|
3140
|
-
emitErr(`No non-test references found for
|
|
3233
|
+
emitErr(formatCommandError(`No non-test references found for ${echoedValue(symName)} (${excludeTestsHiddenNote(suppressed)})`));
|
|
3141
3234
|
return 1;
|
|
3142
3235
|
}
|
|
3143
3236
|
const rootDir = opts.projectRoot ?? resolveProjectRoot({ project: process.cwd() });
|
|
3144
3237
|
const defRows = querySymbols({ name: symName, rootDir, limit: REF_BLIND_DEF_PROBE_LIMIT });
|
|
3145
3238
|
if (defRows.length === 0) {
|
|
3146
|
-
emitErr(`Symbol not found: ${symName}${unknownSymbolSuggestion(symName, rootDir)}`);
|
|
3239
|
+
emitErr(formatCommandError(`Symbol not found: ${echoedValue(symName)}${unknownSymbolSuggestion(symName, rootDir)}`));
|
|
3147
3240
|
if (opts.json !== true && isIndexEmptyForProject(globalDbPath(), rootDir)) emitErr(emptyIndexMessage(rootDir));
|
|
3148
3241
|
return 1;
|
|
3149
3242
|
}
|
|
3150
3243
|
const defPaths = defFileHint !== void 0 ? [defFileHint] : defRows.map((r) => r.filePath);
|
|
3151
3244
|
const firstDefPath = defPaths[0];
|
|
3152
3245
|
if (firstDefPath !== void 0 && defPaths.every((fp) => !isRefIndexedFile(fp))) {
|
|
3153
|
-
emitErr(refBlindLanguageNotice(symName, detectLanguageOfFile(firstDefPath), refsDisplayPath(firstDefPath)));
|
|
3246
|
+
emitErr(formatCommandError(refBlindLanguageNotice(symName, detectLanguageOfFile(firstDefPath), refsDisplayPath(firstDefPath))));
|
|
3154
3247
|
return 1;
|
|
3155
3248
|
}
|
|
3156
3249
|
const kindRows = defFileHint !== void 0 ? querySymbols({ name: symName, filePath: defFileHint, rootDir, limit: REF_BLIND_DEF_PROBE_LIMIT }) : defRows;
|
|
3157
3250
|
const kindVerdict = refBlindKindVerdict(kindRows);
|
|
3158
3251
|
if (kindVerdict.allBlind) {
|
|
3159
|
-
emitErr(refBlindKindNotice(symName, kindVerdict.blindKinds));
|
|
3252
|
+
emitErr(formatCommandError(refBlindKindNotice(symName, kindVerdict.blindKinds)));
|
|
3160
3253
|
return 1;
|
|
3161
3254
|
}
|
|
3162
|
-
emitErr(`No references found for
|
|
3255
|
+
emitErr(formatCommandError(`No references found for ${echoedValue(symName)}`));
|
|
3163
3256
|
if (kindVerdict.blindCount > 0) emitErr(refBlindKindPartialNote(symName, kindVerdict.blindKinds, kindVerdict.blindCount, kindRows.length));
|
|
3164
3257
|
if (opts.json !== true) {
|
|
3165
3258
|
if (isIndexEmptyForProject(globalDbPath(), rootDir)) emitErr(emptyIndexMessage(rootDir));
|
|
@@ -3208,7 +3301,7 @@ function renderTopFilesSummary(refs, topN, suppressed) {
|
|
|
3208
3301
|
const omittedFiles = grouped.length - shown.length;
|
|
3209
3302
|
if (omittedFiles > 0) {
|
|
3210
3303
|
const shownRefs = shown.reduce((sum, g) => sum + g.count, 0);
|
|
3211
|
-
lines.push(` ...(${omittedFiles
|
|
3304
|
+
lines.push(forClient(` ...(${countNoun(omittedFiles, "more file")}, ${countNoun(refs.length - shownRefs, "more reference")} elided; use a higher --top to see more)`));
|
|
3212
3305
|
}
|
|
3213
3306
|
return lines;
|
|
3214
3307
|
}
|
|
@@ -3234,7 +3327,7 @@ function renderCallerGroups(refs, contextLines = 0) {
|
|
|
3234
3327
|
for (const ref of fileRefs) {
|
|
3235
3328
|
lines.push(` :${ref.line} ${ref.context !== "" ? displaySafeText(ref.context) : "(module scope)"}`);
|
|
3236
3329
|
const window = buildContextWindow(file, ref.line, contextLines);
|
|
3237
|
-
if (window !== null) lines.push(...renderContextWindow(displayPath, ref.line, window, "", " "));
|
|
3330
|
+
if (window !== null) lines.push(...renderContextWindow(displaySafeText(displayPath), ref.line, window, "", " "));
|
|
3238
3331
|
}
|
|
3239
3332
|
}
|
|
3240
3333
|
return lines;
|
|
@@ -3242,7 +3335,7 @@ function renderCallerGroups(refs, contextLines = 0) {
|
|
|
3242
3335
|
|
|
3243
3336
|
// src/read_git.ts
|
|
3244
3337
|
init_define_import_meta_env();
|
|
3245
|
-
import * as
|
|
3338
|
+
import * as fs4 from "node:fs";
|
|
3246
3339
|
import * as path3 from "node:path";
|
|
3247
3340
|
|
|
3248
3341
|
// src/conflict_query.ts
|
|
@@ -3445,9 +3538,9 @@ function runConflicts(opts) {
|
|
|
3445
3538
|
const abs = path3.resolve(opts.path);
|
|
3446
3539
|
let stat;
|
|
3447
3540
|
try {
|
|
3448
|
-
stat =
|
|
3541
|
+
stat = fs4.statSync(abs);
|
|
3449
3542
|
} catch {
|
|
3450
|
-
emitErr(
|
|
3543
|
+
emitErr(formatCommandError(couldNotReadError(opts.path)));
|
|
3451
3544
|
return 1;
|
|
3452
3545
|
}
|
|
3453
3546
|
files = stat.isDirectory() ? walkProject(abs).files : [abs];
|
|
@@ -3566,6 +3659,21 @@ function parseHunklessFiles(diffText) {
|
|
|
3566
3659
|
return hunkless;
|
|
3567
3660
|
}
|
|
3568
3661
|
var EMPTY_TREE_HASH = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
3662
|
+
var CHANGED_HINT_BATCH = 512;
|
|
3663
|
+
function batchRowResolved(row) {
|
|
3664
|
+
return row !== void 0 && /^[0-9a-f]{40,64} /.test(row);
|
|
3665
|
+
}
|
|
3666
|
+
function resolveHintRefs(cwd, ref, candidates) {
|
|
3667
|
+
const batch = runGit(["cat-file", "--batch-check"], { cwd, input: `${[ref, ...candidates].join("\n")}
|
|
3668
|
+
` });
|
|
3669
|
+
const rows = batch.stdout.split(/\r?\n/);
|
|
3670
|
+
if (batch.exitCode === 0 && rows.length >= candidates.length + 1) {
|
|
3671
|
+
return { refResolves: batchRowResolved(rows[0]), suggestedRef: candidates.find((_, i) => batchRowResolved(rows[i + 1])) ?? null };
|
|
3672
|
+
}
|
|
3673
|
+
const resolves = (name) => runGit(["rev-parse", "--verify", "--quiet", name], { cwd }).exitCode === 0;
|
|
3674
|
+
if (resolves(ref)) return { refResolves: true, suggestedRef: null };
|
|
3675
|
+
return { refResolves: false, suggestedRef: candidates.find((c) => resolves(c)) ?? null };
|
|
3676
|
+
}
|
|
3569
3677
|
function buildChangedRefHint(cwd, ref) {
|
|
3570
3678
|
const countResult = runGit(["rev-list", "--count", "HEAD"], { cwd });
|
|
3571
3679
|
if (countResult.exitCode !== 0) {
|
|
@@ -3575,61 +3683,67 @@ function buildChangedRefHint(cwd, ref) {
|
|
|
3575
3683
|
if (!Number.isFinite(commitCount) || commitCount < 1) {
|
|
3576
3684
|
return null;
|
|
3577
3685
|
}
|
|
3578
|
-
|
|
3579
|
-
if (refResolves.exitCode === 0) {
|
|
3686
|
+
if (/[\r\n]/.test(ref)) {
|
|
3580
3687
|
return null;
|
|
3581
3688
|
}
|
|
3582
|
-
|
|
3583
|
-
for (let n = commitCount - 1; n >= 1; n--) {
|
|
3584
|
-
|
|
3585
|
-
const candidateResolves = runGit(["rev-parse", "--verify", "--quiet", candidate], { cwd });
|
|
3586
|
-
if (candidateResolves.exitCode === 0) {
|
|
3587
|
-
suggestedRef = candidate;
|
|
3588
|
-
break;
|
|
3589
|
-
}
|
|
3689
|
+
const candidates = [];
|
|
3690
|
+
for (let n = commitCount - 1; n >= 1 && candidates.length < CHANGED_HINT_BATCH; n--) {
|
|
3691
|
+
candidates.push(`HEAD~${n}`);
|
|
3590
3692
|
}
|
|
3693
|
+
const answer = resolveHintRefs(cwd, ref, candidates);
|
|
3694
|
+
if (answer.refResolves) {
|
|
3695
|
+
return null;
|
|
3696
|
+
}
|
|
3697
|
+
let suggestedRef = answer.suggestedRef;
|
|
3591
3698
|
if (suggestedRef === null) {
|
|
3592
3699
|
suggestedRef = EMPTY_TREE_HASH;
|
|
3593
3700
|
}
|
|
3594
3701
|
const commitWord = commitCount === 1 ? "1 commit" : `${commitCount} commits`;
|
|
3595
|
-
return `Hint: this repo has only ${commitWord};
|
|
3702
|
+
return `Hint: this repo has only ${commitWord}; ${echoedValue(ref)} does not exist. Try: token-goat changed --since ${suggestedRef}`;
|
|
3596
3703
|
}
|
|
3597
3704
|
function refIsSafe(ref) {
|
|
3598
3705
|
return !ref.startsWith("-");
|
|
3599
3706
|
}
|
|
3600
3707
|
function emitUnsafeRef(ref) {
|
|
3601
|
-
emitErr(`Refusing a git ref that starts with '-': ${ref}`);
|
|
3708
|
+
emitErr(formatCommandError(`Refusing a git ref that starts with '-': ${ref}`));
|
|
3602
3709
|
}
|
|
3603
3710
|
function literalPathspec(file) {
|
|
3604
3711
|
return `:(literal)${file}`;
|
|
3605
3712
|
}
|
|
3606
|
-
function
|
|
3607
|
-
const
|
|
3713
|
+
function parseNameStatus(stdout) {
|
|
3714
|
+
const unquote = (f) => f.startsWith('"') && f.endsWith('"') && f.length > 1 ? unquoteGitPath(f.slice(1, -1)) : f;
|
|
3715
|
+
const files = [];
|
|
3716
|
+
const renamedFrom = /* @__PURE__ */ new Map();
|
|
3717
|
+
for (const row of stdout.split(/\r?\n/)) {
|
|
3718
|
+
if (row === "") continue;
|
|
3719
|
+
const cols = row.split(" ");
|
|
3720
|
+
const last = cols[cols.length - 1];
|
|
3721
|
+
if (cols.length < 2 || last === void 0 || last === "") continue;
|
|
3722
|
+
files.push(unquote(last));
|
|
3723
|
+
const from = cols[1];
|
|
3724
|
+
if (cols[0]?.startsWith("R") === true && cols.length === 3 && from !== void 0) renamedFrom.set(unquote(last), unquote(from));
|
|
3725
|
+
}
|
|
3726
|
+
return { files, renamedFrom };
|
|
3727
|
+
}
|
|
3728
|
+
function withRenameSources(files, renamedFrom) {
|
|
3608
3729
|
const paths = [...files];
|
|
3609
|
-
|
|
3610
|
-
const
|
|
3611
|
-
if (
|
|
3612
|
-
const unquote = (f) => f.startsWith('"') && f.endsWith('"') && f.length > 1 ? unquoteGitPath(f.slice(1, -1)) : f;
|
|
3613
|
-
for (const row of result.stdout.split(/\r?\n/)) {
|
|
3614
|
-
const [status, from, to] = row.split(" ");
|
|
3615
|
-
if (status?.startsWith("R") !== true || from === void 0 || to === void 0) continue;
|
|
3616
|
-
if (wanted.has(unquote(to))) paths.push(unquote(from));
|
|
3617
|
-
}
|
|
3618
|
-
} catch {
|
|
3730
|
+
for (const file of files) {
|
|
3731
|
+
const from = renamedFrom.get(file);
|
|
3732
|
+
if (from !== void 0) paths.push(from);
|
|
3619
3733
|
}
|
|
3620
3734
|
return paths;
|
|
3621
3735
|
}
|
|
3622
|
-
function unifiedDiffOf(cwd, ref, files, extraArgs = []) {
|
|
3736
|
+
function unifiedDiffOf(cwd, ref, files, renamedFrom, extraArgs = []) {
|
|
3623
3737
|
const run = (paths2) => runGit(["diff", ref, "-M", "--unified=0", ...extraArgs, "--", ...paths2.map(literalPathspec)], { cwd });
|
|
3624
3738
|
const first = run(files);
|
|
3625
3739
|
if (first.exitCode !== 0 || !first.stdout.includes("--- /dev/null")) return first;
|
|
3626
|
-
const paths = withRenameSources(
|
|
3740
|
+
const paths = withRenameSources(files, renamedFrom);
|
|
3627
3741
|
return paths.length > files.length ? run(paths) : first;
|
|
3628
3742
|
}
|
|
3629
|
-
function changedDiffBaselineBytes(cwd, ref, files) {
|
|
3743
|
+
function changedDiffBaselineBytes(cwd, ref, files, renamedFrom) {
|
|
3630
3744
|
if (files.length === 0) return 0;
|
|
3631
3745
|
try {
|
|
3632
|
-
const result = unifiedDiffOf(cwd, ref, files);
|
|
3746
|
+
const result = unifiedDiffOf(cwd, ref, files, renamedFrom);
|
|
3633
3747
|
if (result.exitCode === 0) return deliveredOutputBytes(Buffer.byteLength(result.stdout, "utf8"));
|
|
3634
3748
|
} catch {
|
|
3635
3749
|
}
|
|
@@ -3643,25 +3757,27 @@ function runChanged(opts = {}) {
|
|
|
3643
3757
|
}
|
|
3644
3758
|
const projectDenial = opts.symbolMode === true ? resolveProjectConfinement(opts.projectRoot).denial : null;
|
|
3645
3759
|
if (projectDenial !== null) {
|
|
3646
|
-
emitErr(projectDenial);
|
|
3760
|
+
emitErr(formatCommandError(projectDenial));
|
|
3647
3761
|
return 1;
|
|
3648
3762
|
}
|
|
3649
3763
|
const cwd = opts.projectRoot ?? process.cwd();
|
|
3650
|
-
const projectRoot = resolveProjectRoot({ project: cwd });
|
|
3651
3764
|
let changedFiles;
|
|
3765
|
+
let renamedFrom;
|
|
3652
3766
|
try {
|
|
3653
|
-
const result = runGit(["diff", ref, "--name-
|
|
3767
|
+
const result = runGit(["diff", ref, "--name-status"], { cwd });
|
|
3654
3768
|
if (result.exitCode !== 0) {
|
|
3655
|
-
emitErr(
|
|
3769
|
+
emitErr(formatGitFailure("diff", result.stderr));
|
|
3656
3770
|
const hint = buildChangedRefHint(cwd, ref);
|
|
3657
3771
|
if (hint !== null) {
|
|
3658
|
-
emitErr(hint);
|
|
3772
|
+
emitErr(formatCommandError(hint));
|
|
3659
3773
|
}
|
|
3660
3774
|
return 1;
|
|
3661
3775
|
}
|
|
3662
|
-
|
|
3776
|
+
const listing = parseNameStatus(result.stdout);
|
|
3777
|
+
changedFiles = listing.files;
|
|
3778
|
+
renamedFrom = listing.renamedFrom;
|
|
3663
3779
|
} catch {
|
|
3664
|
-
emitErr(`Could not run git diff against
|
|
3780
|
+
emitErr(formatCommandError(`Could not run git diff against ${echoedValue(ref)}`));
|
|
3665
3781
|
return 1;
|
|
3666
3782
|
}
|
|
3667
3783
|
const emptyEnvelope = () => {
|
|
@@ -3693,19 +3809,20 @@ function runChanged(opts = {}) {
|
|
|
3693
3809
|
const grepRemoved = preGrepFileCount - postGrepFileCount;
|
|
3694
3810
|
if (matchesGrep !== void 0 && grepRemoved > 0) {
|
|
3695
3811
|
emit(
|
|
3696
|
-
`No non-test files matched --grep ${opts.grep ?? ""} (${excludeTestsHiddenNote(hiddenTestFiles)}; ${countNoun(grepRemoved, "other changed file")} did not match the filter)`
|
|
3812
|
+
`No non-test files matched --grep ${displaySafeText(opts.grep ?? "")} (${excludeTestsHiddenNote(hiddenTestFiles)}; ${countNoun(grepRemoved, "other changed file")} did not match the filter)`
|
|
3697
3813
|
);
|
|
3698
3814
|
return 0;
|
|
3699
3815
|
}
|
|
3700
3816
|
emit(`No non-test files changed (${excludeTestsHiddenNote(hiddenTestFiles)})`);
|
|
3701
3817
|
return 0;
|
|
3702
3818
|
}
|
|
3819
|
+
const projectRoot = opts.projectRootResolved === true ? cwd : resolveProjectRoot({ project: cwd });
|
|
3703
3820
|
if (opts.symbolMode === true) {
|
|
3704
3821
|
let hunksByFile = /* @__PURE__ */ new Map();
|
|
3705
3822
|
let hunklessFiles = /* @__PURE__ */ new Set();
|
|
3706
3823
|
let symbolDiffBaselineBytes = 0;
|
|
3707
3824
|
try {
|
|
3708
|
-
const diffResult = unifiedDiffOf(projectRoot, ref, changedFiles, ["--src-prefix=a/", "--dst-prefix=b/"]);
|
|
3825
|
+
const diffResult = unifiedDiffOf(projectRoot, ref, changedFiles, renamedFrom, ["--src-prefix=a/", "--dst-prefix=b/"]);
|
|
3709
3826
|
if (diffResult.exitCode === 0) {
|
|
3710
3827
|
hunksByFile = parseDiffHunks(diffResult.stdout);
|
|
3711
3828
|
hunklessFiles = parseHunklessFiles(diffResult.stdout);
|
|
@@ -3741,7 +3858,7 @@ function runChanged(opts = {}) {
|
|
|
3741
3858
|
recordReadStat("changed_lookup", symbolFullBytes, symbolText, ref);
|
|
3742
3859
|
return 0;
|
|
3743
3860
|
}
|
|
3744
|
-
const fullBytes = changedDiffBaselineBytes(projectRoot, ref, changedFiles);
|
|
3861
|
+
const fullBytes = changedDiffBaselineBytes(projectRoot, ref, changedFiles, renamedFrom);
|
|
3745
3862
|
if (opts.json === true) {
|
|
3746
3863
|
const capped = guardJsonRows(changedFiles);
|
|
3747
3864
|
const text = displaySafeJson({ items: capped.items, truncated: capped.truncated, totalCount: capped.totalCount });
|
|
@@ -3800,22 +3917,22 @@ function runDiff(opts) {
|
|
|
3800
3917
|
try {
|
|
3801
3918
|
diffResult = runGit(diffArgs, { cwd });
|
|
3802
3919
|
} catch {
|
|
3803
|
-
emitErr(`Could not run git diff for
|
|
3920
|
+
emitErr(formatCommandError(`Could not run git diff for ${echoedValue(match.filePath)}`));
|
|
3804
3921
|
return 1;
|
|
3805
3922
|
}
|
|
3806
3923
|
if (diffResult.exitCode !== 0) {
|
|
3807
|
-
emitErr(
|
|
3924
|
+
emitErr(formatGitFailure("diff", diffResult.stderr));
|
|
3808
3925
|
return 1;
|
|
3809
3926
|
}
|
|
3810
3927
|
if (diffResult.stdout.trim() === "") {
|
|
3811
|
-
emit(`No changes to
|
|
3928
|
+
emit(`No changes to ${echoedValue(match.name)} in ${echoedValue(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath))}.`);
|
|
3812
3929
|
return 0;
|
|
3813
3930
|
}
|
|
3814
3931
|
const { hunks } = splitDiffHunks(diffResult.stdout);
|
|
3815
3932
|
const diffFileScoped = isVirtualIndexedPath(match.filePath);
|
|
3816
3933
|
const overlapping = diffFileScoped ? hunks : hunks.filter((h) => h.start <= match.lineEnd && h.end >= match.lineStart);
|
|
3817
3934
|
if (overlapping.length === 0) {
|
|
3818
|
-
emit(`No changes to
|
|
3935
|
+
emit(`No changes to ${echoedValue(match.name)} (lines ${match.lineStart}-${match.lineEnd}) in ${echoedValue(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath))}.`);
|
|
3819
3936
|
return 0;
|
|
3820
3937
|
}
|
|
3821
3938
|
if (opts.json === true) {
|
|
@@ -3898,15 +4015,15 @@ function runLog(opts) {
|
|
|
3898
4015
|
try {
|
|
3899
4016
|
logResult = runGit(logArgs, { cwd });
|
|
3900
4017
|
} catch {
|
|
3901
|
-
emitErr(`Could not run git log for
|
|
4018
|
+
emitErr(formatCommandError(`Could not run git log for ${echoedValue(match.filePath)}`));
|
|
3902
4019
|
return 1;
|
|
3903
4020
|
}
|
|
3904
4021
|
if (logResult.exitCode !== 0) {
|
|
3905
|
-
emitErr(
|
|
4022
|
+
emitErr(formatGitFailure("log", logResult.stderr));
|
|
3906
4023
|
return 1;
|
|
3907
4024
|
}
|
|
3908
4025
|
if (logResult.stdout.trim() === "") {
|
|
3909
|
-
emit(`No history for
|
|
4026
|
+
emit(`No history for ${echoedValue(match.name)} (lines ${match.lineStart}-${match.lineEnd}) in ${echoedValue(toDisplayPath(getDisplayRoot(opts.projectRoot), match.filePath))}.`);
|
|
3910
4027
|
return 0;
|
|
3911
4028
|
}
|
|
3912
4029
|
if (opts.json === true) {
|
|
@@ -3934,14 +4051,14 @@ function runLog(opts) {
|
|
|
3934
4051
|
|
|
3935
4052
|
// src/handle_stat.ts
|
|
3936
4053
|
init_define_import_meta_env();
|
|
3937
|
-
import * as
|
|
3938
|
-
var OPEN_FOR_STAT = process.platform === "win32" ?
|
|
4054
|
+
import * as fs5 from "node:fs";
|
|
4055
|
+
var OPEN_FOR_STAT = process.platform === "win32" ? fs5.constants.O_RDONLY : fs5.constants.O_RDONLY | fs5.constants.O_NONBLOCK;
|
|
3939
4056
|
function statThroughHandle(p) {
|
|
3940
|
-
const fd =
|
|
4057
|
+
const fd = fs5.openSync(p, OPEN_FOR_STAT);
|
|
3941
4058
|
try {
|
|
3942
|
-
return
|
|
4059
|
+
return fs5.fstatSync(fd, { bigint: true });
|
|
3943
4060
|
} finally {
|
|
3944
|
-
|
|
4061
|
+
fs5.closeSync(fd);
|
|
3945
4062
|
}
|
|
3946
4063
|
}
|
|
3947
4064
|
|
|
@@ -4040,8 +4157,7 @@ function createHandoff(name, text, projectRoot) {
|
|
|
4040
4157
|
name,
|
|
4041
4158
|
projectRoot: root,
|
|
4042
4159
|
contentId: contentIdValue,
|
|
4043
|
-
// Keep the handoff independently resolvable if the generic content entry
|
|
4044
|
-
// is later evicted from the shared bounded cache.
|
|
4160
|
+
// Keep the handoff independently resolvable if the generic content entry is later evicted from the shared bounded cache.
|
|
4045
4161
|
text: safeText,
|
|
4046
4162
|
createdAt: Date.now()
|
|
4047
4163
|
};
|
|
@@ -4052,7 +4168,7 @@ function createHandoff(name, text, projectRoot) {
|
|
|
4052
4168
|
});
|
|
4053
4169
|
if (!ok) throw new Error("unable to persist handoff within the local cache bounds");
|
|
4054
4170
|
recordStat("handoff_create");
|
|
4055
|
-
return { id, name, contentId: contentIdValue, projectRoot: root, recovery: `token-goat handoff-resolve ${name}` };
|
|
4171
|
+
return { id, name, contentId: contentIdValue, projectRoot: root, recovery: `token-goat handoff-resolve -- ${quotedArg(name)}` };
|
|
4056
4172
|
}
|
|
4057
4173
|
function resolveHandoff(name, opts = {}) {
|
|
4058
4174
|
const root = normalizeProjectRoot(opts.projectRoot);
|
|
@@ -4077,6 +4193,9 @@ export {
|
|
|
4077
4193
|
checkSemanticReadiness,
|
|
4078
4194
|
offlineEmbedNotice,
|
|
4079
4195
|
mergeNearbyHits,
|
|
4196
|
+
assessDenseRelevance,
|
|
4197
|
+
floorEmptiedPhrase,
|
|
4198
|
+
weakMatchPhrase,
|
|
4080
4199
|
runSymbol,
|
|
4081
4200
|
runBrief,
|
|
4082
4201
|
AMBIGUOUS_HEADING_LIMIT,
|