token-goat 2.9.18 → 2.9.20
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 +5 -1
- package/dist/token-goat-chunk-2CLWWRFR.mjs +26 -0
- package/dist/{token-goat-chunk-LTYWLKAG.mjs → token-goat-chunk-2Q3N5KUQ.mjs} +1283 -1012
- package/dist/{token-goat-chunk-6LGVCCMY.mjs → token-goat-chunk-3OGZOFLS.mjs} +26 -16
- package/dist/{token-goat-chunk-QML7ITHJ.mjs → token-goat-chunk-3VTJC7KU.mjs} +693 -438
- package/dist/{token-goat-chunk-QIDLJGXZ.mjs → token-goat-chunk-6LJNM4ZZ.mjs} +29 -5
- package/dist/{token-goat-chunk-CA6V36KW.mjs → token-goat-chunk-74ADIZZX.mjs} +68 -50
- package/dist/{token-goat-chunk-52IMXJ2L.mjs → token-goat-chunk-ASTBLE2R.mjs} +4 -4
- package/dist/token-goat-chunk-AU2K2QHR.mjs +20 -0
- package/dist/token-goat-chunk-BQIC3AVL.mjs +292 -0
- package/dist/token-goat-chunk-CBXLE54Q.mjs +30 -0
- package/dist/{token-goat-chunk-LMFO66YD.mjs → token-goat-chunk-DA43OE7L.mjs} +1 -1
- package/dist/{token-goat-chunk-ARNRFR6M.mjs → token-goat-chunk-DNAF26L4.mjs} +1 -1
- package/dist/{token-goat-chunk-BFEWOMA3.mjs → token-goat-chunk-DPHJU3P7.mjs} +1186 -4573
- package/dist/{token-goat-chunk-OWSJJY5R.mjs → token-goat-chunk-DW4VKU7D.mjs} +5 -5
- package/dist/token-goat-chunk-DYUBZZNP.mjs +198 -0
- package/dist/{token-goat-chunk-W3E65QOW.mjs → token-goat-chunk-ERGHDBC6.mjs} +310 -47
- package/dist/token-goat-chunk-EUZKG7ZO.mjs +304 -0
- package/dist/{token-goat-chunk-5MMJAJF3.mjs → token-goat-chunk-FWYZVS3E.mjs} +324 -31
- package/dist/token-goat-chunk-G6SYQQO7.mjs +41 -0
- package/dist/{token-goat-chunk-YQZE5NS6.mjs → token-goat-chunk-GIPMOGOI.mjs} +6 -6
- package/dist/{token-goat-chunk-BWCRC23L.mjs → token-goat-chunk-H4VC5TR6.mjs} +29 -20
- package/dist/{token-goat-chunk-V3ZWBEHM.mjs → token-goat-chunk-I5PQRHFE.mjs} +103 -24
- package/dist/token-goat-chunk-ITWYDOKP.mjs +341 -0
- package/dist/{token-goat-chunk-I67CPTDD.mjs → token-goat-chunk-K3ZNBN4U.mjs} +19 -14
- package/dist/{token-goat-chunk-HPOFR6QX.mjs → token-goat-chunk-K5XPIUVB.mjs} +222 -61
- package/dist/token-goat-chunk-KT75DZK4.mjs +1989 -0
- package/dist/{token-goat-chunk-H3FONFBO.mjs → token-goat-chunk-MNJWG2ZO.mjs} +3 -3
- package/dist/{token-goat-chunk-GRI6HWX3.mjs → token-goat-chunk-MUJV7BR3.mjs} +1 -1
- package/dist/{token-goat-chunk-ERTXEKB6.mjs → token-goat-chunk-NMTKNYGF.mjs} +2 -0
- package/dist/{token-goat-chunk-LA3O4JGD.mjs → token-goat-chunk-ODF7H7WS.mjs} +3 -3
- package/dist/{token-goat-chunk-K4DG6EEF.mjs → token-goat-chunk-ONMU7BON.mjs} +7 -8
- package/dist/{token-goat-chunk-4EXFN2AW.mjs → token-goat-chunk-OZRSREKR.mjs} +2 -2
- package/dist/{token-goat-chunk-EPXNOKIV.mjs → token-goat-chunk-P4XBHZXU.mjs} +2 -2
- package/dist/{token-goat-chunk-CTOYJ232.mjs → token-goat-chunk-PAVWB4L4.mjs} +173 -1840
- package/dist/{token-goat-chunk-UENEL6KX.mjs → token-goat-chunk-PTW22MRC.mjs} +2 -2
- package/dist/token-goat-chunk-SL454EN5.mjs +1816 -0
- package/dist/token-goat-chunk-SP5QR2HN.mjs +1379 -0
- package/dist/{token-goat-chunk-7VLWNQDQ.mjs → token-goat-chunk-T46UKRFM.mjs} +1 -1
- package/dist/{token-goat-chunk-L7VCX33I.mjs → token-goat-chunk-T63VHOL3.mjs} +40 -10
- package/dist/token-goat-chunk-VSJGPEBB.mjs +248 -0
- package/dist/{token-goat-chunk-HIZXQVNU.mjs → token-goat-chunk-VYXGHGUY.mjs} +4 -4
- package/dist/token-goat-chunk-W6QYCWAT.mjs +128 -0
- package/dist/{token-goat-chunk-WFX2V3OF.mjs → token-goat-chunk-Z4ALQADF.mjs} +579 -422
- package/dist/token-goat-chunk-ZHFM4DHJ.mjs +324 -0
- package/dist/token-goat-hook.mjs +18 -12
- package/dist/token-goat.core.mjs +29 -20
- package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
- package/docs/cli.md +15 -13
- package/docs/install.md +1 -1
- package/docs/security.md +2 -2
- package/package.json +3 -2
- package/dist/token-goat-chunk-2KTZ6J7T.mjs +0 -173
- package/dist/token-goat-chunk-34OUJ2IE.mjs +0 -35
- package/dist/token-goat-chunk-RHHFEXKF.mjs +0 -93
|
@@ -1,34 +1,39 @@
|
|
|
1
1
|
import { createRequire as __cjsRequire } from 'node:module';
|
|
2
2
|
const require = __cjsRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
|
-
|
|
4
|
+
enqueueDirtyPathsSafe,
|
|
5
|
+
fenceUntrusted,
|
|
5
6
|
getToolName,
|
|
6
|
-
getTrackedFiles
|
|
7
|
-
|
|
7
|
+
getTrackedFiles,
|
|
8
|
+
scanAndRecord
|
|
9
|
+
} from "./token-goat-chunk-DPHJU3P7.mjs";
|
|
8
10
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
RECALL_DEFAULT_LIMIT,
|
|
12
|
+
indexRecallEntry,
|
|
13
|
+
listRecentRecall,
|
|
14
|
+
searchRecall
|
|
15
|
+
} from "./token-goat-chunk-SL454EN5.mjs";
|
|
11
16
|
import {
|
|
12
17
|
isBlobStale,
|
|
13
18
|
loadBlob,
|
|
14
19
|
redactSecrets,
|
|
15
20
|
storeBlob
|
|
16
|
-
} from "./token-goat-chunk-
|
|
21
|
+
} from "./token-goat-chunk-K5XPIUVB.mjs";
|
|
17
22
|
import {
|
|
18
|
-
|
|
19
|
-
} from "./token-goat-chunk-
|
|
23
|
+
parserFingerprintForLanguage
|
|
24
|
+
} from "./token-goat-chunk-ERGHDBC6.mjs";
|
|
20
25
|
import {
|
|
21
26
|
getProjectFileEntries,
|
|
22
27
|
projectScopeClause
|
|
23
|
-
} from "./token-goat-chunk-
|
|
28
|
+
} from "./token-goat-chunk-K3ZNBN4U.mjs";
|
|
24
29
|
import {
|
|
25
30
|
getDb
|
|
26
|
-
} from "./token-goat-chunk-
|
|
31
|
+
} from "./token-goat-chunk-T63VHOL3.mjs";
|
|
27
32
|
import {
|
|
28
33
|
fingerprintFile,
|
|
29
34
|
getDisplayRoot,
|
|
30
35
|
shortFingerprint
|
|
31
|
-
} from "./token-goat-chunk-
|
|
36
|
+
} from "./token-goat-chunk-74ADIZZX.mjs";
|
|
32
37
|
import {
|
|
33
38
|
registerReset
|
|
34
39
|
} from "./token-goat-chunk-EEIDFMEM.mjs";
|
|
@@ -37,14 +42,18 @@ import {
|
|
|
37
42
|
countNoun,
|
|
38
43
|
extractErrorMessage,
|
|
39
44
|
foldPath,
|
|
40
|
-
globalDbPath
|
|
41
|
-
|
|
45
|
+
globalDbPath,
|
|
46
|
+
pad
|
|
47
|
+
} from "./token-goat-chunk-6LJNM4ZZ.mjs";
|
|
42
48
|
import {
|
|
49
|
+
UNTRUSTED_TOOL_TAG,
|
|
50
|
+
UNTRUSTED_WEB_TAG,
|
|
43
51
|
displaySafeJson,
|
|
52
|
+
fenceUntrustedContent,
|
|
44
53
|
normalizePath,
|
|
45
54
|
resolveIndexPath,
|
|
46
55
|
toDisplayPath
|
|
47
|
-
} from "./token-goat-chunk-
|
|
56
|
+
} from "./token-goat-chunk-NMTKNYGF.mjs";
|
|
48
57
|
import {
|
|
49
58
|
compileGuardedRegex
|
|
50
59
|
} from "./token-goat-chunk-GMOUBOX4.mjs";
|
|
@@ -525,7 +534,7 @@ async function describeTarget(target, table, opts) {
|
|
|
525
534
|
const absPath = resolve(process.cwd(), target);
|
|
526
535
|
if (existsSync(absPath)) {
|
|
527
536
|
try {
|
|
528
|
-
const { isSqliteFile, getSqliteSchema, formatSqliteSchema } = await import("./token-goat-chunk-
|
|
537
|
+
const { isSqliteFile, getSqliteSchema, formatSqliteSchema } = await import("./token-goat-chunk-OZRSREKR.mjs");
|
|
529
538
|
if (isSqliteFile(absPath)) {
|
|
530
539
|
const schema = getSqliteSchema(absPath);
|
|
531
540
|
if (table) {
|
|
@@ -752,6 +761,10 @@ function checkSymbolBodySize(dbPath) {
|
|
|
752
761
|
}
|
|
753
762
|
}
|
|
754
763
|
|
|
764
|
+
// src/mcp_tool_pattern.ts
|
|
765
|
+
init_define_import_meta_env();
|
|
766
|
+
var MCP_TOOL_PATTERN = "^mcp__";
|
|
767
|
+
|
|
755
768
|
// src/reconcile.ts
|
|
756
769
|
init_define_import_meta_env();
|
|
757
770
|
import * as fs2 from "node:fs";
|
|
@@ -821,7 +834,7 @@ function runReconcile(opts = {}) {
|
|
|
821
834
|
lines.push(`${countNoun(result.embedStale, "file")} of the above ${result.embedStale === 1 ? "was" : "were"} unchanged on disk but held out-of-date embeddings (${reembedVerb}).`);
|
|
822
835
|
}
|
|
823
836
|
if (result.trackedUnavailable) {
|
|
824
|
-
lines.push("This project has an index but git listed no files in it, so nothing
|
|
837
|
+
lines.push("This project has an index but git listed no files in it, so nothing on disk was compared against it and changed or new files could not be found. Files gone from disk were still detected. Run token-goat inside the repository, or reindex with --walk if this directory is deliberately not under git.");
|
|
825
838
|
}
|
|
826
839
|
if (result.budgetExhausted) {
|
|
827
840
|
lines.push(`Stopped at the ${result.elapsedMs}ms budget with ${countNoun(result.unscanned, "file")} unchecked, so there may be more drift; deletions were not computed at all, because an unchecked file is indistinguishable from a deleted one. Raise --budget-ms for a complete sweep.`);
|
|
@@ -877,7 +890,7 @@ function reconcileProject(opts = {}) {
|
|
|
877
890
|
added.push(file);
|
|
878
891
|
continue;
|
|
879
892
|
}
|
|
880
|
-
if (entry.parserSha !==
|
|
893
|
+
if (entry.parserSha !== parserFingerprintForLanguage(entry.language)) {
|
|
881
894
|
changed.push(file);
|
|
882
895
|
parserStale++;
|
|
883
896
|
continue;
|
|
@@ -908,7 +921,7 @@ function reconcileProject(opts = {}) {
|
|
|
908
921
|
}
|
|
909
922
|
const trackedUnavailable = tracked.length === 0 && indexed.size > 0;
|
|
910
923
|
const removed = [];
|
|
911
|
-
if (!budgetExhausted
|
|
924
|
+
if (!budgetExhausted) {
|
|
912
925
|
for (const [folded, entry] of indexed) {
|
|
913
926
|
if (seenOnDisk.has(folded)) continue;
|
|
914
927
|
if (Date.now() - startedAt > budgetMs) {
|
|
@@ -918,17 +931,17 @@ function reconcileProject(opts = {}) {
|
|
|
918
931
|
}
|
|
919
932
|
try {
|
|
920
933
|
fs2.statSync(entry.filePath);
|
|
921
|
-
} catch {
|
|
922
|
-
|
|
934
|
+
} catch (err) {
|
|
935
|
+
const code = err?.code;
|
|
936
|
+
if (code === "ENOENT" || code === "ENOTDIR") removed.push(entry.filePath);
|
|
923
937
|
}
|
|
924
938
|
}
|
|
925
939
|
}
|
|
926
940
|
let enqueued = 0;
|
|
927
941
|
if (opts.dryRun !== true) {
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
}
|
|
942
|
+
const toEnqueue = [...changed, ...added, ...removed].map((p) => resolveIndexPath(p, cwd));
|
|
943
|
+
enqueueDirtyPathsSafe(toEnqueue, { alreadyResolved: true });
|
|
944
|
+
enqueued = toEnqueue.length;
|
|
932
945
|
if (budgetExhausted) {
|
|
933
946
|
if (lastScanned !== null) writeReconcileCursor(dbPath, projectRoot, lastScanned);
|
|
934
947
|
} else if (tracked.length > 0) {
|
|
@@ -951,8 +964,72 @@ function reconcileProject(opts = {}) {
|
|
|
951
964
|
};
|
|
952
965
|
}
|
|
953
966
|
|
|
967
|
+
// src/cli_recall.ts
|
|
968
|
+
init_define_import_meta_env();
|
|
969
|
+
var RECALL_COMMAND = {
|
|
970
|
+
bash: "bash-output",
|
|
971
|
+
web: "web-output",
|
|
972
|
+
mcp: "mcp-output"
|
|
973
|
+
};
|
|
974
|
+
function fenceTagForCacheType(cacheType) {
|
|
975
|
+
return cacheType === "web" ? UNTRUSTED_WEB_TAG : UNTRUSTED_TOOL_TAG;
|
|
976
|
+
}
|
|
977
|
+
function fenceRecallListing(text, hits) {
|
|
978
|
+
const tags = new Set(hits.map((hit) => fenceTagForCacheType(hit.cacheType)));
|
|
979
|
+
const tag = tags.size === 1 ? [...tags][0] ?? UNTRUSTED_TOOL_TAG : UNTRUSTED_TOOL_TAG;
|
|
980
|
+
return fenceUntrusted(text, tag);
|
|
981
|
+
}
|
|
982
|
+
function fenceSnippetIfMatched(hit) {
|
|
983
|
+
const matches = scanAndRecord(hit.snippet);
|
|
984
|
+
if (matches.length === 0) return hit.snippet;
|
|
985
|
+
return fenceUntrustedContent(hit.snippet, matches, fenceTagForCacheType(hit.cacheType));
|
|
986
|
+
}
|
|
987
|
+
function printHits(query, hits) {
|
|
988
|
+
const w = (text) => {
|
|
989
|
+
process.stdout.write(text);
|
|
990
|
+
};
|
|
991
|
+
if (hits.length === 0) {
|
|
992
|
+
w(query === void 0 ? "No cache entries yet.\n" : `No cache entries match: ${query}
|
|
993
|
+
`);
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
const body = hits.map((hit) => {
|
|
997
|
+
const label = hit.label.length > 80 ? hit.label.slice(0, 77) + "..." : hit.label;
|
|
998
|
+
const pointer = hit.blobPresent ? ` (token-goat ${RECALL_COMMAND[hit.cacheType]} ${hit.id})` : " (blob expired -- content below is all that remains)";
|
|
999
|
+
return `[${pad(hit.cacheType, 4)}] ${hit.id}
|
|
1000
|
+
${pointer}
|
|
1001
|
+
${label}
|
|
1002
|
+
${hit.snippet}
|
|
1003
|
+
`;
|
|
1004
|
+
}).join("\n");
|
|
1005
|
+
w(`${fenceRecallListing(body, hits)}
|
|
1006
|
+
`);
|
|
1007
|
+
}
|
|
1008
|
+
function runRecallCommand(query, opts = {}) {
|
|
1009
|
+
const browse = query === void 0 || query.trim() === "";
|
|
1010
|
+
const scope = {
|
|
1011
|
+
...opts.type !== void 0 ? { type: opts.type } : {},
|
|
1012
|
+
...opts.limit !== void 0 ? { limit: opts.limit } : {}
|
|
1013
|
+
};
|
|
1014
|
+
const effectiveLimit = opts.limit ?? RECALL_DEFAULT_LIMIT;
|
|
1015
|
+
const fetched = browse ? listRecentRecall({ ...scope, limit: effectiveLimit + 1 }) : searchRecall(query, { ...scope, limit: effectiveLimit + 1 });
|
|
1016
|
+
const hits = fetched.slice(0, effectiveLimit);
|
|
1017
|
+
if (fetched.length > hits.length) {
|
|
1018
|
+
process.stderr.write(`Showing ${hits.length} entries; more are available (raise --limit to see them).
|
|
1019
|
+
`);
|
|
1020
|
+
}
|
|
1021
|
+
if (opts.json === true) {
|
|
1022
|
+
const fenced = hits.map((hit) => ({ ...hit, snippet: fenceSnippetIfMatched(hit) }));
|
|
1023
|
+
process.stdout.write(`${displaySafeJson(fenced, 0)}
|
|
1024
|
+
`);
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
printHits(browse ? void 0 : query, hits);
|
|
1028
|
+
}
|
|
1029
|
+
|
|
954
1030
|
export {
|
|
955
1031
|
checkSymbolBodySize,
|
|
1032
|
+
MCP_TOOL_PATTERN,
|
|
956
1033
|
WEB_OUTPUT_SUBDIR,
|
|
957
1034
|
storeWebOutput,
|
|
958
1035
|
getWebOutput,
|
|
@@ -962,6 +1039,8 @@ export {
|
|
|
962
1039
|
runReconcile,
|
|
963
1040
|
isReconcileClean,
|
|
964
1041
|
reconcileProject,
|
|
1042
|
+
RECALL_COMMAND,
|
|
1043
|
+
runRecallCommand,
|
|
965
1044
|
MAX_STDIN_BYTES,
|
|
966
1045
|
readStdinJson,
|
|
967
1046
|
diagnoseSqlFailure,
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { createRequire as __cjsRequire } from 'node:module';
|
|
2
|
+
const require = __cjsRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
ToolFilter,
|
|
5
|
+
compressedTokensSaved,
|
|
6
|
+
deliverCompressed,
|
|
7
|
+
dispatchArgv,
|
|
8
|
+
filterByName,
|
|
9
|
+
selectFilter
|
|
10
|
+
} from "./token-goat-chunk-PAVWB4L4.mjs";
|
|
11
|
+
import {
|
|
12
|
+
capTokens,
|
|
13
|
+
shlexSplit,
|
|
14
|
+
storeBashOutputSync
|
|
15
|
+
} from "./token-goat-chunk-SL454EN5.mjs";
|
|
16
|
+
import {
|
|
17
|
+
recordStat
|
|
18
|
+
} from "./token-goat-chunk-K5XPIUVB.mjs";
|
|
19
|
+
import {
|
|
20
|
+
detectHarness,
|
|
21
|
+
loadConfig
|
|
22
|
+
} from "./token-goat-chunk-74ADIZZX.mjs";
|
|
23
|
+
import {
|
|
24
|
+
init_define_import_meta_env
|
|
25
|
+
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
26
|
+
|
|
27
|
+
// src/bash_runner.ts
|
|
28
|
+
init_define_import_meta_env();
|
|
29
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
30
|
+
import * as os from "node:os";
|
|
31
|
+
|
|
32
|
+
// src/delivery_cap.ts
|
|
33
|
+
init_define_import_meta_env();
|
|
34
|
+
var CLAUDE_CODE_BASH_OUTPUT_CAP_BYTES = 2e4;
|
|
35
|
+
var CLAUDE_CODE_PERSISTED_PREVIEW_BYTES = 2048;
|
|
36
|
+
function bashOutputCapBytes(harness = detectHarness()) {
|
|
37
|
+
return harness === "claudecode" ? CLAUDE_CODE_BASH_OUTPUT_CAP_BYTES : null;
|
|
38
|
+
}
|
|
39
|
+
function clipToDeliveryCap(text, reserveBytes) {
|
|
40
|
+
const cap = bashOutputCapBytes();
|
|
41
|
+
const room = cap === null ? null : cap - reserveBytes;
|
|
42
|
+
if (room === null || room <= 0 || Buffer.byteLength(text, "utf-8") <= room) return { text, clipped: false };
|
|
43
|
+
const sliced = Buffer.from(text, "utf-8").subarray(0, room).toString("utf-8");
|
|
44
|
+
const lastNewline = sliced.lastIndexOf("\n");
|
|
45
|
+
return { text: lastNewline > 0 ? sliced.slice(0, lastNewline) : sliced, clipped: true };
|
|
46
|
+
}
|
|
47
|
+
function deliveredOutputBytes(originalBytes, harness) {
|
|
48
|
+
const cap = bashOutputCapBytes(harness);
|
|
49
|
+
if (cap === null) return Math.max(0, originalBytes);
|
|
50
|
+
if (originalBytes <= cap) return Math.max(0, originalBytes);
|
|
51
|
+
return CLAUDE_CODE_PERSISTED_PREVIEW_BYTES;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/shell.ts
|
|
55
|
+
init_define_import_meta_env();
|
|
56
|
+
import * as fs from "node:fs";
|
|
57
|
+
import * as path from "node:path";
|
|
58
|
+
var WSL_LAUNCHER_SEGMENTS = /* @__PURE__ */ new Set(["system32", "syswow64", "windowsapps"]);
|
|
59
|
+
function isExecutable(p) {
|
|
60
|
+
try {
|
|
61
|
+
return fs.statSync(p).isFile();
|
|
62
|
+
} catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function isWslLauncherDir(dir) {
|
|
67
|
+
return dir.toLowerCase().split(/[\\/]+/).some((seg) => WSL_LAUNCHER_SEGMENTS.has(seg));
|
|
68
|
+
}
|
|
69
|
+
function locateBashOnPath(pathValue, isExe = isExecutable) {
|
|
70
|
+
for (const dir of (pathValue ?? "").split(path.delimiter)) {
|
|
71
|
+
if (!dir || isWslLauncherDir(dir)) continue;
|
|
72
|
+
const cand = path.join(dir, "bash.exe");
|
|
73
|
+
if (isExe(cand)) return cand;
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
function knownGitBashPaths() {
|
|
78
|
+
const localPrograms = process.env["LOCALAPPDATA"] ? path.join(process.env["LOCALAPPDATA"], "Programs") : void 0;
|
|
79
|
+
const bases = [
|
|
80
|
+
process.env["ProgramFiles"],
|
|
81
|
+
process.env["ProgramFiles(x86)"],
|
|
82
|
+
process.env["ProgramW6432"],
|
|
83
|
+
localPrograms
|
|
84
|
+
];
|
|
85
|
+
const out = [];
|
|
86
|
+
for (const base of bases) {
|
|
87
|
+
if (!base) continue;
|
|
88
|
+
out.push(path.join(base, "Git", "bin", "bash.exe"));
|
|
89
|
+
out.push(path.join(base, "Git", "usr", "bin", "bash.exe"));
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
function resolveWindowsBash() {
|
|
94
|
+
if (process.platform !== "win32") return null;
|
|
95
|
+
const override = process.env["TOKEN_GOAT_BASH"];
|
|
96
|
+
if (override && isExecutable(override)) return override;
|
|
97
|
+
const onPath = locateBashOnPath(process.env["PATH"]);
|
|
98
|
+
if (onPath) return onPath;
|
|
99
|
+
for (const cand of knownGitBashPaths()) {
|
|
100
|
+
if (isExecutable(cand)) return cand;
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
function wrappedShell() {
|
|
105
|
+
if (process.platform !== "win32") return true;
|
|
106
|
+
return resolveWindowsBash() ?? true;
|
|
107
|
+
}
|
|
108
|
+
function canRunWrappedShell() {
|
|
109
|
+
return process.platform !== "win32" || resolveWindowsBash() !== null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/bash_runner.ts
|
|
113
|
+
var IdentityFilter = class extends ToolFilter {
|
|
114
|
+
name = "passthrough";
|
|
115
|
+
};
|
|
116
|
+
var DEFAULT_TIMEOUT_SECONDS = 600;
|
|
117
|
+
var MAX_CAPTURE_BYTES = 32 * 1024 * 1024;
|
|
118
|
+
var MIN_RECORD_STAT_BYTES = 32;
|
|
119
|
+
var DEFAULT_HEARTBEAT_INTERVAL_MS = 15e3;
|
|
120
|
+
var CaptureSink = class {
|
|
121
|
+
constructor(cap) {
|
|
122
|
+
this.cap = cap;
|
|
123
|
+
}
|
|
124
|
+
cap;
|
|
125
|
+
chunks = [];
|
|
126
|
+
bytes = 0;
|
|
127
|
+
overflowed = false;
|
|
128
|
+
push(chunk) {
|
|
129
|
+
if (this.overflowed) return;
|
|
130
|
+
this.bytes += chunk.length;
|
|
131
|
+
if (this.bytes > this.cap) {
|
|
132
|
+
this.overflowed = true;
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
this.chunks.push(chunk);
|
|
136
|
+
}
|
|
137
|
+
text() {
|
|
138
|
+
return decode(Buffer.concat(this.chunks));
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
function scheduleHeartbeat(startTime, intervalMs, write) {
|
|
142
|
+
let interval = intervalMs;
|
|
143
|
+
let timer;
|
|
144
|
+
const arm = () => {
|
|
145
|
+
timer = setTimeout(() => {
|
|
146
|
+
write(Math.round((Date.now() - startTime) / 1e3));
|
|
147
|
+
interval *= 2;
|
|
148
|
+
arm();
|
|
149
|
+
}, interval);
|
|
150
|
+
timer.unref();
|
|
151
|
+
};
|
|
152
|
+
arm();
|
|
153
|
+
return {
|
|
154
|
+
onOutput: () => {
|
|
155
|
+
interval = intervalMs;
|
|
156
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
157
|
+
arm();
|
|
158
|
+
},
|
|
159
|
+
stop: () => {
|
|
160
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function resolveFilter(command, filterName, cwd) {
|
|
165
|
+
const effectiveCwd = cwd ?? process.cwd();
|
|
166
|
+
let split;
|
|
167
|
+
try {
|
|
168
|
+
split = shlexSplit(command);
|
|
169
|
+
} catch {
|
|
170
|
+
split = null;
|
|
171
|
+
}
|
|
172
|
+
const argv = split === null ? [command] : dispatchArgv(split, effectiveCwd).argv;
|
|
173
|
+
if (filterName) {
|
|
174
|
+
const named = filterByName(filterName);
|
|
175
|
+
if (named !== null) return { filter: named, argv };
|
|
176
|
+
}
|
|
177
|
+
if (split === null) return { filter: null, argv };
|
|
178
|
+
return { filter: selectFilter(split, effectiveCwd), argv };
|
|
179
|
+
}
|
|
180
|
+
function baseSpawnOptions(timeout, cwd) {
|
|
181
|
+
return { timeout: timeout * 1e3, cwd };
|
|
182
|
+
}
|
|
183
|
+
function spawnTarget(command, nativeShell) {
|
|
184
|
+
const shell = nativeShell ? true : wrappedShell();
|
|
185
|
+
if (typeof shell === "string") return { file: shell, args: ["-c", 'eval "$TG_CMD"'], shell: false, cmdEnv: { TG_CMD: command } };
|
|
186
|
+
return { file: command, args: [], shell };
|
|
187
|
+
}
|
|
188
|
+
function mergeSpawnEnv(env, cmdEnv) {
|
|
189
|
+
return cmdEnv ? { ...env ?? process.env, ...cmdEnv } : env;
|
|
190
|
+
}
|
|
191
|
+
function signalExitCode(signal) {
|
|
192
|
+
const num = os.constants.signals[signal];
|
|
193
|
+
return 128 + (num ?? 0);
|
|
194
|
+
}
|
|
195
|
+
function resolveProfile(explicit) {
|
|
196
|
+
if (explicit) return explicit;
|
|
197
|
+
try {
|
|
198
|
+
const p = loadConfig().compression.profile;
|
|
199
|
+
return p && p !== "auto" ? p : "balanced";
|
|
200
|
+
} catch {
|
|
201
|
+
return "balanced";
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function resolveCompressLimits() {
|
|
205
|
+
try {
|
|
206
|
+
const bc = loadConfig().bash_compress;
|
|
207
|
+
return { maxLines: bc.max_lines, maxBytes: bc.max_bytes };
|
|
208
|
+
} catch {
|
|
209
|
+
return { maxLines: 1e3, maxBytes: 64 * 1024 };
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async function run(command, opts = {}) {
|
|
213
|
+
const timeout = opts.timeout ?? DEFAULT_TIMEOUT_SECONDS;
|
|
214
|
+
const { filter, argv } = resolveFilter(command, opts.filterName, opts.cwd);
|
|
215
|
+
if (filter === null) {
|
|
216
|
+
if ((opts.maxTokens ?? 0) > 0 || opts.quietSuccess) {
|
|
217
|
+
return wrapAndCompress(command, argv, new IdentityFilter(), timeout, resolveProfile(opts.compressionProfile), opts);
|
|
218
|
+
}
|
|
219
|
+
return passthrough(command, timeout, opts.cwd, opts.env, opts.nativeShell);
|
|
220
|
+
}
|
|
221
|
+
return wrapAndCompress(command, argv, filter, timeout, resolveProfile(opts.compressionProfile), opts);
|
|
222
|
+
}
|
|
223
|
+
function runRaw(command, timeout = DEFAULT_TIMEOUT_SECONDS) {
|
|
224
|
+
return passthrough(command, timeout, void 0, void 0);
|
|
225
|
+
}
|
|
226
|
+
function passthrough(command, timeout, cwd, env, nativeShell) {
|
|
227
|
+
const { file, args, shell, cmdEnv } = spawnTarget(command, nativeShell);
|
|
228
|
+
const result = spawnSync(file, args, {
|
|
229
|
+
...baseSpawnOptions(timeout, cwd),
|
|
230
|
+
shell,
|
|
231
|
+
env: mergeSpawnEnv(env, cmdEnv),
|
|
232
|
+
stdio: "inherit"
|
|
233
|
+
});
|
|
234
|
+
if (isTimeout(result.error)) return 124;
|
|
235
|
+
if (result.status !== null) return result.status;
|
|
236
|
+
if (result.signal) return signalExitCode(result.signal);
|
|
237
|
+
return 0;
|
|
238
|
+
}
|
|
239
|
+
function isTimeout(error) {
|
|
240
|
+
return !!error && error.code === "ETIMEDOUT";
|
|
241
|
+
}
|
|
242
|
+
function decode(buf) {
|
|
243
|
+
if (buf == null) return "";
|
|
244
|
+
return typeof buf === "string" ? buf : buf.toString("utf8");
|
|
245
|
+
}
|
|
246
|
+
async function wrapAndCompress(command, argv, filter, timeout, profile, opts) {
|
|
247
|
+
const writeStdout = opts.writeStdout ?? ((s) => process.stdout.write(s));
|
|
248
|
+
const writeStderr = opts.writeStderr ?? ((s) => process.stderr.write(s));
|
|
249
|
+
const startTime = Date.now();
|
|
250
|
+
const { file, args, shell, cmdEnv } = spawnTarget(command, opts.nativeShell);
|
|
251
|
+
const stdoutSink = new CaptureSink(MAX_CAPTURE_BYTES);
|
|
252
|
+
const stderrSink = new CaptureSink(MAX_CAPTURE_BYTES);
|
|
253
|
+
let timedOut = false;
|
|
254
|
+
let overflowed = false;
|
|
255
|
+
const child = spawn(file, args, { cwd: opts.cwd, shell, env: mergeSpawnEnv(opts.env, cmdEnv), stdio: ["ignore", "pipe", "pipe"] });
|
|
256
|
+
const heartbeat = scheduleHeartbeat(startTime, opts.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS, (elapsed) => {
|
|
257
|
+
writeStderr(`[token-goat compress] still running, ${elapsed}s elapsed
|
|
258
|
+
`);
|
|
259
|
+
});
|
|
260
|
+
const timeoutHandle = setTimeout(() => {
|
|
261
|
+
timedOut = true;
|
|
262
|
+
child.kill();
|
|
263
|
+
}, timeout * 1e3);
|
|
264
|
+
const onData = (sink) => (chunk) => {
|
|
265
|
+
heartbeat.onOutput();
|
|
266
|
+
sink.push(chunk);
|
|
267
|
+
if (sink.overflowed) {
|
|
268
|
+
overflowed = true;
|
|
269
|
+
child.kill();
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
child.stdout?.on("data", onData(stdoutSink));
|
|
273
|
+
child.stderr?.on("data", onData(stderrSink));
|
|
274
|
+
const { code, signal } = await new Promise((resolve) => {
|
|
275
|
+
child.on("close", (code2, signal2) => resolve({ code: code2, signal: signal2 }));
|
|
276
|
+
});
|
|
277
|
+
heartbeat.stop();
|
|
278
|
+
clearTimeout(timeoutHandle);
|
|
279
|
+
let stdoutText = stdoutSink.text();
|
|
280
|
+
let stderrText = stderrSink.text();
|
|
281
|
+
if (overflowed) {
|
|
282
|
+
stdoutText += `
|
|
283
|
+
[token-goat: capture capped at ${MAX_CAPTURE_BYTES / (1024 * 1024)} MiB]`;
|
|
284
|
+
}
|
|
285
|
+
let exitCode;
|
|
286
|
+
if (timedOut) {
|
|
287
|
+
exitCode = 124;
|
|
288
|
+
stderrText = (stderrText ? stderrText + "\n" : "") + `[token-goat: command exceeded ${timeout}s timeout and was killed]`;
|
|
289
|
+
} else if (code !== null) {
|
|
290
|
+
exitCode = code;
|
|
291
|
+
} else if (signal) {
|
|
292
|
+
exitCode = signalExitCode(signal);
|
|
293
|
+
} else {
|
|
294
|
+
exitCode = 0;
|
|
295
|
+
}
|
|
296
|
+
if (opts.quietSuccess && exitCode === 0) {
|
|
297
|
+
const duration = ((Date.now() - startTime) / 1e3).toFixed(1) + "s";
|
|
298
|
+
const fullRaw = (stdoutText + (stderrText ? "\n" + stderrText : "")).trim();
|
|
299
|
+
const id = storeBashOutputSync(command, fullRaw, 0, opts.cwd ?? null);
|
|
300
|
+
const summary = `[tg: ok] ${command} (${duration}, recall: token-goat bash-output ${id})
|
|
301
|
+
`;
|
|
302
|
+
writeStdout(summary);
|
|
303
|
+
return 0;
|
|
304
|
+
}
|
|
305
|
+
const limits = resolveCompressLimits();
|
|
306
|
+
const { applied, marker, compressed, text: delivered } = deliverCompressed(filter, stdoutText, stderrText, exitCode, argv, {
|
|
307
|
+
compressionProfile: profile,
|
|
308
|
+
maxLines: limits.maxLines,
|
|
309
|
+
maxBytes: limits.maxBytes
|
|
310
|
+
});
|
|
311
|
+
let text = delivered;
|
|
312
|
+
const maxTokens = opts.maxTokens ?? 0;
|
|
313
|
+
if (maxTokens > 0) text = capTokens(text, maxTokens);
|
|
314
|
+
let body = text + marker;
|
|
315
|
+
if (applied) {
|
|
316
|
+
const fullRaw = (stdoutText + (stderrText ? "\n" + stderrText : "")).trim();
|
|
317
|
+
const recallId = storeBashOutputSync(command, fullRaw, exitCode, opts.cwd ?? null);
|
|
318
|
+
body += "\n[token-goat] full output: bash-output " + recallId + " --full";
|
|
319
|
+
}
|
|
320
|
+
writeStdout(body.endsWith("\n") ? body : body + "\n");
|
|
321
|
+
if (applied) recordSavings(compressed);
|
|
322
|
+
return exitCode;
|
|
323
|
+
}
|
|
324
|
+
function recordSavings(result) {
|
|
325
|
+
const delivered = deliveredOutputBytes(result.originalBytes);
|
|
326
|
+
const bytesSaved = Math.max(0, delivered - result.compressedBytes);
|
|
327
|
+
if (bytesSaved < MIN_RECORD_STAT_BYTES) return;
|
|
328
|
+
recordStat(`bash_compress:${result.filterName}`, bytesSaved, compressedTokensSaved(bytesSaved));
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export {
|
|
332
|
+
clipToDeliveryCap,
|
|
333
|
+
deliveredOutputBytes,
|
|
334
|
+
canRunWrappedShell,
|
|
335
|
+
DEFAULT_TIMEOUT_SECONDS,
|
|
336
|
+
MAX_CAPTURE_BYTES,
|
|
337
|
+
DEFAULT_HEARTBEAT_INTERVAL_MS,
|
|
338
|
+
resolveFilter,
|
|
339
|
+
run,
|
|
340
|
+
runRaw
|
|
341
|
+
};
|
|
@@ -2,15 +2,15 @@ import { createRequire as __cjsRequire } from 'node:module';
|
|
|
2
2
|
const require = __cjsRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
getDb
|
|
5
|
-
} from "./token-goat-chunk-
|
|
5
|
+
} from "./token-goat-chunk-T63VHOL3.mjs";
|
|
6
6
|
import {
|
|
7
7
|
foldPath,
|
|
8
8
|
globalDbPath,
|
|
9
9
|
isCaseInsensitiveFs
|
|
10
|
-
} from "./token-goat-chunk-
|
|
10
|
+
} from "./token-goat-chunk-6LJNM4ZZ.mjs";
|
|
11
11
|
import {
|
|
12
12
|
normalizePath
|
|
13
|
-
} from "./token-goat-chunk-
|
|
13
|
+
} from "./token-goat-chunk-NMTKNYGF.mjs";
|
|
14
14
|
import {
|
|
15
15
|
init_define_import_meta_env
|
|
16
16
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
@@ -50,6 +50,9 @@ function projectScopeClause(column) {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
// src/index_reader.ts
|
|
53
|
+
function indexKey(p) {
|
|
54
|
+
return normalizePath(p);
|
|
55
|
+
}
|
|
53
56
|
function toSymbolEntry(row) {
|
|
54
57
|
return {
|
|
55
58
|
filePath: row.file_path,
|
|
@@ -75,7 +78,7 @@ function applyRootDirScope(rootDir, column, where, params) {
|
|
|
75
78
|
if (rootDir === void 0) return;
|
|
76
79
|
const { clause, params: bounds } = projectScopeClause(column);
|
|
77
80
|
where.push(clause);
|
|
78
|
-
params.push(...bounds(rootDir));
|
|
81
|
+
params.push(...bounds(indexKey(rootDir)));
|
|
79
82
|
}
|
|
80
83
|
function buildSymbolWhere(opts) {
|
|
81
84
|
const where = [];
|
|
@@ -85,13 +88,14 @@ function buildSymbolWhere(opts) {
|
|
|
85
88
|
params.push(opts.name);
|
|
86
89
|
}
|
|
87
90
|
if (opts.filePath !== void 0) {
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
const key = indexKey(opts.filePath);
|
|
92
|
+
if (key.includes("/") || key.includes("\\")) {
|
|
93
|
+
const alt = key.includes("/") ? key.replace(/\//g, "\\") : key.replace(/\\/g, "/");
|
|
90
94
|
where.push(`(${pathEqClause("file_path")} OR ${pathEqClause("file_path")})`);
|
|
91
|
-
params.push(foldPath(
|
|
95
|
+
params.push(foldPath(key), foldPath(alt));
|
|
92
96
|
} else {
|
|
93
97
|
where.push(pathEqClause("file_path"));
|
|
94
|
-
params.push(foldPath(
|
|
98
|
+
params.push(foldPath(key));
|
|
95
99
|
}
|
|
96
100
|
}
|
|
97
101
|
if (opts.kind !== void 0) {
|
|
@@ -141,7 +145,7 @@ function buildRefsWhere(opts) {
|
|
|
141
145
|
const params = [opts.name];
|
|
142
146
|
if (opts.filePath !== void 0) {
|
|
143
147
|
where.push(pathEqClause("file_path"));
|
|
144
|
-
params.push(foldPath(opts.filePath));
|
|
148
|
+
params.push(foldPath(indexKey(opts.filePath)));
|
|
145
149
|
}
|
|
146
150
|
applyRootDirScope(opts.rootDir, "file_path", where, params);
|
|
147
151
|
return { clause: `WHERE ${where.join(" AND ")}`, params };
|
|
@@ -164,7 +168,7 @@ function countRefs(opts, dbPath = globalDbPath()) {
|
|
|
164
168
|
function queryRefsByContext(context, filePath, dbPath = globalDbPath()) {
|
|
165
169
|
const sql = `SELECT file_path, name, line, col, context FROM refs WHERE context = ? AND ${pathEqClause("file_path")} ORDER BY line LIMIT 20`;
|
|
166
170
|
const db = getDb(dbPath);
|
|
167
|
-
const rows = db.prepare(sql).all(context, foldPath(filePath));
|
|
171
|
+
const rows = db.prepare(sql).all(context, foldPath(indexKey(filePath)));
|
|
168
172
|
return rows.map(toRefEntry);
|
|
169
173
|
}
|
|
170
174
|
var REF_COUNT_BATCH = 900;
|
|
@@ -192,7 +196,7 @@ function queryRefCounts(names, dbPath = globalDbPath(), rootDir) {
|
|
|
192
196
|
function getProjectFileEntries(rootDir, dbPath = globalDbPath()) {
|
|
193
197
|
const db = getDb(dbPath);
|
|
194
198
|
const { clause, params } = projectScopeClause("path");
|
|
195
|
-
const rows = db.prepare(`SELECT path, sha, mtime, language, indexed_at, embed_sha, parser_sha FROM files WHERE ${clause}`).all(...params(rootDir));
|
|
199
|
+
const rows = db.prepare(`SELECT path, sha, mtime, language, indexed_at, embed_sha, parser_sha FROM files WHERE ${clause}`).all(...params(indexKey(rootDir)));
|
|
196
200
|
const out = /* @__PURE__ */ new Map();
|
|
197
201
|
for (const row of rows) {
|
|
198
202
|
out.set(foldPath(row.path), {
|
|
@@ -209,11 +213,12 @@ function getProjectFileEntries(rootDir, dbPath = globalDbPath()) {
|
|
|
209
213
|
}
|
|
210
214
|
function getFileEntry(filePath, dbPath = globalDbPath()) {
|
|
211
215
|
const db = getDb(dbPath);
|
|
216
|
+
const key = indexKey(filePath);
|
|
212
217
|
let row = db.prepare(
|
|
213
218
|
`SELECT path, sha, mtime, language, indexed_at, embed_sha, parser_sha FROM files WHERE ${pathEqClause("path")}`
|
|
214
|
-
).get(foldPath(
|
|
215
|
-
if (row === void 0 && (
|
|
216
|
-
const altPath =
|
|
219
|
+
).get(foldPath(key));
|
|
220
|
+
if (row === void 0 && (key.includes("/") || key.includes("\\"))) {
|
|
221
|
+
const altPath = key.includes("/") ? key.replace(/\//g, "\\") : key.replace(/\\/g, "/");
|
|
217
222
|
row = db.prepare(
|
|
218
223
|
`SELECT path, sha, mtime, language, indexed_at, embed_sha, parser_sha FROM files WHERE ${pathEqClause("path")}`
|
|
219
224
|
).get(foldPath(altPath));
|