token-goat 2.9.14 → 2.9.15
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 +15 -1
- package/dist/token-goat-chunk-2X2EBBC6.mjs +277 -0
- package/dist/{token-goat-chunk-XQF5J25J.mjs → token-goat-chunk-3NSDDTGL.mjs} +5 -4
- package/dist/token-goat-chunk-4EXFN2AW.mjs +29 -0
- package/dist/{token-goat-chunk-4SDX3QP3.mjs → token-goat-chunk-5V7DAC7V.mjs} +5 -4
- package/dist/token-goat-chunk-6DLVZDB6.mjs +34 -0
- package/dist/{token-goat-chunk-XEH6KBWW.mjs → token-goat-chunk-7ZYK25AO.mjs} +4 -3
- package/dist/{token-goat-chunk-7OGKZ7AP.mjs → token-goat-chunk-A4JYKD5H.mjs} +5 -3
- package/dist/{token-goat-chunk-2ESBO4IN.mjs → token-goat-chunk-ASYEPR3S.mjs} +10 -7
- package/dist/{token-goat-chunk-PGGDW7DZ.mjs → token-goat-chunk-ATIFTMRC.mjs} +9 -6
- package/dist/{token-goat-chunk-IT6O3PNN.mjs → token-goat-chunk-BL5LNGBG.mjs} +813 -4613
- package/dist/{token-goat-chunk-PRJVGIC5.mjs → token-goat-chunk-C5JIO6HK.mjs} +7 -5
- package/dist/{token-goat-chunk-YTQHZJXW.mjs → token-goat-chunk-DQ4J5AFF.mjs} +40 -17
- package/dist/token-goat-chunk-ERTXEKB6.mjs +228 -0
- package/dist/{token-goat-chunk-ASVVF4JV.mjs → token-goat-chunk-GIIHUSZX.mjs} +137 -19
- package/dist/{token-goat-chunk-DAMXYVIW.mjs → token-goat-chunk-GMQQA7E4.mjs} +296 -276
- package/dist/{token-goat-chunk-T2IWWTHB.mjs → token-goat-chunk-IVUQLQWN.mjs} +33 -1142
- package/dist/{token-goat-chunk-POBYR64E.mjs → token-goat-chunk-K7F2BFIK.mjs} +801 -3
- package/dist/{token-goat-chunk-RUDOKYPJ.mjs → token-goat-chunk-LCZBPOIN.mjs} +1733 -1360
- package/dist/token-goat-chunk-LMFO66YD.mjs +331 -0
- package/dist/{token-goat-chunk-EZNVAIR3.mjs → token-goat-chunk-LT7JRU6K.mjs} +4 -3
- package/dist/{token-goat-chunk-YHGTGG6K.mjs → token-goat-chunk-MZDIJJ3R.mjs} +29 -5
- package/dist/{token-goat-chunk-O5WAMISC.mjs → token-goat-chunk-NDPO7GAH.mjs} +26 -16
- package/dist/token-goat-chunk-NDRP4KJQ.mjs +4371 -0
- package/dist/{token-goat-chunk-ZFM4PWXL.mjs → token-goat-chunk-NU7TLMQK.mjs} +3 -3
- package/dist/token-goat-chunk-OSUFN2FV.mjs +326 -0
- package/dist/token-goat-chunk-OUGNPMDA.mjs +959 -0
- package/dist/{token-goat-chunk-AMYCQJX4.mjs → token-goat-chunk-PM76YS22.mjs} +49 -256
- package/dist/{token-goat-chunk-SAQ5PG4L.mjs → token-goat-chunk-S4XRY446.mjs} +5 -2
- package/dist/{token-goat-chunk-DBNY4RLN.mjs → token-goat-chunk-SFAS46RE.mjs} +5 -3
- package/dist/{token-goat-chunk-XVZ4MNQC.mjs → token-goat-chunk-SZWYESBS.mjs} +221 -78
- package/dist/{token-goat-chunk-HF6H7RNK.mjs → token-goat-chunk-XEPXYDPI.mjs} +3 -2
- package/dist/{token-goat-chunk-EG3663UT.mjs → token-goat-chunk-YKG35VHC.mjs} +4 -2
- package/dist/{token-goat-chunk-VZYD4OZB.mjs → token-goat-chunk-YQ7WI2CO.mjs} +78 -266
- package/dist/{token-goat-chunk-3XQPEJMV.mjs → token-goat-chunk-YZX7EFG4.mjs} +1 -1
- package/dist/token-goat-hook.mjs +13 -9
- package/dist/token-goat.core.mjs +21 -16
- package/docs/cli.md +8 -6
- package/package.json +1 -1
- package/dist/token-goat-chunk-ZD4EM4LR.mjs +0 -30
- package/dist/token-goat-chunk-ZYNNQ36L.mjs +0 -479
|
@@ -4,19 +4,20 @@ import {
|
|
|
4
4
|
canRunWrappedShell,
|
|
5
5
|
clipToDeliveryCap,
|
|
6
6
|
deliveredOutputBytes
|
|
7
|
-
} from "./token-goat-chunk-
|
|
7
|
+
} from "./token-goat-chunk-YZX7EFG4.mjs";
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_RECONCILE_BUDGET_MS,
|
|
10
10
|
HOOK_EVENTS,
|
|
11
11
|
buildCommandManifest,
|
|
12
12
|
checkSymbolBodySize,
|
|
13
|
+
diagnoseSqlFailure,
|
|
13
14
|
flattenCommandNames,
|
|
14
15
|
getWebOutput,
|
|
15
16
|
isReconcileClean,
|
|
16
17
|
readStdinJson,
|
|
17
18
|
reconcileProject,
|
|
18
19
|
storeWebOutput
|
|
19
|
-
} from "./token-goat-chunk-
|
|
20
|
+
} from "./token-goat-chunk-OUGNPMDA.mjs";
|
|
20
21
|
import {
|
|
21
22
|
GENERIC_SERVED_OUTPUT_KEY,
|
|
22
23
|
OUTLINE_MAX_REPLACEMENT_RATIO,
|
|
@@ -35,14 +36,12 @@ import {
|
|
|
35
36
|
enqueueDirtyPathSafe,
|
|
36
37
|
ensureWorkerAlive,
|
|
37
38
|
extractCompactFromMarker,
|
|
38
|
-
extractMarkdownHeadings,
|
|
39
39
|
fenceUntrusted,
|
|
40
40
|
fenceUntrustedSpans,
|
|
41
41
|
fenceWithMatches,
|
|
42
42
|
foldDelivery,
|
|
43
43
|
foldDetail,
|
|
44
44
|
foldingEnabled,
|
|
45
|
-
formatHeadingTreeParts,
|
|
46
45
|
formatProjectMap,
|
|
47
46
|
formatShrinkSummary,
|
|
48
47
|
getBashOutputId,
|
|
@@ -119,7 +118,7 @@ import {
|
|
|
119
118
|
wasCliReadThisSession,
|
|
120
119
|
wasFileReadThisSession,
|
|
121
120
|
wasHintShown
|
|
122
|
-
} from "./token-goat-chunk-
|
|
121
|
+
} from "./token-goat-chunk-BL5LNGBG.mjs";
|
|
123
122
|
import {
|
|
124
123
|
BASH_OUTPUT_SUBDIR,
|
|
125
124
|
BODY_FIRST_TOOL_RESPONSE_KEYS,
|
|
@@ -127,7 +126,6 @@ import {
|
|
|
127
126
|
commandHash,
|
|
128
127
|
compressOutput,
|
|
129
128
|
contextOutput,
|
|
130
|
-
countSymbols,
|
|
131
129
|
dedupeConsecutive,
|
|
132
130
|
denyOutput,
|
|
133
131
|
detectFromCommand,
|
|
@@ -169,17 +167,26 @@ import {
|
|
|
169
167
|
storeBashOutput,
|
|
170
168
|
summarizeOutputDelta,
|
|
171
169
|
withPreservedBlocks
|
|
172
|
-
} from "./token-goat-chunk-
|
|
170
|
+
} from "./token-goat-chunk-YQ7WI2CO.mjs";
|
|
171
|
+
import {
|
|
172
|
+
extractMarkdownHeadings,
|
|
173
|
+
formatHeadingTreeParts
|
|
174
|
+
} from "./token-goat-chunk-NDRP4KJQ.mjs";
|
|
175
|
+
import {
|
|
176
|
+
countSymbols
|
|
177
|
+
} from "./token-goat-chunk-2X2EBBC6.mjs";
|
|
173
178
|
import {
|
|
174
|
-
detectLanguage,
|
|
175
|
-
getDb,
|
|
176
|
-
languageHasFlag,
|
|
177
179
|
recordStat,
|
|
178
180
|
redactSecrets,
|
|
179
181
|
savedTokensFromBytes,
|
|
180
182
|
storeBlob,
|
|
181
183
|
stripAnsiEscapes
|
|
182
|
-
} from "./token-goat-chunk-
|
|
184
|
+
} from "./token-goat-chunk-IVUQLQWN.mjs";
|
|
185
|
+
import {
|
|
186
|
+
detectLanguage,
|
|
187
|
+
getDb,
|
|
188
|
+
languageHasFlag
|
|
189
|
+
} from "./token-goat-chunk-K7F2BFIK.mjs";
|
|
183
190
|
import {
|
|
184
191
|
detectHarness,
|
|
185
192
|
envBool,
|
|
@@ -189,34 +196,36 @@ import {
|
|
|
189
196
|
isUnderSystemTemp,
|
|
190
197
|
loadConfig,
|
|
191
198
|
shortFingerprint
|
|
192
|
-
} from "./token-goat-chunk-
|
|
199
|
+
} from "./token-goat-chunk-S4XRY446.mjs";
|
|
193
200
|
import {
|
|
194
201
|
ENV_KEYS,
|
|
195
202
|
IDENTICAL_READ_MIN_BODY_BYTES,
|
|
196
203
|
PER_FILE_COUNTERFACTUAL_CEILING,
|
|
197
|
-
UNTRUSTED_TOOL_TAG,
|
|
198
204
|
VERSION,
|
|
199
205
|
atomicWriteText,
|
|
200
206
|
containsLineRun,
|
|
201
207
|
countNoun,
|
|
202
208
|
dataDir,
|
|
203
|
-
displaySafePath,
|
|
204
|
-
displaySafeText,
|
|
205
209
|
ensureDirSync,
|
|
206
210
|
escapesOntoNetworkThroughLinks,
|
|
207
211
|
extractErrorMessage,
|
|
208
|
-
fenceUntrustedFileContent,
|
|
209
212
|
foldPath,
|
|
210
213
|
globalDbPath,
|
|
211
214
|
hasCreatedConfig,
|
|
212
215
|
isInsideRoot,
|
|
216
|
+
runGit,
|
|
217
|
+
toKB
|
|
218
|
+
} from "./token-goat-chunk-PM76YS22.mjs";
|
|
219
|
+
import {
|
|
220
|
+
UNTRUSTED_TOOL_TAG,
|
|
221
|
+
displaySafePath,
|
|
222
|
+
displaySafeText,
|
|
223
|
+
fenceUntrustedFileContent,
|
|
213
224
|
neutralizeSpokenMarkers,
|
|
214
225
|
normalizePath,
|
|
215
226
|
resolveIndexPath,
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
toKB
|
|
219
|
-
} from "./token-goat-chunk-AMYCQJX4.mjs";
|
|
227
|
+
toDisplayPath
|
|
228
|
+
} from "./token-goat-chunk-ERTXEKB6.mjs";
|
|
220
229
|
import {
|
|
221
230
|
init_define_import_meta_env
|
|
222
231
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
@@ -936,7 +945,7 @@ init_define_import_meta_env();
|
|
|
936
945
|
var TRACKED_SKILL = "token-goat";
|
|
937
946
|
var MAX_COMMANDS_SHOWN = 8;
|
|
938
947
|
async function currentCommandNames() {
|
|
939
|
-
const { buildProgram } = await import("./token-goat-chunk-
|
|
948
|
+
const { buildProgram } = await import("./token-goat-chunk-NDPO7GAH.mjs");
|
|
940
949
|
return flattenCommandNames(buildCommandManifest(buildProgram()));
|
|
941
950
|
}
|
|
942
951
|
async function recordSkillVersionSnapshot(sessionId, skillName) {
|
|
@@ -7656,11 +7665,11 @@ import { statSync as statSync5 } from "node:fs";
|
|
|
7656
7665
|
// src/bash_extractors.ts
|
|
7657
7666
|
init_define_import_meta_env();
|
|
7658
7667
|
import { statSync as statSync4, openSync as openSync2, readSync, closeSync as closeSync2 } from "node:fs";
|
|
7659
|
-
function surgicalHintFor(hintPath, isEnv, isConfig, isDoc) {
|
|
7660
|
-
return isEnv ? 'Use `token-goat config-get "' + hintPath + '" KEY_NAME` to read a specific variable.' : isConfig ? 'Use `token-goat config-get "' + hintPath + '" KEY_NAME` or `token-goat section "' + hintPath + '::sectionName"` to read a specific value.' : isDoc ? 'Use `token-goat section "' + hintPath + '::SectionHeading"` to read one section.' : 'Use `token-goat read "' + hintPath + '::SymbolName"` to read one function or class.';
|
|
7668
|
+
function surgicalHintFor(hintPath, isEnv, isConfig, isDoc, isXml = false) {
|
|
7669
|
+
return isXml ? 'Use `token-goat xml-outline "' + hintPath + '"` to inspect structure, or `token-goat xml-query "' + hintPath + '" "<selector>"` to query specific nodes.' : isEnv ? 'Use `token-goat config-get "' + hintPath + '" KEY_NAME` to read a specific variable.' : isConfig ? 'Use `token-goat config-get "' + hintPath + '" KEY_NAME` or `token-goat section "' + hintPath + '::sectionName"` to read a specific value.' : isDoc ? 'Use `token-goat section "' + hintPath + '::SectionHeading"` to read one section.' : 'Use `token-goat read "' + hintPath + '::SymbolName"` to read one function or class.';
|
|
7661
7670
|
}
|
|
7662
|
-
function surgicalHintForConfigDoc(filePath, isConfig, isDoc, isSql) {
|
|
7663
|
-
return isConfig ? 'Use `token-goat config-get "' + filePath + '" KEY_NAME` or `token-goat section "' + filePath + '::sectionName"` to read a specific value.' : isSql ? 'Use `token-goat section "' + filePath + '::table_name"` to pull one CREATE TABLE / CREATE TYPE block.' : isDoc ? 'Use `token-goat section "' + filePath + '::SectionHeading"` to read one section.' : 'Use `token-goat read "' + filePath + '::SymbolName"` or `token-goat skeleton "' + filePath + '"` to see the file structure.';
|
|
7671
|
+
function surgicalHintForConfigDoc(filePath, isConfig, isDoc, isSql, isXml = false) {
|
|
7672
|
+
return isXml ? 'Use `token-goat xml-outline "' + filePath + '"` to inspect structure, or `token-goat xml-query "' + filePath + '" "<selector>"` to query specific nodes.' : isConfig ? 'Use `token-goat config-get "' + filePath + '" KEY_NAME` or `token-goat section "' + filePath + '::sectionName"` to read a specific value.' : isSql ? 'Use `token-goat section "' + filePath + '::table_name"` to pull one CREATE TABLE / CREATE TYPE block.' : isDoc ? 'Use `token-goat section "' + filePath + '::SectionHeading"` to read one section.' : 'Use `token-goat read "' + filePath + '::SymbolName"` or `token-goat skeleton "' + filePath + '"` to see the file structure.';
|
|
7664
7673
|
}
|
|
7665
7674
|
function splitShellSegments(cmd) {
|
|
7666
7675
|
const segments = [];
|
|
@@ -7713,19 +7722,21 @@ function extractCatSourceFile(cmd) {
|
|
|
7713
7722
|
function classifyFileExtensions(filePath) {
|
|
7714
7723
|
const basename3 = (filePath.includes("/") ? filePath.split("/").at(-1) : filePath.split("\\").at(-1)) ?? filePath;
|
|
7715
7724
|
const isEnvFile = /^\.env(\.\w+)?$/i.test(basename3);
|
|
7716
|
-
const hasKnownExt = /\.(?:java|py|ts|tsx|js|jsx|go|rb|rs|cpp|cc|cxx|c|h|hpp|kt|swift|cs|php|scala|clj|css|scss|sass|less|md|mdx|rst|txt|json|yaml|yml|toml|xml|conf|cfg|ini|properties|sql|ps1|psm1|env)$/i.test(filePath);
|
|
7725
|
+
const hasKnownExt = /\.(?:java|py|ts|tsx|js|jsx|go|rb|rs|cpp|cc|cxx|c|h|hpp|kt|swift|cs|php|scala|clj|css|scss|sass|less|md|mdx|rst|txt|json|yaml|yml|toml|xml|dtsx|ampkg|xaml|conf|cfg|ini|properties|sql|ps1|psm1|env)$/i.test(filePath);
|
|
7717
7726
|
if (!hasKnownExt && !isEnvFile) return null;
|
|
7718
7727
|
const isSql = /\.sql$/i.test(filePath);
|
|
7719
7728
|
const isDoc = /\.(?:md|mdx|rst|txt)$/i.test(filePath);
|
|
7720
7729
|
const isEnv = isEnvFile || /\.env$/i.test(filePath);
|
|
7721
7730
|
const isConfig = /\.(?:json|yaml|yml|toml|conf|cfg|ini|properties)$/i.test(filePath);
|
|
7722
|
-
|
|
7731
|
+
const isXml = /\.(?:xml|dtsx|ampkg|xaml)$/i.test(filePath);
|
|
7732
|
+
return { isDoc, isEnv, isConfig, isSql, isXml };
|
|
7723
7733
|
}
|
|
7724
7734
|
function classifyDocConfig(filePath) {
|
|
7725
7735
|
const isDoc = /\.(?:md|mdx|rst|txt)$/i.test(filePath);
|
|
7726
7736
|
const isConfig = /\.(?:json|yaml|yml|toml|conf|cfg|ini|properties)$/i.test(filePath);
|
|
7727
7737
|
const isSql = /\.sql$/i.test(filePath);
|
|
7728
|
-
|
|
7738
|
+
const isXml = /\.(?:xml|dtsx|ampkg|xaml)$/i.test(filePath);
|
|
7739
|
+
return { isDoc, isConfig, isSql, isXml };
|
|
7729
7740
|
}
|
|
7730
7741
|
function classifyCatPath(filePath, cmd0) {
|
|
7731
7742
|
if (isTempPath(filePath)) return null;
|
|
@@ -7802,10 +7813,10 @@ function extractPowerShellFileMethodRead(cmd, event) {
|
|
|
7802
7813
|
}
|
|
7803
7814
|
const flags = classifyFileExtensions(filePath);
|
|
7804
7815
|
if (flags === null) {
|
|
7805
|
-
const { isDoc, isConfig, isSql } = classifyDocConfig(filePath);
|
|
7806
|
-
return { filePath, isDoc, isEnv: false, isConfig, isSql };
|
|
7816
|
+
const { isDoc, isConfig, isSql, isXml } = classifyDocConfig(filePath);
|
|
7817
|
+
return { filePath, isDoc, isEnv: false, isConfig, isSql, isXml };
|
|
7807
7818
|
}
|
|
7808
|
-
return { filePath, isDoc: flags.isDoc, isEnv: flags.isEnv, isConfig: flags.isConfig, isSql: flags.isSql };
|
|
7819
|
+
return { filePath, isDoc: flags.isDoc, isEnv: flags.isEnv, isConfig: flags.isConfig, isSql: flags.isSql, isXml: flags.isXml };
|
|
7809
7820
|
}
|
|
7810
7821
|
function extractRgSymbolSearch(cmd) {
|
|
7811
7822
|
if (!/^(?:rg|grep)\s+/.test(cmd)) return null;
|
|
@@ -7960,7 +7971,7 @@ function pythonOpenPathsAreAllLiteral(text) {
|
|
|
7960
7971
|
const calls = pythonOpenCalls(text);
|
|
7961
7972
|
return calls.length > 0 && calls.every((call) => call.pathLiteral !== null);
|
|
7962
7973
|
}
|
|
7963
|
-
var KNOWN_PYTHON_EXT_STR = "java|py|ts|tsx|js|jsx|go|rb|rs|cpp|cc|cxx|c|h|hpp|kt|swift|cs|php|scala|clj|css|scss|sass|less|md|mdx|rst|txt|json|yaml|yml|toml|xml|html|htm|conf|cfg|ini|properties|sql|ps1|psm1|env";
|
|
7974
|
+
var KNOWN_PYTHON_EXT_STR = "java|py|ts|tsx|js|jsx|go|rb|rs|cpp|cc|cxx|c|h|hpp|kt|swift|cs|php|scala|clj|css|scss|sass|less|md|mdx|rst|txt|json|yaml|yml|toml|xml|dtsx|ampkg|xaml|html|htm|conf|cfg|ini|properties|sql|ps1|psm1|env";
|
|
7964
7975
|
var OPEN_EXT = new RegExp(`\\.(?:${KNOWN_PYTHON_EXT_STR})$`, "i");
|
|
7965
7976
|
function extractPythonFileRead(cmd) {
|
|
7966
7977
|
let inner = cmd.trim();
|
|
@@ -7986,11 +7997,11 @@ function extractPythonFileRead(cmd) {
|
|
|
7986
7997
|
const classifyResult = (filePath) => {
|
|
7987
7998
|
const flags = classifyFileExtensions(filePath);
|
|
7988
7999
|
if (flags !== null) {
|
|
7989
|
-
return { filePath, isDoc: flags.isDoc, isConfig: flags.isConfig, isEnv: flags.isEnv, isSql: flags.isSql, isOutputFile: false };
|
|
8000
|
+
return { filePath, isDoc: flags.isDoc, isConfig: flags.isConfig, isEnv: flags.isEnv, isSql: flags.isSql, isXml: flags.isXml, isOutputFile: false };
|
|
7990
8001
|
}
|
|
7991
|
-
const { isDoc, isConfig, isSql } = classifyDocConfig(filePath);
|
|
8002
|
+
const { isDoc, isConfig, isSql, isXml } = classifyDocConfig(filePath);
|
|
7992
8003
|
const isEnv = /\.env(\.\w+)?$/i.test(filePath);
|
|
7993
|
-
return { filePath, isDoc, isConfig, isEnv, isSql, isOutputFile: false };
|
|
8004
|
+
return { filePath, isDoc, isConfig, isEnv, isSql, isXml, isOutputFile: false };
|
|
7994
8005
|
};
|
|
7995
8006
|
const heredocMatch = /^python3?\s+-\s+<<\s*'?(\w+)'?\s*\n([\s\S]*?)\n\1\s*$/.exec(pythonBody);
|
|
7996
8007
|
if (heredocMatch) {
|
|
@@ -8044,9 +8055,9 @@ function extractHeadFile(cmd) {
|
|
|
8044
8055
|
const filePath = direct !== null ? direct[3] ?? direct[4] ?? direct[5] : piped[1] ?? piped[2] ?? piped[3];
|
|
8045
8056
|
if (filePath === void 0) return null;
|
|
8046
8057
|
if (isTempPath(filePath)) return null;
|
|
8047
|
-
if (!/\.(?:ts|tsx|js|jsx|py|go|java|rs|rb|cs|md|mdx|rst|txt|json|yaml|yml|toml|sql|sh)$/i.test(filePath)) return null;
|
|
8048
|
-
const { isDoc, isConfig, isSql } = classifyDocConfig(filePath);
|
|
8049
|
-
return { filePath, isDoc, isConfig, isSql, n };
|
|
8058
|
+
if (!/\.(?:ts|tsx|js|jsx|py|go|java|rs|rb|cs|md|mdx|rst|txt|json|yaml|yml|toml|sql|sh|xml|dtsx|ampkg|xaml)$/i.test(filePath)) return null;
|
|
8059
|
+
const { isDoc, isConfig, isSql, isXml } = classifyDocConfig(filePath);
|
|
8060
|
+
return { filePath, isDoc, isConfig, isSql, isXml, n };
|
|
8050
8061
|
}
|
|
8051
8062
|
function extractSedRange(cmd) {
|
|
8052
8063
|
const m = /^sed\s+-n\s+(?:['"]((?:\d+,\d+p)(?:;\d+,\d+p)*)['"]|(\d+,\d+p))\s+(?:"([^"]+)"|'([^']+)'|(\S+))(?:\s+2>(?:\/dev\/null|&1))?\s*$/.exec(cmd);
|
|
@@ -8148,7 +8159,7 @@ function leadingLinesHint(lead, hintPath, start, end, flags, preHookCwd) {
|
|
|
8148
8159
|
const key = resolveIndexPath(hintPath, preHookCwd ?? process.cwd());
|
|
8149
8160
|
const prior = findRangeOverlap(getFileLineRanges(key), start, end);
|
|
8150
8161
|
if (prior !== null) return sedOverlapHint(hintPath, prior, start, end);
|
|
8151
|
-
return lead + surgicalHintForConfigDoc(hintPath, flags.isConfig, flags.isDoc, flags.isSql);
|
|
8162
|
+
return lead + surgicalHintForConfigDoc(hintPath, flags.isConfig, flags.isDoc, flags.isSql, flags.isXml ?? false);
|
|
8152
8163
|
}
|
|
8153
8164
|
function findRangeOverlap(prior, start, end) {
|
|
8154
8165
|
let best = null;
|
|
@@ -8205,9 +8216,9 @@ function extractTailFile(cmd) {
|
|
|
8205
8216
|
const filePath = direct !== null ? direct[3] ?? direct[4] ?? direct[5] : piped[1] ?? piped[2] ?? piped[3];
|
|
8206
8217
|
if (!filePath) return null;
|
|
8207
8218
|
if (isTempPath(filePath)) return null;
|
|
8208
|
-
if (!/\.(?:ts|tsx|js|jsx|py|go|java|rs|rb|cs|md|mdx|rst|txt|json|yaml|yml|toml|sql|sh)$/i.test(filePath)) return null;
|
|
8209
|
-
const { isDoc, isConfig, isSql } = classifyDocConfig(filePath);
|
|
8210
|
-
return { filePath, isDoc, isConfig, isSql };
|
|
8219
|
+
if (!/\.(?:ts|tsx|js|jsx|py|go|java|rs|rb|cs|md|mdx|rst|txt|json|yaml|yml|toml|sql|sh|xml|dtsx|ampkg|xaml)$/i.test(filePath)) return null;
|
|
8220
|
+
const { isDoc, isConfig, isSql, isXml } = classifyDocConfig(filePath);
|
|
8221
|
+
return { filePath, isDoc, isConfig, isSql, isXml };
|
|
8211
8222
|
}
|
|
8212
8223
|
function extractGetContentTail(cmd) {
|
|
8213
8224
|
const tailMatch = /-Tail\s+(\d+)/i.exec(cmd);
|
|
@@ -8222,9 +8233,9 @@ function extractGetContentTail(cmd) {
|
|
|
8222
8233
|
const filePath = (beforeTail || afterTail).replace(/^["']|["']$/g, "");
|
|
8223
8234
|
if (!filePath) return null;
|
|
8224
8235
|
if (isTempPath(filePath)) return null;
|
|
8225
|
-
if (!/\.(?:ts|tsx|js|jsx|py|go|java|rs|rb|cs|md|mdx|rst|txt|json|yaml|yml|toml|sql|sh|ps1|psm1)$/i.test(filePath)) return null;
|
|
8226
|
-
const { isDoc, isConfig, isSql } = classifyDocConfig(filePath);
|
|
8227
|
-
return { filePath, isDoc, isConfig, isSql };
|
|
8236
|
+
if (!/\.(?:ts|tsx|js|jsx|py|go|java|rs|rb|cs|md|mdx|rst|txt|json|yaml|yml|toml|sql|sh|ps1|psm1|xml|dtsx|ampkg|xaml)$/i.test(filePath)) return null;
|
|
8237
|
+
const { isDoc, isConfig, isSql, isXml } = classifyDocConfig(filePath);
|
|
8238
|
+
return { filePath, isDoc, isConfig, isSql, isXml };
|
|
8228
8239
|
}
|
|
8229
8240
|
function extractGetContentSelectFirst(cmd) {
|
|
8230
8241
|
const m = /^(Get-Content|gc)\s+([^|]+)\s*\|\s*(Select-Object|select)\s+(-First\s+(\d+))/i.exec(cmd);
|
|
@@ -8234,9 +8245,9 @@ function extractGetContentSelectFirst(cmd) {
|
|
|
8234
8245
|
if (n <= 10) return null;
|
|
8235
8246
|
if (!filePath) return null;
|
|
8236
8247
|
if (isTempPath(filePath)) return null;
|
|
8237
|
-
if (!/\.(?:ts|tsx|js|jsx|py|go|java|rs|rb|cs|md|mdx|rst|txt|json|yaml|yml|toml|sql|sh|ps1|psm1)$/i.test(filePath)) return null;
|
|
8238
|
-
const { isDoc, isConfig, isSql } = classifyDocConfig(filePath);
|
|
8239
|
-
return { filePath, isDoc, isConfig, isSql, n };
|
|
8248
|
+
if (!/\.(?:ts|tsx|js|jsx|py|go|java|rs|rb|cs|md|mdx|rst|txt|json|yaml|yml|toml|sql|sh|ps1|psm1|xml|dtsx|ampkg|xaml)$/i.test(filePath)) return null;
|
|
8249
|
+
const { isDoc, isConfig, isSql, isXml } = classifyDocConfig(filePath);
|
|
8250
|
+
return { filePath, isDoc, isConfig, isSql, isXml, n };
|
|
8240
8251
|
}
|
|
8241
8252
|
function taskOutputIsJsonlTranscript(outPath) {
|
|
8242
8253
|
let fd = null;
|
|
@@ -8611,6 +8622,42 @@ function isCompressibleSingleCommand(cmd) {
|
|
|
8611
8622
|
if (hasBareBackgroundOrNewline(cmd)) return false;
|
|
8612
8623
|
return true;
|
|
8613
8624
|
}
|
|
8625
|
+
function extractTerminalXmlParsing(cmd) {
|
|
8626
|
+
const trimmed = cmd.trim();
|
|
8627
|
+
if (!trimmed) return null;
|
|
8628
|
+
const selectXmlM = /\bSelect-Xml\b(?:\s+(?:-Path\s+)?["']?([^"'\s|;]+(?:\.xml|\.dtsx|\.ampkg|\.xaml))["']?)?/i.exec(trimmed);
|
|
8629
|
+
if (selectXmlM) {
|
|
8630
|
+
const rawPath = selectXmlM[1];
|
|
8631
|
+
const filePath = rawPath && !rawPath.startsWith("-") ? rawPath : void 0;
|
|
8632
|
+
return { filePath, toolOrScript: "Select-Xml" };
|
|
8633
|
+
}
|
|
8634
|
+
const psXmlCastM = /\[(?:xml|System\.Xml\.XmlDocument)\]/i.exec(trimmed);
|
|
8635
|
+
if (psXmlCastM) {
|
|
8636
|
+
const fileM = /["']([^"'\r\n]+\.(?:xml|dtsx|ampkg|xaml))["']/i.exec(trimmed) || /(?:Get-Content|gc|ReadAllText)\s+["']?([^"'\s|;)]+\.(?:xml|dtsx|ampkg|xaml))["']?/i.exec(trimmed);
|
|
8637
|
+
const filePath = fileM?.[1];
|
|
8638
|
+
return { filePath, toolOrScript: psXmlCastM[0] };
|
|
8639
|
+
}
|
|
8640
|
+
const inspectScriptM = /(?:powershell|pwsh|&|\.)?\s*["']?(\.?[/\\]?inspect_[^"'\s|;]+\.ps1)["']/i.exec(trimmed) || /\b(inspect_[^"'\s|;]+\.ps1)\b/i.exec(trimmed);
|
|
8641
|
+
if (inspectScriptM) {
|
|
8642
|
+
const fileM = /["']([^"'\r\n]+\.(?:xml|dtsx|ampkg|xaml))["']/i.exec(trimmed);
|
|
8643
|
+
const filePath = fileM?.[1];
|
|
8644
|
+
return { filePath, toolOrScript: inspectScriptM[1] ?? "inspect script" };
|
|
8645
|
+
}
|
|
8646
|
+
const pyXmlM = /\bpython(?:\d+(?:\.\d+)?)?(?:\.exe)?\b.*-c\s+["'].*?\b(xml\.etree|BeautifulSoup|minidom|lxml)\b/i.exec(trimmed);
|
|
8647
|
+
if (pyXmlM) {
|
|
8648
|
+
const fileM = /["']([^"'\r\n]+\.(?:xml|dtsx|ampkg|xaml))["']/i.exec(trimmed);
|
|
8649
|
+
const filePath = fileM?.[1];
|
|
8650
|
+
return { filePath, toolOrScript: `python ${pyXmlM[1]}` };
|
|
8651
|
+
}
|
|
8652
|
+
const cliXmlM = /\b(xmllint|xmlstarlet|xidel)\b/i.exec(trimmed);
|
|
8653
|
+
if (cliXmlM) {
|
|
8654
|
+
const fileM = /["']?([^"'\s|;]+\.(?:xml|dtsx|ampkg|xaml))["']?/i.exec(trimmed);
|
|
8655
|
+
const rawPath = fileM?.[1];
|
|
8656
|
+
const filePath = rawPath && !rawPath.startsWith("-") ? rawPath : void 0;
|
|
8657
|
+
return { filePath, toolOrScript: cliXmlM[1] };
|
|
8658
|
+
}
|
|
8659
|
+
return null;
|
|
8660
|
+
}
|
|
8614
8661
|
|
|
8615
8662
|
// src/hooks_bash_commands.ts
|
|
8616
8663
|
var CD_PREFIX_RE = /^(?:cd\s+(?:"[^"]*"|'[^']*'|\S+)[ \t]*(?:&&|;|\r?\n)\s*)+/;
|
|
@@ -9281,9 +9328,9 @@ async function maybeElideServedGenericOutput(cmd, output, exitCode, cwd, cacheMi
|
|
|
9281
9328
|
if (rewrittenText === null) return null;
|
|
9282
9329
|
return emitRewrite(rewrittenText, "already-served shell output collapsed", { kind: "bash_compress:generic-served-elision", originalBytes: deliveredOutputBytes(originalBytes) });
|
|
9283
9330
|
}
|
|
9284
|
-
async function maybeCompressCompoundOutput(cmd, output, exitCode, cwd, cacheMinBytes) {
|
|
9331
|
+
async function maybeCompressCompoundOutput(cmd, output, exitCode, cwd, cacheMinBytes, isUnwrapped = false) {
|
|
9285
9332
|
if (process.env["TOKEN_GOAT_BASH_COMPRESS"] === "0") return null;
|
|
9286
|
-
if (isCompressibleSingleCommand(cmd)) return null;
|
|
9333
|
+
if (!isUnwrapped && isCompressibleSingleCommand(cmd)) return null;
|
|
9287
9334
|
if (exitCode !== null && exitCode !== 0) return null;
|
|
9288
9335
|
let cfg;
|
|
9289
9336
|
try {
|
|
@@ -9293,7 +9340,7 @@ async function maybeCompressCompoundOutput(cmd, output, exitCode, cwd, cacheMinB
|
|
|
9293
9340
|
}
|
|
9294
9341
|
if (!cfg.enabled || cfg.disabled_filters.includes("generic")) return null;
|
|
9295
9342
|
if (Buffer.byteLength(output, "utf-8") < cacheMinBytes) return null;
|
|
9296
|
-
const shaped = pipelineShapeFilter(cmd, cwd);
|
|
9343
|
+
const shaped = pipelineShapeFilter(cmd, cwd) ?? (isUnwrapped ? detectFromCommand(cmd, cwd ?? void 0)?.filter ?? null : null);
|
|
9297
9344
|
const filter3 = shaped !== null && !cfg.disabled_filters.includes(shaped.name) ? shaped : filterByName("generic");
|
|
9298
9345
|
if (filter3 === null) return null;
|
|
9299
9346
|
const compressed = compressOutput(filter3, output, "", exitCode ?? 0, [], {
|
|
@@ -9436,6 +9483,15 @@ function preBashHandlerInner(event) {
|
|
|
9436
9483
|
"Use `token-goat outline <file>` to see symbol names and line counts without loading files."
|
|
9437
9484
|
);
|
|
9438
9485
|
}
|
|
9486
|
+
const terminalXml = extractTerminalXmlParsing(cmd);
|
|
9487
|
+
if (terminalXml !== null) {
|
|
9488
|
+
const { filePath, toolOrScript } = terminalXml;
|
|
9489
|
+
recordStat("session_hint", 0, 0);
|
|
9490
|
+
const target = filePath ? displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath) : "<file>";
|
|
9491
|
+
return contextOutput(
|
|
9492
|
+
`token-goat available for this file type, consider 'token-goat xml-query "${target}" "<xpath>"' or 'token-goat xml-outline "${target}"' first instead of terminal XML parsing (${toolOrScript}).`
|
|
9493
|
+
);
|
|
9494
|
+
}
|
|
9439
9495
|
const singleLineRangeRead = extractLineRangeRead(cmd);
|
|
9440
9496
|
const sedReads = singleLineRangeRead !== null ? [singleLineRangeRead] : extractLineRangeReadsCompound(cmd);
|
|
9441
9497
|
if (sedReads !== null) {
|
|
@@ -9462,17 +9518,17 @@ function preBashHandlerInner(event) {
|
|
|
9462
9518
|
}
|
|
9463
9519
|
const gcTailResult = extractGetContentTail(cmd);
|
|
9464
9520
|
if (gcTailResult !== null) {
|
|
9465
|
-
const { filePath, isDoc, isConfig, isSql } = gcTailResult;
|
|
9521
|
+
const { filePath, isDoc, isConfig, isSql, isXml } = gcTailResult;
|
|
9466
9522
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9467
9523
|
recordStat("session_hint", 0, 0);
|
|
9468
|
-
return contextOutput("`Get-Content -Tail` bypasses read hooks. " + surgicalHintForConfigDoc(hintPath, isConfig, isDoc, isSql));
|
|
9524
|
+
return contextOutput("`Get-Content -Tail` bypasses read hooks. " + surgicalHintForConfigDoc(hintPath, isConfig, isDoc, isSql, isXml));
|
|
9469
9525
|
}
|
|
9470
9526
|
const gcSelectResult = extractGetContentSelectFirst(cmd);
|
|
9471
9527
|
if (gcSelectResult !== null) {
|
|
9472
|
-
const { filePath, isDoc, isConfig, isSql, n } = gcSelectResult;
|
|
9528
|
+
const { filePath, isDoc, isConfig, isSql, isXml, n } = gcSelectResult;
|
|
9473
9529
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9474
9530
|
recordStat("session_hint", 0, 0);
|
|
9475
|
-
return contextOutput(leadingLinesHint("`Select-Object -First` bypasses read hooks. ", hintPath, 1, n, { isConfig, isDoc, isSql }, preHookCwd));
|
|
9531
|
+
return contextOutput(leadingLinesHint("`Select-Object -First` bypasses read hooks. ", hintPath, 1, n, { isConfig, isDoc, isSql, isXml }, preHookCwd));
|
|
9476
9532
|
}
|
|
9477
9533
|
const catJsonPipe = extractCatJsonPipe(cmd);
|
|
9478
9534
|
if (catJsonPipe !== null) {
|
|
@@ -9485,7 +9541,7 @@ function preBashHandlerInner(event) {
|
|
|
9485
9541
|
}
|
|
9486
9542
|
const catResult = extractCatFile(cmd);
|
|
9487
9543
|
if (catResult !== null) {
|
|
9488
|
-
const { filePath, isDoc, isEnv, isConfig, isSql, cmd0, advisoryOnly } = catResult;
|
|
9544
|
+
const { filePath, isDoc, isEnv, isConfig, isSql, isXml, cmd0, advisoryOnly } = catResult;
|
|
9489
9545
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9490
9546
|
recordStat("session_hint", 0, 0);
|
|
9491
9547
|
if (isSql) {
|
|
@@ -9493,16 +9549,16 @@ function preBashHandlerInner(event) {
|
|
|
9493
9549
|
"`" + cmd0 + '` loads the entire file into context. Use `token-goat section "' + hintPath + '::table_name"` to pull one CREATE TABLE / CREATE TYPE block.'
|
|
9494
9550
|
);
|
|
9495
9551
|
}
|
|
9496
|
-
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc);
|
|
9552
|
+
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc, isXml);
|
|
9497
9553
|
return cdStripped || advisoryOnly ? contextOutput("`" + cmd0 + "` loads the entire file into context. " + hint) : denyOutput("`" + cmd0 + "` loads the entire file into context. " + hint);
|
|
9498
9554
|
}
|
|
9499
9555
|
const catMulti = extractCatFilesMulti(cmd);
|
|
9500
9556
|
if (catMulti !== null) {
|
|
9501
9557
|
recordStat("session_hint", 0, 0);
|
|
9502
9558
|
const cmd0 = catMulti[0].cmd0;
|
|
9503
|
-
const perPath = catMulti.map(({ filePath, isDoc, isEnv, isConfig, isSql }) => {
|
|
9559
|
+
const perPath = catMulti.map(({ filePath, isDoc, isEnv, isConfig, isSql, isXml }) => {
|
|
9504
9560
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9505
|
-
const how = isSql ? 'token-goat section "' + hintPath + '::table_name"' : isEnv || isConfig ? 'token-goat config-get "' + hintPath + '" KEY_NAME' : isDoc ? 'token-goat section "' + hintPath + '::SectionHeading"' : 'token-goat read "' + hintPath + '::SymbolName"';
|
|
9561
|
+
const how = isXml ? 'token-goat xml-outline "' + hintPath + '" or token-goat xml-query "' + hintPath + '" "<selector>"' : isSql ? 'token-goat section "' + hintPath + '::table_name"' : isEnv || isConfig ? 'token-goat config-get "' + hintPath + '" KEY_NAME' : isDoc ? 'token-goat section "' + hintPath + '::SectionHeading"' : 'token-goat read "' + hintPath + '::SymbolName"';
|
|
9506
9562
|
return " " + hintPath + " -> `" + how + "`";
|
|
9507
9563
|
});
|
|
9508
9564
|
const msg = "`" + cmd0 + "` on multiple files loads them all into context. Read each surgically instead:\n" + perPath.join("\n");
|
|
@@ -9510,19 +9566,19 @@ function preBashHandlerInner(event) {
|
|
|
9510
9566
|
}
|
|
9511
9567
|
const psGetContentResult = extractPowerShellWrappedGetContent(cmd, event);
|
|
9512
9568
|
if (psGetContentResult !== null) {
|
|
9513
|
-
const { filePath, isDoc, isEnv, isConfig, isSql } = psGetContentResult;
|
|
9569
|
+
const { filePath, isDoc, isEnv, isConfig, isSql, isXml } = psGetContentResult;
|
|
9514
9570
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9515
9571
|
recordStat("session_hint", 0, 0);
|
|
9516
9572
|
const lead = "`Get-Content` via a `powershell -Command` wrapper bypasses read hooks and loads the entire file into context. ";
|
|
9517
9573
|
if (isSql) {
|
|
9518
9574
|
return contextOutput(lead + 'Use `token-goat section "' + hintPath + '::table_name"` to pull one CREATE TABLE / CREATE TYPE block.');
|
|
9519
9575
|
}
|
|
9520
|
-
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc);
|
|
9576
|
+
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc, isXml);
|
|
9521
9577
|
return cdStripped ? contextOutput(lead + hint) : denyOutput(lead + hint);
|
|
9522
9578
|
}
|
|
9523
9579
|
const wslCatResult = extractWslCatFile(cmd);
|
|
9524
9580
|
if (wslCatResult !== null) {
|
|
9525
|
-
const { filePath, isDoc, isEnv, isConfig, isSql } = wslCatResult;
|
|
9581
|
+
const { filePath, isDoc, isEnv, isConfig, isSql, isXml } = wslCatResult;
|
|
9526
9582
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9527
9583
|
recordStat("session_hint", 0, 0);
|
|
9528
9584
|
if (isSql) {
|
|
@@ -9530,12 +9586,12 @@ function preBashHandlerInner(event) {
|
|
|
9530
9586
|
'`cat` loads the entire file into context. Use `token-goat section "' + hintPath + '::table_name"` to pull one CREATE TABLE / CREATE TYPE block.'
|
|
9531
9587
|
);
|
|
9532
9588
|
}
|
|
9533
|
-
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc);
|
|
9589
|
+
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc, isXml);
|
|
9534
9590
|
return cdStripped ? contextOutput("`cat` loads the entire file into context. " + hint) : denyOutput("`cat` loads the entire file into context. " + hint);
|
|
9535
9591
|
}
|
|
9536
9592
|
const pyRead = extractPythonFileRead(cmd);
|
|
9537
9593
|
if (pyRead !== null) {
|
|
9538
|
-
const { filePath, isDoc, isConfig, isEnv, isSql, isOutputFile } = pyRead;
|
|
9594
|
+
const { filePath, isDoc, isConfig, isEnv, isSql, isXml, isOutputFile } = pyRead;
|
|
9539
9595
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9540
9596
|
recordStat("session_hint", 0, 0);
|
|
9541
9597
|
if (isOutputFile) {
|
|
@@ -9552,22 +9608,22 @@ function preBashHandlerInner(event) {
|
|
|
9552
9608
|
'Python `open()` file reads bypass read hooks. Use `token-goat section "' + hintPath + '::table_name"` to pull one CREATE TABLE / CREATE TYPE block.'
|
|
9553
9609
|
);
|
|
9554
9610
|
}
|
|
9555
|
-
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc);
|
|
9611
|
+
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc, isXml);
|
|
9556
9612
|
return cdStripped ? contextOutput("Python `open()` file reads bypass read hooks. " + hint) : denyOutput("Python `open()` file reads bypass read hooks. " + hint);
|
|
9557
9613
|
}
|
|
9558
9614
|
const tailResult = extractTailFile(cmd);
|
|
9559
9615
|
if (tailResult !== null) {
|
|
9560
|
-
const { filePath, isDoc, isConfig, isSql } = tailResult;
|
|
9616
|
+
const { filePath, isDoc, isConfig, isSql, isXml } = tailResult;
|
|
9561
9617
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9562
9618
|
recordStat("session_hint", 0, 0);
|
|
9563
|
-
return contextOutput("`tail` bypasses read hooks. " + surgicalHintForConfigDoc(hintPath, isConfig, isDoc, isSql));
|
|
9619
|
+
return contextOutput("`tail` bypasses read hooks. " + surgicalHintForConfigDoc(hintPath, isConfig, isDoc, isSql, isXml));
|
|
9564
9620
|
}
|
|
9565
9621
|
const headResult = extractHeadFile(cmd);
|
|
9566
9622
|
if (headResult !== null) {
|
|
9567
|
-
const { filePath, isDoc, isConfig, isSql, n } = headResult;
|
|
9623
|
+
const { filePath, isDoc, isConfig, isSql, isXml, n } = headResult;
|
|
9568
9624
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9569
9625
|
recordStat("session_hint", 0, 0);
|
|
9570
|
-
return contextOutput(leadingLinesHint("`head` bypasses read hooks. ", hintPath, 1, n, { isConfig, isDoc, isSql }, preHookCwd));
|
|
9626
|
+
return contextOutput(leadingLinesHint("`head` bypasses read hooks. ", hintPath, 1, n, { isConfig, isDoc, isSql, isXml }, preHookCwd));
|
|
9571
9627
|
}
|
|
9572
9628
|
const nodeRead = extractNodeFileRead(cmd);
|
|
9573
9629
|
if (nodeRead !== null) {
|
|
@@ -9584,14 +9640,14 @@ function preBashHandlerInner(event) {
|
|
|
9584
9640
|
}
|
|
9585
9641
|
const psMethodRead = extractPowerShellFileMethodRead(cmd, event);
|
|
9586
9642
|
if (psMethodRead !== null) {
|
|
9587
|
-
const { filePath, isDoc, isEnv, isConfig, isSql } = psMethodRead;
|
|
9643
|
+
const { filePath, isDoc, isEnv, isConfig, isSql, isXml } = psMethodRead;
|
|
9588
9644
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9589
9645
|
const lead = "PowerShell `[IO.File]::ReadAllText()` bypasses read hooks. ";
|
|
9590
9646
|
if (isSql) {
|
|
9591
9647
|
recordStat("session_hint", 0, 0);
|
|
9592
9648
|
return contextOutput(lead + 'Use `token-goat section "' + hintPath + '::table_name"` to pull one CREATE TABLE / CREATE TYPE block.');
|
|
9593
9649
|
}
|
|
9594
|
-
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc);
|
|
9650
|
+
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc, isXml);
|
|
9595
9651
|
recordStat("session_hint", 0, 0);
|
|
9596
9652
|
return cdStripped ? contextOutput(lead + hint) : denyOutput(lead + hint);
|
|
9597
9653
|
}
|
|
@@ -9763,15 +9819,25 @@ function extractExitCode(raw) {
|
|
|
9763
9819
|
return null;
|
|
9764
9820
|
}
|
|
9765
9821
|
var GH_SECURITY_PATHS = ["/security_advisories", "/advisories", "security_events"];
|
|
9766
|
-
var GH_SCOPE_PHRASES = [
|
|
9822
|
+
var GH_SCOPE_PHRASES = [
|
|
9823
|
+
"Must have push access",
|
|
9824
|
+
"Resource not accessible by integration",
|
|
9825
|
+
"Must be an admin",
|
|
9826
|
+
"You are not authorized to perform this operation"
|
|
9827
|
+
];
|
|
9828
|
+
var GH_NOT_FOUND = /^gh: .*\(HTTP 404\)|"status":\s*"404"/m;
|
|
9767
9829
|
function buildGhApiHint(cmd, stdout, exitCode) {
|
|
9768
9830
|
if (stdout === "" || !cmd.startsWith("gh api")) return null;
|
|
9769
9831
|
const hints = [];
|
|
9770
9832
|
const isSecurityPath = GH_SECURITY_PATHS.some((p) => cmd.includes(p));
|
|
9771
9833
|
const hasScopePhrase = GH_SCOPE_PHRASES.some((p) => stdout.includes(p));
|
|
9772
|
-
const
|
|
9773
|
-
if (hasScopePhrase
|
|
9834
|
+
const ambiguousSecurity404 = exitCode !== null && exitCode !== 0 && isSecurityPath && GH_NOT_FOUND.test(stdout);
|
|
9835
|
+
if (hasScopePhrase) {
|
|
9774
9836
|
hints.push("[token-goat] GitHub API scope issue: try gh auth refresh -s security_events");
|
|
9837
|
+
} else if (ambiguousSecurity404) {
|
|
9838
|
+
hints.push(
|
|
9839
|
+
"[token-goat] GitHub answers 404 both for a resource that does not exist and for one your token cannot see: check the owner/repo spelling, then gh auth status for the security_events scope."
|
|
9840
|
+
);
|
|
9775
9841
|
}
|
|
9776
9842
|
const trimmed = stdout.trimStart();
|
|
9777
9843
|
if (trimmed.startsWith("{")) {
|
|
@@ -9845,6 +9911,7 @@ async function postBashHandler(event) {
|
|
|
9845
9911
|
try {
|
|
9846
9912
|
const rawCmdRaw = extractCommand(event);
|
|
9847
9913
|
if (rawCmdRaw === void 0) return passOutput();
|
|
9914
|
+
const isUnwrapped = unwrapCompressCommand(rawCmdRaw) === null;
|
|
9848
9915
|
const rawCmd = unwrapCompressCommand(rawCmdRaw) ?? rawCmdRaw;
|
|
9849
9916
|
const cmd = stripCdPrefix(rawCmd);
|
|
9850
9917
|
const output = extractBashOutput(event.raw);
|
|
@@ -9928,13 +9995,19 @@ async function postBashHandler(event) {
|
|
|
9928
9995
|
const gitScopedCacheId = await storeBashOutput(cmd, output, exitCode ?? 0, cwd);
|
|
9929
9996
|
recordBashOutput(gitScopedCacheHash, gitScopedCacheId, Buffer.byteLength(output, "utf-8"));
|
|
9930
9997
|
}
|
|
9998
|
+
if (isUnwrapped && /^git(?:\s+-[^\s]+|\s+--[^\s]+)*\s+diff\b/i.test(cmd)) {
|
|
9999
|
+
const unwrappedCompressed = await maybeCompressCompoundOutput(cmd, output, exitCode, cwd, cacheMinBytes, isUnwrapped);
|
|
10000
|
+
if (unwrappedCompressed !== null) return unwrappedCompressed;
|
|
10001
|
+
}
|
|
9931
10002
|
const isMonitoring = getMonitoringRecallHint(cmd) !== null;
|
|
9932
10003
|
const isFileRead = pureFileReadPath(cmd) !== null;
|
|
9933
10004
|
if (isFileRead || !isMonitoring && !isBuildCommand(cmd) && !isCurlGetCommand(cmd)) {
|
|
9934
10005
|
const identical = await maybeCollapseIdenticalRead(cmd, rawCmd, output, exitCode, cwd, cacheMinBytes);
|
|
9935
10006
|
if (identical !== null) return identical;
|
|
9936
|
-
|
|
9937
|
-
|
|
10007
|
+
if (!isFileRead && (!isUnwrapped || !isCompressibleSingleCommand(cmd))) {
|
|
10008
|
+
const compound = await maybeCompressCompoundOutput(cmd, output, exitCode, cwd, cacheMinBytes, isUnwrapped);
|
|
10009
|
+
if (compound !== null) return compound;
|
|
10010
|
+
}
|
|
9938
10011
|
if (!isFileRead && extractLineRangeReadsCompound(cmd) === null) {
|
|
9939
10012
|
const genericElision = await maybeElideServedGenericOutput(cmd, output, exitCode, cwd, cacheMinBytes);
|
|
9940
10013
|
if (genericElision !== null) return genericElision;
|
|
@@ -10275,6 +10348,7 @@ function postToolUseFailureHandler(event) {
|
|
|
10275
10348
|
const ledger = readLedger(target);
|
|
10276
10349
|
const priorState = ledger.seen[signature];
|
|
10277
10350
|
const editDiagnostic = diagnoseEditFailure(event, errorText);
|
|
10351
|
+
const sqlDiagnostic = diagnoseSqlFailure(event, errorText);
|
|
10278
10352
|
if (priorState === void 0) {
|
|
10279
10353
|
ledger.seen[signature] = false;
|
|
10280
10354
|
ledger.order.push(signature);
|
|
@@ -10288,6 +10362,11 @@ function postToolUseFailureHandler(event) {
|
|
|
10288
10362
|
writeLedger(target, ledger);
|
|
10289
10363
|
return contextOutput(editDiagnostic);
|
|
10290
10364
|
}
|
|
10365
|
+
if (sqlDiagnostic !== null) {
|
|
10366
|
+
ledger.seen[signature] = true;
|
|
10367
|
+
writeLedger(target, ledger);
|
|
10368
|
+
return contextOutput(sqlDiagnostic);
|
|
10369
|
+
}
|
|
10291
10370
|
return passOutput();
|
|
10292
10371
|
}
|
|
10293
10372
|
if (priorState) return passOutput();
|
|
@@ -10296,6 +10375,9 @@ function postToolUseFailureHandler(event) {
|
|
|
10296
10375
|
if (editDiagnostic !== null) {
|
|
10297
10376
|
return contextOutput(editDiagnostic);
|
|
10298
10377
|
}
|
|
10378
|
+
if (sqlDiagnostic !== null) {
|
|
10379
|
+
return contextOutput(sqlDiagnostic);
|
|
10380
|
+
}
|
|
10299
10381
|
return contextOutput(repeatFailureNotice(toolName));
|
|
10300
10382
|
} catch {
|
|
10301
10383
|
return passOutput();
|
|
@@ -10572,6 +10654,37 @@ function compressGithubMcpResult(toolName, resultText) {
|
|
|
10572
10654
|
const stripped = deepStrip(parsed, githubShouldStrip);
|
|
10573
10655
|
return finishWithGenericPass(resultText, stripped);
|
|
10574
10656
|
}
|
|
10657
|
+
var ATLASSIAN_TOOL_RE = /(?:jira|confluence|atlassian)/i;
|
|
10658
|
+
var ATLASSIAN_STRIP_EXACT_KEYS = /* @__PURE__ */ new Set([
|
|
10659
|
+
"avatarUrls",
|
|
10660
|
+
"avatarUrl",
|
|
10661
|
+
"iconUrl",
|
|
10662
|
+
"iconUrls",
|
|
10663
|
+
"self",
|
|
10664
|
+
"expand",
|
|
10665
|
+
"schema",
|
|
10666
|
+
"operations",
|
|
10667
|
+
"editmeta",
|
|
10668
|
+
"names",
|
|
10669
|
+
"_links",
|
|
10670
|
+
"_expandable",
|
|
10671
|
+
"extensions",
|
|
10672
|
+
"timeZone"
|
|
10673
|
+
]);
|
|
10674
|
+
function atlassianShouldStrip(key) {
|
|
10675
|
+
return ATLASSIAN_STRIP_EXACT_KEYS.has(key);
|
|
10676
|
+
}
|
|
10677
|
+
function compressAtlassianMcpResult(toolName, resultText) {
|
|
10678
|
+
if (!ATLASSIAN_TOOL_RE.test(toolName)) return null;
|
|
10679
|
+
let parsed;
|
|
10680
|
+
try {
|
|
10681
|
+
parsed = JSON.parse(resultText);
|
|
10682
|
+
} catch {
|
|
10683
|
+
return null;
|
|
10684
|
+
}
|
|
10685
|
+
const stripped = deepStrip(parsed, atlassianShouldStrip);
|
|
10686
|
+
return finishWithGenericPass(resultText, stripped);
|
|
10687
|
+
}
|
|
10575
10688
|
var BROWSER_TOOL_RE = /^mcp__.*(?:chrome-devtools|claude-in-chrome|playwright).*__/i;
|
|
10576
10689
|
var BROWSER_CONSOLE_METHOD_RE = /(?:^|_)(?:read|list)_console_messages$/i;
|
|
10577
10690
|
var BROWSER_NETWORK_METHOD_RE = /(?:^|_)(?:read|list)_network_requests$/i;
|
|
@@ -10722,10 +10835,11 @@ function stripBase64DataUrls(resultText) {
|
|
|
10722
10835
|
function compressMcpResultWithPacks(toolName, resultText) {
|
|
10723
10836
|
const base64Stripped = stripBase64DataUrls(resultText);
|
|
10724
10837
|
const text = base64Stripped ?? resultText;
|
|
10725
|
-
return compressGithubMcpResult(toolName, text) ?? compressBrowserMcpResult(toolName, text) ?? compressGWorkspaceMcpResult(toolName, text) ?? base64Stripped;
|
|
10838
|
+
return compressGithubMcpResult(toolName, text) ?? compressAtlassianMcpResult(toolName, text) ?? compressBrowserMcpResult(toolName, text) ?? compressGWorkspaceMcpResult(toolName, text) ?? base64Stripped;
|
|
10726
10839
|
}
|
|
10727
10840
|
|
|
10728
10841
|
// src/hooks_mcp.ts
|
|
10842
|
+
var MCP_OVERSIZED_THRESHOLD_BYTES = 25e3;
|
|
10729
10843
|
function preMcpHandler(event) {
|
|
10730
10844
|
const toolName = getToolName(event);
|
|
10731
10845
|
if (!toolName || !event.sessionId) return passOutput();
|
|
@@ -10783,9 +10897,15 @@ function postMcpHandler(event) {
|
|
|
10783
10897
|
minNetSavingsBytes: resolveMinNetSavingsBytes()
|
|
10784
10898
|
});
|
|
10785
10899
|
if (worthwhile) {
|
|
10900
|
+
const bodyBytes = Buffer.byteLength(redactedBody, "utf-8");
|
|
10901
|
+
let finalBody = redactedBody;
|
|
10902
|
+
if (bodyBytes >= MCP_OVERSIZED_THRESHOLD_BYTES) {
|
|
10903
|
+
const preview = clipToDeliveryCap(redactedBody, Buffer.byteLength(notice, "utf-8") + 500);
|
|
10904
|
+
finalBody = preview.text + (preview.clipped ? "\n\n...[preview truncated by token-goat; use mcp-output above to query full payload]..." : "");
|
|
10905
|
+
}
|
|
10786
10906
|
return preserve(
|
|
10787
10907
|
emitRewrite(
|
|
10788
|
-
`${notice}${fenceWithMatches(
|
|
10908
|
+
`${notice}${fenceWithMatches(finalBody, injectionMatches, UNTRUSTED_TOOL_TAG)}`,
|
|
10789
10909
|
"mcp",
|
|
10790
10910
|
{ kind: "mcp:compress", originalBytes }
|
|
10791
10911
|
)
|
|
@@ -10794,6 +10914,29 @@ function postMcpHandler(event) {
|
|
|
10794
10914
|
}
|
|
10795
10915
|
}
|
|
10796
10916
|
}
|
|
10917
|
+
const rawBytes = Buffer.byteLength(resultText, "utf-8");
|
|
10918
|
+
if (rawBytes >= MCP_OVERSIZED_THRESHOLD_BYTES && process.env["TOKEN_GOAT_MCP_COMPRESS"] !== "0") {
|
|
10919
|
+
if (id === null) id = storeMcpOutput(event.sessionId, toolName, toolInput, resultText);
|
|
10920
|
+
if (id !== null) {
|
|
10921
|
+
const notice = `[token-goat: oversized MCP result (${rawBytes} bytes) cached as ${id}]
|
|
10922
|
+
The full payload was cached to prevent harness context spill. Slicing commands:
|
|
10923
|
+
token-goat mcp-output ${id} --json-query '<path>' (e.g. 'issues[*].key', 'values[*].id')
|
|
10924
|
+
token-goat mcp-output ${id} --section '<heading>'
|
|
10925
|
+
token-goat mcp-output ${id} --grep '<regex>' --max-matches 20
|
|
10926
|
+
token-goat mcp-output ${id} --head 50
|
|
10927
|
+
|
|
10928
|
+
`;
|
|
10929
|
+
const preview = clipToDeliveryCap(redactedResult.text, Buffer.byteLength(notice, "utf-8") + 500);
|
|
10930
|
+
const previewBody = preview.text + (preview.clipped ? "\n\n...[preview truncated by token-goat; use mcp-output above to query full payload]..." : "");
|
|
10931
|
+
return preserve(
|
|
10932
|
+
emitRewrite(
|
|
10933
|
+
`${notice}${fenceWithMatches(previewBody, injectionMatches, UNTRUSTED_TOOL_TAG)}`,
|
|
10934
|
+
"mcp",
|
|
10935
|
+
{ kind: "mcp:oversized", originalBytes: rawBytes }
|
|
10936
|
+
)
|
|
10937
|
+
);
|
|
10938
|
+
}
|
|
10939
|
+
}
|
|
10797
10940
|
return passOrFence();
|
|
10798
10941
|
}
|
|
10799
10942
|
registerHook("pre_tool_use", preMcpHandler, { toolPattern: "^mcp__" });
|