token-goat 2.9.14 → 2.9.16
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-2ESBO4IN.mjs → token-goat-chunk-2IEIBVVD.mjs} +16 -9
- package/dist/{token-goat-chunk-RUDOKYPJ.mjs → token-goat-chunk-2PCFAQAS.mjs} +6582 -6194
- package/dist/{token-goat-chunk-AMYCQJX4.mjs → token-goat-chunk-3H6FQT62.mjs} +49 -256
- package/dist/{token-goat-chunk-PRJVGIC5.mjs → token-goat-chunk-4DC6DDIB.mjs} +7 -5
- package/dist/token-goat-chunk-4EXFN2AW.mjs +29 -0
- package/dist/{token-goat-chunk-VZYD4OZB.mjs → token-goat-chunk-5USHO7B6.mjs} +416 -4168
- package/dist/token-goat-chunk-63QWJ6UM.mjs +277 -0
- package/dist/token-goat-chunk-BFNTLGVA.mjs +4547 -0
- package/dist/token-goat-chunk-BGHSSJUA.mjs +102 -0
- package/dist/{token-goat-chunk-T2IWWTHB.mjs → token-goat-chunk-DMQ32ZSR.mjs} +35 -1142
- package/dist/{token-goat-chunk-DBNY4RLN.mjs → token-goat-chunk-EJCY6KHO.mjs} +5 -3
- package/dist/token-goat-chunk-ERTXEKB6.mjs +228 -0
- package/dist/{token-goat-chunk-Z6UXPYJA.mjs → token-goat-chunk-F2ARFHLJ.mjs} +1 -1
- package/dist/{token-goat-chunk-EG3663UT.mjs → token-goat-chunk-GIMGT34T.mjs} +4 -2
- package/dist/{token-goat-chunk-XVZ4MNQC.mjs → token-goat-chunk-GMXBQS6O.mjs} +360 -116
- package/dist/{token-goat-chunk-SAQ5PG4L.mjs → token-goat-chunk-H3DXI6VD.mjs} +8 -4
- package/dist/token-goat-chunk-LJL6FGDS.mjs +35 -0
- package/dist/{token-goat-chunk-NEI4NC54.mjs → token-goat-chunk-LKSXAMJB.mjs} +7 -2
- package/dist/token-goat-chunk-LMFO66YD.mjs +331 -0
- package/dist/{token-goat-chunk-7OGKZ7AP.mjs → token-goat-chunk-M2R4UQ3B.mjs} +5 -3
- package/dist/{token-goat-chunk-YHGTGG6K.mjs → token-goat-chunk-MA5BZ2KI.mjs} +68 -7
- package/dist/{token-goat-chunk-ASVVF4JV.mjs → token-goat-chunk-MIL62GMN.mjs} +171 -23
- package/dist/{token-goat-chunk-ZFM4PWXL.mjs → token-goat-chunk-NAMH252H.mjs} +10 -7
- package/dist/{token-goat-chunk-YTQHZJXW.mjs → token-goat-chunk-NOBZV7PM.mjs} +96 -22
- package/dist/{token-goat-chunk-4SDX3QP3.mjs → token-goat-chunk-NQZCSVN2.mjs} +13 -5
- package/dist/{token-goat-chunk-XEH6KBWW.mjs → token-goat-chunk-OCI25AXY.mjs} +4 -3
- package/dist/token-goat-chunk-OSUFN2FV.mjs +326 -0
- package/dist/{token-goat-chunk-O5WAMISC.mjs → token-goat-chunk-QMZMHQRR.mjs} +29 -18
- package/dist/{token-goat-chunk-POBYR64E.mjs → token-goat-chunk-R3X5TCPB.mjs} +801 -3
- package/dist/token-goat-chunk-RRNZMM3A.mjs +3364 -0
- package/dist/{token-goat-chunk-PGGDW7DZ.mjs → token-goat-chunk-ULA4WCED.mjs} +9 -6
- package/dist/token-goat-chunk-UMXD2M7O.mjs +975 -0
- package/dist/{token-goat-chunk-3XQPEJMV.mjs → token-goat-chunk-UXHDBVUR.mjs} +1 -1
- package/dist/{token-goat-chunk-EZNVAIR3.mjs → token-goat-chunk-VVIYEFBI.mjs} +4 -3
- package/dist/token-goat-chunk-XOHTFRDH.mjs +10760 -0
- package/dist/{token-goat-chunk-HF6H7RNK.mjs → token-goat-chunk-YPS64ACE.mjs} +13 -3
- package/dist/{token-goat-chunk-DAMXYVIW.mjs → token-goat-chunk-Z5VPAXTC.mjs} +2560 -820
- package/dist/{token-goat-chunk-XQF5J25J.mjs → token-goat-chunk-ZEHFYJ7Z.mjs} +5 -4
- package/dist/token-goat-hook.mjs +15 -10
- package/dist/token-goat.core.mjs +24 -18
- package/docs/cli.md +8 -6
- package/package.json +1 -1
- package/dist/token-goat-chunk-IT6O3PNN.mjs +0 -15463
- package/dist/token-goat-chunk-ZD4EM4LR.mjs +0 -30
- package/dist/token-goat-chunk-ZYNNQ36L.mjs +0 -479
|
@@ -4,23 +4,26 @@ import {
|
|
|
4
4
|
canRunWrappedShell,
|
|
5
5
|
clipToDeliveryCap,
|
|
6
6
|
deliveredOutputBytes
|
|
7
|
-
} from "./token-goat-chunk-
|
|
7
|
+
} from "./token-goat-chunk-UXHDBVUR.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-UMXD2M7O.mjs";
|
|
20
21
|
import {
|
|
22
|
+
BODY_FIRST_TOOL_RESPONSE_KEYS,
|
|
21
23
|
GENERIC_SERVED_OUTPUT_KEY,
|
|
22
24
|
OUTLINE_MAX_REPLACEMENT_RATIO,
|
|
23
25
|
OUTLINE_MIN_HEADINGS,
|
|
26
|
+
OUTPUT_FIRST_TOOL_RESPONSE_KEYS,
|
|
24
27
|
WEB_FETCH_KEY_SEP,
|
|
25
28
|
accumulateResidentLines,
|
|
26
29
|
appendDirtyPath,
|
|
@@ -32,23 +35,30 @@ import {
|
|
|
32
35
|
clearCurlDownload,
|
|
33
36
|
compactPathFor,
|
|
34
37
|
computeAdaptiveBudget,
|
|
38
|
+
contextOutput,
|
|
39
|
+
denyOutput,
|
|
40
|
+
emitRewrite,
|
|
41
|
+
emitRewriteIfChanged,
|
|
35
42
|
enqueueDirtyPathSafe,
|
|
36
43
|
ensureWorkerAlive,
|
|
44
|
+
estimateTokens,
|
|
37
45
|
extractCompactFromMarker,
|
|
38
|
-
|
|
46
|
+
extractToolResponseField,
|
|
47
|
+
extractToolResultText,
|
|
39
48
|
fenceUntrusted,
|
|
40
49
|
fenceUntrustedSpans,
|
|
41
50
|
fenceWithMatches,
|
|
42
51
|
foldDelivery,
|
|
43
52
|
foldDetail,
|
|
44
53
|
foldingEnabled,
|
|
45
|
-
formatHeadingTreeParts,
|
|
46
54
|
formatProjectMap,
|
|
47
55
|
formatShrinkSummary,
|
|
48
56
|
getBashOutputId,
|
|
49
57
|
getContextPressure,
|
|
50
58
|
getCurlDownloadPath,
|
|
59
|
+
getCwd,
|
|
51
60
|
getFileLineRanges,
|
|
61
|
+
getFilePath,
|
|
52
62
|
getFileServedOutputs,
|
|
53
63
|
getGlobMatchCount,
|
|
54
64
|
getGrepMatchCount,
|
|
@@ -57,31 +67,41 @@ import {
|
|
|
57
67
|
getSessionBashReruns,
|
|
58
68
|
getSessionFiles,
|
|
59
69
|
getSessionWebFetches,
|
|
70
|
+
getToolInput,
|
|
71
|
+
getToolName,
|
|
72
|
+
getTranscriptPath,
|
|
60
73
|
hasSeenImage,
|
|
61
74
|
hasSessionOutput,
|
|
62
75
|
imageQualifiesForShrink,
|
|
63
76
|
incrementSkillHit,
|
|
64
77
|
indexServedBody,
|
|
65
78
|
installedSkillPath,
|
|
79
|
+
isMcpErrorResponse,
|
|
66
80
|
isStructuralRewriteAccepted,
|
|
81
|
+
isTextualContentBlock,
|
|
67
82
|
lastTabContextMatches,
|
|
68
83
|
lineMayCarryResidentSignal,
|
|
69
84
|
listSiblingSessionStates,
|
|
70
85
|
loadSessionCache,
|
|
71
86
|
loadSessionState,
|
|
87
|
+
makeDedupHintHandlers,
|
|
72
88
|
markCompactStale,
|
|
73
89
|
markCompacted,
|
|
74
90
|
markFileTruncated,
|
|
75
91
|
markHintShown,
|
|
76
92
|
matchesAllowPattern,
|
|
77
93
|
matchesDenyPattern,
|
|
94
|
+
mcpContentBlocks,
|
|
78
95
|
meetsSavingsFloor,
|
|
79
96
|
metadataEndpointRefusal,
|
|
97
|
+
normalizePayload,
|
|
98
|
+
passOutput,
|
|
80
99
|
planMarkdownOutline,
|
|
81
100
|
planServedElisions,
|
|
82
101
|
planSourceSkeleton,
|
|
83
102
|
preToolPathDeclined,
|
|
84
103
|
probeImageMeta,
|
|
104
|
+
readCopilotHooksOwners,
|
|
85
105
|
readTranscriptTail,
|
|
86
106
|
recordBashOutput,
|
|
87
107
|
recordBashRerun,
|
|
@@ -99,13 +119,17 @@ import {
|
|
|
99
119
|
recordSeenImage,
|
|
100
120
|
recordSymbolRead,
|
|
101
121
|
recordWebFetch,
|
|
122
|
+
registerHook,
|
|
102
123
|
removeOutstandingAgentSpawn,
|
|
103
124
|
repeatedSkillBodyHint,
|
|
125
|
+
runHook,
|
|
104
126
|
saveSessionState,
|
|
105
127
|
scanAndRecord,
|
|
128
|
+
serializeOutput,
|
|
106
129
|
servedRunNotice,
|
|
107
130
|
sessionOutputBodyBytes,
|
|
108
131
|
sessionSidecarPath,
|
|
132
|
+
sessionStateKey,
|
|
109
133
|
setLastTabContext,
|
|
110
134
|
setTranscriptPath,
|
|
111
135
|
shrinkImage,
|
|
@@ -118,68 +142,51 @@ import {
|
|
|
118
142
|
vscodePathAllowed,
|
|
119
143
|
wasCliReadThisSession,
|
|
120
144
|
wasFileReadThisSession,
|
|
121
|
-
wasHintShown
|
|
122
|
-
|
|
145
|
+
wasHintShown,
|
|
146
|
+
withPreservedBlocks
|
|
147
|
+
} from "./token-goat-chunk-XOHTFRDH.mjs";
|
|
123
148
|
import {
|
|
124
149
|
BASH_OUTPUT_SUBDIR,
|
|
125
|
-
BODY_FIRST_TOOL_RESPONSE_KEYS,
|
|
126
|
-
OUTPUT_FIRST_TOOL_RESPONSE_KEYS,
|
|
127
150
|
commandHash,
|
|
128
151
|
compressOutput,
|
|
129
|
-
contextOutput,
|
|
130
|
-
countSymbols,
|
|
131
152
|
dedupeConsecutive,
|
|
132
|
-
denyOutput,
|
|
133
153
|
detectFromCommand,
|
|
134
|
-
emitRewrite,
|
|
135
|
-
emitRewriteIfChanged,
|
|
136
|
-
estimateTokens,
|
|
137
|
-
extractToolResponseField,
|
|
138
|
-
extractToolResultText,
|
|
139
154
|
filterByName,
|
|
140
155
|
getBashOutput,
|
|
141
|
-
getCwd,
|
|
142
|
-
getFilePath,
|
|
143
156
|
getMonitoringRecallHint,
|
|
144
|
-
getToolInput,
|
|
145
|
-
getToolName,
|
|
146
|
-
getTranscriptPath,
|
|
147
157
|
hasBareBackgroundOrNewline,
|
|
148
158
|
hasUnquotedOperator,
|
|
149
159
|
indexRecallEntry,
|
|
150
160
|
isBashEntryStale,
|
|
151
161
|
isBuildCommand,
|
|
152
|
-
isMcpErrorResponse,
|
|
153
162
|
isRewriteWorthwhile,
|
|
154
163
|
isScopedGitStatusOrDiffStatCommand,
|
|
155
164
|
isTestRunnerCommand,
|
|
156
|
-
isTextualContentBlock,
|
|
157
|
-
makeDedupHintHandlers,
|
|
158
|
-
mcpContentBlocks,
|
|
159
|
-
normalizePayload,
|
|
160
|
-
passOutput,
|
|
161
|
-
readCopilotHooksOwners,
|
|
162
|
-
registerHook,
|
|
163
165
|
resolveMinNetSavingsBytes,
|
|
164
|
-
runHook,
|
|
165
|
-
serializeOutput,
|
|
166
|
-
sessionStateKey,
|
|
167
166
|
shlexSplit,
|
|
168
167
|
splitOwnTrailingNotices,
|
|
169
168
|
storeBashOutput,
|
|
170
|
-
summarizeOutputDelta
|
|
171
|
-
|
|
172
|
-
} from "./token-goat-chunk-VZYD4OZB.mjs";
|
|
169
|
+
summarizeOutputDelta
|
|
170
|
+
} from "./token-goat-chunk-5USHO7B6.mjs";
|
|
173
171
|
import {
|
|
174
|
-
detectLanguage,
|
|
175
|
-
getDb,
|
|
176
|
-
languageHasFlag,
|
|
177
172
|
recordStat,
|
|
178
173
|
redactSecrets,
|
|
179
174
|
savedTokensFromBytes,
|
|
180
175
|
storeBlob,
|
|
181
176
|
stripAnsiEscapes
|
|
182
|
-
} from "./token-goat-chunk-
|
|
177
|
+
} from "./token-goat-chunk-DMQ32ZSR.mjs";
|
|
178
|
+
import {
|
|
179
|
+
extractMarkdownHeadings,
|
|
180
|
+
formatHeadingTreeParts
|
|
181
|
+
} from "./token-goat-chunk-BFNTLGVA.mjs";
|
|
182
|
+
import {
|
|
183
|
+
countSymbols
|
|
184
|
+
} from "./token-goat-chunk-63QWJ6UM.mjs";
|
|
185
|
+
import {
|
|
186
|
+
detectLanguage,
|
|
187
|
+
getDb,
|
|
188
|
+
languageHasFlag
|
|
189
|
+
} from "./token-goat-chunk-R3X5TCPB.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-H3DXI6VD.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-3H6FQT62.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-QMZMHQRR.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;
|
|
@@ -7824,12 +7835,77 @@ function extractRgSymbolSearch(cmd) {
|
|
|
7824
7835
|
}
|
|
7825
7836
|
function extractCatJsonPipe(cmd) {
|
|
7826
7837
|
const m = /^cat\s+(?:"([^"]+)"|'([^']+)'|(\S+))\s*\|\s*jq\b/.exec(cmd);
|
|
7827
|
-
if (
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7838
|
+
if (m) {
|
|
7839
|
+
const filePath = m[1] ?? m[2] ?? m[3];
|
|
7840
|
+
if (filePath && !isTempPath(filePath) && /\.(?:json|yaml|yml|toml)$/i.test(filePath)) {
|
|
7841
|
+
return { filePath, isDirectJq: false };
|
|
7842
|
+
}
|
|
7843
|
+
}
|
|
7844
|
+
const jqDirect = /^jq(?:\s+(?:-[a-zA-Z]+|--[a-zA-Z0-9-]+(?:=\S+)?))*\s+(?:"[^"]*"|'[^']*'|(?:\.[a-zA-Z0-9_.*[\]]+))\s+(?:"([^"]+)"|'([^']+)'|(\S+))\s*$/.exec(cmd);
|
|
7845
|
+
if (jqDirect) {
|
|
7846
|
+
const filePath = jqDirect[1] ?? jqDirect[2] ?? jqDirect[3];
|
|
7847
|
+
if (filePath && !isTempPath(filePath) && /\.(?:json|yaml|yml|toml)$/i.test(filePath)) {
|
|
7848
|
+
return { filePath, isDirectJq: true };
|
|
7849
|
+
}
|
|
7850
|
+
}
|
|
7851
|
+
return null;
|
|
7852
|
+
}
|
|
7853
|
+
function extractPowerShellJsonPipeline(cmd) {
|
|
7854
|
+
let inner = cmd.trim();
|
|
7855
|
+
const w = POWERSHELL_WRAP_RE.exec(inner);
|
|
7856
|
+
if (w) {
|
|
7857
|
+
inner = (w[1] ?? w[2] ?? "").trim();
|
|
7858
|
+
}
|
|
7859
|
+
if (!/\bConvertFrom-Json\b/i.test(inner)) return null;
|
|
7860
|
+
const parseTarget = (segment) => {
|
|
7861
|
+
const readAll = /\[(?:System\.)?IO\.File\]::ReadAllText\(\s*['"]?([^'")\s]+)['"]?\s*\)/i.exec(segment);
|
|
7862
|
+
if (readAll) {
|
|
7863
|
+
const p = readAll[1];
|
|
7864
|
+
return p && /\.(?:json|txt|log|temp)$/i.test(p) ? p : null;
|
|
7865
|
+
}
|
|
7866
|
+
const tokens = segment.trim().split(/\s+/);
|
|
7867
|
+
const cmdlets = /* @__PURE__ */ new Set(["get-content", "gc", "cat", "type"]);
|
|
7868
|
+
const idx = tokens.findIndex((t) => cmdlets.has(t.toLowerCase()));
|
|
7869
|
+
if (idx === -1) return null;
|
|
7870
|
+
let argIdx = idx + 1;
|
|
7871
|
+
while (argIdx < tokens.length) {
|
|
7872
|
+
const tok = tokens[argIdx];
|
|
7873
|
+
if (!tok) break;
|
|
7874
|
+
if (tok.startsWith("-")) {
|
|
7875
|
+
const flag = tok.toLowerCase();
|
|
7876
|
+
if (flag === "-path" && argIdx + 1 < tokens.length) {
|
|
7877
|
+
const next = tokens[argIdx + 1];
|
|
7878
|
+
if (next && !next.startsWith("-")) {
|
|
7879
|
+
const clean2 = next.replace(/^['"]|['"]$/g, "");
|
|
7880
|
+
return /\.(?:json|txt|log|temp)$/i.test(clean2) ? clean2 : null;
|
|
7881
|
+
}
|
|
7882
|
+
}
|
|
7883
|
+
if ((flag === "-encoding" || flag === "-totalcount") && argIdx + 1 < tokens.length) {
|
|
7884
|
+
argIdx += 2;
|
|
7885
|
+
continue;
|
|
7886
|
+
}
|
|
7887
|
+
argIdx++;
|
|
7888
|
+
continue;
|
|
7889
|
+
}
|
|
7890
|
+
const clean = tok.replace(/^['"(]|['")]$/g, "");
|
|
7891
|
+
return /\.(?:json|txt|log|temp)$/i.test(clean) ? clean : null;
|
|
7892
|
+
}
|
|
7893
|
+
return null;
|
|
7894
|
+
};
|
|
7895
|
+
const pipeIdx = inner.search(/\|\s*ConvertFrom-Json\b/i);
|
|
7896
|
+
if (pipeIdx !== -1) {
|
|
7897
|
+
const upstream = inner.slice(0, pipeIdx).trim();
|
|
7898
|
+
return { filePath: parseTarget(upstream) };
|
|
7899
|
+
}
|
|
7900
|
+
const parenMatch = /ConvertFrom-Json\s*\(([^)]+)\)/i.exec(inner);
|
|
7901
|
+
if (parenMatch) {
|
|
7902
|
+
const inside = parenMatch[1] ?? "";
|
|
7903
|
+
return { filePath: parseTarget(inside) };
|
|
7904
|
+
}
|
|
7905
|
+
if (/ConvertFrom-Json\s*\(/i.test(inner)) {
|
|
7906
|
+
return { filePath: null };
|
|
7907
|
+
}
|
|
7908
|
+
return null;
|
|
7833
7909
|
}
|
|
7834
7910
|
function extractWslCatFile(cmd) {
|
|
7835
7911
|
const wslMatch = /^wsl(?:\s+-d\s+\S+)?\s+bash\s+-c\s+"cat(?:\s+(?:-[a-zA-Z]+|--[a-zA-Z-]+))*\s+\/mnt\/([a-z])\/([^"]*)"/.exec(cmd);
|
|
@@ -7960,7 +8036,7 @@ function pythonOpenPathsAreAllLiteral(text) {
|
|
|
7960
8036
|
const calls = pythonOpenCalls(text);
|
|
7961
8037
|
return calls.length > 0 && calls.every((call) => call.pathLiteral !== null);
|
|
7962
8038
|
}
|
|
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";
|
|
8039
|
+
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
8040
|
var OPEN_EXT = new RegExp(`\\.(?:${KNOWN_PYTHON_EXT_STR})$`, "i");
|
|
7965
8041
|
function extractPythonFileRead(cmd) {
|
|
7966
8042
|
let inner = cmd.trim();
|
|
@@ -7986,11 +8062,11 @@ function extractPythonFileRead(cmd) {
|
|
|
7986
8062
|
const classifyResult = (filePath) => {
|
|
7987
8063
|
const flags = classifyFileExtensions(filePath);
|
|
7988
8064
|
if (flags !== null) {
|
|
7989
|
-
return { filePath, isDoc: flags.isDoc, isConfig: flags.isConfig, isEnv: flags.isEnv, isSql: flags.isSql, isOutputFile: false };
|
|
8065
|
+
return { filePath, isDoc: flags.isDoc, isConfig: flags.isConfig, isEnv: flags.isEnv, isSql: flags.isSql, isXml: flags.isXml, isOutputFile: false };
|
|
7990
8066
|
}
|
|
7991
|
-
const { isDoc, isConfig, isSql } = classifyDocConfig(filePath);
|
|
8067
|
+
const { isDoc, isConfig, isSql, isXml } = classifyDocConfig(filePath);
|
|
7992
8068
|
const isEnv = /\.env(\.\w+)?$/i.test(filePath);
|
|
7993
|
-
return { filePath, isDoc, isConfig, isEnv, isSql, isOutputFile: false };
|
|
8069
|
+
return { filePath, isDoc, isConfig, isEnv, isSql, isXml, isOutputFile: false };
|
|
7994
8070
|
};
|
|
7995
8071
|
const heredocMatch = /^python3?\s+-\s+<<\s*'?(\w+)'?\s*\n([\s\S]*?)\n\1\s*$/.exec(pythonBody);
|
|
7996
8072
|
if (heredocMatch) {
|
|
@@ -8044,9 +8120,9 @@ function extractHeadFile(cmd) {
|
|
|
8044
8120
|
const filePath = direct !== null ? direct[3] ?? direct[4] ?? direct[5] : piped[1] ?? piped[2] ?? piped[3];
|
|
8045
8121
|
if (filePath === void 0) return null;
|
|
8046
8122
|
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 };
|
|
8123
|
+
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;
|
|
8124
|
+
const { isDoc, isConfig, isSql, isXml } = classifyDocConfig(filePath);
|
|
8125
|
+
return { filePath, isDoc, isConfig, isSql, isXml, n };
|
|
8050
8126
|
}
|
|
8051
8127
|
function extractSedRange(cmd) {
|
|
8052
8128
|
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 +8224,7 @@ function leadingLinesHint(lead, hintPath, start, end, flags, preHookCwd) {
|
|
|
8148
8224
|
const key = resolveIndexPath(hintPath, preHookCwd ?? process.cwd());
|
|
8149
8225
|
const prior = findRangeOverlap(getFileLineRanges(key), start, end);
|
|
8150
8226
|
if (prior !== null) return sedOverlapHint(hintPath, prior, start, end);
|
|
8151
|
-
return lead + surgicalHintForConfigDoc(hintPath, flags.isConfig, flags.isDoc, flags.isSql);
|
|
8227
|
+
return lead + surgicalHintForConfigDoc(hintPath, flags.isConfig, flags.isDoc, flags.isSql, flags.isXml ?? false);
|
|
8152
8228
|
}
|
|
8153
8229
|
function findRangeOverlap(prior, start, end) {
|
|
8154
8230
|
let best = null;
|
|
@@ -8205,9 +8281,9 @@ function extractTailFile(cmd) {
|
|
|
8205
8281
|
const filePath = direct !== null ? direct[3] ?? direct[4] ?? direct[5] : piped[1] ?? piped[2] ?? piped[3];
|
|
8206
8282
|
if (!filePath) return null;
|
|
8207
8283
|
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 };
|
|
8284
|
+
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;
|
|
8285
|
+
const { isDoc, isConfig, isSql, isXml } = classifyDocConfig(filePath);
|
|
8286
|
+
return { filePath, isDoc, isConfig, isSql, isXml };
|
|
8211
8287
|
}
|
|
8212
8288
|
function extractGetContentTail(cmd) {
|
|
8213
8289
|
const tailMatch = /-Tail\s+(\d+)/i.exec(cmd);
|
|
@@ -8222,9 +8298,9 @@ function extractGetContentTail(cmd) {
|
|
|
8222
8298
|
const filePath = (beforeTail || afterTail).replace(/^["']|["']$/g, "");
|
|
8223
8299
|
if (!filePath) return null;
|
|
8224
8300
|
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 };
|
|
8301
|
+
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;
|
|
8302
|
+
const { isDoc, isConfig, isSql, isXml } = classifyDocConfig(filePath);
|
|
8303
|
+
return { filePath, isDoc, isConfig, isSql, isXml };
|
|
8228
8304
|
}
|
|
8229
8305
|
function extractGetContentSelectFirst(cmd) {
|
|
8230
8306
|
const m = /^(Get-Content|gc)\s+([^|]+)\s*\|\s*(Select-Object|select)\s+(-First\s+(\d+))/i.exec(cmd);
|
|
@@ -8234,9 +8310,9 @@ function extractGetContentSelectFirst(cmd) {
|
|
|
8234
8310
|
if (n <= 10) return null;
|
|
8235
8311
|
if (!filePath) return null;
|
|
8236
8312
|
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 };
|
|
8313
|
+
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;
|
|
8314
|
+
const { isDoc, isConfig, isSql, isXml } = classifyDocConfig(filePath);
|
|
8315
|
+
return { filePath, isDoc, isConfig, isSql, isXml, n };
|
|
8240
8316
|
}
|
|
8241
8317
|
function taskOutputIsJsonlTranscript(outPath) {
|
|
8242
8318
|
let fd = null;
|
|
@@ -8611,6 +8687,42 @@ function isCompressibleSingleCommand(cmd) {
|
|
|
8611
8687
|
if (hasBareBackgroundOrNewline(cmd)) return false;
|
|
8612
8688
|
return true;
|
|
8613
8689
|
}
|
|
8690
|
+
function extractTerminalXmlParsing(cmd) {
|
|
8691
|
+
const trimmed = cmd.trim();
|
|
8692
|
+
if (!trimmed) return null;
|
|
8693
|
+
const selectXmlM = /\bSelect-Xml\b(?:\s+(?:-Path\s+)?["']?([^"'\s|;]+(?:\.xml|\.dtsx|\.ampkg|\.xaml))["']?)?/i.exec(trimmed);
|
|
8694
|
+
if (selectXmlM) {
|
|
8695
|
+
const rawPath = selectXmlM[1];
|
|
8696
|
+
const filePath = rawPath && !rawPath.startsWith("-") ? rawPath : void 0;
|
|
8697
|
+
return { filePath, toolOrScript: "Select-Xml" };
|
|
8698
|
+
}
|
|
8699
|
+
const psXmlCastM = /\[(?:xml|System\.Xml\.XmlDocument)\]/i.exec(trimmed);
|
|
8700
|
+
if (psXmlCastM) {
|
|
8701
|
+
const fileM = /["']([^"'\r\n]+\.(?:xml|dtsx|ampkg|xaml))["']/i.exec(trimmed) || /(?:Get-Content|gc|ReadAllText)\s+["']?([^"'\s|;)]+\.(?:xml|dtsx|ampkg|xaml))["']?/i.exec(trimmed);
|
|
8702
|
+
const filePath = fileM?.[1];
|
|
8703
|
+
return { filePath, toolOrScript: psXmlCastM[0] };
|
|
8704
|
+
}
|
|
8705
|
+
const inspectScriptM = /(?:powershell|pwsh|&|\.)?\s*["']?(\.?[/\\]?inspect_[^"'\s|;]+\.ps1)["']/i.exec(trimmed) || /\b(inspect_[^"'\s|;]+\.ps1)\b/i.exec(trimmed);
|
|
8706
|
+
if (inspectScriptM) {
|
|
8707
|
+
const fileM = /["']([^"'\r\n]+\.(?:xml|dtsx|ampkg|xaml))["']/i.exec(trimmed);
|
|
8708
|
+
const filePath = fileM?.[1];
|
|
8709
|
+
return { filePath, toolOrScript: inspectScriptM[1] ?? "inspect script" };
|
|
8710
|
+
}
|
|
8711
|
+
const pyXmlM = /\bpython(?:\d+(?:\.\d+)?)?(?:\.exe)?\b.*-c\s+["'].*?\b(xml\.etree|BeautifulSoup|minidom|lxml)\b/i.exec(trimmed);
|
|
8712
|
+
if (pyXmlM) {
|
|
8713
|
+
const fileM = /["']([^"'\r\n]+\.(?:xml|dtsx|ampkg|xaml))["']/i.exec(trimmed);
|
|
8714
|
+
const filePath = fileM?.[1];
|
|
8715
|
+
return { filePath, toolOrScript: `python ${pyXmlM[1]}` };
|
|
8716
|
+
}
|
|
8717
|
+
const cliXmlM = /\b(xmllint|xmlstarlet|xidel)\b/i.exec(trimmed);
|
|
8718
|
+
if (cliXmlM) {
|
|
8719
|
+
const fileM = /["']?([^"'\s|;]+\.(?:xml|dtsx|ampkg|xaml))["']?/i.exec(trimmed);
|
|
8720
|
+
const rawPath = fileM?.[1];
|
|
8721
|
+
const filePath = rawPath && !rawPath.startsWith("-") ? rawPath : void 0;
|
|
8722
|
+
return { filePath, toolOrScript: cliXmlM[1] };
|
|
8723
|
+
}
|
|
8724
|
+
return null;
|
|
8725
|
+
}
|
|
8614
8726
|
|
|
8615
8727
|
// src/hooks_bash_commands.ts
|
|
8616
8728
|
var CD_PREFIX_RE = /^(?:cd\s+(?:"[^"]*"|'[^']*'|\S+)[ \t]*(?:&&|;|\r?\n)\s*)+/;
|
|
@@ -9281,9 +9393,9 @@ async function maybeElideServedGenericOutput(cmd, output, exitCode, cwd, cacheMi
|
|
|
9281
9393
|
if (rewrittenText === null) return null;
|
|
9282
9394
|
return emitRewrite(rewrittenText, "already-served shell output collapsed", { kind: "bash_compress:generic-served-elision", originalBytes: deliveredOutputBytes(originalBytes) });
|
|
9283
9395
|
}
|
|
9284
|
-
async function maybeCompressCompoundOutput(cmd, output, exitCode, cwd, cacheMinBytes) {
|
|
9396
|
+
async function maybeCompressCompoundOutput(cmd, output, exitCode, cwd, cacheMinBytes, isUnwrapped = false) {
|
|
9285
9397
|
if (process.env["TOKEN_GOAT_BASH_COMPRESS"] === "0") return null;
|
|
9286
|
-
if (isCompressibleSingleCommand(cmd)) return null;
|
|
9398
|
+
if (!isUnwrapped && isCompressibleSingleCommand(cmd)) return null;
|
|
9287
9399
|
if (exitCode !== null && exitCode !== 0) return null;
|
|
9288
9400
|
let cfg;
|
|
9289
9401
|
try {
|
|
@@ -9293,7 +9405,7 @@ async function maybeCompressCompoundOutput(cmd, output, exitCode, cwd, cacheMinB
|
|
|
9293
9405
|
}
|
|
9294
9406
|
if (!cfg.enabled || cfg.disabled_filters.includes("generic")) return null;
|
|
9295
9407
|
if (Buffer.byteLength(output, "utf-8") < cacheMinBytes) return null;
|
|
9296
|
-
const shaped = pipelineShapeFilter(cmd, cwd);
|
|
9408
|
+
const shaped = pipelineShapeFilter(cmd, cwd) ?? (isUnwrapped ? detectFromCommand(cmd, cwd ?? void 0)?.filter ?? null : null);
|
|
9297
9409
|
const filter3 = shaped !== null && !cfg.disabled_filters.includes(shaped.name) ? shaped : filterByName("generic");
|
|
9298
9410
|
if (filter3 === null) return null;
|
|
9299
9411
|
const compressed = compressOutput(filter3, output, "", exitCode ?? 0, [], {
|
|
@@ -9436,6 +9548,15 @@ function preBashHandlerInner(event) {
|
|
|
9436
9548
|
"Use `token-goat outline <file>` to see symbol names and line counts without loading files."
|
|
9437
9549
|
);
|
|
9438
9550
|
}
|
|
9551
|
+
const terminalXml = extractTerminalXmlParsing(cmd);
|
|
9552
|
+
if (terminalXml !== null) {
|
|
9553
|
+
const { filePath, toolOrScript } = terminalXml;
|
|
9554
|
+
recordStat("session_hint", 0, 0);
|
|
9555
|
+
const target = filePath ? displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath) : "<file>";
|
|
9556
|
+
return contextOutput(
|
|
9557
|
+
`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}).`
|
|
9558
|
+
);
|
|
9559
|
+
}
|
|
9439
9560
|
const singleLineRangeRead = extractLineRangeRead(cmd);
|
|
9440
9561
|
const sedReads = singleLineRangeRead !== null ? [singleLineRangeRead] : extractLineRangeReadsCompound(cmd);
|
|
9441
9562
|
if (sedReads !== null) {
|
|
@@ -9462,30 +9583,44 @@ function preBashHandlerInner(event) {
|
|
|
9462
9583
|
}
|
|
9463
9584
|
const gcTailResult = extractGetContentTail(cmd);
|
|
9464
9585
|
if (gcTailResult !== null) {
|
|
9465
|
-
const { filePath, isDoc, isConfig, isSql } = gcTailResult;
|
|
9586
|
+
const { filePath, isDoc, isConfig, isSql, isXml } = gcTailResult;
|
|
9466
9587
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9467
9588
|
recordStat("session_hint", 0, 0);
|
|
9468
|
-
return contextOutput("`Get-Content -Tail` bypasses read hooks. " + surgicalHintForConfigDoc(hintPath, isConfig, isDoc, isSql));
|
|
9589
|
+
return contextOutput("`Get-Content -Tail` bypasses read hooks. " + surgicalHintForConfigDoc(hintPath, isConfig, isDoc, isSql, isXml));
|
|
9469
9590
|
}
|
|
9470
9591
|
const gcSelectResult = extractGetContentSelectFirst(cmd);
|
|
9471
9592
|
if (gcSelectResult !== null) {
|
|
9472
|
-
const { filePath, isDoc, isConfig, isSql, n } = gcSelectResult;
|
|
9593
|
+
const { filePath, isDoc, isConfig, isSql, isXml, n } = gcSelectResult;
|
|
9473
9594
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9474
9595
|
recordStat("session_hint", 0, 0);
|
|
9475
|
-
return contextOutput(leadingLinesHint("`Select-Object -First` bypasses read hooks. ", hintPath, 1, n, { isConfig, isDoc, isSql }, preHookCwd));
|
|
9596
|
+
return contextOutput(leadingLinesHint("`Select-Object -First` bypasses read hooks. ", hintPath, 1, n, { isConfig, isDoc, isSql, isXml }, preHookCwd));
|
|
9476
9597
|
}
|
|
9477
9598
|
const catJsonPipe = extractCatJsonPipe(cmd);
|
|
9478
9599
|
if (catJsonPipe !== null) {
|
|
9479
|
-
const { filePath } = catJsonPipe;
|
|
9600
|
+
const { filePath, isDirectJq } = catJsonPipe;
|
|
9480
9601
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9481
9602
|
recordStat("session_hint", 0, 0);
|
|
9603
|
+
const label = isDirectJq ? "`jq`" : "`cat | jq`";
|
|
9604
|
+
return contextOutput(
|
|
9605
|
+
label + ' loads the whole file. Use `token-goat json-query "' + hintPath + '" "<key>"` or `token-goat config-get "' + hintPath + '" KEY_NAME` to slice one value.'
|
|
9606
|
+
);
|
|
9607
|
+
}
|
|
9608
|
+
const psJsonPipe = extractPowerShellJsonPipeline(cmd);
|
|
9609
|
+
if (psJsonPipe !== null) {
|
|
9610
|
+
recordStat("session_hint", 0, 0);
|
|
9611
|
+
if (psJsonPipe.filePath) {
|
|
9612
|
+
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, psJsonPipe.filePath, hintCwd) : psJsonPipe.filePath);
|
|
9613
|
+
return contextOutput(
|
|
9614
|
+
'PowerShell `ConvertFrom-Json` pipeline detected. Use `token-goat json-query "' + hintPath + '" "<selector>"` to extract fields directly without shell conversion scripts.'
|
|
9615
|
+
);
|
|
9616
|
+
}
|
|
9482
9617
|
return contextOutput(
|
|
9483
|
-
'
|
|
9618
|
+
'PowerShell `ConvertFrom-Json` pipeline detected. Use `token-goat json-query <file> "<selector>"` or `token-goat web-output` to extract fields directly.'
|
|
9484
9619
|
);
|
|
9485
9620
|
}
|
|
9486
9621
|
const catResult = extractCatFile(cmd);
|
|
9487
9622
|
if (catResult !== null) {
|
|
9488
|
-
const { filePath, isDoc, isEnv, isConfig, isSql, cmd0, advisoryOnly } = catResult;
|
|
9623
|
+
const { filePath, isDoc, isEnv, isConfig, isSql, isXml, cmd0, advisoryOnly } = catResult;
|
|
9489
9624
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9490
9625
|
recordStat("session_hint", 0, 0);
|
|
9491
9626
|
if (isSql) {
|
|
@@ -9493,16 +9628,16 @@ function preBashHandlerInner(event) {
|
|
|
9493
9628
|
"`" + cmd0 + '` loads the entire file into context. Use `token-goat section "' + hintPath + '::table_name"` to pull one CREATE TABLE / CREATE TYPE block.'
|
|
9494
9629
|
);
|
|
9495
9630
|
}
|
|
9496
|
-
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc);
|
|
9631
|
+
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc, isXml);
|
|
9497
9632
|
return cdStripped || advisoryOnly ? contextOutput("`" + cmd0 + "` loads the entire file into context. " + hint) : denyOutput("`" + cmd0 + "` loads the entire file into context. " + hint);
|
|
9498
9633
|
}
|
|
9499
9634
|
const catMulti = extractCatFilesMulti(cmd);
|
|
9500
9635
|
if (catMulti !== null) {
|
|
9501
9636
|
recordStat("session_hint", 0, 0);
|
|
9502
9637
|
const cmd0 = catMulti[0].cmd0;
|
|
9503
|
-
const perPath = catMulti.map(({ filePath, isDoc, isEnv, isConfig, isSql }) => {
|
|
9638
|
+
const perPath = catMulti.map(({ filePath, isDoc, isEnv, isConfig, isSql, isXml }) => {
|
|
9504
9639
|
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"';
|
|
9640
|
+
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
9641
|
return " " + hintPath + " -> `" + how + "`";
|
|
9507
9642
|
});
|
|
9508
9643
|
const msg = "`" + cmd0 + "` on multiple files loads them all into context. Read each surgically instead:\n" + perPath.join("\n");
|
|
@@ -9510,19 +9645,19 @@ function preBashHandlerInner(event) {
|
|
|
9510
9645
|
}
|
|
9511
9646
|
const psGetContentResult = extractPowerShellWrappedGetContent(cmd, event);
|
|
9512
9647
|
if (psGetContentResult !== null) {
|
|
9513
|
-
const { filePath, isDoc, isEnv, isConfig, isSql } = psGetContentResult;
|
|
9648
|
+
const { filePath, isDoc, isEnv, isConfig, isSql, isXml } = psGetContentResult;
|
|
9514
9649
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9515
9650
|
recordStat("session_hint", 0, 0);
|
|
9516
9651
|
const lead = "`Get-Content` via a `powershell -Command` wrapper bypasses read hooks and loads the entire file into context. ";
|
|
9517
9652
|
if (isSql) {
|
|
9518
9653
|
return contextOutput(lead + 'Use `token-goat section "' + hintPath + '::table_name"` to pull one CREATE TABLE / CREATE TYPE block.');
|
|
9519
9654
|
}
|
|
9520
|
-
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc);
|
|
9655
|
+
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc, isXml);
|
|
9521
9656
|
return cdStripped ? contextOutput(lead + hint) : denyOutput(lead + hint);
|
|
9522
9657
|
}
|
|
9523
9658
|
const wslCatResult = extractWslCatFile(cmd);
|
|
9524
9659
|
if (wslCatResult !== null) {
|
|
9525
|
-
const { filePath, isDoc, isEnv, isConfig, isSql } = wslCatResult;
|
|
9660
|
+
const { filePath, isDoc, isEnv, isConfig, isSql, isXml } = wslCatResult;
|
|
9526
9661
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9527
9662
|
recordStat("session_hint", 0, 0);
|
|
9528
9663
|
if (isSql) {
|
|
@@ -9530,12 +9665,12 @@ function preBashHandlerInner(event) {
|
|
|
9530
9665
|
'`cat` loads the entire file into context. Use `token-goat section "' + hintPath + '::table_name"` to pull one CREATE TABLE / CREATE TYPE block.'
|
|
9531
9666
|
);
|
|
9532
9667
|
}
|
|
9533
|
-
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc);
|
|
9668
|
+
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc, isXml);
|
|
9534
9669
|
return cdStripped ? contextOutput("`cat` loads the entire file into context. " + hint) : denyOutput("`cat` loads the entire file into context. " + hint);
|
|
9535
9670
|
}
|
|
9536
9671
|
const pyRead = extractPythonFileRead(cmd);
|
|
9537
9672
|
if (pyRead !== null) {
|
|
9538
|
-
const { filePath, isDoc, isConfig, isEnv, isSql, isOutputFile } = pyRead;
|
|
9673
|
+
const { filePath, isDoc, isConfig, isEnv, isSql, isXml, isOutputFile } = pyRead;
|
|
9539
9674
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9540
9675
|
recordStat("session_hint", 0, 0);
|
|
9541
9676
|
if (isOutputFile) {
|
|
@@ -9552,22 +9687,22 @@ function preBashHandlerInner(event) {
|
|
|
9552
9687
|
'Python `open()` file reads bypass read hooks. Use `token-goat section "' + hintPath + '::table_name"` to pull one CREATE TABLE / CREATE TYPE block.'
|
|
9553
9688
|
);
|
|
9554
9689
|
}
|
|
9555
|
-
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc);
|
|
9690
|
+
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc, isXml);
|
|
9556
9691
|
return cdStripped ? contextOutput("Python `open()` file reads bypass read hooks. " + hint) : denyOutput("Python `open()` file reads bypass read hooks. " + hint);
|
|
9557
9692
|
}
|
|
9558
9693
|
const tailResult = extractTailFile(cmd);
|
|
9559
9694
|
if (tailResult !== null) {
|
|
9560
|
-
const { filePath, isDoc, isConfig, isSql } = tailResult;
|
|
9695
|
+
const { filePath, isDoc, isConfig, isSql, isXml } = tailResult;
|
|
9561
9696
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9562
9697
|
recordStat("session_hint", 0, 0);
|
|
9563
|
-
return contextOutput("`tail` bypasses read hooks. " + surgicalHintForConfigDoc(hintPath, isConfig, isDoc, isSql));
|
|
9698
|
+
return contextOutput("`tail` bypasses read hooks. " + surgicalHintForConfigDoc(hintPath, isConfig, isDoc, isSql, isXml));
|
|
9564
9699
|
}
|
|
9565
9700
|
const headResult = extractHeadFile(cmd);
|
|
9566
9701
|
if (headResult !== null) {
|
|
9567
|
-
const { filePath, isDoc, isConfig, isSql, n } = headResult;
|
|
9702
|
+
const { filePath, isDoc, isConfig, isSql, isXml, n } = headResult;
|
|
9568
9703
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9569
9704
|
recordStat("session_hint", 0, 0);
|
|
9570
|
-
return contextOutput(leadingLinesHint("`head` bypasses read hooks. ", hintPath, 1, n, { isConfig, isDoc, isSql }, preHookCwd));
|
|
9705
|
+
return contextOutput(leadingLinesHint("`head` bypasses read hooks. ", hintPath, 1, n, { isConfig, isDoc, isSql, isXml }, preHookCwd));
|
|
9571
9706
|
}
|
|
9572
9707
|
const nodeRead = extractNodeFileRead(cmd);
|
|
9573
9708
|
if (nodeRead !== null) {
|
|
@@ -9584,14 +9719,14 @@ function preBashHandlerInner(event) {
|
|
|
9584
9719
|
}
|
|
9585
9720
|
const psMethodRead = extractPowerShellFileMethodRead(cmd, event);
|
|
9586
9721
|
if (psMethodRead !== null) {
|
|
9587
|
-
const { filePath, isDoc, isEnv, isConfig, isSql } = psMethodRead;
|
|
9722
|
+
const { filePath, isDoc, isEnv, isConfig, isSql, isXml } = psMethodRead;
|
|
9588
9723
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9589
9724
|
const lead = "PowerShell `[IO.File]::ReadAllText()` bypasses read hooks. ";
|
|
9590
9725
|
if (isSql) {
|
|
9591
9726
|
recordStat("session_hint", 0, 0);
|
|
9592
9727
|
return contextOutput(lead + 'Use `token-goat section "' + hintPath + '::table_name"` to pull one CREATE TABLE / CREATE TYPE block.');
|
|
9593
9728
|
}
|
|
9594
|
-
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc);
|
|
9729
|
+
const hint = surgicalHintFor(hintPath, isEnv, isConfig, isDoc, isXml);
|
|
9595
9730
|
recordStat("session_hint", 0, 0);
|
|
9596
9731
|
return cdStripped ? contextOutput(lead + hint) : denyOutput(lead + hint);
|
|
9597
9732
|
}
|
|
@@ -9763,15 +9898,25 @@ function extractExitCode(raw) {
|
|
|
9763
9898
|
return null;
|
|
9764
9899
|
}
|
|
9765
9900
|
var GH_SECURITY_PATHS = ["/security_advisories", "/advisories", "security_events"];
|
|
9766
|
-
var GH_SCOPE_PHRASES = [
|
|
9901
|
+
var GH_SCOPE_PHRASES = [
|
|
9902
|
+
"Must have push access",
|
|
9903
|
+
"Resource not accessible by integration",
|
|
9904
|
+
"Must be an admin",
|
|
9905
|
+
"You are not authorized to perform this operation"
|
|
9906
|
+
];
|
|
9907
|
+
var GH_NOT_FOUND = /^gh: .*\(HTTP 404\)|"status":\s*"404"/m;
|
|
9767
9908
|
function buildGhApiHint(cmd, stdout, exitCode) {
|
|
9768
9909
|
if (stdout === "" || !cmd.startsWith("gh api")) return null;
|
|
9769
9910
|
const hints = [];
|
|
9770
9911
|
const isSecurityPath = GH_SECURITY_PATHS.some((p) => cmd.includes(p));
|
|
9771
9912
|
const hasScopePhrase = GH_SCOPE_PHRASES.some((p) => stdout.includes(p));
|
|
9772
|
-
const
|
|
9773
|
-
if (hasScopePhrase
|
|
9913
|
+
const ambiguousSecurity404 = exitCode !== null && exitCode !== 0 && isSecurityPath && GH_NOT_FOUND.test(stdout);
|
|
9914
|
+
if (hasScopePhrase) {
|
|
9774
9915
|
hints.push("[token-goat] GitHub API scope issue: try gh auth refresh -s security_events");
|
|
9916
|
+
} else if (ambiguousSecurity404) {
|
|
9917
|
+
hints.push(
|
|
9918
|
+
"[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."
|
|
9919
|
+
);
|
|
9775
9920
|
}
|
|
9776
9921
|
const trimmed = stdout.trimStart();
|
|
9777
9922
|
if (trimmed.startsWith("{")) {
|
|
@@ -9841,10 +9986,28 @@ function recordBashFileReadsForSessionCache(cmd, cwd) {
|
|
|
9841
9986
|
return;
|
|
9842
9987
|
}
|
|
9843
9988
|
}
|
|
9989
|
+
async function maybeEmitLargeUncompressedHint(cmd, output, exitCode, cwd, isUnwrapped, event, ansiResult) {
|
|
9990
|
+
const outputBytes = Buffer.byteLength(output, "utf-8");
|
|
9991
|
+
if (outputBytes < 4096 || process.env["TOKEN_GOAT_BASH_COMPRESS"] === "0" || exitCode !== null && exitCode !== 0 || event.raw["_tg_harness"] !== "vscode" && (isCompressibleSingleCommand(cmd) || !isUnwrapped)) {
|
|
9992
|
+
return null;
|
|
9993
|
+
}
|
|
9994
|
+
const key = `bash-uncompressed-4k:${event.sessionId ?? ""}:${shortFingerprint(cmd)}`;
|
|
9995
|
+
if (wasHintShown(key)) return null;
|
|
9996
|
+
markHintShown(key);
|
|
9997
|
+
recordStat("session_hint", 0, 0);
|
|
9998
|
+
const id = await storeBashOutput(cmd, output, exitCode ?? 0, cwd);
|
|
9999
|
+
const kb = Math.round(outputBytes / 1024);
|
|
10000
|
+
const msg = `[tg] Output was ${kb}KB uncompressed. For large tool outputs, run with 'token-goat compress -c "${displaySafeText(cmd)}"' or inspect via 'token-goat bash-output ${id}'.`;
|
|
10001
|
+
if (ansiResult !== null && ansiResult.hookType === "rewriteOutput") {
|
|
10002
|
+
return emitRewrite(msg + "\n" + fenceUntrusted(ansiResult.updatedOutput, UNTRUSTED_TOOL_TAG), "large uncompressed output hint", void 0, "counted-elsewhere");
|
|
10003
|
+
}
|
|
10004
|
+
return contextOutput(msg);
|
|
10005
|
+
}
|
|
9844
10006
|
async function postBashHandler(event) {
|
|
9845
10007
|
try {
|
|
9846
10008
|
const rawCmdRaw = extractCommand(event);
|
|
9847
10009
|
if (rawCmdRaw === void 0) return passOutput();
|
|
10010
|
+
const isUnwrapped = unwrapCompressCommand(rawCmdRaw) === null;
|
|
9848
10011
|
const rawCmd = unwrapCompressCommand(rawCmdRaw) ?? rawCmdRaw;
|
|
9849
10012
|
const cmd = stripCdPrefix(rawCmd);
|
|
9850
10013
|
const output = extractBashOutput(event.raw);
|
|
@@ -9928,18 +10091,27 @@ async function postBashHandler(event) {
|
|
|
9928
10091
|
const gitScopedCacheId = await storeBashOutput(cmd, output, exitCode ?? 0, cwd);
|
|
9929
10092
|
recordBashOutput(gitScopedCacheHash, gitScopedCacheId, Buffer.byteLength(output, "utf-8"));
|
|
9930
10093
|
}
|
|
10094
|
+
if (isUnwrapped && /^git(?:\s+-[^\s]+|\s+--[^\s]+)*\s+diff\b/i.test(cmd)) {
|
|
10095
|
+
const unwrappedCompressed = await maybeCompressCompoundOutput(cmd, output, exitCode, cwd, cacheMinBytes, isUnwrapped);
|
|
10096
|
+
if (unwrappedCompressed !== null) return unwrappedCompressed;
|
|
10097
|
+
}
|
|
9931
10098
|
const isMonitoring = getMonitoringRecallHint(cmd) !== null;
|
|
9932
10099
|
const isFileRead = pureFileReadPath(cmd) !== null;
|
|
9933
10100
|
if (isFileRead || !isMonitoring && !isBuildCommand(cmd) && !isCurlGetCommand(cmd)) {
|
|
9934
10101
|
const identical = await maybeCollapseIdenticalRead(cmd, rawCmd, output, exitCode, cwd, cacheMinBytes);
|
|
9935
10102
|
if (identical !== null) return identical;
|
|
9936
|
-
|
|
9937
|
-
|
|
10103
|
+
if (!isFileRead && (!isUnwrapped || !isCompressibleSingleCommand(cmd))) {
|
|
10104
|
+
const compound = await maybeCompressCompoundOutput(cmd, output, exitCode, cwd, cacheMinBytes, isUnwrapped);
|
|
10105
|
+
if (compound !== null) return compound;
|
|
10106
|
+
}
|
|
9938
10107
|
if (!isFileRead && extractLineRangeReadsCompound(cmd) === null) {
|
|
9939
10108
|
const genericElision = await maybeElideServedGenericOutput(cmd, output, exitCode, cwd, cacheMinBytes);
|
|
9940
10109
|
if (genericElision !== null) return genericElision;
|
|
9941
10110
|
}
|
|
9942
|
-
|
|
10111
|
+
const ansiStripped = maybeStripAnsiOnly(output);
|
|
10112
|
+
const largeHint2 = await maybeEmitLargeUncompressedHint(cmd, output, exitCode, cwd, isUnwrapped, event, ansiStripped);
|
|
10113
|
+
if (largeHint2 !== null) return largeHint2;
|
|
10114
|
+
return ansiStripped ?? passOutput();
|
|
9943
10115
|
}
|
|
9944
10116
|
if (Buffer.byteLength(output, "utf-8") < cacheMinBytes) return passOutput();
|
|
9945
10117
|
const cacheKey = isCurlGetCommand(cmd) ? extractCurlUrl(cmd) ?? cmd : stripOutputPipeline(cmd);
|
|
@@ -9959,6 +10131,8 @@ async function postBashHandler(event) {
|
|
|
9959
10131
|
const curlHtmlFold = maybeFoldCurlHtml(cmd, output, id);
|
|
9960
10132
|
if (curlHtmlFold !== null) return curlHtmlFold;
|
|
9961
10133
|
const ansiOnly = maybeStripAnsiOnly(output);
|
|
10134
|
+
const largeHint = await maybeEmitLargeUncompressedHint(cmd, output, exitCode, cwd, isUnwrapped, event, ansiOnly);
|
|
10135
|
+
if (largeHint !== null) return largeHint;
|
|
9962
10136
|
if (ansiOnly !== null) return ansiOnly;
|
|
9963
10137
|
} catch {
|
|
9964
10138
|
}
|
|
@@ -10275,6 +10449,7 @@ function postToolUseFailureHandler(event) {
|
|
|
10275
10449
|
const ledger = readLedger(target);
|
|
10276
10450
|
const priorState = ledger.seen[signature];
|
|
10277
10451
|
const editDiagnostic = diagnoseEditFailure(event, errorText);
|
|
10452
|
+
const sqlDiagnostic = diagnoseSqlFailure(event, errorText);
|
|
10278
10453
|
if (priorState === void 0) {
|
|
10279
10454
|
ledger.seen[signature] = false;
|
|
10280
10455
|
ledger.order.push(signature);
|
|
@@ -10288,6 +10463,11 @@ function postToolUseFailureHandler(event) {
|
|
|
10288
10463
|
writeLedger(target, ledger);
|
|
10289
10464
|
return contextOutput(editDiagnostic);
|
|
10290
10465
|
}
|
|
10466
|
+
if (sqlDiagnostic !== null) {
|
|
10467
|
+
ledger.seen[signature] = true;
|
|
10468
|
+
writeLedger(target, ledger);
|
|
10469
|
+
return contextOutput(sqlDiagnostic);
|
|
10470
|
+
}
|
|
10291
10471
|
return passOutput();
|
|
10292
10472
|
}
|
|
10293
10473
|
if (priorState) return passOutput();
|
|
@@ -10296,6 +10476,9 @@ function postToolUseFailureHandler(event) {
|
|
|
10296
10476
|
if (editDiagnostic !== null) {
|
|
10297
10477
|
return contextOutput(editDiagnostic);
|
|
10298
10478
|
}
|
|
10479
|
+
if (sqlDiagnostic !== null) {
|
|
10480
|
+
return contextOutput(sqlDiagnostic);
|
|
10481
|
+
}
|
|
10299
10482
|
return contextOutput(repeatFailureNotice(toolName));
|
|
10300
10483
|
} catch {
|
|
10301
10484
|
return passOutput();
|
|
@@ -10572,6 +10755,37 @@ function compressGithubMcpResult(toolName, resultText) {
|
|
|
10572
10755
|
const stripped = deepStrip(parsed, githubShouldStrip);
|
|
10573
10756
|
return finishWithGenericPass(resultText, stripped);
|
|
10574
10757
|
}
|
|
10758
|
+
var ATLASSIAN_TOOL_RE = /(?:jira|confluence|atlassian)/i;
|
|
10759
|
+
var ATLASSIAN_STRIP_EXACT_KEYS = /* @__PURE__ */ new Set([
|
|
10760
|
+
"avatarUrls",
|
|
10761
|
+
"avatarUrl",
|
|
10762
|
+
"iconUrl",
|
|
10763
|
+
"iconUrls",
|
|
10764
|
+
"self",
|
|
10765
|
+
"expand",
|
|
10766
|
+
"schema",
|
|
10767
|
+
"operations",
|
|
10768
|
+
"editmeta",
|
|
10769
|
+
"names",
|
|
10770
|
+
"_links",
|
|
10771
|
+
"_expandable",
|
|
10772
|
+
"extensions",
|
|
10773
|
+
"timeZone"
|
|
10774
|
+
]);
|
|
10775
|
+
function atlassianShouldStrip(key) {
|
|
10776
|
+
return ATLASSIAN_STRIP_EXACT_KEYS.has(key);
|
|
10777
|
+
}
|
|
10778
|
+
function compressAtlassianMcpResult(toolName, resultText) {
|
|
10779
|
+
if (!ATLASSIAN_TOOL_RE.test(toolName)) return null;
|
|
10780
|
+
let parsed;
|
|
10781
|
+
try {
|
|
10782
|
+
parsed = JSON.parse(resultText);
|
|
10783
|
+
} catch {
|
|
10784
|
+
return null;
|
|
10785
|
+
}
|
|
10786
|
+
const stripped = deepStrip(parsed, atlassianShouldStrip);
|
|
10787
|
+
return finishWithGenericPass(resultText, stripped);
|
|
10788
|
+
}
|
|
10575
10789
|
var BROWSER_TOOL_RE = /^mcp__.*(?:chrome-devtools|claude-in-chrome|playwright).*__/i;
|
|
10576
10790
|
var BROWSER_CONSOLE_METHOD_RE = /(?:^|_)(?:read|list)_console_messages$/i;
|
|
10577
10791
|
var BROWSER_NETWORK_METHOD_RE = /(?:^|_)(?:read|list)_network_requests$/i;
|
|
@@ -10722,10 +10936,11 @@ function stripBase64DataUrls(resultText) {
|
|
|
10722
10936
|
function compressMcpResultWithPacks(toolName, resultText) {
|
|
10723
10937
|
const base64Stripped = stripBase64DataUrls(resultText);
|
|
10724
10938
|
const text = base64Stripped ?? resultText;
|
|
10725
|
-
return compressGithubMcpResult(toolName, text) ?? compressBrowserMcpResult(toolName, text) ?? compressGWorkspaceMcpResult(toolName, text) ?? base64Stripped;
|
|
10939
|
+
return compressGithubMcpResult(toolName, text) ?? compressAtlassianMcpResult(toolName, text) ?? compressBrowserMcpResult(toolName, text) ?? compressGWorkspaceMcpResult(toolName, text) ?? base64Stripped;
|
|
10726
10940
|
}
|
|
10727
10941
|
|
|
10728
10942
|
// src/hooks_mcp.ts
|
|
10943
|
+
var MCP_OVERSIZED_THRESHOLD_BYTES = 25e3;
|
|
10729
10944
|
function preMcpHandler(event) {
|
|
10730
10945
|
const toolName = getToolName(event);
|
|
10731
10946
|
if (!toolName || !event.sessionId) return passOutput();
|
|
@@ -10783,9 +10998,15 @@ function postMcpHandler(event) {
|
|
|
10783
10998
|
minNetSavingsBytes: resolveMinNetSavingsBytes()
|
|
10784
10999
|
});
|
|
10785
11000
|
if (worthwhile) {
|
|
11001
|
+
const bodyBytes = Buffer.byteLength(redactedBody, "utf-8");
|
|
11002
|
+
let finalBody = redactedBody;
|
|
11003
|
+
if (bodyBytes >= MCP_OVERSIZED_THRESHOLD_BYTES) {
|
|
11004
|
+
const preview = clipToDeliveryCap(redactedBody, Buffer.byteLength(notice, "utf-8") + 500);
|
|
11005
|
+
finalBody = preview.text + (preview.clipped ? "\n\n...[preview truncated by token-goat; use mcp-output above to query full payload]..." : "");
|
|
11006
|
+
}
|
|
10786
11007
|
return preserve(
|
|
10787
11008
|
emitRewrite(
|
|
10788
|
-
`${notice}${fenceWithMatches(
|
|
11009
|
+
`${notice}${fenceWithMatches(finalBody, injectionMatches, UNTRUSTED_TOOL_TAG)}`,
|
|
10789
11010
|
"mcp",
|
|
10790
11011
|
{ kind: "mcp:compress", originalBytes }
|
|
10791
11012
|
)
|
|
@@ -10794,6 +11015,29 @@ function postMcpHandler(event) {
|
|
|
10794
11015
|
}
|
|
10795
11016
|
}
|
|
10796
11017
|
}
|
|
11018
|
+
const rawBytes = Buffer.byteLength(resultText, "utf-8");
|
|
11019
|
+
if (rawBytes >= MCP_OVERSIZED_THRESHOLD_BYTES && process.env["TOKEN_GOAT_MCP_COMPRESS"] !== "0") {
|
|
11020
|
+
if (id === null) id = storeMcpOutput(event.sessionId, toolName, toolInput, resultText);
|
|
11021
|
+
if (id !== null) {
|
|
11022
|
+
const notice = `[token-goat: oversized MCP result (${rawBytes} bytes) cached as ${id}]
|
|
11023
|
+
The full payload was cached to prevent harness context spill. Slicing commands:
|
|
11024
|
+
token-goat mcp-output ${id} --json-query '<path>' (e.g. 'issues[*].key', 'values[*].id')
|
|
11025
|
+
token-goat mcp-output ${id} --section '<heading>'
|
|
11026
|
+
token-goat mcp-output ${id} --grep '<regex>' --max-matches 20
|
|
11027
|
+
token-goat mcp-output ${id} --head 50
|
|
11028
|
+
|
|
11029
|
+
`;
|
|
11030
|
+
const preview = clipToDeliveryCap(redactedResult.text, Buffer.byteLength(notice, "utf-8") + 500);
|
|
11031
|
+
const previewBody = preview.text + (preview.clipped ? "\n\n...[preview truncated by token-goat; use mcp-output above to query full payload]..." : "");
|
|
11032
|
+
return preserve(
|
|
11033
|
+
emitRewrite(
|
|
11034
|
+
`${notice}${fenceWithMatches(previewBody, injectionMatches, UNTRUSTED_TOOL_TAG)}`,
|
|
11035
|
+
"mcp",
|
|
11036
|
+
{ kind: "mcp:oversized", originalBytes: rawBytes }
|
|
11037
|
+
)
|
|
11038
|
+
);
|
|
11039
|
+
}
|
|
11040
|
+
}
|
|
10797
11041
|
return passOrFence();
|
|
10798
11042
|
}
|
|
10799
11043
|
registerHook("pre_tool_use", preMcpHandler, { toolPattern: "^mcp__" });
|
|
@@ -11028,7 +11272,7 @@ function buildSubagentBriefing() {
|
|
|
11028
11272
|
}
|
|
11029
11273
|
const tail = [];
|
|
11030
11274
|
tail.push("");
|
|
11031
|
-
tail.push('Before your first read of any file, check for a token-goat command that returns just what you need and run it instead of a full-file read or wide grep: `token-goat symbol <name>`, `token-goat read "file::symbol"`, `token-goat section "file::<heading>"`. Skipping that check is a violation, not an oversight; the only exemptions are a file under ~200 lines you need whole, a never-indexed file, or an image.');
|
|
11275
|
+
tail.push('Before your first read of any file, check for a token-goat command that returns just what you need and run it instead of a full-file read or wide grep: `token-goat symbol <name>`, `token-goat read "file::symbol"`, `token-goat section "file::<heading>"`, `token-goat json-query file \'a.b.c\'`. Skipping that check is a violation, not an oversight; the only exemptions are a file under ~200 lines you need whole, a never-indexed file, or an image.');
|
|
11032
11276
|
tail.push("");
|
|
11033
11277
|
tail.push('Report contract: cite evidence as `file::symbol` or a token-goat recall id (`token-goat mcp-output <id> --full`) rather than pasting bodies; paste a fenced block only when the exact bytes are load-bearing; state every unverified claim explicitly (e.g. "not verified: ...") rather than omitting it.');
|
|
11034
11278
|
const withCacheIds = head.join("\n") + cacheIdsBlock + "\n" + tail.join("\n");
|