token-goat 2.8.1 → 2.8.3

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.
@@ -3,8 +3,9 @@ const require = __cjsRequire(import.meta.url);
3
3
  import {
4
4
  loadConfig,
5
5
  redactSecrets,
6
+ resolveIndexPath,
6
7
  stripAnsiCodes
7
- } from "./token-goat-chunk-ELDJRLHZ.mjs";
8
+ } from "./token-goat-chunk-6ODZ6PZK.mjs";
8
9
 
9
10
  // src/tool_filters/helpers.ts
10
11
  import * as fs from "node:fs";
@@ -1424,7 +1425,7 @@ function makeLanguageFilter(cfg) {
1424
1425
  var _GH_COPILOT_SPINNER_RE = /^\s*(?:Asking GitHub Copilot|Generating|Thinking|Fetching)\s*\.{0,3}\s*$/i;
1425
1426
  var _GH_COPILOT_BANNER_RE = /^\s*(?:Welcome to GitHub Copilot|Using GitHub Copilot|Authenticated as|GitHub Copilot\s+v\d+)/i;
1426
1427
  var _GH_COPILOT_DISCLAIMER_RE = /^\s*(?:Disclaimer:|This response was|GitHub Copilot|The commands?\s+(?:above|below)|Please review|Always review|Remember to|Note:|Tip:)/i;
1427
- var _AIDER_APPLYING_RE = /^\s*(?:Applying\s+edit(?:s)?(?:\s+to\s+\S+)?|Applied\s+edit\s+to\s+\S+)\s*\.{0,3}\s*$/i;
1428
+ var _AIDER_APPLYING_RE = /^\s*(?:Applying\s+edits?(?:\s+to\s+\S+)?|Applied\s+edit\s+to\s+\S+)\s*(?:\.{1,3})?\s*$/i;
1428
1429
  var _AIDER_TOKENS_RE = /^\s*Tokens:\s+\d[\d,]*\s+sent,\s+\d[\d,]*\s+received/i;
1429
1430
  var _AIDER_COST_RE = /^\s*Cost:\s+\$[\d.]+\s+message,\s+\$[\d.]+\s+session/i;
1430
1431
  var _AIDER_REPOMAP_RE = /^\s*(?:Repo-map:|Added\s+\S+\s+to\s+the\s+chat|Removed\s+\S+\s+from\s+the\s+chat|Loading\s+repo\s+map|Updating\s+repo\s+map|Scanning\s+repo\s+contents|Using\s+\d+\s+tokens\s+of\s+repo\s+map)/i;
@@ -4025,7 +4026,7 @@ var _TF_RESOURCE_COMPLETE_RE = /^[a-z0-9_.[\]"-]+: (?:Creation|Destruction|Modif
4025
4026
  var _TF_PLAN_ATTR_DIFF_RE = /^\s+[~+-]\s+\S/;
4026
4027
  var _TF_KNOWN_AFTER_APPLY_RE = /\(known after apply\)/;
4027
4028
  var _TF_INIT_PROVIDER_RE = /^\s*-\s+(?:Finding|Installing|Installed|Downloading|Locking)\s+\S+/i;
4028
- var _TF_SHOW_RESOURCE_HDR_RE = /^# (?:(?:module\.\S+\.)?[a-z][a-z0-9_]+\.[a-zA-Z0-9_.[\]-]+):$/;
4029
+ var _TF_SHOW_RESOURCE_HDR_RE = /^# (?:(?:module\.[^.\s]+\.)?[a-z][a-z0-9_]+\.[a-zA-Z0-9_.[\]-]+):$/;
4029
4030
  var _TF_SHOW_KEY_ATTR_RE = /^\s+(?:id|arn|name|region|account_id|bucket|type|instance_type|endpoint|address|hostname|dns_name|tags(?:_all)?)\s*=/;
4030
4031
  var TerraformFilter = class extends ToolFilter {
4031
4032
  name = "terraform";
@@ -9030,7 +9031,7 @@ var LOG_WARN_RE = /\b(WARN(?:ING)?)\b|\[WARN(?:ING)?\]|level=warn/i;
9030
9031
  var LOG_INFO_RE = /\b(INFO)\b|\[INFO\]|level=info/i;
9031
9032
  var LOG_DEBUG_RE = /\b(DEBUG|TRACE|VERBOSE)\b|\[DEBUG\]|\[TRACE\]|level=(?:debug|trace)/i;
9032
9033
  var LOG_ANY_RE = /\b(?:ERROR|FAIL(?:URE|ED)?|CRITICAL|EXCEPTION|FATAL|WARN(?:ING)?|INFO|DEBUG|TRACE|VERBOSE)\b|\[(?:ERROR|CRITICAL|FATAL|WARN(?:ING)?|INFO|DEBUG|TRACE)\]|level=(?:error|critical|fatal|warn|info|debug|trace)/i;
9033
- var TRACE_CONTINUATION_RE = /^\s+(?:at |File "|in |\w+Error:|\w+Exception:)|^\s+\w+[\w.]+\(.*\)$|^\s+\.{3}\s*\d+\s+more|^Caused by:|^During handling of the above exception/;
9034
+ var TRACE_CONTINUATION_RE = /^\s+(?:at |File "|in |\w+Error:|\w+Exception:)|^\s+\w+[\w.]+\([^)\r\n]*\)$|^\s+\.{3}\s*\d+\s+more|^Caused by:|^During handling of the above exception/;
9034
9035
  function scoreLogLine(line) {
9035
9036
  if (LOG_LEVEL_RE.test(line)) return 1;
9036
9037
  if (LOG_WARN_RE.test(line)) return 0.5;
@@ -9846,8 +9847,8 @@ function gitPositionalArgs(args) {
9846
9847
  }
9847
9848
  return out;
9848
9849
  }
9849
- var _GIT_CRLF_MODERN_RE = /^warning: in the working copy of '.*', (?:LF will be replaced by CRLF|CRLF will be replaced by LF) the next time Git touches it\.?\r?$/m;
9850
- var _GIT_CRLF_WARNING_RE = /^warning: (?:LF will be replaced by CRLF|CRLF will be replaced by LF) in .*\.?\r?$/;
9850
+ var _GIT_CRLF_MODERN_RE = /^warning: in the working copy of '[^']+', (?:LF will be replaced by CRLF|CRLF will be replaced by LF) the next time Git touches it\.?\r?$/m;
9851
+ var _GIT_CRLF_WARNING_RE = /^warning: (?:LF will be replaced by CRLF|CRLF will be replaced by LF) in [^\r\n]+\.?\r?$/;
9851
9852
  var _GIT_CRLF_CONTINUATION_RE = /^The file will have its original line endings in your working directory\.?\r?$/;
9852
9853
  function _stripGitCrlfWarnings(text) {
9853
9854
  if (!text.includes("will be replaced by") && !text.includes("original line endings") && !text.includes("next time Git touches it")) {
@@ -11793,7 +11794,7 @@ var KtlintFilter = class _KtlintFilter extends ToolFilter {
11793
11794
  }
11794
11795
  };
11795
11796
  var _SWIFTLINT_VIOLATION_RE = /^(.+\.swift):(\d+)(?::\d+)?: (warning|error|serious): (.+?) \(([a-z_]+)\)\s*$/i;
11796
- var _SWIFTLINT_PROGRESS_RE = /^(Linting Swift files|Loading configuration|Linting '|Done linting!|Resolved \d|warning: .+ is deprecated|Ignoring '.+' in '|\s*$)/i;
11797
+ var _SWIFTLINT_PROGRESS_RE = /^(?:Linting Swift files|Loading configuration|Linting '|Done linting!|Resolved \d|warning: [^\r\n]+ is deprecated|Ignoring '[^']+' in '|\s*$)/i;
11797
11798
  var _SWIFTLINT_SUMMARY_RE = /^Done linting!/i;
11798
11799
  var swiftlintFilter = makeLinterFilter({
11799
11800
  name: "swiftlint",
@@ -12043,7 +12044,7 @@ var _CPPCHECK_PROGRESS_RE = /^\d+\/\d+\s+files\s+checked\s+\d+%\s+done/;
12043
12044
  var _CPPCHECK_DIAGNOSTIC_RE = /^\[.+\.(?:c|cpp|cxx|cc|h|hpp|hxx):\d+\]:/;
12044
12045
  var _CPPCHECK_DIAG_NOLINE_RE = /^\[.+\]:\s*\((?:error|warning|style|performance|portability|information)\)/i;
12045
12046
  var _CPPCHECK_CONFIG_RE = /^(?:Checking\s+configuration|Active\s+checkers:|Enabled\s+checkers:|cppcheck:\s+(?:error:|warning:|note:))/i;
12046
- var _CPPCHECK_SUMMARY_RE = /^(?:\d+\s+(?:error|warning|style|performance|portability)s?(?:\s+(?:found|detected))?|No\s+errors\s+found|Done\s+processing|cppcheck:\s+.*(?:done|finished)|\d+\s+unique\s+error)/i;
12047
+ var _CPPCHECK_SUMMARY_RE = /^(?:\d+\s+(?:error|warning|style|performance|portability)s?(?:\s+(?:found|detected))?|No\s+errors\s+found|Done\s+processing|cppcheck:\s+[^\r\n]*(?:done|finished)|\d+\s+unique\s+error)/i;
12047
12048
  var CppcheckFilter = class extends ToolFilter {
12048
12049
  name = "cppcheck";
12049
12050
  binaries = /* @__PURE__ */ new Set(["cppcheck"]);
@@ -12215,14 +12216,14 @@ function dedupLines(lines, maxPerKey = 1, keyFn = (l) => l.trim()) {
12215
12216
  }
12216
12217
  var NPM_DEPRECATED_RE = /^npm warn deprecated\b/i;
12217
12218
  var NPM_NOTICE_RE = /^npm notice\b/i;
12218
- var NPM_NOTICE_LOCKFILE_RE = /^npm notice.*lock/i;
12219
+ var NPM_NOTICE_LOCKFILE_RE = /^npm notice[^\r\n]*lock/i;
12219
12220
  var NPM_ZERO_VULN_RE = /^found 0 vulnerabilities\b/i;
12220
12221
  var NPM_FUNDING_RE = /^\d+\s+packages? are looking for funding\b/i;
12221
12222
  var NPM_FUND_RUN_RE = /^\s*run `npm fund`/i;
12222
12223
  var NPM_WARN_RE = /^npm warn\b/i;
12223
12224
  var NPM_VERBOSE_RE = /^npm (?:timing|sill|http fetch|http request|http finish|verb)\b/i;
12224
12225
  var NPM_REIFY_RE = /^[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]\s/;
12225
- var YARN_PEER_DEP_RE = /^warning ".+ > .+" has (?:unmet|incorrect) peer dependency/i;
12226
+ var YARN_PEER_DEP_RE = /^warning "[^"\r\n]+ > [^"\r\n]+" has (?:unmet|incorrect) peer dependency/i;
12226
12227
  var YARN_PHASE_RE = /^\[\d+\/\d+\]/;
12227
12228
  var YARN_FETCH_PHASE_RE = /^\[2\/4\]/;
12228
12229
  var YARN_INFO_RE = /^info\b/i;
@@ -12233,7 +12234,7 @@ var YARN_BERRY_DONE_RE = /^➤\s+YN0000:\s+·\s+Done/;
12233
12234
  var YARN_BERRY_PREFIX_RE = /^➤\s+YN\d{4}:/;
12234
12235
  var PNPM_PLUS_BAR_RE = /^\++\s*$/;
12235
12236
  var PNPM_PROGRESS_RE = /^Progress:/i;
12236
- var PNPM_RESOLVER_PROGRESS_RE = /^\s*(?:Resolving|Downloading|Fetching)[:\s].*\d+\/\d+|\s+\d+\s+packages?\s+(?:fetched|resolved|downloaded|linked)/;
12237
+ var PNPM_RESOLVER_PROGRESS_RE = /^\s*(?:Resolving|Downloading|Fetching)[:\s][^\r\n]*\d+\/\d+|\s+\d+\s+packages?\s+(?:fetched|resolved|downloaded|linked)/;
12237
12238
  var PNPM_SUMMARY_RE = /^(?:Packages:|Already up to date|Progress:|WARN|ERR!|added|removed|changed)/i;
12238
12239
  var PNPM_LOCKFILE_RE = /^\s*(?:Lockfile|Saved|node_modules|symlink)/i;
12239
12240
  var PIP_VERBOSE_DEBUG_RE = /^(?:DEBUG|VERBOSE|TRACE)\b/;
@@ -12266,13 +12267,13 @@ var BUNDLER_USING_RE = /^Using\s+\S+\s+[\d.]+/;
12266
12267
  var BUNDLER_FETCH_INSTALL_RE = /^(?:Fetching|Installing)\s+\S+\s+[\d.]+/;
12267
12268
  var COMPOSER_INSTALL_RE = /^\s+- Installing \S+ \(/;
12268
12269
  var COMPOSER_DOWNLOADING_RE = /^\s+- Downloading \S+ \(/;
12269
- var COMPOSER_DOWNLOAD_PROGRESS_RE = /^\s+- (?:Installing|Downloading) .+\(\d+%\)/;
12270
+ var COMPOSER_DOWNLOAD_PROGRESS_RE = /^\s+- (?:Installing|Downloading) [^\r\n]+\(\d+%\)/;
12270
12271
  var COMPOSER_FUNDING_RE = /^\d+ packages? you are using are looking for funding/;
12271
12272
  var COMPOSER_WARNING_RE = /^\s*(?:Warning|Deprecation|deprecated|constraint):/i;
12272
12273
  var NUGET_INSTALLING_RE = /^\s*Installing\s+\S+\s+\d+\.\d+/i;
12273
12274
  var NUGET_RESTORING_RE = /^\s*Restoring packages for\b/i;
12274
12275
  var NUGET_OK_HTTPS_RE = /^\s*OK\s+https?:\/\//i;
12275
- var NUGET_ALREADY_INSTALLED_RE = /^\s*Package\s+\S+.*\bis already installed/i;
12276
+ var NUGET_ALREADY_INSTALLED_RE = /^\s*Package\s+\S+[^\r\n]*\bis already installed/i;
12276
12277
  var NUGET_SUCCESS_INSTALL_RE = /^\s*Successfully installed\s+/i;
12277
12278
  var PUB_KEEP_RE2 = /^(?:Resolving dependencies|Changed \d+|No dependencies changed|Got dependencies|Downloading packages|Building package executable)/;
12278
12279
  var PUB_PKG_LINE_RE2 = /^[+>!]\s+\S+\s+\S+/;
@@ -13278,7 +13279,7 @@ var PREAMBLE_RE = /^collecting\s/;
13278
13279
  var HEADER_RE = /^=+\s*(?:test session starts|FAILURES|ERRORS|short test summary info|warnings summary|slowest \d+ durations|\d+ failed|\d+ passed|\d+ error)\b/;
13279
13280
  var COV_TOTAL_RE = /^TOTAL\s+\d/;
13280
13281
  var WARN_DOCS_RE = /^\s*--\s+Docs:\s+https?:\/\//;
13281
- var WARN_MSG_RE = /^\s+\S.*:\d+:\s+\S.*Warning\b/;
13282
+ var WARN_MSG_RE = /^\s+\S[^:\r\n]*:\d+:\s+\S[^\r\n]*Warning\b/;
13282
13283
  var WARN_NODEID_RE = /^\S+::\S+/;
13283
13284
  var SLOW_DURATION_RE = /^\d+\.\d+s\s+(?:call|setup|teardown)\s+\S/;
13284
13285
  var FAIL_LINE_RE = /^(FAILED|ERROR|PASSED|SKIPPED|XFAIL|XPASS)\s+\S/;
@@ -13520,15 +13521,27 @@ var TOOL_FILTERS = [
13520
13521
  ...MISC_FILTERS
13521
13522
  ];
13522
13523
  var PROFILE_CAPS = { aggressive: 50, balanced: 200, minimal: 500 };
13524
+ function peelLeadingCd(argv, cwd) {
13525
+ if (argv.length < 3 || argv[0] !== "cd") return null;
13526
+ const sep = argv[2];
13527
+ if (sep !== "&&" && sep !== ";") return null;
13528
+ const remainder = argv.slice(3);
13529
+ if (remainder.length === 0) return null;
13530
+ const dir = argv[1];
13531
+ return { argv: remainder, cwd: cwd === void 0 ? void 0 : resolveIndexPath(dir, cwd) };
13532
+ }
13523
13533
  function selectFilter(argv, cwd) {
13524
13534
  if (argv.length === 0) return null;
13525
- let resolved = stripPrefixes(argv);
13535
+ const peeled = peelLeadingCd(argv, cwd);
13536
+ const effectiveArgv = peeled !== null ? peeled.argv : argv;
13537
+ const effectiveCwd = peeled !== null ? peeled.cwd : cwd;
13538
+ let resolved = stripPrefixes(effectiveArgv);
13526
13539
  if (resolved.length === 0) {
13527
- resolved = argv.slice(0, 1);
13540
+ resolved = effectiveArgv.slice(0, 1);
13528
13541
  if (resolved.length === 0) return null;
13529
13542
  }
13530
- if (cwd !== void 0) {
13531
- const scriptArgv = resolvePackageManagerScript(resolved, cwd);
13543
+ if (effectiveCwd !== void 0) {
13544
+ const scriptArgv = resolvePackageManagerScript(resolved, effectiveCwd);
13532
13545
  if (scriptArgv !== null) {
13533
13546
  const scriptResolved = stripPrefixes(scriptArgv);
13534
13547
  if (scriptResolved.length > 0) {
@@ -23,7 +23,7 @@ import {
23
23
  summarizeOutputDelta,
24
24
  summarizeResidentContext,
25
25
  taskListPruneHint
26
- } from "./token-goat-chunk-XEDQH5DA.mjs";
26
+ } from "./token-goat-chunk-4HIMCBYK.mjs";
27
27
  import {
28
28
  BODY_FIRST_TOOL_RESPONSE_KEYS,
29
29
  OUTPUT_FIRST_TOOL_RESPONSE_KEYS,
@@ -41,6 +41,7 @@ import {
41
41
  contextOutput,
42
42
  countSymbols,
43
43
  denyOutput,
44
+ emitRewrite,
44
45
  enqueueDirtyPathSafe,
45
46
  ensureWorkerAlive,
46
47
  estimateTokens,
@@ -109,6 +110,7 @@ import {
109
110
  saveSessionState,
110
111
  scanForInjectionPatterns,
111
112
  serializeOutput,
113
+ sessionOutputBodyBytes,
112
114
  sessionSidecarPath,
113
115
  setLastTabContext,
114
116
  shrinkImage,
@@ -118,7 +120,7 @@ import {
118
120
  wasCliReadThisSession,
119
121
  wasFileReadThisSession,
120
122
  wasHintShown
121
- } from "./token-goat-chunk-2G6RAB4G.mjs";
123
+ } from "./token-goat-chunk-PWVXXPCC.mjs";
122
124
  import {
123
125
  canRunWrappedShell,
124
126
  compressOutput,
@@ -129,8 +131,9 @@ import {
129
131
  isRewriteWorthwhile,
130
132
  resolveMinNetSavingsBytes,
131
133
  shlexSplit
132
- } from "./token-goat-chunk-7JDXDERZ.mjs";
134
+ } from "./token-goat-chunk-EFF2XCLB.mjs";
133
135
  import {
136
+ PER_FILE_COUNTERFACTUAL_CEILING,
134
137
  VERSION,
135
138
  detectHarness,
136
139
  detectLanguage,
@@ -149,7 +152,7 @@ import {
149
152
  runGit,
150
153
  shortFingerprint,
151
154
  toKB
152
- } from "./token-goat-chunk-ELDJRLHZ.mjs";
155
+ } from "./token-goat-chunk-6ODZ6PZK.mjs";
153
156
 
154
157
  // src/hooks_grep.ts
155
158
  function grepIntInput(toolInput, key) {
@@ -213,8 +216,10 @@ function foldGrepContentHandler(event) {
213
216
  return passOutput();
214
217
  }
215
218
  if (toolInput["-n"] === false) return passOutput();
216
- const text = extractToolResponseField(event.raw, OUTPUT_FIRST_TOOL_RESPONSE_KEYS);
217
- if (!text) return passOutput();
219
+ const rawText = extractToolResponseField(event.raw, OUTPUT_FIRST_TOOL_RESPONSE_KEYS);
220
+ if (!rawText) return passOutput();
221
+ const redacted = redactSecrets(rawText);
222
+ const text = redacted.text;
218
223
  const rawLines = text.split(/\r\n|\r|\n/);
219
224
  const parsed = [];
220
225
  for (const line of rawLines) {
@@ -257,6 +262,7 @@ function foldGrepContentHandler(event) {
257
262
  }
258
263
  const bytesDelta = originalBytes - rewrittenBytes;
259
264
  recordStat("grep:fold", bytesDelta, Math.round(bytesDelta / 4));
265
+ if (redacted.count > 0) recordStat("secret_redacted", 0, redacted.count, void 0, "grep");
260
266
  return { hookType: "rewriteOutput", updatedOutput: rewritten };
261
267
  } catch {
262
268
  return passOutput();
@@ -620,7 +626,7 @@ import crypto from "node:crypto";
620
626
  var TRACKED_SKILL = "token-goat";
621
627
  var MAX_COMMANDS_SHOWN = 8;
622
628
  async function currentCommandNames() {
623
- const { buildProgram } = await import("./token-goat-chunk-Y2SYNH3S.mjs");
629
+ const { buildProgram } = await import("./token-goat-chunk-4OM2Q2SX.mjs");
624
630
  return flattenCommandNames(buildCommandManifest(buildProgram()));
625
631
  }
626
632
  async function recordSkillVersionSnapshot(sessionId, skillName) {
@@ -7030,15 +7036,22 @@ function postFetchHandler(event) {
7030
7036
  if (injectionMatches.length > 0) {
7031
7037
  recordStat("injection_detected", 0, 0, void 0, injectionMatches.join(","));
7032
7038
  }
7039
+ const bodyRedacted = body ? redactSecrets(body) : { text: body, count: 0 };
7033
7040
  if (!event.sessionId) {
7034
7041
  if (injectionMatches.length > 0) {
7035
- return { hookType: "rewriteOutput", updatedOutput: fenceUntrustedContent(body, injectionMatches) };
7042
+ return emitRewrite(fenceUntrustedContent(bodyRedacted.text, injectionMatches), "fetch");
7043
+ }
7044
+ if (bodyRedacted.count > 0) {
7045
+ return emitRewrite(bodyRedacted.text, "fetch");
7036
7046
  }
7037
7047
  return passOutput();
7038
7048
  }
7039
7049
  if (!body || body.length < 1024) {
7040
7050
  if (injectionMatches.length > 0) {
7041
- return { hookType: "rewriteOutput", updatedOutput: fenceUntrustedContent(body, injectionMatches) };
7051
+ return emitRewrite(fenceUntrustedContent(bodyRedacted.text, injectionMatches), "fetch");
7052
+ }
7053
+ if (bodyRedacted.count > 0) {
7054
+ return emitRewrite(bodyRedacted.text, "fetch");
7042
7055
  }
7043
7056
  return passOutput();
7044
7057
  }
@@ -7054,8 +7067,9 @@ function postFetchHandler(event) {
7054
7067
  }
7055
7068
  const cacheId = storeWebOutput(url, storedBody, `${url}\0${prompt}`, storedBody !== body ? body : void 0);
7056
7069
  recordWebFetch(url, prompt, cacheId);
7070
+ const storedRedacted = storedBody === body ? bodyRedacted : redactSecrets(storedBody);
7057
7071
  if (injectionMatches.length > 0) {
7058
- return { hookType: "rewriteOutput", updatedOutput: fenceUntrustedContent(storedBody, injectionMatches) };
7072
+ return emitRewrite(fenceUntrustedContent(storedRedacted.text, injectionMatches), "fetch");
7059
7073
  }
7060
7074
  if (storedBody !== body) {
7061
7075
  const noticeFor = (id) => `
@@ -7072,9 +7086,12 @@ function postFetchHandler(event) {
7072
7086
  })) {
7073
7087
  const bytesDelta = originalBytes - rewrittenBytes;
7074
7088
  recordStat("webfetch:compress", bytesDelta, Math.round(bytesDelta / 4));
7075
- return { hookType: "rewriteOutput", updatedOutput: storedBody + notice };
7089
+ return emitRewrite(storedRedacted.text + notice, "fetch");
7076
7090
  }
7077
7091
  }
7092
+ if (storedRedacted.count > 0) {
7093
+ return emitRewrite(storedRedacted.text, "fetch");
7094
+ }
7078
7095
  return passOutput();
7079
7096
  } catch {
7080
7097
  return passOutput();
@@ -7127,7 +7144,9 @@ async function preSkillHandler(event) {
7127
7144
  return passOutput();
7128
7145
  }
7129
7146
  if (await hasSessionOutput(event.sessionId, skillName)) {
7130
- recordStat("session_hint");
7147
+ const cachedBytes = await sessionOutputBodyBytes(event.sessionId, skillName);
7148
+ const denyCredit = cachedBytes !== null ? Math.min(cachedBytes, PER_FILE_COUNTERFACTUAL_CEILING) : 0;
7149
+ recordStat("session_hint", denyCredit, Math.round(denyCredit / 4));
7131
7150
  return denyOutput(
7132
7151
  "Skill `" + skillName + "` was already loaded this session and is cached. Use `token-goat skill-body " + skillName + " --compact` to recall the compact slice (or `token-goat skill-body " + skillName + "` for the full body) instead of re-loading it."
7133
7152
  );
@@ -9121,10 +9140,7 @@ function postBashOutputHandler(event) {
9121
9140
  })) {
9122
9141
  return passOutput();
9123
9142
  }
9124
- return {
9125
- hookType: "rewriteOutput",
9126
- updatedOutput: unchangedNotice
9127
- };
9143
+ return emitRewrite(unchangedNotice, "bashoutput", { kind: "bashoutput:unchanged", originalBytes: Buffer.byteLength(rawOutput, "utf-8") });
9128
9144
  }
9129
9145
  if (!output.startsWith(prior.output)) {
9130
9146
  storePollSnapshot(event.sessionId, bashId, output);
@@ -9143,10 +9159,7 @@ function postBashOutputHandler(event) {
9143
9159
  })) {
9144
9160
  return passOutput();
9145
9161
  }
9146
- return {
9147
- hookType: "rewriteOutput",
9148
- updatedOutput: `${deltaNotice}${delta}`
9149
- };
9162
+ return emitRewrite(`${deltaNotice}${delta}`, "bashoutput", { kind: "bashoutput:delta", originalBytes: Buffer.byteLength(rawOutput, "utf-8") });
9150
9163
  } catch {
9151
9164
  return passOutput();
9152
9165
  }
@@ -9201,10 +9214,7 @@ function postTaskOutputHandler(event) {
9201
9214
  })) {
9202
9215
  return passOutput();
9203
9216
  }
9204
- return {
9205
- hookType: "rewriteOutput",
9206
- updatedOutput: collapsed
9207
- };
9217
+ return emitRewrite(collapsed, "taskoutput", { kind: "taskoutput:collapse", originalBytes: Buffer.byteLength(rawOutput, "utf-8") });
9208
9218
  }
9209
9219
  if (output === prior.output) {
9210
9220
  storePollSnapshot2(event.sessionId, taskId, output);
@@ -9218,10 +9228,7 @@ function postTaskOutputHandler(event) {
9218
9228
  })) {
9219
9229
  return passOutput();
9220
9230
  }
9221
- return {
9222
- hookType: "rewriteOutput",
9223
- updatedOutput: unchangedNotice
9224
- };
9231
+ return emitRewrite(unchangedNotice, "taskoutput", { kind: "taskoutput:unchanged", originalBytes: Buffer.byteLength(rawOutput, "utf-8") });
9225
9232
  }
9226
9233
  if (!output.startsWith(prior.output)) {
9227
9234
  storePollSnapshot2(event.sessionId, taskId, output);
@@ -9241,10 +9248,7 @@ function postTaskOutputHandler(event) {
9241
9248
  })) {
9242
9249
  return passOutput();
9243
9250
  }
9244
- return {
9245
- hookType: "rewriteOutput",
9246
- updatedOutput: `${deltaNotice}${collapsedDelta}`
9247
- };
9251
+ return emitRewrite(`${deltaNotice}${collapsedDelta}`, "taskoutput", { kind: "taskoutput:delta", originalBytes: Buffer.byteLength(rawOutput, "utf-8") });
9248
9252
  } catch {
9249
9253
  return passOutput();
9250
9254
  }
@@ -9340,8 +9344,10 @@ var APPROVED_PLAN_MARKER = "## Approved Plan:";
9340
9344
  function postExitPlanModeHandler(event) {
9341
9345
  try {
9342
9346
  if (getToolName(event) !== "ExitPlanMode") return passOutput();
9343
- const output = extractToolResultText(event.raw);
9344
- if (!output) return passOutput();
9347
+ const rawOutput = extractToolResultText(event.raw);
9348
+ if (!rawOutput) return passOutput();
9349
+ const redacted = redactSecrets(rawOutput);
9350
+ const output = redacted.text;
9345
9351
  const markerIndex = output.indexOf(APPROVED_PLAN_MARKER);
9346
9352
  if (markerIndex === -1) return passOutput();
9347
9353
  const planValue = getToolInput(event)["plan"];
@@ -9770,11 +9776,16 @@ function postMcpHandler(event) {
9770
9776
  injectionMatches = [];
9771
9777
  }
9772
9778
  if (injectionMatches.length > 0) recordStat("injection_detected", 0, 0, void 0, injectionMatches.join(","));
9773
- const fenced = () => ({
9774
- hookType: "rewriteOutput",
9775
- updatedOutput: fenceUntrustedContent(redactSecrets(resultText).text, injectionMatches, UNTRUSTED_TOOL_TAG)
9776
- });
9777
- const passOrFence = () => injectionMatches.length > 0 ? fenced() : passOutput();
9779
+ const redactedResult = redactSecrets(resultText);
9780
+ const fenced = () => emitRewrite(
9781
+ fenceUntrustedContent(redactedResult.text, injectionMatches, UNTRUSTED_TOOL_TAG),
9782
+ "mcp"
9783
+ );
9784
+ const passOrFence = () => {
9785
+ if (injectionMatches.length > 0) return fenced();
9786
+ if (redactedResult.count > 0) return emitRewrite(redactedResult.text, "mcp");
9787
+ return passOutput();
9788
+ };
9778
9789
  if (!event.sessionId) return passOrFence();
9779
9790
  if (isMcpErrorResponse(event.raw)) return passOrFence();
9780
9791
  const readOnly = isMcpReadOnly(toolName, toolInput);
@@ -9799,10 +9810,10 @@ function postMcpHandler(event) {
9799
9810
  minNetSavingsBytes: resolveMinNetSavingsBytes()
9800
9811
  });
9801
9812
  if (worthwhile) {
9802
- return {
9803
- hookType: "rewriteOutput",
9804
- updatedOutput: injectionMatches.length > 0 ? `${notice}${fenceUntrustedContent(redactedBody, injectionMatches, UNTRUSTED_TOOL_TAG)}` : `${notice}${redactedBody}`
9805
- };
9813
+ return emitRewrite(
9814
+ injectionMatches.length > 0 ? `${notice}${fenceUntrustedContent(redactedBody, injectionMatches, UNTRUSTED_TOOL_TAG)}` : `${notice}${redactedBody}`,
9815
+ "mcp"
9816
+ );
9806
9817
  }
9807
9818
  }
9808
9819
  }
@@ -9848,14 +9859,32 @@ function preWebSearchDedupHandler(event) {
9848
9859
  }
9849
9860
  function postWebSearchHandler(event) {
9850
9861
  try {
9851
- if (getToolName(event) !== "WebSearch" || !event.sessionId) return passOutput();
9852
- const signature = webSearchSignatureInput(getToolInput(event));
9853
- if (signature === null) return passOutput();
9854
- if (isMcpErrorResponse(event.raw)) return passOutput();
9862
+ if (getToolName(event) !== "WebSearch") return passOutput();
9855
9863
  const resultText = extractToolResultText(event.raw);
9856
9864
  if (!resultText) return passOutput();
9865
+ let injectionMatches = [];
9866
+ try {
9867
+ if (loadConfig().injection.enabled) injectionMatches = scanForInjectionPatterns(resultText);
9868
+ } catch {
9869
+ injectionMatches = [];
9870
+ }
9871
+ if (injectionMatches.length > 0) recordStat("injection_detected", 0, 0, void 0, injectionMatches.join(","));
9872
+ const redacted = redactSecrets(resultText);
9873
+ const passOrFence = () => {
9874
+ if (injectionMatches.length > 0) {
9875
+ return emitRewrite(fenceUntrustedContent(redacted.text, injectionMatches), "websearch");
9876
+ }
9877
+ if (redacted.count > 0) {
9878
+ return emitRewrite(redacted.text, "websearch");
9879
+ }
9880
+ return passOutput();
9881
+ };
9882
+ if (!event.sessionId) return passOrFence();
9883
+ const signature = webSearchSignatureInput(getToolInput(event));
9884
+ if (signature === null) return passOrFence();
9885
+ if (isMcpErrorResponse(event.raw)) return passOrFence();
9857
9886
  storeMcpOutput(event.sessionId, "WebSearch", signature, resultText);
9858
- return passOutput();
9887
+ return passOrFence();
9859
9888
  } catch {
9860
9889
  return passOutput();
9861
9890
  }
@@ -10192,11 +10221,13 @@ function postAgentHandler(event) {
10192
10221
  if (typeof finishedPrompt === "string" && finishedPrompt !== "") {
10193
10222
  removeOutstandingAgentSpawn(finishedPrompt);
10194
10223
  }
10195
- const resultText = extractToolResultText(event.raw);
10224
+ const redactedReport = redactSecrets(extractToolResultText(event.raw));
10225
+ const resultText = redactedReport.text;
10196
10226
  const agentReportCfg = loadConfig().agent_report;
10197
10227
  if (!resultText || resultText.length < agentReportCfg.min_bytes) return passOutput();
10198
10228
  const id = storeMcpOutput(event.sessionId, "Agent", event.toolInput, resultText);
10199
10229
  if (id === null) return passOutput();
10230
+ if (redactedReport.count > 0) recordStat("secret_redacted", 0, redactedReport.count, void 0, "agent");
10200
10231
  recordStat("session_hint", 0, 0);
10201
10232
  const recallHint = `token-goat mcp-output ${id} --full`;
10202
10233
  const notice = `[token-goat] This subagent report (${toKB(resultText.length)}KB) is cached for later recall: ${recallHint}`;