token-goat 2.9.25 → 2.9.28
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 +28 -88
- package/SECURITY.md +14 -0
- package/dist/{token-goat-chunk-ORO4GOMA.mjs → token-goat-chunk-4JJBFT7V.mjs} +3 -3
- package/dist/token-goat-chunk-4JMWPWCS.mjs +96 -0
- package/dist/token-goat-chunk-4RN64ZND.mjs +954 -0
- package/dist/{token-goat-chunk-6W2FFT6H.mjs → token-goat-chunk-4STDIGYC.mjs} +2 -2
- package/dist/{token-goat-chunk-EZVRN44Y.mjs → token-goat-chunk-5NNYIUGV.mjs} +2 -2
- package/dist/{token-goat-chunk-ILROZWXE.mjs → token-goat-chunk-66LODAUT.mjs} +1 -1
- package/dist/{token-goat-chunk-VAIJUZG6.mjs → token-goat-chunk-6CCQDAYY.mjs} +69 -566
- package/dist/{token-goat-chunk-UGCNTVF4.mjs → token-goat-chunk-6DQNNFJ6.mjs} +5 -3
- package/dist/{token-goat-chunk-ZWFP4ZU7.mjs → token-goat-chunk-6SGLIPQB.mjs} +40 -20
- package/dist/{token-goat-chunk-TWVFMUTZ.mjs → token-goat-chunk-6Z5ULNE5.mjs} +3570 -3970
- package/dist/token-goat-chunk-7MAFDRVR.mjs +47 -0
- package/dist/{token-goat-chunk-PPNKB5HP.mjs → token-goat-chunk-7R2XYKC5.mjs} +6 -5
- package/dist/{token-goat-chunk-KYV7E6ZJ.mjs → token-goat-chunk-BCN2YQC6.mjs} +10 -8
- package/dist/token-goat-chunk-BJBRGPBX.mjs +244 -0
- package/dist/{token-goat-chunk-Z5ZTBSHL.mjs → token-goat-chunk-CBMY2FGI.mjs} +479 -544
- package/dist/{token-goat-chunk-UTKNLKYE.mjs → token-goat-chunk-CC2PYJM7.mjs} +2 -1
- package/dist/{token-goat-chunk-7PQYG6TN.mjs → token-goat-chunk-D5ICEPSB.mjs} +14 -14
- package/dist/token-goat-chunk-D7GHQKQD.mjs +30 -0
- package/dist/{token-goat-chunk-NNXCBELZ.mjs → token-goat-chunk-EL7M26WP.mjs} +7623 -8455
- package/dist/{token-goat-chunk-TVTDINTO.mjs → token-goat-chunk-F7QZRIWM.mjs} +69 -20
- package/dist/{token-goat-chunk-MBRX5AP6.mjs → token-goat-chunk-FSTWAOW6.mjs} +3 -3
- package/dist/token-goat-chunk-GGLEE35R.mjs +564 -0
- package/dist/{token-goat-chunk-YZ67F2HJ.mjs → token-goat-chunk-HUDC5GS5.mjs} +2 -2
- package/dist/{token-goat-chunk-BIBZQRC6.mjs → token-goat-chunk-HXNAC4ZF.mjs} +22 -964
- package/dist/token-goat-chunk-I7CB3X4K.mjs +1379 -0
- package/dist/{token-goat-chunk-KMCVX3P2.mjs → token-goat-chunk-IFORDBGC.mjs} +32 -27
- package/dist/{token-goat-chunk-25NRXKIW.mjs → token-goat-chunk-IHKZ3QNA.mjs} +26 -15
- package/dist/token-goat-chunk-IZXKVT4A.mjs +711 -0
- package/dist/{token-goat-chunk-UEQUZDHQ.mjs → token-goat-chunk-JXK2HQXS.mjs} +22 -8
- package/dist/{token-goat-chunk-YE4TGC4Z.mjs → token-goat-chunk-L45ZQRT7.mjs} +1 -1
- package/dist/{token-goat-chunk-IEF2NZFZ.mjs → token-goat-chunk-L7SDVGBT.mjs} +196 -14
- package/dist/token-goat-chunk-LEG3JNJ6.mjs +139 -0
- package/dist/{token-goat-chunk-3FSAZR32.mjs → token-goat-chunk-M56BWPBN.mjs} +1 -1
- package/dist/{token-goat-chunk-QZZPWFVF.mjs → token-goat-chunk-MAMQPC43.mjs} +2 -87
- package/dist/{token-goat-chunk-OHMKCBZI.mjs → token-goat-chunk-MMLMALWK.mjs} +5 -3
- package/dist/{token-goat-chunk-KOL5WXDW.mjs → token-goat-chunk-MVSWBNMD.mjs} +7 -231
- package/dist/{token-goat-chunk-J2PRBQ24.mjs → token-goat-chunk-NILVK7XM.mjs} +4 -4
- package/dist/{token-goat-chunk-OUQIGPW3.mjs → token-goat-chunk-Q4S3UQGO.mjs} +1 -1
- package/dist/{token-goat-chunk-EX2DVKAT.mjs → token-goat-chunk-QM76S6YS.mjs} +3 -3
- package/dist/{token-goat-chunk-G7YWBH25.mjs → token-goat-chunk-RJH64KQH.mjs} +86 -72
- package/dist/{token-goat-chunk-RLDBVMXR.mjs → token-goat-chunk-RSS3TLXU.mjs} +2 -2
- package/dist/{token-goat-chunk-T6652D3F.mjs → token-goat-chunk-SJEKA7Y2.mjs} +21 -16
- package/dist/{token-goat-chunk-II5WBDFB.mjs → token-goat-chunk-UBUKHVYW.mjs} +1 -1
- package/dist/{token-goat-chunk-2SSDSUSF.mjs → token-goat-chunk-VE27HPIF.mjs} +14 -10
- package/dist/{token-goat-chunk-Y463KPAQ.mjs → token-goat-chunk-VWZKZPSR.mjs} +100 -23
- package/dist/{token-goat-chunk-K4TNHLGS.mjs → token-goat-chunk-XI2VFAV6.mjs} +6 -6
- package/dist/{token-goat-chunk-ZDFDCXU2.mjs → token-goat-chunk-XKY4VKJ4.mjs} +1 -1
- package/dist/{token-goat-chunk-BQ6ZDLTF.mjs → token-goat-chunk-YWSP6IU7.mjs} +1 -1
- package/dist/token-goat-hook.mjs +23 -17
- package/dist/token-goat.core.mjs +32 -27
- package/docs/cli.md +32 -21
- package/docs/install.md +2 -0
- package/package.json +1 -1
- package/dist/token-goat-chunk-EDCVQLBR.mjs +0 -26
- package/dist/token-goat-chunk-WEYODFTA.mjs +0 -41
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
import { createRequire as __cjsRequire } from 'node:module';
|
|
2
2
|
const require = __cjsRequire(import.meta.url);
|
|
3
|
-
import {
|
|
4
|
-
compareSemver
|
|
5
|
-
} from "./token-goat-chunk-EZVRN44Y.mjs";
|
|
6
|
-
import {
|
|
7
|
-
buildCopilotWasteReport,
|
|
8
|
-
findLatestCopilotSession,
|
|
9
|
-
findProjectSession,
|
|
10
|
-
isCopilotTranscript
|
|
11
|
-
} from "./token-goat-chunk-UEQUZDHQ.mjs";
|
|
12
|
-
import {
|
|
13
|
-
buildResumePacket
|
|
14
|
-
} from "./token-goat-chunk-K4TNHLGS.mjs";
|
|
15
3
|
import {
|
|
16
4
|
ALL_SYMBOLS_IN_FILE_LIMIT,
|
|
17
5
|
AMBIGUOUS_HEADING_LIMIT,
|
|
@@ -90,6 +78,7 @@ import {
|
|
|
90
78
|
runScreenshot,
|
|
91
79
|
runSection,
|
|
92
80
|
runSemantic,
|
|
81
|
+
runSemanticMulti,
|
|
93
82
|
runSimilar,
|
|
94
83
|
runSkeleton,
|
|
95
84
|
runSqliteQuery,
|
|
@@ -107,7 +96,21 @@ import {
|
|
|
107
96
|
symbolNamesInFile,
|
|
108
97
|
upsertNote,
|
|
109
98
|
warnIfFilesStale
|
|
110
|
-
} from "./token-goat-chunk-
|
|
99
|
+
} from "./token-goat-chunk-VWZKZPSR.mjs";
|
|
100
|
+
import {
|
|
101
|
+
compareSemver
|
|
102
|
+
} from "./token-goat-chunk-5NNYIUGV.mjs";
|
|
103
|
+
import {
|
|
104
|
+
MCP_DISABLE_NOTE,
|
|
105
|
+
buildCopilotWasteReport,
|
|
106
|
+
findLatestCopilotSession,
|
|
107
|
+
findProjectSession,
|
|
108
|
+
isCopilotTranscript,
|
|
109
|
+
unusedMcpServers
|
|
110
|
+
} from "./token-goat-chunk-JXK2HQXS.mjs";
|
|
111
|
+
import {
|
|
112
|
+
buildResumePacket
|
|
113
|
+
} from "./token-goat-chunk-XI2VFAV6.mjs";
|
|
111
114
|
import {
|
|
112
115
|
DEFAULT_RECONCILE_BUDGET_MS,
|
|
113
116
|
HOOK_EVENTS,
|
|
@@ -126,19 +129,9 @@ import {
|
|
|
126
129
|
runRecallCommand,
|
|
127
130
|
runReconcile,
|
|
128
131
|
storeWebOutput
|
|
129
|
-
} from "./token-goat-chunk-
|
|
130
|
-
import {
|
|
131
|
-
buildWasteReport,
|
|
132
|
-
extractResultText,
|
|
133
|
-
findLatestTranscript,
|
|
134
|
-
projectTranscriptsDir,
|
|
135
|
-
safeStringify
|
|
136
|
-
} from "./token-goat-chunk-UGCNTVF4.mjs";
|
|
132
|
+
} from "./token-goat-chunk-VE27HPIF.mjs";
|
|
137
133
|
import {
|
|
138
|
-
|
|
139
|
-
} from "./token-goat-chunk-IEF2NZFZ.mjs";
|
|
140
|
-
import {
|
|
141
|
-
GEMINI_TOOL_NAME_MAP,
|
|
134
|
+
HINT_CATEGORIES,
|
|
142
135
|
MAX_FILES_SCANNED,
|
|
143
136
|
SKIP_DIRS,
|
|
144
137
|
WORKER_HEARTBEAT_STALE_MS,
|
|
@@ -208,15 +201,26 @@ import {
|
|
|
208
201
|
visionTokensSavedByText,
|
|
209
202
|
walkProject,
|
|
210
203
|
writeCompact
|
|
211
|
-
} from "./token-goat-chunk-
|
|
204
|
+
} from "./token-goat-chunk-6Z5ULNE5.mjs";
|
|
205
|
+
import {
|
|
206
|
+
GEMINI_TOOL_NAME_MAP
|
|
207
|
+
} from "./token-goat-chunk-IZXKVT4A.mjs";
|
|
212
208
|
import {
|
|
213
209
|
CompressedOutput,
|
|
214
210
|
TOOL_FILTERS,
|
|
215
211
|
ToolFilter,
|
|
216
212
|
deliverCompressed,
|
|
217
213
|
detectFromCommand
|
|
218
|
-
} from "./token-goat-chunk-
|
|
214
|
+
} from "./token-goat-chunk-RJH64KQH.mjs";
|
|
219
215
|
import {
|
|
216
|
+
buildWasteReport,
|
|
217
|
+
extractResultText,
|
|
218
|
+
findLatestTranscript,
|
|
219
|
+
projectTranscriptsDir,
|
|
220
|
+
safeStringify
|
|
221
|
+
} from "./token-goat-chunk-6DQNNFJ6.mjs";
|
|
222
|
+
import {
|
|
223
|
+
COPILOT_CLI_HOOK_SCRIPT,
|
|
220
224
|
HOOKS_SCRIPT_FILE,
|
|
221
225
|
MATERIALIZE_SHRUNK_IMAGE_JS,
|
|
222
226
|
buildGuidanceBlock,
|
|
@@ -253,7 +257,14 @@ import {
|
|
|
253
257
|
visualStudioProjectMcpPath,
|
|
254
258
|
visualStudioSolutionVscodeMcpPath,
|
|
255
259
|
visualStudioUserMcpPath
|
|
256
|
-
} from "./token-goat-chunk-
|
|
260
|
+
} from "./token-goat-chunk-MMLMALWK.mjs";
|
|
261
|
+
import {
|
|
262
|
+
buildManifest,
|
|
263
|
+
clearAll,
|
|
264
|
+
loadEntries,
|
|
265
|
+
setEntry,
|
|
266
|
+
unsetEntry
|
|
267
|
+
} from "./token-goat-chunk-L7SDVGBT.mjs";
|
|
257
268
|
import {
|
|
258
269
|
AGENT_SALT_MARKER,
|
|
259
270
|
CONTEXT_AUTOCOMPACT_TOKENS,
|
|
@@ -266,8 +277,6 @@ import {
|
|
|
266
277
|
findLatestSessionId,
|
|
267
278
|
formatAge,
|
|
268
279
|
getContextPressure,
|
|
269
|
-
getSessionFiles,
|
|
270
|
-
getSessionId,
|
|
271
280
|
getSkillFilePath,
|
|
272
281
|
incrementSkillHit,
|
|
273
282
|
listOutputs,
|
|
@@ -279,27 +288,39 @@ import {
|
|
|
279
288
|
skillOutputsDir,
|
|
280
289
|
storeCompact,
|
|
281
290
|
storeOutput
|
|
282
|
-
} from "./token-goat-chunk-
|
|
291
|
+
} from "./token-goat-chunk-6CCQDAYY.mjs";
|
|
292
|
+
import {
|
|
293
|
+
getSessionFiles,
|
|
294
|
+
getSessionId
|
|
295
|
+
} from "./token-goat-chunk-GGLEE35R.mjs";
|
|
283
296
|
import {
|
|
284
|
-
capJsonRows,
|
|
285
297
|
claudeConfigDir,
|
|
286
|
-
estimateTokens,
|
|
287
|
-
estimateTokensFromLength,
|
|
288
298
|
formatBytes,
|
|
289
|
-
formatTokenEstimate
|
|
290
|
-
|
|
291
|
-
} from "./token-goat-chunk-QZZPWFVF.mjs";
|
|
299
|
+
formatTokenEstimate
|
|
300
|
+
} from "./token-goat-chunk-MAMQPC43.mjs";
|
|
292
301
|
import {
|
|
293
302
|
BASH_OUTPUT_SUBDIR,
|
|
294
|
-
clipLongMatchLine,
|
|
295
|
-
combineStreams,
|
|
296
303
|
getBashOutput,
|
|
297
304
|
isRecallCacheType
|
|
298
|
-
} from "./token-goat-chunk-
|
|
305
|
+
} from "./token-goat-chunk-HXNAC4ZF.mjs";
|
|
299
306
|
import {
|
|
300
|
-
C,
|
|
301
307
|
DEFAULT_MAX_AGE_MS,
|
|
302
308
|
DEFAULT_MAX_COUNT,
|
|
309
|
+
listBlobs,
|
|
310
|
+
pruneBlobs
|
|
311
|
+
} from "./token-goat-chunk-BJBRGPBX.mjs";
|
|
312
|
+
import {
|
|
313
|
+
capJsonRows,
|
|
314
|
+
estimateTokens,
|
|
315
|
+
estimateTokensFromLength,
|
|
316
|
+
trimToBudget
|
|
317
|
+
} from "./token-goat-chunk-4JMWPWCS.mjs";
|
|
318
|
+
import {
|
|
319
|
+
clipLongMatchLine,
|
|
320
|
+
combineStreams
|
|
321
|
+
} from "./token-goat-chunk-4RN64ZND.mjs";
|
|
322
|
+
import {
|
|
323
|
+
C,
|
|
303
324
|
HOOK_STATS_RETENTION_DAYS,
|
|
304
325
|
RESET,
|
|
305
326
|
_useRichStats,
|
|
@@ -308,8 +329,6 @@ import {
|
|
|
308
329
|
fg,
|
|
309
330
|
formatLocalTimestamp,
|
|
310
331
|
getGlobalDb,
|
|
311
|
-
listBlobs,
|
|
312
|
-
pruneBlobs,
|
|
313
332
|
pruneStalePatternCoveredUnmappedTools,
|
|
314
333
|
readUnmappedTools,
|
|
315
334
|
recordStat,
|
|
@@ -321,19 +340,19 @@ import {
|
|
|
321
340
|
statsHasHarnessColumn,
|
|
322
341
|
stripAnsiEscapes,
|
|
323
342
|
summarize
|
|
324
|
-
} from "./token-goat-chunk-
|
|
343
|
+
} from "./token-goat-chunk-MVSWBNMD.mjs";
|
|
325
344
|
import {
|
|
326
345
|
docxOutline,
|
|
327
346
|
docxTables,
|
|
328
347
|
docxText,
|
|
329
348
|
formatDocxTables
|
|
330
|
-
} from "./token-goat-chunk-
|
|
349
|
+
} from "./token-goat-chunk-XKY4VKJ4.mjs";
|
|
331
350
|
import {
|
|
332
351
|
pptxNotesText,
|
|
333
352
|
pptxOutline,
|
|
334
353
|
pptxSlideText,
|
|
335
354
|
pptxTextGrep
|
|
336
|
-
} from "./token-goat-chunk-
|
|
355
|
+
} from "./token-goat-chunk-Q4S3UQGO.mjs";
|
|
337
356
|
import {
|
|
338
357
|
formatXlsxColumns,
|
|
339
358
|
formatXlsxRange,
|
|
@@ -342,11 +361,11 @@ import {
|
|
|
342
361
|
querySheet,
|
|
343
362
|
rangeSheet,
|
|
344
363
|
xlsxColumns
|
|
345
|
-
} from "./token-goat-chunk-
|
|
364
|
+
} from "./token-goat-chunk-RSS3TLXU.mjs";
|
|
346
365
|
import {
|
|
347
366
|
formatCsvTable,
|
|
348
367
|
parseWhereSpecs
|
|
349
|
-
} from "./token-goat-chunk-
|
|
368
|
+
} from "./token-goat-chunk-YWSP6IU7.mjs";
|
|
350
369
|
import {
|
|
351
370
|
assetEmbedSha,
|
|
352
371
|
deleteFileEmbeddings,
|
|
@@ -372,12 +391,12 @@ import {
|
|
|
372
391
|
readSection,
|
|
373
392
|
treeSitterCoreAvailable,
|
|
374
393
|
treeSitterCoreLoadError
|
|
375
|
-
} from "./token-goat-chunk-
|
|
394
|
+
} from "./token-goat-chunk-D5ICEPSB.mjs";
|
|
376
395
|
import {
|
|
377
396
|
getFileEntry,
|
|
378
397
|
getProjectFileEntries,
|
|
379
398
|
querySymbols
|
|
380
|
-
} from "./token-goat-chunk-
|
|
399
|
+
} from "./token-goat-chunk-HUDC5GS5.mjs";
|
|
381
400
|
import {
|
|
382
401
|
TREE_SITTER_LANGUAGES,
|
|
383
402
|
detectLanguage,
|
|
@@ -388,7 +407,7 @@ import {
|
|
|
388
407
|
matchGroovySlashy,
|
|
389
408
|
nonTreeSitterLanguageCount,
|
|
390
409
|
redactIfDotenv
|
|
391
|
-
} from "./token-goat-chunk-
|
|
410
|
+
} from "./token-goat-chunk-M56BWPBN.mjs";
|
|
392
411
|
import {
|
|
393
412
|
CONFIG_KEY_ENV_OVERRIDES,
|
|
394
413
|
PROJECT_LOCKED_KEYS,
|
|
@@ -417,7 +436,7 @@ import {
|
|
|
417
436
|
stringify,
|
|
418
437
|
validateEnumField,
|
|
419
438
|
validateNumericField
|
|
420
|
-
} from "./token-goat-chunk-
|
|
439
|
+
} from "./token-goat-chunk-CC2PYJM7.mjs";
|
|
421
440
|
import {
|
|
422
441
|
ENV_KEYS,
|
|
423
442
|
LOCK_WAIT_MS_HARDENED,
|
|
@@ -478,7 +497,7 @@ import {
|
|
|
478
497
|
withRetryOnLock,
|
|
479
498
|
writeIfDifferent,
|
|
480
499
|
writeJsonSettings
|
|
481
|
-
} from "./token-goat-chunk-
|
|
500
|
+
} from "./token-goat-chunk-L45ZQRT7.mjs";
|
|
482
501
|
import {
|
|
483
502
|
UNTRUSTED_FILE_TAG,
|
|
484
503
|
UNTRUSTED_TOOL_TAG,
|
|
@@ -3626,9 +3645,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3626
3645
|
* @param {string} [path]
|
|
3627
3646
|
* @return {(string|null|Command)}
|
|
3628
3647
|
*/
|
|
3629
|
-
executableDir(
|
|
3630
|
-
if (
|
|
3631
|
-
this._executableDir =
|
|
3648
|
+
executableDir(path41) {
|
|
3649
|
+
if (path41 === void 0) return this._executableDir;
|
|
3650
|
+
this._executableDir = path41;
|
|
3632
3651
|
return this;
|
|
3633
3652
|
}
|
|
3634
3653
|
/**
|
|
@@ -3928,8 +3947,8 @@ function attemptedCommandName(argv) {
|
|
|
3928
3947
|
}
|
|
3929
3948
|
|
|
3930
3949
|
// src/cli.ts
|
|
3931
|
-
import * as
|
|
3932
|
-
import * as
|
|
3950
|
+
import * as fs44 from "fs";
|
|
3951
|
+
import * as path40 from "path";
|
|
3933
3952
|
|
|
3934
3953
|
// src/walk_index.ts
|
|
3935
3954
|
init_define_import_meta_env();
|
|
@@ -4210,6 +4229,8 @@ var CANONICAL_SKILL_MD = gunzipSync(Buffer.from(CANONICAL_SKILL_GZIP_BASE64, "ba
|
|
|
4210
4229
|
var HOOK_EVENT_MAP = [
|
|
4211
4230
|
["PreToolUse", "pre_tool_use"],
|
|
4212
4231
|
["PostToolUse", "post_tool_use"],
|
|
4232
|
+
// A failed call never reaches PostToolUse: Claude Code 2.1.281 sends a missing-file Read and a non-zero Bash exit here instead, carrying `error`, `is_interrupt` and `duration_ms` (captured, 2026-09-24).
|
|
4233
|
+
["PostToolUseFailure", "post_tool_use_failure"],
|
|
4213
4234
|
["PreCompact", "pre_compact"],
|
|
4214
4235
|
["PostCompact", "post_compact"],
|
|
4215
4236
|
["UserPromptSubmit", "user_prompt_submit"],
|
|
@@ -4423,16 +4444,19 @@ function uninstallHooksScoped(scope) {
|
|
|
4423
4444
|
return true;
|
|
4424
4445
|
}
|
|
4425
4446
|
function isInstalled(scope = "user") {
|
|
4426
|
-
|
|
4427
|
-
const
|
|
4428
|
-
|
|
4447
|
+
if (!fs3.existsSync(claudeHookScriptPath())) return false;
|
|
4448
|
+
const missing = missingHookEvents(scope);
|
|
4449
|
+
return missing !== null && missing.length === 0;
|
|
4450
|
+
}
|
|
4451
|
+
function missingHookEvents(scope = "user") {
|
|
4452
|
+
const hooks = readSettings(settingsPath(scope)).hooks;
|
|
4453
|
+
if (hooks === void 0) return null;
|
|
4454
|
+
if (!HOOK_EVENT_MAP.some(([eventKey]) => groupHasTokenGoat(hooks[eventKey], isTokenGoatHookCommand))) return null;
|
|
4429
4455
|
const scriptPath = claudeHookScriptPath();
|
|
4430
|
-
|
|
4431
|
-
for (const [eventKey, eventArg] of HOOK_EVENT_MAP) {
|
|
4456
|
+
return HOOK_EVENT_MAP.filter(([eventKey, eventArg]) => {
|
|
4432
4457
|
const expected = expectedHookEntryFor(scriptPath, eventArg);
|
|
4433
|
-
|
|
4434
|
-
}
|
|
4435
|
-
return true;
|
|
4458
|
+
return !groupHasTokenGoat(hooks[eventKey], (c, a) => hookEntryMatches(c, a, expected));
|
|
4459
|
+
}).map(([eventKey]) => eventKey);
|
|
4436
4460
|
}
|
|
4437
4461
|
var CLAUDE_MD_BEGIN = "<!-- token-goat-begin -->";
|
|
4438
4462
|
var CLAUDE_MD_END = "<!-- token-goat-end -->";
|
|
@@ -7329,6 +7353,15 @@ function checkVscodeClaudeHooks(useClaudeHooks, claudeHooksInstalled, vscodeHook
|
|
|
7329
7353
|
message: vscodeHooksInstalled2 ? "VS Code has chat.useClaudeHooks on and token-goat hooks are in both ~/.claude/settings.json and the Copilot hooks file, so each hook fires twice in VS Code. Turn chat.useClaudeHooks off in VS Code settings." : 'VS Code has chat.useClaudeHooks on, so it runs the token-goat hooks from ~/.claude/settings.json in Claude Code wire format, which VS Code reads only in part. Run "token-goat install --vscode" and turn chat.useClaudeHooks off in VS Code settings.'
|
|
7330
7354
|
};
|
|
7331
7355
|
}
|
|
7356
|
+
function checkClaudeHookEvents(missing) {
|
|
7357
|
+
const name = "Claude Code hook events";
|
|
7358
|
+
if (missing.user === null && missing.project === null) return null;
|
|
7359
|
+
const gaps = [];
|
|
7360
|
+
if (missing.user !== null && missing.user.length > 0) gaps.push(`user scope lacks ${missing.user.join(", ")}; run: token-goat install`);
|
|
7361
|
+
if (missing.project !== null && missing.project.length > 0) gaps.push(`project scope lacks ${missing.project.join(", ")}; run: token-goat install --project`);
|
|
7362
|
+
if (gaps.length === 0) return { name, status: "ok", message: "every event this build handles is wired" };
|
|
7363
|
+
return { name, status: "warn", message: `${gaps.join(". ")}. Those events never reach token-goat until then; restart any running session afterwards.` };
|
|
7364
|
+
}
|
|
7332
7365
|
function dedupeByResolvedPath(paths) {
|
|
7333
7366
|
const seen = /* @__PURE__ */ new Set();
|
|
7334
7367
|
return paths.filter((p) => {
|
|
@@ -8055,8 +8088,22 @@ function checkCopilotCli(configPath2, scriptPath) {
|
|
|
8055
8088
|
message: 'hook did not return valid JSON -- Copilot treats this as a hook error and denies every tool call. Recovery: run "token-goat install --copilot", then fully restart Copilot CLI.'
|
|
8056
8089
|
};
|
|
8057
8090
|
}
|
|
8091
|
+
if (!shimIsCurrent(scriptPath, COPILOT_CLI_HOOK_SCRIPT)) {
|
|
8092
|
+
return { name: "Copilot CLI", status: "warn", message: staleShimMessage(scriptPath, "Copilot", "token-goat install --copilot") + ", then fully restart Copilot CLI." };
|
|
8093
|
+
}
|
|
8058
8094
|
return { name: "Copilot CLI", status: "ok", message: "preToolUse hook invokes cleanly and returns valid JSON" };
|
|
8059
8095
|
}
|
|
8096
|
+
function shimIsCurrent(scriptPath, expected) {
|
|
8097
|
+
return fs18.readFileSync(scriptPath, "utf-8").replace(/\r\n/g, "\n") === expected.replace(/\r\n/g, "\n");
|
|
8098
|
+
}
|
|
8099
|
+
function staleShimMessage(scriptPath, harness, reinstall) {
|
|
8100
|
+
return `hook shim at ${scriptPath} was written by an older token-goat build, so fixes to it since then are not reaching ${harness}. Recovery: run "${reinstall}"`;
|
|
8101
|
+
}
|
|
8102
|
+
function checkHookShim(name, scriptPath, expected, reinstall) {
|
|
8103
|
+
if (!fs18.existsSync(scriptPath)) return null;
|
|
8104
|
+
if (shimIsCurrent(scriptPath, expected)) return { name, status: "ok", message: `hook shim at ${scriptPath} matches this build` };
|
|
8105
|
+
return { name, status: "warn", message: staleShimMessage(scriptPath, name, reinstall) + ", then restart any running session." };
|
|
8106
|
+
}
|
|
8060
8107
|
var COMPACTION_CHANNEL_WINDOW = 5;
|
|
8061
8108
|
var COMPACTION_STATS_BATCH_SIZE = 50;
|
|
8062
8109
|
var COMPACTION_STATS_SCAN_CEILING = 2e3;
|
|
@@ -8218,6 +8265,12 @@ function runDoctor(dataDir2, configPath2, rootDir, processes) {
|
|
|
8218
8265
|
results.push(checkDiskSpace(actualDataDir));
|
|
8219
8266
|
const copilotResult = checkCopilotCli(copilotCliConfigPath(), copilotCliScriptPath());
|
|
8220
8267
|
if (copilotResult) results.push(copilotResult);
|
|
8268
|
+
const claudeShimResult = checkHookShim("Claude Code", claudeHookScriptPath(), CLAUDECODE_HOOK_SCRIPT, isInstalled("user") || !isInstalled("project") ? "token-goat install" : "token-goat install --project");
|
|
8269
|
+
if (claudeShimResult) results.push(claudeShimResult);
|
|
8270
|
+
const claudeEventsResult = checkClaudeHookEvents({ user: missingHookEvents("user"), project: missingHookEvents("project") });
|
|
8271
|
+
if (claudeEventsResult) results.push(claudeEventsResult);
|
|
8272
|
+
const codexShimResult = checkHookShim("Codex", codexHookScriptPath(), CODEX_HOOK_SCRIPT, "token-goat install --codex");
|
|
8273
|
+
if (codexShimResult) results.push(codexShimResult);
|
|
8221
8274
|
const vscodeHooksResult = checkVscodeClaudeHooks(
|
|
8222
8275
|
vscodeUsesClaudeHooks(),
|
|
8223
8276
|
isInstalled("user") || isInstalled("project"),
|
|
@@ -8470,7 +8523,7 @@ async function runDoctorAndExit(opts) {
|
|
|
8470
8523
|
}
|
|
8471
8524
|
}
|
|
8472
8525
|
try {
|
|
8473
|
-
const { checkUpdateStatus } = await import("./token-goat-chunk-
|
|
8526
|
+
const { checkUpdateStatus } = await import("./token-goat-chunk-4JJBFT7V.mjs");
|
|
8474
8527
|
const update = await checkUpdateStatus(1500);
|
|
8475
8528
|
if (update.updateAvailable && update.latest) {
|
|
8476
8529
|
console.log(`
|
|
@@ -8566,7 +8619,7 @@ function generateCompactHelp() {
|
|
|
8566
8619
|
" -h, --help display help for command",
|
|
8567
8620
|
"",
|
|
8568
8621
|
"Reads: symbol, read, brief, section, semantic, skeleton, outline, refs, scope,",
|
|
8569
|
-
" similar, context-for, call-chain, impact, callers, dead, test-for",
|
|
8622
|
+
" similar, context-for, call-chain, impact, callers, dead, test-for, locate",
|
|
8570
8623
|
"",
|
|
8571
8624
|
"Analysis: arch, affected, blame, deps, types, coverage-gaps, changed, diff, log,",
|
|
8572
8625
|
" exports, imports, find, grep",
|
|
@@ -8579,19 +8632,18 @@ function generateCompactHelp() {
|
|
|
8579
8632
|
"",
|
|
8580
8633
|
"Index & Search: index, map, reconcile, doctor, commands, ask, answer, pack, tokens,",
|
|
8581
8634
|
" budget, failures, todo, trace, logfold, lockdeps, dep-docs, recent, hot,",
|
|
8582
|
-
"
|
|
8635
|
+
" baseline, cost, coverage-report-gaps, clean-cache,",
|
|
8583
8636
|
" cache-audit, reclaim-index, project",
|
|
8584
8637
|
"",
|
|
8585
8638
|
"Session: stats, waste, session-outline, session-audit, session-slice,",
|
|
8586
8639
|
" session-summary, context-stats, bootstrap-audit, memory, hint-stats,",
|
|
8587
|
-
" session-schema, mcp-audit",
|
|
8640
|
+
" session-schema, mcp-audit, audit",
|
|
8588
8641
|
"",
|
|
8589
8642
|
"Skills: skill-body, skill-compact, skill-list, skill-size, skill-history,",
|
|
8590
8643
|
" skill-diff, skill-section",
|
|
8591
8644
|
"",
|
|
8592
8645
|
"Compression: compress-text, retrieve, handoff-create, handoff-resolve,",
|
|
8593
|
-
" compress, recall, bash-output, web-output, mcp-output,
|
|
8594
|
-
" compress, bench",
|
|
8646
|
+
" compress, recall, bash-output, web-output, mcp-output, bench",
|
|
8595
8647
|
"",
|
|
8596
8648
|
"Config & Integration: install, uninstall, upgrade, mcp-serve, mcp-status, hook,",
|
|
8597
8649
|
" bridges-status, worker, statusline, version, config, config-get,",
|
|
@@ -8600,9 +8652,9 @@ function generateCompactHelp() {
|
|
|
8600
8652
|
"Data: note, note-add, note-get, note-list, describe, sqlite-query,",
|
|
8601
8653
|
" sqlite-tables, sqlite-schema, csv-profile, csv-query",
|
|
8602
8654
|
"",
|
|
8603
|
-
"Utils: ignores, bash-history, web-history, openapi-op, openapi-outline,",
|
|
8604
|
-
" gdrive-sections, screenshot,
|
|
8605
|
-
" image-text,
|
|
8655
|
+
"Utils: ignores, bash-history, web-history, history, openapi-op, openapi-outline,",
|
|
8656
|
+
" gdrive-sections, screenshot, fetch-image, image-meta,",
|
|
8657
|
+
" image-text, resume, replace, insert-section, pr-slice,",
|
|
8606
8658
|
" sharepoint-resolve, transcript, transcript-outline, video-chapters,",
|
|
8607
8659
|
" write-file, zip-list, zip-read, mcp-history, compact-doc, compact-hint,",
|
|
8608
8660
|
" conflicts, prune-cache",
|
|
@@ -8904,12 +8956,9 @@ function performHttpFetch(targetUrl, opts) {
|
|
|
8904
8956
|
});
|
|
8905
8957
|
}
|
|
8906
8958
|
|
|
8907
|
-
// src/
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
saveConfig(cfg);
|
|
8911
|
-
}
|
|
8912
|
-
function levenshtein(a, b, cap = 3) {
|
|
8959
|
+
// src/util_suggest.ts
|
|
8960
|
+
init_define_import_meta_env();
|
|
8961
|
+
function levenshteinDistance(a, b, cap = 3) {
|
|
8913
8962
|
if (Math.abs(a.length - b.length) > cap) return cap + 1;
|
|
8914
8963
|
const prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
8915
8964
|
for (let i = 1; i <= a.length; i++) {
|
|
@@ -8922,8 +8971,17 @@ function levenshtein(a, b, cap = 3) {
|
|
|
8922
8971
|
}
|
|
8923
8972
|
return prev[b.length] ?? cap + 1;
|
|
8924
8973
|
}
|
|
8974
|
+
function suggestPackageNames(query, names) {
|
|
8975
|
+
return [...new Set(names)].map((n) => ({ n, d: levenshteinDistance(query.toLowerCase(), n.toLowerCase()) })).filter((x) => x.d <= 3).sort((a, b) => a.d - b.d).slice(0, 5).map((x) => x.n);
|
|
8976
|
+
}
|
|
8977
|
+
|
|
8978
|
+
// src/config_commands.ts
|
|
8979
|
+
function saveConfigSafe(cfg) {
|
|
8980
|
+
ensureDirSync(path18.dirname(configPath()));
|
|
8981
|
+
saveConfig(cfg);
|
|
8982
|
+
}
|
|
8925
8983
|
function closestKeys(unknown, known) {
|
|
8926
|
-
return known.map((k) => ({ k, d:
|
|
8984
|
+
return known.map((k) => ({ k, d: levenshteinDistance(unknown, k) })).filter((x) => x.d <= 3).sort((a, b) => a.d - b.d).slice(0, 3).map((x) => x.k);
|
|
8927
8985
|
}
|
|
8928
8986
|
function didYouMeanKeySuffix(unknownKey) {
|
|
8929
8987
|
const knownKeys = flattenConfig(defaultConfig()).map(([k]) => k);
|
|
@@ -14012,13 +14070,13 @@ function registerFormatCommands(program2, guard) {
|
|
|
14012
14070
|
[]
|
|
14013
14071
|
).option("--head <n>", "limit to the first N matching rows").option("--json", "emit rows as a JSON array of objects instead of CSV").option("--delimiter <char>", "field delimiter (default: ,)").option("--no-header", "treat the first row as data, not a header (columns become col1, col2, ...)").action(guard(cmdCsvQuery));
|
|
14014
14072
|
program2.command("csv-profile <file>").description("per-column type/null/distinct/range summary of a CSV instead of a raw Read").option("--delimiter <char>", "field delimiter (default: ,)").option("--no-header", "treat the first row as data, not a header (columns become col1, col2, ...)").action(guard(cmdCsvProfile));
|
|
14015
|
-
program2.command("json-outline <file>").description("structural summary of a JSON document (array shape / object key types) instead of a raw Read").option("--json", "emit the outline as JSON instead of text").action(guard(cmdJsonOutline));
|
|
14073
|
+
program2.command("json-outline <file>").description("structural summary of a JSON document (array shape / object key types) instead of a raw Read").option("--json", "emit the outline as JSON instead of text").option("--filter <text>", "list only the top-level keys containing TEXT (case-insensitive), with a count of how many matched").action(guard(cmdJsonOutline));
|
|
14016
14074
|
program2.command("json-query <file> <path>").description(
|
|
14017
|
-
|
|
14075
|
+
'extract one value or a projected/filtered subset from a JSON document by dot-path instead of a raw Read\n\npath grammar: dot-separated keys with optional bracket segments -- [n] index, [*] wildcard (projects every element/value), [field=value] filter (keeps array elements whose field stringifies to value), ["key"] for a key holding a dot or space. Examples: data.items[3].name, items[*].id, items[status=active], ["a.b"].c'
|
|
14018
14076
|
).option("--head <n>", "limit a projected/filtered result to the first N items").option("--json", "emit the result as JSON instead of text").action(guard(cmdJsonQuery));
|
|
14019
|
-
program2.command("yaml-outline <file>").description("structural summary of a YAML document (array shape / object key types) instead of a raw Read -- multi-document streams (---separated) outline as an array of documents").option("--json", "emit the outline as JSON instead of text").action(guard(cmdYamlOutline));
|
|
14077
|
+
program2.command("yaml-outline <file>").description("structural summary of a YAML document (array shape / object key types) instead of a raw Read -- multi-document streams (---separated) outline as an array of documents").option("--json", "emit the outline as JSON instead of text").option("--filter <text>", "list only the top-level keys containing TEXT (case-insensitive), with a count of how many matched").action(guard(cmdYamlOutline));
|
|
14020
14078
|
program2.command("yaml-query <file> <path>").description(
|
|
14021
|
-
|
|
14079
|
+
'extract one value or a projected/filtered subset from a YAML document by dot-path instead of a raw Read (same grammar as json-query)\n\npath grammar: dot-separated keys with optional bracket segments -- [n] index, [*] wildcard (projects every element/value), [field=value] filter (keeps array elements whose field stringifies to value), ["key"] for a key holding a dot or space. Examples: spec.containers[0].image, items[*].name, items[kind=Service]'
|
|
14022
14080
|
).option("--head <n>", "limit a projected/filtered result to the first N items").option("--json", "emit the result as JSON instead of text").action(guard(cmdYamlQuery));
|
|
14023
14081
|
program2.command("xml-outline <file>").description("structural summary of an XML document (element hierarchy / attribute names / child counts) instead of a raw Read").option("--json", "emit the outline as JSON instead of text").option("--max-depth <n>", "max depth of element hierarchy to show").option("--depth <n>", "alias for --max-depth").action(guard(cmdXmlOutline));
|
|
14024
14082
|
program2.command("xml-query <file> [path]").description(
|
|
@@ -14383,153 +14441,13 @@ function runAffected(opts) {
|
|
|
14383
14441
|
|
|
14384
14442
|
// src/text_commands.ts
|
|
14385
14443
|
init_define_import_meta_env();
|
|
14386
|
-
import * as
|
|
14387
|
-
import * as
|
|
14388
|
-
|
|
14389
|
-
// src/project_memory.ts
|
|
14390
|
-
init_define_import_meta_env();
|
|
14391
|
-
import * as fs28 from "node:fs";
|
|
14392
|
-
import * as path26 from "node:path";
|
|
14393
|
-
var MAX_ENTRIES = 30;
|
|
14394
|
-
var KEY_RE2 = /^[A-Za-z0-9_-]{1,80}$/;
|
|
14395
|
-
function ordinal(a, b) {
|
|
14396
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
14397
|
-
}
|
|
14398
|
-
function memoryPath(projectHash) {
|
|
14399
|
-
return path26.join(dataDir(), "projects", `${projectHash}_memory.toml`);
|
|
14400
|
-
}
|
|
14401
|
-
function validateKey2(key) {
|
|
14402
|
-
if (!KEY_RE2.test(key)) {
|
|
14403
|
-
throw new Error(
|
|
14404
|
-
`Invalid memory key ${JSON.stringify(key)}: use only letters, digits, hyphens, underscores (max 80 chars)`
|
|
14405
|
-
);
|
|
14406
|
-
}
|
|
14407
|
-
}
|
|
14408
|
-
function parseTOML(content) {
|
|
14409
|
-
const result = {};
|
|
14410
|
-
for (const line of content.split("\n")) {
|
|
14411
|
-
const trimmed = line.trim();
|
|
14412
|
-
if (!trimmed || trimmed.startsWith("#")) {
|
|
14413
|
-
continue;
|
|
14414
|
-
}
|
|
14415
|
-
const match2 = trimmed.match(/^([A-Za-z0-9_-]+)\s*=\s*"(.*)"\s*$/);
|
|
14416
|
-
if (match2) {
|
|
14417
|
-
const [, key, value] = match2;
|
|
14418
|
-
if (key && value !== void 0) {
|
|
14419
|
-
const unescaped = value.replace(/\\([\\nrt"])/g, (_, c) => {
|
|
14420
|
-
switch (c) {
|
|
14421
|
-
case "\\":
|
|
14422
|
-
return "\\";
|
|
14423
|
-
case "n":
|
|
14424
|
-
return "\n";
|
|
14425
|
-
case "r":
|
|
14426
|
-
return "\r";
|
|
14427
|
-
case '"':
|
|
14428
|
-
return '"';
|
|
14429
|
-
default:
|
|
14430
|
-
return _;
|
|
14431
|
-
}
|
|
14432
|
-
});
|
|
14433
|
-
result[key] = unescaped;
|
|
14434
|
-
}
|
|
14435
|
-
}
|
|
14436
|
-
}
|
|
14437
|
-
return result;
|
|
14438
|
-
}
|
|
14439
|
-
function loadRaw(filePath) {
|
|
14440
|
-
try {
|
|
14441
|
-
if (!fs28.existsSync(filePath)) {
|
|
14442
|
-
return {};
|
|
14443
|
-
}
|
|
14444
|
-
const content = fs28.readFileSync(filePath, "utf-8");
|
|
14445
|
-
return parseTOML(content);
|
|
14446
|
-
} catch {
|
|
14447
|
-
return {};
|
|
14448
|
-
}
|
|
14449
|
-
}
|
|
14450
|
-
function save(filePath, entries) {
|
|
14451
|
-
const lines = [];
|
|
14452
|
-
const sorted = Object.entries(entries).sort(([a], [b]) => ordinal(a, b));
|
|
14453
|
-
for (const [k, v] of sorted) {
|
|
14454
|
-
const escaped = v.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\r/g, "\\r").replace(/\n/g, "\\n");
|
|
14455
|
-
lines.push(`${k} = "${escaped}"`);
|
|
14456
|
-
}
|
|
14457
|
-
const content = lines.length > 0 ? lines.join("\n") + "\n" : "";
|
|
14458
|
-
const dir = path26.dirname(filePath);
|
|
14459
|
-
ensureDirSync(dir);
|
|
14460
|
-
atomicWriteText(filePath, content);
|
|
14461
|
-
}
|
|
14462
|
-
function loadEntries(projectHash) {
|
|
14463
|
-
return loadRaw(memoryPath(projectHash));
|
|
14464
|
-
}
|
|
14465
|
-
function setEntry(projectHash, key, value) {
|
|
14466
|
-
validateKey2(key);
|
|
14467
|
-
const p = memoryPath(projectHash);
|
|
14468
|
-
const dir = path26.dirname(p);
|
|
14469
|
-
ensureDirSync(dir);
|
|
14470
|
-
const doSet = () => {
|
|
14471
|
-
const entries = loadRaw(p);
|
|
14472
|
-
const isNewKey = !(key in entries);
|
|
14473
|
-
if (isNewKey && Object.keys(entries).length >= MAX_ENTRIES) {
|
|
14474
|
-
const keysToKeep = MAX_ENTRIES - 1;
|
|
14475
|
-
const allKeys = Object.keys(entries).sort((a, b) => ordinal(a, b));
|
|
14476
|
-
for (const k of allKeys.slice(keysToKeep)) {
|
|
14477
|
-
delete entries[k];
|
|
14478
|
-
}
|
|
14479
|
-
}
|
|
14480
|
-
entries[key] = value;
|
|
14481
|
-
save(p, entries);
|
|
14482
|
-
return true;
|
|
14483
|
-
};
|
|
14484
|
-
if (withFileLock(`${p}.lock`, doSet) === void 0) doSet();
|
|
14485
|
-
}
|
|
14486
|
-
function unsetEntry(projectHash, key) {
|
|
14487
|
-
validateKey2(key);
|
|
14488
|
-
const p = memoryPath(projectHash);
|
|
14489
|
-
const doUnset = () => {
|
|
14490
|
-
const entries = loadRaw(p);
|
|
14491
|
-
if (key in entries) {
|
|
14492
|
-
delete entries[key];
|
|
14493
|
-
save(p, entries);
|
|
14494
|
-
}
|
|
14495
|
-
return true;
|
|
14496
|
-
};
|
|
14497
|
-
if (withFileLock(`${p}.lock`, doUnset) === void 0) doUnset();
|
|
14498
|
-
}
|
|
14499
|
-
function clearAll(projectHash) {
|
|
14500
|
-
const p = memoryPath(projectHash);
|
|
14501
|
-
const doClear = () => {
|
|
14502
|
-
if (fs28.existsSync(p)) {
|
|
14503
|
-
save(p, {});
|
|
14504
|
-
}
|
|
14505
|
-
return true;
|
|
14506
|
-
};
|
|
14507
|
-
if (withFileLock(`${p}.lock`, doClear) === void 0) doClear();
|
|
14508
|
-
}
|
|
14509
|
-
|
|
14510
|
-
// src/util_suggest.ts
|
|
14511
|
-
init_define_import_meta_env();
|
|
14512
|
-
function packageNameDistance(a, b, cap = 3) {
|
|
14513
|
-
if (Math.abs(a.length - b.length) > cap) return cap + 1;
|
|
14514
|
-
const prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
14515
|
-
for (let i = 1; i <= a.length; i++) {
|
|
14516
|
-
const curr = [i];
|
|
14517
|
-
for (let j = 1; j <= b.length; j++) {
|
|
14518
|
-
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
14519
|
-
curr.push(Math.min((curr[j - 1] ?? 0) + 1, (prev[j] ?? 0) + 1, (prev[j - 1] ?? 0) + cost));
|
|
14520
|
-
}
|
|
14521
|
-
prev.splice(0, prev.length, ...curr);
|
|
14522
|
-
}
|
|
14523
|
-
return prev[b.length] ?? cap + 1;
|
|
14524
|
-
}
|
|
14525
|
-
function suggestPackageNames(query, names) {
|
|
14526
|
-
return [...new Set(names)].map((n) => ({ n, d: packageNameDistance(query.toLowerCase(), n.toLowerCase()) })).filter((x) => x.d <= 3).sort((a, b) => a.d - b.d).slice(0, 5).map((x) => x.n);
|
|
14527
|
-
}
|
|
14444
|
+
import * as fs31 from "fs";
|
|
14445
|
+
import * as path28 from "path";
|
|
14528
14446
|
|
|
14529
14447
|
// src/text_todo.ts
|
|
14530
14448
|
init_define_import_meta_env();
|
|
14531
|
-
import * as
|
|
14532
|
-
import * as
|
|
14449
|
+
import * as fs28 from "fs";
|
|
14450
|
+
import * as path26 from "path";
|
|
14533
14451
|
var DEFAULT_KINDS = ["TODO", "FIXME", "HACK", "XXX", "NOTE"];
|
|
14534
14452
|
function splitLines(text) {
|
|
14535
14453
|
return text.split(/\r?\n/);
|
|
@@ -14558,7 +14476,7 @@ function isMarkerOccurrence(matched, hasColon) {
|
|
|
14558
14476
|
function scanFileForTodos(filePath, kindSet) {
|
|
14559
14477
|
let text;
|
|
14560
14478
|
try {
|
|
14561
|
-
text = decodeSource(
|
|
14479
|
+
text = decodeSource(fs28.readFileSync(filePath));
|
|
14562
14480
|
} catch {
|
|
14563
14481
|
return [];
|
|
14564
14482
|
}
|
|
@@ -14586,9 +14504,9 @@ function collectTodoFiles(patterns) {
|
|
|
14586
14504
|
if (patterns.length > 0) {
|
|
14587
14505
|
const results = [];
|
|
14588
14506
|
for (const p of patterns) {
|
|
14589
|
-
const abs =
|
|
14507
|
+
const abs = path26.resolve(p);
|
|
14590
14508
|
try {
|
|
14591
|
-
const stat =
|
|
14509
|
+
const stat = fs28.statSync(abs);
|
|
14592
14510
|
if (stat.isDirectory()) {
|
|
14593
14511
|
pushAll(results, walkProject(abs).files);
|
|
14594
14512
|
} else {
|
|
@@ -14653,11 +14571,11 @@ function cmdTodo(patterns, opts) {
|
|
|
14653
14571
|
|
|
14654
14572
|
// src/text_trace.ts
|
|
14655
14573
|
init_define_import_meta_env();
|
|
14656
|
-
import * as
|
|
14657
|
-
import * as
|
|
14574
|
+
import * as fs29 from "fs";
|
|
14575
|
+
import * as path27 from "path";
|
|
14658
14576
|
function readInput(src) {
|
|
14659
|
-
if (src !== void 0) return
|
|
14660
|
-
return
|
|
14577
|
+
if (src !== void 0) return fs29.readFileSync(src, "utf8");
|
|
14578
|
+
return fs29.readFileSync(0, "utf8");
|
|
14661
14579
|
}
|
|
14662
14580
|
function splitLines2(text) {
|
|
14663
14581
|
return text.split(/\r?\n/);
|
|
@@ -14869,7 +14787,7 @@ function isProjectFrame(framePath, cwd) {
|
|
|
14869
14787
|
if (framePath.includes("/rustc/")) return false;
|
|
14870
14788
|
if (framePath.includes(".cargo/registry") || framePath.includes(".cargo\\registry")) return false;
|
|
14871
14789
|
if (/^<.+>$/.test(framePath)) return false;
|
|
14872
|
-
if (!
|
|
14790
|
+
if (!path27.isAbsolute(framePath) && !framePath.startsWith("..")) return true;
|
|
14873
14791
|
return false;
|
|
14874
14792
|
}
|
|
14875
14793
|
function resolveFrameSymbol(frame, projectRoot) {
|
|
@@ -14977,7 +14895,7 @@ function cmdTrace(src, opts) {
|
|
|
14977
14895
|
|
|
14978
14896
|
// src/text_logfold.ts
|
|
14979
14897
|
init_define_import_meta_env();
|
|
14980
|
-
import * as
|
|
14898
|
+
import * as fs30 from "fs";
|
|
14981
14899
|
|
|
14982
14900
|
// src/filters.ts
|
|
14983
14901
|
init_define_import_meta_env();
|
|
@@ -15107,8 +15025,8 @@ function applyFiltersAndFold(lines, noNormalize, foldRepeats) {
|
|
|
15107
15025
|
return folded;
|
|
15108
15026
|
}
|
|
15109
15027
|
function readInput2(src) {
|
|
15110
|
-
if (src !== void 0) return
|
|
15111
|
-
return
|
|
15028
|
+
if (src !== void 0) return fs30.readFileSync(src, "utf8");
|
|
15029
|
+
return fs30.readFileSync(0, "utf8");
|
|
15112
15030
|
}
|
|
15113
15031
|
function splitLines3(text) {
|
|
15114
15032
|
return text.split(/\r?\n/);
|
|
@@ -15159,21 +15077,21 @@ var LOCK_PRIORITY = [
|
|
|
15159
15077
|
"Cargo.lock"
|
|
15160
15078
|
];
|
|
15161
15079
|
function findLockfile(startPath) {
|
|
15162
|
-
const stat =
|
|
15080
|
+
const stat = fs31.statSync(startPath, { throwIfNoEntry: false });
|
|
15163
15081
|
if (stat !== void 0 && stat.isFile()) {
|
|
15164
15082
|
return { file: startPath, others: [] };
|
|
15165
15083
|
}
|
|
15166
|
-
const dir = stat !== void 0 && stat.isDirectory() ? startPath :
|
|
15084
|
+
const dir = stat !== void 0 && stat.isDirectory() ? startPath : path28.dirname(startPath);
|
|
15167
15085
|
const found = [];
|
|
15168
15086
|
for (const name of LOCK_PRIORITY) {
|
|
15169
|
-
const candidate =
|
|
15170
|
-
if (
|
|
15087
|
+
const candidate = path28.join(dir, name);
|
|
15088
|
+
if (fs31.existsSync(candidate)) found.push(candidate);
|
|
15171
15089
|
}
|
|
15172
15090
|
try {
|
|
15173
|
-
const entries =
|
|
15091
|
+
const entries = fs31.readdirSync(dir);
|
|
15174
15092
|
for (const e of entries) {
|
|
15175
15093
|
if (/^requirements.*\.txt$/.test(e)) {
|
|
15176
|
-
const p =
|
|
15094
|
+
const p = path28.join(dir, e);
|
|
15177
15095
|
if (!found.includes(p)) found.push(p);
|
|
15178
15096
|
}
|
|
15179
15097
|
}
|
|
@@ -15370,8 +15288,8 @@ function parsePnpmLock(content) {
|
|
|
15370
15288
|
return deps;
|
|
15371
15289
|
}
|
|
15372
15290
|
function parseLockFile(filePath) {
|
|
15373
|
-
const base =
|
|
15374
|
-
const content =
|
|
15291
|
+
const base = path28.basename(filePath);
|
|
15292
|
+
const content = fs31.readFileSync(filePath, "utf8");
|
|
15375
15293
|
if (base === "package-lock.json") return { format: "npm", deps: parsePackageLockJson(content) };
|
|
15376
15294
|
if (base === "yarn.lock") return { format: "yarn", deps: parseYarnLock(content) };
|
|
15377
15295
|
if (base === "pnpm-lock.yaml") return { format: "pnpm", deps: parsePnpmLock(content) };
|
|
@@ -15444,7 +15362,7 @@ function cmdLockdepsPackage(lockfile, format, deps, query, json) {
|
|
|
15444
15362
|
}
|
|
15445
15363
|
const primary = matches2.find((d) => d.kind === "direct") ?? matches2[0];
|
|
15446
15364
|
const otherVersions = [...new Set(matches2.filter((d) => d.version !== primary.version).map((d) => d.version))];
|
|
15447
|
-
const graph = format === "npm" ? buildNpmEdges(
|
|
15365
|
+
const graph = format === "npm" ? buildNpmEdges(fs31.readFileSync(lockfile, "utf8")) : null;
|
|
15448
15366
|
const graphAvailable = graph !== null;
|
|
15449
15367
|
const dependsOn = graph !== null ? [...graph.edges.get(query) ?? []].sort() : [];
|
|
15450
15368
|
const dependedOnBy = graph !== null ? findReverseDirectDeps(query, graph.edges, graph.directNames) : [];
|
|
@@ -15484,7 +15402,7 @@ Depended on by direct/top-level deps (${dependedOnBy.length}):
|
|
|
15484
15402
|
`);
|
|
15485
15403
|
}
|
|
15486
15404
|
function cmdLockdeps(filePath, opts) {
|
|
15487
|
-
const target = filePath !== void 0 ?
|
|
15405
|
+
const target = filePath !== void 0 ? path28.resolve(filePath) : process.cwd();
|
|
15488
15406
|
const found = findLockfile(target);
|
|
15489
15407
|
if (found === null) {
|
|
15490
15408
|
throw new Error("No lockfile found. Expected one of: " + LOCK_PRIORITY.join(", ") + ", requirements*.txt");
|
|
@@ -15572,20 +15490,20 @@ function cmdNote(action, key, value, opts) {
|
|
|
15572
15490
|
throw new Error(`Unknown note action: ${action}. Use: set, get, unset, list, clear`);
|
|
15573
15491
|
}
|
|
15574
15492
|
function loadAllSessionReadCounts() {
|
|
15575
|
-
const sessionsDir2 =
|
|
15493
|
+
const sessionsDir2 = path28.join(tokenGoatHome(), "sessions");
|
|
15576
15494
|
const totals = /* @__PURE__ */ new Map();
|
|
15577
15495
|
let entries;
|
|
15578
15496
|
try {
|
|
15579
|
-
entries =
|
|
15497
|
+
entries = fs31.readdirSync(sessionsDir2, { withFileTypes: true });
|
|
15580
15498
|
} catch {
|
|
15581
15499
|
return totals;
|
|
15582
15500
|
}
|
|
15583
15501
|
for (const entry of entries) {
|
|
15584
15502
|
if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
|
|
15585
|
-
const filePath =
|
|
15503
|
+
const filePath = path28.join(sessionsDir2, entry.name);
|
|
15586
15504
|
let raw;
|
|
15587
15505
|
try {
|
|
15588
|
-
raw = JSON.parse(
|
|
15506
|
+
raw = JSON.parse(fs31.readFileSync(filePath, "utf8"));
|
|
15589
15507
|
} catch {
|
|
15590
15508
|
continue;
|
|
15591
15509
|
}
|
|
@@ -15718,7 +15636,7 @@ function cmdIgnores(opts) {
|
|
|
15718
15636
|
}
|
|
15719
15637
|
function countPackIgnorePatterns(root) {
|
|
15720
15638
|
try {
|
|
15721
|
-
return
|
|
15639
|
+
return fs31.readFileSync(path28.join(root, ".tokengoatignore"), "utf8").split("\n").map((ln) => ln.trim()).filter((ln) => ln.length > 0 && !ln.startsWith("#")).length;
|
|
15722
15640
|
} catch {
|
|
15723
15641
|
return 0;
|
|
15724
15642
|
}
|
|
@@ -15727,8 +15645,8 @@ function countPackIgnorePatterns(root) {
|
|
|
15727
15645
|
// src/dep_docs.ts
|
|
15728
15646
|
init_define_import_meta_env();
|
|
15729
15647
|
import { createRequire } from "node:module";
|
|
15730
|
-
import * as
|
|
15731
|
-
import * as
|
|
15648
|
+
import * as fs32 from "node:fs";
|
|
15649
|
+
import * as path29 from "node:path";
|
|
15732
15650
|
var _require = createRequire(import.meta.url);
|
|
15733
15651
|
var _ts = null;
|
|
15734
15652
|
var _tsLoadAttempted = false;
|
|
@@ -15747,21 +15665,21 @@ function loadTs() {
|
|
|
15747
15665
|
}
|
|
15748
15666
|
function dirExists(p) {
|
|
15749
15667
|
try {
|
|
15750
|
-
return
|
|
15668
|
+
return fs32.statSync(p).isDirectory();
|
|
15751
15669
|
} catch {
|
|
15752
15670
|
return false;
|
|
15753
15671
|
}
|
|
15754
15672
|
}
|
|
15755
15673
|
function fileExists(p) {
|
|
15756
15674
|
try {
|
|
15757
|
-
return
|
|
15675
|
+
return fs32.statSync(p).isFile();
|
|
15758
15676
|
} catch {
|
|
15759
15677
|
return false;
|
|
15760
15678
|
}
|
|
15761
15679
|
}
|
|
15762
15680
|
function readFileTextOrNull(p) {
|
|
15763
15681
|
try {
|
|
15764
|
-
return
|
|
15682
|
+
return fs32.readFileSync(p, "utf8");
|
|
15765
15683
|
} catch {
|
|
15766
15684
|
return null;
|
|
15767
15685
|
}
|
|
@@ -15769,7 +15687,7 @@ function readFileTextOrNull(p) {
|
|
|
15769
15687
|
function listInstalledPackageNames(nodeModulesDir) {
|
|
15770
15688
|
let entries;
|
|
15771
15689
|
try {
|
|
15772
|
-
entries =
|
|
15690
|
+
entries = fs32.readdirSync(nodeModulesDir, { withFileTypes: true });
|
|
15773
15691
|
} catch {
|
|
15774
15692
|
return [];
|
|
15775
15693
|
}
|
|
@@ -15779,7 +15697,7 @@ function listInstalledPackageNames(nodeModulesDir) {
|
|
|
15779
15697
|
if (entry.name.startsWith("@")) {
|
|
15780
15698
|
let scoped;
|
|
15781
15699
|
try {
|
|
15782
|
-
scoped =
|
|
15700
|
+
scoped = fs32.readdirSync(path29.join(nodeModulesDir, entry.name), { withFileTypes: true });
|
|
15783
15701
|
} catch {
|
|
15784
15702
|
continue;
|
|
15785
15703
|
}
|
|
@@ -15796,12 +15714,12 @@ var README_NAME_RE = /^readme(\.(md|markdown|txt))?$/i;
|
|
|
15796
15714
|
function findReadmeFile(pkgDir) {
|
|
15797
15715
|
const direct = findReadmeIn(pkgDir);
|
|
15798
15716
|
if (direct !== null) return direct;
|
|
15799
|
-
return findReadmeIn(
|
|
15717
|
+
return findReadmeIn(path29.join(pkgDir, "docs"));
|
|
15800
15718
|
}
|
|
15801
15719
|
function findReadmeIn(dir) {
|
|
15802
15720
|
let entries;
|
|
15803
15721
|
try {
|
|
15804
|
-
entries =
|
|
15722
|
+
entries = fs32.readdirSync(dir, { withFileTypes: true });
|
|
15805
15723
|
} catch {
|
|
15806
15724
|
return null;
|
|
15807
15725
|
}
|
|
@@ -15813,7 +15731,7 @@ function findReadmeIn(dir) {
|
|
|
15813
15731
|
return 1;
|
|
15814
15732
|
};
|
|
15815
15733
|
matches2.sort((a, b) => rank(a.name) - rank(b.name));
|
|
15816
|
-
return
|
|
15734
|
+
return path29.join(dir, matches2[0].name);
|
|
15817
15735
|
}
|
|
15818
15736
|
function typesPackageDirName(pkgName) {
|
|
15819
15737
|
if (pkgName.startsWith("@")) {
|
|
@@ -15840,30 +15758,30 @@ function resolveTypesLocation(pkgDir, pkgJson, nodeModulesDir, pkgName) {
|
|
|
15840
15758
|
if (declared !== void 0) {
|
|
15841
15759
|
const candidates = [declared, declared.endsWith(".d.ts") ? declared : `${declared}.d.ts`, declared.replace(/\.[cm]?[jt]s$/, ".d.ts")];
|
|
15842
15760
|
for (const c of candidates) {
|
|
15843
|
-
const p =
|
|
15761
|
+
const p = path29.join(pkgDir, c);
|
|
15844
15762
|
if (fileExists(p)) return { path: p, source: "bundled" };
|
|
15845
15763
|
}
|
|
15846
15764
|
}
|
|
15847
15765
|
const main = typeof pkgJson["main"] === "string" ? pkgJson["main"] : "index.js";
|
|
15848
|
-
const mainDts =
|
|
15766
|
+
const mainDts = path29.join(pkgDir, main.replace(/\.[cm]?js$/, ".d.ts"));
|
|
15849
15767
|
if (fileExists(mainDts)) return { path: mainDts, source: "bundled" };
|
|
15850
|
-
const indexDts =
|
|
15768
|
+
const indexDts = path29.join(pkgDir, "index.d.ts");
|
|
15851
15769
|
if (fileExists(indexDts)) return { path: indexDts, source: "bundled" };
|
|
15852
15770
|
const typesDirName = typesPackageDirName(pkgName);
|
|
15853
|
-
const typesPkgDir =
|
|
15854
|
-
const typesPkgJsonRaw = readFileTextOrNull(
|
|
15771
|
+
const typesPkgDir = path29.join(nodeModulesDir, "@types", typesDirName);
|
|
15772
|
+
const typesPkgJsonRaw = readFileTextOrNull(path29.join(typesPkgDir, "package.json"));
|
|
15855
15773
|
if (typesPkgJsonRaw !== null) {
|
|
15856
15774
|
try {
|
|
15857
15775
|
const typesPkgJson = JSON.parse(typesPkgJsonRaw);
|
|
15858
15776
|
const entry = (typeof typesPkgJson["types"] === "string" ? typesPkgJson["types"] : void 0) ?? (typeof typesPkgJson["main"] === "string" ? typesPkgJson["main"] : void 0) ?? "index.d.ts";
|
|
15859
15777
|
const entryCandidates = [entry, entry.endsWith(".d.ts") ? entry : `${entry}.d.ts`, entry.replace(/\.[cm]?[jt]s$/, ".d.ts")];
|
|
15860
15778
|
for (const c of entryCandidates) {
|
|
15861
|
-
const entryPath =
|
|
15779
|
+
const entryPath = path29.join(typesPkgDir, c);
|
|
15862
15780
|
if (fileExists(entryPath)) return { path: entryPath, source: "@types" };
|
|
15863
15781
|
}
|
|
15864
15782
|
} catch {
|
|
15865
15783
|
}
|
|
15866
|
-
const fallback =
|
|
15784
|
+
const fallback = path29.join(typesPkgDir, "index.d.ts");
|
|
15867
15785
|
if (fileExists(fallback)) return { path: fallback, source: "@types" };
|
|
15868
15786
|
}
|
|
15869
15787
|
return null;
|
|
@@ -15930,16 +15848,16 @@ function recordDepDocsStat(fullSourceBytes, emittedText, packageName) {
|
|
|
15930
15848
|
}
|
|
15931
15849
|
function runDepDocs(opts) {
|
|
15932
15850
|
const root = resolveProjectRoot({ project: opts.projectRoot ?? process.cwd() });
|
|
15933
|
-
const nodeModulesDir =
|
|
15934
|
-
const pkgDir =
|
|
15935
|
-
const pkgJsonPath =
|
|
15851
|
+
const nodeModulesDir = path29.join(root, "node_modules");
|
|
15852
|
+
const pkgDir = path29.join(nodeModulesDir, opts.packageName);
|
|
15853
|
+
const pkgJsonPath = path29.join(pkgDir, "package.json");
|
|
15936
15854
|
if (!dirExists(pkgDir) || !fileExists(pkgJsonPath)) {
|
|
15937
15855
|
const known = listInstalledPackageNames(nodeModulesDir);
|
|
15938
15856
|
const suggestions = suggestPackageNames(opts.packageName, known);
|
|
15939
15857
|
const hint = suggestions.length > 0 ? ` (did you mean: ${suggestions.map(displaySafeText).join(", ")}?)` : "";
|
|
15940
15858
|
return { text: `Package '${displaySafeText(opts.packageName)}' not found under ${displaySafeText(nodeModulesDir)}${hint}`, code: 1 };
|
|
15941
15859
|
}
|
|
15942
|
-
const pkgJsonRaw =
|
|
15860
|
+
const pkgJsonRaw = fs32.readFileSync(pkgJsonPath, "utf8");
|
|
15943
15861
|
let pkgJson;
|
|
15944
15862
|
try {
|
|
15945
15863
|
pkgJson = JSON.parse(pkgJsonRaw);
|
|
@@ -16352,13 +16270,13 @@ function renderCapabilities(caps) {
|
|
|
16352
16270
|
|
|
16353
16271
|
// src/cli_session.ts
|
|
16354
16272
|
init_define_import_meta_env();
|
|
16355
|
-
import * as
|
|
16273
|
+
import * as fs39 from "node:fs";
|
|
16356
16274
|
|
|
16357
16275
|
// src/session_audit.ts
|
|
16358
16276
|
init_define_import_meta_env();
|
|
16359
|
-
import * as
|
|
16277
|
+
import * as fs33 from "node:fs";
|
|
16360
16278
|
import * as os16 from "node:os";
|
|
16361
|
-
import * as
|
|
16279
|
+
import * as path30 from "node:path";
|
|
16362
16280
|
import * as readline from "node:readline";
|
|
16363
16281
|
var MODEL_VISIBLE_CATEGORIES = ["toolResults", "assistantText", "assistantThinking", "toolUseInputs", "attachments", "userTurns", "harnessMeta", "system"];
|
|
16364
16282
|
function computeCalibration(estimated, measured) {
|
|
@@ -16419,10 +16337,13 @@ var ATTACHMENT_VISIBLE_FIELDS = {
|
|
|
16419
16337
|
};
|
|
16420
16338
|
var CACHE_WRITE_MULTIPLIER = 1.25;
|
|
16421
16339
|
var CACHE_READ_MULTIPLIER = 0.1;
|
|
16422
|
-
var READ_DIVERT_MARKER_RE = /(?:was already read this session|Already read |You've already read|Use `token-goat (?:section|read|bash-output|config-get|skeleton)|token-goat bash-output --file)/;
|
|
16340
|
+
var READ_DIVERT_MARKER_RE = /(?:was already read this session|Already read |You've already read|(?:Use|Run) `token-goat (?:section|read|bash-output|config-get|skeleton|json-query|yaml-query)|token-goat bash-output --file)/;
|
|
16423
16341
|
var READ_DIVERT_MAX_BYTES = 2500;
|
|
16424
16342
|
var READ_FULL_SERVE_MIN_BYTES = 10240;
|
|
16425
16343
|
var DENY_TEMPLATES = [
|
|
16344
|
+
// hint_target.ts's sharpenRepeatedDeny replaces a verbatim repeat of any deny with this one line, so the kind the first copy had is not recoverable from the second.
|
|
16345
|
+
{ kind: "repeat_refusal_deny", re: /Repeat refusal of this exact call/, tool: "Read" },
|
|
16346
|
+
{ kind: "skill_repeat_refusal_deny", re: /Repeat refusal of this exact call/, tool: "Skill" },
|
|
16426
16347
|
{ kind: "node_modules_deny", re: /node_modules is typically noise/, tool: "Read" },
|
|
16427
16348
|
{ kind: "lock_file_deny", re: /Lock files are rarely useful to read in full/, tool: "Read" },
|
|
16428
16349
|
{ kind: "tsbuildinfo_deny", re: /TypeScript incremental build cache file/, tool: "Read" },
|
|
@@ -16432,13 +16353,7 @@ var DENY_TEMPLATES = [
|
|
|
16432
16353
|
// 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.
|
|
16433
16354
|
{ kind: "subagent_markdown_first_read_deny", re: /Subagent first read of a large markdown file/, tool: "Read" },
|
|
16434
16355
|
{ kind: "markdown_heading_tree_deny", re: /Large markdown file \(\d+ headings\)/, tool: "Read" },
|
|
16435
|
-
// The first alternative is a wording hooks_read.ts no longer emits (it claimed a compact-manifest
|
|
16436
|
-
// section that never existed, reworded in 3d044feb). It stays because this table classifies a
|
|
16437
|
-
// historical corpus, not just today's output: transcripts written before the rewording still
|
|
16438
|
-
// carry the old text, and dropping the alternative silently shrank this kind from 51 events to
|
|
16439
|
-
// 30 -- 41% of its history -- with a green suite. A superseded alternative is only removable
|
|
16440
|
-
// once no transcript contains it, which source code cannot tell you. See the superseded-wording
|
|
16441
|
-
// test in tests/deny_outcomes.test.ts.
|
|
16356
|
+
// The first alternative is a wording hooks_read.ts no longer emits (it claimed a compact-manifest section that never existed, reworded in 3d044feb). It stays because this table classifies a historical corpus, not just today's output: transcripts written before the rewording still carry the old text, and dropping the alternative silently shrank this kind from 51 events to 30 -- 41% of its history -- with a green suite. A superseded alternative is only removable once no transcript contains it, which source code cannot tell you. See the superseded-wording test in tests/deny_outcomes.test.ts.
|
|
16442
16357
|
{ 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" },
|
|
16443
16358
|
{ kind: "improve_state_reread_deny", re: /Orchestrator state already read this session/, tool: "Read" },
|
|
16444
16359
|
{ kind: "env_reread_deny", re: /Environment files rarely change mid-session/, tool: "Read" },
|
|
@@ -16448,12 +16363,12 @@ var DENY_TEMPLATES = [
|
|
|
16448
16363
|
{ kind: "session_artifact_large_deny", re: /(?:Session transcript|Tool-result file) is large \(/, tool: "Read" },
|
|
16449
16364
|
{ kind: "session_artifact_generic_reread_deny", re: /already read this session\. Use `token-goat bash-output --file/, tool: "Read" },
|
|
16450
16365
|
{ kind: "truncated_read_deny", re: /File was truncated on last read \(>33K tokens\)/, tool: "Read" },
|
|
16451
|
-
{ kind: "doc_unchanged_deny", re: /is unchanged since last read\. Use `token-goat (?:section|read)/, tool: "Read" },
|
|
16452
|
-
{ kind: "doc_diff_deny", re: /Content changed since last read of [\s\S]*?Use `token-goat (?:section|read)/, tool: "Read" },
|
|
16366
|
+
{ kind: "doc_unchanged_deny", re: /is unchanged since last read\. (?:Use|Run) `token-goat (?:section|read|skeleton|json-query|yaml-query)/, tool: "Read" },
|
|
16367
|
+
{ kind: "doc_diff_deny", re: /Content changed since last read of [\s\S]*?(?:Use|Run) `token-goat (?:section|read|skeleton|json-query|yaml-query)/, tool: "Read" },
|
|
16453
16368
|
{ kind: "read_served_deny", re: /was already served in this session, byte for byte/, tool: "Read" },
|
|
16454
16369
|
// Its own kind rather than folded into read_served_deny above, whose stat name this branch shares: the wording is disjoint (a span, not a byte-for-byte whole serve) and so is the follow-up it invites, since the model still needs part of that span and has to choose a narrower call rather than recall the whole result.
|
|
16455
16370
|
{ kind: "range_reread_deny", re: /Lines \d+\.\.\d+ of [\s\S]*?was already read this session/, tool: "Read" },
|
|
16456
|
-
{ kind: "markdown_already_read_deny", re: /Markdown file already read this session
|
|
16371
|
+
{ kind: "markdown_already_read_deny", re: /Markdown file already read this session\./, tool: "Read" },
|
|
16457
16372
|
{ kind: "read_count_deny", re: /(?:Read|Tried to read) this file \d+ times already/, tool: "Read" },
|
|
16458
16373
|
// Shares read_count_deny's stat name and matches none of its wording: this branch fires on the SHAPE of the reads (consecutive line windows walking one file) rather than on their count, and says so.
|
|
16459
16374
|
{ kind: "sequential_paging_deny", re: /Sequential line-range paging detected on /, tool: "Read" },
|
|
@@ -16543,9 +16458,9 @@ function toolResultText(content) {
|
|
|
16543
16458
|
return "";
|
|
16544
16459
|
}
|
|
16545
16460
|
function listCorpusTranscripts(corpusDir) {
|
|
16546
|
-
if (!
|
|
16461
|
+
if (!fs33.existsSync(corpusDir)) return [];
|
|
16547
16462
|
try {
|
|
16548
|
-
const stat =
|
|
16463
|
+
const stat = fs33.statSync(corpusDir);
|
|
16549
16464
|
if (stat.isFile()) {
|
|
16550
16465
|
return corpusDir.endsWith(".jsonl") ? [corpusDir] : [];
|
|
16551
16466
|
}
|
|
@@ -16555,13 +16470,13 @@ function listCorpusTranscripts(corpusDir) {
|
|
|
16555
16470
|
const found = [];
|
|
16556
16471
|
const walk = (dir, entries) => {
|
|
16557
16472
|
for (const entry of entries) {
|
|
16558
|
-
const full =
|
|
16473
|
+
const full = path30.join(dir, entry.name);
|
|
16559
16474
|
if (entry.name.endsWith(".jsonl")) {
|
|
16560
16475
|
found.push(full);
|
|
16561
16476
|
} else if (entry.isDirectory()) {
|
|
16562
16477
|
let inner;
|
|
16563
16478
|
try {
|
|
16564
|
-
inner =
|
|
16479
|
+
inner = fs33.readdirSync(full, { withFileTypes: true });
|
|
16565
16480
|
} catch {
|
|
16566
16481
|
continue;
|
|
16567
16482
|
}
|
|
@@ -16570,31 +16485,41 @@ function listCorpusTranscripts(corpusDir) {
|
|
|
16570
16485
|
}
|
|
16571
16486
|
};
|
|
16572
16487
|
try {
|
|
16573
|
-
walk(corpusDir,
|
|
16488
|
+
walk(corpusDir, fs33.readdirSync(corpusDir, { withFileTypes: true }));
|
|
16574
16489
|
} catch {
|
|
16575
16490
|
}
|
|
16576
16491
|
return found.sort();
|
|
16577
16492
|
}
|
|
16493
|
+
var MS_PER_DAY = 24 * 60 * 60 * 1e3;
|
|
16494
|
+
function modifiedSince(files, sinceMs) {
|
|
16495
|
+
return files.filter((file) => {
|
|
16496
|
+
try {
|
|
16497
|
+
return fs33.statSync(file).mtimeMs >= sinceMs;
|
|
16498
|
+
} catch {
|
|
16499
|
+
return false;
|
|
16500
|
+
}
|
|
16501
|
+
});
|
|
16502
|
+
}
|
|
16578
16503
|
function defaultCorpusDir() {
|
|
16579
|
-
const claudeDir =
|
|
16580
|
-
if (
|
|
16504
|
+
const claudeDir = path30.join(claudeConfigDir(), "projects");
|
|
16505
|
+
if (fs33.existsSync(claudeDir) && listCorpusTranscripts(claudeDir).length > 0) {
|
|
16581
16506
|
return claudeDir;
|
|
16582
16507
|
}
|
|
16583
16508
|
const home = os16.homedir();
|
|
16584
|
-
const appData = process.env["APPDATA"] ||
|
|
16509
|
+
const appData = process.env["APPDATA"] || path30.join(home, "AppData", "Roaming");
|
|
16585
16510
|
const candidates = [
|
|
16586
16511
|
claudeDir,
|
|
16587
|
-
|
|
16588
|
-
|
|
16589
|
-
|
|
16590
|
-
|
|
16591
|
-
|
|
16592
|
-
|
|
16593
|
-
|
|
16512
|
+
path30.join(appData, "Code", "User", "workspaceStorage"),
|
|
16513
|
+
path30.join(appData, "Code - Insiders", "User", "workspaceStorage"),
|
|
16514
|
+
path30.join(home, "Library", "Application Support", "Code", "User", "workspaceStorage"),
|
|
16515
|
+
path30.join(home, "Library", "Application Support", "Code - Insiders", "User", "workspaceStorage"),
|
|
16516
|
+
path30.join(home, ".config", "Code", "User", "workspaceStorage"),
|
|
16517
|
+
path30.join(home, ".config", "Code - Insiders", "User", "workspaceStorage"),
|
|
16518
|
+
path30.join(home, ".copilot", "session-state")
|
|
16594
16519
|
];
|
|
16595
16520
|
for (const cand of candidates) {
|
|
16596
16521
|
try {
|
|
16597
|
-
if (
|
|
16522
|
+
if (fs33.existsSync(cand) && listCorpusTranscripts(cand).length > 0) {
|
|
16598
16523
|
return cand;
|
|
16599
16524
|
}
|
|
16600
16525
|
} catch {
|
|
@@ -16602,11 +16527,13 @@ function defaultCorpusDir() {
|
|
|
16602
16527
|
}
|
|
16603
16528
|
return claudeDir;
|
|
16604
16529
|
}
|
|
16605
|
-
async function auditOneFile(filePath, s, toolMap, attachmentMap, hookMap, laneObservations, bashHeadMap, denyRows) {
|
|
16530
|
+
async function auditOneFile(filePath, s, toolMap, attachmentMap, hookMap, laneObservations, bashHeadMap, denyRows, toolErrorAcc) {
|
|
16606
16531
|
const isLane = filePath.split(/[\\/]/).includes("subagents");
|
|
16607
16532
|
let laneFirstPrefix = null;
|
|
16608
16533
|
let laneBriefBytes = -1;
|
|
16609
16534
|
const toolNameById = /* @__PURE__ */ new Map();
|
|
16535
|
+
const modelById = /* @__PURE__ */ new Map();
|
|
16536
|
+
const bashCommandById = /* @__PURE__ */ new Map();
|
|
16610
16537
|
const bashHeadById = /* @__PURE__ */ new Map();
|
|
16611
16538
|
let pendingBashReread = [];
|
|
16612
16539
|
const readCallById = /* @__PURE__ */ new Map();
|
|
@@ -16645,7 +16572,7 @@ async function auditOneFile(filePath, s, toolMap, attachmentMap, hookMap, laneOb
|
|
|
16645
16572
|
}
|
|
16646
16573
|
pendingBashReread = keptBash;
|
|
16647
16574
|
};
|
|
16648
|
-
const stream =
|
|
16575
|
+
const stream = fs33.createReadStream(filePath);
|
|
16649
16576
|
const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
|
|
16650
16577
|
const streamFailure = new Promise((_, reject) => stream.on("error", reject));
|
|
16651
16578
|
const consume = (async () => {
|
|
@@ -16709,11 +16636,15 @@ async function auditOneFile(filePath, s, toolMap, attachmentMap, hookMap, laneOb
|
|
|
16709
16636
|
if (!toolNameById.has(block["id"])) {
|
|
16710
16637
|
toolNameById.set(block["id"], name);
|
|
16711
16638
|
toolRollup(toolMap, name).calls += 1;
|
|
16639
|
+
const model = typeof message.model === "string" && message.model !== "" ? message.model : void 0;
|
|
16640
|
+
if (model !== void 0) modelById.set(block["id"], model);
|
|
16641
|
+
toolErrorAcc.countCall(name, model);
|
|
16712
16642
|
const input = block["input"] !== null && typeof block["input"] === "object" ? block["input"] : {};
|
|
16713
16643
|
let readNorm;
|
|
16714
16644
|
let editNorm;
|
|
16715
16645
|
if (name === "Bash" && typeof input["command"] === "string") {
|
|
16716
16646
|
bashHeadById.set(block["id"], commandHead(input["command"]));
|
|
16647
|
+
bashCommandById.set(block["id"], input["command"]);
|
|
16717
16648
|
} else if (name === "Read" && typeof input["file_path"] === "string") {
|
|
16718
16649
|
readNorm = normalizeReadPath(input["file_path"]);
|
|
16719
16650
|
const priorEpoch = readPathEpoch.get(readNorm);
|
|
@@ -16767,9 +16698,17 @@ async function auditOneFile(filePath, s, toolMap, attachmentMap, hookMap, laneOb
|
|
|
16767
16698
|
const name = toolNameById.get(id) ?? "(unknown)";
|
|
16768
16699
|
addCategory(s.estimated.toolResults, bytes);
|
|
16769
16700
|
const roll = toolRollup(toolMap, name);
|
|
16770
|
-
if (!toolNameById.has(id))
|
|
16701
|
+
if (!toolNameById.has(id)) {
|
|
16702
|
+
roll.calls += 1;
|
|
16703
|
+
toolErrorAcc.countCall(name, void 0);
|
|
16704
|
+
}
|
|
16771
16705
|
roll.resultBytes += bytes;
|
|
16772
16706
|
roll.resultEstTokens += estimateTokensFromLength(bytes);
|
|
16707
|
+
if (block["is_error"] === true) {
|
|
16708
|
+
const denialKind = obj["toolDenialKind"];
|
|
16709
|
+
const command = bashCommandById.get(id);
|
|
16710
|
+
toolErrorAcc.countError(name, modelById.get(id), text, { ...typeof denialKind === "string" ? { denialKind } : {}, ...command !== void 0 ? { command } : {} });
|
|
16711
|
+
}
|
|
16773
16712
|
if (name === "Edit" && block["is_error"] === true) {
|
|
16774
16713
|
s.editErrorBaseline.totalErrors += 1;
|
|
16775
16714
|
editErrorById.set(id, true);
|
|
@@ -16777,13 +16716,13 @@ async function auditOneFile(filePath, s, toolMap, attachmentMap, hookMap, laneOb
|
|
|
16777
16716
|
if (name === "Read" || name === "Skill") {
|
|
16778
16717
|
const denyTemplate = DENY_TEMPLATES.find((t) => t.tool === name && t.re.test(text));
|
|
16779
16718
|
if (denyTemplate !== void 0) {
|
|
16780
|
-
const
|
|
16781
|
-
const lastSlash =
|
|
16719
|
+
const path41 = readPathById.get(id) ?? "";
|
|
16720
|
+
const lastSlash = path41.lastIndexOf("/");
|
|
16782
16721
|
openDenies.push({
|
|
16783
16722
|
kind: denyTemplate.kind,
|
|
16784
16723
|
withheldBytes: parseWithheldBytes(denyTemplate.kind, text),
|
|
16785
|
-
path:
|
|
16786
|
-
basename: lastSlash === -1 ?
|
|
16724
|
+
path: path41,
|
|
16725
|
+
basename: lastSlash === -1 ? path41 : path41.slice(lastSlash + 1),
|
|
16787
16726
|
callIndexAtDeny: perCall.length,
|
|
16788
16727
|
compactEpochAtOpen: compactEpoch,
|
|
16789
16728
|
compactEpochAtWindow: null,
|
|
@@ -16973,7 +16912,7 @@ async function auditOneFile(filePath, s, toolMap, attachmentMap, hookMap, laneOb
|
|
|
16973
16912
|
if (isLane) {
|
|
16974
16913
|
let agentType = "(none)";
|
|
16975
16914
|
try {
|
|
16976
|
-
const meta = JSON.parse(
|
|
16915
|
+
const meta = JSON.parse(fs33.readFileSync(filePath.replace(/\.jsonl$/i, ".meta.json"), "utf8"));
|
|
16977
16916
|
if (typeof meta["agentType"] === "string" && meta["agentType"] !== "") agentType = meta["agentType"];
|
|
16978
16917
|
} catch {
|
|
16979
16918
|
}
|
|
@@ -17054,14 +16993,19 @@ function aggregateDenyOutcomes(rows) {
|
|
|
17054
16993
|
return result.sort((a, b) => b.count - a.count || a.kind.localeCompare(b.kind));
|
|
17055
16994
|
}
|
|
17056
16995
|
async function auditSessionCorpus(opts = {}) {
|
|
17057
|
-
const corpusDir =
|
|
17058
|
-
if (!
|
|
16996
|
+
const corpusDir = path30.resolve(opts.dir ?? defaultCorpusDir());
|
|
16997
|
+
if (!fs33.existsSync(corpusDir)) {
|
|
17059
16998
|
throw new Error(`session corpus directory not found: ${corpusDir}`);
|
|
17060
16999
|
}
|
|
17061
|
-
const
|
|
17062
|
-
|
|
17000
|
+
const windowDays = opts.windowDays ?? 0;
|
|
17001
|
+
const allFiles = listCorpusTranscripts(corpusDir);
|
|
17002
|
+
if (allFiles.length === 0) {
|
|
17063
17003
|
throw new Error(`no .jsonl session transcripts found under ${corpusDir}`);
|
|
17064
17004
|
}
|
|
17005
|
+
const files = windowDays === 0 ? allFiles : modifiedSince(allFiles, Date.now() - windowDays * MS_PER_DAY);
|
|
17006
|
+
if (files.length === 0) {
|
|
17007
|
+
throw new Error(`no .jsonl session transcripts under ${corpusDir} were modified in the last ${windowDays} days`);
|
|
17008
|
+
}
|
|
17065
17009
|
const started = Date.now();
|
|
17066
17010
|
const summary = {
|
|
17067
17011
|
corpusDir,
|
|
@@ -17096,8 +17040,11 @@ async function auditSessionCorpus(opts = {}) {
|
|
|
17096
17040
|
denyOutcomes: [],
|
|
17097
17041
|
editErrorBaseline: { totalEdits: 0, totalErrors: 0, rate: 0 },
|
|
17098
17042
|
lineTypes: {},
|
|
17099
|
-
omissionMarkers: { fires: 0, linesOmitted: 0 }
|
|
17043
|
+
omissionMarkers: { fires: 0, linesOmitted: 0 },
|
|
17044
|
+
windowDays,
|
|
17045
|
+
toolErrors: { byTool: [], byModel: [], unknownPrefixes: [] }
|
|
17100
17046
|
};
|
|
17047
|
+
const toolErrorAcc = (await import("./token-goat-chunk-LEG3JNJ6.mjs")).newToolErrorAccumulator();
|
|
17101
17048
|
const toolMap = /* @__PURE__ */ new Map();
|
|
17102
17049
|
const attachmentMap = /* @__PURE__ */ new Map();
|
|
17103
17050
|
const hookMap = /* @__PURE__ */ new Map();
|
|
@@ -17106,7 +17053,7 @@ async function auditSessionCorpus(opts = {}) {
|
|
|
17106
17053
|
const denyRows = [];
|
|
17107
17054
|
for (const file of files) {
|
|
17108
17055
|
try {
|
|
17109
|
-
await auditOneFile(file, summary, toolMap, attachmentMap, hookMap, laneObservations, bashHeadMap, denyRows);
|
|
17056
|
+
await auditOneFile(file, summary, toolMap, attachmentMap, hookMap, laneObservations, bashHeadMap, denyRows, toolErrorAcc);
|
|
17110
17057
|
summary.filesScanned += 1;
|
|
17111
17058
|
} catch {
|
|
17112
17059
|
summary.filesFailed += 1;
|
|
@@ -17146,6 +17093,7 @@ async function auditSessionCorpus(opts = {}) {
|
|
|
17146
17093
|
summary.denyOutcomes = aggregateDenyOutcomes(denyRows);
|
|
17147
17094
|
summary.editErrorBaseline.rate = summary.editErrorBaseline.totalEdits === 0 ? 0 : summary.editErrorBaseline.totalErrors / summary.editErrorBaseline.totalEdits;
|
|
17148
17095
|
summary.calibration = computeCalibration(summary.estimated, summary.measured);
|
|
17096
|
+
summary.toolErrors = toolErrorAcc.finish();
|
|
17149
17097
|
summary.runtimeMs = Date.now() - started;
|
|
17150
17098
|
return summary;
|
|
17151
17099
|
}
|
|
@@ -17266,17 +17214,17 @@ function formatSessionAudit(s) {
|
|
|
17266
17214
|
|
|
17267
17215
|
// src/session_read.ts
|
|
17268
17216
|
init_define_import_meta_env();
|
|
17269
|
-
import * as
|
|
17270
|
-
import * as
|
|
17217
|
+
import * as fs34 from "node:fs";
|
|
17218
|
+
import * as path31 from "node:path";
|
|
17271
17219
|
import * as readline2 from "node:readline";
|
|
17272
17220
|
function resolveSessionTranscript(arg, opts = {}) {
|
|
17273
17221
|
if (arg !== void 0 && arg !== "") {
|
|
17274
|
-
if (
|
|
17222
|
+
if (fs34.existsSync(arg) && fs34.statSync(arg).isFile()) return arg;
|
|
17275
17223
|
const projectRoot2 = resolveProjectRoot(opts.project !== void 0 ? { project: opts.project } : {});
|
|
17276
17224
|
const dir = projectTranscriptsDir(projectRoot2);
|
|
17277
17225
|
const byId = arg.endsWith(".jsonl") ? arg : `${arg}.jsonl`;
|
|
17278
|
-
const candidate =
|
|
17279
|
-
if (
|
|
17226
|
+
const candidate = path31.join(dir, byId);
|
|
17227
|
+
if (fs34.existsSync(candidate) && fs34.statSync(candidate).isFile()) return candidate;
|
|
17280
17228
|
return null;
|
|
17281
17229
|
}
|
|
17282
17230
|
const projectRoot = resolveProjectRoot(opts.project !== void 0 ? { project: opts.project } : {});
|
|
@@ -17334,7 +17282,7 @@ function toolCallsForBlocks(blocks) {
|
|
|
17334
17282
|
return blocks.filter((b) => b.type === "tool_use" && b.name !== void 0).map((b) => b.name);
|
|
17335
17283
|
}
|
|
17336
17284
|
async function* streamTurns(transcriptPath) {
|
|
17337
|
-
const input =
|
|
17285
|
+
const input = fs34.createReadStream(transcriptPath, { encoding: "utf8" });
|
|
17338
17286
|
const rl = readline2.createInterface({ input, crlfDelay: Infinity });
|
|
17339
17287
|
try {
|
|
17340
17288
|
let lineNumber = 0;
|
|
@@ -17433,9 +17381,9 @@ function formatSessionSlice(turns) {
|
|
|
17433
17381
|
|
|
17434
17382
|
// src/cli_bootstrap_audit.ts
|
|
17435
17383
|
init_define_import_meta_env();
|
|
17436
|
-
import * as
|
|
17384
|
+
import * as fs35 from "node:fs";
|
|
17437
17385
|
import * as os17 from "node:os";
|
|
17438
|
-
import * as
|
|
17386
|
+
import * as path32 from "node:path";
|
|
17439
17387
|
import * as readline3 from "node:readline";
|
|
17440
17388
|
var FRONTMATTER_KEYS = /* @__PURE__ */ new Set(["description", "tools", "allowed-tools", "allowed_tools"]);
|
|
17441
17389
|
function parseBudget(name, value) {
|
|
@@ -17444,7 +17392,7 @@ function parseBudget(name, value) {
|
|
|
17444
17392
|
return value;
|
|
17445
17393
|
}
|
|
17446
17394
|
async function readFrontmatter(filePath) {
|
|
17447
|
-
const stream =
|
|
17395
|
+
const stream = fs35.createReadStream(filePath, { encoding: "utf8" });
|
|
17448
17396
|
const lines = readline3.createInterface({ input: stream, crlfDelay: Infinity });
|
|
17449
17397
|
let first = true;
|
|
17450
17398
|
let inFrontmatter = false;
|
|
@@ -17490,44 +17438,44 @@ async function scanMetadataRoot(root, kind, diagnostics, visitedDirs = /* @__PUR
|
|
|
17490
17438
|
let logicalRoot;
|
|
17491
17439
|
let rootIsLink;
|
|
17492
17440
|
try {
|
|
17493
|
-
rootIsLink = (await
|
|
17494
|
-
logicalRoot = await
|
|
17441
|
+
rootIsLink = (await fs35.promises.lstat(root)).isSymbolicLink();
|
|
17442
|
+
logicalRoot = await fs35.promises.realpath(root);
|
|
17495
17443
|
} catch (error) {
|
|
17496
17444
|
if (error.code === "ENOENT") return entries;
|
|
17497
|
-
diagnostics.push({ path:
|
|
17445
|
+
diagnostics.push({ path: path32.resolve(root), reason: "unreadable root" });
|
|
17498
17446
|
return entries;
|
|
17499
17447
|
}
|
|
17500
17448
|
if (rootIsLink && !followLinks) {
|
|
17501
|
-
diagnostics.push({ path:
|
|
17449
|
+
diagnostics.push({ path: path32.resolve(root), reason: "external root link skipped (use --follow-links)" });
|
|
17502
17450
|
return entries;
|
|
17503
17451
|
}
|
|
17504
17452
|
const canonicalKey = (candidate) => process.platform === "win32" ? candidate.toLocaleLowerCase() : candidate;
|
|
17505
17453
|
const isContained = (candidate, allowedRoot) => {
|
|
17506
|
-
const relative3 =
|
|
17507
|
-
return relative3 === "" || relative3 !== ".." && !relative3.startsWith(`..${
|
|
17454
|
+
const relative3 = path32.relative(canonicalKey(allowedRoot), canonicalKey(candidate));
|
|
17455
|
+
return relative3 === "" || relative3 !== ".." && !relative3.startsWith(`..${path32.sep}`) && !path32.isAbsolute(relative3);
|
|
17508
17456
|
};
|
|
17509
17457
|
async function visit(candidate, allowedRoot, topLevel = false) {
|
|
17510
17458
|
let real;
|
|
17511
17459
|
let candidateIsLink;
|
|
17512
17460
|
try {
|
|
17513
|
-
candidateIsLink = (await
|
|
17514
|
-
real = await
|
|
17461
|
+
candidateIsLink = (await fs35.promises.lstat(candidate)).isSymbolicLink();
|
|
17462
|
+
real = await fs35.promises.realpath(candidate);
|
|
17515
17463
|
} catch {
|
|
17516
|
-
diagnostics.push({ path:
|
|
17464
|
+
diagnostics.push({ path: path32.resolve(candidate), reason: "broken or unreadable link" });
|
|
17517
17465
|
return;
|
|
17518
17466
|
}
|
|
17519
17467
|
const withinAllowedRoot = allowedRoot === void 0 ? isContained(real, logicalRoot) : isContained(real, allowedRoot);
|
|
17520
17468
|
const canFollowExternal = followLinks && topLevel;
|
|
17521
17469
|
if (!withinAllowedRoot && !canFollowExternal) {
|
|
17522
|
-
diagnostics.push({ path:
|
|
17470
|
+
diagnostics.push({ path: path32.resolve(candidate), reason: candidateIsLink ? "external link skipped (use --follow-links)" : "canonical target outside scan root" });
|
|
17523
17471
|
return;
|
|
17524
17472
|
}
|
|
17525
17473
|
const trustedRoot = !withinAllowedRoot && canFollowExternal ? real : allowedRoot ?? real;
|
|
17526
17474
|
let stat;
|
|
17527
17475
|
try {
|
|
17528
|
-
stat = await
|
|
17476
|
+
stat = await fs35.promises.stat(real);
|
|
17529
17477
|
} catch {
|
|
17530
|
-
diagnostics.push({ path:
|
|
17478
|
+
diagnostics.push({ path: path32.resolve(candidate), reason: "unreadable" });
|
|
17531
17479
|
return;
|
|
17532
17480
|
}
|
|
17533
17481
|
const canonical = process.platform === "win32" ? real.toLocaleLowerCase() : real;
|
|
@@ -17536,16 +17484,16 @@ async function scanMetadataRoot(root, kind, diagnostics, visitedDirs = /* @__PUR
|
|
|
17536
17484
|
visitedDirs.add(canonical);
|
|
17537
17485
|
let children;
|
|
17538
17486
|
try {
|
|
17539
|
-
children = await
|
|
17487
|
+
children = await fs35.promises.readdir(real, { withFileTypes: true });
|
|
17540
17488
|
} catch {
|
|
17541
|
-
diagnostics.push({ path:
|
|
17489
|
+
diagnostics.push({ path: path32.resolve(candidate), reason: "unreadable directory" });
|
|
17542
17490
|
return;
|
|
17543
17491
|
}
|
|
17544
17492
|
children.sort((a, b) => a.name.localeCompare(b.name));
|
|
17545
|
-
for (const child of children) await visit(
|
|
17493
|
+
for (const child of children) await visit(path32.join(real, child.name), trustedRoot);
|
|
17546
17494
|
return;
|
|
17547
17495
|
}
|
|
17548
|
-
if (!stat.isFile() ||
|
|
17496
|
+
if (!stat.isFile() || path32.extname(real).toLowerCase() !== ".md") return;
|
|
17549
17497
|
if (seenFiles.has(canonical)) return;
|
|
17550
17498
|
seenFiles.add(canonical);
|
|
17551
17499
|
try {
|
|
@@ -17555,35 +17503,35 @@ async function scanMetadataRoot(root, kind, diagnostics, visitedDirs = /* @__PUR
|
|
|
17555
17503
|
const toolsBytes = Buffer.byteLength(metadata.tools, "utf8");
|
|
17556
17504
|
entries.push({
|
|
17557
17505
|
kind,
|
|
17558
|
-
path:
|
|
17506
|
+
path: path32.resolve(real),
|
|
17559
17507
|
description_bytes: descriptionBytes,
|
|
17560
17508
|
tools_bytes: toolsBytes,
|
|
17561
17509
|
metadata_bytes: descriptionBytes + toolsBytes,
|
|
17562
17510
|
estimated_tokens: Math.floor((descriptionBytes + toolsBytes) / 4)
|
|
17563
17511
|
});
|
|
17564
17512
|
} catch {
|
|
17565
|
-
diagnostics.push({ path:
|
|
17513
|
+
diagnostics.push({ path: path32.resolve(candidate), reason: "unreadable file" });
|
|
17566
17514
|
}
|
|
17567
17515
|
}
|
|
17568
17516
|
try {
|
|
17569
|
-
const children = await
|
|
17517
|
+
const children = await fs35.promises.readdir(logicalRoot, { withFileTypes: true });
|
|
17570
17518
|
children.sort((a, b) => a.name.localeCompare(b.name));
|
|
17571
|
-
for (const child of children) await visit(
|
|
17519
|
+
for (const child of children) await visit(path32.join(logicalRoot, child.name), void 0, true);
|
|
17572
17520
|
} catch {
|
|
17573
|
-
diagnostics.push({ path:
|
|
17521
|
+
diagnostics.push({ path: path32.resolve(root), reason: "unreadable root" });
|
|
17574
17522
|
}
|
|
17575
17523
|
return entries;
|
|
17576
17524
|
}
|
|
17577
17525
|
async function buildBootstrapAudit(opts = {}) {
|
|
17578
17526
|
const project = resolveProjectRoot(opts.project === void 0 ? {} : { project: opts.project });
|
|
17579
|
-
const home =
|
|
17527
|
+
const home = path32.resolve(opts.home ?? os17.homedir());
|
|
17580
17528
|
const context = buildStats(project, home, opts.project === void 0 ? [] : [opts.project]);
|
|
17581
17529
|
const diagnostics = [];
|
|
17582
17530
|
const top = opts.top === void 0 ? 10 : parseBudget("--top", opts.top) ?? 10;
|
|
17583
17531
|
const visitedDirs = /* @__PURE__ */ new Set();
|
|
17584
17532
|
const seenFiles = /* @__PURE__ */ new Set();
|
|
17585
|
-
const agents = await scanMetadataRoot(
|
|
17586
|
-
const skills = await scanMetadataRoot(
|
|
17533
|
+
const agents = await scanMetadataRoot(path32.join(claudeConfigDir(home), "agents"), "agent", diagnostics, visitedDirs, seenFiles, opts.followLinks === true);
|
|
17534
|
+
const skills = await scanMetadataRoot(path32.join(claudeConfigDir(home), "skills"), "skill", diagnostics, visitedDirs, seenFiles, opts.followLinks === true);
|
|
17587
17535
|
const rankedEntries = [...agents, ...skills].sort((a, b) => b.metadata_bytes - a.metadata_bytes || a.path.localeCompare(b.path));
|
|
17588
17536
|
const largestTotal = rankedEntries.length;
|
|
17589
17537
|
const largest = rankedEntries.slice(0, top);
|
|
@@ -17650,8 +17598,8 @@ async function runBootstrapAudit(opts = {}) {
|
|
|
17650
17598
|
|
|
17651
17599
|
// src/cli_memory.ts
|
|
17652
17600
|
init_define_import_meta_env();
|
|
17653
|
-
import * as
|
|
17654
|
-
import * as
|
|
17601
|
+
import * as fs36 from "node:fs";
|
|
17602
|
+
import * as path33 from "node:path";
|
|
17655
17603
|
function removeExactDupLines(text, report) {
|
|
17656
17604
|
if (report.exactDupLines.length === 0) return text;
|
|
17657
17605
|
const toRemove = new Set(report.exactDupLines.map(([, dupIdx]) => dupIdx));
|
|
@@ -17709,7 +17657,7 @@ function printReport(reports, clusters) {
|
|
|
17709
17657
|
} else {
|
|
17710
17658
|
for (const cluster of clusters) {
|
|
17711
17659
|
w(
|
|
17712
|
-
` [${cluster.method}, similarity ${cluster.similarity}, ~${cluster.tokens} tok] ${cluster.members.map((m) => displaySafeText(
|
|
17660
|
+
` [${cluster.method}, similarity ${cluster.similarity}, ~${cluster.tokens} tok] ${cluster.members.map((m) => displaySafeText(path33.basename(m))).join(", ")}
|
|
17713
17661
|
`
|
|
17714
17662
|
);
|
|
17715
17663
|
}
|
|
@@ -17724,7 +17672,7 @@ async function runMemoryCommand(opts = {}) {
|
|
|
17724
17672
|
const claudeMds = findClaudeMdFiles(projectRoot);
|
|
17725
17673
|
const reports = auditClaudeMd(claudeMds);
|
|
17726
17674
|
const memoryMdPath = findMemoryMd(projectRoot);
|
|
17727
|
-
const clusters = memoryMdPath !== null ? await findContentDuplicates(
|
|
17675
|
+
const clusters = memoryMdPath !== null ? await findContentDuplicates(path33.dirname(memoryMdPath)) : [];
|
|
17728
17676
|
printReport(reports, clusters);
|
|
17729
17677
|
if (opts.fix !== true) return;
|
|
17730
17678
|
const changes = [];
|
|
@@ -17732,7 +17680,7 @@ async function runMemoryCommand(opts = {}) {
|
|
|
17732
17680
|
if (report.exactDupLines.length === 0) continue;
|
|
17733
17681
|
let before;
|
|
17734
17682
|
try {
|
|
17735
|
-
before =
|
|
17683
|
+
before = fs36.readFileSync(report.path, "utf-8");
|
|
17736
17684
|
} catch {
|
|
17737
17685
|
continue;
|
|
17738
17686
|
}
|
|
@@ -17770,8 +17718,8 @@ async function runMemoryCommand(opts = {}) {
|
|
|
17770
17718
|
|
|
17771
17719
|
// src/cli_waste.ts
|
|
17772
17720
|
init_define_import_meta_env();
|
|
17773
|
-
import * as
|
|
17774
|
-
import * as
|
|
17721
|
+
import * as fs37 from "node:fs";
|
|
17722
|
+
import * as path34 from "node:path";
|
|
17775
17723
|
function printCopilotReport(report) {
|
|
17776
17724
|
const w = (text) => {
|
|
17777
17725
|
process.stdout.write(text);
|
|
@@ -17825,8 +17773,9 @@ function printCopilotReport(report) {
|
|
|
17825
17773
|
} else {
|
|
17826
17774
|
for (const server of mcp.servers) {
|
|
17827
17775
|
const tokens = server.estimatedTokens.toLocaleString();
|
|
17776
|
+
const calls = report.mcpCalls === null ? "" : `, ${countNoun(report.mcpCalls[server.serverName] ?? 0, "call")} this session`;
|
|
17828
17777
|
w(` ${server.serverName}: ${countNoun(server.toolCount, "tool")}, `);
|
|
17829
|
-
w(`${formatBytes(server.definitionBytes)}, ~${tokens} tok
|
|
17778
|
+
w(`${formatBytes(server.definitionBytes)}, ~${tokens} tok${calls}
|
|
17830
17779
|
`);
|
|
17831
17780
|
}
|
|
17832
17781
|
const mcpTokens = mcp.servers.reduce((sum, server) => sum + server.estimatedTokens, 0);
|
|
@@ -17846,6 +17795,15 @@ function printCopilotReport(report) {
|
|
|
17846
17795
|
w(" tool-filter flags above still can.\n");
|
|
17847
17796
|
}
|
|
17848
17797
|
w(" Dropping a server saves its line above on every request for the rest of the session.\n");
|
|
17798
|
+
const unused = unusedMcpServers(report);
|
|
17799
|
+
if (unused === null) {
|
|
17800
|
+
w(" This log records no tool calls, so it cannot say which servers went unused.\n");
|
|
17801
|
+
} else {
|
|
17802
|
+
for (const server of unused) w(` Never called this session: \`copilot mcp disable ${server.serverName}\` drops it from future sessions.
|
|
17803
|
+
`);
|
|
17804
|
+
if (unused.length > 0) w(` ${MCP_DISABLE_NOTE}
|
|
17805
|
+
`);
|
|
17806
|
+
}
|
|
17849
17807
|
}
|
|
17850
17808
|
if (mcp.unreadable > 0) {
|
|
17851
17809
|
const verb = mcp.unreadable === 1 ? "is" : "are";
|
|
@@ -17972,8 +17930,8 @@ function printResidentContext(resident, w) {
|
|
|
17972
17930
|
async function runWasteCommand(opts = {}) {
|
|
17973
17931
|
const projectRoot = resolveProjectRoot(opts.project !== void 0 ? { project: opts.project } : {});
|
|
17974
17932
|
if (opts.transcript !== void 0) {
|
|
17975
|
-
const resolvedPath =
|
|
17976
|
-
if (!
|
|
17933
|
+
const resolvedPath = path34.resolve(opts.transcript);
|
|
17934
|
+
if (!fs37.existsSync(resolvedPath)) {
|
|
17977
17935
|
if (opts.copilot === true) {
|
|
17978
17936
|
const detail = `Copilot session event log not found: ${resolvedPath}`;
|
|
17979
17937
|
if (opts.json === true) {
|
|
@@ -18013,7 +17971,7 @@ async function runWasteCommand(opts = {}) {
|
|
|
18013
17971
|
}
|
|
18014
17972
|
if (opts.copilot === true) {
|
|
18015
17973
|
const eventsPath = opts.project !== void 0 ? findLatestCopilotSession({ projectRoot }) : findLatestCopilotSession({ projectRoot }) ?? findLatestCopilotSession();
|
|
18016
|
-
if (eventsPath === null || !
|
|
17974
|
+
if (eventsPath === null || !fs37.existsSync(eventsPath)) {
|
|
18017
17975
|
const detail = eventsPath === null ? "no Copilot CLI session found under <copilot-home>/session-state" : `Copilot session event log not found: ${eventsPath}`;
|
|
18018
17976
|
if (opts.json === true) {
|
|
18019
17977
|
process.stdout.write(`${displaySafeJson({ error: detail }, 0)}
|
|
@@ -18070,13 +18028,13 @@ async function runWasteCommand(opts = {}) {
|
|
|
18070
18028
|
|
|
18071
18029
|
// src/cli_mcp_audit.ts
|
|
18072
18030
|
init_define_import_meta_env();
|
|
18073
|
-
import * as
|
|
18031
|
+
import * as fs38 from "node:fs";
|
|
18074
18032
|
import * as os18 from "node:os";
|
|
18075
|
-
import * as
|
|
18033
|
+
import * as path35 from "node:path";
|
|
18076
18034
|
function readMcpJsonFile(configPath2) {
|
|
18077
18035
|
try {
|
|
18078
|
-
if (!
|
|
18079
|
-
const content =
|
|
18036
|
+
if (!fs38.existsSync(configPath2)) return null;
|
|
18037
|
+
const content = fs38.readFileSync(configPath2, "utf-8");
|
|
18080
18038
|
const parsed = JSON.parse(content);
|
|
18081
18039
|
const servers = parsed && typeof parsed === "object" ? parsed.mcpServers ?? ("servers" in parsed ? null : parsed) : null;
|
|
18082
18040
|
return servers && typeof servers === "object" ? servers : null;
|
|
@@ -18092,8 +18050,8 @@ function driveLetterCaseVariants(p) {
|
|
|
18092
18050
|
}
|
|
18093
18051
|
function readClaudeJsonConfig(claudeJsonPath, projectRoot) {
|
|
18094
18052
|
try {
|
|
18095
|
-
if (!
|
|
18096
|
-
const parsed = JSON.parse(
|
|
18053
|
+
if (!fs38.existsSync(claudeJsonPath)) return null;
|
|
18054
|
+
const parsed = JSON.parse(fs38.readFileSync(claudeJsonPath, "utf-8"));
|
|
18097
18055
|
const projects = parsed && typeof parsed === "object" ? parsed.projects : null;
|
|
18098
18056
|
if (!projects || typeof projects !== "object") return null;
|
|
18099
18057
|
const slashForms = [projectRoot, projectRoot.replace(/\\/g, "/"), projectRoot.replace(/\//g, "\\")];
|
|
@@ -18111,9 +18069,9 @@ function readClaudeJsonConfig(claudeJsonPath, projectRoot) {
|
|
|
18111
18069
|
}
|
|
18112
18070
|
}
|
|
18113
18071
|
function discoverMcpConfig(projectRoot, home) {
|
|
18114
|
-
const mcpJsonPath =
|
|
18115
|
-
const claudeJsonPath =
|
|
18116
|
-
const copilotJsonPath =
|
|
18072
|
+
const mcpJsonPath = path35.join(projectRoot, ".mcp.json");
|
|
18073
|
+
const claudeJsonPath = path35.join(home, ".claude.json");
|
|
18074
|
+
const copilotJsonPath = path35.join(home, ".copilot", "mcp-config.json");
|
|
18117
18075
|
const sourcesChecked = [mcpJsonPath, claudeJsonPath, copilotJsonPath];
|
|
18118
18076
|
const fromMcpJson = readMcpJsonFile(mcpJsonPath);
|
|
18119
18077
|
if (fromMcpJson !== null) return { servers: fromMcpJson, sourcePath: mcpJsonPath, sourcesChecked };
|
|
@@ -18434,7 +18392,7 @@ function cmdWaste(opts = {}) {
|
|
|
18434
18392
|
});
|
|
18435
18393
|
}
|
|
18436
18394
|
async function cmdAudit(opts = {}) {
|
|
18437
|
-
const { runAuditCommand } = await import("./token-goat-chunk-
|
|
18395
|
+
const { runAuditCommand } = await import("./token-goat-chunk-IHKZ3QNA.mjs");
|
|
18438
18396
|
return runAuditCommand({
|
|
18439
18397
|
...opts.project !== void 0 ? { project: opts.project } : {},
|
|
18440
18398
|
...opts.transcript !== void 0 ? { transcript: opts.transcript } : {},
|
|
@@ -18444,10 +18402,15 @@ async function cmdAudit(opts = {}) {
|
|
|
18444
18402
|
async function cmdSessionAudit(opts = {}) {
|
|
18445
18403
|
let summary;
|
|
18446
18404
|
try {
|
|
18447
|
-
summary = await auditSessionCorpus({ ...opts.dir !== void 0 ? { dir: opts.dir } : {} });
|
|
18405
|
+
summary = await auditSessionCorpus({ ...opts.dir !== void 0 ? { dir: opts.dir } : {}, ...opts.windowDays !== void 0 ? { windowDays: opts.windowDays } : {} });
|
|
18448
18406
|
} catch (err2) {
|
|
18449
18407
|
throw new CliError(err2 instanceof Error ? err2.message : String(err2));
|
|
18450
18408
|
}
|
|
18409
|
+
if (opts.toolErrors === true) {
|
|
18410
|
+
const { formatToolErrorCensus } = await import("./token-goat-chunk-LEG3JNJ6.mjs");
|
|
18411
|
+
out(opts.json === true ? displaySafeJson({ filesScanned: summary.filesScanned, windowDays: summary.windowDays, ...summary.toolErrors }, 0) : formatToolErrorCensus(summary.toolErrors, summary));
|
|
18412
|
+
return;
|
|
18413
|
+
}
|
|
18451
18414
|
out(opts.json === true ? displaySafeJson(summary, 0) : formatSessionAudit(summary));
|
|
18452
18415
|
}
|
|
18453
18416
|
async function cmdSessionOutline(sessionIdOrPath, opts = {}) {
|
|
@@ -18467,7 +18430,7 @@ ${formatSessionOutline(turns)}`;
|
|
|
18467
18430
|
}
|
|
18468
18431
|
function sessionTranscriptSize(transcriptPath) {
|
|
18469
18432
|
try {
|
|
18470
|
-
return
|
|
18433
|
+
return fs39.statSync(transcriptPath).size;
|
|
18471
18434
|
} catch {
|
|
18472
18435
|
return 0;
|
|
18473
18436
|
}
|
|
@@ -18512,10 +18475,10 @@ function cmdStatusline(opts = {}) {
|
|
|
18512
18475
|
}
|
|
18513
18476
|
function cmdHintStats(opts = {}) {
|
|
18514
18477
|
if (opts.markEffective !== void 0 && !isHintCategory(opts.markEffective)) {
|
|
18515
|
-
throw new CliError(`--mark-effective must be one of:
|
|
18478
|
+
throw new CliError(`--mark-effective must be one of: ${HINT_CATEGORIES.join(", ")} (got: ${opts.markEffective})`);
|
|
18516
18479
|
}
|
|
18517
18480
|
if (opts.markIneffective !== void 0 && !isHintCategory(opts.markIneffective)) {
|
|
18518
|
-
throw new CliError(`--mark-ineffective must be one of:
|
|
18481
|
+
throw new CliError(`--mark-ineffective must be one of: ${HINT_CATEGORIES.join(", ")} (got: ${opts.markIneffective})`);
|
|
18519
18482
|
}
|
|
18520
18483
|
runHintStatsCommand({
|
|
18521
18484
|
...opts.json === true ? { json: true } : {},
|
|
@@ -18527,14 +18490,14 @@ function cmdHintStats(opts = {}) {
|
|
|
18527
18490
|
|
|
18528
18491
|
// src/cli_skills.ts
|
|
18529
18492
|
init_define_import_meta_env();
|
|
18530
|
-
import * as
|
|
18531
|
-
import * as
|
|
18493
|
+
import * as fs40 from "node:fs";
|
|
18494
|
+
import * as path36 from "node:path";
|
|
18532
18495
|
async function cmdSkillBody(name, opts) {
|
|
18533
18496
|
const filePath = await getSkillFilePath(name);
|
|
18534
18497
|
if (filePath === null) {
|
|
18535
18498
|
throw new CliError(`skill '${name}' not found`);
|
|
18536
18499
|
}
|
|
18537
|
-
const body = decodeSource(
|
|
18500
|
+
const body = decodeSource(fs40.readFileSync(filePath));
|
|
18538
18501
|
if (opts.compact === true) {
|
|
18539
18502
|
const emitted = extractCompactFromMarker(body) ?? body;
|
|
18540
18503
|
out(emitted);
|
|
@@ -18561,7 +18524,7 @@ async function cmdSkillCompact(name, opts) {
|
|
|
18561
18524
|
}
|
|
18562
18525
|
let body2;
|
|
18563
18526
|
try {
|
|
18564
|
-
body2 = decodeSource(
|
|
18527
|
+
body2 = decodeSource(fs40.readFileSync(filePath));
|
|
18565
18528
|
} catch {
|
|
18566
18529
|
unresolvable++;
|
|
18567
18530
|
continue;
|
|
@@ -18595,19 +18558,19 @@ async function cmdSkillCompact(name, opts) {
|
|
|
18595
18558
|
if (!opts.path.trim()) {
|
|
18596
18559
|
throw new CliError("--path cannot be empty");
|
|
18597
18560
|
}
|
|
18598
|
-
if (!
|
|
18561
|
+
if (!fs40.existsSync(opts.path)) {
|
|
18599
18562
|
throw new CliError(`skill file not found: ${opts.path}`);
|
|
18600
18563
|
}
|
|
18601
18564
|
try {
|
|
18602
|
-
body =
|
|
18565
|
+
body = fs40.readFileSync(opts.path, "utf-8");
|
|
18603
18566
|
} catch (e) {
|
|
18604
18567
|
if (e.code === "ENOENT") {
|
|
18605
18568
|
throw new CliError(`skill file not found: ${opts.path}`);
|
|
18606
18569
|
}
|
|
18607
18570
|
throw new CliError(`failed to read skill file '${opts.path}': ${extractErrorMessage(e)}`);
|
|
18608
18571
|
}
|
|
18609
|
-
cacheName = name ??
|
|
18610
|
-
sourcePath =
|
|
18572
|
+
cacheName = name ?? path36.basename(path36.dirname(path36.resolve(opts.path)));
|
|
18573
|
+
sourcePath = path36.resolve(opts.path);
|
|
18611
18574
|
} else {
|
|
18612
18575
|
if (name === void 0 || !name.trim()) {
|
|
18613
18576
|
throw new CliError("skill-compact requires a <name> or --path <file>");
|
|
@@ -18616,7 +18579,7 @@ async function cmdSkillCompact(name, opts) {
|
|
|
18616
18579
|
if (filePath === null) {
|
|
18617
18580
|
throw new CliError(`skill '${name}' not found`);
|
|
18618
18581
|
}
|
|
18619
|
-
body =
|
|
18582
|
+
body = fs40.readFileSync(filePath, "utf-8");
|
|
18620
18583
|
cacheName = name;
|
|
18621
18584
|
sourcePath = filePath;
|
|
18622
18585
|
}
|
|
@@ -18748,8 +18711,8 @@ async function cmdSkillDiff(name) {
|
|
|
18748
18711
|
}
|
|
18749
18712
|
const newer = versions[0];
|
|
18750
18713
|
const older = versions[1];
|
|
18751
|
-
const newerBody = await
|
|
18752
|
-
const olderBody = await
|
|
18714
|
+
const newerBody = await fs40.promises.readFile(path36.resolve(dir, `${newer.outputId}.txt`), "utf-8").catch(() => null);
|
|
18715
|
+
const olderBody = await fs40.promises.readFile(path36.resolve(dir, `${older.outputId}.txt`), "utf-8").catch(() => null);
|
|
18753
18716
|
if (newerBody === null || olderBody === null) {
|
|
18754
18717
|
out(`a cached version of '${name}' was evicted while diffing -- try again`);
|
|
18755
18718
|
return;
|
|
@@ -18778,7 +18741,7 @@ async function cmdSkillSection(nameHeading, headingArg) {
|
|
|
18778
18741
|
if (!filePath) {
|
|
18779
18742
|
throw new CliError(`skill '${skillName}' not found`);
|
|
18780
18743
|
}
|
|
18781
|
-
const body = decodeSource(
|
|
18744
|
+
const body = decodeSource(fs40.readFileSync(filePath));
|
|
18782
18745
|
const extracted = extractNamedSection(body, heading);
|
|
18783
18746
|
if (!extracted) {
|
|
18784
18747
|
const allHeadings = listSections(filePath);
|
|
@@ -18801,8 +18764,8 @@ init_define_import_meta_env();
|
|
|
18801
18764
|
|
|
18802
18765
|
// src/cli_stats.ts
|
|
18803
18766
|
init_define_import_meta_env();
|
|
18804
|
-
import * as
|
|
18805
|
-
import * as
|
|
18767
|
+
import * as fs41 from "node:fs";
|
|
18768
|
+
import * as path37 from "node:path";
|
|
18806
18769
|
function writeRaw(text) {
|
|
18807
18770
|
const payload = colorStdout() ? text : stripAnsiEscapes(text);
|
|
18808
18771
|
process.stdout.write(ensureNewline(payload));
|
|
@@ -18814,7 +18777,7 @@ function formatTopFiles(ranked) {
|
|
|
18814
18777
|
if (ranked.length === 0) return "";
|
|
18815
18778
|
const lines = ["Top files this session:"];
|
|
18816
18779
|
for (const { path: filePath, count } of ranked) {
|
|
18817
|
-
const basename10 =
|
|
18780
|
+
const basename10 = path37.basename(filePath);
|
|
18818
18781
|
lines.push(` ${count.toString().padStart(3)}x ${basename10} (${filePath})`);
|
|
18819
18782
|
}
|
|
18820
18783
|
return lines.join("\n");
|
|
@@ -18832,11 +18795,11 @@ function renderTopSessionFiles(topN = 5) {
|
|
|
18832
18795
|
function renderTopSessionFilesFromDisk(topN = 5, overrideSessionsDir) {
|
|
18833
18796
|
try {
|
|
18834
18797
|
const dir = overrideSessionsDir ?? sessionsDir();
|
|
18835
|
-
if (!
|
|
18836
|
-
const files =
|
|
18798
|
+
if (!fs41.existsSync(dir)) return "";
|
|
18799
|
+
const files = fs41.readdirSync(dir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, mtime: fs41.statSync(path37.join(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).slice(0, 3);
|
|
18837
18800
|
for (const { name } of files) {
|
|
18838
18801
|
try {
|
|
18839
|
-
const raw =
|
|
18802
|
+
const raw = fs41.readFileSync(path37.join(dir, name), "utf-8");
|
|
18840
18803
|
const data = JSON.parse(raw);
|
|
18841
18804
|
const filesList = data["files"];
|
|
18842
18805
|
if (!Array.isArray(filesList)) continue;
|
|
@@ -18971,6 +18934,19 @@ function getNewestSessionFiles() {
|
|
|
18971
18934
|
const filesArr = Array.isArray(raw["files"]) ? raw["files"] : [];
|
|
18972
18935
|
return { id: newest.id, sessionCount: blobs.length, filesArr };
|
|
18973
18936
|
}
|
|
18937
|
+
function emitHistoryOutput(allItems, limit, json, emptyMessage, printTable) {
|
|
18938
|
+
const sorted = allItems.sort((a, b) => b.storedAt - a.storedAt);
|
|
18939
|
+
const items = capAndNote(sorted, limit);
|
|
18940
|
+
if (json === true) {
|
|
18941
|
+
process.stdout.write(displaySafeJson(items) + "\n");
|
|
18942
|
+
return;
|
|
18943
|
+
}
|
|
18944
|
+
if (items.length === 0) {
|
|
18945
|
+
process.stdout.write(emptyMessage);
|
|
18946
|
+
return;
|
|
18947
|
+
}
|
|
18948
|
+
printTable(items);
|
|
18949
|
+
}
|
|
18974
18950
|
function cmdBashHistory(opts) {
|
|
18975
18951
|
const limit = parseLimitOpt("bash-history", opts.limit);
|
|
18976
18952
|
const blobs = listBlobs(BASH_OUTPUT_SUBDIR);
|
|
@@ -18985,24 +18961,17 @@ function cmdBashHistory(opts) {
|
|
|
18985
18961
|
exitCode: typeof v["exitCode"] === "number" ? v["exitCode"] : -1,
|
|
18986
18962
|
sizeBytes: typeof v["sizeBytes"] === "number" ? v["sizeBytes"] : 0
|
|
18987
18963
|
};
|
|
18988
|
-
}).filter((x) => x !== null)
|
|
18989
|
-
|
|
18990
|
-
|
|
18991
|
-
process.stdout.write(displaySafeJson(items) + "\n");
|
|
18992
|
-
return;
|
|
18993
|
-
}
|
|
18994
|
-
if (items.length === 0) {
|
|
18995
|
-
process.stdout.write("No bash output entries cached.\n");
|
|
18996
|
-
return;
|
|
18997
|
-
}
|
|
18998
|
-
process.stdout.write(`${pad("id", 18)} ${pad("bytes", 8)} ${pad("exit", 4)} command
|
|
18964
|
+
}).filter((x) => x !== null);
|
|
18965
|
+
emitHistoryOutput(allItems, limit, opts.json, "No bash output entries cached.\n", (items) => {
|
|
18966
|
+
process.stdout.write(`${pad("id", 18)} ${pad("bytes", 8)} ${pad("exit", 4)} command
|
|
18999
18967
|
`);
|
|
19000
|
-
|
|
19001
|
-
|
|
19002
|
-
|
|
19003
|
-
|
|
18968
|
+
for (const item of items) {
|
|
18969
|
+
const flatCommand = displaySafeText(item.command);
|
|
18970
|
+
const preview = flatCommand.length > 80 ? flatCommand.slice(0, 77) + "..." : flatCommand;
|
|
18971
|
+
process.stdout.write(`${pad(displaySafeText(item.id), 18)} ${pad(String(item.sizeBytes), 8)} ${pad(String(item.exitCode), 4)} ${preview}
|
|
19004
18972
|
`);
|
|
19005
|
-
|
|
18973
|
+
}
|
|
18974
|
+
});
|
|
19006
18975
|
}
|
|
19007
18976
|
function cmdWebHistory(opts) {
|
|
19008
18977
|
const limit = parseLimitOpt("web-history", opts.limit);
|
|
@@ -19016,22 +18985,15 @@ function cmdWebHistory(opts) {
|
|
|
19016
18985
|
bytes: typeof v["content"] === "string" ? Buffer.byteLength(v["content"], "utf8") : 0,
|
|
19017
18986
|
storedAt: mtime
|
|
19018
18987
|
};
|
|
19019
|
-
}).filter((x) => x !== null)
|
|
19020
|
-
|
|
19021
|
-
|
|
19022
|
-
process.stdout.write(displaySafeJson(items) + "\n");
|
|
19023
|
-
return;
|
|
19024
|
-
}
|
|
19025
|
-
if (items.length === 0) {
|
|
19026
|
-
process.stdout.write("No web output entries cached.\n");
|
|
19027
|
-
return;
|
|
19028
|
-
}
|
|
19029
|
-
process.stdout.write(`${pad("id", 18)} ${pad("bytes", 8)} url
|
|
18988
|
+
}).filter((x) => x !== null);
|
|
18989
|
+
emitHistoryOutput(allItems, limit, opts.json, "No web output entries cached.\n", (items) => {
|
|
18990
|
+
process.stdout.write(`${pad("id", 18)} ${pad("bytes", 8)} url
|
|
19030
18991
|
`);
|
|
19031
|
-
|
|
19032
|
-
|
|
18992
|
+
for (const item of items) {
|
|
18993
|
+
process.stdout.write(`${pad(displaySafeText(item.id), 18)} ${pad(String(item.bytes), 8)} ${displaySafeText(item.url)}
|
|
19033
18994
|
`);
|
|
19034
|
-
|
|
18995
|
+
}
|
|
18996
|
+
});
|
|
19035
18997
|
}
|
|
19036
18998
|
function cmdMcpHistory(opts) {
|
|
19037
18999
|
const limit = parseLimitOpt("mcp-history", opts.limit);
|
|
@@ -19047,22 +19009,15 @@ function cmdMcpHistory(opts) {
|
|
|
19047
19009
|
storedAt: typeof v["storedAt"] === "number" ? v["storedAt"] : mtime,
|
|
19048
19010
|
sizeBytes: typeof v["sizeBytes"] === "number" ? v["sizeBytes"] : 0
|
|
19049
19011
|
};
|
|
19050
|
-
}).filter((x) => x !== null)
|
|
19051
|
-
|
|
19052
|
-
|
|
19053
|
-
process.stdout.write(displaySafeJson(items) + "\n");
|
|
19054
|
-
return;
|
|
19055
|
-
}
|
|
19056
|
-
if (items.length === 0) {
|
|
19057
|
-
process.stdout.write("No mcp output entries cached.\n");
|
|
19058
|
-
return;
|
|
19059
|
-
}
|
|
19060
|
-
process.stdout.write(`${pad("id", 18)} ${pad("bytes", 8)} tool
|
|
19012
|
+
}).filter((x) => x !== null);
|
|
19013
|
+
emitHistoryOutput(allItems, limit, opts.json, "No mcp output entries cached.\n", (items) => {
|
|
19014
|
+
process.stdout.write(`${pad("id", 18)} ${pad("bytes", 8)} tool
|
|
19061
19015
|
`);
|
|
19062
|
-
|
|
19063
|
-
|
|
19016
|
+
for (const item of items) {
|
|
19017
|
+
process.stdout.write(`${pad(displaySafeText(item.id), 18)} ${pad(String(item.sizeBytes), 8)} ${displaySafeText(item.toolName)}
|
|
19064
19018
|
`);
|
|
19065
|
-
|
|
19019
|
+
}
|
|
19020
|
+
});
|
|
19066
19021
|
}
|
|
19067
19022
|
function cmdCleanCache(opts) {
|
|
19068
19023
|
const removed = {};
|
|
@@ -19309,7 +19264,14 @@ function registerSessionCommands(program2, guard) {
|
|
|
19309
19264
|
program2.command("audit").description("session retrospective: analyze the current session transcript (Copilot CLI or Claude Code) and emit a Maintainer Feedback Card").option("--project <path>", "project root to analyze").option("--transcript <path>", "explicit transcript path (default: active or newest session for this project)").option("-j, --json", "output as JSON").action(guard(cmdAudit));
|
|
19310
19265
|
program2.command("session-outline [session-id-or-path]").description("turn-by-turn structure (role, preview, tool calls, approx size) of a Claude Code session JSONL transcript, instead of a raw Read; defaults to the current project's most recent session").option("--project <path>", "project root to resolve the session transcript against").option("--json", "output JSON").action(guard(cmdSessionOutline));
|
|
19311
19266
|
program2.command("session-slice [session-id-or-path]").description("full content of one turn range from a Claude Code session JSONL transcript (see session-outline for turn numbers), instead of a raw Read").requiredOption("--range <spec>", "turn range, e.g. 5-9 or 12 (see session-outline for turn numbers)").option("--project <path>", "project root to resolve the session transcript against").option("--json", "output JSON").action(guard(cmdSessionSlice));
|
|
19312
|
-
program2.command("session-audit").alias("audit-session").description("corpus-wide token attribution across every local Claude Code session transcript: measured billed usage, estimated content size by source and by tool, and billed cost by session position (aggregate counts only, never transcript content)").option("--dir <path>", "transcript corpus root to scan (default: ~/.claude/projects)").option("--json", "output JSON").action(guard(
|
|
19267
|
+
program2.command("session-audit").alias("audit-session").description("corpus-wide token attribution across every local Claude Code session transcript: measured billed usage, estimated content size by source and by tool, and billed cost by session position (aggregate counts only, never transcript content)").option("--dir <path>", "transcript corpus root to scan (default: ~/.claude/projects)").option("--window-days <days>", "only transcripts whose file was modified in the last N days (0 = all time)", "0").option("--tool-errors", "print only the failed-tool-call report: calls, errors, expected failures by reason and unknown ones, per tool and per model, with the top unknown error prefixes").option("--json", "output JSON").action(guard(
|
|
19268
|
+
(opts) => cmdSessionAudit({
|
|
19269
|
+
...opts.dir !== void 0 ? { dir: opts.dir } : {},
|
|
19270
|
+
...opts.json === true ? { json: true } : {},
|
|
19271
|
+
...opts.toolErrors === true ? { toolErrors: true } : {},
|
|
19272
|
+
windowDays: requireNonNegativeInt("--window-days", opts.windowDays)
|
|
19273
|
+
})
|
|
19274
|
+
));
|
|
19313
19275
|
program2.command("mcp-audit").description("MCP server schema cost-vs-usage report: estimate per-server token cost from cached tool calls").option("--project <path>", "project root to analyze").option("--json", "output JSON").action(guard(cmdMcpAudit));
|
|
19314
19276
|
program2.command("recall [query]").description("search across every cached bash-output, web-output, and mcp-output entry (full-text); with no query, list them newest-first").option("--type <type>", "filter to one cache type: bash, web, or mcp").option("--limit <n>", "max results to return (default: 10)").option("--json", "output JSON").action(guard(cmdRecall));
|
|
19315
19277
|
program2.command("hint-stats").description("per-category efficacy report for token-goat's discretionary hint hooks (emitted/acted-on/suppression)").option("--json", "output JSON").option("--reset", "clear all tracked emissions and manual marks").option("--mark-effective <category>", 'record a manual "effective" vote for a hint category').option("--mark-ineffective <category>", 'record a manual "ineffective" vote for a hint category').action(guard(cmdHintStats));
|
|
@@ -19392,7 +19354,7 @@ function registerSessionCommands(program2, guard) {
|
|
|
19392
19354
|
init_define_import_meta_env();
|
|
19393
19355
|
var NO_SERVER_HANDLER_REASON = "token-goat has no registered server-side handler for this event (zero registerHook('notification'|'stop', ...) call sites in src/) -- wiring it client-side would currently be a no-op";
|
|
19394
19356
|
var NO_POST_COMPACT_EVENT_REASON = "post_compact is a Claude Code event (hook_event_name PostCompact, carrying compact_summary); no equivalent has been confirmed for this harness, so it is left unwired rather than guessed at";
|
|
19395
|
-
var NO_SEPARATE_FAILURE_EVENT_REASON = "post_tool_use_failure exists because Copilot CLI
|
|
19357
|
+
var NO_SEPARATE_FAILURE_EVENT_REASON = "post_tool_use_failure exists because Copilot CLI (postToolUseFailure) and Claude Code (PostToolUseFailure) route a failed tool result to a separate event instead of their post-tool one. No separate failure event is wired for this harness, so a failed tool call either arrives on post_tool_use like any other result or is not seen; which of the two has not been checked here";
|
|
19396
19358
|
var COPILOT_NO_POST_COMPACT_REASON = "Copilot CLI has no post-compaction hook: its HookType enum (schemas/api.schema.json, 1.0.79 and 1.0.80) declares preCompact and no postCompact, and both preCompact call sites in app.js await the hook and never assign its result. Whether the summary is reachable another way is open. app.js does emit session.compaction_complete carrying summaryContent, and the session event writer subscribes to '*' -- but emit() vs emitEphemeral() does NOT gate that writer: dispatchEventHandlers runs outside the ephemeral branch in emitInternal, on('*') early-returns past every filter, and the writer's callback applies no filter of its own before handing the JSON to native recordEventJson. The durable-vs-ephemeral decision is in Rust (api_session_event_writer.rs) and was not readable. Nor is the event uniformly summary-bearing: two of the four emit sites are the branches taken when no summary exists, summaryContent is optional in the schema, and the relay session class emits the same event via emitEphemeral. No compaction has ever been observed on the machines checked, so nothing empirical anchors any of it. Context can be written back on the next turn through userPromptSubmitted additionalContext";
|
|
19397
19359
|
var VERIFICATION_RANK = {
|
|
19398
19360
|
dogfooded: 0,
|
|
@@ -19411,9 +19373,8 @@ var BRIDGE_CAPABILITY_MATRIX = [
|
|
|
19411
19373
|
sourceFile: "src/install.ts (HOOK_EVENT_MAP)",
|
|
19412
19374
|
verification: "dogfooded",
|
|
19413
19375
|
verificationNote: "The harness this repo is developed and released under; CLAUDE.md requires every CLI/hook change be run against the built binary here before it ships.",
|
|
19414
|
-
implemented: /* @__PURE__ */ new Set(["pre_tool_use", "post_tool_use", "pre_compact", "post_compact", "user_prompt_submit", "subagent_stop", "session_start"]),
|
|
19376
|
+
implemented: /* @__PURE__ */ new Set(["pre_tool_use", "post_tool_use", "post_tool_use_failure", "pre_compact", "post_compact", "user_prompt_submit", "subagent_stop", "session_start"]),
|
|
19415
19377
|
reasons: [
|
|
19416
|
-
{ events: ["post_tool_use_failure"], reason: NO_SEPARATE_FAILURE_EVENT_REASON },
|
|
19417
19378
|
{ events: ["notification", "stop"], reason: NO_SERVER_HANDLER_REASON }
|
|
19418
19379
|
]
|
|
19419
19380
|
},
|
|
@@ -19450,55 +19411,7 @@ var BRIDGE_CAPABILITY_MATRIX = [
|
|
|
19450
19411
|
}
|
|
19451
19412
|
]
|
|
19452
19413
|
},
|
|
19453
|
-
/**
|
|
19454
|
-
* What Copilot CLI's wired events can actually carry, read from the shipping 1.0.80 bundle
|
|
19455
|
-
* rather than from its hooks reference page. A row's `implemented` set says an event is wired;
|
|
19456
|
-
* it deliberately says nothing about how much of that event's response the harness honors, and
|
|
19457
|
-
* for Copilot the difference matters:
|
|
19458
|
-
*
|
|
19459
|
-
* - `pre_tool_use` deny is real, and the reason text reaches the model. The native string table
|
|
19460
|
-
* (runtime.node offset 98057208) carries `permissionDecision`, `permissionDecisionReason`, the
|
|
19461
|
-
* default "No reason provided." and the formatter "Denied by preToolUse hook: " as distinct
|
|
19462
|
-
* literals, and app.js sets `{textResultForLlm: reason, resultType: "denied"}` per denial and
|
|
19463
|
-
* filters that call out of execution. This was previously only an inference drawn from an
|
|
19464
|
-
* incident comment; it is now confirmed. The fail-closed "(hook errored)" deny-all strings sit
|
|
19465
|
-
* beside these, so that incident was behavior layered on top of a working deny handler, not a
|
|
19466
|
-
* substitute for one.
|
|
19467
|
-
* - `post_tool_use` honors `modifiedResult`, so compression, injection fencing and image shrink
|
|
19468
|
-
* do reach the model: `postToolExecution` (app.js offset 2043150) assigns the returned
|
|
19469
|
-
* `toolResultJson` onto the tool result in place.
|
|
19470
|
-
* - `post_tool_use` drops `additionalContext` on the JS path -- no supplier for the
|
|
19471
|
-
* `onAdditionalContext` callback anywhere in the bundle, and no `additional_contexts` key in
|
|
19472
|
-
* that event's native return payload, unlike its pre-tool sibling. Whether native folds it
|
|
19473
|
-
* into the returned result instead was not verified.
|
|
19474
|
-
* - Failed tool calls never reach `post_tool_use` at all. Copilot routes them to a separate
|
|
19475
|
-
* `postToolUseFailure` event, which is handed only a stringified error and honors only
|
|
19476
|
-
* `additionalContext`; `modifiedResult` is documented as not honored there. So on Copilot the
|
|
19477
|
-
* output of a failed tool call reaches the model unfenced, uncompressed and unshrunk, and no
|
|
19478
|
-
* response shape token-goat's shim can emit changes that. Known gap, deliberately recorded.
|
|
19479
|
-
* What `additionalContext` does on that event is no longer doc-derived: app.js offset 2043380
|
|
19480
|
-
* reads the native processor's return and, when it carries `additionalContext`, either folds
|
|
19481
|
-
* it into `textResultForLlm` (if `appendFailureContextToToolResult` is set) or formats it and
|
|
19482
|
-
* pushes `{content, source: "system"}` onto `toolResult.newMessages`. So the channel is real
|
|
19483
|
-
* and model-visible -- it just carries advice alongside the failure, never a replacement for
|
|
19484
|
-
* it. It is wired now, as its own `post_tool_use_failure` event rather than a reuse of
|
|
19485
|
-
* `post_tool_use`: routing failures through the success event would let success-path handlers
|
|
19486
|
-
* mark a file as successfully read when the read failed. Because the channel spends tokens
|
|
19487
|
-
* instead of saving them, its handler (`src/hooks_tool_failure.ts`) stays silent on a first
|
|
19488
|
-
* failure and speaks only on an exact repeat.
|
|
19489
|
-
* - `pre_compact` is wired and fires, but nothing it returns can reach the model. Both dispatch
|
|
19490
|
-
* sites call it in statement position and drop the result: app.js offset 2467452 (the manual
|
|
19491
|
-
* `/compact` path) and offset 2571216 (`case "execute_pre_compact_hook"`). The contrast is
|
|
19492
|
-
* what makes this conclusive rather than an absence of evidence -- the same `event()` runner's
|
|
19493
|
-
* return IS read for other events, e.g. `notification` at offset 2296123 assigns it and
|
|
19494
|
-
* forwards `additionalContext` as a prepended system prompt. The compaction prompt is then
|
|
19495
|
-
* built from session history and the user's own focus text, with no hook channel into it.
|
|
19496
|
-
* So token-goat's `pre_compact` registration here is observe-only by construction, not merely
|
|
19497
|
-
* unused: a future attempt to inject a session manifest through it would silently do nothing.
|
|
19498
|
-
* Not verified: whether the native declarative runner applies `additionalContext` itself. The
|
|
19499
|
-
* trail ends in stripped Rust. That it would make the explicit JS handling for `notification`
|
|
19500
|
-
* and `userPromptSubmitted` redundant is an argument, not a proof.
|
|
19501
|
-
*/
|
|
19414
|
+
/** What Copilot CLI's wired events can actually carry, read from the shipping 1.0.80 bundle rather than from its hooks reference page. A row's `implemented` set says an event is wired; it deliberately says nothing about how much of that event's response the harness honors, and for Copilot the difference matters: - `pre_tool_use` deny is real, and the reason text reaches the model. The native string table (runtime.node offset 98057208) carries `permissionDecision`, `permissionDecisionReason`, the default "No reason provided." and the formatter "Denied by preToolUse hook: " as distinct literals, and app.js sets `{textResultForLlm: reason, resultType: "denied"}` per denial and filters that call out of execution. This was previously only an inference drawn from an incident comment; it is now confirmed. The fail-closed "(hook errored)" deny-all strings sit beside these, so that incident was behavior layered on top of a working deny handler, not a substitute for one. - `post_tool_use` honors `modifiedResult`, so compression, injection fencing and image shrink do reach the model: `postToolExecution` (app.js offset 2043150) assigns the returned `toolResultJson` onto the tool result in place. - `post_tool_use` drops `additionalContext` on the JS path -- no supplier for the `onAdditionalContext` callback anywhere in the bundle, and no `additional_contexts` key in that event's native return payload, unlike its pre-tool sibling. Whether native folds it into the returned result instead was not verified. - Failed tool calls never reach `post_tool_use` at all. Copilot routes them to a separate `postToolUseFailure` event, which is handed only a stringified error and honors only `additionalContext`; `modifiedResult` is documented as not honored there. So on Copilot the output of a failed tool call reaches the model unfenced, uncompressed and unshrunk, and no response shape token-goat's shim can emit changes that. Known gap, deliberately recorded. What `additionalContext` does on that event is no longer doc-derived: app.js offset 2043380 reads the native processor's return and, when it carries `additionalContext`, either folds it into `textResultForLlm` (if `appendFailureContextToToolResult` is set) or formats it and pushes `{content, source: "system"}` onto `toolResult.newMessages`. So the channel is real and model-visible -- it just carries advice alongside the failure, never a replacement for it. It is wired now, as its own `post_tool_use_failure` event rather than a reuse of `post_tool_use`: routing failures through the success event would let success-path handlers mark a file as successfully read when the read failed. Because the channel spends tokens instead of saving them, its handler (`src/hooks_tool_failure.ts`) stays silent on a first failure and speaks only on an exact repeat. - `pre_compact` is wired and fires, but nothing it returns can reach the model. Both dispatch sites call it in statement position and drop the result: app.js offset 2467452 (the manual `/compact` path) and offset 2571216 (`case "execute_pre_compact_hook"`). The contrast is what makes this conclusive rather than an absence of evidence -- the same `event()` runner's return IS read for other events, e.g. `notification` at offset 2296123 assigns it and forwards `additionalContext` as a prepended system prompt. The compaction prompt is then built from session history and the user's own focus text, with no hook channel into it. So token-goat's `pre_compact` registration here is observe-only by construction, not merely unused: a future attempt to inject a session manifest through it would silently do nothing. Not verified: whether the native declarative runner applies `additionalContext` itself. The trail ends in stripped Rust. That it would make the explicit JS handling for `notification` and `userPromptSubmitted` redundant is an argument, not a proof. */
|
|
19502
19415
|
{
|
|
19503
19416
|
harness: "copilot_cli",
|
|
19504
19417
|
label: "Copilot CLI",
|
|
@@ -19723,25 +19636,25 @@ function installVerificationNotice(harness) {
|
|
|
19723
19636
|
|
|
19724
19637
|
// src/purge.ts
|
|
19725
19638
|
init_define_import_meta_env();
|
|
19726
|
-
import * as
|
|
19727
|
-
import * as
|
|
19639
|
+
import * as fs42 from "node:fs";
|
|
19640
|
+
import * as path38 from "node:path";
|
|
19728
19641
|
function directorySize(root) {
|
|
19729
19642
|
let total = 0;
|
|
19730
19643
|
let entries;
|
|
19731
19644
|
try {
|
|
19732
|
-
entries =
|
|
19645
|
+
entries = fs42.readdirSync(root, { withFileTypes: true });
|
|
19733
19646
|
} catch {
|
|
19734
19647
|
return 0;
|
|
19735
19648
|
}
|
|
19736
19649
|
for (const entry of entries) {
|
|
19737
|
-
const full =
|
|
19650
|
+
const full = path38.join(root, entry.name);
|
|
19738
19651
|
if (entry.isDirectory()) {
|
|
19739
19652
|
total += directorySize(full);
|
|
19740
19653
|
continue;
|
|
19741
19654
|
}
|
|
19742
19655
|
if (!entry.isFile()) continue;
|
|
19743
19656
|
try {
|
|
19744
|
-
total +=
|
|
19657
|
+
total += fs42.statSync(full).size;
|
|
19745
19658
|
} catch {
|
|
19746
19659
|
}
|
|
19747
19660
|
}
|
|
@@ -19760,7 +19673,7 @@ function purgeDataDirectories() {
|
|
|
19760
19673
|
}
|
|
19761
19674
|
const bytes = directorySize(root);
|
|
19762
19675
|
try {
|
|
19763
|
-
|
|
19676
|
+
fs42.rmSync(root, { recursive: true, force: true });
|
|
19764
19677
|
result.removed.push({ path: root, bytes });
|
|
19765
19678
|
} catch (e) {
|
|
19766
19679
|
result.failed.push({ path: root, reason: e instanceof Error ? e.message : String(e) });
|
|
@@ -19907,8 +19820,8 @@ async function getSectionContent(fileId, heading, opts = {}) {
|
|
|
19907
19820
|
|
|
19908
19821
|
// src/cli_bench.ts
|
|
19909
19822
|
init_define_import_meta_env();
|
|
19910
|
-
import * as
|
|
19911
|
-
import * as
|
|
19823
|
+
import * as fs43 from "node:fs";
|
|
19824
|
+
import * as path39 from "node:path";
|
|
19912
19825
|
var ControlFilter = class extends ToolFilter {
|
|
19913
19826
|
constructor(name, transform) {
|
|
19914
19827
|
super();
|
|
@@ -19929,13 +19842,13 @@ var CONTROL_FILTERS = {
|
|
|
19929
19842
|
};
|
|
19930
19843
|
var MAX_BENCH_FILE_BYTES = 5 * 1024 * 1024;
|
|
19931
19844
|
function readCaseFile(id, filePath, what) {
|
|
19932
|
-
const bytes =
|
|
19845
|
+
const bytes = fs43.statSync(filePath).size;
|
|
19933
19846
|
if (bytes > MAX_BENCH_FILE_BYTES) {
|
|
19934
19847
|
throw new Error(
|
|
19935
19848
|
`bench case ${id}: ${what} is ${bytes} bytes, over the ${MAX_BENCH_FILE_BYTES}-byte limit for a corpus file (${filePath})`
|
|
19936
19849
|
);
|
|
19937
19850
|
}
|
|
19938
|
-
return
|
|
19851
|
+
return fs43.readFileSync(filePath, "utf8");
|
|
19939
19852
|
}
|
|
19940
19853
|
function parseCase(id, metaPath, outputPath) {
|
|
19941
19854
|
const metaText = readCaseFile(id, metaPath, "metadata");
|
|
@@ -19970,7 +19883,7 @@ function parseCase(id, metaPath, outputPath) {
|
|
|
19970
19883
|
function loadCorpus(dir) {
|
|
19971
19884
|
let entries;
|
|
19972
19885
|
try {
|
|
19973
|
-
entries =
|
|
19886
|
+
entries = fs43.readdirSync(dir);
|
|
19974
19887
|
} catch {
|
|
19975
19888
|
throw new Error(`bench corpus not found: ${dir}`);
|
|
19976
19889
|
}
|
|
@@ -19978,9 +19891,9 @@ function loadCorpus(dir) {
|
|
|
19978
19891
|
for (const entry of entries.sort()) {
|
|
19979
19892
|
if (!entry.endsWith(".json")) continue;
|
|
19980
19893
|
const id = entry.slice(0, -".json".length);
|
|
19981
|
-
const outputPath =
|
|
19982
|
-
if (!
|
|
19983
|
-
cases.push(parseCase(id,
|
|
19894
|
+
const outputPath = path39.join(dir, `${id}.txt`);
|
|
19895
|
+
if (!fs43.existsSync(outputPath)) throw new Error(`bench case ${id}: missing output file ${outputPath}`);
|
|
19896
|
+
cases.push(parseCase(id, path39.join(dir, entry), outputPath));
|
|
19984
19897
|
}
|
|
19985
19898
|
if (cases.length === 0) throw new Error(`bench corpus is empty: ${dir}`);
|
|
19986
19899
|
return cases;
|
|
@@ -20100,10 +20013,10 @@ function appendTsv(file, report, commit) {
|
|
|
20100
20013
|
report.mustKeepTotal,
|
|
20101
20014
|
report.coveredFilters
|
|
20102
20015
|
].join(" ");
|
|
20103
|
-
const dir =
|
|
20104
|
-
|
|
20105
|
-
const header =
|
|
20106
|
-
|
|
20016
|
+
const dir = path39.dirname(path39.resolve(file));
|
|
20017
|
+
fs43.mkdirSync(dir, { recursive: true });
|
|
20018
|
+
const header = fs43.existsSync(file) ? "" : TSV_HEADER;
|
|
20019
|
+
fs43.appendFileSync(file, header + row + "\n", "utf8");
|
|
20107
20020
|
}
|
|
20108
20021
|
function currentCommit(cwd) {
|
|
20109
20022
|
const opts = cwd === void 0 ? {} : { cwd };
|
|
@@ -20143,10 +20056,10 @@ function readBoundedText(text, file) {
|
|
|
20143
20056
|
if (text === void 0 && file === void 0) throw new CliError("provide text or --file");
|
|
20144
20057
|
let value;
|
|
20145
20058
|
if (file !== void 0) {
|
|
20146
|
-
if (
|
|
20059
|
+
if (fs44.statSync(file).size > CONTENT_MAX_INPUT_CHARS) {
|
|
20147
20060
|
throw new CliError(`file exceeds the ${CONTENT_MAX_INPUT_CHARS}-byte safety limit`);
|
|
20148
20061
|
}
|
|
20149
|
-
value =
|
|
20062
|
+
value = fs44.readFileSync(file, "utf8");
|
|
20150
20063
|
} else {
|
|
20151
20064
|
if (text === void 0) throw new CliError("provide text or --file");
|
|
20152
20065
|
value = text;
|
|
@@ -20191,19 +20104,23 @@ function cmdHandoffResolve(name, opts) {
|
|
|
20191
20104
|
if (result === null) throw new CliError(`no local handoff named "${name}" in this project`);
|
|
20192
20105
|
out(typeof result === "string" ? result : formatCompression(result, false, "payload withheld: inlining it would cost more tokens than the original text; pass --full to get the original text back outright"));
|
|
20193
20106
|
}
|
|
20194
|
-
async function cmdSemantic(query, opts) {
|
|
20107
|
+
async function cmdSemantic(query, more, opts) {
|
|
20195
20108
|
if (!query && !opts.preflight && !opts.warm) {
|
|
20196
20109
|
throw new CliError("missing required argument: query");
|
|
20197
20110
|
}
|
|
20111
|
+
if (opts.preflight === true && more.length > 0) {
|
|
20112
|
+
throw new CliError("--preflight checks the embedding setup and runs no query; drop the queries, or drop --preflight to search");
|
|
20113
|
+
}
|
|
20198
20114
|
const limit = opts.limit !== void 0 ? requireNonNegativeInt("--limit", opts.limit) : 20;
|
|
20199
|
-
const
|
|
20115
|
+
const semanticOpts = {
|
|
20200
20116
|
limit,
|
|
20201
20117
|
...opts.json === true ? { json: true } : {},
|
|
20202
20118
|
...opts.grep !== void 0 ? { grep: opts.grep } : {},
|
|
20203
20119
|
...opts.excludeTests === true ? { excludeTests: true } : {},
|
|
20204
20120
|
...opts.preflight === true ? { preflight: true } : {},
|
|
20205
20121
|
...opts.warm === true ? { warm: true } : {}
|
|
20206
|
-
}
|
|
20122
|
+
};
|
|
20123
|
+
const { text, code } = more.length > 0 ? await runSemanticMulti([query ?? "", ...more], semanticOpts) : await runSemantic(query ?? "", semanticOpts);
|
|
20207
20124
|
(opts.json === true || code === 0 ? out : err)(text);
|
|
20208
20125
|
process.exitCode = code;
|
|
20209
20126
|
}
|
|
@@ -20269,7 +20186,7 @@ async function cmdIndex(pathArg, opts = {}) {
|
|
|
20269
20186
|
continue;
|
|
20270
20187
|
}
|
|
20271
20188
|
const sha = fingerprintFile(key);
|
|
20272
|
-
if (sha === null && !
|
|
20189
|
+
if (sha === null && !fs44.existsSync(key)) continue;
|
|
20273
20190
|
recordKnownRootThrottled(key, dataDir(), dbPath);
|
|
20274
20191
|
const entry = sha !== null ? getFileEntry(key, dbPath) : null;
|
|
20275
20192
|
const spellingStale = entry !== null && indexedPathSpellingIsStale(entry.filePath, key);
|
|
@@ -20306,7 +20223,7 @@ async function cmdIndex(pathArg, opts = {}) {
|
|
|
20306
20223
|
}
|
|
20307
20224
|
continue;
|
|
20308
20225
|
}
|
|
20309
|
-
if (!
|
|
20226
|
+
if (!fs44.existsSync(key)) continue;
|
|
20310
20227
|
}
|
|
20311
20228
|
const embedFresh = parseUnchanged ? embedUnchanged : embedFreshFor(getFileEntry(key, dbPath)?.embedSha);
|
|
20312
20229
|
if (!embedFresh) {
|
|
@@ -20367,7 +20284,7 @@ async function cmdMcpServe() {
|
|
|
20367
20284
|
let StdioServerTransport;
|
|
20368
20285
|
try {
|
|
20369
20286
|
;
|
|
20370
|
-
({ createMcpServer } = await import("./token-goat-chunk-
|
|
20287
|
+
({ createMcpServer } = await import("./token-goat-chunk-SJEKA7Y2.mjs"));
|
|
20371
20288
|
({ StdioServerTransport } = await import("./token-goat-chunk-EVC4TOLE.mjs"));
|
|
20372
20289
|
} catch (err2) {
|
|
20373
20290
|
process.stderr.write(
|
|
@@ -20392,11 +20309,11 @@ async function cmdHook(event, opts) {
|
|
|
20392
20309
|
if (typeof opts.harness === "string" && opts.harness.length > 0) {
|
|
20393
20310
|
process.env[ENV_KEYS.HARNESS_OVERRIDE] = opts.harness;
|
|
20394
20311
|
}
|
|
20395
|
-
const { relay } = await import("./token-goat-chunk-
|
|
20312
|
+
const { relay } = await import("./token-goat-chunk-7MAFDRVR.mjs");
|
|
20396
20313
|
await relay(event);
|
|
20397
20314
|
}
|
|
20398
20315
|
function projectHooksCommitNote(pathFiles, hooksConfigPath) {
|
|
20399
|
-
const shim = hooksConfigPath === void 0 ? "" : ` (${displaySafePath(
|
|
20316
|
+
const shim = hooksConfigPath === void 0 ? "" : ` (${displaySafePath(path40.join(path40.dirname(hooksConfigPath), HOOKS_SCRIPT_FILE))} is generated with them)`;
|
|
20400
20317
|
return `Note: ${pathFiles.map((p) => displaySafePath(p)).join(", ")} ${pathFiles.length === 1 ? "holds" : "hold"} absolute paths to node and token-goat on this machine${shim}, so do not commit them: list them in .git/info/exclude or .gitignore.`;
|
|
20401
20318
|
}
|
|
20402
20319
|
function visualStudioManualSteps(scope) {
|
|
@@ -20429,7 +20346,7 @@ async function cmdInstall(opts) {
|
|
|
20429
20346
|
if (opts.project === true && opts.user === true) {
|
|
20430
20347
|
throw new Error("install takes either -p/--project or --user, not both.");
|
|
20431
20348
|
}
|
|
20432
|
-
await import("./token-goat-chunk-
|
|
20349
|
+
await import("./token-goat-chunk-7MAFDRVR.mjs");
|
|
20433
20350
|
const scope = opts.project === true ? "project" : "user";
|
|
20434
20351
|
if (wantsClaudeCodeBase(opts)) {
|
|
20435
20352
|
const result = installHooks(scope);
|
|
@@ -20575,16 +20492,16 @@ async function cmdInstall(opts) {
|
|
|
20575
20492
|
);
|
|
20576
20493
|
}
|
|
20577
20494
|
try {
|
|
20578
|
-
const skillDir2 =
|
|
20579
|
-
if (
|
|
20580
|
-
const entries =
|
|
20495
|
+
const skillDir2 = path40.join(claudeConfigDir(), "skills");
|
|
20496
|
+
if (fs44.existsSync(skillDir2)) {
|
|
20497
|
+
const entries = fs44.readdirSync(skillDir2, { withFileTypes: true });
|
|
20581
20498
|
const skillNames = [];
|
|
20582
20499
|
const sessionId = getSessionId();
|
|
20583
20500
|
for (const entry of entries) {
|
|
20584
20501
|
if (!entry.isDirectory()) continue;
|
|
20585
|
-
const skillFile =
|
|
20586
|
-
if (
|
|
20587
|
-
const body =
|
|
20502
|
+
const skillFile = path40.join(skillDir2, entry.name, "SKILL.md");
|
|
20503
|
+
if (fs44.existsSync(skillFile)) {
|
|
20504
|
+
const body = fs44.readFileSync(skillFile, "utf-8");
|
|
20588
20505
|
const compact = extractCompactFromMarker(body);
|
|
20589
20506
|
if (compact === null) continue;
|
|
20590
20507
|
const sourceSha = contentHash(body);
|
|
@@ -20595,9 +20512,9 @@ async function cmdInstall(opts) {
|
|
|
20595
20512
|
if (skillNames.length > 0) {
|
|
20596
20513
|
const dir = skillOutputsDir();
|
|
20597
20514
|
ensureDirSync(dir);
|
|
20598
|
-
const pregenPath =
|
|
20515
|
+
const pregenPath = path40.join(dir, "pregen.json");
|
|
20599
20516
|
const pregenData = { ts: Date.now(), names: skillNames };
|
|
20600
|
-
await
|
|
20517
|
+
await fs44.promises.writeFile(pregenPath, JSON.stringify(pregenData, null, 2));
|
|
20601
20518
|
out(`Pre-generated ${skillNames.length} skill compacts.`);
|
|
20602
20519
|
}
|
|
20603
20520
|
}
|
|
@@ -20860,7 +20777,7 @@ function cmdBashOutput(id, opts) {
|
|
|
20860
20777
|
}
|
|
20861
20778
|
let content;
|
|
20862
20779
|
try {
|
|
20863
|
-
const st =
|
|
20780
|
+
const st = fs44.statSync(opts.file);
|
|
20864
20781
|
if (st.isFIFO() || st.isSocket()) {
|
|
20865
20782
|
throw new CliError(`--file '${opts.file}' is a special file (FIFO or socket) \u2014 only regular files are supported`);
|
|
20866
20783
|
}
|
|
@@ -20875,7 +20792,7 @@ function cmdBashOutput(id, opts) {
|
|
|
20875
20792
|
`);
|
|
20876
20793
|
}
|
|
20877
20794
|
}
|
|
20878
|
-
content = redactIfDotenv(opts.file, decodeSource(
|
|
20795
|
+
content = redactIfDotenv(opts.file, decodeSource(fs44.readFileSync(opts.file)));
|
|
20879
20796
|
} catch (e) {
|
|
20880
20797
|
if (e instanceof CliError) throw e;
|
|
20881
20798
|
throw new CliError(`cannot read file: ${opts.file}`);
|
|
@@ -20939,15 +20856,15 @@ function cmdMcpOutput(id, opts) {
|
|
|
20939
20856
|
if (opts.file.includes("\0")) {
|
|
20940
20857
|
throw new CliError("--file path contains a null byte");
|
|
20941
20858
|
}
|
|
20942
|
-
if (!
|
|
20859
|
+
if (!fs44.existsSync(opts.file)) {
|
|
20943
20860
|
throw new CliError(`file not found: ${opts.file}`);
|
|
20944
20861
|
}
|
|
20945
20862
|
try {
|
|
20946
|
-
const st =
|
|
20863
|
+
const st = fs44.statSync(opts.file);
|
|
20947
20864
|
if (st.isFIFO() || st.isSocket()) {
|
|
20948
20865
|
throw new CliError(`--file '${opts.file}' is a special file (FIFO or socket) \u2014 only regular files are supported`);
|
|
20949
20866
|
}
|
|
20950
|
-
content = decodeSource(
|
|
20867
|
+
content = decodeSource(fs44.readFileSync(opts.file));
|
|
20951
20868
|
} catch (e) {
|
|
20952
20869
|
if (e instanceof CliError) throw e;
|
|
20953
20870
|
throw new CliError(`cannot read file: ${opts.file}`);
|
|
@@ -21020,9 +20937,14 @@ async function cmdCompress(commandArgs, opts = {}) {
|
|
|
21020
20937
|
process.exitCode = 1;
|
|
21021
20938
|
return;
|
|
21022
20939
|
}
|
|
21023
|
-
const bashRunner = await import("./token-goat-chunk-
|
|
20940
|
+
const bashRunner = await import("./token-goat-chunk-BCN2YQC6.mjs");
|
|
21024
20941
|
if (opts.compress === false) {
|
|
21025
|
-
process.exitCode = bashRunner.runRaw(
|
|
20942
|
+
process.exitCode = bashRunner.runRaw(
|
|
20943
|
+
command,
|
|
20944
|
+
parseTimeout(opts.timeout, bashRunner.DEFAULT_TIMEOUT_SECONDS),
|
|
20945
|
+
opts.native,
|
|
20946
|
+
opts.shell
|
|
20947
|
+
);
|
|
21026
20948
|
return;
|
|
21027
20949
|
}
|
|
21028
20950
|
const maxTokens = opts.maxTokens !== void 0 ? requireNonNegativeInt("--max-tokens", opts.maxTokens) : 0;
|
|
@@ -21030,9 +20952,11 @@ async function cmdCompress(commandArgs, opts = {}) {
|
|
|
21030
20952
|
filterName: opts.filter,
|
|
21031
20953
|
timeout: parseTimeout(opts.timeout, bashRunner.DEFAULT_TIMEOUT_SECONDS),
|
|
21032
20954
|
maxTokens,
|
|
20955
|
+
...opts.capHintB64 !== void 0 ? { capHint: Buffer.from(opts.capHintB64, "base64").toString("utf8") } : {},
|
|
21033
20956
|
...opts.profile !== void 0 ? { compressionProfile: opts.profile } : {},
|
|
21034
20957
|
...opts.quietSuccess === true ? { quietSuccess: true } : {},
|
|
21035
|
-
...opts.native === true ? { nativeShell: true } : {}
|
|
20958
|
+
...opts.native === true ? { nativeShell: true } : {},
|
|
20959
|
+
...opts.shell !== void 0 ? { shellType: opts.shell } : {}
|
|
21036
20960
|
});
|
|
21037
20961
|
} catch (e) {
|
|
21038
20962
|
err(`token-goat: ${displaySafeText(extractErrorMessage(e))}`);
|
|
@@ -21196,7 +21120,7 @@ function buildProgram() {
|
|
|
21196
21120
|
)
|
|
21197
21121
|
);
|
|
21198
21122
|
});
|
|
21199
|
-
program2.command("semantic [query]").description("semantic search (falls back to full-text search)").option("-l, --limit <n>", "max results").option("-j, --json", "output as JSON").option("--grep <pattern>", "filter to hits whose file path matches this regex (literal substring if it is not valid regex); matched against the path as rendered").option("--exclude-tests", "hide hits whose file is a test file (opt-in; default output is unchanged)").option("--preflight", "run semantic embedding preflight check and exit").option("--warm", "warm up the embedding model session in memory").action(guard(cmdSemantic));
|
|
21123
|
+
program2.command("semantic [query] [more...]").description("semantic search (falls back to full-text search); several queries run in one call, one headed block per query").option("-l, --limit <n>", "max results").option("-j, --json", "output as JSON").option("--grep <pattern>", "filter to hits whose file path matches this regex (literal substring if it is not valid regex); matched against the path as rendered").option("--exclude-tests", "hide hits whose file is a test file (opt-in; default output is unchanged)").option("--preflight", "run semantic embedding preflight check and exit").option("--warm", "warm up the embedding model session in memory").action(guard(cmdSemantic));
|
|
21200
21124
|
const registerSymbolListing = (name, description, run2) => {
|
|
21201
21125
|
program2.command(`${name} <file> [more...]`).description(description).option("-j, --json", "output as JSON").option("--min-lines <n>", "only show symbols at least N lines long").option("--grep <pattern>", "only show symbols whose name matches this regex (literal substring if it is not valid regex)").option("--force-refresh", "reparse file from disk before querying (ignore stale index)").option("--stats", "add per-symbol reference count and doc-coverage flag").action(
|
|
21202
21126
|
(file, more, opts) => runExitText(
|
|
@@ -21252,7 +21176,7 @@ function buildProgram() {
|
|
|
21252
21176
|
program2.command("bench").description("replay a corpus of captured command output through the compressors; prints the byte savings ratio and a fidelity check, and exits 1 when a must-keep line was dropped").option("--corpus <dir>", "corpus directory (default: tests/fixtures/bench, relative to the working directory)").option("--tsv <path>", "append one result row, keyed by the current commit, creating the file and its header if absent").option("--validate", "score the corpus with control filters instead: proves the ratio has a floor and the fidelity guard can actually fail").option("-j, --json", "output as JSON").action(
|
|
21253
21177
|
(opts) => runExitText(
|
|
21254
21178
|
() => runBenchCommand({
|
|
21255
|
-
corpus: opts.corpus ??
|
|
21179
|
+
corpus: opts.corpus ?? path40.join("tests", "fixtures", "bench"),
|
|
21256
21180
|
...opts.tsv !== void 0 ? { tsv: opts.tsv } : {},
|
|
21257
21181
|
...opts.validate === true ? { validate: true } : {},
|
|
21258
21182
|
...opts.json === true ? { json: true } : {}
|
|
@@ -21283,10 +21207,10 @@ function buildProgram() {
|
|
|
21283
21207
|
registerAnalysisCommands(program2, guard);
|
|
21284
21208
|
registerSessionCommands(program2, guard);
|
|
21285
21209
|
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").option("--fresh", "skip the on-disk cache and force a live fetch").action(guard(cmdGdriveSections));
|
|
21286
|
-
program2.command("compress [command...]").alias("bash").alias("run").description("run a shell command (under a POSIX shell / bash) and emit a compressed view of its output").allowUnknownOption(true).option("-c, --cmd <command>", "the shell command to run, as one string (use / for paths across platforms)").option("--cmd-b64 <payload>", "the shell command as a base64-encoded string (preserves quotes, backslashes, and symbols across platforms)").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)").option("-q, --quiet-success", "on exit code 0, emit only [tg: ok] summary and store full output for recall via bash-output").option("--native", "use native platform shell (e.g. cmd.exe on Windows) instead of bash, preserving Windows path backslashes").action(cmdCompress);
|
|
21210
|
+
program2.command("compress [command...]").alias("bash").alias("run").description("run a shell command (under a POSIX shell / bash) and emit a compressed view of its output").allowUnknownOption(true).option("-c, --cmd <command>", "the shell command to run, as one string (use / for paths across platforms)").option("--cmd-b64 <payload>", "the shell command as a base64-encoded string (preserves quotes, backslashes, and symbols across platforms)").option("--shell <type>", "shell interpreter to run under: bash | pwsh | powershell | native").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)").option("--cap-hint-b64 <payload>", "base64 text printed after the output when --max-tokens cut it (the Bash hook sets it to the narrower read command)").option("-q, --quiet-success", "on exit code 0, emit only [tg: ok] summary and store full output for recall via bash-output").option("--native", "use native platform shell (e.g. cmd.exe on Windows) instead of bash, preserving Windows path backslashes").action(cmdCompress);
|
|
21287
21211
|
program2.command("upgrade").alias("update").description("check for updates and upgrade token-goat to the latest version").option("--check", "check whether an update is available without installing").option("-j, --json", "emit version check status as JSON").action(
|
|
21288
21212
|
(opts) => guard(async () => {
|
|
21289
|
-
const { cmdUpgrade } = await import("./token-goat-chunk-
|
|
21213
|
+
const { cmdUpgrade } = await import("./token-goat-chunk-4JJBFT7V.mjs");
|
|
21290
21214
|
await cmdUpgrade(opts, () => cmdInstall({}));
|
|
21291
21215
|
})()
|
|
21292
21216
|
);
|
|
@@ -21303,8 +21227,19 @@ function buildProgram() {
|
|
|
21303
21227
|
return;
|
|
21304
21228
|
}
|
|
21305
21229
|
if (cmd) {
|
|
21230
|
+
const known = program2.commands.some((sub) => sub.name() === cmd || sub.aliases().includes(cmd));
|
|
21231
|
+
if (!known) {
|
|
21232
|
+
err(`token-goat: unknown command '${displaySafeText(cmd)}'. Run 'token-goat commands --grep <pattern>' to search the list.`);
|
|
21233
|
+
process.exitCode = 1;
|
|
21234
|
+
return;
|
|
21235
|
+
}
|
|
21306
21236
|
const argv = [process.argv[0] ?? "node", process.argv[1] ?? "token-goat", cmd, "--help"];
|
|
21307
|
-
|
|
21237
|
+
try {
|
|
21238
|
+
program2.parse(argv);
|
|
21239
|
+
} catch (e) {
|
|
21240
|
+
const code = e.code;
|
|
21241
|
+
if (code !== "commander.help" && code !== "commander.helpDisplayed") throw e;
|
|
21242
|
+
}
|
|
21308
21243
|
} else {
|
|
21309
21244
|
out(generateCompactHelp());
|
|
21310
21245
|
}
|