token-goat 2.9.15 → 2.9.17

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.
Files changed (39) hide show
  1. package/README.md +2 -5
  2. package/dist/{token-goat-chunk-IVUQLQWN.mjs → token-goat-chunk-26YUO7MP.mjs} +5 -3
  3. package/dist/{token-goat-chunk-SZWYESBS.mjs → token-goat-chunk-2M33Q3O4.mjs} +172 -67
  4. package/dist/{token-goat-chunk-S4XRY446.mjs → token-goat-chunk-2VASS5VR.mjs} +4 -3
  5. package/dist/{token-goat-chunk-7ZYK25AO.mjs → token-goat-chunk-2XA5ZW4T.mjs} +4 -4
  6. package/dist/{token-goat-chunk-C5JIO6HK.mjs → token-goat-chunk-5WB7GDH4.mjs} +5 -5
  7. package/dist/{token-goat-chunk-MZDIJJ3R.mjs → token-goat-chunk-66224KCZ.mjs} +40 -3
  8. package/dist/{token-goat-chunk-NDRP4KJQ.mjs → token-goat-chunk-73GXYYZR.mjs} +248 -50
  9. package/dist/{token-goat-chunk-ATIFTMRC.mjs → token-goat-chunk-7EGKXBWT.mjs} +7 -7
  10. package/dist/{token-goat-chunk-GMQQA7E4.mjs → token-goat-chunk-7VQMOBPQ.mjs} +2453 -722
  11. package/dist/token-goat-chunk-BGHSSJUA.mjs +102 -0
  12. package/dist/{token-goat-chunk-2X2EBBC6.mjs → token-goat-chunk-BK3RPPTK.mjs} +2 -2
  13. package/dist/{token-goat-chunk-YQ7WI2CO.mjs → token-goat-chunk-C26ZBGBC.mjs} +393 -3957
  14. package/dist/{token-goat-chunk-SFAS46RE.mjs → token-goat-chunk-CICJFVIH.mjs} +2 -2
  15. package/dist/{token-goat-chunk-6DLVZDB6.mjs → token-goat-chunk-CKIJWTRQ.mjs} +13 -12
  16. package/dist/{token-goat-chunk-5V7DAC7V.mjs → token-goat-chunk-CPHVXKNU.mjs} +10 -3
  17. package/dist/{token-goat-chunk-LT7JRU6K.mjs → token-goat-chunk-EKGVCAES.mjs} +4 -4
  18. package/dist/{token-goat-chunk-Z6UXPYJA.mjs → token-goat-chunk-F2ARFHLJ.mjs} +1 -1
  19. package/dist/{token-goat-chunk-NDPO7GAH.mjs → token-goat-chunk-G75WIVFM.mjs} +21 -20
  20. package/dist/{token-goat-chunk-YZX7EFG4.mjs → token-goat-chunk-GLOM5W5C.mjs} +1 -1
  21. package/dist/{token-goat-chunk-GIIHUSZX.mjs → token-goat-chunk-GPCCYQSS.mjs} +41 -11
  22. package/dist/{token-goat-chunk-OUGNPMDA.mjs → token-goat-chunk-HRUGS6CO.mjs} +30 -14
  23. package/dist/{token-goat-chunk-LCZBPOIN.mjs → token-goat-chunk-IDHWKNKZ.mjs} +143 -51
  24. package/dist/{token-goat-chunk-YKG35VHC.mjs → token-goat-chunk-KZPO4DWC.mjs} +1 -1
  25. package/dist/{token-goat-chunk-NEI4NC54.mjs → token-goat-chunk-LKSXAMJB.mjs} +7 -2
  26. package/dist/{token-goat-chunk-K7F2BFIK.mjs → token-goat-chunk-MWSVUKVV.mjs} +1 -1
  27. package/dist/{token-goat-chunk-BL5LNGBG.mjs → token-goat-chunk-PKNOHVWP.mjs} +2966 -3869
  28. package/dist/{token-goat-chunk-A4JYKD5H.mjs → token-goat-chunk-RB24DBBS.mjs} +2 -2
  29. package/dist/{token-goat-chunk-3NSDDTGL.mjs → token-goat-chunk-RFFUCQK7.mjs} +5 -5
  30. package/dist/token-goat-chunk-RRNZMM3A.mjs +3364 -0
  31. package/dist/{token-goat-chunk-XEPXYDPI.mjs → token-goat-chunk-SWRKVA3J.mjs} +11 -2
  32. package/dist/{token-goat-chunk-NU7TLMQK.mjs → token-goat-chunk-THBLW56G.mjs} +10 -7
  33. package/dist/{token-goat-chunk-PM76YS22.mjs → token-goat-chunk-UBZCON6N.mjs} +1 -1
  34. package/dist/{token-goat-chunk-ASYEPR3S.mjs → token-goat-chunk-W2GUUQAQ.mjs} +7 -3
  35. package/dist/{token-goat-chunk-DQ4J5AFF.mjs → token-goat-chunk-YFGEUIEO.mjs} +69 -18
  36. package/dist/token-goat-hook.mjs +13 -12
  37. package/dist/token-goat.core.mjs +21 -20
  38. package/docs/cli.md +1 -0
  39. package/package.json +1 -1
package/README.md CHANGED
@@ -341,12 +341,9 @@ Per-harness setup for Codex, Gemini, Qwen, Kimi, opencode, OpenClaw, pi, Copilot
341
341
 
342
342
  ## CLI
343
343
 
344
- You rarely type these yourself. Installation writes a routing guide into the agent's instructions, and the agent picks the command that answers its question: a surgical read (`read`, `symbol`, `section`, `skeleton`), a search (`semantic`, `refs`), orientation in an unfamiliar repo (`map`, `arch`, `affected`), recall of output it already has (`bash-output`, `web-output`, `mcp-output`), or a bounded reader for a PDF, Word file, slide deck, workbook, SQLite database, HTML document or image.
344
+ You rarely type these yourself. Installation writes a routing guide into the agent's instructions, and the agent picks the command that answers its question: a surgical read (`read`, `symbol`, `locate`, `section`, `skeleton`), a search (`semantic`, `refs`), orientation in an unfamiliar repo (`map`, `arch`, `affected`), recall of output it already has (`bash-output`, `web-output`, `mcp-output`), or a bounded reader for a PDF, Word file, slide deck, workbook, SQLite database, HTML document or image.
345
345
 
346
- One command is for people working on token-goat rather than for agents: `token-goat bench` replays a
347
- corpus of captured shell output through the real compression path and reports how much smaller the
348
- result got, alongside a count of the lines each case is not allowed to lose. Deleting output makes
349
- the first number look better, so the second one is what keeps the first honest.
346
+ One command is for people working on token-goat rather than for agents: `token-goat bench` replays a corpus of captured shell output through the real compression path and reports how much smaller the result got, alongside a count of the lines each case is not allowed to lose. Deleting output makes the first number look better, so the second one is what keeps the first honest.
350
347
 
351
348
  Every command, with its flags, its output, and the comparison workflows that chain them: **[CLI reference](docs/cli.md)**. For architectural analysis, empirical evaluations, and technical answers to common engineering questions: **[Architecture & Technical Q&A](docs/architecture-qa.html)**.
352
349
 
@@ -2,11 +2,11 @@ import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
3
  import {
4
4
  getDb
5
- } from "./token-goat-chunk-K7F2BFIK.mjs";
5
+ } from "./token-goat-chunk-MWSVUKVV.mjs";
6
6
  import {
7
7
  getHarnessName,
8
8
  loadConfig
9
- } from "./token-goat-chunk-S4XRY446.mjs";
9
+ } from "./token-goat-chunk-2VASS5VR.mjs";
10
10
  import {
11
11
  registerReset
12
12
  } from "./token-goat-chunk-EEIDFMEM.mjs";
@@ -19,7 +19,7 @@ import {
19
19
  ensureDirSync,
20
20
  sanitizeIdForFilename,
21
21
  tokenGoatHome
22
- } from "./token-goat-chunk-PM76YS22.mjs";
22
+ } from "./token-goat-chunk-UBZCON6N.mjs";
23
23
  import {
24
24
  displaySafeText
25
25
  } from "./token-goat-chunk-ERTXEKB6.mjs";
@@ -473,6 +473,7 @@ var _KIND_GROUPS = [
473
473
  "gdrive_image",
474
474
  "webfetch_image",
475
475
  "image_shrink_skipped",
476
+ "image_shrink_over_pixel_limit",
476
477
  "image_shrink_cache_hit",
477
478
  "image_ocr"
478
479
  ])
@@ -872,6 +873,7 @@ var KIND_TO_SOURCE = {
872
873
  image_shrink: SOURCE_IMAGE,
873
874
  image_shrink_cache_hit: SOURCE_IMAGE,
874
875
  image_shrink_skipped: SOURCE_IMAGE,
876
+ image_shrink_over_pixel_limit: SOURCE_IMAGE,
875
877
  image_ocr: SOURCE_IMAGE,
876
878
  webfetch_image: SOURCE_IMAGE,
877
879
  gdrive_image: SOURCE_IMAGE,
@@ -4,7 +4,7 @@ import {
4
4
  canRunWrappedShell,
5
5
  clipToDeliveryCap,
6
6
  deliveredOutputBytes
7
- } from "./token-goat-chunk-YZX7EFG4.mjs";
7
+ } from "./token-goat-chunk-GLOM5W5C.mjs";
8
8
  import {
9
9
  DEFAULT_RECONCILE_BUDGET_MS,
10
10
  HOOK_EVENTS,
@@ -17,11 +17,13 @@ import {
17
17
  readStdinJson,
18
18
  reconcileProject,
19
19
  storeWebOutput
20
- } from "./token-goat-chunk-OUGNPMDA.mjs";
20
+ } from "./token-goat-chunk-HRUGS6CO.mjs";
21
21
  import {
22
+ BODY_FIRST_TOOL_RESPONSE_KEYS,
22
23
  GENERIC_SERVED_OUTPUT_KEY,
23
24
  OUTLINE_MAX_REPLACEMENT_RATIO,
24
25
  OUTLINE_MIN_HEADINGS,
26
+ OUTPUT_FIRST_TOOL_RESPONSE_KEYS,
25
27
  WEB_FETCH_KEY_SEP,
26
28
  accumulateResidentLines,
27
29
  appendDirtyPath,
@@ -33,9 +35,16 @@ import {
33
35
  clearCurlDownload,
34
36
  compactPathFor,
35
37
  computeAdaptiveBudget,
38
+ contextOutput,
39
+ denyOutput,
40
+ emitRewrite,
41
+ emitRewriteIfChanged,
36
42
  enqueueDirtyPathSafe,
37
43
  ensureWorkerAlive,
44
+ estimateTokens,
38
45
  extractCompactFromMarker,
46
+ extractToolResponseField,
47
+ extractToolResultText,
39
48
  fenceUntrusted,
40
49
  fenceUntrustedSpans,
41
50
  fenceWithMatches,
@@ -47,7 +56,9 @@ import {
47
56
  getBashOutputId,
48
57
  getContextPressure,
49
58
  getCurlDownloadPath,
59
+ getCwd,
50
60
  getFileLineRanges,
61
+ getFilePath,
51
62
  getFileServedOutputs,
52
63
  getGlobMatchCount,
53
64
  getGrepMatchCount,
@@ -56,31 +67,41 @@ import {
56
67
  getSessionBashReruns,
57
68
  getSessionFiles,
58
69
  getSessionWebFetches,
70
+ getToolInput,
71
+ getToolName,
72
+ getTranscriptPath,
59
73
  hasSeenImage,
60
74
  hasSessionOutput,
61
75
  imageQualifiesForShrink,
62
76
  incrementSkillHit,
63
77
  indexServedBody,
64
78
  installedSkillPath,
79
+ isMcpErrorResponse,
65
80
  isStructuralRewriteAccepted,
81
+ isTextualContentBlock,
66
82
  lastTabContextMatches,
67
83
  lineMayCarryResidentSignal,
68
84
  listSiblingSessionStates,
69
85
  loadSessionCache,
70
86
  loadSessionState,
87
+ makeDedupHintHandlers,
71
88
  markCompactStale,
72
89
  markCompacted,
73
90
  markFileTruncated,
74
91
  markHintShown,
75
92
  matchesAllowPattern,
76
93
  matchesDenyPattern,
94
+ mcpContentBlocks,
77
95
  meetsSavingsFloor,
78
96
  metadataEndpointRefusal,
97
+ normalizePayload,
98
+ passOutput,
79
99
  planMarkdownOutline,
80
100
  planServedElisions,
81
101
  planSourceSkeleton,
82
102
  preToolPathDeclined,
83
103
  probeImageMeta,
104
+ readCopilotHooksOwners,
84
105
  readTranscriptTail,
85
106
  recordBashOutput,
86
107
  recordBashRerun,
@@ -98,13 +119,17 @@ import {
98
119
  recordSeenImage,
99
120
  recordSymbolRead,
100
121
  recordWebFetch,
122
+ registerHook,
101
123
  removeOutstandingAgentSpawn,
102
124
  repeatedSkillBodyHint,
125
+ runHook,
103
126
  saveSessionState,
104
127
  scanAndRecord,
128
+ serializeOutput,
105
129
  servedRunNotice,
106
130
  sessionOutputBodyBytes,
107
131
  sessionSidecarPath,
132
+ sessionStateKey,
108
133
  setLastTabContext,
109
134
  setTranscriptPath,
110
135
  shrinkImage,
@@ -117,76 +142,51 @@ import {
117
142
  vscodePathAllowed,
118
143
  wasCliReadThisSession,
119
144
  wasFileReadThisSession,
120
- wasHintShown
121
- } from "./token-goat-chunk-BL5LNGBG.mjs";
145
+ wasHintShown,
146
+ withPreservedBlocks
147
+ } from "./token-goat-chunk-PKNOHVWP.mjs";
122
148
  import {
123
149
  BASH_OUTPUT_SUBDIR,
124
- BODY_FIRST_TOOL_RESPONSE_KEYS,
125
- OUTPUT_FIRST_TOOL_RESPONSE_KEYS,
126
150
  commandHash,
127
151
  compressOutput,
128
- contextOutput,
129
152
  dedupeConsecutive,
130
- denyOutput,
131
153
  detectFromCommand,
132
- emitRewrite,
133
- emitRewriteIfChanged,
134
- estimateTokens,
135
- extractToolResponseField,
136
- extractToolResultText,
137
154
  filterByName,
138
155
  getBashOutput,
139
- getCwd,
140
- getFilePath,
141
156
  getMonitoringRecallHint,
142
- getToolInput,
143
- getToolName,
144
- getTranscriptPath,
145
157
  hasBareBackgroundOrNewline,
146
158
  hasUnquotedOperator,
147
159
  indexRecallEntry,
148
160
  isBashEntryStale,
149
161
  isBuildCommand,
150
- isMcpErrorResponse,
151
162
  isRewriteWorthwhile,
152
163
  isScopedGitStatusOrDiffStatCommand,
153
164
  isTestRunnerCommand,
154
- isTextualContentBlock,
155
- makeDedupHintHandlers,
156
- mcpContentBlocks,
157
- normalizePayload,
158
- passOutput,
159
- readCopilotHooksOwners,
160
- registerHook,
161
165
  resolveMinNetSavingsBytes,
162
- runHook,
163
- serializeOutput,
164
- sessionStateKey,
165
166
  shlexSplit,
166
167
  splitOwnTrailingNotices,
167
168
  storeBashOutput,
168
- summarizeOutputDelta,
169
- withPreservedBlocks
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";
169
+ summarizeOutputDelta
170
+ } from "./token-goat-chunk-C26ZBGBC.mjs";
178
171
  import {
179
172
  recordStat,
180
173
  redactSecrets,
181
174
  savedTokensFromBytes,
182
175
  storeBlob,
183
176
  stripAnsiEscapes
184
- } from "./token-goat-chunk-IVUQLQWN.mjs";
177
+ } from "./token-goat-chunk-26YUO7MP.mjs";
178
+ import {
179
+ extractMarkdownHeadings,
180
+ formatHeadingTreeParts
181
+ } from "./token-goat-chunk-73GXYYZR.mjs";
182
+ import {
183
+ countSymbols
184
+ } from "./token-goat-chunk-BK3RPPTK.mjs";
185
185
  import {
186
186
  detectLanguage,
187
187
  getDb,
188
188
  languageHasFlag
189
- } from "./token-goat-chunk-K7F2BFIK.mjs";
189
+ } from "./token-goat-chunk-MWSVUKVV.mjs";
190
190
  import {
191
191
  detectHarness,
192
192
  envBool,
@@ -196,7 +196,7 @@ import {
196
196
  isUnderSystemTemp,
197
197
  loadConfig,
198
198
  shortFingerprint
199
- } from "./token-goat-chunk-S4XRY446.mjs";
199
+ } from "./token-goat-chunk-2VASS5VR.mjs";
200
200
  import {
201
201
  ENV_KEYS,
202
202
  IDENTICAL_READ_MIN_BODY_BYTES,
@@ -207,6 +207,7 @@ import {
207
207
  countNoun,
208
208
  dataDir,
209
209
  ensureDirSync,
210
+ escapeRegExp,
210
211
  escapesOntoNetworkThroughLinks,
211
212
  extractErrorMessage,
212
213
  foldPath,
@@ -215,7 +216,7 @@ import {
215
216
  isInsideRoot,
216
217
  runGit,
217
218
  toKB
218
- } from "./token-goat-chunk-PM76YS22.mjs";
219
+ } from "./token-goat-chunk-UBZCON6N.mjs";
219
220
  import {
220
221
  UNTRUSTED_TOOL_TAG,
221
222
  displaySafePath,
@@ -945,7 +946,7 @@ init_define_import_meta_env();
945
946
  var TRACKED_SKILL = "token-goat";
946
947
  var MAX_COMMANDS_SHOWN = 8;
947
948
  async function currentCommandNames() {
948
- const { buildProgram } = await import("./token-goat-chunk-NDPO7GAH.mjs");
949
+ const { buildProgram } = await import("./token-goat-chunk-G75WIVFM.mjs");
949
950
  return flattenCommandNames(buildCommandManifest(buildProgram()));
950
951
  }
951
952
  async function recordSkillVersionSnapshot(sessionId, skillName) {
@@ -1234,8 +1235,10 @@ function reconcileNote(cwd, indexed) {
1234
1235
  const budgetMs = envInt(ENV_KEYS.RECONCILE_BUDGET_MS, DEFAULT_RECONCILE_BUDGET_MS, 0, 6e4);
1235
1236
  const result = reconcileProject({ cwd, budgetMs });
1236
1237
  if (isReconcileClean(result) && !result.budgetExhausted) return null;
1238
+ const upgraded = result.parserStale + result.embedStale;
1239
+ const edited = result.changed.length - upgraded;
1237
1240
  const parts = [];
1238
- if (result.changed.length > 0) parts.push(`${result.changed.length} changed`);
1241
+ if (edited > 0) parts.push(`${edited} changed`);
1239
1242
  if (result.added.length > 0) parts.push(`${result.added.length} new`);
1240
1243
  if (result.removed.length > 0) parts.push(`${result.removed.length} removed`);
1241
1244
  const breakdown = parts.length > 1 ? ` (${parts.join(", ")})` : "";
@@ -1244,7 +1247,11 @@ function reconcileNote(cwd, indexed) {
1244
1247
  if (total === 0) {
1245
1248
  return `token-goat: index drift check${truncated} found nothing in the part it had time to scan. Symbol lookups may be briefly stale.`;
1246
1249
  }
1247
- return `token-goat: reindexing ${countNoun(total, "file")} that changed outside this session${breakdown}${truncated}. Symbol lookups may be briefly stale.`;
1250
+ const drifted = total - upgraded;
1251
+ const clauses = [];
1252
+ if (drifted > 0) clauses.push(`${countNoun(drifted, "file")} that changed outside this session${breakdown}`);
1253
+ if (upgraded > 0) clauses.push(`${countNoun(upgraded, "file")} unchanged on disk but indexed by an older version of token-goat`);
1254
+ return `token-goat: reindexing ${clauses.join(" and ")}${truncated}. Symbol lookups may be briefly stale.`;
1248
1255
  } catch {
1249
1256
  return null;
1250
1257
  }
@@ -1773,11 +1780,11 @@ function toRegExp(r, i) {
1773
1780
  if (r.str.length === 0) {
1774
1781
  throw new Error(`Rule #${i} ("${r.name}") has empty "str" property, which is not allowed.`);
1775
1782
  }
1776
- return new RegExp(escapeRegExp(r.str), "y");
1783
+ return new RegExp(escapeRegExp2(r.str), "y");
1777
1784
  }
1778
- return new RegExp(escapeRegExp(r.name), "y");
1785
+ return new RegExp(escapeRegExp2(r.name), "y");
1779
1786
  }
1780
- function escapeRegExp(str) {
1787
+ function escapeRegExp2(str) {
1781
1788
  return str.replace(/[-[\]{}()*+!<=:?./\\^$|#\s,]/g, "\\$&");
1782
1789
  }
1783
1790
  function toSticky(re) {
@@ -7705,10 +7712,7 @@ function splitShellSegments(cmd) {
7705
7712
  }
7706
7713
  function isTempPath(fp) {
7707
7714
  const norm = fp.replace(/\\/g, "/");
7708
- return /^\/tmp\//i.test(norm) || /\/var\/folders\//i.test(norm) || // Anchored to a local drive root on purpose. Unanchored, this clause said yes to
7709
- // `//host/share/AppData/Local/Temp/x.md`, and the caller's answer to yes is to stat the path --
7710
- // which on Windows opens an SMB session to whatever host a command named. A temp directory is
7711
- // somewhere on a local volume; nothing that starts with two separators is one.
7715
+ return /^\/tmp\//i.test(norm) || /\/var\/folders\//i.test(norm) || // Anchored to a local drive root on purpose. Unanchored, this clause said yes to `//host/share/AppData/Local/Temp/x.md`, and the caller's answer to yes is to stat the path -- which on Windows opens an SMB session to whatever host a command named. A temp directory is somewhere on a local volume; nothing that starts with two separators is one.
7712
7716
  /^[a-z]:\/(?:[^/]+\/)*AppData\/Local\/Temp\//i.test(norm) || norm.startsWith("/c/Users/") && norm.includes("/AppData/Local/Temp/") || isUnderSystemTemp(fp);
7713
7717
  }
7714
7718
  function isOrchestratorStateFile(filePath) {
@@ -7835,12 +7839,77 @@ function extractRgSymbolSearch(cmd) {
7835
7839
  }
7836
7840
  function extractCatJsonPipe(cmd) {
7837
7841
  const m = /^cat\s+(?:"([^"]+)"|'([^']+)'|(\S+))\s*\|\s*jq\b/.exec(cmd);
7838
- if (!m) return null;
7839
- const filePath = m[1] ?? m[2] ?? m[3];
7840
- if (!filePath) return null;
7841
- if (isTempPath(filePath)) return null;
7842
- if (!/\.(?:json|yaml|yml|toml)$/i.test(filePath)) return null;
7843
- return { filePath };
7842
+ if (m) {
7843
+ const filePath = m[1] ?? m[2] ?? m[3];
7844
+ if (filePath && !isTempPath(filePath) && /\.(?:json|yaml|yml|toml)$/i.test(filePath)) {
7845
+ return { filePath, isDirectJq: false };
7846
+ }
7847
+ }
7848
+ const jqDirect = /^jq(?:\s+(?:-[a-zA-Z]+|--[a-zA-Z0-9-]+(?:=\S+)?))*\s+(?:"[^"]*"|'[^']*'|(?:\.[a-zA-Z0-9_.*[\]]+))\s+(?:"([^"]+)"|'([^']+)'|(\S+))\s*$/.exec(cmd);
7849
+ if (jqDirect) {
7850
+ const filePath = jqDirect[1] ?? jqDirect[2] ?? jqDirect[3];
7851
+ if (filePath && !isTempPath(filePath) && /\.(?:json|yaml|yml|toml)$/i.test(filePath)) {
7852
+ return { filePath, isDirectJq: true };
7853
+ }
7854
+ }
7855
+ return null;
7856
+ }
7857
+ function extractPowerShellJsonPipeline(cmd) {
7858
+ let inner = cmd.trim();
7859
+ const w = POWERSHELL_WRAP_RE.exec(inner);
7860
+ if (w) {
7861
+ inner = (w[1] ?? w[2] ?? "").trim();
7862
+ }
7863
+ if (!/\bConvertFrom-Json\b/i.test(inner)) return null;
7864
+ const parseTarget = (segment) => {
7865
+ const readAll = /\[(?:System\.)?IO\.File\]::ReadAllText\(\s*['"]?([^'")\s]+)['"]?\s*\)/i.exec(segment);
7866
+ if (readAll) {
7867
+ const p = readAll[1];
7868
+ return p && /\.(?:json|txt|log|temp)$/i.test(p) ? p : null;
7869
+ }
7870
+ const tokens = segment.trim().split(/\s+/);
7871
+ const cmdlets = /* @__PURE__ */ new Set(["get-content", "gc", "cat", "type"]);
7872
+ const idx = tokens.findIndex((t) => cmdlets.has(t.toLowerCase()));
7873
+ if (idx === -1) return null;
7874
+ let argIdx = idx + 1;
7875
+ while (argIdx < tokens.length) {
7876
+ const tok = tokens[argIdx];
7877
+ if (!tok) break;
7878
+ if (tok.startsWith("-")) {
7879
+ const flag = tok.toLowerCase();
7880
+ if (flag === "-path" && argIdx + 1 < tokens.length) {
7881
+ const next = tokens[argIdx + 1];
7882
+ if (next && !next.startsWith("-")) {
7883
+ const clean2 = next.replace(/^['"]|['"]$/g, "");
7884
+ return /\.(?:json|txt|log|temp)$/i.test(clean2) ? clean2 : null;
7885
+ }
7886
+ }
7887
+ if ((flag === "-encoding" || flag === "-totalcount") && argIdx + 1 < tokens.length) {
7888
+ argIdx += 2;
7889
+ continue;
7890
+ }
7891
+ argIdx++;
7892
+ continue;
7893
+ }
7894
+ const clean = tok.replace(/^['"(]|['")]$/g, "");
7895
+ return /\.(?:json|txt|log|temp)$/i.test(clean) ? clean : null;
7896
+ }
7897
+ return null;
7898
+ };
7899
+ const pipeIdx = inner.search(/\|\s*ConvertFrom-Json\b/i);
7900
+ if (pipeIdx !== -1) {
7901
+ const upstream = inner.slice(0, pipeIdx).trim();
7902
+ return { filePath: parseTarget(upstream) };
7903
+ }
7904
+ const parenMatch = /ConvertFrom-Json\s*\(([^)]+)\)/i.exec(inner);
7905
+ if (parenMatch) {
7906
+ const inside = parenMatch[1] ?? "";
7907
+ return { filePath: parseTarget(inside) };
7908
+ }
7909
+ if (/ConvertFrom-Json\s*\(/i.test(inner)) {
7910
+ return { filePath: null };
7911
+ }
7912
+ return null;
7844
7913
  }
7845
7914
  function extractWslCatFile(cmd) {
7846
7915
  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);
@@ -8191,6 +8260,7 @@ function extractNodeFileRead(cmd) {
8191
8260
  const filePath = readSync2[1];
8192
8261
  if (isOrchestratorStateFile(filePath)) return null;
8193
8262
  if (isTempPath(filePath)) return null;
8263
+ if (new RegExp(`(?:writeFileSync|appendFileSync)\\(\\s*['"]${escapeRegExp(filePath)}['"]`).test(cmd)) return null;
8194
8264
  const { isDoc, isConfig, isSql } = classifyDocConfig(filePath);
8195
8265
  return { filePath, isDoc, isConfig, isSql };
8196
8266
  }
@@ -8456,10 +8526,7 @@ var CURL_VALUE_FLAGS = /* @__PURE__ */ new Set([
8456
8526
  "--range",
8457
8527
  "-r",
8458
8528
  "--interface",
8459
- // Options whose own value is a URL or a host. Leaving these out was the same defect as reading
8460
- // the first URL in the string: `curl --doh-url https://doh/ -o f https://target` answered with
8461
- // the DoH resolver rather than the file being fetched. `--url-query` belongs here too -- it
8462
- // appends query data to the request, it does not name the request target.
8529
+ // Options whose own value is a URL or a host. Leaving these out was the same defect as reading the first URL in the string: `curl --doh-url https://doh/ -o f https://target` answered with the DoH resolver rather than the file being fetched. `--url-query` belongs here too -- it appends query data to the request, it does not name the request target.
8463
8530
  "--url-query",
8464
8531
  "--doh-url",
8465
8532
  "--preproxy",
@@ -9532,11 +9599,25 @@ function preBashHandlerInner(event) {
9532
9599
  }
9533
9600
  const catJsonPipe = extractCatJsonPipe(cmd);
9534
9601
  if (catJsonPipe !== null) {
9535
- const { filePath } = catJsonPipe;
9602
+ const { filePath, isDirectJq } = catJsonPipe;
9536
9603
  const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
9537
9604
  recordStat("session_hint", 0, 0);
9605
+ const label = isDirectJq ? "`jq`" : "`cat | jq`";
9606
+ return contextOutput(
9607
+ label + ' loads the whole file. Use `token-goat json-query "' + hintPath + '" "<key>"` or `token-goat config-get "' + hintPath + '" KEY_NAME` to slice one value.'
9608
+ );
9609
+ }
9610
+ const psJsonPipe = extractPowerShellJsonPipeline(cmd);
9611
+ if (psJsonPipe !== null) {
9612
+ recordStat("session_hint", 0, 0);
9613
+ if (psJsonPipe.filePath) {
9614
+ const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, psJsonPipe.filePath, hintCwd) : psJsonPipe.filePath);
9615
+ return contextOutput(
9616
+ 'PowerShell `ConvertFrom-Json` pipeline detected. Use `token-goat json-query "' + hintPath + '" "<selector>"` to extract fields directly without shell conversion scripts.'
9617
+ );
9618
+ }
9538
9619
  return contextOutput(
9539
- '`cat | jq` loads the whole file. Use `token-goat config-get "' + hintPath + '" KEY_NAME` or `token-goat section "' + hintPath + '::sectionName"` to slice one value.'
9620
+ 'PowerShell `ConvertFrom-Json` pipeline detected. Use `token-goat json-query <file> "<selector>"` or `token-goat web-output` to extract fields directly.'
9540
9621
  );
9541
9622
  }
9542
9623
  const catResult = extractCatFile(cmd);
@@ -9907,6 +9988,25 @@ function recordBashFileReadsForSessionCache(cmd, cwd) {
9907
9988
  return;
9908
9989
  }
9909
9990
  }
9991
+ async function maybeEmitLargeUncompressedHint(cmd, output, exitCode, cwd, isUnwrapped, event, ansiResult) {
9992
+ const outputBytes = Buffer.byteLength(output, "utf-8");
9993
+ if (outputBytes < 4096 || process.env["TOKEN_GOAT_BASH_COMPRESS"] === "0" || exitCode !== null && exitCode !== 0 || // token-goat's own output is already the narrow form; telling the model to compress it is noise.
9994
+ /^\s*token-goat\s/.test(cmd) || event.raw["_tg_harness"] !== "vscode" && (isCompressibleSingleCommand(cmd) || !isUnwrapped)) {
9995
+ return null;
9996
+ }
9997
+ const key = `bash-uncompressed-4k:${event.sessionId ?? ""}:${shortFingerprint(cmd)}`;
9998
+ if (wasHintShown(key)) return null;
9999
+ markHintShown(key);
10000
+ recordStat("session_hint", 0, 0);
10001
+ const id = await storeBashOutput(cmd, output, exitCode ?? 0, cwd);
10002
+ const kb = Math.round(outputBytes / 1024);
10003
+ const compressable = !/["`$\r\n]/.test(cmd);
10004
+ const msg = `[tg] Output was ${kb}KB uncompressed; \`token-goat bash-output ${id}\` recalls it` + (compressable ? `, and \`token-goat compress -c "${displaySafeText(cmd)}"\` compresses the next run.` : ".");
10005
+ if (ansiResult !== null && ansiResult.hookType === "rewriteOutput") {
10006
+ return emitRewrite(msg + "\n" + fenceUntrusted(ansiResult.updatedOutput, UNTRUSTED_TOOL_TAG), "large uncompressed output hint", void 0, "counted-elsewhere");
10007
+ }
10008
+ return contextOutput(msg);
10009
+ }
9910
10010
  async function postBashHandler(event) {
9911
10011
  try {
9912
10012
  const rawCmdRaw = extractCommand(event);
@@ -10012,7 +10112,10 @@ async function postBashHandler(event) {
10012
10112
  const genericElision = await maybeElideServedGenericOutput(cmd, output, exitCode, cwd, cacheMinBytes);
10013
10113
  if (genericElision !== null) return genericElision;
10014
10114
  }
10015
- return maybeStripAnsiOnly(output) ?? passOutput();
10115
+ const ansiStripped = maybeStripAnsiOnly(output);
10116
+ const largeHint2 = await maybeEmitLargeUncompressedHint(cmd, output, exitCode, cwd, isUnwrapped, event, ansiStripped);
10117
+ if (largeHint2 !== null) return largeHint2;
10118
+ return ansiStripped ?? passOutput();
10016
10119
  }
10017
10120
  if (Buffer.byteLength(output, "utf-8") < cacheMinBytes) return passOutput();
10018
10121
  const cacheKey = isCurlGetCommand(cmd) ? extractCurlUrl(cmd) ?? cmd : stripOutputPipeline(cmd);
@@ -10032,6 +10135,8 @@ async function postBashHandler(event) {
10032
10135
  const curlHtmlFold = maybeFoldCurlHtml(cmd, output, id);
10033
10136
  if (curlHtmlFold !== null) return curlHtmlFold;
10034
10137
  const ansiOnly = maybeStripAnsiOnly(output);
10138
+ const largeHint = await maybeEmitLargeUncompressedHint(cmd, output, exitCode, cwd, isUnwrapped, event, ansiOnly);
10139
+ if (largeHint !== null) return largeHint;
10035
10140
  if (ansiOnly !== null) return ansiOnly;
10036
10141
  } catch {
10037
10142
  }
@@ -11171,7 +11276,7 @@ function buildSubagentBriefing() {
11171
11276
  }
11172
11277
  const tail = [];
11173
11278
  tail.push("");
11174
- 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.');
11279
+ 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.');
11175
11280
  tail.push("");
11176
11281
  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.');
11177
11282
  const withCacheIds = head.join("\n") + cacheIdsBlock + "\n" + tail.join("\n");
@@ -13,7 +13,7 @@ import {
13
13
  foldPath,
14
14
  projectConfigPath,
15
15
  runGit
16
- } from "./token-goat-chunk-PM76YS22.mjs";
16
+ } from "./token-goat-chunk-UBZCON6N.mjs";
17
17
  import {
18
18
  normalizeDarwinSystemAlias
19
19
  } from "./token-goat-chunk-ERTXEKB6.mjs";
@@ -1421,7 +1421,8 @@ var CONFIG_DEFAULTS = {
1421
1421
  image_shrink: {
1422
1422
  enabled: true,
1423
1423
  jpeg_quality: 75,
1424
- max_image_pixels: 16e6,
1424
+ // 16,000,000 used to reject a routine 24MP DSLR/phone photo outright -- the exact input this feature exists to shrink -- while the engine's own decode ceiling (MAX_DECODED_BYTES in image_engine.ts, 256MB at 4 bytes/pixel for a single frame) sits at 67,108,864px. 64,000,000 covers cameras well past 24MP (including 48MP phone sensors) with ~4.9% margin below that hard ceiling, which assertDecodableSize enforces independently of this value on every decode regardless of what this header check allows through. Measured on this engine (2026-09-17): a 24MP PNG decodes+shrinks in ~370ms, 60,000,516px in ~920ms, and 67,108,864px (the ceiling itself) in ~760ms -- all comfortably fast, so the new value is chosen for coverage headroom under the ceiling, not for decode-time cost. Decode time is not the cost that binds, though: memory is. This value is read off a header before anything is decoded, so what it really sets is how large a buffer a file's own declared dimensions may talk this hook into allocating -- at 4 bytes per pixel, raising it from 16,000,000 raised that peak from ~64MB to ~256MB, which is why it now sits flush against MAX_DECODED_BYTES rather than comfortably below it. And on the JPEG path there is no assertDecodableSize call at all: decodeJpeg hands the buffer to jpeg-js, so a JPEG decode is bounded by whatever maxResolutionInMP/maxMemoryUsageInMB that call passes -- a bound this codebase states only because decodeJpeg passes both explicitly rather than inheriting jpeg-js's own 100MP default, which is looser than the 67.1MP MAX_DECODED_BYTES allows.
1425
+ max_image_pixels: 64e6,
1425
1426
  screenshot_redirect: true,
1426
1427
  ocr_enabled: true,
1427
1428
  // Confidence is Tesseract's own 0-100 mean-word-confidence score. 65 is a deliberately
@@ -1566,7 +1567,7 @@ var CONFIG_DEFAULTS = {
1566
1567
  offline: false
1567
1568
  },
1568
1569
  mcp: {
1569
- confine_reads_to_project_root: true,
1570
+ confine_reads_to_project_root: false,
1570
1571
  allowed_roots: []
1571
1572
  },
1572
1573
  hint_stats: {
@@ -6,13 +6,13 @@ import {
6
6
  pptxOutline,
7
7
  pptxSlideText,
8
8
  pptxTextGrep
9
- } from "./token-goat-chunk-ASYEPR3S.mjs";
10
- import "./token-goat-chunk-MZDIJJ3R.mjs";
9
+ } from "./token-goat-chunk-W2GUUQAQ.mjs";
10
+ import "./token-goat-chunk-66224KCZ.mjs";
11
11
  import "./token-goat-chunk-XTQAOTSO.mjs";
12
12
  import "./token-goat-chunk-AH6QILZM.mjs";
13
- import "./token-goat-chunk-Y4AFKTHK.mjs";
14
- import "./token-goat-chunk-PM76YS22.mjs";
13
+ import "./token-goat-chunk-UBZCON6N.mjs";
15
14
  import "./token-goat-chunk-ERTXEKB6.mjs";
15
+ import "./token-goat-chunk-Y4AFKTHK.mjs";
16
16
  import "./token-goat-chunk-GMOUBOX4.mjs";
17
17
  import "./token-goat-chunk-A37V4PBF.mjs";
18
18
  export {
@@ -20,17 +20,17 @@ import {
20
20
  setOcrTimeoutForTesting,
21
21
  setTesseractEntryForTesting,
22
22
  verifyOcrLangCache
23
- } from "./token-goat-chunk-SFAS46RE.mjs";
24
- import "./token-goat-chunk-IVUQLQWN.mjs";
25
- import "./token-goat-chunk-K7F2BFIK.mjs";
23
+ } from "./token-goat-chunk-CICJFVIH.mjs";
24
+ import "./token-goat-chunk-26YUO7MP.mjs";
25
+ import "./token-goat-chunk-MWSVUKVV.mjs";
26
26
  import {
27
27
  DEFAULT_OCR_LANG,
28
28
  isSupportedOcrLang,
29
29
  resolveOcrLangs
30
- } from "./token-goat-chunk-S4XRY446.mjs";
30
+ } from "./token-goat-chunk-2VASS5VR.mjs";
31
31
  import "./token-goat-chunk-EEIDFMEM.mjs";
32
32
  import "./token-goat-chunk-OSUFN2FV.mjs";
33
- import "./token-goat-chunk-PM76YS22.mjs";
33
+ import "./token-goat-chunk-UBZCON6N.mjs";
34
34
  import "./token-goat-chunk-ERTXEKB6.mjs";
35
35
  import "./token-goat-chunk-GMOUBOX4.mjs";
36
36
  import "./token-goat-chunk-A37V4PBF.mjs";
@@ -10,13 +10,13 @@ import {
10
10
  import {
11
11
  createLazyModuleLoader
12
12
  } from "./token-goat-chunk-AH6QILZM.mjs";
13
+ import {
14
+ pushAll
15
+ } from "./token-goat-chunk-UBZCON6N.mjs";
13
16
  import {
14
17
  DocumentRefusedError,
15
18
  MAX_DOCUMENT_WORK_MILLIS
16
19
  } from "./token-goat-chunk-Y4AFKTHK.mjs";
17
- import {
18
- pushAll
19
- } from "./token-goat-chunk-PM76YS22.mjs";
20
20
  import {
21
21
  init_define_import_meta_env
22
22
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -332,6 +332,26 @@ function pushTextValue(runs, val) {
332
332
  runs.push(String(val["#text"]));
333
333
  }
334
334
  }
335
+ var MATH_PARA_RE = /<m:oMathPara(?:\s[^>]*)?>([\s\S]*?)<\/m:oMathPara>/g;
336
+ var MATH_RE = /<m:oMath(?:\s[^>]*)?>([\s\S]*?)<\/m:oMath>/g;
337
+ var MATH_TEXT_RE = /<m:t(?:\s[^>]*)?>([^<]*)<\/m:t>/g;
338
+ function mathRunText(fragment) {
339
+ let out = "";
340
+ for (const m of fragment.matchAll(MATH_TEXT_RE)) out += m[1];
341
+ return out;
342
+ }
343
+ function inlineMathRuns(xml, openRun, closeRun) {
344
+ const asRun = (text) => text.length > 0 ? `${openRun}${text}${closeRun}` : "";
345
+ const withParas = xml.replace(MATH_PARA_RE, (_whole, inner) => {
346
+ const lines = [];
347
+ for (const m of inner.matchAll(MATH_RE)) {
348
+ const text = mathRunText(m[1]);
349
+ if (text.length > 0) lines.push(text);
350
+ }
351
+ return asRun(lines.length > 0 ? lines.join(" ") : mathRunText(inner));
352
+ });
353
+ return withParas.replace(MATH_RE, (_whole, inner) => asRun(mathRunText(inner)));
354
+ }
335
355
  function collectTextRuns(node, tag, skipInside = []) {
336
356
  const runs = [];
337
357
  function walk(n) {
@@ -354,6 +374,21 @@ function collectTextRuns(node, tag, skipInside = []) {
354
374
  walk(node);
355
375
  return runs;
356
376
  }
377
+ function dropAlternateContentFallbacks(node) {
378
+ if (Array.isArray(node)) {
379
+ node.forEach(dropAlternateContentFallbacks);
380
+ return;
381
+ }
382
+ if (node === null || typeof node !== "object") return;
383
+ for (const [key, val] of Object.entries(node)) {
384
+ if (key === "mc:AlternateContent") {
385
+ for (const alt of Array.isArray(val) ? val : [val]) {
386
+ if (alt !== null && typeof alt === "object" && "mc:Choice" in alt && "mc:Fallback" in alt) delete alt["mc:Fallback"];
387
+ }
388
+ }
389
+ if (val !== null && typeof val === "object") dropAlternateContentFallbacks(val);
390
+ }
391
+ }
357
392
  function collectElements(node, tag, opts = {}) {
358
393
  const skip = opts.skipInside;
359
394
  const out = [];
@@ -413,7 +448,9 @@ export {
413
448
  ooxmlPartBudget,
414
449
  decodeZipEntry,
415
450
  parseOoxmlPart,
451
+ inlineMathRuns,
416
452
  collectTextRuns,
453
+ dropAlternateContentFallbacks,
417
454
  collectElements,
418
455
  collectParagraphTexts,
419
456
  sortNumberedParts