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.
Files changed (55) hide show
  1. package/README.md +5 -1
  2. package/dist/token-goat-chunk-2CLWWRFR.mjs +26 -0
  3. package/dist/{token-goat-chunk-LTYWLKAG.mjs → token-goat-chunk-2Q3N5KUQ.mjs} +1283 -1012
  4. package/dist/{token-goat-chunk-6LGVCCMY.mjs → token-goat-chunk-3OGZOFLS.mjs} +26 -16
  5. package/dist/{token-goat-chunk-QML7ITHJ.mjs → token-goat-chunk-3VTJC7KU.mjs} +693 -438
  6. package/dist/{token-goat-chunk-QIDLJGXZ.mjs → token-goat-chunk-6LJNM4ZZ.mjs} +29 -5
  7. package/dist/{token-goat-chunk-CA6V36KW.mjs → token-goat-chunk-74ADIZZX.mjs} +68 -50
  8. package/dist/{token-goat-chunk-52IMXJ2L.mjs → token-goat-chunk-ASTBLE2R.mjs} +4 -4
  9. package/dist/token-goat-chunk-AU2K2QHR.mjs +20 -0
  10. package/dist/token-goat-chunk-BQIC3AVL.mjs +292 -0
  11. package/dist/token-goat-chunk-CBXLE54Q.mjs +30 -0
  12. package/dist/{token-goat-chunk-LMFO66YD.mjs → token-goat-chunk-DA43OE7L.mjs} +1 -1
  13. package/dist/{token-goat-chunk-ARNRFR6M.mjs → token-goat-chunk-DNAF26L4.mjs} +1 -1
  14. package/dist/{token-goat-chunk-BFEWOMA3.mjs → token-goat-chunk-DPHJU3P7.mjs} +1186 -4573
  15. package/dist/{token-goat-chunk-OWSJJY5R.mjs → token-goat-chunk-DW4VKU7D.mjs} +5 -5
  16. package/dist/token-goat-chunk-DYUBZZNP.mjs +198 -0
  17. package/dist/{token-goat-chunk-W3E65QOW.mjs → token-goat-chunk-ERGHDBC6.mjs} +310 -47
  18. package/dist/token-goat-chunk-EUZKG7ZO.mjs +304 -0
  19. package/dist/{token-goat-chunk-5MMJAJF3.mjs → token-goat-chunk-FWYZVS3E.mjs} +324 -31
  20. package/dist/token-goat-chunk-G6SYQQO7.mjs +41 -0
  21. package/dist/{token-goat-chunk-YQZE5NS6.mjs → token-goat-chunk-GIPMOGOI.mjs} +6 -6
  22. package/dist/{token-goat-chunk-BWCRC23L.mjs → token-goat-chunk-H4VC5TR6.mjs} +29 -20
  23. package/dist/{token-goat-chunk-V3ZWBEHM.mjs → token-goat-chunk-I5PQRHFE.mjs} +103 -24
  24. package/dist/token-goat-chunk-ITWYDOKP.mjs +341 -0
  25. package/dist/{token-goat-chunk-I67CPTDD.mjs → token-goat-chunk-K3ZNBN4U.mjs} +19 -14
  26. package/dist/{token-goat-chunk-HPOFR6QX.mjs → token-goat-chunk-K5XPIUVB.mjs} +222 -61
  27. package/dist/token-goat-chunk-KT75DZK4.mjs +1989 -0
  28. package/dist/{token-goat-chunk-H3FONFBO.mjs → token-goat-chunk-MNJWG2ZO.mjs} +3 -3
  29. package/dist/{token-goat-chunk-GRI6HWX3.mjs → token-goat-chunk-MUJV7BR3.mjs} +1 -1
  30. package/dist/{token-goat-chunk-ERTXEKB6.mjs → token-goat-chunk-NMTKNYGF.mjs} +2 -0
  31. package/dist/{token-goat-chunk-LA3O4JGD.mjs → token-goat-chunk-ODF7H7WS.mjs} +3 -3
  32. package/dist/{token-goat-chunk-K4DG6EEF.mjs → token-goat-chunk-ONMU7BON.mjs} +7 -8
  33. package/dist/{token-goat-chunk-4EXFN2AW.mjs → token-goat-chunk-OZRSREKR.mjs} +2 -2
  34. package/dist/{token-goat-chunk-EPXNOKIV.mjs → token-goat-chunk-P4XBHZXU.mjs} +2 -2
  35. package/dist/{token-goat-chunk-CTOYJ232.mjs → token-goat-chunk-PAVWB4L4.mjs} +173 -1840
  36. package/dist/{token-goat-chunk-UENEL6KX.mjs → token-goat-chunk-PTW22MRC.mjs} +2 -2
  37. package/dist/token-goat-chunk-SL454EN5.mjs +1816 -0
  38. package/dist/token-goat-chunk-SP5QR2HN.mjs +1379 -0
  39. package/dist/{token-goat-chunk-7VLWNQDQ.mjs → token-goat-chunk-T46UKRFM.mjs} +1 -1
  40. package/dist/{token-goat-chunk-L7VCX33I.mjs → token-goat-chunk-T63VHOL3.mjs} +40 -10
  41. package/dist/token-goat-chunk-VSJGPEBB.mjs +248 -0
  42. package/dist/{token-goat-chunk-HIZXQVNU.mjs → token-goat-chunk-VYXGHGUY.mjs} +4 -4
  43. package/dist/token-goat-chunk-W6QYCWAT.mjs +128 -0
  44. package/dist/{token-goat-chunk-WFX2V3OF.mjs → token-goat-chunk-Z4ALQADF.mjs} +579 -422
  45. package/dist/token-goat-chunk-ZHFM4DHJ.mjs +324 -0
  46. package/dist/token-goat-hook.mjs +18 -12
  47. package/dist/token-goat.core.mjs +29 -20
  48. package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
  49. package/docs/cli.md +15 -13
  50. package/docs/install.md +1 -1
  51. package/docs/security.md +2 -2
  52. package/package.json +3 -2
  53. package/dist/token-goat-chunk-2KTZ6J7T.mjs +0 -173
  54. package/dist/token-goat-chunk-34OUJ2IE.mjs +0 -35
  55. 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
- enqueueDirtyPathSafe,
4
+ enqueueDirtyPathsSafe,
5
+ fenceUntrusted,
5
6
  getToolName,
6
- getTrackedFiles
7
- } from "./token-goat-chunk-BFEWOMA3.mjs";
7
+ getTrackedFiles,
8
+ scanAndRecord
9
+ } from "./token-goat-chunk-DPHJU3P7.mjs";
8
10
  import {
9
- indexRecallEntry
10
- } from "./token-goat-chunk-CTOYJ232.mjs";
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-HPOFR6QX.mjs";
21
+ } from "./token-goat-chunk-K5XPIUVB.mjs";
17
22
  import {
18
- PARSER_FINGERPRINT
19
- } from "./token-goat-chunk-W3E65QOW.mjs";
23
+ parserFingerprintForLanguage
24
+ } from "./token-goat-chunk-ERGHDBC6.mjs";
20
25
  import {
21
26
  getProjectFileEntries,
22
27
  projectScopeClause
23
- } from "./token-goat-chunk-I67CPTDD.mjs";
28
+ } from "./token-goat-chunk-K3ZNBN4U.mjs";
24
29
  import {
25
30
  getDb
26
- } from "./token-goat-chunk-L7VCX33I.mjs";
31
+ } from "./token-goat-chunk-T63VHOL3.mjs";
27
32
  import {
28
33
  fingerprintFile,
29
34
  getDisplayRoot,
30
35
  shortFingerprint
31
- } from "./token-goat-chunk-CA6V36KW.mjs";
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
- } from "./token-goat-chunk-QIDLJGXZ.mjs";
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-ERTXEKB6.mjs";
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-4EXFN2AW.mjs");
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 could be compared and no deletions were computed. Run token-goat inside the repository, or reindex with --walk if this directory is deliberately not under git.");
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 !== PARSER_FINGERPRINT) {
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 && !trackedUnavailable) {
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
- removed.push(entry.filePath);
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
- for (const p of [...changed, ...added, ...removed]) {
929
- enqueueDirtyPathSafe(resolveIndexPath(p, cwd), { alreadyResolved: true });
930
- enqueued++;
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-L7VCX33I.mjs";
5
+ } from "./token-goat-chunk-T63VHOL3.mjs";
6
6
  import {
7
7
  foldPath,
8
8
  globalDbPath,
9
9
  isCaseInsensitiveFs
10
- } from "./token-goat-chunk-QIDLJGXZ.mjs";
10
+ } from "./token-goat-chunk-6LJNM4ZZ.mjs";
11
11
  import {
12
12
  normalizePath
13
- } from "./token-goat-chunk-ERTXEKB6.mjs";
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
- if (opts.filePath.includes("/") || opts.filePath.includes("\\")) {
89
- const alt = opts.filePath.includes("/") ? opts.filePath.replace(/\//g, "\\") : opts.filePath.replace(/\\/g, "/");
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(opts.filePath), foldPath(alt));
95
+ params.push(foldPath(key), foldPath(alt));
92
96
  } else {
93
97
  where.push(pathEqClause("file_path"));
94
- params.push(foldPath(opts.filePath));
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(filePath));
215
- if (row === void 0 && (filePath.includes("/") || filePath.includes("\\"))) {
216
- const altPath = filePath.includes("/") ? filePath.replace(/\//g, "\\") : filePath.replace(/\\/g, "/");
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));