token-goat 2.9.6 → 2.9.8

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.
@@ -4,14 +4,14 @@ import {
4
4
  buildEvent,
5
5
  relay,
6
6
  relayInProcess
7
- } from "./token-goat-chunk-EIZYCVBM.mjs";
7
+ } from "./token-goat-chunk-XYLPMQ6I.mjs";
8
8
  import {
9
9
  MAX_STDIN_BYTES,
10
10
  readStdinJson
11
- } from "./token-goat-chunk-7GJBID7S.mjs";
12
- import "./token-goat-chunk-3HJQR4OO.mjs";
13
- import "./token-goat-chunk-LXIC7MTW.mjs";
14
- import "./token-goat-chunk-T2OE7MYM.mjs";
11
+ } from "./token-goat-chunk-VEEHPNBV.mjs";
12
+ import "./token-goat-chunk-TXZY7C24.mjs";
13
+ import "./token-goat-chunk-REHUP2OE.mjs";
14
+ import "./token-goat-chunk-JZYJH76S.mjs";
15
15
  import "./token-goat-chunk-EEIDFMEM.mjs";
16
16
  import "./token-goat-chunk-A37V4PBF.mjs";
17
17
  export {
@@ -2,7 +2,7 @@ import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
3
  import {
4
4
  detectHarness
5
- } from "./token-goat-chunk-T2OE7MYM.mjs";
5
+ } from "./token-goat-chunk-JZYJH76S.mjs";
6
6
  import {
7
7
  init_define_import_meta_env
8
8
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -47,6 +47,7 @@ import {
47
47
  getFilePath,
48
48
  getHarnessName,
49
49
  globalDbPath,
50
+ hasUnquotedOperator,
50
51
  isAutoTriggerMultiplierExplicit,
51
52
  isCaseInsensitiveFs,
52
53
  isCodeFenceDelimiter,
@@ -100,7 +101,7 @@ import {
100
101
  toDisplayPath,
101
102
  toKB,
102
103
  withFileLock
103
- } from "./token-goat-chunk-T2OE7MYM.mjs";
104
+ } from "./token-goat-chunk-JZYJH76S.mjs";
104
105
  import {
105
106
  registerReset
106
107
  } from "./token-goat-chunk-EEIDFMEM.mjs";
@@ -6688,11 +6689,15 @@ function getFileLineRanges(filePath) {
6688
6689
  return _fileLineRanges.get(foldPath(normalizePath(filePath))) ?? [];
6689
6690
  }
6690
6691
  var MAX_SERVED_OUTPUTS_PER_FILE = 8;
6692
+ var GENERIC_SERVED_OUTPUT_KEY = "\0<bash-generic-served>";
6693
+ var GENERIC_SERVED_OUTPUT_FOLDED_KEY = foldPath(normalizePath(GENERIC_SERVED_OUTPUT_KEY));
6694
+ var MAX_GENERIC_SERVED_OUTPUTS = 32;
6691
6695
  function recordFileServedOutput(filePath, outputId) {
6692
6696
  const key = foldPath(normalizePath(filePath));
6697
+ const cap = key === GENERIC_SERVED_OUTPUT_FOLDED_KEY ? MAX_GENERIC_SERVED_OUTPUTS : MAX_SERVED_OUTPUTS_PER_FILE;
6693
6698
  const ids = (_fileServedOutputs.get(key) ?? []).filter((id) => id !== outputId);
6694
6699
  ids.push(outputId);
6695
- if (ids.length > MAX_SERVED_OUTPUTS_PER_FILE) ids.splice(0, ids.length - MAX_SERVED_OUTPUTS_PER_FILE);
6700
+ if (ids.length > cap) ids.splice(0, ids.length - cap);
6696
6701
  _fileServedOutputs.set(key, ids);
6697
6702
  }
6698
6703
  function getFileServedOutputs(filePath) {
@@ -7624,6 +7629,7 @@ function isPsMultilineSystemQuery(cmd) {
7624
7629
  }
7625
7630
  function getMonitoringRecallHint(cmd) {
7626
7631
  const trimmed = cmd.trim();
7632
+ if (hasUnquotedOperator(trimmed, ["&&", "||", ";"])) return null;
7627
7633
  for (const { pattern, recallHint } of MONITORING_COMMAND_PATTERNS) {
7628
7634
  if (pattern.test(trimmed)) return recallHint;
7629
7635
  }
@@ -8191,13 +8197,15 @@ function mergeLineRanges(disk, mem) {
8191
8197
  }
8192
8198
  return Array.from(byPath.entries());
8193
8199
  }
8200
+ var GENERIC_SERVED_OUTPUT_FOLDED_KEY2 = foldPath(normalizePath(GENERIC_SERVED_OUTPUT_KEY));
8194
8201
  function mergeServedOutputs(disk, mem) {
8195
8202
  const byPath = /* @__PURE__ */ new Map();
8196
8203
  for (const [filePath, ids] of disk) byPath.set(filePath, [...ids]);
8197
8204
  for (const [filePath, ids] of mem) {
8198
8205
  const prev = byPath.get(filePath) ?? [];
8199
8206
  const merged = [...prev.filter((id) => !ids.includes(id)), ...ids];
8200
- if (merged.length > MAX_SERVED_OUTPUTS_PER_FILE) merged.splice(0, merged.length - MAX_SERVED_OUTPUTS_PER_FILE);
8207
+ const cap = filePath === GENERIC_SERVED_OUTPUT_FOLDED_KEY2 ? MAX_GENERIC_SERVED_OUTPUTS : MAX_SERVED_OUTPUTS_PER_FILE;
8208
+ if (merged.length > cap) merged.splice(0, merged.length - cap);
8201
8209
  byPath.set(filePath, merged);
8202
8210
  }
8203
8211
  return Array.from(byPath.entries());
@@ -9939,7 +9947,7 @@ function pruneShrinkCache() {
9939
9947
  }
9940
9948
  }
9941
9949
  async function finalizeShrinkResult(result, filePath) {
9942
- const basename12 = path6.basename(filePath);
9950
+ const basename12 = displaySafePath(path6.basename(filePath));
9943
9951
  const shrinkSaved = result.originalBytes - result.shrunkBytes;
9944
9952
  const tier = loadConfig().image_shrink.vision_tier;
9945
9953
  recordStat("image_shrink", shrinkSaved, visionTokensSaved(result.originalWidth, result.originalHeight, result.width, result.height, tier), void 0, basename12);
@@ -11061,7 +11069,7 @@ function _pathPriorityPenalty(filePath) {
11061
11069
 
11062
11070
  // src/parser_fingerprint.ts
11063
11071
  init_define_import_meta_env();
11064
- var PARSER_FINGERPRINT = "567346f98dadd8cb";
11072
+ var PARSER_FINGERPRINT = "d96c01d5957651c0";
11065
11073
 
11066
11074
  // src/parser.ts
11067
11075
  init_define_import_meta_env();
@@ -14798,16 +14806,26 @@ ${commented}`);
14798
14806
  // src/parser.ts
14799
14807
  var _require3 = createRequire3(import.meta.url);
14800
14808
  var _parserCtor;
14809
+ var _parserCtorError = null;
14810
+ var _parserCtorOverride = void 0;
14801
14811
  var _grammarCache = /* @__PURE__ */ new Map();
14802
14812
  function loadParserCtor() {
14813
+ if (_parserCtorOverride !== void 0) return _parserCtorOverride;
14803
14814
  if (_parserCtor !== void 0) return _parserCtor;
14804
14815
  try {
14805
14816
  _parserCtor = _require3("tree-sitter");
14806
- } catch {
14817
+ } catch (e) {
14807
14818
  _parserCtor = null;
14819
+ _parserCtorError = e instanceof Error ? e : new Error(String(e));
14808
14820
  }
14809
14821
  return _parserCtor;
14810
14822
  }
14823
+ function treeSitterCoreAvailable() {
14824
+ return loadParserCtor() !== null;
14825
+ }
14826
+ function treeSitterCoreLoadError() {
14827
+ return _parserCtorError;
14828
+ }
14811
14829
  var CPP_HEADER_SNIFF_RE = /\bclass\s+\w|\bnamespace\s+\w|\btemplate\s*<|::\s*\w|\b(?:public|private|protected)\s*:/;
14812
14830
  var MAX_SYMBOL_BODY_CHARS = SYMBOL_BODY_CHAR_CAP;
14813
14831
  function boundSymbolBody(body) {
@@ -18768,6 +18786,9 @@ var FILE_TYPE_THRESHOLDS = {
18768
18786
  // always intercept (any size)
18769
18787
  html: 5e4,
18770
18788
  txt: 2e4,
18789
+ log: 1e4,
18790
+ svg: 8e3,
18791
+ xml: 2e4,
18771
18792
  csv: 1e4,
18772
18793
  tsv: 1e4,
18773
18794
  transcript: 1e4,
@@ -18835,8 +18856,9 @@ ${headings.join("\n")}` : ""].filter(Boolean).join("\n")
18835
18856
  }
18836
18857
  function handleTxt(filePath, content, contentLengthHint) {
18837
18858
  const length = contentLengthHint ?? content.length;
18838
- if (length < FILE_TYPE_THRESHOLDS.txt) return { shouldBlock: false, message: "" };
18839
18859
  const isLog = /\.(log|out|err|trace)$/i.test(filePath) || /[\\/]logs[\\/]/.test(filePath);
18860
+ const threshold = isLog ? FILE_TYPE_THRESHOLDS.log : FILE_TYPE_THRESHOLDS.txt;
18861
+ if (length < threshold) return { shouldBlock: false, message: "" };
18840
18862
  const recall = isLog ? `Log file \u2014 use Read with offset/limit params, or: token-goat bash-output --file "${filePath}" --tail 100 --grep "error|ERROR"` : "Use Read with offset and limit params to sample specific line ranges.";
18841
18863
  if (previewUnavailable(content, length)) {
18842
18864
  return {
@@ -18868,6 +18890,64 @@ ${fenceUntrustedFileContent(preview)}
18868
18890
  ${recall}`
18869
18891
  };
18870
18892
  }
18893
+ function handleSvg(filePath, content, contentLengthHint) {
18894
+ const length = contentLengthHint ?? content.length;
18895
+ if (length < FILE_TYPE_THRESHOLDS.svg) return { shouldBlock: false, message: "" };
18896
+ if (previewUnavailable(content, length)) {
18897
+ return {
18898
+ shouldBlock: true,
18899
+ message: [
18900
+ `Large SVG file (${formatBytes(length)}) \u2014 too large to preview (exceeds the in-hook scan cap).`,
18901
+ `Inspect structure: token-goat xml-outline "${filePath}"`,
18902
+ `Query layers/elements: token-goat xml-query "${filePath}" "//g[@id]"`
18903
+ ].join("\n")
18904
+ };
18905
+ }
18906
+ const titleMatch = content.match(/<title[^>]*>([^<]*)<\/title>/i);
18907
+ const title = titleMatch ? titleMatch[1]?.trim() : "";
18908
+ const groupIds = [];
18909
+ const idRegex = /<g[^>]*\bid=["']([^"']+)["']/gi;
18910
+ let match;
18911
+ while ((match = idRegex.exec(content)) !== null && groupIds.length < 10) {
18912
+ if (match[1]) groupIds.push(match[1]);
18913
+ }
18914
+ const preview = [
18915
+ title ? `Title: ${title}` : "",
18916
+ groupIds.length > 0 ? `Layer/Group IDs: ${groupIds.join(", ")}` : ""
18917
+ ].filter(Boolean).join("\n");
18918
+ return {
18919
+ shouldBlock: true,
18920
+ message: [
18921
+ `Large SVG/diagram file (${formatBytes(length)}) \u2014 raw coordinate paths flood context.`,
18922
+ preview ? fenceUntrustedFileContent(preview) : "",
18923
+ `Inspect structure: token-goat xml-outline "${filePath}"`,
18924
+ `Query elements: token-goat xml-query "${filePath}" "//g[@id]"`,
18925
+ `Search text labels: token-goat grep "<text>" --glob "${filePath}"`
18926
+ ].filter(Boolean).join("\n")
18927
+ };
18928
+ }
18929
+ function handleXml(filePath, content, contentLengthHint) {
18930
+ const length = contentLengthHint ?? content.length;
18931
+ if (length < FILE_TYPE_THRESHOLDS.xml) return { shouldBlock: false, message: "" };
18932
+ if (previewUnavailable(content, length)) {
18933
+ return {
18934
+ shouldBlock: true,
18935
+ message: [
18936
+ `Large XML file (${formatBytes(length)}) \u2014 too large to preview (exceeds the in-hook scan cap).`,
18937
+ `Inspect structure: token-goat xml-outline "${filePath}"`,
18938
+ `Query nodes: token-goat xml-query "${filePath}" "<selector>"`
18939
+ ].join("\n")
18940
+ };
18941
+ }
18942
+ return {
18943
+ shouldBlock: true,
18944
+ message: [
18945
+ `Large XML file (${formatBytes(length)}).`,
18946
+ `Inspect hierarchy: token-goat xml-outline "${filePath}"`,
18947
+ `Query specific elements: token-goat xml-query "${filePath}" "<selector>"`
18948
+ ].join("\n")
18949
+ };
18950
+ }
18871
18951
  function handleOfficeBinary(filePath) {
18872
18952
  const filename = filePath.split(/[\\/]/).pop() || "";
18873
18953
  const parts = filename.split(".");
@@ -18986,6 +19066,8 @@ function dispatchFileTypeHandler(filePath, content, contentLengthHint) {
18986
19066
  if (["md", "mdx", "markdown", "rst"].includes(ext)) return null;
18987
19067
  const effectiveLength = contentLengthHint ?? content.length;
18988
19068
  if (ext === "pdf") return handlePdf(filePath, effectiveLength);
19069
+ if (ext === "svg") return handleSvg(filePath, content, effectiveLength);
19070
+ if (ext === "xml") return handleXml(filePath, content, effectiveLength);
18989
19071
  if (["html", "htm", "xhtml"].includes(ext)) return handleHtml(filePath, content, effectiveLength);
18990
19072
  if (["txt", "log", "out", "err", "trace"].includes(ext)) return handleTxt(filePath, content, effectiveLength);
18991
19073
  if (ext === "xlsx") return handleXlsx(filePath);
@@ -19335,7 +19417,7 @@ function buildDeltaCapsule(projectRoot, limit = 8) {
19335
19417
  }).slice(0, limit);
19336
19418
  if (changed.length === 0) return null;
19337
19419
  return `Cross-session evidence changed since it was cached:
19338
- ${changed.map((entry) => `- ${entry.source} (use a fresh surgical read)`).join("\n")}`;
19420
+ ${changed.map((entry) => `- ${displaySafePath(entry.source)} (use a fresh surgical read)`).join("\n")}`;
19339
19421
  }
19340
19422
 
19341
19423
  // src/notebook_compact.ts
@@ -20032,7 +20114,7 @@ function isSourceExtension(basename12) {
20032
20114
  return language === "apex" || language === "salesforce_metadata" || language === "salesforce_markup";
20033
20115
  }
20034
20116
  var BINARY_FILE_TYPE_EXTS = /* @__PURE__ */ new Set(["pdf", "docx", "xlsx", "pptx", "odt", "ods", "ott", "odp"]);
20035
- var TEXT_FILE_TYPE_EXTS = /* @__PURE__ */ new Set(["html", "htm", "xhtml", "txt", "log", "out", "err", "trace", "csv", "tsv", "vtt", "srt"]);
20117
+ var TEXT_FILE_TYPE_EXTS = /* @__PURE__ */ new Set(["html", "htm", "xhtml", "txt", "log", "out", "err", "trace", "csv", "tsv", "vtt", "srt", "svg", "xml"]);
20036
20118
  var DISPATCHED_FILE_TYPE_EXTS = /* @__PURE__ */ new Set([...BINARY_FILE_TYPE_EXTS, ...TEXT_FILE_TYPE_EXTS]);
20037
20119
  function isDispatchedFileType(basename12) {
20038
20120
  return DISPATCHED_FILE_TYPE_EXTS.has(path21.extname(basename12).slice(1).toLowerCase());
@@ -20051,7 +20133,7 @@ function surgicalHint(filePath, basename12, lineCount) {
20051
20133
  }
20052
20134
  function detectSkillFile(filePath) {
20053
20135
  const match = filePath.match(/\.claude[\\/]skills[\\/]([^\\/]+)[\\/]SKILL\.md$/i);
20054
- return match ? match[1] : null;
20136
+ return match ? displaySafePath(match[1]) : null;
20055
20137
  }
20056
20138
  function buildLineDiffDetailed(oldContent, newContent, label) {
20057
20139
  const oldLines = oldContent.split("\n");
@@ -20196,7 +20278,7 @@ function preReadHandlerInner(event) {
20196
20278
  } catch {
20197
20279
  }
20198
20280
  }
20199
- const basename12 = path21.basename(normalized);
20281
+ const basename12 = displaySafePath(path21.basename(normalized));
20200
20282
  if (isLockFile(basename12)) {
20201
20283
  return denyOutput(
20202
20284
  'Lock files are rarely useful to read in full. Use `token-goat section "' + shown + '::<section>"` to extract a specific dependency, or read the relevant manifest instead.'
@@ -20257,7 +20339,7 @@ function preReadHandlerInner(event) {
20257
20339
  recordActualRead(event, normalized);
20258
20340
  const fullSize = statSize(normalized) ?? 0;
20259
20341
  const savedBytes = counterfactualCredit(fullSize, compactBody.length);
20260
- recordStat("session_hint", savedBytes, savedTokensFromBytes(savedBytes));
20342
+ recordStat("session_hint", savedBytes, savedTokensFromBytes(savedBytes), void 0, "stable-doc-compact");
20261
20343
  return denyOutput(
20262
20344
  "Serving the extractive compact sidecar in place of the full file (source unchanged since the last `compact-doc` build):\n\n" + fenceUntrustedFileContent(compactBody) + '\n\nThis is a lossy extract, not the whole file: front matter and any prose before the first heading are dropped entirely, each section is cut to its opening sentences, and long code fences are truncated. If you need content it left out, re-read with offset/limit for a line window, or `token-goat section "' + shown + '::Heading"` for one section in full. Use `token-goat compact-doc "' + shown + '" --force` to rebuild it, or `token-goat compact-doc "' + shown + '" --show` to view it directly. ' + editAnywayHint(normalized)
20263
20345
  );
@@ -20274,7 +20356,7 @@ function preReadHandlerInner(event) {
20274
20356
  if (savedBytes >= NB_STRIP_MIN_SAVINGS) {
20275
20357
  recordActualRead(event, normalized);
20276
20358
  const nbCredit = counterfactualCredit(rawBytes.length, sidecarContent.length);
20277
- recordStat("session_hint", nbCredit, savedTokensFromBytes(nbCredit));
20359
+ recordStat("session_hint", nbCredit, savedTokensFromBytes(nbCredit), void 0, "notebook-strip");
20278
20360
  return denyOutput(
20279
20361
  "Serving the output-stripped notebook in place of the full file (code-cell outputs and execution counts removed; source and metadata preserved):\n\n" + fenceUntrustedFileContent(sidecarContent) + "\n\n" + editAnywayHint(normalized)
20280
20362
  );
@@ -20402,7 +20484,7 @@ function preReadHandlerInner(event) {
20402
20484
  if (snapDiff.kind === "diff") {
20403
20485
  recordActualRead(event, normalized);
20404
20486
  const artifactDiffCredit = counterfactualCredit(snapDiff.currentContent.length, snapDiff.diff.length);
20405
- recordStat("session_hint", artifactDiffCredit, savedTokensFromBytes(artifactDiffCredit));
20487
+ recordStat("session_hint", artifactDiffCredit, savedTokensFromBytes(artifactDiffCredit), void 0, "artifact-snapshot-diff");
20406
20488
  return denyOutput(
20407
20489
  "Content changed since last read of " + basename12 + ". Here is what changed:\n\n" + fenceUntrustedFileContent("```diff\n" + snapDiff.diff + "\n```") + "\n\n" + sessionArtifactRecall(normalized)
20408
20490
  );
@@ -20420,7 +20502,7 @@ function preReadHandlerInner(event) {
20420
20502
  recordActualRead(event, normalized);
20421
20503
  if (outputSize !== null && outputSize >= TASK_OUTPUT_DENY_BYTES) {
20422
20504
  const artifactDenyCredit = counterfactualCredit(outputSize);
20423
- recordStat("session_hint", artifactDenyCredit, savedTokensFromBytes(artifactDenyCredit));
20505
+ recordStat("session_hint", artifactDenyCredit, savedTokensFromBytes(artifactDenyCredit), void 0, "artifact-large-deny");
20424
20506
  return denyOutput(
20425
20507
  label + " is large (" + toKB(outputSize) + "KB). " + sessionArtifactRecall(normalized)
20426
20508
  );
@@ -20509,12 +20591,12 @@ function preReadHandlerInner(event) {
20509
20591
  if (config2.hints.reread_deny && !protectedRead) {
20510
20592
  if (wasFileTruncatedThisSession(normalized)) {
20511
20593
  if (estimateTruncatedLineCount(normalized) >= config2.hints.truncated_read_min_lines) {
20512
- recordStat("session_hint", rereadCredit, savedTokensFromBytes(rereadCredit));
20594
+ recordStat("session_hint", rereadCredit, savedTokensFromBytes(rereadCredit), void 0, "reread-truncated-deny");
20513
20595
  return denyOutput(truncatedReadDenyMessage(normalized));
20514
20596
  }
20515
20597
  }
20516
20598
  if (/\.(md|mdx|markdown|rst)$/i.test(basename12)) {
20517
- recordStat("session_hint", rereadCredit, savedTokensFromBytes(rereadCredit));
20599
+ recordStat("session_hint", rereadCredit, savedTokensFromBytes(rereadCredit), void 0, "reread-doc-deny");
20518
20600
  return denyOutput(
20519
20601
  'Markdown file already read this session. Use `token-goat section "' + shown + '::HeadingName"` to read one section.'
20520
20602
  );
@@ -20530,7 +20612,7 @@ function preReadHandlerInner(event) {
20530
20612
  }
20531
20613
  const hint = _isDocFile(normalized) ? 'Use `token-goat section "' + shown + '::SectionName"` to read one section.' : "Use token-goat read/section/symbol to re-read surgically.";
20532
20614
  if (config2.hints.reread_deny && !protectedRead && (rereadBytes >= config2.hints.reread_deny_min_bytes || reads >= 2)) {
20533
- recordStat("session_hint", rereadCredit, savedTokensFromBytes(rereadCredit));
20615
+ recordStat("session_hint", rereadCredit, savedTokensFromBytes(rereadCredit), void 0, "reread-count-deny");
20534
20616
  return denyOutput(
20535
20617
  shown + " was already read this session (" + reads + " " + plural + "). " + hint
20536
20618
  );
@@ -20555,7 +20637,7 @@ function preReadHandlerInner(event) {
20555
20637
  const hint = _isDocFile(normalized) ? 'Use `token-goat section "' + shown + '::SectionName"` to read one section.' : "Consider token-goat skeleton or token-goat section.";
20556
20638
  if (gateSize >= largeFileDenyBytes()) {
20557
20639
  const denyCredit = counterfactualCredit(size);
20558
- recordStat("session_hint", denyCredit, savedTokensFromBytes(denyCredit));
20640
+ recordStat("session_hint", denyCredit, savedTokensFromBytes(denyCredit), void 0, "large-file-deny");
20559
20641
  return denyOutput(
20560
20642
  shown + " is very large (" + kb + "KB). " + hint + " " + describeSliceAdvice(slice, normalized) + " " + editAnywayHint(normalized)
20561
20643
  );
@@ -21991,6 +22073,7 @@ export {
21991
22073
  clearCurlDownload,
21992
22074
  recordFileLineRange,
21993
22075
  getFileLineRanges,
22076
+ GENERIC_SERVED_OUTPUT_KEY,
21994
22077
  recordFileServedOutput,
21995
22078
  getFileServedOutputs,
21996
22079
  markFileTruncated,
@@ -22099,6 +22182,9 @@ export {
22099
22182
  PARSER_FINGERPRINT,
22100
22183
  stripLeadingAttributes2 as stripLeadingAttributes,
22101
22184
  IMPORT_RE2 as IMPORT_RE,
22185
+ treeSitterCoreAvailable,
22186
+ treeSitterCoreLoadError,
22187
+ isTreeSitterAvailable,
22102
22188
  yamlOpenQuoteAfter,
22103
22189
  yamlLineClosesQuote,
22104
22190
  lineOpenDelimiterAfter,
@@ -9,11 +9,12 @@ import {
9
9
  isBlobStale,
10
10
  loadBlob,
11
11
  storeBlob
12
- } from "./token-goat-chunk-3HJQR4OO.mjs";
12
+ } from "./token-goat-chunk-TXZY7C24.mjs";
13
13
  import {
14
14
  SYMBOL_BODY_CHAR_CAP,
15
15
  copilotCliMcpToolsDir,
16
16
  countNoun,
17
+ displaySafeText,
17
18
  extractErrorMessage,
18
19
  fingerprintFile,
19
20
  foldPath,
@@ -24,7 +25,7 @@ import {
24
25
  resolveIndexPath,
25
26
  shortFingerprint,
26
27
  toDisplayPath
27
- } from "./token-goat-chunk-T2OE7MYM.mjs";
28
+ } from "./token-goat-chunk-JZYJH76S.mjs";
28
29
  import {
29
30
  registerReset
30
31
  } from "./token-goat-chunk-EEIDFMEM.mjs";
@@ -840,8 +841,9 @@ function repeatedSkillBodyHint(injections) {
840
841
  const worst = injections[0];
841
842
  if (worst === void 0) return null;
842
843
  if (worst.count < SKILL_BODY_REPEAT_THRESHOLD || worst.bytes < LARGE_SKILL_BODY_BYTES) return null;
844
+ const skill = displaySafeText(worst.skill);
843
845
  const tokens = formatTokenEstimate(estimateTokensFromLength(worst.bytes));
844
- return `The \`${worst.skill}\` skill body has been injected ${worst.count} times this session (${formatBytes(worst.bytes)} total, ~${tokens} tok est). Slash expansion and the Skill tool both send the whole body every time, and no hook can intercept either. If it is already loaded, work from it instead of re-invoking; to reread one part, use \`token-goat skill-section ${worst.skill} '<heading>'\`.`;
846
+ return `The \`${skill}\` skill body has been injected ${worst.count} times this session (${formatBytes(worst.bytes)} total, ~${tokens} tok est). Slash expansion and the Skill tool both send the whole body every time, and no hook can intercept either. If it is already loaded, work from it instead of re-invoking; to reread one part, use \`token-goat skill-section ${skill} '<heading>'\`.`;
845
847
  }
846
848
  function readTranscriptTail(transcriptPath, maxBytes = RESIDENT_TAIL_MAX_BYTES) {
847
849
  let fd = null;
@@ -3,7 +3,7 @@ const require = __cjsRequire(import.meta.url);
3
3
  import {
4
4
  deliveredOutputBytes,
5
5
  wrappedShell
6
- } from "./token-goat-chunk-LXIC7MTW.mjs";
6
+ } from "./token-goat-chunk-REHUP2OE.mjs";
7
7
  import {
8
8
  ToolFilter,
9
9
  capTokens,
@@ -15,7 +15,7 @@ import {
15
15
  recordStat,
16
16
  selectFilter,
17
17
  shlexSplit
18
- } from "./token-goat-chunk-T2OE7MYM.mjs";
18
+ } from "./token-goat-chunk-JZYJH76S.mjs";
19
19
  import "./token-goat-chunk-EEIDFMEM.mjs";
20
20
  import {
21
21
  init_define_import_meta_env