token-goat 2.2.3 → 2.2.4
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.
- package/dist/token-goat.mjs +2092 -390
- package/package.json +1 -1
package/dist/token-goat.mjs
CHANGED
|
@@ -981,8 +981,8 @@ var require_command = __commonJS({
|
|
|
981
981
|
init_define_import_meta_env();
|
|
982
982
|
var EventEmitter = __require("node:events").EventEmitter;
|
|
983
983
|
var childProcess = __require("node:child_process");
|
|
984
|
-
var
|
|
985
|
-
var
|
|
984
|
+
var path22 = __require("node:path");
|
|
985
|
+
var fs20 = __require("node:fs");
|
|
986
986
|
var process2 = __require("node:process");
|
|
987
987
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
988
988
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1914,11 +1914,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1914
1914
|
let launchWithNode = false;
|
|
1915
1915
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1916
1916
|
function findFile(baseDir, baseName) {
|
|
1917
|
-
const localBin =
|
|
1918
|
-
if (
|
|
1919
|
-
if (sourceExt.includes(
|
|
1917
|
+
const localBin = path22.resolve(baseDir, baseName);
|
|
1918
|
+
if (fs20.existsSync(localBin)) return localBin;
|
|
1919
|
+
if (sourceExt.includes(path22.extname(baseName))) return void 0;
|
|
1920
1920
|
const foundExt = sourceExt.find(
|
|
1921
|
-
(ext) =>
|
|
1921
|
+
(ext) => fs20.existsSync(`${localBin}${ext}`)
|
|
1922
1922
|
);
|
|
1923
1923
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1924
1924
|
return void 0;
|
|
@@ -1930,21 +1930,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1930
1930
|
if (this._scriptPath) {
|
|
1931
1931
|
let resolvedScriptPath;
|
|
1932
1932
|
try {
|
|
1933
|
-
resolvedScriptPath =
|
|
1933
|
+
resolvedScriptPath = fs20.realpathSync(this._scriptPath);
|
|
1934
1934
|
} catch (err2) {
|
|
1935
1935
|
resolvedScriptPath = this._scriptPath;
|
|
1936
1936
|
}
|
|
1937
|
-
executableDir =
|
|
1938
|
-
|
|
1937
|
+
executableDir = path22.resolve(
|
|
1938
|
+
path22.dirname(resolvedScriptPath),
|
|
1939
1939
|
executableDir
|
|
1940
1940
|
);
|
|
1941
1941
|
}
|
|
1942
1942
|
if (executableDir) {
|
|
1943
1943
|
let localFile = findFile(executableDir, executableFile);
|
|
1944
1944
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
1945
|
-
const legacyName =
|
|
1945
|
+
const legacyName = path22.basename(
|
|
1946
1946
|
this._scriptPath,
|
|
1947
|
-
|
|
1947
|
+
path22.extname(this._scriptPath)
|
|
1948
1948
|
);
|
|
1949
1949
|
if (legacyName !== this._name) {
|
|
1950
1950
|
localFile = findFile(
|
|
@@ -1955,7 +1955,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1955
1955
|
}
|
|
1956
1956
|
executableFile = localFile || executableFile;
|
|
1957
1957
|
}
|
|
1958
|
-
launchWithNode = sourceExt.includes(
|
|
1958
|
+
launchWithNode = sourceExt.includes(path22.extname(executableFile));
|
|
1959
1959
|
let proc;
|
|
1960
1960
|
if (process2.platform !== "win32") {
|
|
1961
1961
|
if (launchWithNode) {
|
|
@@ -2795,7 +2795,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2795
2795
|
* @return {Command}
|
|
2796
2796
|
*/
|
|
2797
2797
|
nameFromFilename(filename) {
|
|
2798
|
-
this._name =
|
|
2798
|
+
this._name = path22.basename(filename, path22.extname(filename));
|
|
2799
2799
|
return this;
|
|
2800
2800
|
}
|
|
2801
2801
|
/**
|
|
@@ -2809,9 +2809,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2809
2809
|
* @param {string} [path]
|
|
2810
2810
|
* @return {(string|null|Command)}
|
|
2811
2811
|
*/
|
|
2812
|
-
executableDir(
|
|
2813
|
-
if (
|
|
2814
|
-
this._executableDir =
|
|
2812
|
+
executableDir(path23) {
|
|
2813
|
+
if (path23 === void 0) return this._executableDir;
|
|
2814
|
+
this._executableDir = path23;
|
|
2815
2815
|
return this;
|
|
2816
2816
|
}
|
|
2817
2817
|
/**
|
|
@@ -3158,27 +3158,27 @@ var require_filesystem = __commonJS({
|
|
|
3158
3158
|
"node_modules/detect-libc/lib/filesystem.js"(exports, module) {
|
|
3159
3159
|
"use strict";
|
|
3160
3160
|
init_define_import_meta_env();
|
|
3161
|
-
var
|
|
3161
|
+
var fs20 = __require("fs");
|
|
3162
3162
|
var LDD_PATH = "/usr/bin/ldd";
|
|
3163
3163
|
var SELF_PATH = "/proc/self/exe";
|
|
3164
3164
|
var MAX_LENGTH = 2048;
|
|
3165
|
-
var
|
|
3166
|
-
const fd =
|
|
3165
|
+
var readFileSync16 = (path22) => {
|
|
3166
|
+
const fd = fs20.openSync(path22, "r");
|
|
3167
3167
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
3168
|
-
const bytesRead =
|
|
3169
|
-
|
|
3168
|
+
const bytesRead = fs20.readSync(fd, buffer, 0, MAX_LENGTH, 0);
|
|
3169
|
+
fs20.close(fd, () => {
|
|
3170
3170
|
});
|
|
3171
3171
|
return buffer.subarray(0, bytesRead);
|
|
3172
3172
|
};
|
|
3173
|
-
var readFile3 = (
|
|
3174
|
-
|
|
3173
|
+
var readFile3 = (path22) => new Promise((resolve8, reject) => {
|
|
3174
|
+
fs20.open(path22, "r", (err2, fd) => {
|
|
3175
3175
|
if (err2) {
|
|
3176
3176
|
reject(err2);
|
|
3177
3177
|
} else {
|
|
3178
3178
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3179
|
+
fs20.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
|
|
3180
|
+
resolve8(buffer.subarray(0, bytesRead));
|
|
3181
|
+
fs20.close(fd, () => {
|
|
3182
3182
|
});
|
|
3183
3183
|
});
|
|
3184
3184
|
}
|
|
@@ -3187,7 +3187,7 @@ var require_filesystem = __commonJS({
|
|
|
3187
3187
|
module.exports = {
|
|
3188
3188
|
LDD_PATH,
|
|
3189
3189
|
SELF_PATH,
|
|
3190
|
-
readFileSync:
|
|
3190
|
+
readFileSync: readFileSync16,
|
|
3191
3191
|
readFile: readFile3
|
|
3192
3192
|
};
|
|
3193
3193
|
}
|
|
@@ -3238,7 +3238,7 @@ var require_detect_libc = __commonJS({
|
|
|
3238
3238
|
init_define_import_meta_env();
|
|
3239
3239
|
var childProcess = __require("child_process");
|
|
3240
3240
|
var { isLinux, getReport } = require_process();
|
|
3241
|
-
var { LDD_PATH, SELF_PATH, readFile: readFile3, readFileSync:
|
|
3241
|
+
var { LDD_PATH, SELF_PATH, readFile: readFile3, readFileSync: readFileSync16 } = require_filesystem();
|
|
3242
3242
|
var { interpreterPath } = require_elf();
|
|
3243
3243
|
var cachedFamilyInterpreter;
|
|
3244
3244
|
var cachedFamilyFilesystem;
|
|
@@ -3247,10 +3247,10 @@ var require_detect_libc = __commonJS({
|
|
|
3247
3247
|
var commandOut = "";
|
|
3248
3248
|
var safeCommand = () => {
|
|
3249
3249
|
if (!commandOut) {
|
|
3250
|
-
return new Promise((
|
|
3250
|
+
return new Promise((resolve8) => {
|
|
3251
3251
|
childProcess.exec(command, (err2, out2) => {
|
|
3252
3252
|
commandOut = err2 ? " " : out2;
|
|
3253
|
-
|
|
3253
|
+
resolve8(commandOut);
|
|
3254
3254
|
});
|
|
3255
3255
|
});
|
|
3256
3256
|
}
|
|
@@ -3292,11 +3292,11 @@ var require_detect_libc = __commonJS({
|
|
|
3292
3292
|
}
|
|
3293
3293
|
return null;
|
|
3294
3294
|
};
|
|
3295
|
-
var familyFromInterpreterPath = (
|
|
3296
|
-
if (
|
|
3297
|
-
if (
|
|
3295
|
+
var familyFromInterpreterPath = (path22) => {
|
|
3296
|
+
if (path22) {
|
|
3297
|
+
if (path22.includes("/ld-musl-")) {
|
|
3298
3298
|
return MUSL;
|
|
3299
|
-
} else if (
|
|
3299
|
+
} else if (path22.includes("/ld-linux-")) {
|
|
3300
3300
|
return GLIBC;
|
|
3301
3301
|
}
|
|
3302
3302
|
}
|
|
@@ -3330,7 +3330,7 @@ var require_detect_libc = __commonJS({
|
|
|
3330
3330
|
}
|
|
3331
3331
|
cachedFamilyFilesystem = null;
|
|
3332
3332
|
try {
|
|
3333
|
-
const lddContent =
|
|
3333
|
+
const lddContent = readFileSync16(LDD_PATH);
|
|
3334
3334
|
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
|
|
3335
3335
|
} catch (e) {
|
|
3336
3336
|
}
|
|
@@ -3343,8 +3343,8 @@ var require_detect_libc = __commonJS({
|
|
|
3343
3343
|
cachedFamilyInterpreter = null;
|
|
3344
3344
|
try {
|
|
3345
3345
|
const selfContent = await readFile3(SELF_PATH);
|
|
3346
|
-
const
|
|
3347
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
3346
|
+
const path22 = interpreterPath(selfContent);
|
|
3347
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path22);
|
|
3348
3348
|
} catch (e) {
|
|
3349
3349
|
}
|
|
3350
3350
|
return cachedFamilyInterpreter;
|
|
@@ -3355,9 +3355,9 @@ var require_detect_libc = __commonJS({
|
|
|
3355
3355
|
}
|
|
3356
3356
|
cachedFamilyInterpreter = null;
|
|
3357
3357
|
try {
|
|
3358
|
-
const selfContent =
|
|
3359
|
-
const
|
|
3360
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
3358
|
+
const selfContent = readFileSync16(SELF_PATH);
|
|
3359
|
+
const path22 = interpreterPath(selfContent);
|
|
3360
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path22);
|
|
3361
3361
|
} catch (e) {
|
|
3362
3362
|
}
|
|
3363
3363
|
return cachedFamilyInterpreter;
|
|
@@ -3419,7 +3419,7 @@ var require_detect_libc = __commonJS({
|
|
|
3419
3419
|
}
|
|
3420
3420
|
cachedVersionFilesystem = null;
|
|
3421
3421
|
try {
|
|
3422
|
-
const lddContent =
|
|
3422
|
+
const lddContent = readFileSync16(LDD_PATH);
|
|
3423
3423
|
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
|
|
3424
3424
|
if (versionMatch) {
|
|
3425
3425
|
cachedVersionFilesystem = versionMatch[1];
|
|
@@ -3965,7 +3965,7 @@ var require_parse = __commonJS({
|
|
|
3965
3965
|
"use strict";
|
|
3966
3966
|
init_define_import_meta_env();
|
|
3967
3967
|
var SemVer = require_semver();
|
|
3968
|
-
var
|
|
3968
|
+
var parse3 = (version, options, throwErrors = false) => {
|
|
3969
3969
|
if (version instanceof SemVer) {
|
|
3970
3970
|
return version;
|
|
3971
3971
|
}
|
|
@@ -3978,7 +3978,7 @@ var require_parse = __commonJS({
|
|
|
3978
3978
|
throw er;
|
|
3979
3979
|
}
|
|
3980
3980
|
};
|
|
3981
|
-
module.exports =
|
|
3981
|
+
module.exports = parse3;
|
|
3982
3982
|
}
|
|
3983
3983
|
});
|
|
3984
3984
|
|
|
@@ -3988,9 +3988,9 @@ var require_coerce = __commonJS({
|
|
|
3988
3988
|
"use strict";
|
|
3989
3989
|
init_define_import_meta_env();
|
|
3990
3990
|
var SemVer = require_semver();
|
|
3991
|
-
var
|
|
3991
|
+
var parse3 = require_parse();
|
|
3992
3992
|
var { safeRe: re, t } = require_re();
|
|
3993
|
-
var
|
|
3993
|
+
var coerce2 = (version, options) => {
|
|
3994
3994
|
if (version instanceof SemVer) {
|
|
3995
3995
|
return version;
|
|
3996
3996
|
}
|
|
@@ -4023,9 +4023,9 @@ var require_coerce = __commonJS({
|
|
|
4023
4023
|
const patch = match[4] || "0";
|
|
4024
4024
|
const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : "";
|
|
4025
4025
|
const build = options.includePrerelease && match[6] ? `+${match[6]}` : "";
|
|
4026
|
-
return
|
|
4026
|
+
return parse3(`${major}.${minor}.${patch}${prerelease}${build}`, options);
|
|
4027
4027
|
};
|
|
4028
|
-
module.exports =
|
|
4028
|
+
module.exports = coerce2;
|
|
4029
4029
|
}
|
|
4030
4030
|
});
|
|
4031
4031
|
|
|
@@ -4947,7 +4947,7 @@ var require_libvips = __commonJS({
|
|
|
4947
4947
|
"node_modules/sharp/lib/libvips.js"(exports, module) {
|
|
4948
4948
|
"use strict";
|
|
4949
4949
|
init_define_import_meta_env();
|
|
4950
|
-
var { spawnSync:
|
|
4950
|
+
var { spawnSync: spawnSync4 } = __require("node:child_process");
|
|
4951
4951
|
var { createHash: createHash3 } = __require("node:crypto");
|
|
4952
4952
|
var semverCoerce = require_coerce();
|
|
4953
4953
|
var semverGreaterThanOrEqualTo = require_gte();
|
|
@@ -5032,7 +5032,7 @@ var require_libvips = __commonJS({
|
|
|
5032
5032
|
};
|
|
5033
5033
|
var isRosetta = () => {
|
|
5034
5034
|
if (process.platform === "darwin" && process.arch === "x64") {
|
|
5035
|
-
const translated =
|
|
5035
|
+
const translated = spawnSync4("sysctl sysctl.proc_translated", spawnSyncOptions).stdout;
|
|
5036
5036
|
return (translated || "").trim() === "sysctl.proc_translated: 1";
|
|
5037
5037
|
}
|
|
5038
5038
|
return false;
|
|
@@ -5047,13 +5047,13 @@ var require_libvips = __commonJS({
|
|
|
5047
5047
|
}
|
|
5048
5048
|
return "";
|
|
5049
5049
|
};
|
|
5050
|
-
var spawnRebuild = () =>
|
|
5050
|
+
var spawnRebuild = () => spawnSync4(`node-gyp rebuild --directory=src ${isEmscripten() ? "--nodedir=emscripten" : ""}`, {
|
|
5051
5051
|
...spawnSyncOptions,
|
|
5052
5052
|
stdio: "inherit"
|
|
5053
5053
|
}).status;
|
|
5054
5054
|
var globalLibvipsVersion = () => {
|
|
5055
5055
|
if (process.platform !== "win32") {
|
|
5056
|
-
const globalLibvipsVersion2 =
|
|
5056
|
+
const globalLibvipsVersion2 = spawnSync4("pkg-config --modversion vips-cpp", {
|
|
5057
5057
|
...spawnSyncOptions,
|
|
5058
5058
|
env: {
|
|
5059
5059
|
...process.env,
|
|
@@ -5067,7 +5067,7 @@ var require_libvips = __commonJS({
|
|
|
5067
5067
|
};
|
|
5068
5068
|
var pkgConfigPath = () => {
|
|
5069
5069
|
if (process.platform !== "win32") {
|
|
5070
|
-
const brewPkgConfigPath =
|
|
5070
|
+
const brewPkgConfigPath = spawnSync4(
|
|
5071
5071
|
'which brew >/dev/null 2>&1 && brew environment --plain | grep PKG_CONFIG_LIBDIR | cut -d" " -f2',
|
|
5072
5072
|
spawnSyncOptions
|
|
5073
5073
|
).stdout || "";
|
|
@@ -5138,9 +5138,9 @@ var require_sharp = __commonJS({
|
|
|
5138
5138
|
];
|
|
5139
5139
|
var sharp;
|
|
5140
5140
|
var errors = [];
|
|
5141
|
-
for (const
|
|
5141
|
+
for (const path22 of paths) {
|
|
5142
5142
|
try {
|
|
5143
|
-
sharp = __require(
|
|
5143
|
+
sharp = __require(path22);
|
|
5144
5144
|
break;
|
|
5145
5145
|
} catch (err2) {
|
|
5146
5146
|
errors.push(err2);
|
|
@@ -5149,7 +5149,7 @@ var require_sharp = __commonJS({
|
|
|
5149
5149
|
if (sharp) {
|
|
5150
5150
|
module.exports = sharp;
|
|
5151
5151
|
} else {
|
|
5152
|
-
const [isLinux, isMacOs, isWindows2] = ["linux", "darwin", "win32"].map((
|
|
5152
|
+
const [isLinux, isMacOs, isWindows2] = ["linux", "darwin", "win32"].map((os7) => runtimePlatform.startsWith(os7));
|
|
5153
5153
|
const help = [`Could not load the "sharp" module using the ${runtimePlatform} runtime`];
|
|
5154
5154
|
errors.forEach((err2) => {
|
|
5155
5155
|
if (err2.code !== "MODULE_NOT_FOUND") {
|
|
@@ -5166,15 +5166,15 @@ var require_sharp = __commonJS({
|
|
|
5166
5166
|
` Requires ${expected}`
|
|
5167
5167
|
);
|
|
5168
5168
|
} else if (prebuiltPlatforms.includes(runtimePlatform)) {
|
|
5169
|
-
const [
|
|
5170
|
-
const libc =
|
|
5169
|
+
const [os7, cpu] = runtimePlatform.split("-");
|
|
5170
|
+
const libc = os7.endsWith("musl") ? " --libc=musl" : "";
|
|
5171
5171
|
help.push(
|
|
5172
5172
|
"- Ensure optional dependencies can be installed:",
|
|
5173
5173
|
" npm install --include=optional sharp",
|
|
5174
5174
|
"- Ensure your package manager supports multi-platform installation:",
|
|
5175
5175
|
" See https://sharp.pixelplumbing.com/install#cross-platform",
|
|
5176
5176
|
"- Add platform-specific dependencies:",
|
|
5177
|
-
` npm install --os=${
|
|
5177
|
+
` npm install --os=${os7.replace("musl", "")}${libc} --cpu=${cpu} sharp`
|
|
5178
5178
|
);
|
|
5179
5179
|
} else {
|
|
5180
5180
|
help.push(
|
|
@@ -6552,15 +6552,15 @@ var require_route = __commonJS({
|
|
|
6552
6552
|
};
|
|
6553
6553
|
}
|
|
6554
6554
|
function wrapConversion(toModel, graph) {
|
|
6555
|
-
const
|
|
6555
|
+
const path22 = [graph[toModel].parent, toModel];
|
|
6556
6556
|
let fn = conversions[graph[toModel].parent][toModel];
|
|
6557
6557
|
let cur = graph[toModel].parent;
|
|
6558
6558
|
while (graph[cur].parent) {
|
|
6559
|
-
|
|
6559
|
+
path22.unshift(graph[cur].parent);
|
|
6560
6560
|
fn = link(conversions[graph[cur].parent][cur], fn);
|
|
6561
6561
|
cur = graph[cur].parent;
|
|
6562
6562
|
}
|
|
6563
|
-
fn.conversion =
|
|
6563
|
+
fn.conversion = path22;
|
|
6564
6564
|
return fn;
|
|
6565
6565
|
}
|
|
6566
6566
|
module.exports = function(fromModel) {
|
|
@@ -7392,14 +7392,14 @@ var require_input = __commonJS({
|
|
|
7392
7392
|
return this;
|
|
7393
7393
|
} else {
|
|
7394
7394
|
if (this._isStreamInput()) {
|
|
7395
|
-
return new Promise((
|
|
7395
|
+
return new Promise((resolve8, reject) => {
|
|
7396
7396
|
const finished = () => {
|
|
7397
7397
|
this._flattenBufferIn();
|
|
7398
7398
|
sharp.metadata(this.options, (err2, metadata2) => {
|
|
7399
7399
|
if (err2) {
|
|
7400
7400
|
reject(is.nativeError(err2, stack));
|
|
7401
7401
|
} else {
|
|
7402
|
-
|
|
7402
|
+
resolve8(metadata2);
|
|
7403
7403
|
}
|
|
7404
7404
|
});
|
|
7405
7405
|
};
|
|
@@ -7410,12 +7410,12 @@ var require_input = __commonJS({
|
|
|
7410
7410
|
}
|
|
7411
7411
|
});
|
|
7412
7412
|
} else {
|
|
7413
|
-
return new Promise((
|
|
7413
|
+
return new Promise((resolve8, reject) => {
|
|
7414
7414
|
sharp.metadata(this.options, (err2, metadata2) => {
|
|
7415
7415
|
if (err2) {
|
|
7416
7416
|
reject(is.nativeError(err2, stack));
|
|
7417
7417
|
} else {
|
|
7418
|
-
|
|
7418
|
+
resolve8(metadata2);
|
|
7419
7419
|
}
|
|
7420
7420
|
});
|
|
7421
7421
|
});
|
|
@@ -7448,25 +7448,25 @@ var require_input = __commonJS({
|
|
|
7448
7448
|
return this;
|
|
7449
7449
|
} else {
|
|
7450
7450
|
if (this._isStreamInput()) {
|
|
7451
|
-
return new Promise((
|
|
7451
|
+
return new Promise((resolve8, reject) => {
|
|
7452
7452
|
this.on("finish", function() {
|
|
7453
7453
|
this._flattenBufferIn();
|
|
7454
7454
|
sharp.stats(this.options, (err2, stats2) => {
|
|
7455
7455
|
if (err2) {
|
|
7456
7456
|
reject(is.nativeError(err2, stack));
|
|
7457
7457
|
} else {
|
|
7458
|
-
|
|
7458
|
+
resolve8(stats2);
|
|
7459
7459
|
}
|
|
7460
7460
|
});
|
|
7461
7461
|
});
|
|
7462
7462
|
});
|
|
7463
7463
|
} else {
|
|
7464
|
-
return new Promise((
|
|
7464
|
+
return new Promise((resolve8, reject) => {
|
|
7465
7465
|
sharp.stats(this.options, (err2, stats2) => {
|
|
7466
7466
|
if (err2) {
|
|
7467
7467
|
reject(is.nativeError(err2, stack));
|
|
7468
7468
|
} else {
|
|
7469
|
-
|
|
7469
|
+
resolve8(stats2);
|
|
7470
7470
|
}
|
|
7471
7471
|
});
|
|
7472
7472
|
});
|
|
@@ -8107,7 +8107,7 @@ var require_operation = __commonJS({
|
|
|
8107
8107
|
}
|
|
8108
8108
|
return this;
|
|
8109
8109
|
}
|
|
8110
|
-
function
|
|
8110
|
+
function normalise2(options) {
|
|
8111
8111
|
if (is.plainObject(options)) {
|
|
8112
8112
|
if (is.defined(options.lower)) {
|
|
8113
8113
|
if (is.number(options.lower) && is.inRange(options.lower, 0, 99)) {
|
|
@@ -8295,7 +8295,7 @@ var require_operation = __commonJS({
|
|
|
8295
8295
|
unflatten,
|
|
8296
8296
|
gamma,
|
|
8297
8297
|
negate,
|
|
8298
|
-
normalise,
|
|
8298
|
+
normalise: normalise2,
|
|
8299
8299
|
normalize,
|
|
8300
8300
|
clahe,
|
|
8301
8301
|
convolve,
|
|
@@ -8464,7 +8464,7 @@ var require_output = __commonJS({
|
|
|
8464
8464
|
"node_modules/sharp/lib/output.js"(exports, module) {
|
|
8465
8465
|
"use strict";
|
|
8466
8466
|
init_define_import_meta_env();
|
|
8467
|
-
var
|
|
8467
|
+
var path22 = __require("node:path");
|
|
8468
8468
|
var is = require_is();
|
|
8469
8469
|
var sharp = require_sharp();
|
|
8470
8470
|
var formats = /* @__PURE__ */ new Map([
|
|
@@ -8495,9 +8495,9 @@ var require_output = __commonJS({
|
|
|
8495
8495
|
let err2;
|
|
8496
8496
|
if (!is.string(fileOut)) {
|
|
8497
8497
|
err2 = new Error("Missing output file path");
|
|
8498
|
-
} else if (is.string(this.options.input.file) &&
|
|
8498
|
+
} else if (is.string(this.options.input.file) && path22.resolve(this.options.input.file) === path22.resolve(fileOut)) {
|
|
8499
8499
|
err2 = new Error("Cannot use same file for input and output");
|
|
8500
|
-
} else if (jp2Regex.test(
|
|
8500
|
+
} else if (jp2Regex.test(path22.extname(fileOut)) && !this.constructor.format.jp2k.output.file) {
|
|
8501
8501
|
err2 = errJp2Save();
|
|
8502
8502
|
}
|
|
8503
8503
|
if (err2) {
|
|
@@ -9242,7 +9242,7 @@ var require_output = __commonJS({
|
|
|
9242
9242
|
return this;
|
|
9243
9243
|
} else {
|
|
9244
9244
|
if (this._isStreamInput()) {
|
|
9245
|
-
return new Promise((
|
|
9245
|
+
return new Promise((resolve8, reject) => {
|
|
9246
9246
|
this.once("finish", () => {
|
|
9247
9247
|
this._flattenBufferIn();
|
|
9248
9248
|
sharp.pipeline(this.options, (err2, data, info) => {
|
|
@@ -9250,24 +9250,24 @@ var require_output = __commonJS({
|
|
|
9250
9250
|
reject(is.nativeError(err2, stack));
|
|
9251
9251
|
} else {
|
|
9252
9252
|
if (this.options.resolveWithObject) {
|
|
9253
|
-
|
|
9253
|
+
resolve8({ data, info });
|
|
9254
9254
|
} else {
|
|
9255
|
-
|
|
9255
|
+
resolve8(data);
|
|
9256
9256
|
}
|
|
9257
9257
|
}
|
|
9258
9258
|
});
|
|
9259
9259
|
});
|
|
9260
9260
|
});
|
|
9261
9261
|
} else {
|
|
9262
|
-
return new Promise((
|
|
9262
|
+
return new Promise((resolve8, reject) => {
|
|
9263
9263
|
sharp.pipeline(this.options, (err2, data, info) => {
|
|
9264
9264
|
if (err2) {
|
|
9265
9265
|
reject(is.nativeError(err2, stack));
|
|
9266
9266
|
} else {
|
|
9267
9267
|
if (this.options.resolveWithObject) {
|
|
9268
|
-
|
|
9268
|
+
resolve8({ data, info });
|
|
9269
9269
|
} else {
|
|
9270
|
-
|
|
9270
|
+
resolve8(data);
|
|
9271
9271
|
}
|
|
9272
9272
|
}
|
|
9273
9273
|
});
|
|
@@ -9475,8 +9475,8 @@ var {
|
|
|
9475
9475
|
} = import_index.default;
|
|
9476
9476
|
|
|
9477
9477
|
// src/cli.ts
|
|
9478
|
-
import * as
|
|
9479
|
-
import * as
|
|
9478
|
+
import * as fs19 from "fs";
|
|
9479
|
+
import * as path21 from "path";
|
|
9480
9480
|
|
|
9481
9481
|
// src/baseline.ts
|
|
9482
9482
|
init_define_import_meta_env();
|
|
@@ -9493,7 +9493,7 @@ init_define_import_meta_env();
|
|
|
9493
9493
|
import { createRequire } from "node:module";
|
|
9494
9494
|
function resolveVersion() {
|
|
9495
9495
|
if (true) {
|
|
9496
|
-
return "2.2.
|
|
9496
|
+
return "2.2.4";
|
|
9497
9497
|
}
|
|
9498
9498
|
const require2 = createRequire(import.meta.url);
|
|
9499
9499
|
const pkg = require2("../package.json");
|
|
@@ -10191,23 +10191,23 @@ function isNoisePath(inputPath) {
|
|
|
10191
10191
|
}
|
|
10192
10192
|
}
|
|
10193
10193
|
const slashIdx = p.lastIndexOf("/");
|
|
10194
|
-
const
|
|
10195
|
-
if (NOISE_BASENAMES.has(
|
|
10194
|
+
const basename9 = slashIdx >= 0 ? p.slice(slashIdx + 1) : p;
|
|
10195
|
+
if (NOISE_BASENAMES.has(basename9)) {
|
|
10196
10196
|
return true;
|
|
10197
10197
|
}
|
|
10198
|
-
if (
|
|
10198
|
+
if (basename9.startsWith(".improve-state-") || basename9.startsWith("improve_commit_msg_")) {
|
|
10199
10199
|
return true;
|
|
10200
10200
|
}
|
|
10201
|
-
const dotIdx =
|
|
10201
|
+
const dotIdx = basename9.lastIndexOf(".");
|
|
10202
10202
|
if (dotIdx >= 0) {
|
|
10203
|
-
const ext =
|
|
10203
|
+
const ext = basename9.slice(dotIdx);
|
|
10204
10204
|
if (NOISE_EXTS.has(ext)) {
|
|
10205
10205
|
return true;
|
|
10206
10206
|
}
|
|
10207
10207
|
}
|
|
10208
10208
|
for (const ext of NOISE_EXTS) {
|
|
10209
10209
|
if (ext.includes(".") && ext.split(".").length > 2) {
|
|
10210
|
-
if (
|
|
10210
|
+
if (basename9.endsWith(ext)) {
|
|
10211
10211
|
return true;
|
|
10212
10212
|
}
|
|
10213
10213
|
}
|
|
@@ -10294,6 +10294,48 @@ function formatMap(entries, opts = {}) {
|
|
|
10294
10294
|
return lines.join("\n");
|
|
10295
10295
|
}
|
|
10296
10296
|
|
|
10297
|
+
// src/walk_index.ts
|
|
10298
|
+
init_define_import_meta_env();
|
|
10299
|
+
import * as os2 from "node:os";
|
|
10300
|
+
import * as path7 from "node:path";
|
|
10301
|
+
function isWalkExcluded(file) {
|
|
10302
|
+
const base = path7.basename(file).toLowerCase();
|
|
10303
|
+
if (base === ".env" || base.startsWith(".env.")) return true;
|
|
10304
|
+
if (base.endsWith(".d.ts")) return true;
|
|
10305
|
+
return false;
|
|
10306
|
+
}
|
|
10307
|
+
function assertWalkableRoot(root) {
|
|
10308
|
+
const resolved = path7.resolve(root);
|
|
10309
|
+
const fold = (p) => process.platform === "win32" || process.platform === "darwin" ? p.toLowerCase() : p;
|
|
10310
|
+
const norm = fold(normalizePath(resolved));
|
|
10311
|
+
const fsRoot = fold(normalizePath(path7.parse(resolved).root));
|
|
10312
|
+
if (norm === fsRoot) {
|
|
10313
|
+
throw new Error(`refusing to walk-index a filesystem root: ${resolved}`);
|
|
10314
|
+
}
|
|
10315
|
+
const home = os2.homedir();
|
|
10316
|
+
if (home) {
|
|
10317
|
+
const normHome = fold(normalizePath(path7.resolve(home)));
|
|
10318
|
+
if (norm === normHome) {
|
|
10319
|
+
throw new Error(`refusing to walk-index the home directory: ${resolved}`);
|
|
10320
|
+
}
|
|
10321
|
+
const boundary = norm.endsWith("/") ? norm : `${norm}/`;
|
|
10322
|
+
if (normHome.startsWith(boundary)) {
|
|
10323
|
+
throw new Error(`refusing to walk-index '${resolved}' \u2014 it contains the home directory`);
|
|
10324
|
+
}
|
|
10325
|
+
}
|
|
10326
|
+
}
|
|
10327
|
+
function collectWalkIndexFiles(root) {
|
|
10328
|
+
const resolved = path7.resolve(root);
|
|
10329
|
+
assertWalkableRoot(resolved);
|
|
10330
|
+
const { files } = walkProject(resolved);
|
|
10331
|
+
if (files.length >= MAX_FILES_SCANNED) {
|
|
10332
|
+
throw new Error(
|
|
10333
|
+
`'${resolved}' has too many source files (>= ${MAX_FILES_SCANNED}); refusing to walk-index \u2014 index a git repo or point at a narrower path`
|
|
10334
|
+
);
|
|
10335
|
+
}
|
|
10336
|
+
return files.filter((f) => !isWalkExcluded(f));
|
|
10337
|
+
}
|
|
10338
|
+
|
|
10297
10339
|
// src/session.ts
|
|
10298
10340
|
init_define_import_meta_env();
|
|
10299
10341
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
@@ -10361,6 +10403,9 @@ function wasFileReadThisSession(filePath) {
|
|
|
10361
10403
|
const entry = _files.get(normalizePath(filePath));
|
|
10362
10404
|
return entry !== void 0 && entry.readCount > 0;
|
|
10363
10405
|
}
|
|
10406
|
+
function recordWebFetch(url, cacheId) {
|
|
10407
|
+
_webFetches.set(url, cacheId);
|
|
10408
|
+
}
|
|
10364
10409
|
function getSessionWebFetches() {
|
|
10365
10410
|
return _webFetches;
|
|
10366
10411
|
}
|
|
@@ -10409,6 +10454,25 @@ function getSessionId() {
|
|
|
10409
10454
|
_sessionId = fromEnv !== void 0 && fromEnv !== "" ? fromEnv : generateSessionId();
|
|
10410
10455
|
return _sessionId;
|
|
10411
10456
|
}
|
|
10457
|
+
function exportSessionState() {
|
|
10458
|
+
return {
|
|
10459
|
+
files: Array.from(_files.values()),
|
|
10460
|
+
hintsShown: Array.from(_hintsShown),
|
|
10461
|
+
webFetches: Array.from(_webFetches.entries()),
|
|
10462
|
+
bashOutputs: Array.from(_bashOutputs.entries()),
|
|
10463
|
+
curlDownloads: Array.from(_curlDownloads.entries())
|
|
10464
|
+
};
|
|
10465
|
+
}
|
|
10466
|
+
function importSessionState(s) {
|
|
10467
|
+
_files = /* @__PURE__ */ new Map();
|
|
10468
|
+
for (const e of s.files) {
|
|
10469
|
+
if (e && typeof e.path === "string") _files.set(e.path, e);
|
|
10470
|
+
}
|
|
10471
|
+
_hintsShown = new Set(s.hintsShown);
|
|
10472
|
+
_webFetches = new Map(s.webFetches);
|
|
10473
|
+
_bashOutputs = new Map(s.bashOutputs);
|
|
10474
|
+
_curlDownloads = new Map(s.curlDownloads);
|
|
10475
|
+
}
|
|
10412
10476
|
registerReset(() => {
|
|
10413
10477
|
_files = /* @__PURE__ */ new Map();
|
|
10414
10478
|
_hintsShown = /* @__PURE__ */ new Set();
|
|
@@ -10728,7 +10792,8 @@ function assignFlatEndLines(sections, totalLines) {
|
|
|
10728
10792
|
const next = sections[i + 1];
|
|
10729
10793
|
const s = sections[i];
|
|
10730
10794
|
if (s === void 0) continue;
|
|
10731
|
-
|
|
10795
|
+
const end = next !== void 0 ? next.line - 1 : totalLines;
|
|
10796
|
+
s.endLine = end < s.line ? s.line : end;
|
|
10732
10797
|
}
|
|
10733
10798
|
}
|
|
10734
10799
|
function propagateEndLinesToSymbols(symbols, sections) {
|
|
@@ -10860,7 +10925,7 @@ function extractHtml(content, filePath) {
|
|
|
10860
10925
|
|
|
10861
10926
|
// src/languages/liquid.ts
|
|
10862
10927
|
init_define_import_meta_env();
|
|
10863
|
-
import * as
|
|
10928
|
+
import * as path8 from "node:path";
|
|
10864
10929
|
var INCLUDE_RE = /{%\s*include\s+['"]([^'"]+)['"]/gi;
|
|
10865
10930
|
var SECTION_RE = /{%\s*section\s+['"]([^'"]+)['"]/gi;
|
|
10866
10931
|
var RENDER_RE = /{%\s*render\s+['"]([^'"]+)['"]/gi;
|
|
@@ -10904,7 +10969,7 @@ function extractLiquid(content, filePath, relPath) {
|
|
|
10904
10969
|
const resolvedRel = relPath ?? filePath;
|
|
10905
10970
|
const relPosix = resolvedRel.replace(/\\/g, "/");
|
|
10906
10971
|
if (relPosix.startsWith("sections/") || relPosix.includes("/sections/")) {
|
|
10907
|
-
const stem =
|
|
10972
|
+
const stem = path8.basename(resolvedRel, path8.extname(resolvedRel));
|
|
10908
10973
|
symbols.push({ filePath, name: stem, kind: "liquid_section_file", lineStart: 1, lineEnd: 1, body: "", docstring: "" });
|
|
10909
10974
|
}
|
|
10910
10975
|
const totalLines = content.split("\n").length;
|
|
@@ -12204,6 +12269,14 @@ function serializeOutput(output) {
|
|
|
12204
12269
|
return JSON.stringify({ context: output.context });
|
|
12205
12270
|
case "update":
|
|
12206
12271
|
return JSON.stringify({ updatedInput: { content: output.content } });
|
|
12272
|
+
case "rewriteInput":
|
|
12273
|
+
return JSON.stringify({
|
|
12274
|
+
hookSpecificOutput: {
|
|
12275
|
+
hookEventName: "PreToolUse",
|
|
12276
|
+
permissionDecision: "allow",
|
|
12277
|
+
updatedInput: output.updatedInput
|
|
12278
|
+
}
|
|
12279
|
+
});
|
|
12207
12280
|
case "pass":
|
|
12208
12281
|
return JSON.stringify({});
|
|
12209
12282
|
}
|
|
@@ -12222,11 +12295,239 @@ var HOOK_EVENTS = [
|
|
|
12222
12295
|
"subagent_stop"
|
|
12223
12296
|
];
|
|
12224
12297
|
|
|
12225
|
-
// src/
|
|
12298
|
+
// src/session_store.ts
|
|
12226
12299
|
init_define_import_meta_env();
|
|
12227
|
-
import * as
|
|
12300
|
+
import * as fs7 from "node:fs";
|
|
12228
12301
|
import * as path10 from "node:path";
|
|
12229
12302
|
|
|
12303
|
+
// src/disk_cache.ts
|
|
12304
|
+
init_define_import_meta_env();
|
|
12305
|
+
import * as fs6 from "node:fs";
|
|
12306
|
+
import * as path9 from "node:path";
|
|
12307
|
+
import * as os3 from "node:os";
|
|
12308
|
+
var DEFAULT_MAX_COUNT = 200;
|
|
12309
|
+
var DEFAULT_MAX_AGE_MS = 24 * 3600 * 1e3;
|
|
12310
|
+
var ID_SANITIZE_RE = /[^a-zA-Z0-9_-]/g;
|
|
12311
|
+
function tokenGoatHome() {
|
|
12312
|
+
const override = process.env["TOKEN_GOAT_HOME"];
|
|
12313
|
+
if (override !== void 0 && override !== "") return override;
|
|
12314
|
+
return path9.join(os3.homedir(), ".token-goat");
|
|
12315
|
+
}
|
|
12316
|
+
function sanitizeId(id) {
|
|
12317
|
+
return id.replace(ID_SANITIZE_RE, "_").slice(0, 64);
|
|
12318
|
+
}
|
|
12319
|
+
function blobDir(subdir) {
|
|
12320
|
+
return path9.join(tokenGoatHome(), subdir);
|
|
12321
|
+
}
|
|
12322
|
+
function blobPath(subdir, id) {
|
|
12323
|
+
const safe = sanitizeId(id);
|
|
12324
|
+
if (!safe) return null;
|
|
12325
|
+
const dir = blobDir(subdir);
|
|
12326
|
+
const candidate = path9.join(dir, `${safe}.json`);
|
|
12327
|
+
try {
|
|
12328
|
+
const rel = path9.relative(dir, candidate);
|
|
12329
|
+
if (rel.startsWith("..")) return null;
|
|
12330
|
+
} catch {
|
|
12331
|
+
return null;
|
|
12332
|
+
}
|
|
12333
|
+
return candidate;
|
|
12334
|
+
}
|
|
12335
|
+
function storeBlob(subdir, id, value, opts = {}) {
|
|
12336
|
+
const p = blobPath(subdir, id);
|
|
12337
|
+
if (!p) return false;
|
|
12338
|
+
try {
|
|
12339
|
+
const dir = path9.dirname(p);
|
|
12340
|
+
if (!fs6.existsSync(dir)) fs6.mkdirSync(dir, { recursive: true });
|
|
12341
|
+
atomicWriteText(p, JSON.stringify(value));
|
|
12342
|
+
} catch {
|
|
12343
|
+
return false;
|
|
12344
|
+
}
|
|
12345
|
+
pruneBlobs(subdir, opts.maxCount ?? DEFAULT_MAX_COUNT, opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS);
|
|
12346
|
+
return true;
|
|
12347
|
+
}
|
|
12348
|
+
function loadBlob(subdir, id) {
|
|
12349
|
+
const p = blobPath(subdir, id);
|
|
12350
|
+
if (!p) return null;
|
|
12351
|
+
try {
|
|
12352
|
+
if (!fs6.existsSync(p)) return null;
|
|
12353
|
+
return JSON.parse(fs6.readFileSync(p, "utf8"));
|
|
12354
|
+
} catch {
|
|
12355
|
+
return null;
|
|
12356
|
+
}
|
|
12357
|
+
}
|
|
12358
|
+
function pruneBlobs(subdir, maxCount = DEFAULT_MAX_COUNT, maxAgeMs = DEFAULT_MAX_AGE_MS) {
|
|
12359
|
+
const dir = blobDir(subdir);
|
|
12360
|
+
let removed = 0;
|
|
12361
|
+
try {
|
|
12362
|
+
if (!fs6.existsSync(dir)) return 0;
|
|
12363
|
+
const cutoff = Date.now() - maxAgeMs;
|
|
12364
|
+
const kept = [];
|
|
12365
|
+
for (const file of fs6.readdirSync(dir)) {
|
|
12366
|
+
if (!file.endsWith(".json")) continue;
|
|
12367
|
+
const full = path9.join(dir, file);
|
|
12368
|
+
let mtime;
|
|
12369
|
+
try {
|
|
12370
|
+
mtime = fs6.statSync(full).mtimeMs;
|
|
12371
|
+
} catch {
|
|
12372
|
+
continue;
|
|
12373
|
+
}
|
|
12374
|
+
if (mtime < cutoff) {
|
|
12375
|
+
try {
|
|
12376
|
+
fs6.unlinkSync(full);
|
|
12377
|
+
removed++;
|
|
12378
|
+
} catch {
|
|
12379
|
+
continue;
|
|
12380
|
+
}
|
|
12381
|
+
} else {
|
|
12382
|
+
kept.push([full, mtime]);
|
|
12383
|
+
}
|
|
12384
|
+
}
|
|
12385
|
+
if (kept.length > maxCount) {
|
|
12386
|
+
kept.sort((a, b) => a[1] - b[1]);
|
|
12387
|
+
for (const [full] of kept.slice(0, kept.length - maxCount)) {
|
|
12388
|
+
try {
|
|
12389
|
+
fs6.unlinkSync(full);
|
|
12390
|
+
removed++;
|
|
12391
|
+
} catch {
|
|
12392
|
+
continue;
|
|
12393
|
+
}
|
|
12394
|
+
}
|
|
12395
|
+
}
|
|
12396
|
+
} catch {
|
|
12397
|
+
return removed;
|
|
12398
|
+
}
|
|
12399
|
+
return removed;
|
|
12400
|
+
}
|
|
12401
|
+
|
|
12402
|
+
// src/session_store.ts
|
|
12403
|
+
var SAFE_RE = /[^a-zA-Z0-9_-]/g;
|
|
12404
|
+
var MAX_FILES = 500;
|
|
12405
|
+
var SESSIONS_SUBDIR = "sessions";
|
|
12406
|
+
function sessionPath(sessionId) {
|
|
12407
|
+
if (!sessionId) return null;
|
|
12408
|
+
const safe = sessionId.replace(SAFE_RE, "_").slice(0, 64);
|
|
12409
|
+
if (!safe) return null;
|
|
12410
|
+
const dir = path10.join(tokenGoatHome(), SESSIONS_SUBDIR);
|
|
12411
|
+
const candidate = path10.join(dir, `${safe}.json`);
|
|
12412
|
+
try {
|
|
12413
|
+
const rel = path10.relative(dir, candidate);
|
|
12414
|
+
if (rel.startsWith("..")) return null;
|
|
12415
|
+
} catch {
|
|
12416
|
+
return null;
|
|
12417
|
+
}
|
|
12418
|
+
return candidate;
|
|
12419
|
+
}
|
|
12420
|
+
function asStringPairs(raw) {
|
|
12421
|
+
if (!Array.isArray(raw)) return [];
|
|
12422
|
+
const out2 = [];
|
|
12423
|
+
for (const item of raw) {
|
|
12424
|
+
if (Array.isArray(item) && typeof item[0] === "string" && typeof item[1] === "string") {
|
|
12425
|
+
out2.push([item[0], item[1]]);
|
|
12426
|
+
}
|
|
12427
|
+
}
|
|
12428
|
+
return out2;
|
|
12429
|
+
}
|
|
12430
|
+
function asFileEntry(raw) {
|
|
12431
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
12432
|
+
const o = raw;
|
|
12433
|
+
if (typeof o["path"] !== "string" || typeof o["readCount"] !== "number" || typeof o["lastReadAt"] !== "number" || typeof o["wasEdited"] !== "boolean" || typeof o["sizeBytes"] !== "number") {
|
|
12434
|
+
return null;
|
|
12435
|
+
}
|
|
12436
|
+
const entry = {
|
|
12437
|
+
path: o["path"],
|
|
12438
|
+
readCount: o["readCount"],
|
|
12439
|
+
lastReadAt: o["lastReadAt"],
|
|
12440
|
+
wasEdited: o["wasEdited"],
|
|
12441
|
+
sizeBytes: o["sizeBytes"]
|
|
12442
|
+
};
|
|
12443
|
+
return o["wasTruncated"] === true ? { ...entry, wasTruncated: true } : entry;
|
|
12444
|
+
}
|
|
12445
|
+
function coerce(raw) {
|
|
12446
|
+
const o = raw !== null && typeof raw === "object" ? raw : {};
|
|
12447
|
+
const files = [];
|
|
12448
|
+
if (Array.isArray(o["files"])) {
|
|
12449
|
+
for (const f of o["files"]) {
|
|
12450
|
+
const e = asFileEntry(f);
|
|
12451
|
+
if (e !== null) files.push(e);
|
|
12452
|
+
}
|
|
12453
|
+
}
|
|
12454
|
+
const hintsShown = Array.isArray(o["hintsShown"]) ? o["hintsShown"].filter((h) => typeof h === "string") : [];
|
|
12455
|
+
return {
|
|
12456
|
+
files,
|
|
12457
|
+
hintsShown,
|
|
12458
|
+
webFetches: asStringPairs(o["webFetches"]),
|
|
12459
|
+
bashOutputs: asStringPairs(o["bashOutputs"]),
|
|
12460
|
+
curlDownloads: asStringPairs(o["curlDownloads"])
|
|
12461
|
+
};
|
|
12462
|
+
}
|
|
12463
|
+
function mergeFileEntry(a, b) {
|
|
12464
|
+
const newest = a.lastReadAt >= b.lastReadAt ? a : b;
|
|
12465
|
+
const merged = {
|
|
12466
|
+
path: a.path,
|
|
12467
|
+
readCount: Math.max(a.readCount, b.readCount),
|
|
12468
|
+
lastReadAt: Math.max(a.lastReadAt, b.lastReadAt),
|
|
12469
|
+
wasEdited: a.wasEdited || b.wasEdited,
|
|
12470
|
+
sizeBytes: newest.sizeBytes
|
|
12471
|
+
};
|
|
12472
|
+
return a.wasTruncated || b.wasTruncated ? { ...merged, wasTruncated: true } : merged;
|
|
12473
|
+
}
|
|
12474
|
+
function mergePairs(disk, mem) {
|
|
12475
|
+
return Array.from(new Map([...disk, ...mem]).entries());
|
|
12476
|
+
}
|
|
12477
|
+
function mergeSessionState(disk, mem) {
|
|
12478
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
12479
|
+
for (const e of disk.files) byPath.set(e.path, e);
|
|
12480
|
+
for (const e of mem.files) {
|
|
12481
|
+
const prev = byPath.get(e.path);
|
|
12482
|
+
byPath.set(e.path, prev ? mergeFileEntry(prev, e) : e);
|
|
12483
|
+
}
|
|
12484
|
+
return {
|
|
12485
|
+
files: Array.from(byPath.values()),
|
|
12486
|
+
hintsShown: Array.from(/* @__PURE__ */ new Set([...disk.hintsShown, ...mem.hintsShown])),
|
|
12487
|
+
webFetches: mergePairs(disk.webFetches, mem.webFetches),
|
|
12488
|
+
bashOutputs: mergePairs(disk.bashOutputs, mem.bashOutputs),
|
|
12489
|
+
curlDownloads: mergePairs(disk.curlDownloads, mem.curlDownloads)
|
|
12490
|
+
};
|
|
12491
|
+
}
|
|
12492
|
+
function capFiles(s, max) {
|
|
12493
|
+
if (s.files.length <= max) return s;
|
|
12494
|
+
const kept = [...s.files].sort((a, b) => b.lastReadAt - a.lastReadAt).slice(0, max);
|
|
12495
|
+
return { ...s, files: kept };
|
|
12496
|
+
}
|
|
12497
|
+
function readDiskState(p) {
|
|
12498
|
+
try {
|
|
12499
|
+
if (!fs7.existsSync(p)) return null;
|
|
12500
|
+
return coerce(JSON.parse(fs7.readFileSync(p, "utf8")));
|
|
12501
|
+
} catch {
|
|
12502
|
+
return null;
|
|
12503
|
+
}
|
|
12504
|
+
}
|
|
12505
|
+
function loadSessionState(sessionId) {
|
|
12506
|
+
const p = sessionPath(sessionId);
|
|
12507
|
+
if (!p) return;
|
|
12508
|
+
const disk = readDiskState(p);
|
|
12509
|
+
if (disk === null) return;
|
|
12510
|
+
importSessionState(disk);
|
|
12511
|
+
}
|
|
12512
|
+
function saveSessionState(sessionId) {
|
|
12513
|
+
const p = sessionPath(sessionId);
|
|
12514
|
+
if (!p) return;
|
|
12515
|
+
try {
|
|
12516
|
+
const mem = exportSessionState();
|
|
12517
|
+
const disk = readDiskState(p);
|
|
12518
|
+
const merged = capFiles(disk ? mergeSessionState(disk, mem) : mem, MAX_FILES);
|
|
12519
|
+
const dir = path10.dirname(p);
|
|
12520
|
+
if (!fs7.existsSync(dir)) fs7.mkdirSync(dir, { recursive: true });
|
|
12521
|
+
atomicWriteText(p, JSON.stringify(merged));
|
|
12522
|
+
} catch {
|
|
12523
|
+
}
|
|
12524
|
+
}
|
|
12525
|
+
|
|
12526
|
+
// src/hooks_read.ts
|
|
12527
|
+
init_define_import_meta_env();
|
|
12528
|
+
import * as fs10 from "node:fs";
|
|
12529
|
+
import * as path13 from "node:path";
|
|
12530
|
+
|
|
12230
12531
|
// src/hooks_common.ts
|
|
12231
12532
|
init_define_import_meta_env();
|
|
12232
12533
|
function getToolName(event) {
|
|
@@ -12251,7 +12552,7 @@ function contextOutput(context) {
|
|
|
12251
12552
|
|
|
12252
12553
|
// src/config.ts
|
|
12253
12554
|
init_define_import_meta_env();
|
|
12254
|
-
import * as
|
|
12555
|
+
import * as fs8 from "node:fs";
|
|
12255
12556
|
|
|
12256
12557
|
// node_modules/smol-toml/dist/index.js
|
|
12257
12558
|
init_define_import_meta_env();
|
|
@@ -12886,7 +13187,7 @@ function peekTable(key, table, meta, type) {
|
|
|
12886
13187
|
}
|
|
12887
13188
|
return [k, t, state.c];
|
|
12888
13189
|
}
|
|
12889
|
-
function
|
|
13190
|
+
function parse2(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
|
|
12890
13191
|
let res = {};
|
|
12891
13192
|
let meta = {};
|
|
12892
13193
|
let tbl = res;
|
|
@@ -13199,7 +13500,7 @@ function loadConfig() {
|
|
|
13199
13500
|
const p = configPath();
|
|
13200
13501
|
let currentMtime = 0;
|
|
13201
13502
|
try {
|
|
13202
|
-
currentMtime =
|
|
13503
|
+
currentMtime = fs8.statSync(p).mtimeMs;
|
|
13203
13504
|
} catch {
|
|
13204
13505
|
}
|
|
13205
13506
|
const envFp = configEnvFingerprint();
|
|
@@ -13209,8 +13510,8 @@ function loadConfig() {
|
|
|
13209
13510
|
let raw = {};
|
|
13210
13511
|
if (currentMtime !== 0) {
|
|
13211
13512
|
try {
|
|
13212
|
-
const text =
|
|
13213
|
-
raw =
|
|
13513
|
+
const text = fs8.readFileSync(p, "utf8");
|
|
13514
|
+
raw = parse2(text);
|
|
13214
13515
|
} catch {
|
|
13215
13516
|
}
|
|
13216
13517
|
}
|
|
@@ -13419,10 +13720,10 @@ function _buildConfig(raw) {
|
|
|
13419
13720
|
|
|
13420
13721
|
// src/snapshots.ts
|
|
13421
13722
|
init_define_import_meta_env();
|
|
13422
|
-
import * as
|
|
13423
|
-
import * as
|
|
13723
|
+
import * as fs9 from "node:fs";
|
|
13724
|
+
import * as path11 from "node:path";
|
|
13424
13725
|
import * as crypto from "node:crypto";
|
|
13425
|
-
import * as
|
|
13726
|
+
import * as os4 from "node:os";
|
|
13426
13727
|
var MAX_SNAPSHOTS_PER_SESSION = 150;
|
|
13427
13728
|
var MAX_SNAPSHOT_BYTES = 256 * 1024;
|
|
13428
13729
|
var SNAPSHOT_TRUNCATE_BYTES = 50 * 1024;
|
|
@@ -13434,10 +13735,10 @@ var SESSION_DIR_RE = /[^a-zA-Z0-9_-]/g;
|
|
|
13434
13735
|
function sessionDir(sessionId) {
|
|
13435
13736
|
if (!sessionId) return null;
|
|
13436
13737
|
const safe = sessionId.replace(SESSION_DIR_RE, "_").slice(0, 64) || "anon";
|
|
13437
|
-
const base =
|
|
13438
|
-
const candidate =
|
|
13738
|
+
const base = path11.join(os4.homedir(), ".token-goat", "session_snapshots");
|
|
13739
|
+
const candidate = path11.join(base, safe);
|
|
13439
13740
|
try {
|
|
13440
|
-
const rel =
|
|
13741
|
+
const rel = path11.relative(base, candidate);
|
|
13441
13742
|
if (rel.startsWith("..")) return null;
|
|
13442
13743
|
} catch {
|
|
13443
13744
|
return null;
|
|
@@ -13450,7 +13751,7 @@ function pathKey(filePath) {
|
|
|
13450
13751
|
function snapshot_path(sessionId, filePath) {
|
|
13451
13752
|
const d = sessionDir(sessionId);
|
|
13452
13753
|
if (!d) return null;
|
|
13453
|
-
return
|
|
13754
|
+
return path11.join(d, `${pathKey(filePath)}.bin`);
|
|
13454
13755
|
}
|
|
13455
13756
|
function kindSidecarPath(snapshotPath) {
|
|
13456
13757
|
return snapshotPath + ".kind";
|
|
@@ -13458,11 +13759,11 @@ function kindSidecarPath(snapshotPath) {
|
|
|
13458
13759
|
function writeSnapshotKind(sidecarPath, kind) {
|
|
13459
13760
|
try {
|
|
13460
13761
|
const safeKind = VALID_KINDS.has(kind) ? kind : KIND_READ;
|
|
13461
|
-
const dir =
|
|
13462
|
-
if (!
|
|
13463
|
-
|
|
13762
|
+
const dir = path11.dirname(sidecarPath);
|
|
13763
|
+
if (!fs9.existsSync(dir)) {
|
|
13764
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
13464
13765
|
}
|
|
13465
|
-
|
|
13766
|
+
fs9.writeFileSync(sidecarPath, safeKind, "utf8");
|
|
13466
13767
|
return true;
|
|
13467
13768
|
} catch {
|
|
13468
13769
|
return false;
|
|
@@ -13471,12 +13772,12 @@ function writeSnapshotKind(sidecarPath, kind) {
|
|
|
13471
13772
|
function evictOldest(d, maxCount) {
|
|
13472
13773
|
try {
|
|
13473
13774
|
const entries = [];
|
|
13474
|
-
const files =
|
|
13775
|
+
const files = fs9.readdirSync(d);
|
|
13475
13776
|
for (const file of files) {
|
|
13476
|
-
const fullPath =
|
|
13777
|
+
const fullPath = path11.join(d, file);
|
|
13477
13778
|
if (!file.endsWith(".bin")) continue;
|
|
13478
13779
|
try {
|
|
13479
|
-
const stat3 =
|
|
13780
|
+
const stat3 = fs9.statSync(fullPath);
|
|
13480
13781
|
entries.push([fullPath, stat3.mtimeMs]);
|
|
13481
13782
|
} catch {
|
|
13482
13783
|
continue;
|
|
@@ -13488,10 +13789,10 @@ function evictOldest(d, maxCount) {
|
|
|
13488
13789
|
const over = entries.length - maxCount;
|
|
13489
13790
|
for (const [p] of entries.slice(0, over)) {
|
|
13490
13791
|
try {
|
|
13491
|
-
|
|
13792
|
+
fs9.unlinkSync(p);
|
|
13492
13793
|
removed++;
|
|
13493
13794
|
try {
|
|
13494
|
-
|
|
13795
|
+
fs9.unlinkSync(kindSidecarPath(p));
|
|
13495
13796
|
} catch {
|
|
13496
13797
|
}
|
|
13497
13798
|
} catch {
|
|
@@ -13520,9 +13821,9 @@ function store(sessionId, filePath, content, opts = {}) {
|
|
|
13520
13821
|
if (!p) return null;
|
|
13521
13822
|
const sha = crypto.createHash("sha256").update(stored).digest("hex");
|
|
13522
13823
|
try {
|
|
13523
|
-
if (
|
|
13824
|
+
if (fs9.existsSync(p)) {
|
|
13524
13825
|
try {
|
|
13525
|
-
const existing =
|
|
13826
|
+
const existing = fs9.readFileSync(p);
|
|
13526
13827
|
if (Buffer.from(existing).equals(stored)) {
|
|
13527
13828
|
return {
|
|
13528
13829
|
path: p,
|
|
@@ -13533,14 +13834,14 @@ function store(sessionId, filePath, content, opts = {}) {
|
|
|
13533
13834
|
} catch {
|
|
13534
13835
|
}
|
|
13535
13836
|
}
|
|
13536
|
-
const dir =
|
|
13537
|
-
if (!
|
|
13538
|
-
|
|
13837
|
+
const dir = path11.dirname(p);
|
|
13838
|
+
if (!fs9.existsSync(dir)) {
|
|
13839
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
13539
13840
|
}
|
|
13540
13841
|
evictOldest(dir, MAX_SNAPSHOTS_PER_SESSION - 1);
|
|
13541
13842
|
const tempPath = p + ".tmp";
|
|
13542
|
-
|
|
13543
|
-
|
|
13843
|
+
fs9.writeFileSync(tempPath, stored);
|
|
13844
|
+
fs9.renameSync(tempPath, p);
|
|
13544
13845
|
const sidecar = kindSidecarPath(p);
|
|
13545
13846
|
writeSnapshotKind(sidecar, kind);
|
|
13546
13847
|
return {
|
|
@@ -13554,9 +13855,9 @@ function store(sessionId, filePath, content, opts = {}) {
|
|
|
13554
13855
|
}
|
|
13555
13856
|
function load(sessionId, filePath, opts = {}) {
|
|
13556
13857
|
const p = snapshot_path(sessionId, filePath);
|
|
13557
|
-
if (!p || !
|
|
13858
|
+
if (!p || !fs9.existsSync(p)) return null;
|
|
13558
13859
|
try {
|
|
13559
|
-
const stat3 =
|
|
13860
|
+
const stat3 = fs9.statSync(p);
|
|
13560
13861
|
if (stat3.size > MAX_SNAPSHOT_BYTES) {
|
|
13561
13862
|
return null;
|
|
13562
13863
|
}
|
|
@@ -13564,7 +13865,7 @@ function load(sessionId, filePath, opts = {}) {
|
|
|
13564
13865
|
return null;
|
|
13565
13866
|
}
|
|
13566
13867
|
try {
|
|
13567
|
-
const data =
|
|
13868
|
+
const data = fs9.readFileSync(p);
|
|
13568
13869
|
if (opts.expected_sha) {
|
|
13569
13870
|
const actualSha = crypto.createHash("sha256").update(data).digest("hex");
|
|
13570
13871
|
if (actualSha.toLowerCase() !== opts.expected_sha.toLowerCase()) {
|
|
@@ -13609,11 +13910,11 @@ function buildPackageManifestHint(options) {
|
|
|
13609
13910
|
return null;
|
|
13610
13911
|
}
|
|
13611
13912
|
}
|
|
13612
|
-
function _sanitizeHintPath(
|
|
13613
|
-
if (typeof
|
|
13913
|
+
function _sanitizeHintPath(path22) {
|
|
13914
|
+
if (typeof path22 !== "string") {
|
|
13614
13915
|
return "???";
|
|
13615
13916
|
}
|
|
13616
|
-
return
|
|
13917
|
+
return path22.replace(/[\x00]/g, "").slice(0, 200);
|
|
13617
13918
|
}
|
|
13618
13919
|
|
|
13619
13920
|
// src/hints/lang_patterns.ts
|
|
@@ -13751,15 +14052,15 @@ var LOCK_FILE_COUNT = LOCK_FILE_NAMES.size;
|
|
|
13751
14052
|
var MANIFEST_FILE_COUNT = MANIFEST_FILE_NAMES.size + MANIFEST_EXTENSIONS.size + MANIFEST_BASENAME_PATTERNS.length;
|
|
13752
14053
|
var BUILD_DIR_COUNT = BUILD_DIR_NAMES.size;
|
|
13753
14054
|
var GENERATED_EXT_COUNT = ALWAYS_GENERATED_EXTS.size + CONDITIONALLY_GENERATED_EXTS.size;
|
|
13754
|
-
function isLockFile(
|
|
13755
|
-
return LOCK_FILE_NAMES.has(
|
|
14055
|
+
function isLockFile(basename9) {
|
|
14056
|
+
return LOCK_FILE_NAMES.has(basename9.toLowerCase());
|
|
13756
14057
|
}
|
|
13757
|
-
function isManifestFile(
|
|
13758
|
-
const lower =
|
|
14058
|
+
function isManifestFile(basename9) {
|
|
14059
|
+
const lower = basename9.toLowerCase();
|
|
13759
14060
|
if (MANIFEST_FILE_NAMES.has(lower)) return true;
|
|
13760
14061
|
const dot = lower.lastIndexOf(".");
|
|
13761
14062
|
if (dot !== -1 && MANIFEST_EXTENSIONS.has(lower.slice(dot))) return true;
|
|
13762
|
-
if (MANIFEST_BASENAME_PATTERNS.some((re) => re.test(
|
|
14063
|
+
if (MANIFEST_BASENAME_PATTERNS.some((re) => re.test(basename9))) return true;
|
|
13763
14064
|
return false;
|
|
13764
14065
|
}
|
|
13765
14066
|
function pathSegments(filePath) {
|
|
@@ -13917,8 +14218,8 @@ var WELL_KNOWN_SECTIONS = {
|
|
|
13917
14218
|
"CLAUDE.md": ["Commands", "Architecture"],
|
|
13918
14219
|
"CLAUDE.arch.md": ["Component Map", "Architecture"]
|
|
13919
14220
|
};
|
|
13920
|
-
function getWellKnownSections(
|
|
13921
|
-
return WELL_KNOWN_SECTIONS[
|
|
14221
|
+
function getWellKnownSections(basename9) {
|
|
14222
|
+
return WELL_KNOWN_SECTIONS[basename9] ?? [];
|
|
13922
14223
|
}
|
|
13923
14224
|
function extractChangelogVersionHint(content, filePath) {
|
|
13924
14225
|
const lines = content.split("\n");
|
|
@@ -14066,7 +14367,7 @@ function dispatchFileTypeHandler(filePath, content, contentLengthHint) {
|
|
|
14066
14367
|
|
|
14067
14368
|
// src/stats.ts
|
|
14068
14369
|
init_define_import_meta_env();
|
|
14069
|
-
import * as
|
|
14370
|
+
import * as path12 from "node:path";
|
|
14070
14371
|
|
|
14071
14372
|
// src/render/stats_renderer.ts
|
|
14072
14373
|
init_define_import_meta_env();
|
|
@@ -14846,7 +15147,7 @@ CREATE INDEX IF NOT EXISTS idx_stats_kind ON stats(kind);
|
|
|
14846
15147
|
var _globalSchemaApplied = /* @__PURE__ */ new Set();
|
|
14847
15148
|
registerReset(() => _globalSchemaApplied.clear());
|
|
14848
15149
|
function getGlobalDb() {
|
|
14849
|
-
const dbPath =
|
|
15150
|
+
const dbPath = path12.join(dataDir(), "global.db");
|
|
14850
15151
|
const db = getDb(dbPath);
|
|
14851
15152
|
if (!_globalSchemaApplied.has(dbPath)) {
|
|
14852
15153
|
db.exec(GLOBAL_SCHEMA_SQL);
|
|
@@ -15038,8 +15339,8 @@ function renderStats2(opts) {
|
|
|
15038
15339
|
}
|
|
15039
15340
|
|
|
15040
15341
|
// src/hooks_read.ts
|
|
15041
|
-
function isTsConfigFile(
|
|
15042
|
-
const lower =
|
|
15342
|
+
function isTsConfigFile(basename9) {
|
|
15343
|
+
const lower = basename9.toLowerCase();
|
|
15043
15344
|
return /^tsconfig(\..+)?\.json$/i.test(lower) || lower === "jsconfig.json";
|
|
15044
15345
|
}
|
|
15045
15346
|
var LARGE_FILE_BYTES = 100 * 1024;
|
|
@@ -15058,17 +15359,20 @@ function isSessionArtifactFile(filePath) {
|
|
|
15058
15359
|
if (/[/\\]tool-results[/\\][a-z0-9]+\.txt$/i.test(filePath)) return true;
|
|
15059
15360
|
return false;
|
|
15060
15361
|
}
|
|
15362
|
+
function sessionArtifactRecall(filePath) {
|
|
15363
|
+
return 'Use `token-goat bash-output --file "' + filePath + '" --tail 50` (or `--grep PATTERN`) to read a slice instead of the full file.';
|
|
15364
|
+
}
|
|
15061
15365
|
function statSize(absPath) {
|
|
15062
15366
|
try {
|
|
15063
|
-
return
|
|
15367
|
+
return fs10.statSync(absPath).size;
|
|
15064
15368
|
} catch {
|
|
15065
15369
|
return null;
|
|
15066
15370
|
}
|
|
15067
15371
|
}
|
|
15068
15372
|
var DIFFABLE_SOURCE_RE = /\.(ts|tsx|js|jsx|mjs|cjs|css|scss|sass|less|json|jsonc|py|go|rs|java|rb|php|swift|kt|c|h|cpp|cc|cxx|hpp|cs|sql|yaml|yml|toml)$/i;
|
|
15069
|
-
function surgicalHint(filePath,
|
|
15070
|
-
const isDocFile = /\.(md|mdx|rst|txt)$/i.test(
|
|
15071
|
-
const isSectionFile = /\.(json|jsonc|css|scss|sass|less|yaml|yml|toml)$/i.test(
|
|
15373
|
+
function surgicalHint(filePath, basename9) {
|
|
15374
|
+
const isDocFile = /\.(md|mdx|rst|txt)$/i.test(basename9);
|
|
15375
|
+
const isSectionFile = /\.(json|jsonc|css|scss|sass|less|yaml|yml|toml)$/i.test(basename9);
|
|
15072
15376
|
if (isDocFile) {
|
|
15073
15377
|
return 'Use `token-goat section "' + filePath + '::HeadingName"` to extract a part.';
|
|
15074
15378
|
} else if (isSectionFile) {
|
|
@@ -15119,8 +15423,8 @@ function preReadHandler(event) {
|
|
|
15119
15423
|
"node_modules is typically noise; use npm ls, npm outdated, or npm audit instead for dependency info. To force access, use: token-goat read node_modules/package/file.js::symbol-name or token-goat section node_modules/package/file.js::heading"
|
|
15120
15424
|
);
|
|
15121
15425
|
}
|
|
15122
|
-
const
|
|
15123
|
-
if (isLockFile(
|
|
15426
|
+
const basename9 = path13.basename(normalized);
|
|
15427
|
+
if (isLockFile(basename9)) {
|
|
15124
15428
|
return denyOutput(
|
|
15125
15429
|
'Lock files are rarely useful to read in full. Use `token-goat section "' + normalized + '::<section>"` to extract a specific dependency, or read the relevant manifest instead.'
|
|
15126
15430
|
);
|
|
@@ -15140,25 +15444,25 @@ function preReadHandler(event) {
|
|
|
15140
15444
|
recordFileRead(normalized);
|
|
15141
15445
|
return contextOutput(manifestHint.text);
|
|
15142
15446
|
}
|
|
15143
|
-
if (isTsConfigFile(
|
|
15447
|
+
if (isTsConfigFile(basename9) && wasFileReadThisSession(normalized)) {
|
|
15144
15448
|
recordFileRead(normalized);
|
|
15145
15449
|
return contextOutput(
|
|
15146
|
-
"Already read " +
|
|
15450
|
+
"Already read " + basename9 + '. Use `token-goat section "' + normalized + '::compilerOptions"` to extract compiler options, or `token-goat config-get ' + normalized + " compilerOptions.target` for a single value."
|
|
15147
15451
|
);
|
|
15148
15452
|
}
|
|
15149
|
-
if (isManifestFile(
|
|
15453
|
+
if (isManifestFile(basename9) && wasFileReadThisSession(normalized)) {
|
|
15150
15454
|
recordFileRead(normalized);
|
|
15151
15455
|
return contextOutput(
|
|
15152
|
-
"You've already read " +
|
|
15456
|
+
"You've already read " + basename9 + '. Use `token-goat section "' + normalized + '::<field>"` or `token-goat config-get ' + normalized + " <key>` to extract just the value you need."
|
|
15153
15457
|
);
|
|
15154
15458
|
}
|
|
15155
|
-
const isMarkdown = /\.(md|mdx|markdown|rst)$/i.test(
|
|
15459
|
+
const isMarkdown = /\.(md|mdx|markdown|rst)$/i.test(basename9);
|
|
15156
15460
|
if (isMarkdown) {
|
|
15157
15461
|
let fileContent = null;
|
|
15158
15462
|
try {
|
|
15159
15463
|
const sz = statSize(normalized);
|
|
15160
15464
|
if (sz !== null && sz >= MARKDOWN_SIZE_THRESHOLD) {
|
|
15161
|
-
fileContent =
|
|
15465
|
+
fileContent = fs10.readFileSync(normalized, "utf8");
|
|
15162
15466
|
}
|
|
15163
15467
|
} catch {
|
|
15164
15468
|
}
|
|
@@ -15167,9 +15471,9 @@ function preReadHandler(event) {
|
|
|
15167
15471
|
if (headings.length >= 3) {
|
|
15168
15472
|
recordFileRead(normalized);
|
|
15169
15473
|
const hintText = formatHeadingTree(headings, normalized);
|
|
15170
|
-
const wellKnown = getWellKnownSections(
|
|
15474
|
+
const wellKnown = getWellKnownSections(basename9);
|
|
15171
15475
|
const wellKnownText = wellKnown.length > 0 ? "\nQuick access: " + wellKnown.map((s) => 'token-goat section "' + normalized + "::" + s + '"').join(" | ") : "";
|
|
15172
|
-
const changelogExtra =
|
|
15476
|
+
const changelogExtra = basename9.toLowerCase() === "changelog.md" ? extractChangelogVersionHint(fileContent, normalized) : "";
|
|
15173
15477
|
return denyOutput(hintText + wellKnownText + changelogExtra);
|
|
15174
15478
|
}
|
|
15175
15479
|
}
|
|
@@ -15178,19 +15482,19 @@ function preReadHandler(event) {
|
|
|
15178
15482
|
if (isMemoryMd && wasFileReadThisSession(normalized)) {
|
|
15179
15483
|
recordFileRead(normalized);
|
|
15180
15484
|
recordStat("session_hint", 0, 0);
|
|
15181
|
-
const isMainMemory =
|
|
15485
|
+
const isMainMemory = basename9.toLowerCase() === "memory.md";
|
|
15182
15486
|
return denyOutput(
|
|
15183
15487
|
isMainMemory ? "MEMORY.md was read this session. Its content is in the compact manifest as 'session memory'." : normalized + ' was already read this session. Memory files rarely change mid-session. Use `token-goat section "' + normalized + '::SectionHeading"` to extract one section.'
|
|
15184
15488
|
);
|
|
15185
15489
|
}
|
|
15186
|
-
if (/^\.improve-state-.*\.json$/.test(
|
|
15490
|
+
if (/^\.improve-state-.*\.json$/.test(basename9) && wasFileReadThisSession(normalized)) {
|
|
15187
15491
|
recordFileRead(normalized);
|
|
15188
15492
|
recordStat("session_hint", 0, 0);
|
|
15189
15493
|
return denyOutput(
|
|
15190
15494
|
"Orchestrator state already read this session. Use `token-goat bash-output <id>` or recall it from the compact manifest."
|
|
15191
15495
|
);
|
|
15192
15496
|
}
|
|
15193
|
-
if (/^\.env(\.\w+)?$/.test(
|
|
15497
|
+
if (/^\.env(\.\w+)?$/.test(basename9) && wasFileReadThisSession(normalized)) {
|
|
15194
15498
|
recordFileRead(normalized);
|
|
15195
15499
|
recordStat("session_hint", 0, 0);
|
|
15196
15500
|
return denyOutput(
|
|
@@ -15203,7 +15507,7 @@ function preReadHandler(event) {
|
|
|
15203
15507
|
recordFileRead(normalized);
|
|
15204
15508
|
recordStat("session_hint", 0, 0);
|
|
15205
15509
|
return denyOutput(
|
|
15206
|
-
"File was truncated on last read.
|
|
15510
|
+
"File was truncated on last read. " + sessionArtifactRecall(normalized)
|
|
15207
15511
|
);
|
|
15208
15512
|
}
|
|
15209
15513
|
const artifactSessionId = getSessionId();
|
|
@@ -15212,7 +15516,7 @@ function preReadHandler(event) {
|
|
|
15212
15516
|
try {
|
|
15213
15517
|
const sz = statSize(normalized);
|
|
15214
15518
|
if (sz !== null && sz <= 256 * 1024) {
|
|
15215
|
-
const currentContent =
|
|
15519
|
+
const currentContent = fs10.readFileSync(normalized, "utf8");
|
|
15216
15520
|
const TRUNC_MARKER = "\n<snapshot truncated at ";
|
|
15217
15521
|
const oldRaw = oldArtifactSnap.toString("utf8");
|
|
15218
15522
|
const truncIdx = oldRaw.indexOf(TRUNC_MARKER);
|
|
@@ -15221,16 +15525,16 @@ function preReadHandler(event) {
|
|
|
15221
15525
|
recordFileRead(normalized);
|
|
15222
15526
|
recordStat("session_hint", 0, 0);
|
|
15223
15527
|
return denyOutput(
|
|
15224
|
-
|
|
15528
|
+
basename9 + " is unchanged since last read. " + sessionArtifactRecall(normalized)
|
|
15225
15529
|
);
|
|
15226
15530
|
}
|
|
15227
|
-
const diff = buildLineDiff(oldContent, currentContent,
|
|
15531
|
+
const diff = buildLineDiff(oldContent, currentContent, basename9);
|
|
15228
15532
|
if (diff !== "") {
|
|
15229
15533
|
recordFileRead(normalized);
|
|
15230
15534
|
const savedBytes = Math.max(0, currentContent.length - diff.length);
|
|
15231
15535
|
recordStat("session_hint", savedBytes, Math.round(savedBytes / 4));
|
|
15232
15536
|
return denyOutput(
|
|
15233
|
-
"Content changed since last read of " +
|
|
15537
|
+
"Content changed since last read of " + basename9 + ". Here is what changed:\n\n```diff\n" + diff + "\n```\n\n" + sessionArtifactRecall(normalized)
|
|
15234
15538
|
);
|
|
15235
15539
|
}
|
|
15236
15540
|
}
|
|
@@ -15240,18 +15544,16 @@ function preReadHandler(event) {
|
|
|
15240
15544
|
recordFileRead(normalized);
|
|
15241
15545
|
recordStat("session_hint", 0, 0);
|
|
15242
15546
|
return denyOutput(
|
|
15243
|
-
normalized + " was already read this session.
|
|
15547
|
+
normalized + " was already read this session. " + sessionArtifactRecall(normalized)
|
|
15244
15548
|
);
|
|
15245
15549
|
}
|
|
15246
15550
|
if (/[/\\]tasks[/\\][a-z0-9]+\.output$/i.test(normalized)) {
|
|
15247
15551
|
recordFileRead(normalized);
|
|
15248
|
-
return contextOutput(
|
|
15249
|
-
"Session transcript: use `token-goat bash-output --tail N` or `--grep PATTERN` to read a slice instead of the full file."
|
|
15250
|
-
);
|
|
15552
|
+
return contextOutput("Session transcript: " + sessionArtifactRecall(normalized));
|
|
15251
15553
|
}
|
|
15252
15554
|
}
|
|
15253
|
-
const isDocDiffable = /\.(md|mdx|rst|txt)$/i.test(
|
|
15254
|
-
const isSourceDiffable = loadConfig().hints.serve_diff_on_reread && DIFFABLE_SOURCE_RE.test(
|
|
15555
|
+
const isDocDiffable = /\.(md|mdx|rst|txt)$/i.test(basename9);
|
|
15556
|
+
const isSourceDiffable = loadConfig().hints.serve_diff_on_reread && DIFFABLE_SOURCE_RE.test(basename9);
|
|
15255
15557
|
if ((isDocDiffable || isSourceDiffable) && wasFileReadThisSession(normalized)) {
|
|
15256
15558
|
if (wasFileTruncatedThisSession(normalized)) {
|
|
15257
15559
|
recordFileRead(normalized);
|
|
@@ -15266,7 +15568,7 @@ function preReadHandler(event) {
|
|
|
15266
15568
|
try {
|
|
15267
15569
|
const sz = statSize(normalized);
|
|
15268
15570
|
if (sz !== null && sz <= 256 * 1024) {
|
|
15269
|
-
const currentContent =
|
|
15571
|
+
const currentContent = fs10.readFileSync(normalized, "utf8");
|
|
15270
15572
|
const TRUNC_MARKER = "\n<snapshot truncated at ";
|
|
15271
15573
|
const oldRaw = oldSnap.toString("utf8");
|
|
15272
15574
|
const truncIdx = oldRaw.indexOf(TRUNC_MARKER);
|
|
@@ -15275,10 +15577,10 @@ function preReadHandler(event) {
|
|
|
15275
15577
|
recordFileRead(normalized);
|
|
15276
15578
|
recordStat("session_hint", 0, 0);
|
|
15277
15579
|
return denyOutput(
|
|
15278
|
-
|
|
15580
|
+
basename9 + " is unchanged since last read. " + surgicalHint(normalized, basename9)
|
|
15279
15581
|
);
|
|
15280
15582
|
}
|
|
15281
|
-
const diff = buildLineDiff(oldContent, currentContent,
|
|
15583
|
+
const diff = buildLineDiff(oldContent, currentContent, basename9);
|
|
15282
15584
|
if (diff !== "") {
|
|
15283
15585
|
if (isSourceDiffable && !isDocDiffable && diff.length > currentContent.length * 0.6) {
|
|
15284
15586
|
} else {
|
|
@@ -15286,7 +15588,7 @@ function preReadHandler(event) {
|
|
|
15286
15588
|
const savedBytes = Math.max(0, currentContent.length - diff.length);
|
|
15287
15589
|
recordStat("session_hint", savedBytes, Math.round(savedBytes / 4));
|
|
15288
15590
|
return denyOutput(
|
|
15289
|
-
"Content changed since last read of " +
|
|
15591
|
+
"Content changed since last read of " + basename9 + ". Here is what changed:\n\n```diff\n" + diff + "\n```\n\n" + surgicalHint(normalized, basename9)
|
|
15290
15592
|
);
|
|
15291
15593
|
}
|
|
15292
15594
|
}
|
|
@@ -15298,7 +15600,7 @@ function preReadHandler(event) {
|
|
|
15298
15600
|
if (wasFileReadThisSession(normalized)) {
|
|
15299
15601
|
const entry = getSessionFiles().get(normalized);
|
|
15300
15602
|
const reads = entry?.readCount ?? 1;
|
|
15301
|
-
const
|
|
15603
|
+
const plural2 = reads === 1 ? "read" : "reads";
|
|
15302
15604
|
recordFileRead(normalized);
|
|
15303
15605
|
const rereadBytes = statSize(normalized) ?? 0;
|
|
15304
15606
|
recordStat("session_hint", rereadBytes, Math.round(rereadBytes / 4));
|
|
@@ -15307,12 +15609,12 @@ function preReadHandler(event) {
|
|
|
15307
15609
|
'File was truncated on last read (>33K tokens). Use `token-goat skeleton "' + normalized + '"` for structure or `token-goat read "' + normalized + '::SymbolName"` for one function.'
|
|
15308
15610
|
);
|
|
15309
15611
|
}
|
|
15310
|
-
if (/\.(md|mdx)$/i.test(
|
|
15612
|
+
if (/\.(md|mdx)$/i.test(basename9)) {
|
|
15311
15613
|
return denyOutput(
|
|
15312
15614
|
'Markdown file already read this session. Use `token-goat section "' + normalized + '::HeadingName"` to read one section.'
|
|
15313
15615
|
);
|
|
15314
15616
|
}
|
|
15315
|
-
const isSourceExt = /\.(ts|tsx|js|jsx|py|go|rs|java|rb|php|swift|kt|cpp|c|h)$/i.test(
|
|
15617
|
+
const isSourceExt = /\.(ts|tsx|js|jsx|py|go|rs|java|rb|php|swift|kt|cpp|c|h)$/i.test(basename9);
|
|
15316
15618
|
if (isSourceExt && reads >= 2) {
|
|
15317
15619
|
recordStat("read_count_deny", rereadBytes, Math.round(rereadBytes / 4));
|
|
15318
15620
|
return denyOutput(
|
|
@@ -15322,11 +15624,11 @@ function preReadHandler(event) {
|
|
|
15322
15624
|
const hint = _isDocFile(normalized) ? 'Use `token-goat section "' + normalized + '::SectionName"` to read one section.' : "Use token-goat read/section/symbol to re-read surgically.";
|
|
15323
15625
|
if (rereadBytes >= REREAD_DENY_BYTES || reads >= 2) {
|
|
15324
15626
|
return denyOutput(
|
|
15325
|
-
normalized + " was already read this session (" + reads + " " +
|
|
15627
|
+
normalized + " was already read this session (" + reads + " " + plural2 + "). " + hint
|
|
15326
15628
|
);
|
|
15327
15629
|
}
|
|
15328
15630
|
return contextOutput(
|
|
15329
|
-
"Note: " + normalized + " was already read this session (" + reads + " " +
|
|
15631
|
+
"Note: " + normalized + " was already read this session (" + reads + " " + plural2 + "). " + hint
|
|
15330
15632
|
);
|
|
15331
15633
|
}
|
|
15332
15634
|
const size = statSize(normalized);
|
|
@@ -15344,7 +15646,7 @@ function preReadHandler(event) {
|
|
|
15344
15646
|
"Note: " + normalized + " is large (" + kb + "KB). " + hint
|
|
15345
15647
|
);
|
|
15346
15648
|
}
|
|
15347
|
-
const fileTypeExt =
|
|
15649
|
+
const fileTypeExt = path13.extname(normalized).slice(1).toLowerCase();
|
|
15348
15650
|
const binaryExts = /* @__PURE__ */ new Set(["pdf", "docx", "xlsx", "pptx", "odt", "ods", "ott", "odp"]);
|
|
15349
15651
|
const textTypeExts = /* @__PURE__ */ new Set(["html", "htm", "xhtml", "txt", "log", "out", "err", "trace", "csv", "tsv"]);
|
|
15350
15652
|
const fileStatSize = size ?? statSize(normalized) ?? 0;
|
|
@@ -15353,7 +15655,7 @@ function preReadHandler(event) {
|
|
|
15353
15655
|
let ftContent = "";
|
|
15354
15656
|
if (!binaryExts.has(fileTypeExt)) {
|
|
15355
15657
|
try {
|
|
15356
|
-
ftContent =
|
|
15658
|
+
ftContent = fs10.readFileSync(normalized, "utf8");
|
|
15357
15659
|
} catch {
|
|
15358
15660
|
}
|
|
15359
15661
|
}
|
|
@@ -15387,13 +15689,13 @@ function postReadHandler(event) {
|
|
|
15387
15689
|
if (respText.includes("[Truncated:") || respText.includes("Truncated: PARTIAL view")) {
|
|
15388
15690
|
markFileTruncated(normalized);
|
|
15389
15691
|
}
|
|
15390
|
-
const postBasename =
|
|
15692
|
+
const postBasename = path13.basename(normalized);
|
|
15391
15693
|
const diffSourcesEnabled = loadConfig().hints.serve_diff_on_reread;
|
|
15392
15694
|
if (/\.(md|mdx|rst|txt)$/i.test(postBasename) || isSessionArtifactFile(normalized) || diffSourcesEnabled && DIFFABLE_SOURCE_RE.test(postBasename)) {
|
|
15393
15695
|
try {
|
|
15394
15696
|
const sz = statSize(normalized);
|
|
15395
15697
|
if (sz !== null && sz <= 256 * 1024) {
|
|
15396
|
-
const content =
|
|
15698
|
+
const content = fs10.readFileSync(normalized);
|
|
15397
15699
|
store(getSessionId(), normalized, content);
|
|
15398
15700
|
}
|
|
15399
15701
|
} catch {
|
|
@@ -15405,31 +15707,31 @@ registerHook("post_tool_use", postReadHandler, { toolName: "Read" });
|
|
|
15405
15707
|
|
|
15406
15708
|
// src/hooks_edit.ts
|
|
15407
15709
|
init_define_import_meta_env();
|
|
15408
|
-
import * as
|
|
15710
|
+
import * as path15 from "node:path";
|
|
15409
15711
|
|
|
15410
15712
|
// src/hooks_index.ts
|
|
15411
15713
|
init_define_import_meta_env();
|
|
15412
|
-
import * as
|
|
15413
|
-
import * as
|
|
15714
|
+
import * as fs11 from "node:fs";
|
|
15715
|
+
import * as path14 from "node:path";
|
|
15414
15716
|
function dirtyQueuePath() {
|
|
15415
|
-
return
|
|
15717
|
+
return path14.join(dataDir(), "queue", "dirty.txt");
|
|
15416
15718
|
}
|
|
15417
15719
|
function appendDirtyPath(normalizedPath) {
|
|
15418
15720
|
const queuePath = dirtyQueuePath();
|
|
15419
|
-
const dir =
|
|
15721
|
+
const dir = path14.dirname(queuePath);
|
|
15420
15722
|
try {
|
|
15421
|
-
|
|
15723
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
15422
15724
|
} catch (e) {
|
|
15423
|
-
if (e.code !== "EEXIST" || !
|
|
15725
|
+
if (e.code !== "EEXIST" || !fs11.existsSync(dir)) throw e;
|
|
15424
15726
|
}
|
|
15425
|
-
|
|
15727
|
+
fs11.appendFileSync(queuePath, `${normalizedPath}
|
|
15426
15728
|
`);
|
|
15427
15729
|
}
|
|
15428
15730
|
function getDirtyPaths() {
|
|
15429
15731
|
const queuePath = dirtyQueuePath();
|
|
15430
15732
|
let raw;
|
|
15431
15733
|
try {
|
|
15432
|
-
raw =
|
|
15734
|
+
raw = fs11.readFileSync(queuePath, "utf8");
|
|
15433
15735
|
} catch {
|
|
15434
15736
|
return [];
|
|
15435
15737
|
}
|
|
@@ -15445,16 +15747,16 @@ function getDirtyPaths() {
|
|
|
15445
15747
|
}
|
|
15446
15748
|
function clearDirtyQueue() {
|
|
15447
15749
|
try {
|
|
15448
|
-
|
|
15750
|
+
fs11.rmSync(dirtyQueuePath(), { force: true });
|
|
15449
15751
|
} catch {
|
|
15450
15752
|
}
|
|
15451
15753
|
}
|
|
15452
15754
|
function preCompactIndexHandler(_event) {
|
|
15453
15755
|
const paths = getDirtyPaths();
|
|
15454
15756
|
if (paths.length > 0) {
|
|
15455
|
-
const sidecar =
|
|
15757
|
+
const sidecar = path14.join(dataDir(), "queue", "pending.txt");
|
|
15456
15758
|
try {
|
|
15457
|
-
|
|
15759
|
+
fs11.mkdirSync(path14.dirname(sidecar), { recursive: true });
|
|
15458
15760
|
atomicWriteBytes(sidecar, Buffer.from(`${paths.join("\n")}
|
|
15459
15761
|
`, "utf8"));
|
|
15460
15762
|
clearDirtyQueue();
|
|
@@ -15472,7 +15774,7 @@ function postEditHandler(event) {
|
|
|
15472
15774
|
const normalized = normalizePath(filePath);
|
|
15473
15775
|
recordFileEdit(normalized);
|
|
15474
15776
|
appendDirtyPath(normalized);
|
|
15475
|
-
const editedBasename =
|
|
15777
|
+
const editedBasename = path15.basename(normalized);
|
|
15476
15778
|
if (/\.(md|mdx|markdown|rst)$/i.test(editedBasename)) {
|
|
15477
15779
|
const escapedPath = normalized.replace(/`/g, "\\`");
|
|
15478
15780
|
return contextOutput(
|
|
@@ -15489,9 +15791,9 @@ init_define_import_meta_env();
|
|
|
15489
15791
|
var MAX_ROWS = 40;
|
|
15490
15792
|
function renderReadRow(entry) {
|
|
15491
15793
|
const kb = Math.max(1, Math.round(entry.sizeBytes / 1024));
|
|
15492
|
-
const
|
|
15794
|
+
const plural2 = entry.readCount === 1 ? "read" : "reads";
|
|
15493
15795
|
const edited = entry.wasEdited ? ", edited" : "";
|
|
15494
|
-
return `- ${entry.path} (${kb}kb, ${entry.readCount} ${
|
|
15796
|
+
return `- ${entry.path} (${kb}kb, ${entry.readCount} ${plural2}${edited})`;
|
|
15495
15797
|
}
|
|
15496
15798
|
function buildManifest() {
|
|
15497
15799
|
const files = [...getSessionFiles().values()];
|
|
@@ -15620,6 +15922,50 @@ registerHook("subagent_stop", subagentStopHandler);
|
|
|
15620
15922
|
|
|
15621
15923
|
// src/hooks_fetch.ts
|
|
15622
15924
|
init_define_import_meta_env();
|
|
15925
|
+
|
|
15926
|
+
// src/web_cache.ts
|
|
15927
|
+
init_define_import_meta_env();
|
|
15928
|
+
var WEB_OUTPUT_SUBDIR = "web_outputs";
|
|
15929
|
+
var _byId = /* @__PURE__ */ new Map();
|
|
15930
|
+
var _urlIndex = /* @__PURE__ */ new Map();
|
|
15931
|
+
function cacheIdForUrl(url) {
|
|
15932
|
+
return shortFingerprint(url);
|
|
15933
|
+
}
|
|
15934
|
+
function storeWebOutput(url, content) {
|
|
15935
|
+
const cacheId = cacheIdForUrl(url);
|
|
15936
|
+
_byId.set(cacheId, content);
|
|
15937
|
+
_urlIndex.set(url, cacheId);
|
|
15938
|
+
storeBlob(WEB_OUTPUT_SUBDIR, cacheId, { url, content });
|
|
15939
|
+
return cacheId;
|
|
15940
|
+
}
|
|
15941
|
+
function coerceWebBlob(raw) {
|
|
15942
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
15943
|
+
const o = raw;
|
|
15944
|
+
if (typeof o["content"] !== "string") return null;
|
|
15945
|
+
return { url: typeof o["url"] === "string" ? o["url"] : null, content: o["content"] };
|
|
15946
|
+
}
|
|
15947
|
+
function getWebOutput(cacheId) {
|
|
15948
|
+
const hit = _byId.get(cacheId);
|
|
15949
|
+
if (hit !== void 0) return hit;
|
|
15950
|
+
const blob = coerceWebBlob(loadBlob(WEB_OUTPUT_SUBDIR, cacheId));
|
|
15951
|
+
if (blob === null) return null;
|
|
15952
|
+
_byId.set(cacheId, blob.content);
|
|
15953
|
+
if (blob.url !== null) _urlIndex.set(blob.url, cacheId);
|
|
15954
|
+
return blob.content;
|
|
15955
|
+
}
|
|
15956
|
+
function getWebOutputByUrl(url) {
|
|
15957
|
+
const cacheId = _urlIndex.get(url);
|
|
15958
|
+
if (cacheId === void 0) return null;
|
|
15959
|
+
const content = _byId.get(cacheId);
|
|
15960
|
+
if (content === void 0) return null;
|
|
15961
|
+
return { cacheId, content };
|
|
15962
|
+
}
|
|
15963
|
+
registerReset(() => {
|
|
15964
|
+
_byId = /* @__PURE__ */ new Map();
|
|
15965
|
+
_urlIndex = /* @__PURE__ */ new Map();
|
|
15966
|
+
});
|
|
15967
|
+
|
|
15968
|
+
// src/hooks_fetch.ts
|
|
15623
15969
|
function extractToolResponse(raw) {
|
|
15624
15970
|
const toolResponse = raw["tool_response"];
|
|
15625
15971
|
if (typeof toolResponse === "string") {
|
|
@@ -15670,6 +16016,8 @@ function postFetchHandler(event) {
|
|
|
15670
16016
|
if (!body || body.length < 1024) {
|
|
15671
16017
|
return passOutput();
|
|
15672
16018
|
}
|
|
16019
|
+
const cacheId = storeWebOutput(url, body);
|
|
16020
|
+
recordWebFetch(url, cacheId);
|
|
15673
16021
|
return passOutput();
|
|
15674
16022
|
} catch {
|
|
15675
16023
|
return passOutput();
|
|
@@ -15754,9 +16102,10 @@ init_define_import_meta_env();
|
|
|
15754
16102
|
|
|
15755
16103
|
// src/bash_output_cache.ts
|
|
15756
16104
|
init_define_import_meta_env();
|
|
15757
|
-
import * as
|
|
15758
|
-
import { resolve as
|
|
15759
|
-
var
|
|
16105
|
+
import * as fs12 from "fs/promises";
|
|
16106
|
+
import { resolve as resolve5 } from "path";
|
|
16107
|
+
var BASH_OUTPUT_SUBDIR = "bash_outputs";
|
|
16108
|
+
var _byId2 = /* @__PURE__ */ new Map();
|
|
15760
16109
|
var _globsByKey = /* @__PURE__ */ new Map();
|
|
15761
16110
|
var _grepsByKey = /* @__PURE__ */ new Map();
|
|
15762
16111
|
var COMMAND_PATTERNS = {
|
|
@@ -15797,7 +16146,7 @@ async function gitStateFingerprint(cwd) {
|
|
|
15797
16146
|
const headSha = headResult.stdout.trim();
|
|
15798
16147
|
let indexMtime = "";
|
|
15799
16148
|
try {
|
|
15800
|
-
const stat3 = await
|
|
16149
|
+
const stat3 = await fs12.stat(resolve5(cwd, ".git", "index"));
|
|
15801
16150
|
indexMtime = stat3.mtimeMs.toString();
|
|
15802
16151
|
} catch {
|
|
15803
16152
|
}
|
|
@@ -15807,9 +16156,9 @@ async function gitStateFingerprint(cwd) {
|
|
|
15807
16156
|
return null;
|
|
15808
16157
|
}
|
|
15809
16158
|
}
|
|
15810
|
-
async function dirStateFingerprint(
|
|
16159
|
+
async function dirStateFingerprint(path22) {
|
|
15811
16160
|
try {
|
|
15812
|
-
const stat3 = await
|
|
16161
|
+
const stat3 = await fs12.stat(path22);
|
|
15813
16162
|
if (!stat3.isDirectory()) return null;
|
|
15814
16163
|
return shortFingerprint(stat3.mtimeMs.toString());
|
|
15815
16164
|
} catch {
|
|
@@ -15825,7 +16174,7 @@ async function depLockfileFingerprint(cmd, cwd) {
|
|
|
15825
16174
|
if (!candidates) return null;
|
|
15826
16175
|
for (const lockfile of candidates) {
|
|
15827
16176
|
try {
|
|
15828
|
-
const content = await
|
|
16177
|
+
const content = await fs12.readFile(resolve5(cwd, lockfile));
|
|
15829
16178
|
return shortFingerprint(content);
|
|
15830
16179
|
} catch {
|
|
15831
16180
|
continue;
|
|
@@ -15895,78 +16244,1195 @@ async function storeBashOutput(command, output, exitCode, cwd = null) {
|
|
|
15895
16244
|
storedAt: Date.now(),
|
|
15896
16245
|
sizeBytes: Buffer.byteLength(output, "utf-8")
|
|
15897
16246
|
};
|
|
15898
|
-
|
|
16247
|
+
_byId2.set(id, entry);
|
|
16248
|
+
storeBlob(BASH_OUTPUT_SUBDIR, id, entry);
|
|
15899
16249
|
return id;
|
|
15900
16250
|
}
|
|
16251
|
+
function coerceBashEntry(raw) {
|
|
16252
|
+
if (raw === null || typeof raw !== "object") return null;
|
|
16253
|
+
const o = raw;
|
|
16254
|
+
if (typeof o["id"] !== "string" || typeof o["command"] !== "string" || typeof o["output"] !== "string" || typeof o["exitCode"] !== "number" || typeof o["storedAt"] !== "number" || typeof o["sizeBytes"] !== "number") {
|
|
16255
|
+
return null;
|
|
16256
|
+
}
|
|
16257
|
+
return {
|
|
16258
|
+
id: o["id"],
|
|
16259
|
+
command: o["command"],
|
|
16260
|
+
output: o["output"],
|
|
16261
|
+
exitCode: o["exitCode"],
|
|
16262
|
+
storedAt: o["storedAt"],
|
|
16263
|
+
sizeBytes: o["sizeBytes"]
|
|
16264
|
+
};
|
|
16265
|
+
}
|
|
15901
16266
|
function getBashOutput(id) {
|
|
15902
|
-
|
|
16267
|
+
const hit = _byId2.get(id);
|
|
16268
|
+
if (hit !== void 0) return hit;
|
|
16269
|
+
const entry = coerceBashEntry(loadBlob(BASH_OUTPUT_SUBDIR, id));
|
|
16270
|
+
if (entry === null) return null;
|
|
16271
|
+
_byId2.set(id, entry);
|
|
16272
|
+
return entry;
|
|
15903
16273
|
}
|
|
15904
16274
|
registerReset(() => {
|
|
15905
|
-
|
|
16275
|
+
_byId2 = /* @__PURE__ */ new Map();
|
|
15906
16276
|
_globsByKey = /* @__PURE__ */ new Map();
|
|
15907
16277
|
_grepsByKey = /* @__PURE__ */ new Map();
|
|
15908
16278
|
});
|
|
15909
16279
|
|
|
15910
|
-
// src/
|
|
15911
|
-
|
|
15912
|
-
|
|
15913
|
-
|
|
16280
|
+
// src/tool_filters/index.ts
|
|
16281
|
+
init_define_import_meta_env();
|
|
16282
|
+
|
|
16283
|
+
// src/tool_filters/helpers.ts
|
|
16284
|
+
init_define_import_meta_env();
|
|
16285
|
+
|
|
16286
|
+
// src/bash_compress.ts
|
|
16287
|
+
init_define_import_meta_env();
|
|
16288
|
+
|
|
16289
|
+
// src/filters.ts
|
|
16290
|
+
init_define_import_meta_env();
|
|
16291
|
+
|
|
16292
|
+
// src/bash_compress.ts
|
|
16293
|
+
var ANSI_ESCAPE_RE = (
|
|
16294
|
+
// eslint-disable-next-line no-control-regex -- intentionally matches ESC (\x1B) and BEL (\x07) control bytes
|
|
16295
|
+
/\x1B\[[0-?]*[ -/]*[@-~]|\x1B\].*?(?:\x07|\x1B\\)|\x1B[PX^_].*?\x1B\\|\x1B[@-Z\\-_]/gs
|
|
16296
|
+
);
|
|
16297
|
+
function stripAnsiCodes(text) {
|
|
16298
|
+
if (!text.includes("\x1B")) return text;
|
|
16299
|
+
return text.replace(ANSI_ESCAPE_RE, "");
|
|
15914
16300
|
}
|
|
15915
|
-
|
|
15916
|
-
|
|
15917
|
-
|
|
15918
|
-
|
|
15919
|
-
|
|
15920
|
-
|
|
15921
|
-
|
|
15922
|
-
|
|
15923
|
-
|
|
15924
|
-
|
|
15925
|
-
|
|
15926
|
-
|
|
15927
|
-
|
|
15928
|
-
|
|
16301
|
+
|
|
16302
|
+
// src/tool_filters/helpers.ts
|
|
16303
|
+
var DEFAULT_MAX_LINES = 1e3;
|
|
16304
|
+
var DEFAULT_MAX_BYTES = 64 * 1024;
|
|
16305
|
+
var MAX_INSPECT_BYTES = 2 * 1024 * 1024;
|
|
16306
|
+
var DEFAULT_MAX_INPUT_BYTES = 500 * 1024;
|
|
16307
|
+
var FALLBACK_MAX_LINE_CHARS = 400;
|
|
16308
|
+
function getMaxInputBytes() {
|
|
16309
|
+
const raw = process.env["TOKEN_GOAT_FILTER_MAX_BYTES"];
|
|
16310
|
+
const v = raw ? Number.parseInt(raw, 10) : 0;
|
|
16311
|
+
return Number.isFinite(v) && v > 0 ? v : DEFAULT_MAX_INPUT_BYTES;
|
|
16312
|
+
}
|
|
16313
|
+
function compressionMarker(filter, pct) {
|
|
16314
|
+
return `
|
|
16315
|
+
[token-goat: ${filter} filter -${Math.round(pct)}%; disable via TOKEN_GOAT_BASH_COMPRESS]`;
|
|
16316
|
+
}
|
|
16317
|
+
var ERROR_SIGNAL_RE = /error:|Error:|ERROR|FAILED|failed|fatal:|Traceback|exception:|Exception:|AssertionError|assert |panic:/i;
|
|
16318
|
+
var REDIRECT_TOKEN_RE = /^(\d*)(>>?|<<?).*$|^&>$|^>&.*$/;
|
|
16319
|
+
var BYTES_ELIDED_MARKER_RE = /\n\.\.\. \[\d+ bytes elided by token-goat\]$/;
|
|
16320
|
+
var CONTROL_CHAR_RE = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/g;
|
|
16321
|
+
function utf8Len(s) {
|
|
16322
|
+
return Buffer.byteLength(s, "utf8");
|
|
16323
|
+
}
|
|
16324
|
+
function safeDecode(text) {
|
|
16325
|
+
return text.indexOf("\0") === -1 ? text : text.split("\0").join("");
|
|
16326
|
+
}
|
|
16327
|
+
function sanitizeControlChars(text) {
|
|
16328
|
+
return text.replace(CONTROL_CHAR_RE, "");
|
|
16329
|
+
}
|
|
16330
|
+
function stripProgress(text) {
|
|
16331
|
+
if (!text.includes("\r")) return text;
|
|
16332
|
+
return text.split("\n").map((line) => line.includes("\r") ? line.slice(line.lastIndexOf("\r") + 1) : line).join("\n");
|
|
16333
|
+
}
|
|
16334
|
+
function normalise(text, opts = {}) {
|
|
16335
|
+
if (!text) return "";
|
|
16336
|
+
let t = text.replace(/\r\n/g, "\n");
|
|
16337
|
+
if (!opts.skipProgress) t = stripProgress(t);
|
|
16338
|
+
t = stripAnsiCodes(t);
|
|
16339
|
+
return sanitizeControlChars(t);
|
|
16340
|
+
}
|
|
16341
|
+
var UUID_RE = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i;
|
|
16342
|
+
var LONG_HEX_RE = /\b[0-9a-f]{32,}\b/i;
|
|
16343
|
+
var JWT_RE = /\b[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/;
|
|
16344
|
+
function hasHighEntropyToken(line) {
|
|
16345
|
+
if (UUID_RE.test(line) || LONG_HEX_RE.test(line) || JWT_RE.test(line)) return true;
|
|
16346
|
+
for (const tok of line.split(/[\s"'`,;:()[\]{}<>]+/)) {
|
|
16347
|
+
if (tok.length < 24) continue;
|
|
16348
|
+
if (/[a-z]/.test(tok) && /[A-Z]/.test(tok) && /[0-9]/.test(tok) && /^[A-Za-z0-9+/=_-]+$/.test(tok)) {
|
|
16349
|
+
return true;
|
|
16350
|
+
}
|
|
16351
|
+
}
|
|
16352
|
+
return false;
|
|
16353
|
+
}
|
|
16354
|
+
function dedupeConsecutive(lines, opts = {}) {
|
|
16355
|
+
const minRun = opts.minRun ?? 2;
|
|
16356
|
+
const fmt = opts.fmt ?? ((line, count2) => `${line} (\xD7${count2})`);
|
|
16357
|
+
const entropyBypass = opts.entropyBypass ?? false;
|
|
16358
|
+
const out2 = [];
|
|
16359
|
+
let prev = null;
|
|
16360
|
+
let count = 0;
|
|
16361
|
+
const flush = () => {
|
|
16362
|
+
if (prev === null) return;
|
|
16363
|
+
if (count >= minRun) out2.push(fmt(prev, count));
|
|
16364
|
+
else for (let i = 0; i < count; i++) out2.push(prev);
|
|
16365
|
+
};
|
|
16366
|
+
for (const line of lines) {
|
|
16367
|
+
if (entropyBypass && hasHighEntropyToken(line)) {
|
|
16368
|
+
flush();
|
|
16369
|
+
prev = null;
|
|
16370
|
+
count = 0;
|
|
16371
|
+
out2.push(line);
|
|
16372
|
+
continue;
|
|
16373
|
+
}
|
|
16374
|
+
if (line === prev) {
|
|
16375
|
+
count += 1;
|
|
16376
|
+
continue;
|
|
16377
|
+
}
|
|
16378
|
+
flush();
|
|
16379
|
+
prev = line;
|
|
16380
|
+
count = 1;
|
|
16381
|
+
}
|
|
16382
|
+
flush();
|
|
16383
|
+
return out2;
|
|
16384
|
+
}
|
|
16385
|
+
function truncateMiddle(lines, maxLines, opts = {}) {
|
|
16386
|
+
if (lines.length <= maxLines) return lines;
|
|
16387
|
+
const headRatio = opts.headRatio ?? 0.4;
|
|
16388
|
+
const markerFmt = opts.markerFmt ?? ((n) => `... [${n} lines elided by token-goat]`);
|
|
16389
|
+
const headKeep = Math.max(1, Math.floor(maxLines * headRatio));
|
|
16390
|
+
const tailKeep = Math.max(1, maxLines - headKeep);
|
|
16391
|
+
const elided = lines.length - headKeep - tailKeep;
|
|
16392
|
+
return [...lines.slice(0, headKeep), markerFmt(elided), ...lines.slice(lines.length - tailKeep)];
|
|
16393
|
+
}
|
|
16394
|
+
function truncateMiddleSmart(lines, maxLines, opts = {}) {
|
|
16395
|
+
if (lines.length <= maxLines) return lines;
|
|
16396
|
+
const headKeep = opts.headKeep ?? 10;
|
|
16397
|
+
const tailKeep = opts.tailKeep ?? 10;
|
|
16398
|
+
const errorContext = opts.errorContext ?? 2;
|
|
16399
|
+
const maxErrorLines = opts.maxErrorLines ?? 10;
|
|
16400
|
+
const markerFmt = opts.markerFmt ?? ((n) => `--- ${n} lines omitted ---`);
|
|
16401
|
+
const errorIndices = [];
|
|
16402
|
+
for (let i = 0; i < lines.length; i++) if (ERROR_SIGNAL_RE.test(lines[i])) errorIndices.push(i);
|
|
16403
|
+
if (errorIndices.length === 0) return truncateMiddle(lines, maxLines, { markerFmt });
|
|
16404
|
+
const total = lines.length;
|
|
16405
|
+
const effHead = Math.min(headKeep, Math.floor(total / 4));
|
|
16406
|
+
const effTail = Math.min(tailKeep, Math.floor(total / 4));
|
|
16407
|
+
const middle = /* @__PURE__ */ new Set();
|
|
16408
|
+
for (let k = 0; k < errorIndices.length && k < maxErrorLines; k++) {
|
|
16409
|
+
const ei = errorIndices[k];
|
|
16410
|
+
for (let ci = Math.max(0, ei - errorContext); ci < Math.min(total, ei + errorContext + 1); ci++) {
|
|
16411
|
+
middle.add(ci);
|
|
16412
|
+
}
|
|
16413
|
+
}
|
|
16414
|
+
for (let i = 0; i < effHead; i++) middle.delete(i);
|
|
16415
|
+
for (let i = total - effTail; i < total; i++) middle.delete(i);
|
|
16416
|
+
const budgetForMiddle = Math.max(0, maxLines - effHead - effTail);
|
|
16417
|
+
let sortedMiddle = Array.from(middle).sort((a, b) => a - b);
|
|
16418
|
+
if (sortedMiddle.length > budgetForMiddle) sortedMiddle = sortedMiddle.slice(0, budgetForMiddle);
|
|
16419
|
+
const result = [];
|
|
16420
|
+
const appendSection = (indices) => {
|
|
16421
|
+
for (let pos = 0; pos < indices.length; pos++) {
|
|
16422
|
+
const idx = indices[pos];
|
|
16423
|
+
if (pos > 0) {
|
|
16424
|
+
const prevIdx = indices[pos - 1];
|
|
16425
|
+
if (idx !== prevIdx + 1) result.push(markerFmt(idx - prevIdx - 1));
|
|
15929
16426
|
}
|
|
15930
|
-
|
|
15931
|
-
break;
|
|
16427
|
+
result.push(lines[idx]);
|
|
15932
16428
|
}
|
|
16429
|
+
};
|
|
16430
|
+
const headList = Array.from({ length: effHead }, (_, i) => i);
|
|
16431
|
+
const tailList = Array.from({ length: effTail }, (_, i) => total - effTail + i);
|
|
16432
|
+
appendSection(headList);
|
|
16433
|
+
if (sortedMiddle.length) {
|
|
16434
|
+
const gapAfterHead = sortedMiddle[0] - (headList.length ? headList[headList.length - 1] : -1) - 1;
|
|
16435
|
+
if (gapAfterHead > 0) result.push(markerFmt(gapAfterHead));
|
|
16436
|
+
appendSection(sortedMiddle);
|
|
16437
|
+
}
|
|
16438
|
+
if (tailList.length) {
|
|
16439
|
+
const lastKept = sortedMiddle.length ? sortedMiddle[sortedMiddle.length - 1] : headList.length ? headList[headList.length - 1] : -1;
|
|
16440
|
+
const gapBeforeTail = tailList[0] - lastKept - 1;
|
|
16441
|
+
if (gapBeforeTail > 0) result.push(markerFmt(gapBeforeTail));
|
|
16442
|
+
appendSection(tailList);
|
|
15933
16443
|
}
|
|
15934
|
-
|
|
15935
|
-
|
|
15936
|
-
|
|
15937
|
-
|
|
15938
|
-
|
|
15939
|
-
|
|
15940
|
-
|
|
15941
|
-
|
|
16444
|
+
return result;
|
|
16445
|
+
}
|
|
16446
|
+
function capBytes(text, maxBytes) {
|
|
16447
|
+
const encoded = Buffer.from(text, "utf8");
|
|
16448
|
+
if (encoded.length <= maxBytes) return text;
|
|
16449
|
+
const marker = `
|
|
16450
|
+
... [${encoded.length - maxBytes} bytes elided by token-goat]`;
|
|
16451
|
+
const budget = maxBytes - Buffer.byteLength(marker, "utf8");
|
|
16452
|
+
if (budget <= 0) return marker.trim();
|
|
16453
|
+
let slice = encoded.subarray(0, budget);
|
|
16454
|
+
const nl = slice.lastIndexOf(10);
|
|
16455
|
+
if (nl > budget / 2) slice = slice.subarray(0, nl);
|
|
16456
|
+
return slice.toString("utf8") + marker;
|
|
16457
|
+
}
|
|
16458
|
+
function capTokens(text, maxTokens) {
|
|
16459
|
+
const clean = stripAnsiCodes(text);
|
|
16460
|
+
if (clean.length / 3.5 <= maxTokens) return text;
|
|
16461
|
+
const maxBytes = Math.floor(maxTokens * 3.5);
|
|
16462
|
+
let truncated = capBytes(clean, maxBytes);
|
|
16463
|
+
if (!truncated.includes("[token-goat: output capped at")) {
|
|
16464
|
+
truncated = truncated.replace(BYTES_ELIDED_MARKER_RE, "");
|
|
16465
|
+
truncated += `
|
|
16466
|
+
[token-goat: output capped at ~${maxTokens} tokens]`;
|
|
16467
|
+
}
|
|
16468
|
+
return truncated;
|
|
16469
|
+
}
|
|
16470
|
+
function trimRepeatedPrefix(lines, pattern, keep) {
|
|
16471
|
+
const out2 = [];
|
|
16472
|
+
let matched = 0;
|
|
16473
|
+
let dropped = 0;
|
|
16474
|
+
for (const line of lines) {
|
|
16475
|
+
if (pattern.test(line)) {
|
|
16476
|
+
matched += 1;
|
|
16477
|
+
if (matched <= keep) out2.push(line);
|
|
16478
|
+
else dropped += 1;
|
|
16479
|
+
} else {
|
|
16480
|
+
out2.push(line);
|
|
15942
16481
|
}
|
|
15943
|
-
}
|
|
15944
|
-
|
|
16482
|
+
}
|
|
16483
|
+
if (dropped) out2.push(`[token-goat: +${dropped} more lines matching ${pattern.source}]`);
|
|
16484
|
+
return out2;
|
|
15945
16485
|
}
|
|
15946
|
-
function
|
|
15947
|
-
|
|
15948
|
-
return typeof cmd === "string" && cmd.trim() !== "" ? cmd.trim() : void 0;
|
|
16486
|
+
function maybeNote(notes, value, msg) {
|
|
16487
|
+
if (value) notes.push(msg);
|
|
15949
16488
|
}
|
|
15950
|
-
function
|
|
15951
|
-
|
|
15952
|
-
return /^\/tmp\//i.test(norm) || /\/var\/folders\//i.test(norm) || /AppData\/Local\/Temp\//i.test(norm) || norm.startsWith("/c/Users/") && norm.includes("/AppData/Local/Temp/");
|
|
16489
|
+
function squeezeBlankLines(text) {
|
|
16490
|
+
return text.replace(/\n\s*\n\s*\n+/g, "\n\n");
|
|
15953
16491
|
}
|
|
15954
|
-
function
|
|
15955
|
-
|
|
15956
|
-
|
|
16492
|
+
function preserveStderrOnError(stdout, stderr, exitCode) {
|
|
16493
|
+
if (exitCode !== 0 && stderr.trim()) {
|
|
16494
|
+
return stdout.trim() ? `${stdout.replace(/\s+$/, "")}
|
|
16495
|
+
---
|
|
16496
|
+
${stderr.replace(/\s+$/, "")}` : stderr;
|
|
16497
|
+
}
|
|
16498
|
+
return null;
|
|
15957
16499
|
}
|
|
15958
|
-
|
|
15959
|
-
|
|
15960
|
-
|
|
16500
|
+
var PASSTHROUGH_PREFIXES = /* @__PURE__ */ new Set([
|
|
16501
|
+
"sudo",
|
|
16502
|
+
"doas",
|
|
16503
|
+
"time",
|
|
16504
|
+
"nice",
|
|
16505
|
+
"ionice",
|
|
16506
|
+
"nohup",
|
|
16507
|
+
"exec",
|
|
16508
|
+
"env",
|
|
16509
|
+
"stdbuf",
|
|
16510
|
+
"unbuffer",
|
|
16511
|
+
"script"
|
|
16512
|
+
]);
|
|
16513
|
+
var TWO_TOKEN_PREFIXES = {
|
|
16514
|
+
python: /* @__PURE__ */ new Set(["-m"]),
|
|
16515
|
+
python3: /* @__PURE__ */ new Set(["-m"]),
|
|
16516
|
+
py: /* @__PURE__ */ new Set(["-m"]),
|
|
16517
|
+
uv: /* @__PURE__ */ new Set(["run", "tool"]),
|
|
16518
|
+
uvx: /* @__PURE__ */ new Set(),
|
|
16519
|
+
poetry: /* @__PURE__ */ new Set(["run"]),
|
|
16520
|
+
rye: /* @__PURE__ */ new Set(["run"]),
|
|
16521
|
+
pdm: /* @__PURE__ */ new Set(["run"]),
|
|
16522
|
+
pipenv: /* @__PURE__ */ new Set(["run"]),
|
|
16523
|
+
npx: /* @__PURE__ */ new Set(),
|
|
16524
|
+
pnpm: /* @__PURE__ */ new Set(["exec", "dlx"]),
|
|
16525
|
+
yarn: /* @__PURE__ */ new Set(["exec", "dlx"]),
|
|
16526
|
+
bundle: /* @__PURE__ */ new Set(["exec"]),
|
|
16527
|
+
tox: /* @__PURE__ */ new Set(["-e"]),
|
|
16528
|
+
hatch: /* @__PURE__ */ new Set(["run"])
|
|
16529
|
+
};
|
|
16530
|
+
function pathName(p) {
|
|
16531
|
+
const norm = p.replace(/\\/g, "/");
|
|
16532
|
+
const idx = norm.lastIndexOf("/");
|
|
16533
|
+
return idx >= 0 ? norm.slice(idx + 1) : norm;
|
|
16534
|
+
}
|
|
16535
|
+
function pathStem(p) {
|
|
16536
|
+
const name = pathName(p);
|
|
16537
|
+
const dot = name.lastIndexOf(".");
|
|
16538
|
+
return dot > 0 ? name.slice(0, dot) : name;
|
|
16539
|
+
}
|
|
16540
|
+
function positionalArgs(args) {
|
|
16541
|
+
return args.filter((a) => !a.startsWith("-"));
|
|
16542
|
+
}
|
|
16543
|
+
var SHORT_FLAGS_WITH_VALUE = /* @__PURE__ */ new Set(["-n", "-c", "-i", "-u", "-e"]);
|
|
16544
|
+
function stripPrefixes(argv) {
|
|
16545
|
+
if (argv.length === 0) return [];
|
|
16546
|
+
let out2 = [...argv];
|
|
16547
|
+
while (out2.length && out2[0].includes("=") && !out2[0].startsWith("-") && !out2[0].includes("/")) {
|
|
16548
|
+
const head = out2[0].split("=", 1)[0];
|
|
16549
|
+
if (head && (/[A-Za-z]/.test(head[0]) || head[0] === "_") && /^[A-Za-z0-9_]+$/.test(head)) out2.shift();
|
|
16550
|
+
else break;
|
|
16551
|
+
}
|
|
16552
|
+
while (out2.length) {
|
|
16553
|
+
if (!PASSTHROUGH_PREFIXES.has(pathStem(out2[0]).toLowerCase())) break;
|
|
16554
|
+
out2.shift();
|
|
16555
|
+
while (out2.length && out2[0].startsWith("-")) {
|
|
16556
|
+
const flag = out2.shift();
|
|
16557
|
+
if (SHORT_FLAGS_WITH_VALUE.has(flag) && out2.length) out2.shift();
|
|
16558
|
+
}
|
|
16559
|
+
}
|
|
16560
|
+
if (out2.length === 0) return out2;
|
|
16561
|
+
const stem = pathStem(out2[0]).toLowerCase();
|
|
16562
|
+
const triggers = TWO_TOKEN_PREFIXES[stem];
|
|
16563
|
+
if (triggers !== void 0 && out2.length >= 2) {
|
|
16564
|
+
const nextTok = out2[1];
|
|
16565
|
+
if (triggers.size === 0 || triggers.has(nextTok)) {
|
|
16566
|
+
const consume = triggers.size === 0 ? 1 : 2;
|
|
16567
|
+
if (out2.length > consume) out2 = out2.slice(consume);
|
|
16568
|
+
}
|
|
16569
|
+
}
|
|
16570
|
+
return out2;
|
|
15961
16571
|
}
|
|
15962
|
-
function
|
|
15963
|
-
const
|
|
15964
|
-
|
|
16572
|
+
function shlexSplit(cmd) {
|
|
16573
|
+
const tokens = [];
|
|
16574
|
+
let cur = "";
|
|
16575
|
+
let has = false;
|
|
16576
|
+
let i = 0;
|
|
16577
|
+
const n = cmd.length;
|
|
16578
|
+
while (i < n) {
|
|
16579
|
+
const ch = cmd[i];
|
|
16580
|
+
if (ch === " " || ch === " " || ch === "\n" || ch === "\r") {
|
|
16581
|
+
if (has) {
|
|
16582
|
+
tokens.push(cur);
|
|
16583
|
+
cur = "";
|
|
16584
|
+
has = false;
|
|
16585
|
+
}
|
|
16586
|
+
i += 1;
|
|
16587
|
+
continue;
|
|
16588
|
+
}
|
|
16589
|
+
has = true;
|
|
16590
|
+
if (ch === "\\") {
|
|
16591
|
+
if (i + 1 < n) {
|
|
16592
|
+
cur += cmd[i + 1];
|
|
16593
|
+
i += 2;
|
|
16594
|
+
} else {
|
|
16595
|
+
i += 1;
|
|
16596
|
+
}
|
|
16597
|
+
continue;
|
|
16598
|
+
}
|
|
16599
|
+
if (ch === "'") {
|
|
16600
|
+
i += 1;
|
|
16601
|
+
const end = cmd.indexOf("'", i);
|
|
16602
|
+
if (end === -1) throw new Error("No closing quotation");
|
|
16603
|
+
cur += cmd.slice(i, end);
|
|
16604
|
+
i = end + 1;
|
|
16605
|
+
continue;
|
|
16606
|
+
}
|
|
16607
|
+
if (ch === '"') {
|
|
16608
|
+
i += 1;
|
|
16609
|
+
let buf = "";
|
|
16610
|
+
while (i < n && cmd[i] !== '"') {
|
|
16611
|
+
if (cmd[i] === "\\" && i + 1 < n && (cmd[i + 1] === '"' || cmd[i + 1] === "\\")) {
|
|
16612
|
+
buf += cmd[i + 1];
|
|
16613
|
+
i += 2;
|
|
16614
|
+
} else {
|
|
16615
|
+
buf += cmd[i];
|
|
16616
|
+
i += 1;
|
|
16617
|
+
}
|
|
16618
|
+
}
|
|
16619
|
+
if (i >= n) throw new Error("No closing quotation");
|
|
16620
|
+
cur += buf;
|
|
16621
|
+
i += 1;
|
|
16622
|
+
continue;
|
|
16623
|
+
}
|
|
16624
|
+
cur += ch;
|
|
16625
|
+
i += 1;
|
|
16626
|
+
}
|
|
16627
|
+
if (has) tokens.push(cur);
|
|
16628
|
+
return tokens;
|
|
16629
|
+
}
|
|
16630
|
+
function capLongLines(lines, maxChars = FALLBACK_MAX_LINE_CHARS) {
|
|
16631
|
+
return lines.map(
|
|
16632
|
+
(line) => line.length > maxChars ? `${line.slice(0, maxChars)} \u2026 [${line.length - maxChars} chars elided]` : line
|
|
16633
|
+
);
|
|
16634
|
+
}
|
|
16635
|
+
function fallbackTruncate(stdout, stderr, maxLines) {
|
|
16636
|
+
const half = Math.floor(maxLines / 2);
|
|
16637
|
+
const outLines = truncateMiddle(capLongLines(dedupeConsecutive(stdout.split("\n"))), half);
|
|
16638
|
+
const errLines = truncateMiddle(capLongLines(dedupeConsecutive(stderr.split("\n"))), half);
|
|
16639
|
+
if (stderr) return `${outLines.join("\n")}
|
|
16640
|
+
---
|
|
16641
|
+
${errLines.join("\n")}`;
|
|
16642
|
+
return outLines.join("\n");
|
|
16643
|
+
}
|
|
16644
|
+
function compressBashOutput(stdout, stderr) {
|
|
16645
|
+
let body = dedupeConsecutive(stdout.split("\n"), { entropyBypass: true }).join("\n");
|
|
16646
|
+
if (stderr.trim()) {
|
|
16647
|
+
const err2 = dedupeConsecutive(stderr.split("\n"), { entropyBypass: true }).join("\n");
|
|
16648
|
+
body = `${body.replace(/\s+$/, "")}
|
|
16649
|
+
---
|
|
16650
|
+
${err2.replace(/\s+$/, "")}`;
|
|
16651
|
+
}
|
|
16652
|
+
return body;
|
|
16653
|
+
}
|
|
16654
|
+
function byteLength(s) {
|
|
16655
|
+
return utf8Len(s);
|
|
16656
|
+
}
|
|
16657
|
+
|
|
16658
|
+
// src/tool_filters/base.ts
|
|
16659
|
+
init_define_import_meta_env();
|
|
16660
|
+
var CompressedOutput = class {
|
|
16661
|
+
constructor(text, originalBytes, compressedBytes, filterName, exitCode = 0, notes = []) {
|
|
16662
|
+
this.text = text;
|
|
16663
|
+
this.originalBytes = originalBytes;
|
|
16664
|
+
this.compressedBytes = compressedBytes;
|
|
16665
|
+
this.filterName = filterName;
|
|
16666
|
+
this.exitCode = exitCode;
|
|
16667
|
+
this.notes = notes;
|
|
16668
|
+
}
|
|
16669
|
+
/** Non-negative byte savings (`original - compressed`, clamped at 0). */
|
|
16670
|
+
get bytesSaved() {
|
|
16671
|
+
return Math.max(0, this.originalBytes - this.compressedBytes);
|
|
16672
|
+
}
|
|
16673
|
+
/** Estimated token savings (`n // 3 + 1`, matching `estimateTokens`). */
|
|
16674
|
+
get tokensSaved() {
|
|
16675
|
+
const n = this.bytesSaved;
|
|
16676
|
+
return n <= 0 ? 0 : Math.max(1, Math.floor(n / 3) + 1);
|
|
16677
|
+
}
|
|
16678
|
+
/** Reduction as a percentage of the original size (0 when no input). */
|
|
16679
|
+
get percentSaved() {
|
|
16680
|
+
if (this.originalBytes <= 0) return 0;
|
|
16681
|
+
return 100 * this.bytesSaved / this.originalBytes;
|
|
16682
|
+
}
|
|
16683
|
+
/**
|
|
16684
|
+
* `text` with the trailing compression-summary marker appended. Skipped
|
|
16685
|
+
* entirely on a no-op (savings ≤ 0) so raw output never carries a marker.
|
|
16686
|
+
*/
|
|
16687
|
+
withMarker() {
|
|
16688
|
+
if (this.bytesSaved <= 0 || this.originalBytes <= 0) return this.text;
|
|
16689
|
+
return this.text + compressionMarker(this.filterName, this.percentSaved);
|
|
16690
|
+
}
|
|
16691
|
+
};
|
|
16692
|
+
var ToolFilter = class {
|
|
16693
|
+
/** Command basenames this filter handles (lowercased stems). */
|
|
16694
|
+
binaries = /* @__PURE__ */ new Set();
|
|
16695
|
+
/** Optional subcommand gate; matched against the first 3 positional args. */
|
|
16696
|
+
subcommands = /* @__PURE__ */ new Set();
|
|
16697
|
+
/** When true, pass raw error output through on non-zero exit. */
|
|
16698
|
+
errorPassthrough = false;
|
|
16699
|
+
/** Detect whether this filter applies to the raw command string. */
|
|
16700
|
+
detectFromCommand(cmd) {
|
|
16701
|
+
try {
|
|
16702
|
+
if (!cmd || cmd.length > 65536) return false;
|
|
16703
|
+
const resolved = stripPrefixes(shlexSplit(cmd));
|
|
16704
|
+
if (resolved.length === 0) return false;
|
|
16705
|
+
return this.matches(resolved);
|
|
16706
|
+
} catch {
|
|
16707
|
+
return false;
|
|
16708
|
+
}
|
|
16709
|
+
}
|
|
16710
|
+
/**
|
|
16711
|
+
* Return true when this filter should run for `argv`. Checks `binaries`
|
|
16712
|
+
* against the lowercased stem (and full name, for dot-in-name binaries like
|
|
16713
|
+
* `py.test`) of `argv[0]`; when `subcommands` is non-empty, requires one in
|
|
16714
|
+
* the first three positional args.
|
|
16715
|
+
*/
|
|
16716
|
+
matches(argv) {
|
|
16717
|
+
if (argv.length === 0) return false;
|
|
16718
|
+
const first = argv[0];
|
|
16719
|
+
const stem = pathStem(first).toLowerCase();
|
|
16720
|
+
const name = pathName(first).toLowerCase();
|
|
16721
|
+
if (!this.binaries.has(stem) && !this.binaries.has(name)) return false;
|
|
16722
|
+
if (this.subcommands.size === 0) return true;
|
|
16723
|
+
return positionalArgs(argv.slice(1)).slice(0, 3).some((tok) => this.subcommands.has(tok));
|
|
16724
|
+
}
|
|
16725
|
+
/** Combine stdout/stderr with a `---` separator when both are present. */
|
|
16726
|
+
combineOutput(stdout, stderr) {
|
|
16727
|
+
if (stderr.trim() && stdout.trim()) return `${stdout.replace(/\s+$/, "")}
|
|
16728
|
+
---
|
|
16729
|
+
${stderr.replace(/\s+$/, "")}`;
|
|
16730
|
+
return stdout.trim() ? stdout.replace(/\s+$/, "") : stderr.replace(/\s+$/, "");
|
|
16731
|
+
}
|
|
16732
|
+
/** Append a `[token-goat: <joined notes>]` summary line to `kept`. */
|
|
16733
|
+
emitNotes(kept, notes, prefix = "token-goat: ") {
|
|
16734
|
+
if (notes.length) kept.push(`[${prefix}${notes.join("; ")}]`);
|
|
16735
|
+
}
|
|
16736
|
+
/** Join `kept` with newlines and squeeze runs of blank lines. */
|
|
16737
|
+
finalize(kept) {
|
|
16738
|
+
return squeezeBlankLines(kept.join("\n"));
|
|
16739
|
+
}
|
|
16740
|
+
/**
|
|
16741
|
+
* Hook applied to each stream right after {@link normalise}. Identity by
|
|
16742
|
+
* default; the git filter family overrides it to strip CRLF warnings. Keeps
|
|
16743
|
+
* `apply` free of per-family name checks.
|
|
16744
|
+
*/
|
|
16745
|
+
postNormalise(text) {
|
|
16746
|
+
return text;
|
|
16747
|
+
}
|
|
16748
|
+
/**
|
|
16749
|
+
* Template: when {@link errorPassthrough} is set, return the raw combined
|
|
16750
|
+
* error output on non-zero exit before delegating to {@link compressBody}.
|
|
16751
|
+
* Filters that handle errors structurally (pytest, cargo) override this
|
|
16752
|
+
* directly and leave `errorPassthrough` false.
|
|
16753
|
+
*/
|
|
16754
|
+
compress(stdout, stderr, exitCode, argv) {
|
|
16755
|
+
if (this.errorPassthrough) {
|
|
16756
|
+
const err2 = preserveStderrOnError(stdout, stderr, exitCode);
|
|
16757
|
+
if (err2 !== null) return err2;
|
|
16758
|
+
}
|
|
16759
|
+
return this.compressBody(stdout, stderr, exitCode, argv);
|
|
16760
|
+
}
|
|
16761
|
+
/**
|
|
16762
|
+
* Inner compression logic, called after the error-passthrough guard.
|
|
16763
|
+
* Default is a passthrough that joins the two streams — useful when the only
|
|
16764
|
+
* compression is the ANSI / progress strip `apply` already performed.
|
|
16765
|
+
*/
|
|
16766
|
+
compressBody(stdout, stderr, _exitCode, _argv) {
|
|
16767
|
+
if (stderr && stdout) return `${stdout.replace(/\s+$/, "")}
|
|
16768
|
+
---
|
|
16769
|
+
${stderr.replace(/\s+$/, "")}`;
|
|
16770
|
+
return stdout || stderr;
|
|
16771
|
+
}
|
|
16772
|
+
/**
|
|
16773
|
+
* Top-level entry: sanitise → input cap → normalise → compress → line/byte
|
|
16774
|
+
* cap → wrap in {@link CompressedOutput}. Faithful port of the Python
|
|
16775
|
+
* `apply` 10-step pipeline. Errors from {@link compress} fall back to a
|
|
16776
|
+
* truncated view so the agent always sees something.
|
|
16777
|
+
*/
|
|
16778
|
+
apply(stdout, stderr, exitCode, argv, opts = {}) {
|
|
16779
|
+
const maxLines = opts.maxLines ?? DEFAULT_MAX_LINES;
|
|
16780
|
+
const maxBytes = opts.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
16781
|
+
const skipProgress = opts.skipProgress ?? false;
|
|
16782
|
+
let so = safeDecode(stdout);
|
|
16783
|
+
let se = safeDecode(stderr);
|
|
16784
|
+
const maxInput = getMaxInputBytes();
|
|
16785
|
+
const notes = [];
|
|
16786
|
+
const soBytes = Buffer.from(so, "utf8");
|
|
16787
|
+
const seBytes = Buffer.from(se, "utf8");
|
|
16788
|
+
if (soBytes.length > maxInput) {
|
|
16789
|
+
so = soBytes.subarray(0, maxInput).toString("utf8");
|
|
16790
|
+
notes.push(`input truncated at ${Math.floor(maxInput / 1024)}KB (TOKEN_GOAT_FILTER_MAX_BYTES)`);
|
|
16791
|
+
}
|
|
16792
|
+
if (seBytes.length > maxInput) {
|
|
16793
|
+
se = seBytes.subarray(0, maxInput).toString("utf8");
|
|
16794
|
+
if (!notes.some((n) => n.includes("input truncated"))) {
|
|
16795
|
+
notes.push(`stderr truncated at ${Math.floor(maxInput / 1024)}KB (TOKEN_GOAT_FILTER_MAX_BYTES)`);
|
|
16796
|
+
}
|
|
16797
|
+
}
|
|
16798
|
+
const originalBytes = soBytes.length + seBytes.length;
|
|
16799
|
+
if (!so.trim() && !se.trim()) {
|
|
16800
|
+
const text = notes.length ? `[${notes.join("; ")}]
|
|
16801
|
+
` : "";
|
|
16802
|
+
return new CompressedOutput(text, originalBytes, byteLength(text), this.name, exitCode, notes);
|
|
16803
|
+
}
|
|
16804
|
+
let body;
|
|
16805
|
+
try {
|
|
16806
|
+
const normOut = this.postNormalise(normalise(so, { skipProgress }));
|
|
16807
|
+
const normErr = this.postNormalise(normalise(se, { skipProgress }));
|
|
16808
|
+
const normBytes = byteLength(normOut) + byteLength(normErr);
|
|
16809
|
+
if (originalBytes > 0 && normBytes <= originalBytes * 0.6) {
|
|
16810
|
+
body = compressBashOutput(normOut, normErr);
|
|
16811
|
+
notes.push("early-exit: normalisation alone sufficient");
|
|
16812
|
+
} else if (normBytes > MAX_INSPECT_BYTES) {
|
|
16813
|
+
notes.push(`input exceeded inspect budget (${Math.floor(MAX_INSPECT_BYTES / 1024)} KiB); fell back to truncation`);
|
|
16814
|
+
body = fallbackTruncate(normOut, normErr, maxLines);
|
|
16815
|
+
} else {
|
|
16816
|
+
body = this.compress(normOut, normErr, exitCode, argv);
|
|
16817
|
+
}
|
|
16818
|
+
} catch (exc) {
|
|
16819
|
+
const kind = exc instanceof Error ? exc.constructor.name : "Error";
|
|
16820
|
+
notes.push(`${this.name} filter raised ${kind}; truncated raw`);
|
|
16821
|
+
const fbOut = this.postNormalise(normalise(so, { skipProgress }));
|
|
16822
|
+
const fbErr = this.postNormalise(normalise(se, { skipProgress }));
|
|
16823
|
+
body = fallbackTruncate(fbOut, fbErr, maxLines);
|
|
16824
|
+
}
|
|
16825
|
+
const lines = body.split("\n");
|
|
16826
|
+
if (lines.length > maxLines) body = truncateMiddleSmart(lines, maxLines).join("\n");
|
|
16827
|
+
body = capBytes(body, maxBytes);
|
|
16828
|
+
if (notes.length) body = `[${notes.join("; ")}]
|
|
16829
|
+
${body}`;
|
|
16830
|
+
return new CompressedOutput(body, originalBytes, byteLength(body), this.name, exitCode, notes);
|
|
16831
|
+
}
|
|
16832
|
+
};
|
|
16833
|
+
|
|
16834
|
+
// src/tool_filters/generic.ts
|
|
16835
|
+
init_define_import_meta_env();
|
|
16836
|
+
var GenericFilter = class extends ToolFilter {
|
|
16837
|
+
name = "generic";
|
|
16838
|
+
compress(stdout, stderr, _exitCode, _argv) {
|
|
16839
|
+
const outLines = dedupeConsecutive(stdout.split("\n"), { entropyBypass: true });
|
|
16840
|
+
const errLines = dedupeConsecutive(stderr.split("\n"), { entropyBypass: true });
|
|
16841
|
+
let result;
|
|
16842
|
+
if (stderr.trim()) {
|
|
16843
|
+
const outPart = outLines.join("\n").replace(/\s+$/, "");
|
|
16844
|
+
const errPart = errLines.join("\n").replace(/\s+$/, "");
|
|
16845
|
+
result = outPart ? `${outPart}
|
|
16846
|
+
---
|
|
16847
|
+
${errPart}` : errPart;
|
|
16848
|
+
} else {
|
|
16849
|
+
result = outLines.join("\n");
|
|
16850
|
+
}
|
|
16851
|
+
return capTokens(result, 2e3);
|
|
16852
|
+
}
|
|
16853
|
+
};
|
|
16854
|
+
|
|
16855
|
+
// src/tool_filters/families.ts
|
|
16856
|
+
init_define_import_meta_env();
|
|
16857
|
+
function plural(n, suffix = "s") {
|
|
16858
|
+
return n === 1 ? "" : suffix;
|
|
16859
|
+
}
|
|
16860
|
+
function makeNodeTestRunnerFilter(cfg) {
|
|
16861
|
+
return new class extends ToolFilter {
|
|
16862
|
+
name = cfg.name;
|
|
16863
|
+
binaries = new Set(cfg.binaries);
|
|
16864
|
+
compress(stdout, stderr, _exitCode, _argv) {
|
|
16865
|
+
const merged = this.combineOutput(stdout, stderr);
|
|
16866
|
+
const lines = merged.split("\n");
|
|
16867
|
+
const kept = [];
|
|
16868
|
+
let passFile = 0;
|
|
16869
|
+
let tick = 0;
|
|
16870
|
+
let inFail = false;
|
|
16871
|
+
let blockLines = 0;
|
|
16872
|
+
let inBlock = false;
|
|
16873
|
+
let inFailuresSection = false;
|
|
16874
|
+
let failuresDropped = 0;
|
|
16875
|
+
const flush = () => {
|
|
16876
|
+
if (blockLines) {
|
|
16877
|
+
kept.push(` [token-goat: collapsed ${blockLines} ${cfg.outputNoun} line${plural(blockLines)}]`);
|
|
16878
|
+
}
|
|
16879
|
+
blockLines = 0;
|
|
16880
|
+
inBlock = false;
|
|
16881
|
+
};
|
|
16882
|
+
for (const line of lines) {
|
|
16883
|
+
if (cfg.failuresSection) {
|
|
16884
|
+
if (line.trim() === "Failures:") {
|
|
16885
|
+
flush();
|
|
16886
|
+
inFail = false;
|
|
16887
|
+
inFailuresSection = true;
|
|
16888
|
+
failuresDropped += 1;
|
|
16889
|
+
continue;
|
|
16890
|
+
}
|
|
16891
|
+
if (inFailuresSection) {
|
|
16892
|
+
if (cfg.summaryRe.test(line)) {
|
|
16893
|
+
inFailuresSection = false;
|
|
16894
|
+
kept.push(line);
|
|
16895
|
+
} else {
|
|
16896
|
+
failuresDropped += 1;
|
|
16897
|
+
}
|
|
16898
|
+
continue;
|
|
16899
|
+
}
|
|
16900
|
+
}
|
|
16901
|
+
if (cfg.passFileRe.test(line) && !inFail) {
|
|
16902
|
+
flush();
|
|
16903
|
+
passFile += 1;
|
|
16904
|
+
continue;
|
|
16905
|
+
}
|
|
16906
|
+
if (cfg.failFileRe.test(line)) {
|
|
16907
|
+
flush();
|
|
16908
|
+
inFail = true;
|
|
16909
|
+
kept.push(line);
|
|
16910
|
+
continue;
|
|
16911
|
+
}
|
|
16912
|
+
if (cfg.summaryRe.test(line)) {
|
|
16913
|
+
flush();
|
|
16914
|
+
kept.push(line);
|
|
16915
|
+
continue;
|
|
16916
|
+
}
|
|
16917
|
+
if (!line.trim() && inFail) {
|
|
16918
|
+
inFail = false;
|
|
16919
|
+
kept.push(line);
|
|
16920
|
+
continue;
|
|
16921
|
+
}
|
|
16922
|
+
if (inFail) {
|
|
16923
|
+
kept.push(line);
|
|
16924
|
+
continue;
|
|
16925
|
+
}
|
|
16926
|
+
if (cfg.outputHdrRe.test(line)) {
|
|
16927
|
+
flush();
|
|
16928
|
+
inBlock = true;
|
|
16929
|
+
blockLines = 1;
|
|
16930
|
+
continue;
|
|
16931
|
+
}
|
|
16932
|
+
if (inBlock) {
|
|
16933
|
+
const stripped = line.trim();
|
|
16934
|
+
if (!stripped || line.length > 0 && !/^\s/.test(line)) {
|
|
16935
|
+
flush();
|
|
16936
|
+
} else {
|
|
16937
|
+
blockLines += 1;
|
|
16938
|
+
continue;
|
|
16939
|
+
}
|
|
16940
|
+
}
|
|
16941
|
+
if (cfg.testTickRe.test(line)) {
|
|
16942
|
+
tick += 1;
|
|
16943
|
+
continue;
|
|
16944
|
+
}
|
|
16945
|
+
kept.push(line);
|
|
16946
|
+
}
|
|
16947
|
+
flush();
|
|
16948
|
+
const notes = [];
|
|
16949
|
+
maybeNote(notes, passFile, `collapsed ${passFile} ${cfg.passFileNoun}${plural(passFile)}`);
|
|
16950
|
+
maybeNote(notes, tick, `collapsed ${tick} passing tick${plural(tick)}`);
|
|
16951
|
+
if (failuresDropped) {
|
|
16952
|
+
notes.push(
|
|
16953
|
+
`collapsed ${failuresDropped} line${plural(failuresDropped)} from duplicate 'Failures:' section (already shown inline)`
|
|
16954
|
+
);
|
|
16955
|
+
}
|
|
16956
|
+
this.emitNotes(kept, notes);
|
|
16957
|
+
return this.finalize(kept);
|
|
16958
|
+
}
|
|
16959
|
+
}();
|
|
16960
|
+
}
|
|
16961
|
+
|
|
16962
|
+
// src/tool_filters/test_runners.ts
|
|
16963
|
+
init_define_import_meta_env();
|
|
16964
|
+
var jestFilter = makeNodeTestRunnerFilter({
|
|
16965
|
+
name: "jest",
|
|
16966
|
+
binaries: ["jest", "mocha", "ava", "tap"],
|
|
16967
|
+
// File-level PASS header: `PASS src/foo.test.js`, or a bare `✓ file` at col 0.
|
|
16968
|
+
passFileRe: /^(?:\s*PASS\s+\S|[✓√]\s+\S)/,
|
|
16969
|
+
failFileRe: /^\s*(?:FAIL|✗|×|✘)\s+\S/,
|
|
16970
|
+
summaryRe: /^(Test Suites|Tests|Snapshots|Time|Ran all test suites):/,
|
|
16971
|
+
// Per-test tick: any ✓/√ line not already claimed as a file header above.
|
|
16972
|
+
testTickRe: /^\s*[✓√]/,
|
|
16973
|
+
outputHdrRe: /^\s*console\.(log|error|warn|info|debug)\s/,
|
|
16974
|
+
outputNoun: "console output",
|
|
16975
|
+
passFileNoun: "PASS file",
|
|
16976
|
+
failuresSection: true
|
|
16977
|
+
});
|
|
16978
|
+
var vitestFilter = makeNodeTestRunnerFilter({
|
|
16979
|
+
name: "vitest",
|
|
16980
|
+
binaries: ["vitest"],
|
|
16981
|
+
// File-level pass header carries a duration: `✓ src/x.test.ts (12ms)`.
|
|
16982
|
+
passFileRe: /^\s*✓\s+\S.*\([\d.]+\s*\w+\)/,
|
|
16983
|
+
failFileRe: /^\s*(?:×|FAIL|✗|✘)\s+\S/,
|
|
16984
|
+
summaryRe: /^(Test Files|Tests|Modules|Duration|Start at)[\s:]+\d/,
|
|
16985
|
+
// Per-test tick is indented ≥2 spaces: ` ✓ should pass`.
|
|
16986
|
+
testTickRe: /^\s{2,}✓\s/,
|
|
16987
|
+
outputHdrRe: /^\s*stdout\s*\|/,
|
|
16988
|
+
outputNoun: "stdout",
|
|
16989
|
+
passFileNoun: "passing file"
|
|
16990
|
+
});
|
|
16991
|
+
var TEST_RUNNER_FILTERS = [jestFilter, vitestFilter];
|
|
16992
|
+
|
|
16993
|
+
// src/tool_filters/pytest.ts
|
|
16994
|
+
init_define_import_meta_env();
|
|
16995
|
+
var XDIST_PREFIX_RE = /^\[gw\d+\]\s*(?:\[\s*\d+%\]\s*)?/;
|
|
16996
|
+
var DOTS_RE = /^[.FxXEsS]+\s*(\[\s*\d+%\])?\s*$/;
|
|
16997
|
+
var BANNER_RE = /^(?:platform\s|cachedir:\s|rootdir:\s|plugins:\s|configfile:\s|bringing up\s|cacheprovider-)/;
|
|
16998
|
+
var PREAMBLE_RE = /^collecting\s/;
|
|
16999
|
+
var HEADER_RE2 = /^=+\s*(?:test session starts|FAILURES|ERRORS|short test summary info|warnings summary|slowest \d+ durations|\d+ failed|\d+ passed|\d+ error)\b/;
|
|
17000
|
+
var COV_TOTAL_RE = /^TOTAL\s+\d/;
|
|
17001
|
+
var WARN_DOCS_RE = /^\s*--\s+Docs:\s+https?:\/\//;
|
|
17002
|
+
var WARN_MSG_RE = /^\s+\S.*:\d+:\s+\S.*Warning\b/;
|
|
17003
|
+
var SLOW_DURATION_RE = /^\d+\.\d+s\s+(?:call|setup|teardown)\s+\S/;
|
|
17004
|
+
var FAIL_LINE_RE = /^(FAILED|ERROR|PASSED|SKIPPED|XFAIL|XPASS)\s+\S/;
|
|
17005
|
+
var VERBOSE_LINE_RE = /^\S.+::\S+[ \t]+(PASSED|FAILED|ERROR|SKIPPED|XFAIL|XPASS)(?:[ \t]|$)/;
|
|
17006
|
+
var COLLECT_RE = /^collected \d+ items?/;
|
|
17007
|
+
var COV_SEP_RE = /^[-=]+\s*$/;
|
|
17008
|
+
var COV_ROW_RE = /^\S.*\s+\d+\s+\d+\s+\d+%?\s*$/;
|
|
17009
|
+
var MAX_SLOW_KEPT = 5;
|
|
17010
|
+
var PytestFilter = class extends ToolFilter {
|
|
17011
|
+
name = "pytest";
|
|
17012
|
+
binaries = /* @__PURE__ */ new Set(["pytest", "py.test"]);
|
|
17013
|
+
compress(stdout, stderr, _exitCode, _argv) {
|
|
17014
|
+
const text = this.combineOutput(stdout, stderr);
|
|
17015
|
+
const lines = text.split("\n");
|
|
17016
|
+
let kept = [];
|
|
17017
|
+
let passedCount = 0;
|
|
17018
|
+
let inFailures = false;
|
|
17019
|
+
let inErrors = false;
|
|
17020
|
+
let inSlowSection = false;
|
|
17021
|
+
let inWarningsSection = false;
|
|
17022
|
+
let slowKept = 0;
|
|
17023
|
+
let slowDropped = 0;
|
|
17024
|
+
let inCovTable = false;
|
|
17025
|
+
let covTableRowsDropped = 0;
|
|
17026
|
+
const warnMsgSeen = /* @__PURE__ */ new Map();
|
|
17027
|
+
let warningsDropped = 0;
|
|
17028
|
+
for (let line of lines) {
|
|
17029
|
+
if (XDIST_PREFIX_RE.test(line)) line = line.replace(XDIST_PREFIX_RE, "");
|
|
17030
|
+
if (DOTS_RE.test(line)) continue;
|
|
17031
|
+
if (BANNER_RE.test(line)) continue;
|
|
17032
|
+
if (PREAMBLE_RE.test(line)) continue;
|
|
17033
|
+
if (HEADER_RE2.test(line)) {
|
|
17034
|
+
inFailures = line.includes("FAILURES");
|
|
17035
|
+
inErrors = line.includes("ERRORS") || line.includes("short test summary");
|
|
17036
|
+
inSlowSection = line.includes("slowest") && line.includes("durations");
|
|
17037
|
+
inWarningsSection = line.includes("warnings summary");
|
|
17038
|
+
inCovTable = false;
|
|
17039
|
+
if (line.includes("test session starts")) continue;
|
|
17040
|
+
kept.push(line);
|
|
17041
|
+
continue;
|
|
17042
|
+
}
|
|
17043
|
+
if (line.startsWith("Name") && line.includes("Stmts") && line.includes("Miss")) {
|
|
17044
|
+
inCovTable = true;
|
|
17045
|
+
kept.push(line);
|
|
17046
|
+
continue;
|
|
17047
|
+
}
|
|
17048
|
+
if (inCovTable) {
|
|
17049
|
+
if (COV_TOTAL_RE.test(line)) {
|
|
17050
|
+
if (covTableRowsDropped) {
|
|
17051
|
+
kept.push(`[token-goat: collapsed ${covTableRowsDropped} coverage table rows]`);
|
|
17052
|
+
covTableRowsDropped = 0;
|
|
17053
|
+
}
|
|
17054
|
+
kept.push(line);
|
|
17055
|
+
inCovTable = false;
|
|
17056
|
+
continue;
|
|
17057
|
+
}
|
|
17058
|
+
if (COV_SEP_RE.test(line)) {
|
|
17059
|
+
kept.push(line);
|
|
17060
|
+
continue;
|
|
17061
|
+
}
|
|
17062
|
+
if (COV_ROW_RE.test(line)) {
|
|
17063
|
+
covTableRowsDropped += 1;
|
|
17064
|
+
continue;
|
|
17065
|
+
}
|
|
17066
|
+
inCovTable = false;
|
|
17067
|
+
}
|
|
17068
|
+
if (inWarningsSection) {
|
|
17069
|
+
if (WARN_DOCS_RE.test(line)) {
|
|
17070
|
+
warningsDropped += 1;
|
|
17071
|
+
continue;
|
|
17072
|
+
}
|
|
17073
|
+
if (WARN_MSG_RE.test(line)) {
|
|
17074
|
+
const colonIdx = line.lastIndexOf("Warning");
|
|
17075
|
+
const normKey = colonIdx >= 0 ? line.slice(colonIdx).trim() : line.trim();
|
|
17076
|
+
const count = warnMsgSeen.get(normKey) ?? 0;
|
|
17077
|
+
warnMsgSeen.set(normKey, count + 1);
|
|
17078
|
+
if (count === 0) kept.push(line);
|
|
17079
|
+
else warningsDropped += 1;
|
|
17080
|
+
continue;
|
|
17081
|
+
}
|
|
17082
|
+
}
|
|
17083
|
+
if (inSlowSection) {
|
|
17084
|
+
if (SLOW_DURATION_RE.test(line)) {
|
|
17085
|
+
if (slowKept < MAX_SLOW_KEPT) {
|
|
17086
|
+
kept.push(line);
|
|
17087
|
+
slowKept += 1;
|
|
17088
|
+
} else {
|
|
17089
|
+
slowDropped += 1;
|
|
17090
|
+
}
|
|
17091
|
+
continue;
|
|
17092
|
+
}
|
|
17093
|
+
if (!line.trim() || HEADER_RE2.test(line)) {
|
|
17094
|
+
if (slowDropped) {
|
|
17095
|
+
kept.push(`[token-goat: collapsed ${slowDropped} slow-test duration lines]`);
|
|
17096
|
+
slowDropped = 0;
|
|
17097
|
+
}
|
|
17098
|
+
inSlowSection = false;
|
|
17099
|
+
if (!line.trim()) continue;
|
|
17100
|
+
if (HEADER_RE2.test(line)) {
|
|
17101
|
+
inFailures = line.includes("FAILURES");
|
|
17102
|
+
inErrors = line.includes("ERRORS") || line.includes("short test summary");
|
|
17103
|
+
inWarningsSection = line.includes("warnings summary");
|
|
17104
|
+
kept.push(line);
|
|
17105
|
+
continue;
|
|
17106
|
+
}
|
|
17107
|
+
} else {
|
|
17108
|
+
kept.push(line);
|
|
17109
|
+
continue;
|
|
17110
|
+
}
|
|
17111
|
+
}
|
|
17112
|
+
if (!inFailures && !inErrors && FAIL_LINE_RE.test(line)) {
|
|
17113
|
+
const tag = line.split(/\s+/, 1)[0];
|
|
17114
|
+
if (tag === "PASSED") {
|
|
17115
|
+
passedCount += 1;
|
|
17116
|
+
continue;
|
|
17117
|
+
}
|
|
17118
|
+
kept.push(line);
|
|
17119
|
+
continue;
|
|
17120
|
+
}
|
|
17121
|
+
if (!inFailures && !inErrors) {
|
|
17122
|
+
const m = VERBOSE_LINE_RE.exec(line);
|
|
17123
|
+
if (m) {
|
|
17124
|
+
if (m[1] === "PASSED") {
|
|
17125
|
+
passedCount += 1;
|
|
17126
|
+
continue;
|
|
17127
|
+
}
|
|
17128
|
+
kept.push(line);
|
|
17129
|
+
continue;
|
|
17130
|
+
}
|
|
17131
|
+
}
|
|
17132
|
+
kept.push(line);
|
|
17133
|
+
}
|
|
17134
|
+
if (slowDropped) kept.push(`[token-goat: collapsed ${slowDropped} slow-test duration lines]`);
|
|
17135
|
+
if (covTableRowsDropped)
|
|
17136
|
+
kept.push(`[token-goat: collapsed ${covTableRowsDropped} coverage table rows]`);
|
|
17137
|
+
kept = trimRepeatedPrefix(kept, COLLECT_RE, 3);
|
|
17138
|
+
if (passedCount) kept.push(`[token-goat: collapsed ${passedCount} PASSED lines]`);
|
|
17139
|
+
if (warningsDropped)
|
|
17140
|
+
kept.push(`[token-goat: collapsed ${warningsDropped} duplicate/docs warning lines]`);
|
|
17141
|
+
return this.finalize(kept);
|
|
17142
|
+
}
|
|
17143
|
+
};
|
|
17144
|
+
var pytestFilter = new PytestFilter();
|
|
17145
|
+
|
|
17146
|
+
// src/tool_filters/go_test.ts
|
|
17147
|
+
init_define_import_meta_env();
|
|
17148
|
+
var TEST_RUN_RE = /^=== (RUN|PAUSE|CONT|NAME)\s/;
|
|
17149
|
+
var RACE_FENCE_RE = /^={10,}\s*$/;
|
|
17150
|
+
var RACE_WARNING_RE = /^WARNING: DATA RACE/;
|
|
17151
|
+
var TEST_PASS_RE = /^\s*--- PASS:\s/;
|
|
17152
|
+
var TEST_FAIL_RE = /^\s*--- FAIL:\s/;
|
|
17153
|
+
var TEST_RPC_RE = /^=== (RUN|PAUSE|CONT)\s/;
|
|
17154
|
+
var SKIP_RE = /^\s*--- SKIP:\s/;
|
|
17155
|
+
var GOROUTINE_HEADER_RE = /^(?:Goroutine \d+|Previous|Current)\s/;
|
|
17156
|
+
var OK_PKG_RE = /^ok\s+\S+\s+\d/;
|
|
17157
|
+
var FAIL_PKG_RE = /^FAIL\t\S+/;
|
|
17158
|
+
var MAX_RACE_GOROUTINE_FRAMES = 5;
|
|
17159
|
+
var GoTestFilter = class extends ToolFilter {
|
|
17160
|
+
name = "go-test";
|
|
17161
|
+
binaries = /* @__PURE__ */ new Set(["go"]);
|
|
17162
|
+
// Fire only for `go test` (test as the FIRST positional), not `go build`/`run`.
|
|
17163
|
+
matches(argv) {
|
|
17164
|
+
if (argv.length === 0) return false;
|
|
17165
|
+
const stem = argv[0].replace(/\\/g, "/").split("/").pop().toLowerCase().replace(/\.exe$/, "");
|
|
17166
|
+
if (stem !== "go") return false;
|
|
17167
|
+
return positionalArgs(argv.slice(1)).slice(0, 1)[0] === "test";
|
|
17168
|
+
}
|
|
17169
|
+
compress(stdout, stderr, _exitCode, argv) {
|
|
17170
|
+
if (argv.includes("-json")) return this.combineOutput(stdout, stderr);
|
|
17171
|
+
const merged = this.combineOutput(stdout, stderr);
|
|
17172
|
+
const lines = merged.split("\n");
|
|
17173
|
+
const kept = [];
|
|
17174
|
+
let passCount = 0;
|
|
17175
|
+
let skipCount = 0;
|
|
17176
|
+
let inFailBlock = false;
|
|
17177
|
+
let droppedRun = 0;
|
|
17178
|
+
let droppedDownload = 0;
|
|
17179
|
+
let inRaceBlock = false;
|
|
17180
|
+
let raceBlockLines = [];
|
|
17181
|
+
let racePendingFence = false;
|
|
17182
|
+
let raceCount = 0;
|
|
17183
|
+
const flushRaceBlock = () => {
|
|
17184
|
+
let inGoroutine = false;
|
|
17185
|
+
let goroutineFrameCount = 0;
|
|
17186
|
+
let goroutineFramesDropped = 0;
|
|
17187
|
+
for (const rline of raceBlockLines) {
|
|
17188
|
+
if (GOROUTINE_HEADER_RE.test(rline)) {
|
|
17189
|
+
if (goroutineFramesDropped) {
|
|
17190
|
+
kept.push(` [token-goat: +${goroutineFramesDropped} goroutine frames omitted]`);
|
|
17191
|
+
}
|
|
17192
|
+
inGoroutine = true;
|
|
17193
|
+
goroutineFrameCount = 0;
|
|
17194
|
+
goroutineFramesDropped = 0;
|
|
17195
|
+
kept.push(rline);
|
|
17196
|
+
continue;
|
|
17197
|
+
}
|
|
17198
|
+
if (inGoroutine) {
|
|
17199
|
+
if ((rline.startsWith(" ") || rline.startsWith(" ")) && rline.trim()) {
|
|
17200
|
+
goroutineFrameCount += 1;
|
|
17201
|
+
if (goroutineFrameCount <= MAX_RACE_GOROUTINE_FRAMES) kept.push(rline);
|
|
17202
|
+
else goroutineFramesDropped += 1;
|
|
17203
|
+
continue;
|
|
17204
|
+
}
|
|
17205
|
+
if (goroutineFramesDropped) {
|
|
17206
|
+
kept.push(` [token-goat: +${goroutineFramesDropped} goroutine frames omitted]`);
|
|
17207
|
+
}
|
|
17208
|
+
inGoroutine = false;
|
|
17209
|
+
goroutineFrameCount = 0;
|
|
17210
|
+
goroutineFramesDropped = 0;
|
|
17211
|
+
}
|
|
17212
|
+
kept.push(rline);
|
|
17213
|
+
}
|
|
17214
|
+
if (goroutineFramesDropped) {
|
|
17215
|
+
kept.push(` [token-goat: +${goroutineFramesDropped} goroutine frames omitted]`);
|
|
17216
|
+
}
|
|
17217
|
+
};
|
|
17218
|
+
for (const line of lines) {
|
|
17219
|
+
if (line.startsWith("go: downloading")) {
|
|
17220
|
+
droppedDownload += 1;
|
|
17221
|
+
continue;
|
|
17222
|
+
}
|
|
17223
|
+
if (RACE_FENCE_RE.test(line)) {
|
|
17224
|
+
if (inRaceBlock) {
|
|
17225
|
+
raceBlockLines.push(line);
|
|
17226
|
+
flushRaceBlock();
|
|
17227
|
+
raceBlockLines = [];
|
|
17228
|
+
inRaceBlock = false;
|
|
17229
|
+
racePendingFence = false;
|
|
17230
|
+
} else if (!racePendingFence) {
|
|
17231
|
+
racePendingFence = true;
|
|
17232
|
+
raceBlockLines = [line];
|
|
17233
|
+
} else {
|
|
17234
|
+
kept.push(...raceBlockLines, line);
|
|
17235
|
+
raceBlockLines = [];
|
|
17236
|
+
racePendingFence = false;
|
|
17237
|
+
}
|
|
17238
|
+
continue;
|
|
17239
|
+
}
|
|
17240
|
+
if (racePendingFence) {
|
|
17241
|
+
raceBlockLines.push(line);
|
|
17242
|
+
if (RACE_WARNING_RE.test(line)) {
|
|
17243
|
+
inRaceBlock = true;
|
|
17244
|
+
raceCount += 1;
|
|
17245
|
+
racePendingFence = false;
|
|
17246
|
+
} else if (!line.trim()) {
|
|
17247
|
+
kept.push(...raceBlockLines);
|
|
17248
|
+
raceBlockLines = [];
|
|
17249
|
+
racePendingFence = false;
|
|
17250
|
+
}
|
|
17251
|
+
continue;
|
|
17252
|
+
}
|
|
17253
|
+
if (inRaceBlock) {
|
|
17254
|
+
raceBlockLines.push(line);
|
|
17255
|
+
continue;
|
|
17256
|
+
}
|
|
17257
|
+
if (TEST_RPC_RE.test(line)) {
|
|
17258
|
+
droppedRun += 1;
|
|
17259
|
+
continue;
|
|
17260
|
+
}
|
|
17261
|
+
if (TEST_FAIL_RE.test(line)) {
|
|
17262
|
+
inFailBlock = true;
|
|
17263
|
+
kept.push(line);
|
|
17264
|
+
continue;
|
|
17265
|
+
}
|
|
17266
|
+
if (TEST_PASS_RE.test(line)) {
|
|
17267
|
+
inFailBlock = false;
|
|
17268
|
+
passCount += 1;
|
|
17269
|
+
continue;
|
|
17270
|
+
}
|
|
17271
|
+
if (SKIP_RE.test(line)) {
|
|
17272
|
+
skipCount += 1;
|
|
17273
|
+
continue;
|
|
17274
|
+
}
|
|
17275
|
+
if (TEST_RUN_RE.test(line)) {
|
|
17276
|
+
if (inFailBlock) {
|
|
17277
|
+
inFailBlock = false;
|
|
17278
|
+
} else {
|
|
17279
|
+
droppedRun += 1;
|
|
17280
|
+
continue;
|
|
17281
|
+
}
|
|
17282
|
+
}
|
|
17283
|
+
if (inFailBlock && (line.startsWith(" ") || line.startsWith(" ") || !line.trim())) {
|
|
17284
|
+
kept.push(line);
|
|
17285
|
+
continue;
|
|
17286
|
+
}
|
|
17287
|
+
inFailBlock = false;
|
|
17288
|
+
kept.push(line);
|
|
17289
|
+
}
|
|
17290
|
+
if (raceBlockLines.length) flushRaceBlock();
|
|
17291
|
+
const goOkCount = kept.filter((l) => OK_PKG_RE.test(l)).length;
|
|
17292
|
+
const goFailCount = kept.filter((l) => FAIL_PKG_RE.test(l)).length;
|
|
17293
|
+
if (goOkCount + goFailCount >= 2) {
|
|
17294
|
+
kept.push(`[${goOkCount} packages passed, ${goFailCount} packages failed]`);
|
|
17295
|
+
}
|
|
17296
|
+
const notes = [];
|
|
17297
|
+
maybeNote(
|
|
17298
|
+
notes,
|
|
17299
|
+
raceCount,
|
|
17300
|
+
`kept ${raceCount} DATA RACE block(s) verbatim (goroutine stacks collapsed)`
|
|
17301
|
+
);
|
|
17302
|
+
maybeNote(notes, passCount, `collapsed ${passCount} PASS testcases`);
|
|
17303
|
+
maybeNote(notes, skipCount, `collapsed ${skipCount} SKIP testcases`);
|
|
17304
|
+
maybeNote(notes, droppedRun, `dropped ${droppedRun} === RUN/PAUSE/CONT lines`);
|
|
17305
|
+
maybeNote(notes, droppedDownload, `dropped ${droppedDownload} 'go: downloading' lines`);
|
|
17306
|
+
this.emitNotes(kept, notes);
|
|
17307
|
+
return this.finalize(kept);
|
|
17308
|
+
}
|
|
17309
|
+
};
|
|
17310
|
+
var goTestFilter = new GoTestFilter();
|
|
17311
|
+
|
|
17312
|
+
// src/tool_filters/dispatch.ts
|
|
17313
|
+
init_define_import_meta_env();
|
|
17314
|
+
var TOOL_FILTERS = [
|
|
17315
|
+
// Batch A — test runners. Node family (jest/mocha/ava/tap, vitest) first, then
|
|
17316
|
+
// the bespoke runners (pytest, go test) that need their own structural logic.
|
|
17317
|
+
// No overlap with later batches; safe at the head — except `go-test`, which
|
|
17318
|
+
// must precede any future `go build`/`go run` filter (both match `go`), so it
|
|
17319
|
+
// is registered here ahead of the build batch.
|
|
17320
|
+
...TEST_RUNNER_FILTERS,
|
|
17321
|
+
pytestFilter,
|
|
17322
|
+
goTestFilter
|
|
17323
|
+
// Batches append here: package-managers · linters · vcs · build · containers ·
|
|
17324
|
+
// cloud/iac · ci · ai-clis · shell/file · lang.
|
|
17325
|
+
];
|
|
17326
|
+
var PROFILE_CAPS = { aggressive: 50, balanced: 200, minimal: 500 };
|
|
17327
|
+
function selectFilter(argv) {
|
|
17328
|
+
if (argv.length === 0) return null;
|
|
17329
|
+
let resolved = stripPrefixes(argv);
|
|
17330
|
+
if (resolved.length === 0) {
|
|
17331
|
+
resolved = argv.slice(0, 1);
|
|
17332
|
+
if (resolved.length === 0) return null;
|
|
17333
|
+
}
|
|
17334
|
+
for (const f of TOOL_FILTERS) {
|
|
17335
|
+
try {
|
|
17336
|
+
if (f.matches(resolved)) return f;
|
|
17337
|
+
} catch {
|
|
17338
|
+
}
|
|
17339
|
+
}
|
|
17340
|
+
return null;
|
|
17341
|
+
}
|
|
17342
|
+
function hasRedirect(argv) {
|
|
17343
|
+
return argv.some((tok) => REDIRECT_TOKEN_RE.test(tok));
|
|
17344
|
+
}
|
|
17345
|
+
function detectFromCommand(command) {
|
|
17346
|
+
if (!command || command.length > 65536) return null;
|
|
17347
|
+
if (["&&", "||", "$(", "`"].some((op) => command.includes(op))) return null;
|
|
17348
|
+
if (command.includes("|") || command.includes(";")) return null;
|
|
17349
|
+
let argv;
|
|
17350
|
+
try {
|
|
17351
|
+
argv = shlexSplit(command);
|
|
17352
|
+
} catch {
|
|
17353
|
+
return null;
|
|
17354
|
+
}
|
|
17355
|
+
if (hasRedirect(argv)) return null;
|
|
17356
|
+
const filter = selectFilter(argv);
|
|
17357
|
+
if (filter === null) return null;
|
|
17358
|
+
return { filter, argv: stripPrefixes(argv) };
|
|
17359
|
+
}
|
|
17360
|
+
function compressOutput(filter, stdout, stderr, exitCode, argv, opts = {}) {
|
|
17361
|
+
const profile = opts.compressionProfile ?? "balanced";
|
|
17362
|
+
const maxLines = opts.maxLines ?? 1e3;
|
|
17363
|
+
let effectiveMaxLines = PROFILE_CAPS[profile] ?? 200;
|
|
17364
|
+
if (maxLines < effectiveMaxLines) effectiveMaxLines = maxLines;
|
|
17365
|
+
const skipProgress = profile === "minimal";
|
|
17366
|
+
const applyOpts = { maxLines: effectiveMaxLines, skipProgress };
|
|
17367
|
+
if (opts.maxBytes !== void 0) applyOpts.maxBytes = opts.maxBytes;
|
|
17368
|
+
return filter.apply(stdout, stderr, exitCode, argv, applyOpts);
|
|
17369
|
+
}
|
|
17370
|
+
function filterByName(name) {
|
|
17371
|
+
if (name === "generic") return new GenericFilter();
|
|
17372
|
+
for (const f of TOOL_FILTERS) if (f.name === name) return f;
|
|
17373
|
+
return null;
|
|
17374
|
+
}
|
|
17375
|
+
|
|
17376
|
+
// src/hooks_bash.ts
|
|
17377
|
+
function stripCdPrefix(cmd) {
|
|
17378
|
+
const stripped = cmd.replace(/^(?:cd\s+(?:"[^"]*"|'[^']*'|\S+)\s*&&\s*)+/, "");
|
|
17379
|
+
return stripped.trim() || cmd;
|
|
17380
|
+
}
|
|
17381
|
+
function stripOutputPipeline(cmd) {
|
|
17382
|
+
let inSingle = false;
|
|
17383
|
+
let inDouble = false;
|
|
17384
|
+
let cut = cmd.length;
|
|
17385
|
+
for (let i = 0; i < cmd.length; i++) {
|
|
17386
|
+
const ch = cmd[i];
|
|
17387
|
+
if (ch === "'" && !inDouble) {
|
|
17388
|
+
inSingle = !inSingle;
|
|
17389
|
+
} else if (ch === '"' && !inSingle) {
|
|
17390
|
+
inDouble = !inDouble;
|
|
17391
|
+
} else if (ch === "|" && !inSingle && !inDouble) {
|
|
17392
|
+
if (cmd[i + 1] === "|") {
|
|
17393
|
+
i++;
|
|
17394
|
+
continue;
|
|
17395
|
+
}
|
|
17396
|
+
cut = i;
|
|
17397
|
+
break;
|
|
17398
|
+
}
|
|
17399
|
+
}
|
|
17400
|
+
let base = cmd.slice(0, cut);
|
|
17401
|
+
let prev;
|
|
17402
|
+
do {
|
|
17403
|
+
prev = base;
|
|
17404
|
+
const masked = base.replace(/"((?:[^"\\]|\\.)*)"/g, (_m, inner) => '"' + " ".repeat(inner.length) + '"').replace(/'([^']*)'/g, (_m, inner) => "'" + " ".repeat(inner.length) + "'");
|
|
17405
|
+
const newMasked = masked.replace(/\s*(?:[0-9]*>&[0-9]+|[0-9&]*>>?\s*(?:"[^"]*"|'[^']*'|[^\s|]+))\s*$/, "");
|
|
17406
|
+
if (newMasked.length < masked.length) {
|
|
17407
|
+
base = base.slice(0, newMasked.length);
|
|
17408
|
+
}
|
|
17409
|
+
} while (base !== prev);
|
|
17410
|
+
return base.trim();
|
|
17411
|
+
}
|
|
17412
|
+
function extractCommand(event) {
|
|
17413
|
+
const cmd = event.toolInput["command"];
|
|
17414
|
+
return typeof cmd === "string" && cmd.trim() !== "" ? cmd.trim() : void 0;
|
|
17415
|
+
}
|
|
17416
|
+
function isTempPath(fp) {
|
|
17417
|
+
const norm = fp.replace(/\\/g, "/");
|
|
17418
|
+
return /^\/tmp\//i.test(norm) || /\/var\/folders\//i.test(norm) || /AppData\/Local\/Temp\//i.test(norm) || norm.startsWith("/c/Users/") && norm.includes("/AppData/Local/Temp/");
|
|
17419
|
+
}
|
|
17420
|
+
function isOrchestratorStateFile(filePath) {
|
|
17421
|
+
const basename9 = (filePath.includes("/") ? filePath.split("/").at(-1) : filePath.split("\\").at(-1)) ?? filePath;
|
|
17422
|
+
return /^\.improve-state-/.test(basename9);
|
|
17423
|
+
}
|
|
17424
|
+
function extractCatSourceFile(cmd) {
|
|
17425
|
+
const m = /^cat\s+(\S+\.(?:java|py|ts|tsx|js|jsx|go|rb|rs|cpp|cc|cxx|c|h|hpp|kt|swift|cs|php|scala|clj|css|scss|sass|less))\s*$/.exec(cmd);
|
|
17426
|
+
return m?.[1] ?? null;
|
|
17427
|
+
}
|
|
17428
|
+
function extractCatFile(cmd) {
|
|
17429
|
+
const m = /^cat(?:\s+(?:-[a-zA-Z]+|--[a-zA-Z-]+))*\s+(?:"([^"]+)"|'([^']+)'|(\S+))\s*$/.exec(cmd);
|
|
17430
|
+
if (!m) return null;
|
|
15965
17431
|
const filePath = m[1] ?? m[2] ?? m[3];
|
|
15966
17432
|
if (filePath === void 0) return null;
|
|
15967
17433
|
if (isTempPath(filePath)) return null;
|
|
15968
|
-
const
|
|
15969
|
-
const isEnvFile = /^\.env(\.\w+)?$/i.test(
|
|
17434
|
+
const basename9 = (filePath.includes("/") ? filePath.split("/").at(-1) : filePath.split("\\").at(-1)) ?? filePath;
|
|
17435
|
+
const isEnvFile = /^\.env(\.\w+)?$/i.test(basename9);
|
|
15970
17436
|
const hasKnownExt = /\.(?:java|py|ts|tsx|js|jsx|go|rb|rs|cpp|cc|cxx|c|h|hpp|kt|swift|cs|php|scala|clj|css|scss|sass|less|md|mdx|rst|txt|json|yaml|yml|toml|xml|conf|cfg|ini|properties|sql|env)$/i.test(filePath);
|
|
15971
17437
|
if (!hasKnownExt && !isEnvFile) return null;
|
|
15972
17438
|
const isSql = /\.sql$/i.test(filePath);
|
|
@@ -16007,8 +17473,8 @@ function extractWslCatFile(cmd) {
|
|
|
16007
17473
|
if (!drive || !pathRest) return null;
|
|
16008
17474
|
const filePath = drive + ":/" + pathRest;
|
|
16009
17475
|
if (isTempPath(filePath)) return null;
|
|
16010
|
-
const
|
|
16011
|
-
const isEnvFile = /^\.env(\.\w+)?$/i.test(
|
|
17476
|
+
const basename9 = (filePath.includes("/") ? filePath.split("/").at(-1) : filePath.split("\\").at(-1)) ?? filePath;
|
|
17477
|
+
const isEnvFile = /^\.env(\.\w+)?$/i.test(basename9);
|
|
16012
17478
|
const hasKnownExt = /\.(?:java|py|ts|tsx|js|jsx|go|rb|rs|cpp|cc|cxx|c|h|hpp|kt|swift|cs|php|scala|clj|css|scss|sass|less|md|mdx|rst|txt|json|yaml|yml|toml|xml|conf|cfg|ini|properties|sql|env)$/i.test(filePath);
|
|
16013
17479
|
if (!hasKnownExt && !isEnvFile) return null;
|
|
16014
17480
|
const isSql = /\.sql$/i.test(filePath);
|
|
@@ -16124,7 +17590,7 @@ function extractTasksOutput(cmd) {
|
|
|
16124
17590
|
const fp = catM[1] ?? catM[2] ?? catM[3];
|
|
16125
17591
|
if (fp) {
|
|
16126
17592
|
const m = taskOutputRe.exec(fp);
|
|
16127
|
-
if (m) return { id: m[1] };
|
|
17593
|
+
if (m) return { id: m[1], path: fp };
|
|
16128
17594
|
}
|
|
16129
17595
|
}
|
|
16130
17596
|
if (!/-f\b/.test(cmd) && !/-n\s*\+/.test(cmd)) {
|
|
@@ -16136,7 +17602,7 @@ function extractTasksOutput(cmd) {
|
|
|
16136
17602
|
if (m) {
|
|
16137
17603
|
const nStr = tailM[1] ?? tailM[2];
|
|
16138
17604
|
const n = nStr !== void 0 ? parseInt(nStr, 10) : void 0;
|
|
16139
|
-
return n !== void 0 ? { id: m[1], n } : { id: m[1] };
|
|
17605
|
+
return n !== void 0 ? { id: m[1], path: fp, n } : { id: m[1], path: fp };
|
|
16140
17606
|
}
|
|
16141
17607
|
}
|
|
16142
17608
|
}
|
|
@@ -16145,7 +17611,7 @@ function extractTasksOutput(cmd) {
|
|
|
16145
17611
|
const fp = byteTailM[1] ?? byteTailM[2] ?? byteTailM[3];
|
|
16146
17612
|
if (fp) {
|
|
16147
17613
|
const m = taskOutputRe.exec(fp);
|
|
16148
|
-
if (m) return { id: m[1] };
|
|
17614
|
+
if (m) return { id: m[1], path: fp };
|
|
16149
17615
|
}
|
|
16150
17616
|
}
|
|
16151
17617
|
}
|
|
@@ -16236,6 +17702,53 @@ function buildRecallHint(cmd, outputId) {
|
|
|
16236
17702
|
}
|
|
16237
17703
|
return "Output from a prior `" + cmdPreview + "` run is cached. Use `token-goat bash-output " + outputId + "` (or `--tail 50`, `--grep ERROR`) to re-inspect it without re-running.";
|
|
16238
17704
|
}
|
|
17705
|
+
function shellQuoteSingle(s) {
|
|
17706
|
+
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
17707
|
+
}
|
|
17708
|
+
function isCompressibleSingleCommand(cmd) {
|
|
17709
|
+
if (!cmd || cmd.length > 65536) return false;
|
|
17710
|
+
if (["&&", "||", "$(", "`"].some((op) => cmd.includes(op))) return false;
|
|
17711
|
+
if (cmd.includes("|") || cmd.includes(";")) return false;
|
|
17712
|
+
if (/[<>]/.test(cmd)) return false;
|
|
17713
|
+
return true;
|
|
17714
|
+
}
|
|
17715
|
+
function maybeCompressRewrite(event, rawCmd, cmd) {
|
|
17716
|
+
if (process.env["TOKEN_GOAT_BASH_COMPRESS"] === "0") return null;
|
|
17717
|
+
let cfg;
|
|
17718
|
+
try {
|
|
17719
|
+
cfg = loadConfig().bash_compress;
|
|
17720
|
+
} catch {
|
|
17721
|
+
return null;
|
|
17722
|
+
}
|
|
17723
|
+
if (!cfg.enabled) return null;
|
|
17724
|
+
const detected = detectFromCommand(cmd);
|
|
17725
|
+
let filterName;
|
|
17726
|
+
if (detected !== null) {
|
|
17727
|
+
filterName = detected.filter.name;
|
|
17728
|
+
} else if (isCompressibleSingleCommand(cmd)) {
|
|
17729
|
+
filterName = "generic";
|
|
17730
|
+
} else {
|
|
17731
|
+
return null;
|
|
17732
|
+
}
|
|
17733
|
+
if (cfg.disabled_filters.includes(filterName)) return null;
|
|
17734
|
+
const wrapped = `token-goat compress -f ${filterName} -c ${shellQuoteSingle(rawCmd)}`;
|
|
17735
|
+
return { hookType: "rewriteInput", updatedInput: { ...event.toolInput, command: wrapped } };
|
|
17736
|
+
}
|
|
17737
|
+
function unwrapCompressCommand(executed) {
|
|
17738
|
+
const t = executed.trim();
|
|
17739
|
+
if (!/^token-goat\s+compress\b/.test(t)) return null;
|
|
17740
|
+
let argv;
|
|
17741
|
+
try {
|
|
17742
|
+
argv = shlexSplit(t);
|
|
17743
|
+
} catch {
|
|
17744
|
+
return null;
|
|
17745
|
+
}
|
|
17746
|
+
for (let i = 0; i + 1 < argv.length; i++) {
|
|
17747
|
+
const tok = argv[i];
|
|
17748
|
+
if (tok === "-c" || tok === "--cmd") return argv[i + 1] ?? null;
|
|
17749
|
+
}
|
|
17750
|
+
return null;
|
|
17751
|
+
}
|
|
16239
17752
|
function preBashHandler(event) {
|
|
16240
17753
|
const rawCmd = extractCommand(event);
|
|
16241
17754
|
if (rawCmd === void 0) return passOutput();
|
|
@@ -16243,10 +17756,11 @@ function preBashHandler(event) {
|
|
|
16243
17756
|
const cdStripped = cmd !== rawCmd;
|
|
16244
17757
|
const taskOutput = extractTasksOutput(cmd);
|
|
16245
17758
|
if (taskOutput !== null) {
|
|
16246
|
-
const { id } = taskOutput;
|
|
17759
|
+
const { id, path: outPath, n } = taskOutput;
|
|
16247
17760
|
recordStat("session_hint", 0, 0);
|
|
17761
|
+
const tail = n ?? 50;
|
|
16248
17762
|
return denyOutput(
|
|
16249
|
-
"Use `token-goat bash-output " +
|
|
17763
|
+
"Task output " + id + ' is on disk. Use `token-goat bash-output --file "' + outPath + '" --tail ' + tail + "` (or `--grep PATTERN`) to read a slice instead of the whole file."
|
|
16250
17764
|
);
|
|
16251
17765
|
}
|
|
16252
17766
|
const findResult = extractFindCommand(cmd);
|
|
@@ -16375,9 +17889,9 @@ function preBashHandler(event) {
|
|
|
16375
17889
|
if (monitoringHint !== null) {
|
|
16376
17890
|
const monCmdHash = shortFingerprint(stripOutputPipeline(cmd));
|
|
16377
17891
|
const monOutputId = getBashOutputId(monCmdHash);
|
|
16378
|
-
|
|
16379
|
-
|
|
16380
|
-
const monBytes = monEntry
|
|
17892
|
+
const monEntry = monOutputId !== null ? getBashOutput(monOutputId) : null;
|
|
17893
|
+
if (monOutputId !== null && monEntry !== null) {
|
|
17894
|
+
const monBytes = monEntry.sizeBytes;
|
|
16381
17895
|
const catFile = extractCatSourceFile(cmd);
|
|
16382
17896
|
if (catFile !== null) {
|
|
16383
17897
|
recordStat("bash_compress:recall", monBytes, Math.round(monBytes / 4));
|
|
@@ -16406,9 +17920,9 @@ function preBashHandler(event) {
|
|
|
16406
17920
|
const curlCacheKey = extractCurlUrl(cmd) ?? cmd;
|
|
16407
17921
|
const curlHash = shortFingerprint(curlCacheKey);
|
|
16408
17922
|
const curlOutputId = getBashOutputId(curlHash);
|
|
16409
|
-
|
|
16410
|
-
|
|
16411
|
-
const curlBytes = curlEntry
|
|
17923
|
+
const curlEntry = curlOutputId !== null ? getBashOutput(curlOutputId) : null;
|
|
17924
|
+
if (curlOutputId !== null && curlEntry !== null) {
|
|
17925
|
+
const curlBytes = curlEntry.sizeBytes;
|
|
16412
17926
|
recordStat("bash_compress:recall", curlBytes, Math.round(curlBytes / 4));
|
|
16413
17927
|
const curlPreview = cmd.length > 60 ? cmd.slice(0, 57) + "..." : cmd;
|
|
16414
17928
|
return contextOutput(
|
|
@@ -16416,14 +17930,16 @@ function preBashHandler(event) {
|
|
|
16416
17930
|
);
|
|
16417
17931
|
}
|
|
16418
17932
|
}
|
|
16419
|
-
if (!isBuildCommand(cmd)) return passOutput();
|
|
17933
|
+
if (!isBuildCommand(cmd) && detectFromCommand(cmd) === null) return passOutput();
|
|
16420
17934
|
const cmdHash = shortFingerprint(stripOutputPipeline(cmd));
|
|
16421
17935
|
const outputId = getBashOutputId(cmdHash);
|
|
16422
|
-
|
|
16423
|
-
|
|
16424
|
-
|
|
16425
|
-
|
|
16426
|
-
|
|
17936
|
+
const entry = outputId !== null ? getBashOutput(outputId) : null;
|
|
17937
|
+
if (outputId !== null && entry !== null) {
|
|
17938
|
+
const bytes = entry.sizeBytes;
|
|
17939
|
+
recordStat("bash_compress:recall", bytes, Math.round(bytes / 4));
|
|
17940
|
+
return contextOutput(buildRecallHint(cmd, outputId));
|
|
17941
|
+
}
|
|
17942
|
+
return maybeCompressRewrite(event, rawCmd, cmd) ?? passOutput();
|
|
16427
17943
|
}
|
|
16428
17944
|
registerHook("pre_tool_use", preBashHandler, { toolName: "Bash" });
|
|
16429
17945
|
var MIN_CACHE_BYTES = 512;
|
|
@@ -16438,15 +17954,57 @@ function extractBashOutput(raw) {
|
|
|
16438
17954
|
}
|
|
16439
17955
|
return "";
|
|
16440
17956
|
}
|
|
17957
|
+
function extractExitCode(raw) {
|
|
17958
|
+
const resp = raw["tool_response"];
|
|
17959
|
+
if (resp !== null && typeof resp === "object") {
|
|
17960
|
+
const r = resp;
|
|
17961
|
+
for (const key of ["exit_code", "exitCode", "returncode", "code"]) {
|
|
17962
|
+
if (typeof r[key] === "number") return r[key];
|
|
17963
|
+
}
|
|
17964
|
+
}
|
|
17965
|
+
return null;
|
|
17966
|
+
}
|
|
17967
|
+
var GH_SECURITY_PATHS = ["/security_advisories", "/advisories", "security_events"];
|
|
17968
|
+
var GH_SCOPE_PHRASES = ["Must have push access", "Resource not accessible by integration", "Must be an admin"];
|
|
17969
|
+
function buildGhApiHint(cmd, stdout, exitCode) {
|
|
17970
|
+
if (stdout === "" || !cmd.startsWith("gh api")) return null;
|
|
17971
|
+
const hints = [];
|
|
17972
|
+
const isSecurityPath = GH_SECURITY_PATHS.some((p) => cmd.includes(p));
|
|
17973
|
+
const hasScopePhrase = GH_SCOPE_PHRASES.some((p) => stdout.includes(p));
|
|
17974
|
+
const failedSecurityCall = exitCode !== null && exitCode !== 0 && isSecurityPath;
|
|
17975
|
+
if (hasScopePhrase || failedSecurityCall) {
|
|
17976
|
+
hints.push("[token-goat] GitHub API scope issue: try gh auth refresh -s security_events");
|
|
17977
|
+
}
|
|
17978
|
+
const trimmed = stdout.trimStart();
|
|
17979
|
+
if (trimmed.startsWith("{")) {
|
|
17980
|
+
try {
|
|
17981
|
+
const parsed = JSON.parse(stdout);
|
|
17982
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
17983
|
+
const keyCount = Object.keys(parsed).length;
|
|
17984
|
+
if (keyCount >= 15) {
|
|
17985
|
+
hints.push(`[token-goat] Large API response (${keyCount} keys). Filter with --jq '.key1,.key2' to reduce tokens.`);
|
|
17986
|
+
}
|
|
17987
|
+
}
|
|
17988
|
+
} catch {
|
|
17989
|
+
}
|
|
17990
|
+
}
|
|
17991
|
+
return hints.length > 0 ? hints.join(" ") : null;
|
|
17992
|
+
}
|
|
16441
17993
|
async function postBashHandler(event) {
|
|
16442
17994
|
try {
|
|
16443
|
-
const
|
|
16444
|
-
if (
|
|
17995
|
+
const rawCmdRaw = extractCommand(event);
|
|
17996
|
+
if (rawCmdRaw === void 0) return passOutput();
|
|
17997
|
+
const rawCmd = unwrapCompressCommand(rawCmdRaw) ?? rawCmdRaw;
|
|
16445
17998
|
const cmd = stripCdPrefix(rawCmd);
|
|
16446
17999
|
const curlDl = extractCurlDownload(cmd);
|
|
16447
18000
|
if (curlDl !== null) {
|
|
16448
18001
|
recordCurlDownload(curlDl.url, curlDl.outputPath);
|
|
16449
18002
|
}
|
|
18003
|
+
const ghHint = buildGhApiHint(cmd, extractBashOutput(event.raw), extractExitCode(event.raw));
|
|
18004
|
+
if (ghHint !== null) {
|
|
18005
|
+
recordStat("session_hint", 0, 0);
|
|
18006
|
+
return contextOutput(ghHint);
|
|
18007
|
+
}
|
|
16450
18008
|
const isMonitoring = getMonitoringRecallHint(cmd) !== null;
|
|
16451
18009
|
if (!isMonitoring && !isBuildCommand(cmd) && !isCurlGetCommand(cmd)) return passOutput();
|
|
16452
18010
|
const output = extractBashOutput(event.raw);
|
|
@@ -16464,8 +18022,8 @@ registerHook("post_tool_use", postBashHandler, { toolName: "Bash" });
|
|
|
16464
18022
|
|
|
16465
18023
|
// src/image_shrink.ts
|
|
16466
18024
|
init_define_import_meta_env();
|
|
16467
|
-
import * as
|
|
16468
|
-
import * as
|
|
18025
|
+
import * as fs13 from "node:fs";
|
|
18026
|
+
import * as path16 from "node:path";
|
|
16469
18027
|
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
16470
18028
|
".png",
|
|
16471
18029
|
".jpg",
|
|
@@ -16492,7 +18050,7 @@ async function loadSharp() {
|
|
|
16492
18050
|
return _sharpCache;
|
|
16493
18051
|
}
|
|
16494
18052
|
function isImagePath(p) {
|
|
16495
|
-
return IMAGE_EXTENSIONS.has(
|
|
18053
|
+
return IMAGE_EXTENSIONS.has(path16.extname(p).toLowerCase());
|
|
16496
18054
|
}
|
|
16497
18055
|
async function shrinkImage(input, opts) {
|
|
16498
18056
|
const maxDimension = opts?.maxDimension ?? DEFAULT_MAX_DIMENSION;
|
|
@@ -16524,7 +18082,7 @@ async function shrinkImage(input, opts) {
|
|
|
16524
18082
|
}
|
|
16525
18083
|
function statSize2(absPath) {
|
|
16526
18084
|
try {
|
|
16527
|
-
const st =
|
|
18085
|
+
const st = fs13.statSync(absPath);
|
|
16528
18086
|
return st.isFile() ? st.size : null;
|
|
16529
18087
|
} catch {
|
|
16530
18088
|
return null;
|
|
@@ -16538,7 +18096,7 @@ async function preReadImageHandler(event) {
|
|
|
16538
18096
|
if (size === null || size < DEFAULT_SIZE_THRESHOLD_BYTES) return passOutput();
|
|
16539
18097
|
let input;
|
|
16540
18098
|
try {
|
|
16541
|
-
input =
|
|
18099
|
+
input = fs13.readFileSync(filePath);
|
|
16542
18100
|
} catch {
|
|
16543
18101
|
return passOutput();
|
|
16544
18102
|
}
|
|
@@ -16547,7 +18105,7 @@ async function preReadImageHandler(event) {
|
|
|
16547
18105
|
const saved = result.originalBytes - result.shrunkBytes;
|
|
16548
18106
|
const pct = Math.round(saved / result.originalBytes * 100);
|
|
16549
18107
|
const dataUrl = `data:image/${result.format};base64,${result.data.toString("base64")}`;
|
|
16550
|
-
const summary = `token-goat shrank ${
|
|
18108
|
+
const summary = `token-goat shrank ${path16.basename(filePath)}: ${Math.round(result.originalBytes / 1024)}kb -> ${Math.round(result.shrunkBytes / 1024)}kb (${pct}% smaller, ${result.width}x${result.height} ${result.format}).`;
|
|
16551
18109
|
return contextOutput(`${summary}
|
|
16552
18110
|
${dataUrl}`);
|
|
16553
18111
|
}
|
|
@@ -16556,7 +18114,7 @@ registerHook("pre_tool_use", preReadImageHandler, { toolName: "Read" });
|
|
|
16556
18114
|
// src/relay.ts
|
|
16557
18115
|
var DEFAULT_STDIN_TIMEOUT_MS = 5e3;
|
|
16558
18116
|
function readStdinJson(timeoutMs = DEFAULT_STDIN_TIMEOUT_MS) {
|
|
16559
|
-
return new Promise((
|
|
18117
|
+
return new Promise((resolve8, reject) => {
|
|
16560
18118
|
const chunks = [];
|
|
16561
18119
|
let settled = false;
|
|
16562
18120
|
const finish = (fn) => {
|
|
@@ -16582,7 +18140,7 @@ function readStdinJson(timeoutMs = DEFAULT_STDIN_TIMEOUT_MS) {
|
|
|
16582
18140
|
return;
|
|
16583
18141
|
}
|
|
16584
18142
|
try {
|
|
16585
|
-
|
|
18143
|
+
resolve8(JSON.parse(text));
|
|
16586
18144
|
} catch (err2) {
|
|
16587
18145
|
reject(err2 instanceof Error ? err2 : new Error(String(err2)));
|
|
16588
18146
|
}
|
|
@@ -16617,7 +18175,15 @@ async function relay(eventName) {
|
|
|
16617
18175
|
}
|
|
16618
18176
|
const payload = await readStdinJson();
|
|
16619
18177
|
const event = buildEvent(eventName, payload);
|
|
18178
|
+
try {
|
|
18179
|
+
loadSessionState(event.sessionId);
|
|
18180
|
+
} catch {
|
|
18181
|
+
}
|
|
16620
18182
|
const output = await runHook(event);
|
|
18183
|
+
try {
|
|
18184
|
+
saveSessionState(event.sessionId);
|
|
18185
|
+
} catch {
|
|
18186
|
+
}
|
|
16621
18187
|
process.stdout.write(serializeOutput(output));
|
|
16622
18188
|
} catch {
|
|
16623
18189
|
process.stdout.write("{}");
|
|
@@ -16626,9 +18192,9 @@ async function relay(eventName) {
|
|
|
16626
18192
|
|
|
16627
18193
|
// src/install.ts
|
|
16628
18194
|
init_define_import_meta_env();
|
|
16629
|
-
import * as
|
|
16630
|
-
import * as
|
|
16631
|
-
import * as
|
|
18195
|
+
import * as fs14 from "node:fs";
|
|
18196
|
+
import * as os5 from "node:os";
|
|
18197
|
+
import * as path17 from "node:path";
|
|
16632
18198
|
var HOOK_EVENT_MAP = [
|
|
16633
18199
|
["PreToolUse", "pre_tool_use"],
|
|
16634
18200
|
["PostToolUse", "post_tool_use"],
|
|
@@ -16639,13 +18205,13 @@ function hookCommand(eventArg) {
|
|
|
16639
18205
|
return `token-goat hook ${eventArg}`;
|
|
16640
18206
|
}
|
|
16641
18207
|
function settingsPath(scope) {
|
|
16642
|
-
const base = scope === "user" ?
|
|
16643
|
-
return
|
|
18208
|
+
const base = scope === "user" ? path17.join(os5.homedir(), ".claude") : path17.join(process.cwd(), ".claude");
|
|
18209
|
+
return path17.join(base, "settings.json");
|
|
16644
18210
|
}
|
|
16645
18211
|
function readSettings(p) {
|
|
16646
18212
|
let raw;
|
|
16647
18213
|
try {
|
|
16648
|
-
raw =
|
|
18214
|
+
raw = fs14.readFileSync(p, "utf8");
|
|
16649
18215
|
} catch {
|
|
16650
18216
|
return {};
|
|
16651
18217
|
}
|
|
@@ -16685,7 +18251,7 @@ function installHooks(scope = "user") {
|
|
|
16685
18251
|
return { scope, settingsPath: p, alreadyInstalled: true };
|
|
16686
18252
|
}
|
|
16687
18253
|
settings.hooks = hooks;
|
|
16688
|
-
|
|
18254
|
+
fs14.mkdirSync(path17.dirname(p), { recursive: true });
|
|
16689
18255
|
atomicWriteText(p, `${JSON.stringify(settings, null, 2)}
|
|
16690
18256
|
`);
|
|
16691
18257
|
return { scope, settingsPath: p, alreadyInstalled: false };
|
|
@@ -16724,7 +18290,7 @@ function uninstallHooks(scope = "user") {
|
|
|
16724
18290
|
} else {
|
|
16725
18291
|
settings.hooks = hooks;
|
|
16726
18292
|
}
|
|
16727
|
-
|
|
18293
|
+
fs14.mkdirSync(path17.dirname(p), { recursive: true });
|
|
16728
18294
|
atomicWriteText(p, `${JSON.stringify(settings, null, 2)}
|
|
16729
18295
|
`);
|
|
16730
18296
|
return true;
|
|
@@ -16733,21 +18299,21 @@ function uninstallHooks(scope = "user") {
|
|
|
16733
18299
|
// src/worker.ts
|
|
16734
18300
|
init_define_import_meta_env();
|
|
16735
18301
|
import { spawn } from "node:child_process";
|
|
16736
|
-
import * as
|
|
16737
|
-
import * as
|
|
18302
|
+
import * as fs15 from "node:fs";
|
|
18303
|
+
import * as path18 from "node:path";
|
|
16738
18304
|
import { Worker, isMainThread, parentPort, workerData } from "node:worker_threads";
|
|
16739
18305
|
import { fileURLToPath } from "node:url";
|
|
16740
18306
|
var DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
16741
18307
|
function dirtyQueuePathFor(dir) {
|
|
16742
|
-
return
|
|
18308
|
+
return path18.join(dir, "queue", "dirty.txt");
|
|
16743
18309
|
}
|
|
16744
18310
|
function workerPidPath(dir = dataDir()) {
|
|
16745
|
-
return
|
|
18311
|
+
return path18.join(dir, "worker.pid");
|
|
16746
18312
|
}
|
|
16747
18313
|
function getDirtyPathsFor(dir) {
|
|
16748
18314
|
let raw;
|
|
16749
18315
|
try {
|
|
16750
|
-
raw =
|
|
18316
|
+
raw = fs15.readFileSync(dirtyQueuePathFor(dir), "utf8");
|
|
16751
18317
|
} catch {
|
|
16752
18318
|
return [];
|
|
16753
18319
|
}
|
|
@@ -16755,15 +18321,19 @@ function getDirtyPathsFor(dir) {
|
|
|
16755
18321
|
const out2 = [];
|
|
16756
18322
|
for (const line of raw.split("\n")) {
|
|
16757
18323
|
const trimmed = line.trim();
|
|
16758
|
-
if (trimmed === ""
|
|
16759
|
-
|
|
18324
|
+
if (trimmed === "") continue;
|
|
18325
|
+
const normalized = normalizePath(trimmed);
|
|
18326
|
+
const caseInsensitiveFs = process.platform === "win32" || process.platform === "darwin";
|
|
18327
|
+
const dedupeKey = caseInsensitiveFs ? normalized.toLowerCase() : normalized;
|
|
18328
|
+
if (seen.has(dedupeKey)) continue;
|
|
18329
|
+
seen.add(dedupeKey);
|
|
16760
18330
|
out2.push(trimmed);
|
|
16761
18331
|
}
|
|
16762
18332
|
return out2;
|
|
16763
18333
|
}
|
|
16764
18334
|
function clearDirtyQueueFor(dir) {
|
|
16765
18335
|
try {
|
|
16766
|
-
|
|
18336
|
+
fs15.rmSync(dirtyQueuePathFor(dir), { force: true });
|
|
16767
18337
|
} catch {
|
|
16768
18338
|
}
|
|
16769
18339
|
}
|
|
@@ -16778,7 +18348,7 @@ function makeIndexer(dbPath) {
|
|
|
16778
18348
|
function processDirtyBatch(paths, index = makeIndexer(globalDbPath())) {
|
|
16779
18349
|
let indexed = 0;
|
|
16780
18350
|
for (const p of paths) {
|
|
16781
|
-
if (!p || !
|
|
18351
|
+
if (!p || !fs15.existsSync(p)) continue;
|
|
16782
18352
|
const sha = fingerprintFile(p);
|
|
16783
18353
|
if (sha === null) continue;
|
|
16784
18354
|
index(p, sha);
|
|
@@ -16789,7 +18359,7 @@ function processDirtyBatch(paths, index = makeIndexer(globalDbPath())) {
|
|
|
16789
18359
|
function drainOnce(dir, index) {
|
|
16790
18360
|
const paths = getDirtyPathsFor(dir);
|
|
16791
18361
|
if (paths.length === 0) return 0;
|
|
16792
|
-
const indexed = processDirtyBatch(paths, index ?? makeIndexer(
|
|
18362
|
+
const indexed = processDirtyBatch(paths, index ?? makeIndexer(path18.join(dir, "global.db")));
|
|
16793
18363
|
clearDirtyQueueFor(dir);
|
|
16794
18364
|
return indexed;
|
|
16795
18365
|
}
|
|
@@ -16803,7 +18373,7 @@ function pidAlive(pid) {
|
|
|
16803
18373
|
}
|
|
16804
18374
|
function readPidFile(dir) {
|
|
16805
18375
|
try {
|
|
16806
|
-
const raw =
|
|
18376
|
+
const raw = fs15.readFileSync(workerPidPath(dir), "utf8").trim();
|
|
16807
18377
|
if (!/^\d+$/.test(raw)) return null;
|
|
16808
18378
|
return parseInt(raw, 10);
|
|
16809
18379
|
} catch {
|
|
@@ -16826,7 +18396,7 @@ function stopWorker(dir = dataDir()) {
|
|
|
16826
18396
|
}
|
|
16827
18397
|
}
|
|
16828
18398
|
try {
|
|
16829
|
-
|
|
18399
|
+
fs15.rmSync(workerPidPath(dir), { force: true });
|
|
16830
18400
|
} catch {
|
|
16831
18401
|
}
|
|
16832
18402
|
return alive;
|
|
@@ -16835,9 +18405,9 @@ function startDetachedWorker(opts) {
|
|
|
16835
18405
|
const pollIntervalMs = opts?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
16836
18406
|
const dir = opts?.dataDir ?? dataDir();
|
|
16837
18407
|
try {
|
|
16838
|
-
|
|
18408
|
+
fs15.mkdirSync(dir, { recursive: true });
|
|
16839
18409
|
} catch (e) {
|
|
16840
|
-
if (e.code !== "EEXIST" || !
|
|
18410
|
+
if (e.code !== "EEXIST" || !fs15.existsSync(dir)) throw e;
|
|
16841
18411
|
}
|
|
16842
18412
|
const child = spawn(
|
|
16843
18413
|
process.execPath,
|
|
@@ -16857,7 +18427,7 @@ function startDetachedWorker(opts) {
|
|
|
16857
18427
|
if (pid === void 0) {
|
|
16858
18428
|
throw new Error("startDetachedWorker: spawn produced no pid");
|
|
16859
18429
|
}
|
|
16860
|
-
|
|
18430
|
+
fs15.writeFileSync(workerPidPath(dir), `${pid}
|
|
16861
18431
|
`);
|
|
16862
18432
|
child.unref();
|
|
16863
18433
|
return pid;
|
|
@@ -16869,7 +18439,7 @@ async function runWorkerLoop(dir, pollIntervalMs, shouldStop = () => false) {
|
|
|
16869
18439
|
} catch {
|
|
16870
18440
|
}
|
|
16871
18441
|
if (shouldStop()) break;
|
|
16872
|
-
await new Promise((
|
|
18442
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollIntervalMs));
|
|
16873
18443
|
}
|
|
16874
18444
|
}
|
|
16875
18445
|
function workerEntry() {
|
|
@@ -16898,42 +18468,131 @@ function workerEntry() {
|
|
|
16898
18468
|
}
|
|
16899
18469
|
workerEntry();
|
|
16900
18470
|
|
|
16901
|
-
// src/
|
|
18471
|
+
// src/bash_runner.ts
|
|
16902
18472
|
init_define_import_meta_env();
|
|
16903
|
-
|
|
16904
|
-
|
|
16905
|
-
|
|
16906
|
-
|
|
18473
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
18474
|
+
import * as os6 from "node:os";
|
|
18475
|
+
var DEFAULT_TIMEOUT_SECONDS = 600;
|
|
18476
|
+
var MAX_CAPTURE_BYTES = 32 * 1024 * 1024;
|
|
18477
|
+
var MIN_RECORD_STAT_BYTES = 32;
|
|
18478
|
+
function resolveFilter(command, filterName) {
|
|
18479
|
+
if (filterName) {
|
|
18480
|
+
const named = filterByName(filterName);
|
|
18481
|
+
if (named !== null) return named;
|
|
18482
|
+
}
|
|
18483
|
+
let argv;
|
|
18484
|
+
try {
|
|
18485
|
+
argv = shlexSplit(command);
|
|
18486
|
+
} catch {
|
|
18487
|
+
return null;
|
|
18488
|
+
}
|
|
18489
|
+
return selectFilter(argv);
|
|
16907
18490
|
}
|
|
16908
|
-
function
|
|
16909
|
-
const
|
|
16910
|
-
|
|
16911
|
-
_urlIndex.set(url, cacheId);
|
|
16912
|
-
return cacheId;
|
|
18491
|
+
function signalExitCode(signal) {
|
|
18492
|
+
const num = os6.constants.signals[signal];
|
|
18493
|
+
return 128 + (num ?? 0);
|
|
16913
18494
|
}
|
|
16914
|
-
function
|
|
16915
|
-
|
|
18495
|
+
function resolveProfile(explicit) {
|
|
18496
|
+
if (explicit) return explicit;
|
|
18497
|
+
try {
|
|
18498
|
+
const p = loadConfig().compression.profile;
|
|
18499
|
+
return p && p !== "auto" ? p : "balanced";
|
|
18500
|
+
} catch {
|
|
18501
|
+
return "balanced";
|
|
18502
|
+
}
|
|
16916
18503
|
}
|
|
16917
|
-
function
|
|
16918
|
-
const
|
|
16919
|
-
|
|
16920
|
-
|
|
16921
|
-
|
|
16922
|
-
|
|
18504
|
+
function run(command, opts = {}) {
|
|
18505
|
+
const timeout = opts.timeout ?? DEFAULT_TIMEOUT_SECONDS;
|
|
18506
|
+
const filter = resolveFilter(command, opts.filterName);
|
|
18507
|
+
if (filter === null) {
|
|
18508
|
+
return passthrough(command, timeout, opts.cwd, opts.env);
|
|
18509
|
+
}
|
|
18510
|
+
return wrapAndCompress(command, filter, timeout, resolveProfile(opts.compressionProfile), opts);
|
|
18511
|
+
}
|
|
18512
|
+
function runRaw(command, timeout = DEFAULT_TIMEOUT_SECONDS) {
|
|
18513
|
+
return passthrough(command, timeout, void 0, void 0);
|
|
18514
|
+
}
|
|
18515
|
+
function passthrough(command, timeout, cwd, env) {
|
|
18516
|
+
const result = spawnSync2(command, {
|
|
18517
|
+
shell: true,
|
|
18518
|
+
stdio: "inherit",
|
|
18519
|
+
timeout: timeout * 1e3,
|
|
18520
|
+
cwd,
|
|
18521
|
+
env
|
|
18522
|
+
});
|
|
18523
|
+
if (isTimeout(result.error)) return 124;
|
|
18524
|
+
if (result.status !== null) return result.status;
|
|
18525
|
+
if (result.signal) return signalExitCode(result.signal);
|
|
18526
|
+
return 0;
|
|
18527
|
+
}
|
|
18528
|
+
function isTimeout(error) {
|
|
18529
|
+
return !!error && error.code === "ETIMEDOUT";
|
|
18530
|
+
}
|
|
18531
|
+
function decode(buf) {
|
|
18532
|
+
if (buf == null) return "";
|
|
18533
|
+
return typeof buf === "string" ? buf : buf.toString("utf8");
|
|
18534
|
+
}
|
|
18535
|
+
function wrapAndCompress(command, filter, timeout, profile, opts) {
|
|
18536
|
+
const writeStdout = opts.writeStdout ?? ((s) => process.stdout.write(s));
|
|
18537
|
+
const start = Date.now();
|
|
18538
|
+
const result = spawnSync2(command, {
|
|
18539
|
+
shell: true,
|
|
18540
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
18541
|
+
timeout: timeout * 1e3,
|
|
18542
|
+
maxBuffer: MAX_CAPTURE_BYTES,
|
|
18543
|
+
cwd: opts.cwd,
|
|
18544
|
+
env: opts.env
|
|
18545
|
+
});
|
|
18546
|
+
const timedOut = isTimeout(result.error);
|
|
18547
|
+
const overflowed = !!result.error && result.error.code === "ENOBUFS";
|
|
18548
|
+
let stdoutText = decode(result.stdout);
|
|
18549
|
+
let stderrText = decode(result.stderr);
|
|
18550
|
+
if (overflowed) {
|
|
18551
|
+
stdoutText += `
|
|
18552
|
+
[token-goat: capture capped at ${MAX_CAPTURE_BYTES / (1024 * 1024)} MiB]`;
|
|
18553
|
+
}
|
|
18554
|
+
let exitCode;
|
|
18555
|
+
if (timedOut) {
|
|
18556
|
+
exitCode = 124;
|
|
18557
|
+
stderrText = (stderrText ? stderrText + "\n" : "") + `[token-goat: command exceeded ${timeout}s timeout and was killed]`;
|
|
18558
|
+
} else if (result.status !== null) {
|
|
18559
|
+
exitCode = result.status;
|
|
18560
|
+
} else if (result.signal) {
|
|
18561
|
+
exitCode = signalExitCode(result.signal);
|
|
18562
|
+
} else {
|
|
18563
|
+
exitCode = 0;
|
|
18564
|
+
}
|
|
18565
|
+
let argv;
|
|
18566
|
+
try {
|
|
18567
|
+
argv = shlexSplit(command);
|
|
18568
|
+
} catch {
|
|
18569
|
+
argv = [command];
|
|
18570
|
+
}
|
|
18571
|
+
const compressed = compressOutput(filter, stdoutText, stderrText, exitCode, argv, {
|
|
18572
|
+
compressionProfile: profile
|
|
18573
|
+
});
|
|
18574
|
+
let text = compressed.text;
|
|
18575
|
+
const maxTokens = opts.maxTokens ?? 0;
|
|
18576
|
+
if (maxTokens > 0) text = capTokens(text, maxTokens);
|
|
18577
|
+
const marker = compressed.withMarker().slice(compressed.text.length);
|
|
18578
|
+
const body = text + marker;
|
|
18579
|
+
writeStdout(body.endsWith("\n") ? body : body + "\n");
|
|
18580
|
+
recordSavings(compressed, Date.now() - start);
|
|
18581
|
+
return exitCode;
|
|
18582
|
+
}
|
|
18583
|
+
function recordSavings(result, _elapsedMs) {
|
|
18584
|
+
if (result.bytesSaved < MIN_RECORD_STAT_BYTES) return;
|
|
18585
|
+
recordStat(`bash_compress:${result.filterName}`, result.bytesSaved, result.tokensSaved);
|
|
16923
18586
|
}
|
|
16924
|
-
registerReset(() => {
|
|
16925
|
-
_byId2 = /* @__PURE__ */ new Map();
|
|
16926
|
-
_urlIndex = /* @__PURE__ */ new Map();
|
|
16927
|
-
});
|
|
16928
18587
|
|
|
16929
18588
|
// src/read_commands.ts
|
|
16930
18589
|
init_define_import_meta_env();
|
|
16931
|
-
import * as
|
|
16932
|
-
import * as
|
|
18590
|
+
import * as fs16 from "node:fs";
|
|
18591
|
+
import * as path19 from "node:path";
|
|
16933
18592
|
|
|
16934
18593
|
// src/section_reader.ts
|
|
16935
18594
|
init_define_import_meta_env();
|
|
16936
|
-
import { readFileSync as
|
|
18595
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
16937
18596
|
function parseHeadingSpec(spec) {
|
|
16938
18597
|
const m = /^(.*?)#(\d+)$/.exec(spec);
|
|
16939
18598
|
if (m !== null && m[1] !== void 0 && m[2] !== void 0) {
|
|
@@ -17027,7 +18686,7 @@ function sectionEndIndex(headers, headerPos, totalLines) {
|
|
|
17027
18686
|
function readSection(filePath, headingSpec) {
|
|
17028
18687
|
let text;
|
|
17029
18688
|
try {
|
|
17030
|
-
text =
|
|
18689
|
+
text = readFileSync12(filePath, "utf-8");
|
|
17031
18690
|
} catch {
|
|
17032
18691
|
return null;
|
|
17033
18692
|
}
|
|
@@ -17069,7 +18728,7 @@ function readSection(filePath, headingSpec) {
|
|
|
17069
18728
|
function listAllSections(filePath) {
|
|
17070
18729
|
let text;
|
|
17071
18730
|
try {
|
|
17072
|
-
text =
|
|
18731
|
+
text = readFileSync12(filePath, "utf-8");
|
|
17073
18732
|
} catch {
|
|
17074
18733
|
return [];
|
|
17075
18734
|
}
|
|
@@ -17083,7 +18742,7 @@ var DIDYOUMEAN_LIMIT = 5;
|
|
|
17083
18742
|
var GREP_MAX_LINES = 200;
|
|
17084
18743
|
function fileExists(p) {
|
|
17085
18744
|
try {
|
|
17086
|
-
|
|
18745
|
+
fs16.statSync(p);
|
|
17087
18746
|
return true;
|
|
17088
18747
|
} catch {
|
|
17089
18748
|
return false;
|
|
@@ -17091,7 +18750,7 @@ function fileExists(p) {
|
|
|
17091
18750
|
}
|
|
17092
18751
|
function readFileText(p) {
|
|
17093
18752
|
try {
|
|
17094
|
-
return
|
|
18753
|
+
return fs16.readFileSync(p, "utf-8");
|
|
17095
18754
|
} catch {
|
|
17096
18755
|
return null;
|
|
17097
18756
|
}
|
|
@@ -17385,7 +19044,7 @@ function runGrep(opts) {
|
|
|
17385
19044
|
const hits = [];
|
|
17386
19045
|
function searchFile(filePath) {
|
|
17387
19046
|
try {
|
|
17388
|
-
const text =
|
|
19047
|
+
const text = fs16.readFileSync(filePath, "utf-8");
|
|
17389
19048
|
const lines = text.split("\n");
|
|
17390
19049
|
lines.forEach((lineText, idx) => {
|
|
17391
19050
|
if (regex.test(lineText)) {
|
|
@@ -17397,10 +19056,10 @@ function runGrep(opts) {
|
|
|
17397
19056
|
}
|
|
17398
19057
|
function searchDir(dir) {
|
|
17399
19058
|
try {
|
|
17400
|
-
for (const entry of
|
|
19059
|
+
for (const entry of fs16.readdirSync(dir)) {
|
|
17401
19060
|
if (entry.startsWith(".")) continue;
|
|
17402
|
-
const full =
|
|
17403
|
-
const stat4 =
|
|
19061
|
+
const full = path19.join(dir, entry);
|
|
19062
|
+
const stat4 = fs16.statSync(full);
|
|
17404
19063
|
if (stat4.isDirectory()) {
|
|
17405
19064
|
if (opts.recursive !== false) searchDir(full);
|
|
17406
19065
|
} else {
|
|
@@ -17414,7 +19073,7 @@ function runGrep(opts) {
|
|
|
17414
19073
|
emitErr(`Path not found: ${searchPath}`);
|
|
17415
19074
|
return 1;
|
|
17416
19075
|
}
|
|
17417
|
-
const stat3 =
|
|
19076
|
+
const stat3 = fs16.statSync(searchPath);
|
|
17418
19077
|
if (stat3.isDirectory()) {
|
|
17419
19078
|
searchDir(searchPath);
|
|
17420
19079
|
} else {
|
|
@@ -17443,7 +19102,7 @@ function runConfigGet(opts) {
|
|
|
17443
19102
|
emitErr(`Could not read: ${opts.file}`);
|
|
17444
19103
|
return 1;
|
|
17445
19104
|
}
|
|
17446
|
-
const ext =
|
|
19105
|
+
const ext = path19.extname(opts.file).toLowerCase();
|
|
17447
19106
|
if (ext === ".json") {
|
|
17448
19107
|
try {
|
|
17449
19108
|
let obj = JSON.parse(text);
|
|
@@ -17465,10 +19124,22 @@ function runConfigGet(opts) {
|
|
|
17465
19124
|
return 1;
|
|
17466
19125
|
}
|
|
17467
19126
|
}
|
|
17468
|
-
const
|
|
19127
|
+
const keyParts = opts.key.split(".");
|
|
19128
|
+
const leafKey = keyParts.at(-1) ?? opts.key;
|
|
19129
|
+
const sectionPath = keyParts.length > 1 ? keyParts.slice(0, -1).join(".") : null;
|
|
17469
19130
|
const lines = text.split("\n");
|
|
19131
|
+
let currentSection = "";
|
|
17470
19132
|
for (const line of lines) {
|
|
17471
19133
|
const trimmed = line.trim();
|
|
19134
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
19135
|
+
currentSection = trimmed.slice(1, -1);
|
|
19136
|
+
continue;
|
|
19137
|
+
}
|
|
19138
|
+
if (sectionPath !== null) {
|
|
19139
|
+
if (currentSection !== sectionPath) {
|
|
19140
|
+
continue;
|
|
19141
|
+
}
|
|
19142
|
+
}
|
|
17472
19143
|
if (trimmed.startsWith(`${leafKey} =`) || trimmed.startsWith(`${leafKey}=`)) {
|
|
17473
19144
|
const eqIdx = trimmed.indexOf("=");
|
|
17474
19145
|
emit(trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, ""));
|
|
@@ -17524,7 +19195,7 @@ function runExports(opts) {
|
|
|
17524
19195
|
names.push(s.name);
|
|
17525
19196
|
}
|
|
17526
19197
|
}
|
|
17527
|
-
const ext =
|
|
19198
|
+
const ext = path19.extname(opts.file).toLowerCase();
|
|
17528
19199
|
const text = readFileText(opts.file);
|
|
17529
19200
|
if (text !== null) {
|
|
17530
19201
|
if (ext === ".go") {
|
|
@@ -17636,7 +19307,7 @@ function runImports(opts) {
|
|
|
17636
19307
|
emitErr(`Could not read: ${opts.file}`);
|
|
17637
19308
|
return 1;
|
|
17638
19309
|
}
|
|
17639
|
-
const imports = extractImports(text,
|
|
19310
|
+
const imports = extractImports(text, path19.extname(opts.file));
|
|
17640
19311
|
if (imports.length === 0) {
|
|
17641
19312
|
emit(`No imports found in '${opts.file}'`);
|
|
17642
19313
|
return 0;
|
|
@@ -17653,8 +19324,8 @@ function runImports(opts) {
|
|
|
17653
19324
|
|
|
17654
19325
|
// src/skill_cache.ts
|
|
17655
19326
|
init_define_import_meta_env();
|
|
17656
|
-
import * as
|
|
17657
|
-
import { resolve as
|
|
19327
|
+
import * as fs17 from "fs/promises";
|
|
19328
|
+
import { resolve as resolve6 } from "path";
|
|
17658
19329
|
var COMPACT_END_MARKER = "<!-- COMPACT_END -->";
|
|
17659
19330
|
var _skillOutputsDirOverride = null;
|
|
17660
19331
|
registerReset(() => {
|
|
@@ -17662,11 +19333,11 @@ registerReset(() => {
|
|
|
17662
19333
|
});
|
|
17663
19334
|
function skillOutputsDir() {
|
|
17664
19335
|
if (_skillOutputsDirOverride) return _skillOutputsDirOverride;
|
|
17665
|
-
return
|
|
19336
|
+
return resolve6(dataDir(), "skills");
|
|
17666
19337
|
}
|
|
17667
19338
|
async function ensureSkillsDir() {
|
|
17668
19339
|
try {
|
|
17669
|
-
await
|
|
19340
|
+
await fs17.mkdir(skillOutputsDir(), { recursive: true });
|
|
17670
19341
|
} catch {
|
|
17671
19342
|
}
|
|
17672
19343
|
}
|
|
@@ -17685,6 +19356,9 @@ function safeSkillName(skillName) {
|
|
|
17685
19356
|
if (!/^[A-Za-z0-9_:-]+$/.test(skillName)) return null;
|
|
17686
19357
|
return skillName.replace(/[^a-zA-Z0-9_:-]/g, "_");
|
|
17687
19358
|
}
|
|
19359
|
+
function sanitizeSkillId(name) {
|
|
19360
|
+
return name.replace(/:/g, "_");
|
|
19361
|
+
}
|
|
17688
19362
|
function extractCompactFromMarker(body) {
|
|
17689
19363
|
if (!body || !body.includes(COMPACT_END_MARKER)) {
|
|
17690
19364
|
return null;
|
|
@@ -17708,14 +19382,14 @@ function extractCompactFromMarker(body) {
|
|
|
17708
19382
|
async function listOutputs() {
|
|
17709
19383
|
try {
|
|
17710
19384
|
const dir = skillOutputsDir();
|
|
17711
|
-
const entries = await
|
|
19385
|
+
const entries = await fs17.readdir(dir, { withFileTypes: true });
|
|
17712
19386
|
const metas = [];
|
|
17713
19387
|
for (const entry of entries) {
|
|
17714
19388
|
if (!entry.isFile() || !entry.name.endsWith(".meta")) {
|
|
17715
19389
|
continue;
|
|
17716
19390
|
}
|
|
17717
19391
|
try {
|
|
17718
|
-
const content = await
|
|
19392
|
+
const content = await fs17.readFile(resolve6(dir, entry.name), "utf-8");
|
|
17719
19393
|
const meta = JSON.parse(content);
|
|
17720
19394
|
metas.push(meta);
|
|
17721
19395
|
} catch {
|
|
@@ -17733,14 +19407,14 @@ async function storeCompact(sessionId, skillName, compactText, sourceSha) {
|
|
|
17733
19407
|
const name = safeSkillName(skillName);
|
|
17734
19408
|
if (!name) return;
|
|
17735
19409
|
const safeSession = safeSessionFragment(sessionId);
|
|
17736
|
-
const fileId = `${safeSession}-${name}-compact`;
|
|
19410
|
+
const fileId = `${safeSession}-${sanitizeSkillId(name)}-compact`;
|
|
17737
19411
|
const dir = skillOutputsDir();
|
|
17738
19412
|
let text = compactText;
|
|
17739
19413
|
if (sourceSha) {
|
|
17740
19414
|
text = `<!-- source_sha: ${sourceSha.slice(0, 12)} -->
|
|
17741
19415
|
${text}`;
|
|
17742
19416
|
}
|
|
17743
|
-
await atomicWriteText(
|
|
19417
|
+
await atomicWriteText(resolve6(dir, fileId), text);
|
|
17744
19418
|
} catch {
|
|
17745
19419
|
}
|
|
17746
19420
|
}
|
|
@@ -17757,16 +19431,16 @@ async function listSkills(sessionId) {
|
|
|
17757
19431
|
seen.add(meta.skillName);
|
|
17758
19432
|
const dir = skillOutputsDir();
|
|
17759
19433
|
const safeSession = safeSessionFragment(meta.outputId.split("-")[0]);
|
|
17760
|
-
const compactFileId = `${safeSession}-${meta.skillName
|
|
19434
|
+
const compactFileId = `${safeSession}-${sanitizeSkillId(meta.skillName)}-compact`;
|
|
17761
19435
|
let compactLen = 0;
|
|
17762
19436
|
try {
|
|
17763
|
-
const stat3 = await
|
|
19437
|
+
const stat3 = await fs17.stat(resolve6(dir, compactFileId));
|
|
17764
19438
|
compactLen = stat3.size;
|
|
17765
19439
|
} catch {
|
|
17766
19440
|
compactLen = 0;
|
|
17767
19441
|
}
|
|
17768
19442
|
const hasMarker = extractCompactFromMarker(
|
|
17769
|
-
await
|
|
19443
|
+
await fs17.readFile(resolve6(dir, `${meta.outputId}.txt`), "utf-8").catch(() => "")
|
|
17770
19444
|
) !== null;
|
|
17771
19445
|
results.push({
|
|
17772
19446
|
name: meta.skillName,
|
|
@@ -17798,9 +19472,9 @@ async function getSkillFilePath(skillName) {
|
|
|
17798
19472
|
|
|
17799
19473
|
// src/cli_doctor.ts
|
|
17800
19474
|
init_define_import_meta_env();
|
|
17801
|
-
import * as
|
|
17802
|
-
import * as
|
|
17803
|
-
import { execSync, spawnSync as
|
|
19475
|
+
import * as fs18 from "fs";
|
|
19476
|
+
import * as path20 from "path";
|
|
19477
|
+
import { execSync, spawnSync as spawnSync3 } from "child_process";
|
|
17804
19478
|
function checkWorkerRunning() {
|
|
17805
19479
|
try {
|
|
17806
19480
|
const output = execSync("tasklist", { encoding: "utf-8" });
|
|
@@ -17810,8 +19484,8 @@ function checkWorkerRunning() {
|
|
|
17810
19484
|
}
|
|
17811
19485
|
}
|
|
17812
19486
|
function checkDbExists(dataDir2) {
|
|
17813
|
-
const dbPath =
|
|
17814
|
-
if (!
|
|
19487
|
+
const dbPath = path20.join(dataDir2, "index.db");
|
|
19488
|
+
if (!fs18.existsSync(dbPath)) {
|
|
17815
19489
|
return {
|
|
17816
19490
|
name: "Database",
|
|
17817
19491
|
status: "warn",
|
|
@@ -17821,7 +19495,7 @@ function checkDbExists(dataDir2) {
|
|
|
17821
19495
|
return {
|
|
17822
19496
|
name: "Database",
|
|
17823
19497
|
status: "ok",
|
|
17824
|
-
message: `index.db exists (${Math.round(
|
|
19498
|
+
message: `index.db exists (${Math.round(fs18.statSync(dbPath).size / 1024)} KB)`
|
|
17825
19499
|
};
|
|
17826
19500
|
}
|
|
17827
19501
|
function checkInstall() {
|
|
@@ -17841,7 +19515,7 @@ function checkInstall() {
|
|
|
17841
19515
|
}
|
|
17842
19516
|
}
|
|
17843
19517
|
function checkConfigValid(configPath2) {
|
|
17844
|
-
if (!
|
|
19518
|
+
if (!fs18.existsSync(configPath2)) {
|
|
17845
19519
|
return {
|
|
17846
19520
|
name: "Config",
|
|
17847
19521
|
status: "warn",
|
|
@@ -17849,7 +19523,7 @@ function checkConfigValid(configPath2) {
|
|
|
17849
19523
|
};
|
|
17850
19524
|
}
|
|
17851
19525
|
try {
|
|
17852
|
-
const content =
|
|
19526
|
+
const content = fs18.readFileSync(configPath2, "utf-8");
|
|
17853
19527
|
JSON.parse(content);
|
|
17854
19528
|
return {
|
|
17855
19529
|
name: "Config",
|
|
@@ -17866,7 +19540,7 @@ function checkConfigValid(configPath2) {
|
|
|
17866
19540
|
}
|
|
17867
19541
|
function checkDiskSpace(dataDir2) {
|
|
17868
19542
|
try {
|
|
17869
|
-
const result =
|
|
19543
|
+
const result = spawnSync3("df", ["-h", dataDir2], { encoding: "utf-8" });
|
|
17870
19544
|
const stdout = typeof result.stdout === "string" ? result.stdout : "";
|
|
17871
19545
|
if (result.error !== void 0 || result.status !== 0 || !stdout) {
|
|
17872
19546
|
return { name: "Disk Space", status: "warn", message: "could not determine" };
|
|
@@ -17887,9 +19561,9 @@ function runDoctor(dataDir2, configPath2) {
|
|
|
17887
19561
|
results.push(checkInstall());
|
|
17888
19562
|
results.push(checkWorkerRunning() ? { name: "Worker", status: "ok", message: "running" } : { name: "Worker", status: "warn", message: "not running" });
|
|
17889
19563
|
const homeDir = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
17890
|
-
const actualDataDir = dataDir2 ||
|
|
19564
|
+
const actualDataDir = dataDir2 || path20.join(homeDir, ".token-goat");
|
|
17891
19565
|
results.push(checkDbExists(actualDataDir));
|
|
17892
|
-
const actualConfigPath = configPath2 ||
|
|
19566
|
+
const actualConfigPath = configPath2 || path20.join(actualDataDir, "config.json");
|
|
17893
19567
|
results.push(checkConfigValid(actualConfigPath));
|
|
17894
19568
|
results.push(checkDiskSpace(actualDataDir));
|
|
17895
19569
|
return results;
|
|
@@ -18042,11 +19716,16 @@ function cmdSemantic(query, opts) {
|
|
|
18042
19716
|
${previewLines(s.body, 3)}`);
|
|
18043
19717
|
out(blocks.join("\n\n"));
|
|
18044
19718
|
}
|
|
18045
|
-
function cmdIndex(pathArg) {
|
|
19719
|
+
function cmdIndex(pathArg, opts = {}) {
|
|
18046
19720
|
const root = pathArg ?? process.cwd();
|
|
18047
|
-
|
|
19721
|
+
let files = getTrackedFiles(root);
|
|
18048
19722
|
if (files.length === 0) {
|
|
18049
|
-
|
|
19723
|
+
if (opts.walk !== true) {
|
|
19724
|
+
throw new CliError(
|
|
19725
|
+
`no tracked files found under '${root}' (is it a git repo?). Pass --walk to index a non-git folder.`
|
|
19726
|
+
);
|
|
19727
|
+
}
|
|
19728
|
+
files = collectWalkIndexFiles(root);
|
|
18050
19729
|
}
|
|
18051
19730
|
let indexed = 0;
|
|
18052
19731
|
for (const f of files) {
|
|
@@ -18149,11 +19828,11 @@ function cmdBashOutput(id, opts) {
|
|
|
18149
19828
|
}
|
|
18150
19829
|
let content;
|
|
18151
19830
|
try {
|
|
18152
|
-
const st =
|
|
19831
|
+
const st = fs19.statSync(opts.file);
|
|
18153
19832
|
if (st.isFIFO() || st.isSocket()) {
|
|
18154
19833
|
throw new CliError(`--file '${opts.file}' is a special file (FIFO or socket) \u2014 only regular files are supported`);
|
|
18155
19834
|
}
|
|
18156
|
-
content =
|
|
19835
|
+
content = fs19.readFileSync(opts.file, "utf-8");
|
|
18157
19836
|
} catch (e) {
|
|
18158
19837
|
if (e instanceof CliError) throw e;
|
|
18159
19838
|
throw new CliError(`cannot read file: ${opts.file}`);
|
|
@@ -18188,12 +19867,34 @@ function runExit(fn) {
|
|
|
18188
19867
|
process.exitCode = 1;
|
|
18189
19868
|
}
|
|
18190
19869
|
}
|
|
19870
|
+
function cmdCompress(opts) {
|
|
19871
|
+
try {
|
|
19872
|
+
if (opts.compress === false) {
|
|
19873
|
+
process.exitCode = runRaw(opts.cmd, parseTimeout(opts.timeout));
|
|
19874
|
+
return;
|
|
19875
|
+
}
|
|
19876
|
+
const maxTokens = opts.maxTokens ? parseInt(opts.maxTokens, 10) || 0 : 0;
|
|
19877
|
+
process.exitCode = run(opts.cmd, {
|
|
19878
|
+
filterName: opts.filter,
|
|
19879
|
+
timeout: parseTimeout(opts.timeout),
|
|
19880
|
+
maxTokens,
|
|
19881
|
+
...opts.profile !== void 0 ? { compressionProfile: opts.profile } : {}
|
|
19882
|
+
});
|
|
19883
|
+
} catch (e) {
|
|
19884
|
+
err(`token-goat: ${extractErrorMessage(e)}`);
|
|
19885
|
+
process.exitCode = 1;
|
|
19886
|
+
}
|
|
19887
|
+
}
|
|
19888
|
+
function parseTimeout(raw) {
|
|
19889
|
+
const sec = raw ? parseInt(raw, 10) : 0;
|
|
19890
|
+
return Number.isFinite(sec) && sec > 0 ? sec : DEFAULT_TIMEOUT_SECONDS;
|
|
19891
|
+
}
|
|
18191
19892
|
async function cmdSkillBody(name, opts) {
|
|
18192
19893
|
const filePath = await getSkillFilePath(name);
|
|
18193
19894
|
if (filePath === null) {
|
|
18194
19895
|
throw new CliError(`skill '${name}' not found`);
|
|
18195
19896
|
}
|
|
18196
|
-
const body =
|
|
19897
|
+
const body = fs19.readFileSync(filePath, "utf-8");
|
|
18197
19898
|
if (opts.compact === true) {
|
|
18198
19899
|
const lines = body.split("\n");
|
|
18199
19900
|
const end = lines.findIndex((l) => l.includes("COMPACT_END"));
|
|
@@ -18211,7 +19912,7 @@ async function cmdSkillCompact(name) {
|
|
|
18211
19912
|
if (filePath === null) {
|
|
18212
19913
|
throw new CliError(`skill '${name}' not found`);
|
|
18213
19914
|
}
|
|
18214
|
-
const body =
|
|
19915
|
+
const body = fs19.readFileSync(filePath, "utf-8");
|
|
18215
19916
|
const sessionFiles = getSessionFiles();
|
|
18216
19917
|
const sessionId = Array.from(sessionFiles.keys())[0] ?? "default";
|
|
18217
19918
|
await storeCompact(sessionId, name, body);
|
|
@@ -18252,7 +19953,7 @@ async function cmdSkillSize(opts) {
|
|
|
18252
19953
|
}
|
|
18253
19954
|
function atomicWriteBuffer(dest, data) {
|
|
18254
19955
|
try {
|
|
18255
|
-
if (
|
|
19956
|
+
if (fs19.statSync(dest).isDirectory()) {
|
|
18256
19957
|
const e = Object.assign(new Error(`EISDIR: illegal operation on a directory, open '${dest}'`), { code: "EISDIR", path: dest });
|
|
18257
19958
|
throw e;
|
|
18258
19959
|
}
|
|
@@ -18260,16 +19961,16 @@ function atomicWriteBuffer(dest, data) {
|
|
|
18260
19961
|
if (e.code !== "ENOENT") throw e;
|
|
18261
19962
|
}
|
|
18262
19963
|
const rnd = Math.random().toString(36).slice(2, 8);
|
|
18263
|
-
const tmp =
|
|
19964
|
+
const tmp = path21.join(path21.dirname(path21.resolve(dest)), `.tmp.${process.pid}.${rnd}`);
|
|
18264
19965
|
try {
|
|
18265
|
-
|
|
19966
|
+
fs19.writeFileSync(tmp, data, { mode: 384 });
|
|
18266
19967
|
try {
|
|
18267
|
-
|
|
19968
|
+
fs19.renameSync(tmp, dest);
|
|
18268
19969
|
} catch (e) {
|
|
18269
19970
|
if (e.code === "EXDEV") {
|
|
18270
|
-
|
|
19971
|
+
fs19.copyFileSync(tmp, dest);
|
|
18271
19972
|
try {
|
|
18272
|
-
|
|
19973
|
+
fs19.unlinkSync(tmp);
|
|
18273
19974
|
} catch (ue) {
|
|
18274
19975
|
process.stderr.write(`token-goat write-file: warning: could not remove temp file ${tmp}: ${ue.message}
|
|
18275
19976
|
`);
|
|
@@ -18280,7 +19981,7 @@ function atomicWriteBuffer(dest, data) {
|
|
|
18280
19981
|
}
|
|
18281
19982
|
} catch (e) {
|
|
18282
19983
|
try {
|
|
18283
|
-
|
|
19984
|
+
fs19.unlinkSync(tmp);
|
|
18284
19985
|
} catch {
|
|
18285
19986
|
}
|
|
18286
19987
|
throw e;
|
|
@@ -18290,9 +19991,9 @@ function mapFsError(e, src, dest) {
|
|
|
18290
19991
|
const fe = e;
|
|
18291
19992
|
if (fe.code === "ENOENT") {
|
|
18292
19993
|
const errPath = fe.path ?? "";
|
|
18293
|
-
const isSource = src !== void 0 &&
|
|
19994
|
+
const isSource = src !== void 0 && path21.resolve(errPath) === path21.resolve(src);
|
|
18294
19995
|
if (isSource) throw new CliError(`source file not found: ${src}`);
|
|
18295
|
-
const destDir = dest ?
|
|
19996
|
+
const destDir = dest ? path21.dirname(path21.resolve(dest)) : path21.dirname(path21.resolve(errPath || "."));
|
|
18296
19997
|
throw new CliError(`destination directory does not exist: ${destDir}`);
|
|
18297
19998
|
}
|
|
18298
19999
|
if (fe.code === "ENOTDIR") {
|
|
@@ -18300,7 +20001,7 @@ function mapFsError(e, src, dest) {
|
|
|
18300
20001
|
}
|
|
18301
20002
|
if (fe.code === "EISDIR") {
|
|
18302
20003
|
const errPath = fe.path ?? "";
|
|
18303
|
-
const isSource = src !== void 0 && (errPath === "" ||
|
|
20004
|
+
const isSource = src !== void 0 && (errPath === "" || path21.resolve(errPath) === path21.resolve(src));
|
|
18304
20005
|
if (isSource) throw new CliError(`source is a directory, not a file: ${src}`);
|
|
18305
20006
|
throw new CliError(`destination is a directory, not a file: ${dest ?? (errPath || "(unknown)")}`);
|
|
18306
20007
|
}
|
|
@@ -18366,7 +20067,7 @@ function cmdWriteFile(dest, opts) {
|
|
|
18366
20067
|
throw new CliError("destination path contains a null byte");
|
|
18367
20068
|
}
|
|
18368
20069
|
if (isWindows()) {
|
|
18369
|
-
const base =
|
|
20070
|
+
const base = path21.basename(dest);
|
|
18370
20071
|
const stem = base.replace(/\.[^.]*$/, "").toUpperCase();
|
|
18371
20072
|
if (WIN_RESERVED.has(stem)) {
|
|
18372
20073
|
throw new CliError(`destination '${base}' is a reserved Windows device name`);
|
|
@@ -18389,7 +20090,7 @@ function cmdWriteFile(dest, opts) {
|
|
|
18389
20090
|
throw new CliError("--from /dev/stdin requires piped input; use piped stdin mode or --b64 for interactive use");
|
|
18390
20091
|
}
|
|
18391
20092
|
try {
|
|
18392
|
-
const st =
|
|
20093
|
+
const st = fs19.statSync(opts.from);
|
|
18393
20094
|
if (st.isFIFO() || st.isSocket()) {
|
|
18394
20095
|
throw new CliError(`--from '${opts.from}' is a special file (FIFO or socket) \u2014 only regular files are supported`);
|
|
18395
20096
|
}
|
|
@@ -18401,7 +20102,7 @@ function cmdWriteFile(dest, opts) {
|
|
|
18401
20102
|
if (st.size > maxFromBytes) {
|
|
18402
20103
|
throw new CliError(`--from source exceeds size limit (${Math.round(st.size / 1024 / 1024)} MB); set TOKEN_GOAT_MAX_STDIN_MB to override`);
|
|
18403
20104
|
}
|
|
18404
|
-
atomicWriteBuffer(dest,
|
|
20105
|
+
atomicWriteBuffer(dest, fs19.readFileSync(opts.from));
|
|
18405
20106
|
} catch (e) {
|
|
18406
20107
|
if (e instanceof CliError) throw e;
|
|
18407
20108
|
mapFsError(e, opts.from, dest);
|
|
@@ -18443,7 +20144,7 @@ function cmdWriteFile(dest, opts) {
|
|
|
18443
20144
|
throw new CliError(`TOKEN_GOAT_MAX_STDIN_MB must be a positive integer; got '${process.env["TOKEN_GOAT_MAX_STDIN_MB"] ?? ""}'`);
|
|
18444
20145
|
}
|
|
18445
20146
|
const maxBytes = maxMB * 1024 * 1024;
|
|
18446
|
-
return new Promise((
|
|
20147
|
+
return new Promise((resolve8, reject) => {
|
|
18447
20148
|
const chunks = [];
|
|
18448
20149
|
let totalBytes = 0;
|
|
18449
20150
|
let settled = false;
|
|
@@ -18466,7 +20167,7 @@ function cmdWriteFile(dest, opts) {
|
|
|
18466
20167
|
cleanup();
|
|
18467
20168
|
try {
|
|
18468
20169
|
atomicWriteBuffer(dest, Buffer.concat(chunks));
|
|
18469
|
-
|
|
20170
|
+
resolve8();
|
|
18470
20171
|
} catch (e) {
|
|
18471
20172
|
try {
|
|
18472
20173
|
mapFsError(e, void 0, dest);
|
|
@@ -18569,7 +20270,7 @@ function buildProgram() {
|
|
|
18569
20270
|
})
|
|
18570
20271
|
)
|
|
18571
20272
|
);
|
|
18572
|
-
program2.command("index [path]").description("parse all git-tracked files and (re)build the symbol index").action(guard(cmdIndex));
|
|
20273
|
+
program2.command("index [path]").description("parse all git-tracked files and (re)build the symbol index").option("--walk", "if not a git repo, index a bounded directory walk instead (skips .env / generated / oversized trees)").action(guard(cmdIndex));
|
|
18573
20274
|
program2.command("map").description("project overview").option("-c, --compact", "compact, low-token summary").action(guard(cmdMap));
|
|
18574
20275
|
program2.command("hook <event>").description("hook relay entrypoint (reads JSON on stdin)").action(guard(cmdHook));
|
|
18575
20276
|
program2.command("install").description("install hooks into Claude Code settings").option("-p, --project", "install into project scope instead of user scope").action(guard(cmdInstall));
|
|
@@ -18624,6 +20325,7 @@ function buildProgram() {
|
|
|
18624
20325
|
program2.command("config-get <file> <key>").description("read one value from a config file (TOML/JSON/YAML/INI)").action((file, key) => runExit(() => runConfigGet({ file, key })));
|
|
18625
20326
|
program2.command("write-file <dest>").description("write exact bytes to a file \u2014 handles backticks, quotes, $vars, CRLF without escaping\n\nModes: --b64 PAYLOAD (base64), --from SOURCE (copy file), or piped stdin").option("--from <source>", "copy bytes from this source file instead of stdin/base64").option("--b64 <payload>", "decode base64 payload and write to dest").action(guard(cmdWriteFile));
|
|
18626
20327
|
program2.command("gdrive-sections <file-id>").description("fetch and list sections from a public Google Doc").option("--heading <name>", "get content of one named section").action(guard(cmdGdriveSections));
|
|
20328
|
+
program2.command("compress").description("run a shell command and emit a compressed view of its output").requiredOption("-c, --cmd <command>", "the shell command to run, as one string").option("-f, --filter <name>", "filter name (auto-detected from the command when omitted)").option("--timeout <seconds>", "wall-clock timeout in seconds (0 = built-in default)").option("--no-compress", "stream output raw without compression (debug the wrapper)").option("--profile <name>", "compression profile: aggressive | balanced | minimal").option("--max-tokens <n>", "post-compress token cap (0 = no cap)").action(cmdCompress);
|
|
18627
20329
|
program2.command("version").description("print the token-goat version").action(
|
|
18628
20330
|
guard(() => {
|
|
18629
20331
|
out(VERSION);
|
|
@@ -18631,7 +20333,7 @@ function buildProgram() {
|
|
|
18631
20333
|
);
|
|
18632
20334
|
return program2;
|
|
18633
20335
|
}
|
|
18634
|
-
async function
|
|
20336
|
+
async function run2(argv = process.argv) {
|
|
18635
20337
|
const program2 = buildProgram();
|
|
18636
20338
|
program2.exitOverride();
|
|
18637
20339
|
try {
|
|
@@ -18653,7 +20355,7 @@ async function run(argv = process.argv) {
|
|
|
18653
20355
|
}
|
|
18654
20356
|
|
|
18655
20357
|
// src/main.ts
|
|
18656
|
-
void
|
|
20358
|
+
void run2();
|
|
18657
20359
|
/*! Bundled license information:
|
|
18658
20360
|
|
|
18659
20361
|
smol-toml/dist/date.js:
|