token-goat 2.9.3 → 2.9.5
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 +8 -4
- package/dist/{token-goat-chunk-XSSQFI4C.mjs → token-goat-chunk-2FVSKFZU.mjs} +5 -5
- package/dist/{token-goat-chunk-7A7SBE6R.mjs → token-goat-chunk-4P6GTCMM.mjs} +220 -23
- package/dist/{token-goat-chunk-6FQMEMWX.mjs → token-goat-chunk-5T2K7DEE.mjs} +108 -46
- package/dist/{token-goat-chunk-3UBORD6Z.mjs → token-goat-chunk-DRL5USXI.mjs} +3 -3
- package/dist/{token-goat-chunk-HC5NMGPD.mjs → token-goat-chunk-GFBXHGFY.mjs} +5 -5
- package/dist/{token-goat-chunk-OKJX2JWW.mjs → token-goat-chunk-HTJP6FHK.mjs} +2 -1
- package/dist/{token-goat-chunk-A4VBNWSL.mjs → token-goat-chunk-JO5JX72D.mjs} +2 -2
- package/dist/{token-goat-chunk-LLNA42NI.mjs → token-goat-chunk-KFFAZ5DJ.mjs} +2 -2
- package/dist/{token-goat-chunk-3XVGPLDS.mjs → token-goat-chunk-U4FTM2SB.mjs} +9765 -9147
- package/dist/{token-goat-chunk-2VVXTAGD.mjs → token-goat-chunk-ZLP6TCGN.mjs} +215 -27
- package/dist/{token-goat-chunk-KKHKXUVS.mjs → token-goat-chunk-ZOKNDG6V.mjs} +229 -97
- package/dist/token-goat-hook.mjs +5 -5
- package/dist/token-goat.core.mjs +5 -5
- package/docs/cli.md +15 -8
- package/docs/security.md +6 -2
- package/package.json +1 -1
|
@@ -86,7 +86,7 @@ import {
|
|
|
86
86
|
runZipRead,
|
|
87
87
|
symbolNamesInFile,
|
|
88
88
|
upsertNote
|
|
89
|
-
} from "./token-goat-chunk-
|
|
89
|
+
} from "./token-goat-chunk-4P6GTCMM.mjs";
|
|
90
90
|
import {
|
|
91
91
|
DEFAULT_RECONCILE_BUDGET_MS,
|
|
92
92
|
GEMINI_TOOL_NAME_MAP,
|
|
@@ -108,7 +108,7 @@ import {
|
|
|
108
108
|
runReconcile,
|
|
109
109
|
storeWebOutput,
|
|
110
110
|
summarizeResidentContext
|
|
111
|
-
} from "./token-goat-chunk-
|
|
111
|
+
} from "./token-goat-chunk-JO5JX72D.mjs";
|
|
112
112
|
import {
|
|
113
113
|
AGENT_SALT_MARKER,
|
|
114
114
|
BASH_OUTPUT_SUBDIR,
|
|
@@ -175,6 +175,7 @@ import {
|
|
|
175
175
|
getFileEntry,
|
|
176
176
|
getHintStatsSummary,
|
|
177
177
|
getHintStatsTotals,
|
|
178
|
+
getParserFreshness,
|
|
178
179
|
getProjectIndexCounts,
|
|
179
180
|
getSessionFiles,
|
|
180
181
|
getSessionId,
|
|
@@ -193,6 +194,7 @@ import {
|
|
|
193
194
|
isHintCategory,
|
|
194
195
|
isParseSkipEligible,
|
|
195
196
|
isRecallCacheType,
|
|
197
|
+
isSuppressionCategory,
|
|
196
198
|
isWorkerRunning,
|
|
197
199
|
listBlobs,
|
|
198
200
|
listOutputs,
|
|
@@ -238,7 +240,7 @@ import {
|
|
|
238
240
|
visionTokensSavedByText,
|
|
239
241
|
walkProject,
|
|
240
242
|
writeCompact
|
|
241
|
-
} from "./token-goat-chunk-
|
|
243
|
+
} from "./token-goat-chunk-U4FTM2SB.mjs";
|
|
242
244
|
import {
|
|
243
245
|
C,
|
|
244
246
|
CONFIG_KEY_ENV_OVERRIDES,
|
|
@@ -364,7 +366,7 @@ import {
|
|
|
364
366
|
withFileLock,
|
|
365
367
|
withRetryOnLock,
|
|
366
368
|
writeJsonSettings
|
|
367
|
-
} from "./token-goat-chunk-
|
|
369
|
+
} from "./token-goat-chunk-ZOKNDG6V.mjs";
|
|
368
370
|
import {
|
|
369
371
|
__export,
|
|
370
372
|
init_define_import_meta_env
|
|
@@ -5950,6 +5952,7 @@ function statsJsonPayload(summary) {
|
|
|
5950
5952
|
by_command: summary.by_command,
|
|
5951
5953
|
by_source: summary.by_source,
|
|
5952
5954
|
by_harness: summary.by_harness,
|
|
5955
|
+
by_pricing_version: summary.by_pricing_version,
|
|
5953
5956
|
counts: summary.counts,
|
|
5954
5957
|
window_days: summary.window_days
|
|
5955
5958
|
};
|
|
@@ -6219,6 +6222,38 @@ function checkEmbeddingCoverage(dbPath, rootDir) {
|
|
|
6219
6222
|
};
|
|
6220
6223
|
}
|
|
6221
6224
|
}
|
|
6225
|
+
var PARSER_FRESHNESS_WARN_FRACTION = 0.25;
|
|
6226
|
+
function checkParserFreshness(dbPath, rootDir) {
|
|
6227
|
+
if (!fs12.existsSync(dbPath)) {
|
|
6228
|
+
return { name: "Parser freshness", status: "ok", message: "no database yet" };
|
|
6229
|
+
}
|
|
6230
|
+
try {
|
|
6231
|
+
const { indexedFiles, currentFiles } = getParserFreshness(dbPath, PARSER_FINGERPRINT, rootDir);
|
|
6232
|
+
if (indexedFiles === 0) {
|
|
6233
|
+
return { name: "Parser freshness", status: "ok", message: "no indexed files yet" };
|
|
6234
|
+
}
|
|
6235
|
+
const stale = indexedFiles - currentFiles;
|
|
6236
|
+
const pct3 = Math.round(stale / indexedFiles * 100);
|
|
6237
|
+
if (currentFiles / indexedFiles < 1 - PARSER_FRESHNESS_WARN_FRACTION) {
|
|
6238
|
+
return {
|
|
6239
|
+
name: "Parser freshness",
|
|
6240
|
+
status: "warn",
|
|
6241
|
+
message: `${stale} of ${indexedFiles} indexed file(s) (${pct3}%) were parsed by a different build of the extraction logic, so their symbols are whatever that build extracted \u2014 'symbol', 'read', 'outline' and 'skeleton' answer from those rows, and the read-hook body fold declines on them. Run 'token-goat index' in this project to reparse them; --force is not needed, a parser mismatch reindexes on its own`
|
|
6242
|
+
};
|
|
6243
|
+
}
|
|
6244
|
+
return {
|
|
6245
|
+
name: "Parser freshness",
|
|
6246
|
+
status: "ok",
|
|
6247
|
+
message: `${currentFiles} of ${indexedFiles} indexed file(s) match the running parser`
|
|
6248
|
+
};
|
|
6249
|
+
} catch (err2) {
|
|
6250
|
+
return {
|
|
6251
|
+
name: "Parser freshness",
|
|
6252
|
+
status: "warn",
|
|
6253
|
+
message: `could not query parser freshness: ${extractErrorMessage(err2)}`
|
|
6254
|
+
};
|
|
6255
|
+
}
|
|
6256
|
+
}
|
|
6222
6257
|
var DIRTY_QUEUE_BACKLOG_WARN_THRESHOLD = 500;
|
|
6223
6258
|
function checkDirtyQueueHealth(dataDir2) {
|
|
6224
6259
|
let pendingCount = 0;
|
|
@@ -6454,6 +6489,9 @@ var LOCKED_BOOLEAN_SAFE_VALUE = {
|
|
|
6454
6489
|
"screenshot.block_private_targets": true,
|
|
6455
6490
|
"network.offline": true,
|
|
6456
6491
|
"indexing.cross_project_symbols": false,
|
|
6492
|
+
// `hints.fold_code_bodies` is deliberately absent for the same reason as `hints.fold_prose_paragraphs` below: it now ships on. Its cost was the thing keeping it off, and that cost is now measured rather than assumed -- 6.6 points of recovery reads beyond what the same symbols draw anyway, against a fold that withholds a whole function body. It remains project-locked, so the environment deciding it is still reported by the value-replacement arm.
|
|
6493
|
+
// `hints.fold_prose_paragraphs` is deliberately absent: it now ships on, so neither direction is a weakening. Setting it true restates the shipped default, and setting it false shows the reader MORE of a document, so warning on either would break this file's own rule that a default install stays quiet. It remains project-locked, so the environment deciding it is still worth reporting, which is what the value-replacement arm below does.
|
|
6494
|
+
// The three remaining hints keys, fold_comment_blocks and outline_large_documents and skeleton_large_sources, are absent for exactly the same reason and just as deliberately: each ships on, so neither direction of an override is a weakening, and a false entry here would make a default install warn about itself. All three stay project-locked, so the environment deciding one is still reported by the value-replacement arm below.
|
|
6457
6495
|
"webfetch.compress_bodies": true
|
|
6458
6496
|
};
|
|
6459
6497
|
function lockedEnvOverridableKeys() {
|
|
@@ -6520,9 +6558,15 @@ function checkSecurityPosture(cfg, dataDirPath) {
|
|
|
6520
6558
|
cfg.mcp.confine_reads_to_project_root ? {
|
|
6521
6559
|
name: "Security mcp roots",
|
|
6522
6560
|
status: "ok",
|
|
6523
|
-
|
|
6561
|
+
// Two separate controls, and reporting only the first read as a guarantee about the second. `confine_reads_to_project_root` keeps a read inside the root the caller named; `mcp.allowed_roots` decides which roots may be named at all, and empty means any of them (assertRootAllowed returns early). Saying "confined to the project root" while the caller picks that root overstates the confinement, so the empty case now names itself.
|
|
6562
|
+
message: extraRoots === 0 ? "reads are confined to the project root the caller names, but mcp.allowed_roots is empty, so an MCP caller may name any root on this machine" : `reads are confined to the project root, and callers may name only the ${extraRoots} root${extraRoots === 1 ? "" : "s"} in mcp.allowed_roots`
|
|
6524
6563
|
} : { name: "Security mcp roots", status: "warn", message: "confinement is off (mcp.confine_reads_to_project_root): a read can leave the project" }
|
|
6525
6564
|
);
|
|
6565
|
+
results.push({
|
|
6566
|
+
name: "Security symbol scope",
|
|
6567
|
+
status: "ok",
|
|
6568
|
+
message: cfg.indexing.cross_project_symbols ? "symbol lookups can resolve into other projects in the machine-wide index (indexing.cross_project_symbols = false confines them to this project)" : "symbol lookups are confined to this project"
|
|
6569
|
+
});
|
|
6526
6570
|
const overridden = envOverriddenSecuritySettings();
|
|
6527
6571
|
const weakened = overridden.filter((o) => o.kind === "weakened");
|
|
6528
6572
|
const replaced = overridden.filter((o) => o.kind === "replaced");
|
|
@@ -6656,6 +6700,7 @@ function runDoctor(dataDir2, configPath2, rootDir, processes) {
|
|
|
6656
6700
|
results.push(checkConfigValid(actualConfigPath));
|
|
6657
6701
|
results.push(checkEmbeddings(loadConfig(rootDir)));
|
|
6658
6702
|
results.push(checkEmbeddingCoverage(path12.join(actualDataDir, "global.db"), rootDir));
|
|
6703
|
+
results.push(checkParserFreshness(path12.join(actualDataDir, "global.db"), rootDir));
|
|
6659
6704
|
for (const result of checkSecurityPosture(loadConfig(rootDir), actualDataDir)) results.push(result);
|
|
6660
6705
|
results.push(checkDiskSpace(actualDataDir));
|
|
6661
6706
|
const copilotResult = checkCopilotCli(copilotCliConfigPath(), copilotCliScriptPath());
|
|
@@ -14057,15 +14102,15 @@ var READ_DIVERT_MARKER_RE = /(?:was already read this session|Already read |You'
|
|
|
14057
14102
|
var READ_DIVERT_MAX_BYTES = 2500;
|
|
14058
14103
|
var READ_FULL_SERVE_MIN_BYTES = 10240;
|
|
14059
14104
|
var DENY_TEMPLATES = [
|
|
14060
|
-
{ kind: "node_modules_deny", re: /node_modules is typically noise
|
|
14061
|
-
{ kind: "lock_file_deny", re: /Lock files are rarely useful to read in full
|
|
14062
|
-
{ kind: "tsbuildinfo_deny", re: /TypeScript incremental build cache file
|
|
14063
|
-
{ kind: "generated_build_deny", re: /Generated\/build artifact — read the source file instead
|
|
14064
|
-
{ kind: "compact_sidecar_served", re: /Serving the extractive compact sidecar in place of the full file
|
|
14065
|
-
{ kind: "notebook_sidecar_served", re: /Serving the output-stripped notebook in place of the full file
|
|
14105
|
+
{ kind: "node_modules_deny", re: /node_modules is typically noise/, tool: "Read" },
|
|
14106
|
+
{ kind: "lock_file_deny", re: /Lock files are rarely useful to read in full/, tool: "Read" },
|
|
14107
|
+
{ kind: "tsbuildinfo_deny", re: /TypeScript incremental build cache file/, tool: "Read" },
|
|
14108
|
+
{ kind: "generated_build_deny", re: /Generated\/build artifact — read the source file instead\./, tool: "Read" },
|
|
14109
|
+
{ kind: "compact_sidecar_served", re: /Serving the extractive compact sidecar in place of the full file/, tool: "Read" },
|
|
14110
|
+
{ kind: "notebook_sidecar_served", re: /Serving the output-stripped notebook in place of the full file/, tool: "Read" },
|
|
14066
14111
|
// Must stay ABOVE markdown_heading_tree_deny: this deny's message embeds the same "Large markdown file (N headings)" guidance block, so the generic alternative would swallow it and the new intervention would be uncountable. DENY_TEMPLATES is scanned with `.find`, so the more specific wording has to come first.
|
|
14067
|
-
{ kind: "subagent_markdown_first_read_deny", re: /Subagent first read of a large markdown file
|
|
14068
|
-
{ kind: "markdown_heading_tree_deny", re: /Large markdown file \(\d+ headings\)
|
|
14112
|
+
{ kind: "subagent_markdown_first_read_deny", re: /Subagent first read of a large markdown file/, tool: "Read" },
|
|
14113
|
+
{ kind: "markdown_heading_tree_deny", re: /Large markdown file \(\d+ headings\)/, tool: "Read" },
|
|
14069
14114
|
// The first alternative is a wording hooks_read.ts no longer emits (it claimed a compact-manifest
|
|
14070
14115
|
// section that never existed, reworded in 3d044feb). It stays because this table classifies a
|
|
14071
14116
|
// historical corpus, not just today's output: transcripts written before the rewording still
|
|
@@ -14073,24 +14118,32 @@ var DENY_TEMPLATES = [
|
|
|
14073
14118
|
// 30 -- 41% of its history -- with a green suite. A superseded alternative is only removable
|
|
14074
14119
|
// once no transcript contains it, which source code cannot tell you. See the superseded-wording
|
|
14075
14120
|
// test in tests/deny_outcomes.test.ts.
|
|
14076
|
-
{ kind: "memory_md_reread_deny", re: /MEMORY\.md was read this session\. Its content is in the compact manifest|already read this session\. Memory files rarely change mid-session
|
|
14077
|
-
{ kind: "improve_state_reread_deny", re: /Orchestrator state already read this session
|
|
14078
|
-
{ kind: "env_reread_deny", re: /Environment files rarely change mid-session
|
|
14079
|
-
{ kind: "session_artifact_truncated_deny", re: /File was truncated on last read\. Use `token-goat bash-output
|
|
14080
|
-
{ kind: "session_artifact_unchanged_deny", re: /is unchanged since last read\. Use `token-goat bash-output
|
|
14081
|
-
{ kind: "session_artifact_diff_deny", re: /Content changed since last read of [\s\S]*?bash-output --file
|
|
14082
|
-
{ kind: "session_artifact_large_deny", re: /(?:Session transcript|Tool-result file) is large \(
|
|
14083
|
-
{ kind: "session_artifact_generic_reread_deny", re: /already read this session\. Use `token-goat bash-output --file
|
|
14084
|
-
{ kind: "truncated_read_deny", re: /File was truncated on last read \(>33K tokens\)
|
|
14085
|
-
{ kind: "doc_unchanged_deny", re: /is unchanged since last read\. Use `token-goat (?:section|read)
|
|
14086
|
-
{ kind: "doc_diff_deny", re: /Content changed since last read of [\s\S]*?Use `token-goat (?:section|read)
|
|
14087
|
-
{ kind: "read_served_deny", re: /was already served in this session, byte for byte
|
|
14088
|
-
{ kind: "markdown_already_read_deny", re: /Markdown file already read this session\. Use `token-goat section
|
|
14089
|
-
{ kind: "read_count_deny", re: /Read this file \d+ times already
|
|
14090
|
-
{ kind: "generic_reread_deny", re: /was already read this session \(\d+ read
|
|
14091
|
-
{ kind: "large_file_deny", re: /is very large \(\d+(?:\.\d+)?KB\)
|
|
14092
|
-
{ kind: "file_type_handler_deny", re: /too large to preview \(exceeds the in-hook scan cap\)|cannot be read as text\.|Read cannot return spreadsheet content|Read cannot return slide content|Read cannot return document content|Use Read with offset and limit parameters to read specific line ranges
|
|
14121
|
+
{ kind: "memory_md_reread_deny", re: /MEMORY\.md was read this session\. Its content is in the compact manifest|already read this session\. Memory files rarely change mid-session/, tool: "Read" },
|
|
14122
|
+
{ kind: "improve_state_reread_deny", re: /Orchestrator state already read this session/, tool: "Read" },
|
|
14123
|
+
{ kind: "env_reread_deny", re: /Environment files rarely change mid-session/, tool: "Read" },
|
|
14124
|
+
{ kind: "session_artifact_truncated_deny", re: /File was truncated on last read\. Use `token-goat bash-output/, tool: "Read" },
|
|
14125
|
+
{ kind: "session_artifact_unchanged_deny", re: /is unchanged since last read\. Use `token-goat bash-output/, tool: "Read" },
|
|
14126
|
+
{ kind: "session_artifact_diff_deny", re: /Content changed since last read of [\s\S]*?bash-output --file/, tool: "Read" },
|
|
14127
|
+
{ kind: "session_artifact_large_deny", re: /(?:Session transcript|Tool-result file) is large \(/, tool: "Read" },
|
|
14128
|
+
{ kind: "session_artifact_generic_reread_deny", re: /already read this session\. Use `token-goat bash-output --file/, tool: "Read" },
|
|
14129
|
+
{ kind: "truncated_read_deny", re: /File was truncated on last read \(>33K tokens\)/, tool: "Read" },
|
|
14130
|
+
{ kind: "doc_unchanged_deny", re: /is unchanged since last read\. Use `token-goat (?:section|read)/, tool: "Read" },
|
|
14131
|
+
{ kind: "doc_diff_deny", re: /Content changed since last read of [\s\S]*?Use `token-goat (?:section|read)/, tool: "Read" },
|
|
14132
|
+
{ kind: "read_served_deny", re: /was already served in this session, byte for byte/, tool: "Read" },
|
|
14133
|
+
{ kind: "markdown_already_read_deny", re: /Markdown file already read this session\. Use `token-goat section/, tool: "Read" },
|
|
14134
|
+
{ kind: "read_count_deny", re: /Read this file \d+ times already/, tool: "Read" },
|
|
14135
|
+
{ kind: "generic_reread_deny", re: /was already read this session \(\d+ read/, tool: "Read" },
|
|
14136
|
+
{ kind: "large_file_deny", re: /is very large \(\d+(?:\.\d+)?KB\)\./, tool: "Read" },
|
|
14137
|
+
{ kind: "file_type_handler_deny", re: /too large to preview \(exceeds the in-hook scan cap\)|cannot be read as text\.|Read cannot return spreadsheet content|Read cannot return slide content|Read cannot return document content|Use Read with offset and limit parameters to read specific line ranges/, tool: "Read" },
|
|
14138
|
+
// Skill-tool denies from src/hooks_skill.ts's preSkillHandler -- kind names prefixed skill_ so they read as a family, distinct from the Read-deny kinds above. The two heading-tree wordings share the prose around them ("...its heading tree...instead of the full body. Use `token-goat skill-section NAME '<heading>'`...") but each anchors on an infix the other never emits -- truncated always says "shows N of M headings below" (no "inlined"), complete always says "(N headings) is inlined below" (no "shows") -- so neither regex can match the other's text; skill_heading_tree_truncated_deny is still listed first on the same specific-before-generic principle as markdown_heading_tree_deny above, in case a future rewording narrows the gap.
|
|
14139
|
+
{ kind: "skill_already_loaded_deny", re: /was already loaded this session and is cached/, tool: "Skill" },
|
|
14140
|
+
{ kind: "skill_compact_slice_deny", re: /has a compact slice available/, tool: "Skill" },
|
|
14141
|
+
// The compact slice has two outcomes and they are separate kinds because they cost different things: the pointer above withholds the slice behind a command, this one inlines the slice and withholds only the rest of the body. Its "(N bytes) is inlined below" cannot collide with the heading-tree wording below, which requires "heading tree (N headings) is inlined below".
|
|
14142
|
+
{ kind: "skill_compact_slice_inlined_deny", re: /compact slice \(\d+ bytes\) is inlined below instead of the full body/, tool: "Skill" },
|
|
14143
|
+
{ kind: "skill_heading_tree_truncated_deny", re: /heading tree shows \d+ of \d+ headings below instead of the full body/, tool: "Skill" },
|
|
14144
|
+
{ kind: "skill_heading_tree_complete_deny", re: /heading tree \(\d+ headings\) is inlined below instead of the full body/, tool: "Skill" }
|
|
14093
14145
|
];
|
|
14146
|
+
var DENY_TEMPLATE_KINDS = DENY_TEMPLATES.map((t) => t.kind);
|
|
14094
14147
|
var DENY_KINDS_WITH_SIZE = /* @__PURE__ */ new Set(["large_file_deny", "session_artifact_large_deny", "file_type_handler_deny"]);
|
|
14095
14148
|
var DENY_SIZE_RE = /(\d+(?:\.\d+)?)\s*(B|KB|MB|GB|TB)\b/;
|
|
14096
14149
|
function parseWithheldBytes(kind, text) {
|
|
@@ -14360,9 +14413,8 @@ async function auditOneFile(filePath, s, toolMap, attachmentMap, hookMap, laneOb
|
|
|
14360
14413
|
s.editErrorBaseline.totalErrors += 1;
|
|
14361
14414
|
editErrorById.set(id, true);
|
|
14362
14415
|
}
|
|
14363
|
-
if (name === "Read") {
|
|
14364
|
-
|
|
14365
|
-
const denyTemplate = DENY_TEMPLATES.find((t) => t.re.test(text));
|
|
14416
|
+
if (name === "Read" || name === "Skill") {
|
|
14417
|
+
const denyTemplate = DENY_TEMPLATES.find((t) => t.tool === name && t.re.test(text));
|
|
14366
14418
|
if (denyTemplate !== void 0) {
|
|
14367
14419
|
const path31 = readPathById.get(id) ?? "";
|
|
14368
14420
|
const lastSlash = path31.lastIndexOf("/");
|
|
@@ -14377,6 +14429,9 @@ async function auditOneFile(filePath, s, toolMap, attachmentMap, hookMap, laneOb
|
|
|
14377
14429
|
toolCalls: []
|
|
14378
14430
|
});
|
|
14379
14431
|
}
|
|
14432
|
+
}
|
|
14433
|
+
if (name === "Read") {
|
|
14434
|
+
s.readInterception.readResults += 1;
|
|
14380
14435
|
if (bytes < READ_DIVERT_MAX_BYTES && READ_DIVERT_MARKER_RE.test(text)) {
|
|
14381
14436
|
s.readInterception.divertedByMarker += 1;
|
|
14382
14437
|
s.readInterception.divertedBytes += bytes;
|
|
@@ -14906,7 +14961,7 @@ function analyzeMcpCache() {
|
|
|
14906
14961
|
const metrics = serverMetrics.get(toolName);
|
|
14907
14962
|
metrics.callCount += 1;
|
|
14908
14963
|
metrics.totalBytes += sizeBytes;
|
|
14909
|
-
metrics.perCallEstimate =
|
|
14964
|
+
metrics.perCallEstimate = estimateTokensFromLength(metrics.totalBytes / metrics.callCount);
|
|
14910
14965
|
}
|
|
14911
14966
|
return serverMetrics;
|
|
14912
14967
|
}
|
|
@@ -15286,15 +15341,18 @@ function suppressedCell(row) {
|
|
|
15286
15341
|
if (!row.suppressed) return "no";
|
|
15287
15342
|
return row.suppressionPermanent ? "yes (permanent)" : "yes";
|
|
15288
15343
|
}
|
|
15344
|
+
function efficacyCell(row) {
|
|
15345
|
+
const pct3 = row.efficacyPct === null ? "n/a" : `${row.efficacyPct}%`;
|
|
15346
|
+
return isSuppressionCategory(row.category) ? `${pct3} *` : pct3;
|
|
15347
|
+
}
|
|
15289
15348
|
function printSummary(rows) {
|
|
15290
15349
|
const w = (text) => {
|
|
15291
15350
|
process.stdout.write(text);
|
|
15292
15351
|
};
|
|
15293
|
-
w(pad("category", 22) + pad("emitted", 9) + pad("acted-on", 10) + pad("efficacy",
|
|
15352
|
+
w(pad("category", 22) + pad("emitted", 9) + pad("acted-on", 10) + pad("efficacy", 12) + pad("suppressed", 17) + pad("manual+", 9) + pad("manual-", 9) + "spent\n");
|
|
15294
15353
|
for (const row of rows) {
|
|
15295
|
-
const pct3 = row.efficacyPct === null ? "n/a" : `${row.efficacyPct}%`;
|
|
15296
15354
|
w(
|
|
15297
|
-
pad(row.category, 22) + pad(String(row.emitted), 9) + pad(String(row.actedOn), 10) + pad(
|
|
15355
|
+
pad(row.category, 22) + pad(String(row.emitted), 9) + pad(String(row.actedOn), 10) + pad(efficacyCell(row), 12) + pad(suppressedCell(row), 17) + pad(String(row.manualEffective), 9) + pad(String(row.manualIneffective), 9) + formatSpentCell(row) + "\n"
|
|
15298
15356
|
);
|
|
15299
15357
|
}
|
|
15300
15358
|
}
|
|
@@ -15335,6 +15393,11 @@ function runHintStatsCommand(opts = {}) {
|
|
|
15335
15393
|
process.stdout.write("No hint emissions recorded yet \u2014 the zeros below are absence of data, not measured ineffectiveness.\n");
|
|
15336
15394
|
}
|
|
15337
15395
|
printSummary(rows);
|
|
15396
|
+
if (rows.some((r) => isSuppressionCategory(r.category) && r.emitted > 0)) {
|
|
15397
|
+
process.stdout.write(
|
|
15398
|
+
'\n* Scored on an absence: these hints ask the agent NOT to do something, so a window that expires with no re-read counts as compliance. Their percentage is not comparable with the unmarked rows, which only count when the agent runs the command the hint named. A high starred figure means "the warned-against read was not seen", not "this hint persuaded anyone".\n'
|
|
15399
|
+
);
|
|
15400
|
+
}
|
|
15338
15401
|
const permanent = rows.filter((r) => r.suppressionPermanent);
|
|
15339
15402
|
if (permanent.length > 0) {
|
|
15340
15403
|
const names = permanent.map((r) => r.category).join(", ");
|
|
@@ -15667,7 +15730,7 @@ async function cmdMcpServe() {
|
|
|
15667
15730
|
let StdioServerTransport;
|
|
15668
15731
|
try {
|
|
15669
15732
|
;
|
|
15670
|
-
({ createMcpServer } = await import("./token-goat-chunk-
|
|
15733
|
+
({ createMcpServer } = await import("./token-goat-chunk-DRL5USXI.mjs"));
|
|
15671
15734
|
({ StdioServerTransport } = await import("./token-goat-chunk-EVC4TOLE.mjs"));
|
|
15672
15735
|
} catch (err2) {
|
|
15673
15736
|
process.stderr.write(
|
|
@@ -15692,7 +15755,7 @@ async function cmdHook(event, opts) {
|
|
|
15692
15755
|
if (typeof opts.harness === "string" && opts.harness.length > 0) {
|
|
15693
15756
|
process.env[ENV_KEYS.HARNESS_OVERRIDE] = opts.harness;
|
|
15694
15757
|
}
|
|
15695
|
-
const { relay } = await import("./token-goat-chunk-
|
|
15758
|
+
const { relay } = await import("./token-goat-chunk-GFBXHGFY.mjs");
|
|
15696
15759
|
await relay(event);
|
|
15697
15760
|
}
|
|
15698
15761
|
async function cmdInstall(opts) {
|
|
@@ -16234,23 +16297,22 @@ async function cmdPdfLocate(file, pattern, opts) {
|
|
|
16234
16297
|
if (opts.maxMatches !== void 0) locateOpts.maxMatches = requirePositiveInt("--max-matches", opts.maxMatches);
|
|
16235
16298
|
if (opts.context !== void 0) locateOpts.context = requirePositiveInt("--context", opts.context);
|
|
16236
16299
|
if (opts.pages !== void 0) locateOpts.pages = opts.pages;
|
|
16237
|
-
const matches2 = await runPdfLocate(file, pattern, locateOpts);
|
|
16300
|
+
const { matches: matches2, truncated } = await runPdfLocate(file, pattern, locateOpts);
|
|
16238
16301
|
const pages = matches2.map((m) => m.page);
|
|
16239
16302
|
let printed;
|
|
16240
16303
|
if (opts.json === true) {
|
|
16241
16304
|
const fencedMatches = matches2.map((m) => ({ ...m, snippet: fenceFileFieldIfMatched(m.snippet) }));
|
|
16242
|
-
printed = JSON.stringify({ file, pattern, matchCount: fencedMatches.length, pages, matches: fencedMatches }, null, 2);
|
|
16305
|
+
printed = JSON.stringify({ file, pattern, matchCount: fencedMatches.length, truncated, pages, matches: fencedMatches }, null, 2);
|
|
16243
16306
|
out(printed);
|
|
16244
16307
|
} else if (matches2.length === 0) {
|
|
16245
16308
|
printed = "(no matches)";
|
|
16246
16309
|
out(printed);
|
|
16247
16310
|
} else {
|
|
16248
16311
|
const lines = matches2.map((m) => `p${m.page}: ${m.snippet}`);
|
|
16249
|
-
|
|
16250
|
-
|
|
16312
|
+
const summary = truncated ? `at least ${countNoun(matches2.length, "match", "matches")} across at least ${countNoun(pages.length, "page")}; scan stopped at --max-matches, raise it for more` : `${countNoun(matches2.length, "match", "matches")} across ${countNoun(pages.length, "page")}`;
|
|
16313
|
+
printed = fenceFileText(`${lines.join("\n")}
|
|
16251
16314
|
|
|
16252
|
-
${
|
|
16253
|
-
);
|
|
16315
|
+
${summary}`);
|
|
16254
16316
|
out(printed);
|
|
16255
16317
|
}
|
|
16256
16318
|
const fullSourceBytes = fileSizeOrZero(file);
|
|
@@ -16626,7 +16688,7 @@ function emitExtraFileArgsNote(command, first, extras, opts = {}) {
|
|
|
16626
16688
|
}
|
|
16627
16689
|
async function cmdCompress(opts) {
|
|
16628
16690
|
try {
|
|
16629
|
-
const bashRunner = await import("./token-goat-chunk-
|
|
16691
|
+
const bashRunner = await import("./token-goat-chunk-KFFAZ5DJ.mjs");
|
|
16630
16692
|
if (opts.compress === false) {
|
|
16631
16693
|
process.exitCode = bashRunner.runRaw(opts.cmd, parseTimeout(opts.timeout, bashRunner.DEFAULT_TIMEOUT_SECONDS));
|
|
16632
16694
|
return;
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
runSkeleton,
|
|
26
26
|
runSymbol,
|
|
27
27
|
withPinnedReads
|
|
28
|
-
} from "./token-goat-chunk-
|
|
28
|
+
} from "./token-goat-chunk-4P6GTCMM.mjs";
|
|
29
29
|
import {
|
|
30
30
|
buildProjectMap,
|
|
31
31
|
embeddingsDepsAvailable,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
getProjectIndexCounts,
|
|
35
35
|
isWorkerRunning,
|
|
36
36
|
mapLookupBytesSaved
|
|
37
|
-
} from "./token-goat-chunk-
|
|
37
|
+
} from "./token-goat-chunk-U4FTM2SB.mjs";
|
|
38
38
|
import {
|
|
39
39
|
ENV_KEYS,
|
|
40
40
|
VERSION,
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
recordStat,
|
|
49
49
|
resolveProjectRoot,
|
|
50
50
|
savedTokensFromBytes
|
|
51
|
-
} from "./token-goat-chunk-
|
|
51
|
+
} from "./token-goat-chunk-ZOKNDG6V.mjs";
|
|
52
52
|
import "./token-goat-chunk-EEIDFMEM.mjs";
|
|
53
53
|
import {
|
|
54
54
|
init_define_import_meta_env
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
buildEvent,
|
|
5
5
|
relay,
|
|
6
6
|
relayInProcess
|
|
7
|
-
} from "./token-goat-chunk-
|
|
7
|
+
} from "./token-goat-chunk-ZLP6TCGN.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-JO5JX72D.mjs";
|
|
12
|
+
import "./token-goat-chunk-U4FTM2SB.mjs";
|
|
13
|
+
import "./token-goat-chunk-HTJP6FHK.mjs";
|
|
14
|
+
import "./token-goat-chunk-ZOKNDG6V.mjs";
|
|
15
15
|
import "./token-goat-chunk-EEIDFMEM.mjs";
|
|
16
16
|
import "./token-goat-chunk-A37V4PBF.mjs";
|
|
17
17
|
export {
|
|
@@ -2,7 +2,7 @@ import { createRequire as __cjsRequire } from 'node:module';
|
|
|
2
2
|
const require = __cjsRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
detectHarness
|
|
5
|
-
} from "./token-goat-chunk-
|
|
5
|
+
} from "./token-goat-chunk-ZOKNDG6V.mjs";
|
|
6
6
|
import {
|
|
7
7
|
init_define_import_meta_env
|
|
8
8
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
@@ -78,6 +78,7 @@ function canRunWrappedShell() {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
export {
|
|
81
|
+
bashOutputCapBytes,
|
|
81
82
|
deliveredOutputBytes,
|
|
82
83
|
wrappedShell,
|
|
83
84
|
canRunWrappedShell
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
isBlobStale,
|
|
10
10
|
loadBlob,
|
|
11
11
|
storeBlob
|
|
12
|
-
} from "./token-goat-chunk-
|
|
12
|
+
} from "./token-goat-chunk-U4FTM2SB.mjs";
|
|
13
13
|
import {
|
|
14
14
|
SYMBOL_BODY_CHAR_CAP,
|
|
15
15
|
copilotCliMcpToolsDir,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
resolveIndexPath,
|
|
25
25
|
shortFingerprint,
|
|
26
26
|
toDisplayPath
|
|
27
|
-
} from "./token-goat-chunk-
|
|
27
|
+
} from "./token-goat-chunk-ZOKNDG6V.mjs";
|
|
28
28
|
import {
|
|
29
29
|
registerReset
|
|
30
30
|
} from "./token-goat-chunk-EEIDFMEM.mjs";
|
|
@@ -3,7 +3,7 @@ const require = __cjsRequire(import.meta.url);
|
|
|
3
3
|
import {
|
|
4
4
|
deliveredOutputBytes,
|
|
5
5
|
wrappedShell
|
|
6
|
-
} from "./token-goat-chunk-
|
|
6
|
+
} from "./token-goat-chunk-HTJP6FHK.mjs";
|
|
7
7
|
import {
|
|
8
8
|
ToolFilter,
|
|
9
9
|
capTokens,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
recordStat,
|
|
16
16
|
selectFilter,
|
|
17
17
|
shlexSplit
|
|
18
|
-
} from "./token-goat-chunk-
|
|
18
|
+
} from "./token-goat-chunk-ZOKNDG6V.mjs";
|
|
19
19
|
import "./token-goat-chunk-EEIDFMEM.mjs";
|
|
20
20
|
import {
|
|
21
21
|
init_define_import_meta_env
|