token-goat 2.6.34 → 2.6.35

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 (24) hide show
  1. package/SECURITY.md +11 -10
  2. package/dist/{token-goat-chunk-IYYQOPY4.mjs → token-goat-chunk-D5IZEGN2.mjs} +18 -4
  3. package/dist/{token-goat-chunk-WA2ER6TZ.mjs → token-goat-chunk-DQIT5JIF.mjs} +1 -1
  4. package/dist/{token-goat-chunk-L7QLEVO7.mjs → token-goat-chunk-DRAIYVUI.mjs} +16 -14
  5. package/dist/{token-goat-chunk-GXBPEQR2.mjs → token-goat-chunk-HW4VUKJ5.mjs} +14 -8
  6. package/dist/{token-goat-chunk-CN7GUPX6.mjs → token-goat-chunk-I2KCEGIP.mjs} +378 -54
  7. package/dist/{token-goat-chunk-7FWBSPCT.mjs → token-goat-chunk-K7W3P2TJ.mjs} +139 -6
  8. package/dist/{token-goat-chunk-OA3GFKP2.mjs → token-goat-chunk-SIHYQCTM.mjs} +2 -2
  9. package/dist/{token-goat-chunk-I6EQH27G.mjs → token-goat-chunk-UIZVX3HN.mjs} +2 -2
  10. package/dist/{token-goat-chunk-FRMEOIRU.mjs → token-goat-chunk-Y2NH6DGZ.mjs} +208 -13
  11. package/dist/{token-goat-chunk-CKRATWCJ.mjs → token-goat-chunk-YF67EWRH.mjs} +5 -5
  12. package/dist/{token-goat-hook-chunk-CNLMPHXT.mjs → token-goat-hook-chunk-2O7P4Z6Q.mjs} +139 -6
  13. package/dist/{token-goat-hook-chunk-I5VM5PO5.mjs → token-goat-hook-chunk-3AAH72SO.mjs} +14 -8
  14. package/dist/{token-goat-hook-chunk-BU5OFDGQ.mjs → token-goat-hook-chunk-4POU6OHK.mjs} +208 -13
  15. package/dist/{token-goat-hook-chunk-6C5RN3CM.mjs → token-goat-hook-chunk-CRBMPT74.mjs} +2 -2
  16. package/dist/{token-goat-hook-chunk-QTZ6YUMQ.mjs → token-goat-hook-chunk-D6UJEFHX.mjs} +2 -2
  17. package/dist/{token-goat-hook-chunk-ATEGFQAU.mjs → token-goat-hook-chunk-J4HKWUWZ.mjs} +5 -5
  18. package/dist/{token-goat-hook-chunk-2ISZ4AZR.mjs → token-goat-hook-chunk-NIPXIAPA.mjs} +1 -1
  19. package/dist/{token-goat-hook-chunk-KGLMNOGD.mjs → token-goat-hook-chunk-NXVT4F3S.mjs} +18 -4
  20. package/dist/{token-goat-hook-chunk-OQML5EMA.mjs → token-goat-hook-chunk-VU6VGZBM.mjs} +16 -14
  21. package/dist/{token-goat-hook-chunk-6QTWMSRO.mjs → token-goat-hook-chunk-XM4W3WCO.mjs} +378 -54
  22. package/dist/token-goat-hook.mjs +5 -5
  23. package/dist/token-goat.core.mjs +5 -5
  24. package/package.json +4 -3
@@ -8,7 +8,7 @@ import {
8
8
  import { createRequire } from "node:module";
9
9
  function resolveVersion() {
10
10
  if (true) {
11
- return "2.6.34";
11
+ return "2.6.35";
12
12
  }
13
13
  const require2 = createRequire(import.meta.url);
14
14
  const pkg = require2("../package.json");
@@ -1196,6 +1196,9 @@ function getDisplayRoot(explicitRoot) {
1196
1196
  _displayRootCache = { cwd, root };
1197
1197
  return root;
1198
1198
  }
1199
+ registerReset(() => {
1200
+ _displayRootCache = null;
1201
+ });
1199
1202
  function isUnderSystemTemp(filePath) {
1200
1203
  let sysTemp;
1201
1204
  try {
@@ -2508,7 +2511,7 @@ function getLastProjectConfigParseError() {
2508
2511
  return _lastProjectConfigParseError;
2509
2512
  }
2510
2513
  var PROJECT_LOCKED_SECTIONS = ["injection", "webfetch", "gdrive", "mcp", "network"];
2511
- var PROJECT_LOCKED_KEYS = ["indexing.cross_project_symbols"];
2514
+ var PROJECT_LOCKED_KEYS = ["indexing.cross_project_symbols", "worker.blocked_roots"];
2512
2515
  var _lastProjectConfigLockedKeys = [];
2513
2516
  function stripLockedProjectKeys(projectRaw) {
2514
2517
  const cleaned = {};
@@ -2680,6 +2683,9 @@ function resolveConfigProjectRoot() {
2680
2683
  _projectRootCache = { cwd, root };
2681
2684
  return root;
2682
2685
  }
2686
+ registerReset(() => {
2687
+ _projectRootCache = null;
2688
+ });
2683
2689
  function isAutoTriggerMultiplierExplicit() {
2684
2690
  const setsMultiplier = (text) => {
2685
2691
  const raw = parse(text);
@@ -4171,7 +4177,8 @@ function propagateEndLinesToSymbols(symbols, sections) {
4171
4177
  return sym;
4172
4178
  });
4173
4179
  }
4174
- function findMatchingBraceEndLine(content, openBraceIndex, totalLines, lineIndex, lineCommentPrefix) {
4180
+ function findMatchingBraceEndLine(content, openBraceIndex, totalLines, lineIndex, lineCommentPrefix, opts) {
4181
+ const block = opts?.blockComment;
4175
4182
  let depth = 0;
4176
4183
  let quote = null;
4177
4184
  for (let i = openBraceIndex; i < content.length; i++) {
@@ -4184,6 +4191,11 @@ function findMatchingBraceEndLine(content, openBraceIndex, totalLines, lineIndex
4184
4191
  if (ch === quote) quote = null;
4185
4192
  continue;
4186
4193
  }
4194
+ if (block !== void 0 && content.startsWith(block[0], i)) {
4195
+ const close = content.indexOf(block[1], i + block[0].length);
4196
+ i = close === -1 ? content.length : close + block[1].length - 1;
4197
+ continue;
4198
+ }
4187
4199
  if (lineCommentPrefix !== void 0 && content.startsWith(lineCommentPrefix, i)) {
4188
4200
  while (i < content.length && content[i] !== "\n") i++;
4189
4201
  continue;
@@ -4200,7 +4212,106 @@ function findMatchingBraceEndLine(content, openBraceIndex, totalLines, lineIndex
4200
4212
  }
4201
4213
  }
4202
4214
  }
4203
- return totalLines;
4215
+ return opts?.noMatchValue ?? totalLines;
4216
+ }
4217
+ function assignBraceBlockSpans(symbols, content, lineCommentPrefix) {
4218
+ if (symbols.length === 0) return [...symbols];
4219
+ const lines = content.split("\n");
4220
+ const totalLines = lines.length;
4221
+ const lineIndex = buildLineIndex(content);
4222
+ const starts = [...new Set(symbols.map((s) => s.lineStart))].sort((a, b) => a - b);
4223
+ const blockComment = lineCommentPrefix === "//" ? ["/*", "*/"] : lineCommentPrefix === "#" ? ["<#", "#>"] : void 0;
4224
+ return symbols.map((sym) => {
4225
+ if (sym.lineEnd !== sym.lineStart) return sym;
4226
+ const nextStart = starts.find((s) => s > sym.lineStart);
4227
+ const lastSearchLine = Math.min(nextStart !== void 0 ? nextStart - 1 : totalLines, sym.lineStart + BRACE_SEARCH_MAX_LINES);
4228
+ const openIndex = findBlockOpenBrace(content, lineIndex, sym.lineStart, lastSearchLine, lineCommentPrefix, blockComment);
4229
+ if (openIndex === null) return sym;
4230
+ const endLine = findMatchingBraceEndLine(
4231
+ content,
4232
+ openIndex,
4233
+ totalLines,
4234
+ lineIndex,
4235
+ lineCommentPrefix,
4236
+ blockComment === void 0 ? { noMatchValue: -1 } : { blockComment, noMatchValue: -1 }
4237
+ );
4238
+ if (endLine <= sym.lineStart) return sym;
4239
+ return { ...sym, lineEnd: endLine, body: lines.slice(sym.lineStart - 1, endLine).join("\n") };
4240
+ });
4241
+ }
4242
+ var BRACE_SEARCH_MAX_LINES = 10;
4243
+ function findBlockOpenBrace(content, lineIndex, startLine, lastSearchLine, lineCommentPrefix, blockComment) {
4244
+ const from = lineIndex[startLine - 1];
4245
+ if (from === void 0) return null;
4246
+ const to = lineIndex[lastSearchLine] ?? content.length;
4247
+ let quote = null;
4248
+ let parenDepth = 0;
4249
+ let linesSeen = 0;
4250
+ let atLineStart = false;
4251
+ for (let i = from; i < to; i++) {
4252
+ const ch = content[i];
4253
+ if (ch === void 0) break;
4254
+ if (quote !== null) {
4255
+ if (ch === "\\") {
4256
+ i++;
4257
+ continue;
4258
+ }
4259
+ if (ch === quote) quote = null;
4260
+ continue;
4261
+ }
4262
+ if (ch === "\n") {
4263
+ linesSeen++;
4264
+ atLineStart = true;
4265
+ continue;
4266
+ }
4267
+ if (blockComment !== void 0 && content.startsWith(blockComment[0], i)) {
4268
+ const close = content.indexOf(blockComment[1], i + blockComment[0].length);
4269
+ if (close === -1) return null;
4270
+ i = close + blockComment[1].length - 1;
4271
+ continue;
4272
+ }
4273
+ if (lineCommentPrefix !== void 0 && content.startsWith(lineCommentPrefix, i)) {
4274
+ while (i + 1 < to && content[i + 1] !== "\n") i++;
4275
+ continue;
4276
+ }
4277
+ if (atLineStart && !/\s/.test(ch)) {
4278
+ atLineStart = false;
4279
+ if (parenDepth === 0 && linesSeen >= 1 && startsWithBlockKeyword(content, i, to)) return null;
4280
+ }
4281
+ if (ch === '"' || ch === "'") {
4282
+ quote = ch;
4283
+ continue;
4284
+ }
4285
+ if (ch === "(" || ch === "[") parenDepth++;
4286
+ else if (ch === ")" || ch === "]") {
4287
+ if (parenDepth > 0) parenDepth--;
4288
+ } else if (ch === ";") return null;
4289
+ else if (ch === "{") return i;
4290
+ }
4291
+ return null;
4292
+ }
4293
+ var BLOCK_OPENING_KEYWORDS = /* @__PURE__ */ new Set([
4294
+ "if",
4295
+ "for",
4296
+ "while",
4297
+ "do",
4298
+ "switch",
4299
+ "when",
4300
+ "match",
4301
+ "try",
4302
+ "foreach",
4303
+ "loop",
4304
+ "guard",
4305
+ "repeat",
4306
+ "unless",
4307
+ "until"
4308
+ ]);
4309
+ function startsWithBlockKeyword(content, i, to) {
4310
+ const first = content[i];
4311
+ if (first === void 0 || !/[A-Za-z_]/.test(first)) return false;
4312
+ let j = i + 1;
4313
+ while (j < to && /[A-Za-z0-9_]/.test(content[j])) j++;
4314
+ return BLOCK_OPENING_KEYWORDS.has(content.slice(i, j));
4204
4315
  }
4205
4316
 
4206
4317
  // src/languages/ini_idx.ts
@@ -5983,7 +6094,13 @@ var SECRET_PATTERNS = [
5983
6094
  // directly against the header name and the scheme directly against the space, so a body like
5984
6095
  // {"Authorization": "Bearer <token>"} -- the shape any logged fetch or MCP result arrives in
5985
6096
  // -- matched nothing and the token was cached verbatim.
5986
- ["auth_bearer_token", /(?<=Authorization["']?[ \t]{0,8}:[ \t]{0,8}["']?[ \t]{0,8}Bearer[ \t])[A-Za-z0-9\-._~+/]{10,}=*/gi],
6097
+ // `token` is the second scheme spelling in wide use -- it is what curl and gh examples pass for
6098
+ // GitHub and many other APIs -- and an opaque value behind it carries exactly the same authority
6099
+ // as one behind `Bearer`. The trailing gap is `{1,8}` rather than a single space for the same
6100
+ // reason every other gap in this lookbehind already is: a hand-aligned or reformatted header
6101
+ // ("Authorization: Bearer <token>") is ordinary, and demanding exactly one space there made
6102
+ // this the one position in the pattern that a second space defeated.
6103
+ ["auth_bearer_token", /(?<=Authorization["']?[ \t]{0,8}:[ \t]{0,8}["']?[ \t]{0,8}(?:Bearer|token)[ \t]{1,8})[A-Za-z0-9\-._~+/]{10,}=*/gi],
5987
6104
  ["auth_basic_token", /(?<=Authorization["']?[ \t]{0,8}:[ \t]{0,8}["']?[ \t]{0,8}Basic[ \t])[A-Za-z0-9+/]{6,}=*/gi],
5988
6105
  // JWTs have no distinctive prefix of their own, but the base64url encoding of the smallest
5989
6106
  // realistic header ('{"alg":' or similar) always starts with "eyJ", so that's the practical
@@ -6037,7 +6154,22 @@ var SECRET_PATTERNS = [
6037
6154
  // SECRET_KEY=, and DB_PASSWORD_HASH= all passed through in full. That class matches
6038
6155
  // identifier characters only, so prose that merely mentions a keyword still never reaches
6039
6156
  // a separator and stays unredacted. api[_-]?key covers the apikey and api-key spellings too.
6040
- ["generic_secret_assignment", /(?<=(?:password|passwd|secret|api[_-]?key|access[_-]?token|refresh[_-]?token|id[_-]?token)[a-z0-9_-]{0,64}["']?[ \t]{0,8}[:=][ \t]{0,8}["']?)(?:\\[^\n]|[^\s\\&;#'"[\],{}:]){4,}/gi]
6157
+ // `& ; # , :` play two incompatible roles. They separate one field from the next (a query
6158
+ // string, a cookie header, an inline env list), and they are also perfectly ordinary password
6159
+ // characters. Rejecting them outright got the first role right and the second badly wrong: the
6160
+ // match stopped at the first one and left everything after it in plain text, so
6161
+ // `password=corr&horse&battery` redacted four characters and printed the rest, and
6162
+ // `DB_PASSWORD=Aa1:xyz` matched nothing at all because the run before the `:` was under the
6163
+ // four-character floor. A tail left sitting in the open is the outcome this module's header
6164
+ // calls worse than no redaction, because it reads as handled.
6165
+ //
6166
+ // So the separator role is decided by what follows rather than assumed: one of these characters
6167
+ // ends the value only when the next thing along is another `name=` / `name:` pair, which is what
6168
+ // an actual field separator is always followed by. `,OTHER=public` and `; other=1` still end it;
6169
+ // the `&` in the middle of a passphrase does not. Whitespace, quotes and brackets are unchanged
6170
+ // -- they end a value unconditionally, which is also what keeps this pattern from re-matching
6171
+ // the `[REDACTED:...]` placeholder it just wrote.
6172
+ ["generic_secret_assignment", /(?<=(?:password|passwd|secret|api[_-]?key|access[_-]?token|refresh[_-]?token|id[_-]?token)[a-z0-9_-]{0,64}["']?[ \t]{0,8}[:=][ \t]{0,8}["']?)(?:\\[^\n]|[^\s\\&;#,:'"[\]{}]|[&;#,:](?![ \t]*[A-Za-z_][A-Za-z0-9_.-]*[ \t]*[:=])){4,}/gi]
6041
6173
  ];
6042
6174
  function redactSecrets(text) {
6043
6175
  let count = 0;
@@ -6234,6 +6366,7 @@ export {
6234
6366
  assignFlatEndLines,
6235
6367
  propagateEndLinesToSymbols,
6236
6368
  findMatchingBraceEndLine,
6369
+ assignBraceBlockSpans,
6237
6370
  extractIni,
6238
6371
  _lineClosesQuote,
6239
6372
  _detectOpenQuote,
@@ -6,7 +6,7 @@ import {
6
6
  loadBlob,
7
7
  sanitizeFtsQuery,
8
8
  storeBlob
9
- } from "./token-goat-chunk-CN7GUPX6.mjs";
9
+ } from "./token-goat-chunk-I2KCEGIP.mjs";
10
10
  import {
11
11
  SYMBOL_BODY_CHAR_CAP,
12
12
  extractErrorMessage,
@@ -16,7 +16,7 @@ import {
16
16
  redactSecrets,
17
17
  runGit,
18
18
  shortFingerprint
19
- } from "./token-goat-chunk-7FWBSPCT.mjs";
19
+ } from "./token-goat-chunk-K7W3P2TJ.mjs";
20
20
  import {
21
21
  registerReset
22
22
  } from "./token-goat-chunk-AO2QD2AG.mjs";
@@ -10,11 +10,11 @@ import {
10
10
  selectFilter,
11
11
  shlexSplit,
12
12
  wrappedShell
13
- } from "./token-goat-chunk-WA2ER6TZ.mjs";
13
+ } from "./token-goat-chunk-DQIT5JIF.mjs";
14
14
  import {
15
15
  loadConfig,
16
16
  recordStat
17
- } from "./token-goat-chunk-7FWBSPCT.mjs";
17
+ } from "./token-goat-chunk-K7W3P2TJ.mjs";
18
18
  import "./token-goat-chunk-AO2QD2AG.mjs";
19
19
  import "./token-goat-chunk-AEX54RUZ.mjs";
20
20
 
@@ -2,13 +2,15 @@ import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
3
  import {
4
4
  canRunWrappedShell,
5
+ compressOutput,
5
6
  dedupeConsecutive,
6
7
  detectFromCommand,
8
+ filterByName,
7
9
  hasBareBackgroundOrNewline,
8
10
  isRewriteWorthwhile,
9
11
  resolveMinNetSavingsBytes,
10
12
  shlexSplit
11
- } from "./token-goat-chunk-WA2ER6TZ.mjs";
13
+ } from "./token-goat-chunk-DQIT5JIF.mjs";
12
14
  import {
13
15
  BASH_OUTPUT_SUBDIR,
14
16
  HOOK_EVENTS,
@@ -27,7 +29,7 @@ import {
27
29
  storeBashOutput,
28
30
  storeWebOutput,
29
31
  summarizeOutputDelta
30
- } from "./token-goat-chunk-OA3GFKP2.mjs";
32
+ } from "./token-goat-chunk-SIHYQCTM.mjs";
31
33
  import {
32
34
  BODY_FIRST_TOOL_RESPONSE_KEYS,
33
35
  OUTPUT_FIRST_TOOL_RESPONSE_KEYS,
@@ -117,7 +119,7 @@ import {
117
119
  wasCliReadThisSession,
118
120
  wasFileReadThisSession,
119
121
  wasHintShown
120
- } from "./token-goat-chunk-CN7GUPX6.mjs";
122
+ } from "./token-goat-chunk-I2KCEGIP.mjs";
121
123
  import {
122
124
  VERSION,
123
125
  detectHarness,
@@ -136,7 +138,7 @@ import {
136
138
  runGit,
137
139
  shortFingerprint,
138
140
  toKB
139
- } from "./token-goat-chunk-7FWBSPCT.mjs";
141
+ } from "./token-goat-chunk-K7W3P2TJ.mjs";
140
142
  import "./token-goat-chunk-AO2QD2AG.mjs";
141
143
  import "./token-goat-chunk-AEX54RUZ.mjs";
142
144
 
@@ -576,7 +578,7 @@ import crypto from "node:crypto";
576
578
  var TRACKED_SKILL = "token-goat";
577
579
  var MAX_COMMANDS_SHOWN = 8;
578
580
  async function currentCommandNames() {
579
- const { buildProgram } = await import("./token-goat-chunk-CKRATWCJ.mjs");
581
+ const { buildProgram } = await import("./token-goat-chunk-YF67EWRH.mjs");
580
582
  return flattenCommandNames(buildCommandManifest(buildProgram()));
581
583
  }
582
584
  async function recordSkillVersionSnapshot(sessionId, skillName) {
@@ -7905,12 +7907,151 @@ function extractRgStructuralSearch(cmd) {
7905
7907
  function extractGrepPipeChain(cmd) {
7906
7908
  return /^(?:rg|grep)\b.*\|\s*(?:rg|grep)\b/.test(cmd);
7907
7909
  }
7910
+ function splitCommandWords(cmd) {
7911
+ const words = [];
7912
+ let cur = "";
7913
+ let quote = null;
7914
+ let started = false;
7915
+ for (let i = 0; i < cmd.length; i++) {
7916
+ const ch = cmd[i];
7917
+ if (quote !== null) {
7918
+ if (ch === "\\" && quote === '"' && i + 1 < cmd.length) {
7919
+ cur += cmd[i + 1];
7920
+ i++;
7921
+ continue;
7922
+ }
7923
+ if (ch === quote) quote = null;
7924
+ else cur += ch;
7925
+ continue;
7926
+ }
7927
+ if (ch === "\\" && i + 1 < cmd.length) {
7928
+ cur += cmd[i + 1];
7929
+ i++;
7930
+ started = true;
7931
+ continue;
7932
+ }
7933
+ if (ch === '"' || ch === "'") {
7934
+ quote = ch;
7935
+ started = true;
7936
+ continue;
7937
+ }
7938
+ if (/\s/.test(ch)) {
7939
+ if (started) words.push(cur);
7940
+ cur = "";
7941
+ started = false;
7942
+ continue;
7943
+ }
7944
+ cur += ch;
7945
+ started = true;
7946
+ }
7947
+ if (started) words.push(cur);
7948
+ return words;
7949
+ }
7950
+ var CURL_VALUE_FLAGS = /* @__PURE__ */ new Set([
7951
+ "-H",
7952
+ "--header",
7953
+ "-A",
7954
+ "--user-agent",
7955
+ "-e",
7956
+ "--referer",
7957
+ "-b",
7958
+ "--cookie",
7959
+ "-c",
7960
+ "--cookie-jar",
7961
+ "-o",
7962
+ "--output",
7963
+ "--output-dir",
7964
+ "-u",
7965
+ "--user",
7966
+ "-U",
7967
+ "--proxy-user",
7968
+ "-x",
7969
+ "--proxy",
7970
+ "-X",
7971
+ "--request",
7972
+ "-d",
7973
+ "--data",
7974
+ "--data-raw",
7975
+ "--data-binary",
7976
+ "--data-urlencode",
7977
+ "-F",
7978
+ "--form",
7979
+ "-T",
7980
+ "--upload-file",
7981
+ "-K",
7982
+ "--config",
7983
+ "-w",
7984
+ "--write-out",
7985
+ "-m",
7986
+ "--max-time",
7987
+ "--connect-to",
7988
+ "--resolve",
7989
+ "--retry",
7990
+ "--cacert",
7991
+ "-E",
7992
+ "--cert",
7993
+ "--key",
7994
+ "--range",
7995
+ "-r",
7996
+ "--interface",
7997
+ // Options whose own value is a URL or a host. Leaving these out was the same defect as reading
7998
+ // the first URL in the string: `curl --doh-url https://doh/ -o f https://target` answered with
7999
+ // the DoH resolver rather than the file being fetched. `--url-query` belongs here too -- it
8000
+ // appends query data to the request, it does not name the request target.
8001
+ "--url-query",
8002
+ "--doh-url",
8003
+ "--preproxy",
8004
+ "--proxy1.0",
8005
+ "--socks4",
8006
+ "--socks4a",
8007
+ "--socks5",
8008
+ "--socks5-hostname",
8009
+ "--proxy-header",
8010
+ "--noproxy",
8011
+ "--dns-servers",
8012
+ "--aws-sigv4",
8013
+ "--proxy-cacert",
8014
+ "--proxy-cert",
8015
+ "--proxy-key",
8016
+ "--oauth2-bearer",
8017
+ "--hsts",
8018
+ "--alt-svc",
8019
+ "--etag-save",
8020
+ "--etag-compare",
8021
+ "--trace",
8022
+ "--trace-ascii",
8023
+ "--dump-header",
8024
+ "-D"
8025
+ ]);
7908
8026
  function extractCurlUrl(cmd) {
7909
- const m = /(https?:\/\/[^\s'"]+)/.exec(cmd);
7910
- return m?.[1] ?? null;
8027
+ const words = splitCommandWords(cmd);
8028
+ let positional = null;
8029
+ for (let i = 0; i < words.length; i++) {
8030
+ const w = words[i];
8031
+ if (w === "--url") {
8032
+ const next = words[i + 1];
8033
+ if (next !== void 0 && /^https?:\/\//.test(next)) return next;
8034
+ i++;
8035
+ continue;
8036
+ }
8037
+ const eq = w.indexOf("=");
8038
+ if (w.startsWith("--") && eq > 0) {
8039
+ if (w.slice(0, eq) === "--url" && /^https?:\/\//.test(w.slice(eq + 1))) return w.slice(eq + 1);
8040
+ continue;
8041
+ }
8042
+ if (CURL_VALUE_FLAGS.has(w)) {
8043
+ i++;
8044
+ continue;
8045
+ }
8046
+ if (w.startsWith("-") && w !== "-") continue;
8047
+ if (/^https?:\/\//.test(w)) return w;
8048
+ positional ??= /https?:\/\/[^\s'")}`]+/.exec(w)?.[0] ?? null;
8049
+ }
8050
+ if (positional !== null) return positional;
8051
+ return null;
7911
8052
  }
7912
8053
  function extractTgSurgicalRead(cmd, cwd) {
7913
- const m = /^token-goat\s+(symbol|read|section|skill-body|skill-compact|map)(?:\s+(.*))?$/.exec(cmd);
8054
+ const m = /^(?:token-goat|tg)\s+(symbol|read|section|skill-body|skill-compact|map)(?:\s+(.*))?$/.exec(cmd);
7914
8055
  if (!m) return null;
7915
8056
  const sub = m[1];
7916
8057
  const rest = (m[2] ?? "").trim();
@@ -7989,9 +8130,9 @@ function extractCurlDownload(cmd) {
7989
8130
  const outputPath = outputMatch[1] ?? outputMatch[2] ?? outputMatch[3];
7990
8131
  if (!outputPath) return null;
7991
8132
  if (curlHasUnsafeFlags(cmd)) return null;
7992
- const urlMatch = /(https?:\/\/[^\s'"]+)/.exec(cmd);
7993
- if (!urlMatch?.[1]) return null;
7994
- return { url: urlMatch[1], outputPath };
8133
+ const url = extractCurlUrl(cmd);
8134
+ if (url === null) return null;
8135
+ return { url, outputPath };
7995
8136
  }
7996
8137
  function isTscCommand(cmd) {
7997
8138
  return /^\s*tsc(\s|$)/i.test(cmd);
@@ -8044,9 +8185,34 @@ function maybeCompressRewrite(event, rawCmd, cmd) {
8044
8185
  const wrapped = `token-goat compress -f ${filterName} --timeout ${cfg.timeout_seconds} -c ${shellQuoteSingle(rawCmd)}`;
8045
8186
  return { hookType: "rewriteInput", updatedInput: { ...event.toolInput, command: wrapped } };
8046
8187
  }
8188
+ async function maybeCompressCompoundOutput(cmd, output, exitCode, cwd, cacheMinBytes) {
8189
+ if (process.env["TOKEN_GOAT_BASH_COMPRESS"] === "0") return null;
8190
+ if (isCompressibleSingleCommand(cmd)) return null;
8191
+ if (exitCode !== null && exitCode !== 0) return null;
8192
+ let cfg;
8193
+ try {
8194
+ cfg = loadConfig().bash_compress;
8195
+ } catch {
8196
+ return null;
8197
+ }
8198
+ if (!cfg.enabled || cfg.disabled_filters.includes("generic")) return null;
8199
+ if (Buffer.byteLength(output, "utf-8") < cacheMinBytes) return null;
8200
+ const filter3 = filterByName("generic");
8201
+ if (filter3 === null) return null;
8202
+ const compressed = compressOutput(filter3, output, "", exitCode ?? 0, [], {
8203
+ maxLines: cfg.max_lines,
8204
+ maxBytes: cfg.max_bytes
8205
+ });
8206
+ const minNet = resolveMinNetSavingsBytes();
8207
+ if (!compressed.worthApplying(minNet)) return null;
8208
+ const id = await storeBashOutput(cmd, output, exitCode ?? 0, cwd);
8209
+ recordStat("bash_compress:generic", compressed.bytesSaved, compressed.tokensSaved);
8210
+ const body = compressed.withMarker(minNet) + "\n[token-goat] full output: bash-output " + id + " --full";
8211
+ return { hookType: "rewriteOutput", updatedOutput: body };
8212
+ }
8047
8213
  function unwrapCompressCommand(executed) {
8048
8214
  const t = executed.trim();
8049
- if (!/^token-goat\s+compress\b/.test(t)) return null;
8215
+ if (!/^(?:token-goat|tg)\s+compress\b/.test(t)) return null;
8050
8216
  let argv;
8051
8217
  try {
8052
8218
  argv = shlexSplit(t);
@@ -8098,6 +8264,28 @@ function detectUnbalancedShellSyntax(cmd) {
8098
8264
  i = j;
8099
8265
  continue;
8100
8266
  }
8267
+ if (ch === "$" && cmd[i + 1] === "'") {
8268
+ let j = i + 2;
8269
+ let closed = false;
8270
+ while (j < cmd.length) {
8271
+ if (cmd[j] === "\\") {
8272
+ j += 2;
8273
+ continue;
8274
+ }
8275
+ if (cmd[j] === "'") {
8276
+ j++;
8277
+ closed = true;
8278
+ break;
8279
+ }
8280
+ j++;
8281
+ }
8282
+ if (!closed) {
8283
+ inSingle = true;
8284
+ break;
8285
+ }
8286
+ i = j;
8287
+ continue;
8288
+ }
8101
8289
  if (ch === "#" && (i === 0 || /\s/.test(cmd[i - 1] ?? ""))) {
8102
8290
  const nl2 = cmd.indexOf("\n", i);
8103
8291
  i = nl2 === -1 ? cmd.length : nl2 + 1;
@@ -8704,7 +8892,11 @@ async function postBashHandler(event) {
8704
8892
  recordBashOutput(gitScopedCacheHash, gitScopedCacheId, Buffer.byteLength(output, "utf-8"));
8705
8893
  }
8706
8894
  const isMonitoring = getMonitoringRecallHint(cmd) !== null;
8707
- if (!isMonitoring && !isBuildCommand(cmd) && !isCurlGetCommand(cmd)) return passOutput();
8895
+ if (!isMonitoring && !isBuildCommand(cmd) && !isCurlGetCommand(cmd)) {
8896
+ const compound = await maybeCompressCompoundOutput(cmd, output, exitCode, cwd, cacheMinBytes);
8897
+ if (compound !== null) return compound;
8898
+ return passOutput();
8899
+ }
8708
8900
  if (Buffer.byteLength(output, "utf-8") < cacheMinBytes) return passOutput();
8709
8901
  const cacheKey = isCurlGetCommand(cmd) ? extractCurlUrl(cmd) ?? cmd : stripOutputPipeline(cmd);
8710
8902
  const simpleHash = shortFingerprint(cacheKey);
@@ -9830,6 +10022,9 @@ async function relayInProcess(eventName, rawPayload) {
9830
10022
  async function relay(eventName) {
9831
10023
  try {
9832
10024
  if (!isHookEventName(eventName)) {
10025
+ console.error(
10026
+ `[relay] unknown hook event '${eventName}'; nothing ran. Valid events: ${HOOK_EVENTS.join(", ")}`
10027
+ );
9833
10028
  process.stdout.write("{}");
9834
10029
  return;
9835
10030
  }
@@ -7,11 +7,11 @@ import {
7
7
  expandGlobs,
8
8
  leftoverIntegrations,
9
9
  run
10
- } from "./token-goat-chunk-GXBPEQR2.mjs";
11
- import "./token-goat-chunk-IYYQOPY4.mjs";
12
- import "./token-goat-chunk-OA3GFKP2.mjs";
13
- import "./token-goat-chunk-CN7GUPX6.mjs";
14
- import "./token-goat-chunk-7FWBSPCT.mjs";
10
+ } from "./token-goat-chunk-HW4VUKJ5.mjs";
11
+ import "./token-goat-chunk-D5IZEGN2.mjs";
12
+ import "./token-goat-chunk-SIHYQCTM.mjs";
13
+ import "./token-goat-chunk-I2KCEGIP.mjs";
14
+ import "./token-goat-chunk-K7W3P2TJ.mjs";
15
15
  import "./token-goat-chunk-AO2QD2AG.mjs";
16
16
  import "./token-goat-chunk-AEX54RUZ.mjs";
17
17
  export {