token-goat 2.9.11 → 2.9.13

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 (25) hide show
  1. package/README.md +7 -1
  2. package/dist/{token-goat-chunk-FDURVZQD.mjs → token-goat-chunk-2WC4ZUXN.mjs} +1 -1
  3. package/dist/{token-goat-chunk-MRZ555B3.mjs → token-goat-chunk-3ESRORNM.mjs} +188 -97
  4. package/dist/token-goat-chunk-4NXUKV7D.mjs +56 -0
  5. package/dist/{token-goat-chunk-Y5VKNLVD.mjs → token-goat-chunk-6B44WLIF.mjs} +5 -5
  6. package/dist/{token-goat-chunk-2ZUPQYLO.mjs → token-goat-chunk-B3CTCQTH.mjs} +1 -1
  7. package/dist/{token-goat-chunk-V53Z47ZH.mjs → token-goat-chunk-FQCNJV4V.mjs} +20 -6
  8. package/dist/{token-goat-chunk-3ZALKJ23.mjs → token-goat-chunk-FZU7GMUS.mjs} +49 -24
  9. package/dist/{token-goat-chunk-AAEYU2U2.mjs → token-goat-chunk-JOXLE672.mjs} +344 -5699
  10. package/dist/{token-goat-chunk-HDL77BN3.mjs → token-goat-chunk-JVNPCQB7.mjs} +10 -7
  11. package/dist/{token-goat-chunk-LHLQFGWQ.mjs → token-goat-chunk-OMNQUUIT.mjs} +9 -27
  12. package/dist/{token-goat-chunk-PJPFOOGM.mjs → token-goat-chunk-P2PU4CR5.mjs} +8 -6
  13. package/dist/{token-goat-chunk-YCKCFYTM.mjs → token-goat-chunk-QKXBGBQR.mjs} +110 -21
  14. package/dist/{token-goat-chunk-MKITQ5RY.mjs → token-goat-chunk-QWSUZWFP.mjs} +44 -33
  15. package/dist/{token-goat-chunk-4NZUXC4F.mjs → token-goat-chunk-RDITECDL.mjs} +7 -5
  16. package/dist/{token-goat-chunk-LKOYKSID.mjs → token-goat-chunk-U7X6LQD2.mjs} +271 -69
  17. package/dist/token-goat-chunk-UM47DRD3.mjs +242 -0
  18. package/dist/token-goat-chunk-UMXJN7DI.mjs +5521 -0
  19. package/dist/token-goat-chunk-YOA4N6WA.mjs +308 -0
  20. package/dist/{token-goat-chunk-SY7WTZMW.mjs → token-goat-chunk-ZZI3IDQZ.mjs} +1016 -995
  21. package/dist/token-goat-hook.mjs +8 -6
  22. package/dist/token-goat.core.mjs +10 -7
  23. package/docs/cli.md +11 -8
  24. package/docs/security.md +1 -1
  25. package/package.json +1 -1
@@ -8,14 +8,17 @@ import {
8
8
  leftoverIntegrations,
9
9
  run,
10
10
  visualStudioManualSteps
11
- } from "./token-goat-chunk-MRZ555B3.mjs";
12
- import "./token-goat-chunk-LKOYKSID.mjs";
13
- import "./token-goat-chunk-2ZUPQYLO.mjs";
14
- import "./token-goat-chunk-V53Z47ZH.mjs";
15
- import "./token-goat-chunk-SY7WTZMW.mjs";
16
- import "./token-goat-chunk-AAEYU2U2.mjs";
11
+ } from "./token-goat-chunk-3ESRORNM.mjs";
12
+ import "./token-goat-chunk-FQCNJV4V.mjs";
13
+ import "./token-goat-chunk-U7X6LQD2.mjs";
14
+ import "./token-goat-chunk-ZZI3IDQZ.mjs";
15
+ import "./token-goat-chunk-JOXLE672.mjs";
16
+ import "./token-goat-chunk-YOA4N6WA.mjs";
17
+ import "./token-goat-chunk-UM47DRD3.mjs";
18
+ import "./token-goat-chunk-UMXJN7DI.mjs";
17
19
  import "./token-goat-chunk-EEIDFMEM.mjs";
18
- import "./token-goat-chunk-YCKCFYTM.mjs";
20
+ import "./token-goat-chunk-B3CTCQTH.mjs";
21
+ import "./token-goat-chunk-QKXBGBQR.mjs";
19
22
  import "./token-goat-chunk-A37V4PBF.mjs";
20
23
  export {
21
24
  applyExitOverride,
@@ -54,10 +54,7 @@ var McpServer = class {
54
54
  constructor(info) {
55
55
  this.info = info;
56
56
  }
57
- /**
58
- * Registers a tool. Schema generation happens here rather than at `tools/list` time, which also
59
- * means a malformed shape fails loudly at startup instead of on a client's first listing.
60
- */
57
+ /** Registers a tool. Schema generation happens here rather than at `tools/list` time, which also means a malformed shape fails loudly at startup instead of on a client's first listing. */
61
58
  registerTool(name, definition, handler) {
62
59
  if (this.tools.has(name)) throw new Error(`MCP tool registered twice: ${name}`);
63
60
  const shape = definition.inputSchema;
@@ -65,20 +62,13 @@ var McpServer = class {
65
62
  name,
66
63
  description: definition.description,
67
64
  jsonSchema: buildJsonSchema(shape),
68
- // An absent shape still needs a validator, so an argumentless tool called with arguments is
69
- // not silently handed them.
70
- validator: external_exports.object(shape ?? {})
65
+ // An absent shape still needs a validator, so an argumentless tool called with arguments is not silently handed them.
66
+ validator: external_exports.object(shape ?? {}),
67
+ annotations: definition.annotations
71
68
  });
72
69
  this.handlers.set(name, handler);
73
70
  }
74
- /**
75
- * Wires this server to a transport and starts it.
76
- *
77
- * `onmessage` is assigned before `start()` on purpose: a transport may have buffered messages
78
- * that arrive the moment it starts (the SDK's in-memory transport queues anything sent before a
79
- * handler exists and drains the queue inside `start()`), so a server that started first would
80
- * drop the client's `initialize`.
81
- */
71
+ /** Wires this server to a transport and starts it. `onmessage` is assigned before `start()` on purpose: a transport may have buffered messages that arrive the moment it starts (the SDK's in-memory transport queues anything sent before a handler exists and drains the queue inside `start()`), so a server that started first would drop the client's `initialize`. */
82
72
  async connect(transport) {
83
73
  this.transport = transport;
84
74
  transport.onmessage = (message) => {
@@ -135,14 +125,7 @@ var McpServer = class {
135
125
  const protocolVersion = typeof requested === "string" && SUPPORTED_PROTOCOL_VERSIONS.includes(requested) ? requested : LATEST_PROTOCOL_VERSION;
136
126
  return {
137
127
  protocolVersion,
138
- // Tools only, and they never change after startup, so no `listChanged`. This is the one
139
- // place we deliberately do not copy the SDK, which declares `listChanged: true` because its
140
- // McpServer is *able* to send that notification. Token-goat registers every tool before it
141
- // connects and never adds or removes one, so we would be promising a notification we can
142
- // never have cause to send. No client behaviour turns on it either way -- a subscription
143
- // that never fires and an absent subscription are the same thing when the list is fixed --
144
- // so the honest declaration wins. Contrast the tool-error text below, which a model reads as
145
- // content and is therefore matched to the SDK exactly.
128
+ // Tools only, and they never change after startup, so no `listChanged`. This is the one place we deliberately do not copy the SDK, which declares `listChanged: true` because its McpServer is *able* to send that notification. Token-goat registers every tool before it connects and never adds or removes one, so we would be promising a notification we can never have cause to send. No client behaviour turns on it either way -- a subscription that never fires and an absent subscription are the same thing when the list is fixed -- so the honest declaration wins. Contrast the tool-error text below, which a model reads as content and is therefore matched to the SDK exactly.
146
129
  capabilities: { tools: {} },
147
130
  serverInfo: { name: this.info.name, version: this.info.version }
148
131
  };
@@ -152,10 +135,9 @@ var McpServer = class {
152
135
  name: tool.name,
153
136
  ...tool.description !== void 0 ? { description: tool.description } : {},
154
137
  inputSchema: tool.jsonSchema,
155
- // The SDK emits this for every tool it registers, and it is literally true of ours: we do
156
- // not implement task augmentation, so a client that asks for it gets refused. Emitting the
157
- // same thing keeps `tools/list` byte-identical to what token-goat sent before, which is what
158
- // the differential test in tests/mcp_jsonrpc.test.ts pins.
138
+ // Omitted entirely when the tool registered none, rather than sent as an empty object: the SDK does the same, and a client reading an empty object cannot tell it from a tool that declined to answer.
139
+ ...tool.annotations !== void 0 ? { annotations: tool.annotations } : {},
140
+ // The SDK emits this for every tool it registers, and it is literally true of ours: we do not implement task augmentation, so a client that asks for it gets refused. Emitting the same thing keeps `tools/list` byte-identical to what token-goat sent before, which is what the differential test in tests/mcp_jsonrpc.test.ts pins.
159
141
  execution: { taskSupport: "forbidden" }
160
142
  }));
161
143
  }
@@ -4,16 +4,18 @@ import {
4
4
  buildEvent,
5
5
  relay,
6
6
  relayInProcess
7
- } from "./token-goat-chunk-MKITQ5RY.mjs";
8
- import "./token-goat-chunk-FDURVZQD.mjs";
7
+ } from "./token-goat-chunk-QWSUZWFP.mjs";
8
+ import "./token-goat-chunk-2WC4ZUXN.mjs";
9
9
  import {
10
10
  MAX_STDIN_BYTES,
11
11
  readStdinJson
12
- } from "./token-goat-chunk-V53Z47ZH.mjs";
13
- import "./token-goat-chunk-SY7WTZMW.mjs";
14
- import "./token-goat-chunk-AAEYU2U2.mjs";
12
+ } from "./token-goat-chunk-FQCNJV4V.mjs";
13
+ import "./token-goat-chunk-ZZI3IDQZ.mjs";
14
+ import "./token-goat-chunk-JOXLE672.mjs";
15
+ import "./token-goat-chunk-UM47DRD3.mjs";
16
+ import "./token-goat-chunk-UMXJN7DI.mjs";
15
17
  import "./token-goat-chunk-EEIDFMEM.mjs";
16
- import "./token-goat-chunk-YCKCFYTM.mjs";
18
+ import "./token-goat-chunk-QKXBGBQR.mjs";
17
19
  import "./token-goat-chunk-A37V4PBF.mjs";
18
20
  export {
19
21
  MAX_STDIN_BYTES,
@@ -9,7 +9,7 @@ init_define_import_meta_env();
9
9
  import { createRequire } from "node:module";
10
10
  function resolveVersion() {
11
11
  if (true) {
12
- return "2.9.11";
12
+ return "2.9.13";
13
13
  }
14
14
  const require2 = createRequire(import.meta.url);
15
15
  const pkg = require2("../package.json");
@@ -596,8 +596,11 @@ var PROBE_MAX_LENGTH = 512;
596
596
  var PROBE_LENGTHS = Array.from({ length: PROBE_MAX_LENGTH / PROBE_STEP }, (_, i) => (i + 1) * PROBE_STEP);
597
597
  var PROJECTED_LINE_LENGTH = 1e4;
598
598
  var PROJECTION_BUDGET_MS = 1e3;
599
- var PROJECTION_SIGNAL_MS = 1;
599
+ var TIMING_SIGNAL_MS = 1;
600
600
  var PROBE_GROWTH_FACTOR = 12;
601
+ function climbsBetweenRungs(previous, elapsed) {
602
+ return previous !== void 0 && elapsed > TIMING_SIGNAL_MS && elapsed > previous * PROBE_GROWTH_FACTOR;
603
+ }
601
604
  var PROBE_TERMINATORS = ["!", "a", "0", " ", "\uFFFF", "\n", "\u2028"];
602
605
  var PROBE_BUDGET_MS = 25;
603
606
  var MAX_COUNTED_REPEAT = 8;
@@ -608,7 +611,7 @@ function timeMatch(re, input) {
608
611
  const started = performance.now();
609
612
  const matched = probe.test(input);
610
613
  const first = performance.now() - started;
611
- if (first <= PROJECTION_SIGNAL_MS || first > PROBE_BUDGET_MS * 4) return { ms: first, matched };
614
+ if (first <= TIMING_SIGNAL_MS) return { ms: first, matched };
612
615
  const again = new RegExp(re.source, re.flags.replace("g", ""));
613
616
  const restarted = performance.now();
614
617
  again.test(input);
@@ -750,9 +753,10 @@ function probeAlphabets(source) {
750
753
  function growsExponentially(re) {
751
754
  const relaxed = detune(re.source);
752
755
  if (relaxed === null || !relaxed.hadLookaround) {
753
- if (climbsPastBudget(re)) return true;
756
+ const cause = climbsPastBudget(re);
757
+ if (cause !== null) return cause;
754
758
  }
755
- if (relaxed === null) return false;
759
+ if (relaxed === null) return null;
756
760
  for (const body of relaxed.negativeBodies) {
757
761
  let inner;
758
762
  try {
@@ -760,13 +764,14 @@ function growsExponentially(re) {
760
764
  } catch {
761
765
  continue;
762
766
  }
763
- if (growsExponentially(inner)) return true;
767
+ const innerCause = growsExponentially(inner);
768
+ if (innerCause !== null) return innerCause;
764
769
  }
765
770
  let widened;
766
771
  try {
767
772
  widened = new RegExp(relaxed.source, re.flags);
768
773
  } catch {
769
- return false;
774
+ return null;
770
775
  }
771
776
  return growsExponentially(widened);
772
777
  }
@@ -793,14 +798,14 @@ function climbsPastBudget(re) {
793
798
  return m;
794
799
  };
795
800
  for (const candidate of swept === void 0 ? candidates : [swept, ...candidates]) {
796
- if (attempt(candidate) === "over-budget") return true;
801
+ if (attempt(candidate) === "over-budget") return "over-budget";
797
802
  if (failing !== void 0) break;
798
803
  }
799
804
  if (failing === void 0 && sweeps < MAX_SWEEPS && sweptMs < SWEEP_BUDGET_MS) {
800
805
  sweeps++;
801
806
  const sweepStarted = Date.now();
802
807
  for (const candidate of SWEEP_TAILS) {
803
- if (attempt(candidate) === "over-budget") return true;
808
+ if (attempt(candidate) === "over-budget") return "over-budget";
804
809
  if (failing !== void 0) {
805
810
  swept = candidate;
806
811
  break;
@@ -810,14 +815,14 @@ function climbsPastBudget(re) {
810
815
  }
811
816
  if (failing !== void 0) falsified = true;
812
817
  const elapsed = (failing ?? last).ms;
813
- if (previous !== void 0 && elapsed > 1 && elapsed > previous * PROBE_GROWTH_FACTOR) return true;
818
+ if (climbsBetweenRungs(previous, elapsed)) return "ratio";
814
819
  previous = elapsed;
815
820
  timings.push(elapsed);
816
821
  }
817
- if (projectsPastBudget(timings)) return true;
822
+ if (projectsPastBudget(timings)) return "projection";
818
823
  }
819
- if (!falsified && QUANTIFIED_GROUP.test(re.source)) return true;
820
- return false;
824
+ if (!falsified && QUANTIFIED_GROUP.test(re.source)) return "unfalsifiable";
825
+ return null;
821
826
  }
822
827
  function groupEnd(source, start) {
823
828
  let depth = 0;
@@ -912,7 +917,7 @@ function projectsPastBudget(timings) {
912
917
  const top = timings[hi];
913
918
  const prior = timings[lo];
914
919
  if (top === void 0 || prior === void 0 || loLength === void 0 || loLength >= hiLength) return false;
915
- if (top <= PROJECTION_SIGNAL_MS || prior <= 0) return false;
920
+ if (top <= TIMING_SIGNAL_MS || prior <= 0) return false;
916
921
  const exponent = Math.log2(top / prior) / Math.log2(hiLength / loLength);
917
922
  return top * (PROJECTED_LINE_LENGTH / hiLength) ** exponent > PROJECTION_BUDGET_MS;
918
923
  }
@@ -927,10 +932,12 @@ function compileGuardedRegex(pattern, flags = "") {
927
932
  } catch (e) {
928
933
  return { ok: false, reason: e instanceof Error ? e.message : "is not a valid regular expression" };
929
934
  }
930
- if (growsExponentially(re)) {
935
+ const cause = growsExponentially(re);
936
+ if (cause !== null) {
931
937
  return {
932
938
  ok: false,
933
- reason: hasNestedQuantifier(pattern) ? "repeats a group that already repeats, which can take exponential time to match" : "takes time that climbs steeply with the length of the line, which can stall on ordinary text"
939
+ reason: hasNestedQuantifier(pattern) ? "repeats a group that already repeats, which can take exponential time to match" : "takes time that climbs steeply with the length of the line, which can stall on ordinary text",
940
+ cause
934
941
  };
935
942
  }
936
943
  return { ok: true, re };
@@ -1073,6 +1080,77 @@ function projectPathIsConsultable(target, projectRoot) {
1073
1080
  return isInsideRoot(target, projectRoot);
1074
1081
  }
1075
1082
 
1083
+ // src/indexed_source.ts
1084
+ init_define_import_meta_env();
1085
+
1086
+ // src/languages/ipynb_idx.ts
1087
+ init_define_import_meta_env();
1088
+ function normalizeSource(source) {
1089
+ if (typeof source === "string") return source;
1090
+ if (!Array.isArray(source)) return "";
1091
+ const lines = source.filter((s) => typeof s === "string");
1092
+ if (lines.length === 0) return "";
1093
+ const noneEndWithNewline = lines.every((l) => !l.endsWith("\n"));
1094
+ return noneEndWithNewline ? lines.join("\n") : lines.join("");
1095
+ }
1096
+ function resolveKernelLanguage(metadata) {
1097
+ const kernelspecLang = metadata?.kernelspec?.language;
1098
+ if (typeof kernelspecLang === "string" && kernelspecLang !== "") return kernelspecLang.toLowerCase();
1099
+ const infoLang = metadata?.language_info?.name;
1100
+ if (typeof infoLang === "string" && infoLang !== "") return infoLang.toLowerCase();
1101
+ return void 0;
1102
+ }
1103
+ function ipynbToVirtualSource(raw) {
1104
+ let data;
1105
+ try {
1106
+ data = JSON.parse(raw);
1107
+ } catch {
1108
+ return { content: "", cellLanguage: null };
1109
+ }
1110
+ if (typeof data !== "object" || data === null) return { content: "", cellLanguage: null };
1111
+ const nb = data;
1112
+ if (!Array.isArray(nb.cells)) return { content: "", cellLanguage: null };
1113
+ const declared = resolveKernelLanguage(nb.metadata);
1114
+ const isPython = declared === void 0 || declared === "python" || declared === "python3";
1115
+ if (!isPython) return { content: "", cellLanguage: null };
1116
+ const blocks = [];
1117
+ nb.cells.forEach((cell, index) => {
1118
+ if (typeof cell !== "object" || cell === null) return;
1119
+ const c = cell;
1120
+ if (c.cell_type === "code") {
1121
+ const src = normalizeSource(c.source).replace(/\n+$/, "");
1122
+ blocks.push(`# %% cell ${index}
1123
+ ${src}`);
1124
+ } else if (c.cell_type === "markdown") {
1125
+ const src = normalizeSource(c.source).replace(/\n+$/, "");
1126
+ const commented = src.split("\n").map((line) => line === "" ? "#" : `# ${line}`).join("\n");
1127
+ blocks.push(`# %% [markdown] cell ${index}
1128
+ ${commented}`);
1129
+ }
1130
+ });
1131
+ return { content: blocks.join("\n\n"), cellLanguage: "python" };
1132
+ }
1133
+
1134
+ // src/indexed_source.ts
1135
+ function indexedSourceText(filePath, raw) {
1136
+ return isVirtualIndexedPath(filePath) ? ipynbToVirtualSource(stripBom(raw)).content : raw;
1137
+ }
1138
+ function stripBom(text) {
1139
+ return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
1140
+ }
1141
+ function isVirtualIndexedPath(filePath) {
1142
+ return filePath.toLowerCase().endsWith(".ipynb");
1143
+ }
1144
+ function virtualIndexedScopeNote(displayPath, consequence) {
1145
+ return `[${displayPath} is a notebook: its indexed line numbers address the flattened cell source, not the JSON in the file, so ${consequence}.]`;
1146
+ }
1147
+ var NOTEBOOK_CELL_LINES_SUFFIX = " (notebook cell lines)";
1148
+ function formatSymbolLocation(displayPath, lineStart, lineEnd) {
1149
+ const range = lineEnd === void 0 ? `${lineStart}` : `${lineStart}-${lineEnd}`;
1150
+ const suffix = isVirtualIndexedPath(displayPath) ? NOTEBOOK_CELL_LINES_SUFFIX : "";
1151
+ return `${displayPath}:${range}${suffix}`;
1152
+ }
1153
+
1076
1154
  // src/util.ts
1077
1155
  function sleepSync(ms) {
1078
1156
  if (ms <= 0) return;
@@ -1477,7 +1555,7 @@ function buildContextWindow(absPath, line, contextLines) {
1477
1555
  if (!Number.isFinite(contextLines) || contextLines <= 0) return null;
1478
1556
  let text;
1479
1557
  try {
1480
- text = readFileSync2(absPath, "utf-8");
1558
+ text = indexedSourceText(absPath, readFileSync2(absPath, "utf-8"));
1481
1559
  } catch {
1482
1560
  return null;
1483
1561
  }
@@ -1600,7 +1678,7 @@ function redactUrlQuery(raw) {
1600
1678
  const q = raw.indexOf("?");
1601
1679
  return q === -1 ? raw : raw.slice(0, q);
1602
1680
  }
1603
- function stripBom(text) {
1681
+ function stripBom2(text) {
1604
1682
  return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
1605
1683
  }
1606
1684
  function withExtension(filePath, format) {
@@ -2260,7 +2338,7 @@ function stripStringLiterals(line, opts = {}) {
2260
2338
  i++;
2261
2339
  continue;
2262
2340
  }
2263
- if (ch === "\\" && i + 1 < line.length) {
2341
+ if (ch === "\\" && i + 1 < line.length && line[i + 1] !== "\n") {
2264
2342
  out += " ";
2265
2343
  i += 2;
2266
2344
  continue;
@@ -2326,6 +2404,8 @@ var MULTILINE_CLOSER_ANCHOR = {
2326
2404
  scala: "anywhere",
2327
2405
  // Dart's multi-line string production is a delimiter, content, then the delimiter, with no rule about where on a line the closing delimiter falls (Dart Programming Language Specification, section "Strings").
2328
2406
  dart: "anywhere",
2407
+ // A GraphQL block string closes at the next `"""` wherever it sits: the spec's BlockString production places no positional rule on the closing delimiter, and a one-line description such as `"""A user."""` is the ordinary form (GraphQL specification, section 2.9.4 "String Value").
2408
+ graphql: "anywhere",
2329
2409
  // C# has two cross-line forms and they disagree, so the language-level value is the permissive one. A verbatim string (`@"..."`) closes on the next non-doubled quote wherever it sits and has no positional rule (C# language reference, "String literals"). A multi-line raw string literal does require its closing run to begin its own line (C# language reference, "Raw string literals"), but that rule is unreachable as a mis-pairing here: the same section forbids the content from holding a quote run as long as the delimiter, so no run inside the body can be mistaken for the closer in the first place, and the run-length rule already in `closingQuoteRunEnd` is what enforces it.
2330
2410
  csharp: "anywhere",
2331
2411
  // R has no fixed-delimiter multi-line form and no positional rule: an ordinary character constant runs to its next unescaped quote (R Language Definition, section 10.3.1 "Literal constants") and a raw constant to its mirrored closing punctuation (R base help page `?Quotes`, "Raw character constants"), on whatever line either lands.
@@ -2339,6 +2419,8 @@ function closerSearchStart(line, from, anchor) {
2339
2419
  var TRIPLE_QUOTE_RUN_CLOSE = {
2340
2420
  kotlin: "last",
2341
2421
  scala: "last",
2422
+ // A GraphQL block string ends at the first `"""` run, because its grammar excludes that sequence from the body outright rather than letting the longest run win (GraphQL specification, section 2.9.4 "String Value", the BlockString production).
2423
+ graphql: "first",
2342
2424
  // Swift's closing delimiter has to stand alone on its own line (The Swift Programming Language, "Strings and Characters", section "Multiline String Literals"), so no run longer than three ever terminates a valid Swift literal; it is grouped with Kotlin and Scala so that the same-line and cross-line paths agree, not to assert a rule Swift itself defines.
2343
2425
  swift: "last",
2344
2426
  csharp: "last",
@@ -2469,6 +2551,7 @@ function findMultilineCloser(line, from, state) {
2469
2551
  var MULTILINE_OPENER_COMMENT_MARKERS = {
2470
2552
  php: ["//", "#"],
2471
2553
  kotlin: ["//"],
2554
+ graphql: ["#"],
2472
2555
  csharp: ["//"],
2473
2556
  powershell: ["#"],
2474
2557
  swift: ["//"],
@@ -2681,7 +2764,7 @@ function findMultilineOpener(line, from, lang) {
2681
2764
  const kind = m[1] === "'" ? "nowdoc" : "heredoc";
2682
2765
  return { openStart: m.index, closesSameLine: null, state: { kind, identifier, closerAnchor: MULTILINE_CLOSER_ANCHOR[lang] } };
2683
2766
  }
2684
- if (lang === "kotlin" || lang === "swift" || lang === "scala") {
2767
+ if (lang === "kotlin" || lang === "swift" || lang === "scala" || lang === "graphql") {
2685
2768
  let swiftExt = null;
2686
2769
  if (lang === "swift") {
2687
2770
  for (let h = line.indexOf("#", from); h !== -1; h = line.indexOf("#", h + 1)) {
@@ -3457,6 +3540,12 @@ export {
3457
3540
  projectScopeRoot,
3458
3541
  assertWriteInScope,
3459
3542
  projectPathIsConsultable,
3543
+ ipynbToVirtualSource,
3544
+ indexedSourceText,
3545
+ isVirtualIndexedPath,
3546
+ virtualIndexedScopeNote,
3547
+ NOTEBOOK_CELL_LINES_SUFFIX,
3548
+ formatSymbolLocation,
3460
3549
  hasNestedQuantifier,
3461
3550
  growsExponentially,
3462
3551
  compileGuardedRegex,
@@ -3500,7 +3589,7 @@ export {
3500
3589
  escapeRegExp,
3501
3590
  windowsCmdQuoteArg,
3502
3591
  redactUrlQuery,
3503
- stripBom,
3592
+ stripBom2 as stripBom,
3504
3593
  withExtension,
3505
3594
  ensureNewline,
3506
3595
  extractErrorMessage,
@@ -4,7 +4,7 @@ import {
4
4
  canRunWrappedShell,
5
5
  clipToDeliveryCap,
6
6
  deliveredOutputBytes
7
- } from "./token-goat-chunk-FDURVZQD.mjs";
7
+ } from "./token-goat-chunk-2WC4ZUXN.mjs";
8
8
  import {
9
9
  DEFAULT_RECONCILE_BUDGET_MS,
10
10
  HOOK_EVENTS,
@@ -22,7 +22,7 @@ import {
22
22
  storeWebOutput,
23
23
  summarizeResidentContext,
24
24
  taskListPruneHint
25
- } from "./token-goat-chunk-V53Z47ZH.mjs";
25
+ } from "./token-goat-chunk-FQCNJV4V.mjs";
26
26
  import {
27
27
  BASH_OUTPUT_SUBDIR,
28
28
  GENERIC_SERVED_OUTPUT_KEY,
@@ -121,7 +121,6 @@ import {
121
121
  setLastTabContext,
122
122
  shrinkImage,
123
123
  storeBashOutput,
124
- storeBlob,
125
124
  storeOutput,
126
125
  summarizeOutputDelta,
127
126
  takePendingLargeFileHint,
@@ -131,7 +130,7 @@ import {
131
130
  wasCliReadThisSession,
132
131
  wasFileReadThisSession,
133
132
  wasHintShown
134
- } from "./token-goat-chunk-SY7WTZMW.mjs";
133
+ } from "./token-goat-chunk-ZZI3IDQZ.mjs";
135
134
  import {
136
135
  BODY_FIRST_TOOL_RESPONSE_KEYS,
137
136
  OUTPUT_FIRST_TOOL_RESPONSE_KEYS,
@@ -140,47 +139,55 @@ import {
140
139
  dedupeConsecutive,
141
140
  denyOutput,
142
141
  detectFromCommand,
143
- detectHarness,
144
- detectLanguage,
145
142
  emitRewrite,
146
143
  emitRewriteIfChanged,
147
- envBool,
148
- envInt,
149
144
  estimateTokens,
150
145
  extractToolResponseField,
151
146
  extractToolResultText,
152
147
  filterByName,
153
- findProject,
154
148
  getCwd,
155
- getDb,
156
149
  getFilePath,
157
- getHarnessName,
158
150
  getToolInput,
159
151
  getToolName,
160
152
  hasBareBackgroundOrNewline,
161
153
  hasUnquotedOperator,
162
154
  isMcpErrorResponse,
163
155
  isRewriteWorthwhile,
164
- isUnderSystemTemp,
165
- languageHasFlag,
166
- loadConfig,
156
+ isTextualContentBlock,
167
157
  makeDedupHintHandlers,
158
+ mcpContentBlocks,
168
159
  normalizePayload,
169
160
  passOutput,
170
161
  readCopilotHooksOwners,
171
- recordStat,
172
- redactSecrets,
173
162
  registerHook,
174
163
  resolveMinNetSavingsBytes,
175
164
  runHook,
176
- savedTokensFromBytes,
177
165
  serializeOutput,
178
166
  sessionStateKey,
179
167
  shlexSplit,
180
- shortFingerprint,
181
168
  splitOwnTrailingNotices,
169
+ withPreservedBlocks
170
+ } from "./token-goat-chunk-JOXLE672.mjs";
171
+ import {
172
+ storeBlob
173
+ } from "./token-goat-chunk-UM47DRD3.mjs";
174
+ import {
175
+ detectHarness,
176
+ detectLanguage,
177
+ envBool,
178
+ envInt,
179
+ findProject,
180
+ getDb,
181
+ getHarnessName,
182
+ isUnderSystemTemp,
183
+ languageHasFlag,
184
+ loadConfig,
185
+ recordStat,
186
+ redactSecrets,
187
+ savedTokensFromBytes,
188
+ shortFingerprint,
182
189
  stripAnsiEscapes
183
- } from "./token-goat-chunk-AAEYU2U2.mjs";
190
+ } from "./token-goat-chunk-UMXJN7DI.mjs";
184
191
  import {
185
192
  ENV_KEYS,
186
193
  IDENTICAL_READ_MIN_BODY_BYTES,
@@ -207,7 +214,7 @@ import {
207
214
  runGit,
208
215
  toDisplayPath,
209
216
  toKB
210
- } from "./token-goat-chunk-YCKCFYTM.mjs";
217
+ } from "./token-goat-chunk-QKXBGBQR.mjs";
211
218
  import {
212
219
  init_define_import_meta_env
213
220
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -927,7 +934,7 @@ init_define_import_meta_env();
927
934
  var TRACKED_SKILL = "token-goat";
928
935
  var MAX_COMMANDS_SHOWN = 8;
929
936
  async function currentCommandNames() {
930
- const { buildProgram } = await import("./token-goat-chunk-HDL77BN3.mjs");
937
+ const { buildProgram } = await import("./token-goat-chunk-JVNPCQB7.mjs");
931
938
  return flattenCommandNames(buildCommandManifest(buildProgram()));
932
939
  }
933
940
  async function recordSkillVersionSnapshot(sessionId, skillName) {
@@ -10745,10 +10752,14 @@ function postMcpHandler(event) {
10745
10752
  if (!resultText) return passOutput();
10746
10753
  const injectionMatches = scanAndRecord(resultText);
10747
10754
  const redactedResult = redactSecrets(resultText);
10748
- const fenced = () => emitRewriteIfChanged(
10749
- resultText,
10750
- fenceWithMatches(redactedResult.text, injectionMatches, UNTRUSTED_TOOL_TAG),
10751
- "mcp"
10755
+ const preserved = (mcpContentBlocks(event.raw) ?? []).filter((b) => !isTextualContentBlock(b));
10756
+ const preserve = (output) => withPreservedBlocks(output, preserved);
10757
+ const fenced = () => preserve(
10758
+ emitRewriteIfChanged(
10759
+ resultText,
10760
+ fenceWithMatches(redactedResult.text, injectionMatches, UNTRUSTED_TOOL_TAG),
10761
+ "mcp"
10762
+ )
10752
10763
  );
10753
10764
  const passOrFence = () => fenced();
10754
10765
  if (!event.sessionId) return passOrFence();
@@ -10776,10 +10787,12 @@ function postMcpHandler(event) {
10776
10787
  minNetSavingsBytes: resolveMinNetSavingsBytes()
10777
10788
  });
10778
10789
  if (worthwhile) {
10779
- return emitRewrite(
10780
- `${notice}${fenceWithMatches(redactedBody, injectionMatches, UNTRUSTED_TOOL_TAG)}`,
10781
- "mcp",
10782
- { kind: "mcp:compress", originalBytes }
10790
+ return preserve(
10791
+ emitRewrite(
10792
+ `${notice}${fenceWithMatches(redactedBody, injectionMatches, UNTRUSTED_TOOL_TAG)}`,
10793
+ "mcp",
10794
+ { kind: "mcp:compress", originalBytes }
10795
+ )
10783
10796
  );
10784
10797
  }
10785
10798
  }
@@ -10877,6 +10890,7 @@ import { createHash } from "node:crypto";
10877
10890
  function getResponseContentBlocks(raw) {
10878
10891
  const tr = raw["tool_response"];
10879
10892
  if (!tr || typeof tr !== "object") return null;
10893
+ if (Array.isArray(tr)) return tr;
10880
10894
  const content = tr["content"];
10881
10895
  return Array.isArray(content) ? content : null;
10882
10896
  }
@@ -10915,10 +10929,7 @@ async function shrinkImageBlock(block) {
10915
10929
  changed: true,
10916
10930
  // Decoded image bytes, not base64 characters. Both branches of this function file under the same `image_shrink` kind, and the shrink branch below credits `result.originalBytes - result.shrunkBytes` -- decoded bytes, the convention documented at image_shrink.ts's own recordStat call. Base64 inflates by 4/3, so crediting `originalDataUrl.length` here booked roughly 33% more for a repeat screenshot than an identical shrink of the same image, and the ledger summed the two units into one row. The gate above deliberately still measures the data URL: it decides whether the rewrite pays off on the wire, where base64 characters are what is actually sent.
10917
10931
  savedBytes: buffer.length - Buffer.byteLength(SCREENSHOT_REPEAT_NOTICE, "utf-8"),
10918
- // The whole image is withheld here rather than resized, so the visual tokens saved are its
10919
- // entire billed cost less the notice standing in for it. Billed cost, not raw patch count:
10920
- // an oversized screenshot would have been capped by the API's own downscale, so pricing the
10921
- // untouched dimensions would credit a bill that was never going to be sent.
10932
+ // The whole image is withheld here rather than resized, so the visual tokens saved are its entire billed cost less the notice standing in for it. Billed cost, not raw patch count: an oversized screenshot would have been capped by the API's own downscale, so pricing the untouched dimensions would credit a bill that was never going to be sent.
10922
10933
  savedTokens: Math.max(0, visionTokens(meta?.width ?? 0, meta?.height ?? 0, tier) - savedTokensFromBytes(Buffer.byteLength(SCREENSHOT_REPEAT_NOTICE, "utf-8")))
10923
10934
  };
10924
10935
  }
@@ -3,7 +3,7 @@ const require = __cjsRequire(import.meta.url);
3
3
  import {
4
4
  deliveredOutputBytes,
5
5
  wrappedShell
6
- } from "./token-goat-chunk-FDURVZQD.mjs";
6
+ } from "./token-goat-chunk-2WC4ZUXN.mjs";
7
7
  import {
8
8
  ToolFilter,
9
9
  capTokens,
@@ -11,13 +11,15 @@ import {
11
11
  deliverCompressed,
12
12
  dispatchArgv,
13
13
  filterByName,
14
- loadConfig,
15
- recordStat,
16
14
  selectFilter,
17
15
  shlexSplit
18
- } from "./token-goat-chunk-AAEYU2U2.mjs";
16
+ } from "./token-goat-chunk-JOXLE672.mjs";
17
+ import {
18
+ loadConfig,
19
+ recordStat
20
+ } from "./token-goat-chunk-UMXJN7DI.mjs";
19
21
  import "./token-goat-chunk-EEIDFMEM.mjs";
20
- import "./token-goat-chunk-YCKCFYTM.mjs";
22
+ import "./token-goat-chunk-QKXBGBQR.mjs";
21
23
  import {
22
24
  init_define_import_meta_env
23
25
  } from "./token-goat-chunk-A37V4PBF.mjs";