token-goat 2.8.3 → 2.8.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/README.md +14 -12
- package/dist/{token-goat-chunk-PWVXXPCC.mjs → token-goat-chunk-4OTIB7SB.mjs} +450 -138
- package/dist/{token-goat-chunk-EFF2XCLB.mjs → token-goat-chunk-CZALRRGN.mjs} +175 -56
- package/dist/{token-goat-chunk-6ODZ6PZK.mjs → token-goat-chunk-E76UNTVK.mjs} +189 -69
- package/dist/{token-goat-chunk-4OM2Q2SX.mjs → token-goat-chunk-HNODKNWO.mjs} +5 -5
- package/dist/{token-goat-chunk-4HIMCBYK.mjs → token-goat-chunk-IZRXU64B.mjs} +51 -4
- package/dist/{token-goat-chunk-DP3NNGGV.mjs → token-goat-chunk-L6YP6FKQ.mjs} +5 -5
- package/dist/{token-goat-chunk-C5IL6MJH.mjs → token-goat-chunk-LZOAPGWR.mjs} +6 -5
- package/dist/{token-goat-chunk-VAGPOZHO.mjs → token-goat-chunk-NZFTWBGV.mjs} +2 -2
- package/dist/{token-goat-chunk-TX4JFJTD.mjs → token-goat-chunk-RE7S7H26.mjs} +110 -50
- package/dist/{token-goat-chunk-222VPFP2.mjs → token-goat-chunk-U4UI5F3S.mjs} +953 -188
- package/dist/{token-goat-chunk-NKNCHJ4H.mjs → token-goat-chunk-ZQ3PUOP3.mjs} +310 -109
- package/dist/token-goat-hook.mjs +5 -5
- package/dist/token-goat.core.mjs +5 -5
- package/package.json +3 -1
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { createRequire } from "node:module";
|
|
9
9
|
function resolveVersion() {
|
|
10
10
|
if (true) {
|
|
11
|
-
return "2.8.
|
|
11
|
+
return "2.8.4";
|
|
12
12
|
}
|
|
13
13
|
const require2 = createRequire(import.meta.url);
|
|
14
14
|
const pkg = require2("../package.json");
|
|
@@ -263,6 +263,16 @@ function lowercaseDriveLetter(s) {
|
|
|
263
263
|
}
|
|
264
264
|
var EXTENDED_UNC_PREFIX_RE = /^\\\\\?\\UNC\\/i;
|
|
265
265
|
var EXTENDED_PREFIX_RE = /^\\\\\?\\/;
|
|
266
|
+
function shellMountToWindowsPath(p) {
|
|
267
|
+
const s = p.includes("\\") ? p.replace(/\\/g, "/") : p;
|
|
268
|
+
const m = WSL_PATH_RE.exec(s);
|
|
269
|
+
if (m) return `${m[1].toLowerCase()}:/${m[2].replace(/^\/+/, "")}`;
|
|
270
|
+
if (process.platform === "win32") {
|
|
271
|
+
const g = MSYS_PATH_RE.exec(s);
|
|
272
|
+
if (g) return `${g[1].toLowerCase()}:${g[2] ?? "/"}`;
|
|
273
|
+
}
|
|
274
|
+
return s;
|
|
275
|
+
}
|
|
266
276
|
function normalizePath(p) {
|
|
267
277
|
let s = p;
|
|
268
278
|
if (EXTENDED_UNC_PREFIX_RE.test(s)) {
|
|
@@ -270,20 +280,7 @@ function normalizePath(p) {
|
|
|
270
280
|
} else if (EXTENDED_PREFIX_RE.test(s)) {
|
|
271
281
|
s = s.slice(4);
|
|
272
282
|
}
|
|
273
|
-
|
|
274
|
-
s = s.replace(/\\/g, "/");
|
|
275
|
-
}
|
|
276
|
-
const m = WSL_PATH_RE.exec(s);
|
|
277
|
-
if (m) {
|
|
278
|
-
const driveLetter = m[1].toLowerCase();
|
|
279
|
-
const rest = m[2];
|
|
280
|
-
const restStripped = rest.replace(/^\/+/, "");
|
|
281
|
-
s = `${driveLetter}:/${restStripped}`;
|
|
282
|
-
}
|
|
283
|
-
if (process.platform === "win32") {
|
|
284
|
-
const g = MSYS_PATH_RE.exec(s);
|
|
285
|
-
if (g) s = `${g[1].toLowerCase()}:${g[2] ?? "/"}`;
|
|
286
|
-
}
|
|
283
|
+
s = shellMountToWindowsPath(s);
|
|
287
284
|
s = expandShortPath(s);
|
|
288
285
|
s = lowercaseDriveLetter(s);
|
|
289
286
|
s = normalizeDarwinSystemAlias(s);
|
|
@@ -297,8 +294,10 @@ function normalizeDarwinSystemAlias(p) {
|
|
|
297
294
|
}
|
|
298
295
|
function resolveIndexPath(file, base = process.cwd()) {
|
|
299
296
|
const isWindowsAbsolute = (s) => /^[a-zA-Z]:[/\\]/.test(s);
|
|
300
|
-
const
|
|
301
|
-
|
|
297
|
+
const f = shellMountToWindowsPath(file);
|
|
298
|
+
const b = shellMountToWindowsPath(base);
|
|
299
|
+
const resolve5 = isWindowsAbsolute(f) || isWindowsAbsolute(b) ? path2.win32.resolve : path2.resolve;
|
|
300
|
+
return normalizePath(resolve5(b, f));
|
|
302
301
|
}
|
|
303
302
|
function toDisplayPath(root, target) {
|
|
304
303
|
if (root === void 0) return target;
|
|
@@ -759,6 +758,14 @@ function grepFilteredToEmptyNotice(preFilterCount, grep, nounSingular, nounPlura
|
|
|
759
758
|
const pronoun = preFilterCount === 1 ? "it" : "them";
|
|
760
759
|
return ` (all ${preFilterCount} ${noun} ${verb} filtered out by --grep ${grep} -- widen or drop the filter to see ${pronoun})`;
|
|
761
760
|
}
|
|
761
|
+
function filtersFilteredToEmptyNotice(preFilterCount, activeFilters, nounSingular, nounPlural, reassurance) {
|
|
762
|
+
const noun = preFilterCount === 1 ? nounSingular : nounPlural;
|
|
763
|
+
const cause = activeFilters.length === 0 ? "the active filter" : activeFilters.join(" + ");
|
|
764
|
+
const knob = activeFilters.length > 1 ? "filters" : "filter";
|
|
765
|
+
const verb = preFilterCount === 1 ? "was" : "were";
|
|
766
|
+
const tail = reassurance === void 0 ? "" : `; ${reassurance}`;
|
|
767
|
+
return ` (all ${preFilterCount} ${noun} ${verb} filtered out by ${cause}${tail} -- widen or drop the ${knob} to see them)`;
|
|
768
|
+
}
|
|
762
769
|
function countNoun(count, singular, plural = `${singular}s`) {
|
|
763
770
|
return `${count} ${count === 1 ? singular : plural}`;
|
|
764
771
|
}
|
|
@@ -2161,7 +2168,15 @@ var CONFIG_DEFAULTS = {
|
|
|
2161
2168
|
// 85+, while a photo with an incidental sign or logo in frame scores much lower and
|
|
2162
2169
|
// noisier -- padding the threshold below the terminal/code norm still comfortably
|
|
2163
2170
|
// excludes photographic false positives without needing a second heuristic.
|
|
2164
|
-
ocr_min_confidence: 65
|
|
2171
|
+
ocr_min_confidence: 65,
|
|
2172
|
+
// Which resolution tier the model being shown the image is on, which decides what its pixels
|
|
2173
|
+
// cost. 'standard' (1568px long edge, 1568 visual tokens) is every model before Claude 4.7;
|
|
2174
|
+
// 'high' (2576px, 4784 tokens) is 4.7 and later, and bills the same large image up to roughly
|
|
2175
|
+
// three times higher. Only the saving *reported* by `token-goat stats` depends on this -- no
|
|
2176
|
+
// image is encoded differently -- and 'standard' is the default because it is the floor: it
|
|
2177
|
+
// caps the counterfactual at the smaller of the two bills and so can never credit a saving
|
|
2178
|
+
// that was not there. Set it to 'high' on a Claude 4.7+ model to see the larger real figure.
|
|
2179
|
+
vision_tier: "standard"
|
|
2165
2180
|
},
|
|
2166
2181
|
screenshot: {
|
|
2167
2182
|
chrome_path: "",
|
|
@@ -2321,6 +2336,9 @@ function validatedFloat(raw, def, min, max) {
|
|
|
2321
2336
|
if (!Number.isFinite(n)) return def;
|
|
2322
2337
|
return Math.max(min, Math.min(max, n));
|
|
2323
2338
|
}
|
|
2339
|
+
function validatedVisionTier(raw, def) {
|
|
2340
|
+
return raw === "standard" || raw === "high" ? raw : def;
|
|
2341
|
+
}
|
|
2324
2342
|
function validatedStr(raw, def) {
|
|
2325
2343
|
return typeof raw === "string" ? raw : def;
|
|
2326
2344
|
}
|
|
@@ -2684,6 +2702,8 @@ function mergeRawConfig(base, override) {
|
|
|
2684
2702
|
const baseSection = baseVal !== null && typeof baseVal === "object" && !Array.isArray(baseVal) ? baseVal : {};
|
|
2685
2703
|
merged[key] = { ...baseSection, ...overrideVal };
|
|
2686
2704
|
} else {
|
|
2705
|
+
const baseVal = base[key];
|
|
2706
|
+
if (baseVal !== null && typeof baseVal === "object" && !Array.isArray(baseVal)) continue;
|
|
2687
2707
|
merged[key] = overrideVal;
|
|
2688
2708
|
}
|
|
2689
2709
|
}
|
|
@@ -2877,8 +2897,10 @@ function _buildConfig(raw, projectRaw = {}) {
|
|
|
2877
2897
|
is_cfg.screenshot_redirect = validatedBool(is_raw["screenshot_redirect"], is_cfg.screenshot_redirect);
|
|
2878
2898
|
is_cfg.ocr_enabled = validatedBool(is_raw["ocr_enabled"], is_cfg.ocr_enabled);
|
|
2879
2899
|
is_cfg.ocr_min_confidence = validatedInt(is_raw["ocr_min_confidence"], is_cfg.ocr_min_confidence, ...boundsOf("image_shrink.ocr_min_confidence"));
|
|
2900
|
+
is_cfg.vision_tier = validatedVisionTier(is_raw["vision_tier"], is_cfg.vision_tier);
|
|
2880
2901
|
is_cfg.max_image_pixels = envInt("TOKEN_GOAT_MAX_IMAGE_PIXELS", is_cfg.max_image_pixels, ...boundsOf("image_shrink.max_image_pixels"));
|
|
2881
2902
|
is_cfg.ocr_enabled = envBool("TOKEN_GOAT_OCR_ENABLED", is_cfg.ocr_enabled);
|
|
2903
|
+
is_cfg.vision_tier = validatedVisionTier(process.env["TOKEN_GOAT_VISION_TIER"], is_cfg.vision_tier);
|
|
2882
2904
|
const sc_raw = section(raw, "screenshot");
|
|
2883
2905
|
const sc_cfg = getDefaultConfig("screenshot");
|
|
2884
2906
|
sc_cfg.chrome_path = validatedStr(sc_raw["chrome_path"], sc_cfg.chrome_path);
|
|
@@ -3077,6 +3099,7 @@ var CONFIG_KEY_ENV_OVERRIDES = {
|
|
|
3077
3099
|
"skill_preservation.orphan_sweep_enabled": ["TOKEN_GOAT_ORPHAN_SWEEP"],
|
|
3078
3100
|
"image_shrink.max_image_pixels": ["TOKEN_GOAT_MAX_IMAGE_PIXELS"],
|
|
3079
3101
|
"image_shrink.ocr_enabled": ["TOKEN_GOAT_OCR_ENABLED"],
|
|
3102
|
+
"image_shrink.vision_tier": ["TOKEN_GOAT_VISION_TIER"],
|
|
3080
3103
|
"screenshot.block_private_targets": ["TOKEN_GOAT_SCREENSHOT_BLOCK_PRIVATE_TARGETS"],
|
|
3081
3104
|
"repomap.compact_file_threshold": ["TOKEN_GOAT_REPOMAP_COMPACT_THRESHOLD"],
|
|
3082
3105
|
"repomap.exclude_tests": ["TOKEN_GOAT_REPOMAP_EXCLUDE_TESTS"],
|
|
@@ -3199,7 +3222,8 @@ function saveConfig(config) {
|
|
|
3199
3222
|
max_image_pixels: is_cfg.max_image_pixels,
|
|
3200
3223
|
screenshot_redirect: is_cfg.screenshot_redirect,
|
|
3201
3224
|
ocr_enabled: is_cfg.ocr_enabled,
|
|
3202
|
-
ocr_min_confidence: is_cfg.ocr_min_confidence
|
|
3225
|
+
ocr_min_confidence: is_cfg.ocr_min_confidence,
|
|
3226
|
+
vision_tier: is_cfg.vision_tier
|
|
3203
3227
|
},
|
|
3204
3228
|
screenshot: {
|
|
3205
3229
|
chrome_path: config.screenshot.chrome_path,
|
|
@@ -4175,9 +4199,11 @@ function makeSymbolEmitter(symbols, sections, seen, filePath, maxSymbols = 500,
|
|
|
4175
4199
|
}
|
|
4176
4200
|
function assignFlatEndLines(sections, totalLines) {
|
|
4177
4201
|
for (let i = 0; i < sections.length; i++) {
|
|
4178
|
-
const next = sections[i + 1];
|
|
4179
4202
|
const s = sections[i];
|
|
4180
4203
|
if (s === void 0) continue;
|
|
4204
|
+
let j = i + 1;
|
|
4205
|
+
while (j < sections.length && (sections[j]?.line ?? 0) <= s.line) j++;
|
|
4206
|
+
const next = sections[j];
|
|
4181
4207
|
const end = next !== void 0 ? next.line - 1 : totalLines;
|
|
4182
4208
|
s.endLine = end < s.line ? s.line : end;
|
|
4183
4209
|
}
|
|
@@ -4472,6 +4498,7 @@ function findBlockOpenBrace(content, lineIndex, startLine, lastSearchLine, lineC
|
|
|
4472
4498
|
else if (ch === ")" || ch === "]") {
|
|
4473
4499
|
if (parenDepth > 0) parenDepth--;
|
|
4474
4500
|
} else if (ch === ";") return null;
|
|
4501
|
+
else if (ch === "}" && parenDepth === 0) return null;
|
|
4475
4502
|
else if (ch === "{") return i;
|
|
4476
4503
|
}
|
|
4477
4504
|
return null;
|
|
@@ -4567,8 +4594,9 @@ function extractEnv(content, filePath) {
|
|
|
4567
4594
|
if (_lineClosesQuote(line, openQuote)) openQuote = null;
|
|
4568
4595
|
continue;
|
|
4569
4596
|
}
|
|
4570
|
-
|
|
4571
|
-
|
|
4597
|
+
const trimmed = line.replace(/^[ \t]+/, "");
|
|
4598
|
+
if (!trimmed || trimmed[0] === "#" || trimmed[0] === ";") continue;
|
|
4599
|
+
const m = ENV_KEY_RE.exec(trimmed);
|
|
4572
4600
|
if (m === null) continue;
|
|
4573
4601
|
const name = m[1]?.trim() ?? "";
|
|
4574
4602
|
if (!name || name.length > MAX_HEADING_LEN) continue;
|
|
@@ -4576,7 +4604,7 @@ function extractEnv(content, filePath) {
|
|
|
4576
4604
|
if (seen.has(key)) continue;
|
|
4577
4605
|
seen.add(key);
|
|
4578
4606
|
symbols.push(makeLineSymbol(filePath, name, "env_key", i + 1));
|
|
4579
|
-
openQuote = _detectOpenQuote(
|
|
4607
|
+
openQuote = _detectOpenQuote(trimmed.slice(m[0].length));
|
|
4580
4608
|
}
|
|
4581
4609
|
return symbols;
|
|
4582
4610
|
}
|
|
@@ -4955,7 +4983,8 @@ CREATE TABLE IF NOT EXISTS files (
|
|
|
4955
4983
|
language TEXT,
|
|
4956
4984
|
indexed_at REAL,
|
|
4957
4985
|
embed_sha TEXT,
|
|
4958
|
-
retry_count INTEGER NOT NULL DEFAULT 0
|
|
4986
|
+
retry_count INTEGER NOT NULL DEFAULT 0,
|
|
4987
|
+
parser_sha TEXT
|
|
4959
4988
|
);
|
|
4960
4989
|
-- Expression index on TG_LOWER(path) -- see pathEqClause (sql_path.ts) and TG_LOWER's
|
|
4961
4990
|
-- registration above. TG_LOWER is registered { deterministic: true }, which is required for
|
|
@@ -5215,7 +5244,7 @@ CREATE TRIGGER IF NOT EXISTS cache_recall_au AFTER UPDATE ON cache_recall BEGIN
|
|
|
5215
5244
|
VALUES (new.row_id, new.label, new.content);
|
|
5216
5245
|
END;
|
|
5217
5246
|
`;
|
|
5218
|
-
var SCHEMA_VERSION =
|
|
5247
|
+
var SCHEMA_VERSION = 13;
|
|
5219
5248
|
function alterTableIdempotent(conn, sql) {
|
|
5220
5249
|
try {
|
|
5221
5250
|
conn.exec(sql);
|
|
@@ -5259,7 +5288,9 @@ var MIGRATIONS = {
|
|
|
5259
5288
|
// .env would have kept serving its pre-fix chunks indefinitely. Deleting the rows here both
|
|
5260
5289
|
// removes the stored secrets and, by clearing embed_sha, makes the next drain re-embed the file
|
|
5261
5290
|
// through the redacting path.
|
|
5262
|
-
10: purgeDotenvEmbeddings
|
|
5291
|
+
10: purgeDotenvEmbeddings,
|
|
5292
|
+
// v12 -> v13: adds files.parser_sha, the digest of the extraction logic that produced this file's rows, tracked separately from files.sha for the same reason embed_sha is -- content freshness and parse freshness are different questions, and the content sha alone could only ever answer the first. A pre-existing v12 database's `files` table predates the column, so it needs an explicit ALTER TABLE here; a brand-new database already has it from SCHEMA_SQL's CREATE TABLE above, so the ALTER TABLE would fail with "duplicate column name" there -- swallow exactly that error and rethrow anything else, same pattern as v1 -> v2 / v2 -> v3 / v8 -> v9 / v9 -> v10 above. Deliberately left NULL for every existing row rather than backfilled with the current fingerprint: NULL is the truthful answer (nobody recorded which parser wrote those rows), and it is also the answer that makes the freshness gates reparse them once, which is exactly what a database indexed by an older parser needs.
|
|
5293
|
+
12: (conn) => alterTableIdempotent(conn, "ALTER TABLE files ADD COLUMN parser_sha TEXT")
|
|
5263
5294
|
};
|
|
5264
5295
|
function runMigrations(conn, fromVersion, toVersion) {
|
|
5265
5296
|
for (let v = fromVersion; v < toVersion; v++) {
|
|
@@ -5745,7 +5776,51 @@ var _KIND_GROUPS = [
|
|
|
5745
5776
|
"exports",
|
|
5746
5777
|
"imports",
|
|
5747
5778
|
"changed_lookup",
|
|
5748
|
-
"dep_docs"
|
|
5779
|
+
"dep_docs",
|
|
5780
|
+
// Every other SOURCE_READ kind in stats.ts's KIND_TO_SOURCE: the surgical-read commands over documents, structured data and session/PR state. They were registered and produced but grouped nowhere, so `stats --full` printed the whole family under 'Other', away from the read-savings siblings they are measured against. image_meta/image_text sit here rather than under 'Images' because stats.ts files them as SOURCE_READ: they save read bytes, they do not shrink an image.
|
|
5781
|
+
"brief_view",
|
|
5782
|
+
"conflicts",
|
|
5783
|
+
"coverage_report_gaps",
|
|
5784
|
+
"csv_query",
|
|
5785
|
+
"csv_profile",
|
|
5786
|
+
"compact_doc",
|
|
5787
|
+
"docx_outline",
|
|
5788
|
+
"docx_text",
|
|
5789
|
+
"gdrive_sections",
|
|
5790
|
+
"image_meta",
|
|
5791
|
+
"image_text",
|
|
5792
|
+
"json_query",
|
|
5793
|
+
"json_outline",
|
|
5794
|
+
"note_read",
|
|
5795
|
+
"note_list",
|
|
5796
|
+
"openapi_op",
|
|
5797
|
+
"openapi_outline",
|
|
5798
|
+
"pdf_extract",
|
|
5799
|
+
"pdf_locate",
|
|
5800
|
+
"pdf_outline",
|
|
5801
|
+
"pdf_meta",
|
|
5802
|
+
"pptx_outline",
|
|
5803
|
+
"pptx_slide",
|
|
5804
|
+
"pptx_notes",
|
|
5805
|
+
"pptx_text",
|
|
5806
|
+
"pr_slice",
|
|
5807
|
+
"session_outline",
|
|
5808
|
+
"session_slice",
|
|
5809
|
+
"sqlite_query",
|
|
5810
|
+
"sqlite_schema",
|
|
5811
|
+
"transcript",
|
|
5812
|
+
"transcript_outline",
|
|
5813
|
+
"video_chapters",
|
|
5814
|
+
"xlsx_sheets",
|
|
5815
|
+
"xlsx_head",
|
|
5816
|
+
"xlsx_range",
|
|
5817
|
+
"xlsx_query",
|
|
5818
|
+
"xml_query",
|
|
5819
|
+
"xml_outline",
|
|
5820
|
+
"yaml_query",
|
|
5821
|
+
"yaml_outline",
|
|
5822
|
+
"zip_list",
|
|
5823
|
+
"zip_read"
|
|
5749
5824
|
])
|
|
5750
5825
|
},
|
|
5751
5826
|
{ label: "Lookups", members: /* @__PURE__ */ new Set(["symbol_lookup", "semantic_search", "map_lookup"]) },
|
|
@@ -5767,74 +5842,72 @@ var _KIND_GROUPS = [
|
|
|
5767
5842
|
"session_hint_overhead",
|
|
5768
5843
|
"session_hint_suppressed",
|
|
5769
5844
|
"read_count_deny",
|
|
5770
|
-
"read_dedup_hint",
|
|
5771
5845
|
"grep_dedup_hint",
|
|
5772
5846
|
"glob_dedup_hint",
|
|
5773
5847
|
"diff_hint",
|
|
5774
5848
|
"predictive_prefetch_hit",
|
|
5775
|
-
"read_partial_overlap_hint",
|
|
5776
5849
|
"structured_file_hint",
|
|
5777
5850
|
"write_rewrite_hint",
|
|
5778
5851
|
"websearch_dedup_hint",
|
|
5779
5852
|
"large_file_hint_followed",
|
|
5780
|
-
"large_file_hint_ignored"
|
|
5781
|
-
|
|
5782
|
-
},
|
|
5783
|
-
{
|
|
5784
|
-
label: "Bash",
|
|
5785
|
-
members: /* @__PURE__ */ new Set([
|
|
5786
|
-
"bash_dedup_hint",
|
|
5787
|
-
"bash_output_cached",
|
|
5788
|
-
"bash_output_recall",
|
|
5789
|
-
"bash_output_recall_miss",
|
|
5790
|
-
"bash_dedup_stale",
|
|
5791
|
-
"bash_range_read_hint",
|
|
5792
|
-
"bash_streak_hint",
|
|
5793
|
-
"bash_poll_hint",
|
|
5794
|
-
"env_probe_cache_hit",
|
|
5795
|
-
"git_diff_scope_hint",
|
|
5796
|
-
"dep_list_cache_hit",
|
|
5797
|
-
"bash_read_equiv_already_read",
|
|
5798
|
-
"bash_grep_result_cache_hit",
|
|
5799
|
-
"git_diff_context_trimmed"
|
|
5853
|
+
"large_file_hint_ignored",
|
|
5854
|
+
"evidence_cache_hit"
|
|
5800
5855
|
])
|
|
5801
5856
|
},
|
|
5857
|
+
// Empty for the same reason as MCP below: every live Bash kind arrives through _kindGroupLabel's `bash_compress:` prefix branch, not through a literal name. The fifteen literal names this set used to carry (bash_output_cached, bash_dedup_hint, env_probe_cache_hit and the rest) came over with the Python port and were never recorded or registered anywhere in this tree, so they grouped rows that could not exist.
|
|
5858
|
+
{ label: "Bash", members: /* @__PURE__ */ new Set() },
|
|
5802
5859
|
{
|
|
5803
5860
|
label: "Web",
|
|
5804
5861
|
members: /* @__PURE__ */ new Set([
|
|
5805
|
-
"web_dedup_hint",
|
|
5806
|
-
"web_output_cached",
|
|
5807
|
-
"web_output_recall",
|
|
5808
|
-
"web_output_recall_miss",
|
|
5809
|
-
"web_dedup_stale",
|
|
5810
5862
|
"web_fetch",
|
|
5811
5863
|
"injection_detected"
|
|
5812
5864
|
])
|
|
5813
5865
|
},
|
|
5866
|
+
// Membership comes from _kindGroupLabel's `mcp:` prefix branch, not from this set, which is why
|
|
5867
|
+
// it is empty. The entry still has to exist: _renderByKindSection iterates _KIND_GROUPS' labels
|
|
5868
|
+
// (plus 'Other') to decide what to print, so a label _kindGroupLabel returns but that is missing
|
|
5869
|
+
// here does not fall back to 'Other' -- its rows disappear from the table entirely.
|
|
5870
|
+
{ label: "MCP", members: /* @__PURE__ */ new Set() },
|
|
5814
5871
|
{
|
|
5815
5872
|
label: "Compact / Skills",
|
|
5816
5873
|
members: /* @__PURE__ */ new Set([
|
|
5817
|
-
"compact_manifest",
|
|
5818
|
-
"compact_assist",
|
|
5819
|
-
"compact_recovery",
|
|
5820
|
-
"skill_body_recall",
|
|
5821
|
-
"skill_compact_served",
|
|
5822
|
-
"skill_cached",
|
|
5823
5874
|
"skill_load",
|
|
5824
5875
|
"skill_oversized_first_load",
|
|
5825
|
-
"skill_compact_inlined"
|
|
5826
|
-
|
|
5827
|
-
|
|
5876
|
+
"skill_compact_inlined"
|
|
5877
|
+
])
|
|
5878
|
+
},
|
|
5879
|
+
// SOURCE_CONTENT: real rewrites of tool output that remove real bytes (agent report compaction, Grep fold, browser tab dedup, bash/content compression and the handoff pair). The by-source table has shown a 'content' row since the source was added, but the by-kind table had no member set for it, so every one of these kinds printed under 'Other'. The taskoutput: prefix branch in _kindGroupLabel routes here too.
|
|
5880
|
+
{
|
|
5881
|
+
label: "Content",
|
|
5882
|
+
members: /* @__PURE__ */ new Set([
|
|
5883
|
+
"content_compress",
|
|
5884
|
+
"content_retrieve",
|
|
5885
|
+
"agent_report_compact",
|
|
5886
|
+
"agent_report_compact_declined",
|
|
5887
|
+
"browser_tab_dedup",
|
|
5888
|
+
"grep:fold",
|
|
5889
|
+
"handoff_create",
|
|
5890
|
+
"handoff_resolve",
|
|
5891
|
+
"plan_echo_collapse"
|
|
5828
5892
|
])
|
|
5829
5893
|
}
|
|
5830
5894
|
];
|
|
5831
5895
|
function _kindGroupLabel(kind) {
|
|
5832
|
-
if (kind.startsWith("bash_compress:")) {
|
|
5896
|
+
if (kind.startsWith("bash_compress:") || kind.startsWith("bashoutput:")) {
|
|
5833
5897
|
return "Bash";
|
|
5834
5898
|
}
|
|
5835
|
-
if (kind.startsWith("webfetch:")) {
|
|
5899
|
+
if (kind.startsWith("webfetch:") || kind.startsWith("gdrive:")) {
|
|
5836
5900
|
return "Web";
|
|
5837
5901
|
}
|
|
5902
|
+
if (kind.startsWith("mcp:")) {
|
|
5903
|
+
return "MCP";
|
|
5904
|
+
}
|
|
5905
|
+
if (kind.startsWith("skill_body:") || kind.startsWith("skill_compact:")) {
|
|
5906
|
+
return "Compact / Skills";
|
|
5907
|
+
}
|
|
5908
|
+
if (kind.startsWith("taskoutput:")) {
|
|
5909
|
+
return "Content";
|
|
5910
|
+
}
|
|
5838
5911
|
for (const group of _KIND_GROUPS) {
|
|
5839
5912
|
if (group.members.has(kind)) {
|
|
5840
5913
|
return group.label;
|
|
@@ -6138,6 +6211,10 @@ var SOURCE_SKILL = "skill";
|
|
|
6138
6211
|
var SOURCE_CONTENT = "content";
|
|
6139
6212
|
var SOURCE_OTHER = "other";
|
|
6140
6213
|
var _BYTES_MODE_ONLY_KINDS = /* @__PURE__ */ new Set(["webfetch_image", "gdrive_image"]);
|
|
6214
|
+
var COUNT_ONLY_KINDS = /* @__PURE__ */ new Set(["secret_redacted"]);
|
|
6215
|
+
function savedTokensFromBytes(bytes) {
|
|
6216
|
+
return Math.round(Math.max(0, bytes) / 4);
|
|
6217
|
+
}
|
|
6141
6218
|
var KIND_TO_SOURCE = {
|
|
6142
6219
|
image_shrink: SOURCE_IMAGE,
|
|
6143
6220
|
image_shrink_cache_hit: SOURCE_IMAGE,
|
|
@@ -6238,6 +6315,10 @@ var KIND_TO_SOURCE = {
|
|
|
6238
6315
|
// Decline counterpart to agent_report_compact: the fence-collapse net-benefit gate ran and found at least one over-long fence, but declined to rewrite because net savings did not clear the notice cost. Always recorded at (0, 0) -- see the recordStat call site -- so it never contributes to any savings total; it exists purely to make gate hit-rate and near-misses visible instead of the decline being invisible.
|
|
6239
6316
|
agent_report_compact_declined: SOURCE_CONTENT,
|
|
6240
6317
|
content_compress: SOURCE_CONTENT,
|
|
6318
|
+
// Verbatim-repeat collapse of a browser tool's "Tab Context:" text block (hooks_browser_image.ts postBrowserImageHandler). SOURCE_CONTENT for the same reason as agent_report_compact above: it is a real rewrite with real bytes removed, not an advisory nudge. Deliberately not SOURCE_IMAGE -- it shares a handler with image_shrink but collapses text, and folding text bytes into the image ledger is the two-units-under-one-label mistake this file's image_shrink entry was just fixed for.
|
|
6319
|
+
browser_tab_dedup: SOURCE_CONTENT,
|
|
6320
|
+
// Collapse of the plan echo in an approved ExitPlanMode result (hooks_exitplanmode.ts). SOURCE_CONTENT for the same reason as agent_report_compact: real bytes removed from a tool result, not an advisory nudge. The handler shipped for releases emitting this rewrite and recording nothing at all, so the mechanism was invisible in `stats` and its net benefit could not be checked against the gate that admits it.
|
|
6321
|
+
plan_echo_collapse: SOURCE_CONTENT,
|
|
6241
6322
|
// Lossless re-layout of Grep content-mode output (hooks_grep.ts foldGrepContentHandler). SOURCE_CONTENT, not SOURCE_HINT, for the same reason as agent_report_compact above: its sibling grep_dedup_hint is advisory and saves nothing directly, whereas this is a real rewrite with real bytes removed. Filing it under the advisory bucket would silently add non-hint savings to hint_stats.ts's savedBytes (which reads by_source[SOURCE_HINT] wholesale) and overstate the hint ledger's net benefit.
|
|
6242
6323
|
"grep:fold": SOURCE_CONTENT,
|
|
6243
6324
|
content_retrieve: SOURCE_CONTENT,
|
|
@@ -6366,7 +6447,8 @@ CREATE TABLE IF NOT EXISTS stats (
|
|
|
6366
6447
|
tokens_saved INTEGER NOT NULL DEFAULT 0,
|
|
6367
6448
|
bytes_saved INTEGER NOT NULL DEFAULT 0,
|
|
6368
6449
|
detail TEXT,
|
|
6369
|
-
harness TEXT
|
|
6450
|
+
harness TEXT,
|
|
6451
|
+
traceparent TEXT
|
|
6370
6452
|
);
|
|
6371
6453
|
CREATE INDEX IF NOT EXISTS idx_stats_ts ON stats(ts);
|
|
6372
6454
|
CREATE INDEX IF NOT EXISTS idx_stats_kind ON stats(kind);
|
|
@@ -6389,6 +6471,11 @@ function migrateGlobalSchema(db) {
|
|
|
6389
6471
|
} catch (err) {
|
|
6390
6472
|
if (!(err instanceof Error) || !/duplicate column/i.test(err.message)) throw err;
|
|
6391
6473
|
}
|
|
6474
|
+
try {
|
|
6475
|
+
db.exec("ALTER TABLE stats ADD COLUMN traceparent TEXT");
|
|
6476
|
+
} catch (err) {
|
|
6477
|
+
if (!(err instanceof Error) || !/duplicate column/i.test(err.message)) throw err;
|
|
6478
|
+
}
|
|
6392
6479
|
}
|
|
6393
6480
|
var _harnessColumnByDb = /* @__PURE__ */ new WeakMap();
|
|
6394
6481
|
function statsHasHarnessColumn(db) {
|
|
@@ -6405,6 +6492,21 @@ function statsHasHarnessColumn(db) {
|
|
|
6405
6492
|
_harnessColumnByDb.set(db, present);
|
|
6406
6493
|
return present;
|
|
6407
6494
|
}
|
|
6495
|
+
var _traceparentColumnByDb = /* @__PURE__ */ new WeakMap();
|
|
6496
|
+
function statsHasTraceparentColumn(db) {
|
|
6497
|
+
const cached = _traceparentColumnByDb.get(db);
|
|
6498
|
+
if (cached !== void 0) return cached;
|
|
6499
|
+
let present;
|
|
6500
|
+
try {
|
|
6501
|
+
present = db.prepare("PRAGMA table_info(stats)").all().some(
|
|
6502
|
+
(c) => c.name === "traceparent"
|
|
6503
|
+
);
|
|
6504
|
+
} catch {
|
|
6505
|
+
present = false;
|
|
6506
|
+
}
|
|
6507
|
+
_traceparentColumnByDb.set(db, present);
|
|
6508
|
+
return present;
|
|
6509
|
+
}
|
|
6408
6510
|
function getGlobalDb(homeDir) {
|
|
6409
6511
|
const basePath = homeDir ? dataDirForHome(homeDir) : dataDir();
|
|
6410
6512
|
const dbPath = path8.join(basePath, "global.db");
|
|
@@ -6423,11 +6525,18 @@ function noStatsMessage(windowDays, homeDir) {
|
|
|
6423
6525
|
if (total === 0) return "No stats recorded yet.";
|
|
6424
6526
|
return `No stats in the last ${countNoun(windowDays, "day")} (${total} recorded outside this window; use --window-days 0 for all time).`;
|
|
6425
6527
|
}
|
|
6426
|
-
function recordStat(kind, bytesSaved = 0, tokensSaved = 0, _testDb, detail) {
|
|
6528
|
+
function recordStat(kind, bytesSaved = 0, tokensSaved = 0, _testDb, detail, traceparent) {
|
|
6427
6529
|
try {
|
|
6428
6530
|
const db = _testDb ?? getGlobalDb();
|
|
6429
6531
|
const ts = Math.floor(Date.now() / 1e3);
|
|
6430
|
-
|
|
6532
|
+
const tp = traceparent ?? process.env["TRACEPARENT"] ?? process.env["traceparent"] ?? null;
|
|
6533
|
+
const hasHarness = statsHasHarnessColumn(db);
|
|
6534
|
+
const hasTraceparent = statsHasTraceparentColumn(db);
|
|
6535
|
+
if (hasHarness && hasTraceparent) {
|
|
6536
|
+
db.prepare(
|
|
6537
|
+
"INSERT INTO stats (ts, kind, bytes_saved, tokens_saved, detail, harness, traceparent) VALUES (?, ?, ?, ?, ?, ?, ?)"
|
|
6538
|
+
).run(ts, kind, bytesSaved, tokensSaved, detail ?? null, getHarnessName(), tp);
|
|
6539
|
+
} else if (hasHarness) {
|
|
6431
6540
|
db.prepare(
|
|
6432
6541
|
"INSERT INTO stats (ts, kind, bytes_saved, tokens_saved, detail, harness) VALUES (?, ?, ?, ?, ?, ?)"
|
|
6433
6542
|
).run(ts, kind, bytesSaved, tokensSaved, detail ?? null, getHarnessName());
|
|
@@ -6482,10 +6591,14 @@ function summarize(windowDays = 30, testDb, homeDir) {
|
|
|
6482
6591
|
const stmt = db.prepare(query);
|
|
6483
6592
|
const rows = sinceTs !== null ? stmt.all(sinceTs) : stmt.all();
|
|
6484
6593
|
const tsToDateCache = {};
|
|
6594
|
+
const counts = {};
|
|
6485
6595
|
for (const row of rows) {
|
|
6486
6596
|
const bytesSaved = row.bytes_saved ?? 0;
|
|
6487
|
-
const
|
|
6597
|
+
const recorded = row.tokens_saved ?? 0;
|
|
6488
6598
|
const kind = row.kind;
|
|
6599
|
+
const isCount = COUNT_ONLY_KINDS.has(kind);
|
|
6600
|
+
if (isCount) counts[kind] = (counts[kind] ?? 0) + recorded;
|
|
6601
|
+
const tokensSaved = isCount ? 0 : recorded;
|
|
6489
6602
|
const tsRaw = row.ts;
|
|
6490
6603
|
if (tsRaw === void 0) continue;
|
|
6491
6604
|
const ts = tsRaw;
|
|
@@ -6544,6 +6657,7 @@ function summarize(windowDays = 30, testDb, homeDir) {
|
|
|
6544
6657
|
by_project: byProjectList,
|
|
6545
6658
|
by_source: bySourceDict,
|
|
6546
6659
|
by_harness: byHarness,
|
|
6660
|
+
counts,
|
|
6547
6661
|
by_command: Object.entries(byCommandDict).map(([command, bucket]) => ({ ...bucket, command })).filter((r) => r.events > 0),
|
|
6548
6662
|
window_days: windowDays
|
|
6549
6663
|
};
|
|
@@ -6554,6 +6668,10 @@ function _totalsLines(summary) {
|
|
|
6554
6668
|
`Total events: ${summary.total_events}`,
|
|
6555
6669
|
`Bytes saved: ${fmtBytes(summary.total_bytes_saved)}`,
|
|
6556
6670
|
`Tokens saved: ${summary.total_tokens_saved}`,
|
|
6671
|
+
// Printed on its own line, below the token total and never inside it, because it counts
|
|
6672
|
+
// placeholders rather than tokens. Omitted entirely when nothing was redacted, so the line is
|
|
6673
|
+
// information rather than a permanent zero. See COUNT_ONLY_KINDS.
|
|
6674
|
+
...summary.counts["secret_redacted"] ? [`Secrets hidden: ${summary.counts["secret_redacted"]} (a count, not tokens)`] : [],
|
|
6557
6675
|
`Window: ${summary.window_days} days`
|
|
6558
6676
|
];
|
|
6559
6677
|
}
|
|
@@ -6872,6 +6990,7 @@ export {
|
|
|
6872
6990
|
toKB,
|
|
6873
6991
|
compileGrepMatcher,
|
|
6874
6992
|
grepFilteredToEmptyNotice,
|
|
6993
|
+
filtersFilteredToEmptyNotice,
|
|
6875
6994
|
countNoun,
|
|
6876
6995
|
excludeTestsHiddenNote,
|
|
6877
6996
|
countContentLines,
|
|
@@ -6959,6 +7078,7 @@ export {
|
|
|
6959
7078
|
fg,
|
|
6960
7079
|
C,
|
|
6961
7080
|
SOURCE_HINT,
|
|
7081
|
+
savedTokensFromBytes,
|
|
6962
7082
|
formatLocalTimestamp,
|
|
6963
7083
|
recordStat,
|
|
6964
7084
|
recordUnmappedTool,
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
expandGlobs,
|
|
8
8
|
leftoverIntegrations,
|
|
9
9
|
run
|
|
10
|
-
} from "./token-goat-chunk-
|
|
11
|
-
import "./token-goat-chunk-
|
|
12
|
-
import "./token-goat-chunk-
|
|
13
|
-
import "./token-goat-chunk-
|
|
14
|
-
import "./token-goat-chunk-
|
|
10
|
+
} from "./token-goat-chunk-U4UI5F3S.mjs";
|
|
11
|
+
import "./token-goat-chunk-RE7S7H26.mjs";
|
|
12
|
+
import "./token-goat-chunk-IZRXU64B.mjs";
|
|
13
|
+
import "./token-goat-chunk-4OTIB7SB.mjs";
|
|
14
|
+
import "./token-goat-chunk-E76UNTVK.mjs";
|
|
15
15
|
import "./token-goat-chunk-AO2QD2AG.mjs";
|
|
16
16
|
import "./token-goat-chunk-AEX54RUZ.mjs";
|
|
17
17
|
export {
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
loadBlob,
|
|
9
9
|
sanitizeFtsQuery,
|
|
10
10
|
storeBlob
|
|
11
|
-
} from "./token-goat-chunk-
|
|
11
|
+
} from "./token-goat-chunk-4OTIB7SB.mjs";
|
|
12
12
|
import {
|
|
13
13
|
SYMBOL_BODY_CHAR_CAP,
|
|
14
14
|
extractErrorMessage,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
redactSecrets,
|
|
19
19
|
runGit,
|
|
20
20
|
shortFingerprint
|
|
21
|
-
} from "./token-goat-chunk-
|
|
21
|
+
} from "./token-goat-chunk-E76UNTVK.mjs";
|
|
22
22
|
import {
|
|
23
23
|
registerReset
|
|
24
24
|
} from "./token-goat-chunk-AO2QD2AG.mjs";
|
|
@@ -151,8 +151,22 @@ var GROK_TOOL_NAME_MAP = {
|
|
|
151
151
|
write: "Write",
|
|
152
152
|
search_replace: "Edit",
|
|
153
153
|
run_terminal_command: "Bash",
|
|
154
|
+
// The grok 0.2.93 binary registers its shell tool as `tool.run_terminal_cmd` (tracing-id table in ~/.grok/bin/agent.exe) and its newer embedded hooks doc's PreToolUse example sends `"toolName": "run_terminal_cmd"`, while the older embedded doc revision and a 2026-07-09 live capture on the same version both show `run_terminal_command`. Which spelling arrives is profile/version dependent, so BOTH are mapped: an unmatched extra entry is a harmless no-op, a missing one silently kills every Bash hook (compression, wrap, hints) on that profile.
|
|
155
|
+
run_terminal_cmd: "Bash",
|
|
154
156
|
grep: "Grep",
|
|
155
|
-
list_dir: "Glob"
|
|
157
|
+
list_dir: "Glob",
|
|
158
|
+
// `glob` is a distinct registered grok tool (tool.glob in the 0.2.93 binary's tracing-id table), separate from list_dir; unmapped it arrived as lowercase 'glob' and matched no handler.
|
|
159
|
+
glob: "Glob",
|
|
160
|
+
// web_fetch/web_search were entirely absent from this map, so grok's URL fetches bypassed token-goat's WebFetch pipeline (URL-policy deny included) and its searches bypassed the WebSearch dedup/compression. Verified against the 0.2.93 binary: tool.web_fetch / tool.web_search registered ids, grok_build WebFetchInput's field described as "The URL to fetch content from" (i.e. `url`), grok_build WebSearchInput's fields query/citations/allowed_domains -- all matching the keys hooks_fetch.ts / hooks_websearch.ts already read, so a name map alone revives both.
|
|
161
|
+
web_fetch: "WebFetch",
|
|
162
|
+
web_search: "WebSearch",
|
|
163
|
+
// The Hashline prompt profile registers hashline_read/hashline_edit/hashline_grep (tool.hashline_* in the binary; grok's own hook alias table pairs them with Read/Edit/Grep). Their input key shapes were not individually verified: if one differs, the mapped handler degrades to the same no-op as an unmapped name, never a wrong rewrite. The *_concise twins are the GrokBuildConcise profile's registrations of the same three core tools.
|
|
164
|
+
hashline_read: "Read",
|
|
165
|
+
hashline_edit: "Edit",
|
|
166
|
+
hashline_grep: "Grep",
|
|
167
|
+
read_file_concise: "Read",
|
|
168
|
+
search_replace_concise: "Edit",
|
|
169
|
+
run_terminal_cmd_concise: "Bash"
|
|
156
170
|
};
|
|
157
171
|
var GROK_INPUT_KEY_MAP = {
|
|
158
172
|
Read: { target_file: "file_path" }
|
|
@@ -162,10 +176,28 @@ var KIMI_TOOL_NAME_MAP = {
|
|
|
162
176
|
ReadMediaFile: "Read"
|
|
163
177
|
};
|
|
164
178
|
var KIMI_INPUT_KEY_MAP = {
|
|
165
|
-
Read
|
|
179
|
+
// line_offset/n_lines are Kimi's Read paging arguments (ReadInputSchema in MoonshotAI/kimi-code packages/agent-core-v2/src/agent/tools/os/read/read.ts: `path`, `line_offset` "the line number to start reading from", `n_lines` "the number of lines to read"). Unmapped, every ranged Kimi read looked unbounded to hooks_read.ts's estimateRequestedSlice and was gated on the whole file's size -- a small slice of a big file could draw the large-file deny meant for full reads. line_offset's 1-indexed positive form matches Read's own offset semantics exactly; its negative tail-read form has no token-goat equivalent and is clamped to 1 by estimateRequestedSlice's `offset >= 1` guard, degrading to a window of the right SIZE (which is all the gate consumes). ReadMediaFile shares this map via its Read rename and carries only `path`, so the extra entries never touch it.
|
|
180
|
+
Read: { path: "file_path", line_offset: "offset", n_lines: "limit" },
|
|
166
181
|
Write: { path: "file_path" },
|
|
167
182
|
Edit: { path: "file_path" }
|
|
168
183
|
};
|
|
184
|
+
var QWEN_TOOL_NAME_MAP = {
|
|
185
|
+
read_file: "Read",
|
|
186
|
+
write_file: "Write",
|
|
187
|
+
edit: "Edit",
|
|
188
|
+
replace: "Edit",
|
|
189
|
+
notebook_edit: "NotebookEdit",
|
|
190
|
+
run_shell_command: "Bash",
|
|
191
|
+
grep_search: "Grep",
|
|
192
|
+
search_file_content: "Grep",
|
|
193
|
+
glob: "Glob",
|
|
194
|
+
web_fetch: "WebFetch",
|
|
195
|
+
web_search: "WebSearch",
|
|
196
|
+
list_directory: "Read"
|
|
197
|
+
};
|
|
198
|
+
var QWEN_INPUT_KEY_MAP = {
|
|
199
|
+
Read: { path: "file_path" }
|
|
200
|
+
};
|
|
169
201
|
function remapInputKeys(input, keyMap) {
|
|
170
202
|
const newInput = {};
|
|
171
203
|
for (const [k, v] of Object.entries(input)) {
|
|
@@ -209,6 +241,14 @@ function grokToCanonicalWire(obj) {
|
|
|
209
241
|
}
|
|
210
242
|
return wire;
|
|
211
243
|
}
|
|
244
|
+
function aliasLlmContentToOutput(result) {
|
|
245
|
+
const toolResponse = result["tool_response"];
|
|
246
|
+
if (toolResponse === null || typeof toolResponse !== "object" || Array.isArray(toolResponse)) return;
|
|
247
|
+
const responseRecord = toolResponse;
|
|
248
|
+
if (typeof responseRecord["llmContent"] === "string" && responseRecord["output"] === void 0) {
|
|
249
|
+
result["tool_response"] = { ...responseRecord, output: responseRecord["llmContent"] };
|
|
250
|
+
}
|
|
251
|
+
}
|
|
212
252
|
function normalizePayload(payload, harness = "claude") {
|
|
213
253
|
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
214
254
|
_LOG.warn("normalizePayload: payload is not a dict; received %s", typeof payload);
|
|
@@ -246,12 +286,19 @@ function normalizePayload(payload, harness = "claude") {
|
|
|
246
286
|
result2["_tg_harness"] = harness;
|
|
247
287
|
return result2;
|
|
248
288
|
}
|
|
289
|
+
if (harness === "qwen") {
|
|
290
|
+
const result2 = remapToolName(obj, toolName, QWEN_TOOL_NAME_MAP, QWEN_INPUT_KEY_MAP);
|
|
291
|
+
aliasLlmContentToOutput(result2);
|
|
292
|
+
result2["_tg_harness"] = harness;
|
|
293
|
+
return result2;
|
|
294
|
+
}
|
|
249
295
|
if (harness === "gemini") {
|
|
250
296
|
const result2 = remapToolName(obj, toolName, GEMINI_TOOL_NAME_MAP, GEMINI_INPUT_KEY_MAP);
|
|
251
297
|
if ("functionCallId" in result2 && !("toolUseId" in result2)) {
|
|
252
298
|
result2["toolUseId"] = result2["functionCallId"];
|
|
253
299
|
delete result2["functionCallId"];
|
|
254
300
|
}
|
|
301
|
+
aliasLlmContentToOutput(result2);
|
|
255
302
|
result2["_tg_harness"] = harness;
|
|
256
303
|
return result2;
|
|
257
304
|
}
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
buildEvent,
|
|
5
5
|
relay,
|
|
6
6
|
relayInProcess
|
|
7
|
-
} from "./token-goat-chunk-
|
|
7
|
+
} from "./token-goat-chunk-ZQ3PUOP3.mjs";
|
|
8
8
|
import {
|
|
9
9
|
MAX_STDIN_BYTES,
|
|
10
10
|
readStdinJson
|
|
11
|
-
} from "./token-goat-chunk-
|
|
12
|
-
import "./token-goat-chunk-
|
|
13
|
-
import "./token-goat-chunk-
|
|
14
|
-
import "./token-goat-chunk-
|
|
11
|
+
} from "./token-goat-chunk-IZRXU64B.mjs";
|
|
12
|
+
import "./token-goat-chunk-4OTIB7SB.mjs";
|
|
13
|
+
import "./token-goat-chunk-CZALRRGN.mjs";
|
|
14
|
+
import "./token-goat-chunk-E76UNTVK.mjs";
|
|
15
15
|
import "./token-goat-chunk-AO2QD2AG.mjs";
|
|
16
16
|
import "./token-goat-chunk-AEX54RUZ.mjs";
|
|
17
17
|
export {
|