token-goat 2.9.26 → 2.9.29

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 (78) hide show
  1. package/README.md +30 -88
  2. package/SECURITY.md +14 -0
  3. package/dist/{token-goat-chunk-OZRSREKR.mjs → token-goat-chunk-2AWQ2R5X.mjs} +2 -2
  4. package/dist/{token-goat-chunk-BH4ZVRB2.mjs → token-goat-chunk-2NNUA2LR.mjs} +4 -4
  5. package/dist/token-goat-chunk-2WOUYWLM.mjs +955 -0
  6. package/dist/{token-goat-chunk-IKZLSRII.mjs → token-goat-chunk-435UQTKD.mjs} +5 -3
  7. package/dist/{token-goat-chunk-62IHOU6L.mjs → token-goat-chunk-44BM7DDQ.mjs} +5 -3
  8. package/dist/token-goat-chunk-52NSDWYY.mjs +96 -0
  9. package/dist/{token-goat-chunk-CXBOFPF4.mjs → token-goat-chunk-67BNIKKO.mjs} +32 -18
  10. package/dist/{token-goat-chunk-XBESNWEX.mjs → token-goat-chunk-6AK46ZT7.mjs} +2 -3
  11. package/dist/{token-goat-chunk-7SXPJOSZ.mjs → token-goat-chunk-7CPMDFGB.mjs} +166 -40
  12. package/dist/token-goat-chunk-ASLWOQ3I.mjs +14 -0
  13. package/dist/{token-goat-chunk-MWID3YOY.mjs → token-goat-chunk-BGYOZ6DO.mjs} +6 -4
  14. package/dist/{token-goat-chunk-PAV6NNY7.mjs → token-goat-chunk-C5YPNZKQ.mjs} +22 -8
  15. package/dist/{token-goat-chunk-D2X7XN5M.mjs → token-goat-chunk-CIQ2FTY3.mjs} +23 -242
  16. package/dist/token-goat-chunk-D4ETHJD6.mjs +246 -0
  17. package/dist/{token-goat-chunk-7Y6GWTII.mjs → token-goat-chunk-DNRPXHYH.mjs} +25 -17
  18. package/dist/{token-goat-chunk-L43RKNHA.mjs → token-goat-chunk-DNSPXQXQ.mjs} +2 -2
  19. package/dist/token-goat-chunk-DPNLUJWB.mjs +220 -0
  20. package/dist/token-goat-chunk-E4ZOJIZK.mjs +1382 -0
  21. package/dist/token-goat-chunk-E5TK5DNO.mjs +718 -0
  22. package/dist/{token-goat-chunk-VVROQBQJ.mjs → token-goat-chunk-EUSDXRXU.mjs} +62 -12
  23. package/dist/{token-goat-chunk-POOI26O6.mjs → token-goat-chunk-FTP4U4QA.mjs} +12 -8
  24. package/dist/token-goat-chunk-G23DWHV4.mjs +142 -0
  25. package/dist/{token-goat-chunk-MDV5VWF4.mjs → token-goat-chunk-G7IWXCFF.mjs} +223 -15
  26. package/dist/{token-goat-chunk-C2PG4K5D.mjs → token-goat-chunk-GLXRTTLE.mjs} +7 -5
  27. package/dist/{token-goat-chunk-M6CVNHTW.mjs → token-goat-chunk-H5J3C56Q.mjs} +95 -573
  28. package/dist/{token-goat-chunk-BAWKGODL.mjs → token-goat-chunk-HNFZZHFW.mjs} +2 -2
  29. package/dist/{token-goat-chunk-TG5ZPD6B.mjs → token-goat-chunk-HUYUHODZ.mjs} +1036 -759
  30. package/dist/token-goat-chunk-IVE6U7KV.mjs +53 -0
  31. package/dist/{token-goat-chunk-ZZT6PVB3.mjs → token-goat-chunk-IVWI2OCK.mjs} +72 -45
  32. package/dist/{token-goat-chunk-GMOUBOX4.mjs → token-goat-chunk-JTKCQMQA.mjs} +37 -5
  33. package/dist/{token-goat-chunk-H2CPLEMP.mjs → token-goat-chunk-KOPIR3KZ.mjs} +46 -23
  34. package/dist/token-goat-chunk-L7H3U27L.mjs +35 -0
  35. package/dist/{token-goat-chunk-FLEYOCAS.mjs → token-goat-chunk-LZNBQTDK.mjs} +6 -4
  36. package/dist/token-goat-chunk-MELOKFDJ.mjs +199 -0
  37. package/dist/{token-goat-chunk-RH27ZSPF.mjs → token-goat-chunk-NMBWLRHW.mjs} +164 -50
  38. package/dist/{token-goat-chunk-43JFN26X.mjs → token-goat-chunk-O6I2XU4P.mjs} +27 -967
  39. package/dist/{token-goat-chunk-G6EYO5CD.mjs → token-goat-chunk-ONXH6NZ5.mjs} +2 -87
  40. package/dist/token-goat-chunk-ORNFMIER.mjs +295 -0
  41. package/dist/{token-goat-chunk-LHUP4DXZ.mjs → token-goat-chunk-PGTH2U4C.mjs} +1 -1
  42. package/dist/{token-goat-chunk-5BQ7W7D7.mjs → token-goat-chunk-PKRWMHVP.mjs} +76 -59
  43. package/dist/{token-goat-chunk-DA43OE7L.mjs → token-goat-chunk-PQ53BSCF.mjs} +1 -1
  44. package/dist/{token-goat-chunk-STYRLQIW.mjs → token-goat-chunk-PYSUADX4.mjs} +2 -2
  45. package/dist/{token-goat-chunk-JALB3KWJ.mjs → token-goat-chunk-QO3LXVVR.mjs} +4247 -5005
  46. package/dist/{token-goat-chunk-L45IWWMC.mjs → token-goat-chunk-RLP6J7WR.mjs} +6 -6
  47. package/dist/token-goat-chunk-RQGGMPCR.mjs +205 -0
  48. package/dist/{token-goat-chunk-MBDJR6HU.mjs → token-goat-chunk-RTMVLHWX.mjs} +3708 -4003
  49. package/dist/{token-goat-chunk-E3K3BTEQ.mjs → token-goat-chunk-S4VSXURL.mjs} +8 -6
  50. package/dist/{token-goat-chunk-LKSXAMJB.mjs → token-goat-chunk-SE6E4BKJ.mjs} +1 -1
  51. package/dist/token-goat-chunk-TCQANXYC.mjs +351 -0
  52. package/dist/token-goat-chunk-TDUT2CL6.mjs +564 -0
  53. package/dist/{token-goat-chunk-LRIZ7K3F.mjs → token-goat-chunk-TGOXNAHW.mjs} +54 -111
  54. package/dist/{token-goat-chunk-WNBSCSAI.mjs → token-goat-chunk-UA5BKWWQ.mjs} +1 -1
  55. package/dist/{token-goat-chunk-RIB6XY2V.mjs → token-goat-chunk-UXSXQQIY.mjs} +1 -1
  56. package/dist/{token-goat-chunk-7EPYB34H.mjs → token-goat-chunk-VMFWNHGR.mjs} +84 -73
  57. package/dist/token-goat-chunk-VQ6F6T7X.mjs +36 -0
  58. package/dist/{token-goat-chunk-5M3NRJD2.mjs → token-goat-chunk-VZQEWRVH.mjs} +6 -4
  59. package/dist/{token-goat-chunk-OSUFN2FV.mjs → token-goat-chunk-XB5KKOCG.mjs} +5 -25
  60. package/dist/{token-goat-chunk-6E2IDLHF.mjs → token-goat-chunk-XYWPOSCN.mjs} +57 -615
  61. package/dist/{token-goat-chunk-CQHY4SL7.mjs → token-goat-chunk-YAGLESS3.mjs} +8 -5
  62. package/dist/token-goat-chunk-YKSRAWUU.mjs +33 -0
  63. package/dist/{token-goat-chunk-F2ARFHLJ.mjs → token-goat-chunk-YOOVFPTP.mjs} +2 -2
  64. package/dist/{token-goat-chunk-EEIDFMEM.mjs → token-goat-chunk-YZAAZU2S.mjs} +12 -3
  65. package/dist/token-goat-chunk-Z6KBMOBI.mjs +53 -0
  66. package/dist/{token-goat-chunk-4GEDH2WU.mjs → token-goat-chunk-ZER6EAXZ.mjs} +81 -70
  67. package/dist/token-goat-hook-client.cjs +475 -0
  68. package/dist/token-goat-hook-client.mjs +26 -0
  69. package/dist/token-goat-hook.mjs +31 -21
  70. package/dist/token-goat.core.mjs +9 -39
  71. package/docs/C4_RUNTIME_ARCHITECTURE.md +2 -2
  72. package/docs/cli.md +35 -23
  73. package/docs/install.md +18 -14
  74. package/package.json +1 -1
  75. package/dist/token-goat-chunk-ADMR3QVF.mjs +0 -41
  76. package/dist/token-goat-chunk-E6B2UFDF.mjs +0 -30
  77. package/dist/token-goat-chunk-GKZ2US5B.mjs +0 -187
  78. package/dist/token-goat-chunk-MZTO4FXH.mjs +0 -26
@@ -1,516 +1,74 @@
1
1
  import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
+ import {
4
+ GENERIC_SERVED_OUTPUT_KEY,
5
+ MAX_GENERIC_SERVED_OUTPUTS,
6
+ MAX_OUTSTANDING_AGENT_SPAWNS,
7
+ MAX_RANGES_PER_FILE,
8
+ MAX_SEEN_IMAGE_HASHES,
9
+ MAX_SERVED_OUTPUTS_PER_FILE,
10
+ consumedCurlDownloadKeys,
11
+ consumedFileLineRangeKeys,
12
+ consumedFileServedOutputKeys,
13
+ consumedOutstandingAgentSpawnKeys,
14
+ consumedPendingLargeFileHintKeys,
15
+ curlDownloadsAtLoad,
16
+ exportSessionState,
17
+ filesFullReadCountAtLoad,
18
+ filesReadCountAtLoad,
19
+ importSessionState,
20
+ migrateCurlDownloadKey,
21
+ migrateWebFetchKey,
22
+ outstandingAgentSpawnKey,
23
+ outstandingAgentSpawnsAtLoad,
24
+ pendingLargeFileHintsAtLoad
25
+ } from "./token-goat-chunk-TDUT2CL6.mjs";
3
26
  import {
4
27
  claudeConfigDir,
5
28
  readTranscriptTail
6
- } from "./token-goat-chunk-G6EYO5CD.mjs";
29
+ } from "./token-goat-chunk-ONXH6NZ5.mjs";
7
30
  import {
8
31
  DEFAULT_MAX_AGE_MS,
9
- DEFAULT_MAX_COUNT,
32
+ DEFAULT_MAX_COUNT
33
+ } from "./token-goat-chunk-D4ETHJD6.mjs";
34
+ import {
10
35
  recordStat,
11
36
  redactSecrets
12
- } from "./token-goat-chunk-D2X7XN5M.mjs";
37
+ } from "./token-goat-chunk-CIQ2FTY3.mjs";
13
38
  import {
14
39
  detectHarness,
15
40
  isAutoTriggerMultiplierExplicit,
16
41
  loadConfig,
17
42
  shortFingerprint
18
- } from "./token-goat-chunk-LRIZ7K3F.mjs";
43
+ } from "./token-goat-chunk-TGOXNAHW.mjs";
19
44
  import {
20
45
  registerReset
21
- } from "./token-goat-chunk-EEIDFMEM.mjs";
46
+ } from "./token-goat-chunk-YZAAZU2S.mjs";
22
47
  import {
23
48
  LOCK_WAIT_MS_HARDENED,
24
49
  atomicWriteText,
25
- dataDir,
26
50
  ensureDirSync,
27
- foldPath,
28
51
  isCodeFenceDelimiter,
29
52
  normalizePathForwardSlash,
30
53
  sanitizeIdForFilename,
31
54
  stripLower,
32
- tokenGoatHome,
33
- withFileLock
34
- } from "./token-goat-chunk-6E2IDLHF.mjs";
55
+ withFileLock,
56
+ withRetryOnLock
57
+ } from "./token-goat-chunk-XYWPOSCN.mjs";
58
+ import {
59
+ foldPath
60
+ } from "./token-goat-chunk-TCQANXYC.mjs";
35
61
  import {
36
62
  normalizePath
37
63
  } from "./token-goat-chunk-NMTKNYGF.mjs";
64
+ import {
65
+ dataDir,
66
+ tokenGoatHome
67
+ } from "./token-goat-chunk-MELOKFDJ.mjs";
38
68
  import {
39
69
  init_define_import_meta_env
40
70
  } from "./token-goat-chunk-A37V4PBF.mjs";
41
71
 
42
- // src/session.ts
43
- init_define_import_meta_env();
44
- import { randomBytes, randomUUID } from "node:crypto";
45
- import * as fs from "node:fs";
46
- var _files = /* @__PURE__ */ new Map();
47
- var _filesAtLoad = /* @__PURE__ */ new Map();
48
- var _filesFullReadCountAtLoad = /* @__PURE__ */ new Map();
49
- var _hintsShown = /* @__PURE__ */ new Set();
50
- var _scheduledPromptCounts = /* @__PURE__ */ new Map();
51
- var _webFetches = /* @__PURE__ */ new Map();
52
- var _bashOutputs = /* @__PURE__ */ new Map();
53
- var _grepQueries = /* @__PURE__ */ new Map();
54
- var _globQueries = /* @__PURE__ */ new Map();
55
- var _lastTabContext = null;
56
- var _seenImageHashes = [];
57
- var _outstandingAgentSpawns = [];
58
- var _outstandingAgentSpawnsAtLoad = [];
59
- var _bashReruns = /* @__PURE__ */ new Set();
60
- var _curlDownloads = /* @__PURE__ */ new Map();
61
- var _curlDownloadsAtLoad = /* @__PURE__ */ new Map();
62
- var _fileLineRanges = /* @__PURE__ */ new Map();
63
- var _fileServedOutputs = /* @__PURE__ */ new Map();
64
- var _fileLineRangesAtLoad = /* @__PURE__ */ new Map();
65
- var _fileServedOutputsAtLoad = /* @__PURE__ */ new Map();
66
- var _compactedAt = 0;
67
- var _cliReads = /* @__PURE__ */ new Set();
68
- var _pendingLargeFileHints = /* @__PURE__ */ new Map();
69
- var _pendingLargeFileHintsAtLoad = /* @__PURE__ */ new Map();
70
- var _sessionId = null;
71
- var _transcriptPath = null;
72
- function fileSize(absPath) {
73
- try {
74
- return fs.statSync(absPath).size;
75
- } catch {
76
- return 0;
77
- }
78
- }
79
- function resolveFilesKey(normalized) {
80
- if (_files.has(normalized)) return normalized;
81
- const folded = foldPath(normalized);
82
- if (folded === normalized) return normalized;
83
- for (const existingKey of _files.keys()) {
84
- if (foldPath(existingKey) === folded) return existingKey;
85
- }
86
- return normalized;
87
- }
88
- function recordFileRead(filePath, isFullRead = true) {
89
- const normalized = normalizePath(filePath);
90
- const key = resolveFilesKey(normalized);
91
- const now = Date.now();
92
- const size = fileSize(normalized);
93
- const prev = _files.get(key);
94
- if (prev === void 0) {
95
- _files.set(key, {
96
- path: key,
97
- readCount: 1,
98
- lastReadAt: now,
99
- wasEdited: false,
100
- sizeBytes: size,
101
- ...isFullRead ? { lastFullReadAt: now, fullReadCount: 1 } : {}
102
- });
103
- return;
104
- }
105
- _files.set(key, {
106
- ...prev,
107
- readCount: prev.readCount + 1,
108
- lastReadAt: now,
109
- sizeBytes: size,
110
- ...isFullRead ? { lastFullReadAt: now, fullReadCount: (prev.fullReadCount ?? 0) + 1 } : {}
111
- });
112
- }
113
- var MAX_SYMBOLS_PER_FILE = 25;
114
- function recordSymbolRead(filePath, symbol) {
115
- const normalized = normalizePath(filePath);
116
- const key = resolveFilesKey(normalized);
117
- const prev = _files.get(key);
118
- if (prev === void 0) {
119
- _files.set(key, {
120
- path: key,
121
- readCount: 0,
122
- lastReadAt: Date.now(),
123
- wasEdited: false,
124
- sizeBytes: fileSize(normalized),
125
- symbols_read: [symbol]
126
- });
127
- return;
128
- }
129
- const existing = prev.symbols_read ?? [];
130
- if (existing.includes(symbol)) return;
131
- const symbols_read = [...existing, symbol].slice(-MAX_SYMBOLS_PER_FILE);
132
- _files.set(key, { ...prev, symbols_read });
133
- }
134
- function filesReadCountAtLoad() {
135
- return _filesAtLoad;
136
- }
137
- function filesFullReadCountAtLoad() {
138
- return _filesFullReadCountAtLoad;
139
- }
140
- function recordFileEdit(filePath) {
141
- const normalized = normalizePath(filePath);
142
- const key = resolveFilesKey(normalized);
143
- _fileLineRanges.delete(foldPath(normalized));
144
- const prev = _files.get(key);
145
- if (prev === void 0) {
146
- _files.set(key, {
147
- path: key,
148
- readCount: 0,
149
- lastReadAt: 0,
150
- wasEdited: true,
151
- sizeBytes: fileSize(normalized)
152
- });
153
- return;
154
- }
155
- _files.set(key, { ...prev, wasEdited: true });
156
- }
157
- function getSessionFiles() {
158
- return _files;
159
- }
160
- function wasFileReadThisSession(filePath) {
161
- const entry = _files.get(resolveFilesKey(normalizePath(filePath)));
162
- return entry !== void 0 && entry.readCount > 0 && entry.lastReadAt >= _compactedAt;
163
- }
164
- function wasFileFullyReadThisSession(filePath) {
165
- const entry = _files.get(resolveFilesKey(normalizePath(filePath)));
166
- return entry !== void 0 && entry.lastFullReadAt !== void 0 && entry.lastFullReadAt >= _compactedAt;
167
- }
168
- function getCompactedAt() {
169
- return _compactedAt;
170
- }
171
- function markCompacted(now = Date.now()) {
172
- if (now <= _compactedAt) return;
173
- _compactedAt = now;
174
- _fileLineRanges = /* @__PURE__ */ new Map();
175
- _fileServedOutputs = /* @__PURE__ */ new Map();
176
- }
177
- function getSessionFileEntry(filePath) {
178
- return _files.get(resolveFilesKey(normalizePath(filePath)));
179
- }
180
- function wasHintShown(hintKey) {
181
- return _hintsShown.has(hintKey);
182
- }
183
- function markHintShown(hintKey) {
184
- _hintsShown.add(hintKey);
185
- }
186
- function recordScheduledPrompt(sessionId) {
187
- const count = (_scheduledPromptCounts.get(sessionId) ?? 0) + 1;
188
- _scheduledPromptCounts.set(sessionId, count);
189
- return count;
190
- }
191
- function wasCliReadThisSession(cliReadKey) {
192
- return _cliReads.has(cliReadKey);
193
- }
194
- function recordCliRead(cliReadKey) {
195
- _cliReads.add(cliReadKey);
196
- }
197
- function recordLargeFileHintPending(filePath, sizeBytes) {
198
- _pendingLargeFileHints.set(foldPath(normalizePath(filePath)), sizeBytes);
199
- }
200
- function takePendingLargeFileHint(filePath) {
201
- const key = foldPath(normalizePath(filePath));
202
- const size = _pendingLargeFileHints.get(key);
203
- if (size === void 0) return null;
204
- _pendingLargeFileHints.delete(key);
205
- return size;
206
- }
207
- function consumedPendingLargeFileHintKeys() {
208
- const consumed = [];
209
- for (const key of _pendingLargeFileHintsAtLoad.keys()) {
210
- if (!_pendingLargeFileHints.has(key)) consumed.push(key);
211
- }
212
- return consumed;
213
- }
214
- function pendingLargeFileHintsAtLoad() {
215
- return _pendingLargeFileHintsAtLoad;
216
- }
217
- var WEB_FETCH_KEY_SEP = "\0";
218
- function webFetchKey(url, prompt) {
219
- const digest = shortFingerprint(`${url}${WEB_FETCH_KEY_SEP}${prompt}`);
220
- return [redactSecrets(url).text, redactSecrets(prompt).text, digest].join(WEB_FETCH_KEY_SEP);
221
- }
222
- function recordWebFetch(url, prompt, cacheId) {
223
- _webFetches.set(webFetchKey(url, prompt), cacheId);
224
- }
225
- function migrateCurlDownloadKey(key) {
226
- if (/^[0-9a-f]{16}$/.test(key)) return key;
227
- return curlDownloadKey(key);
228
- }
229
- function migrateWebFetchKey(key) {
230
- const parts = key.split(WEB_FETCH_KEY_SEP);
231
- if (parts.length !== 2) return key;
232
- return webFetchKey(parts[0] ?? "", parts[1] ?? "");
233
- }
234
- function getSessionWebFetches() {
235
- return _webFetches;
236
- }
237
- function recordBashOutput(commandHash, outputId, _sizeBytes) {
238
- _bashOutputs.set(commandHash, outputId);
239
- }
240
- function getSessionBashOutputs() {
241
- return Array.from(_bashOutputs.entries());
242
- }
243
- function recordBashRerun(commandHash) {
244
- _bashReruns.add(commandHash);
245
- }
246
- function getSessionBashReruns() {
247
- return Array.from(_bashReruns);
248
- }
249
- function getBashOutputId(commandHash) {
250
- return _bashOutputs.get(commandHash) ?? null;
251
- }
252
- function recordGrepQuery(signature, matchCount) {
253
- _grepQueries.set(signature, matchCount);
254
- }
255
- function getGrepMatchCount(signature) {
256
- return _grepQueries.get(signature) ?? null;
257
- }
258
- function recordGlobQuery(signature, matchCount) {
259
- _globQueries.set(signature, matchCount);
260
- }
261
- function getGlobMatchCount(signature) {
262
- return _globQueries.get(signature) ?? null;
263
- }
264
- function setLastTabContext(text) {
265
- _lastTabContext = shortFingerprint(text);
266
- }
267
- function lastTabContextMatches(text) {
268
- return _lastTabContext !== null && _lastTabContext === shortFingerprint(text);
269
- }
270
- var MAX_SEEN_IMAGE_HASHES = 16;
271
- function hasSeenImage(hash) {
272
- return _seenImageHashes.includes(hash);
273
- }
274
- function recordSeenImage(hash) {
275
- const at = _seenImageHashes.indexOf(hash);
276
- if (at !== -1) _seenImageHashes.splice(at, 1);
277
- _seenImageHashes.push(hash);
278
- if (_seenImageHashes.length > MAX_SEEN_IMAGE_HASHES) {
279
- _seenImageHashes.splice(0, _seenImageHashes.length - MAX_SEEN_IMAGE_HASHES);
280
- }
281
- }
282
- var MAX_OUTSTANDING_AGENT_SPAWNS = 30;
283
- function recordOutstandingAgentSpawn(prompt) {
284
- _outstandingAgentSpawns.push({ prompt: redactSecrets(prompt).text, ts: Date.now() });
285
- if (_outstandingAgentSpawns.length > MAX_OUTSTANDING_AGENT_SPAWNS) {
286
- _outstandingAgentSpawns.splice(0, _outstandingAgentSpawns.length - MAX_OUTSTANDING_AGENT_SPAWNS);
287
- }
288
- }
289
- function getOutstandingAgentSpawns() {
290
- return _outstandingAgentSpawns;
291
- }
292
- function removeOutstandingAgentSpawn(finishedPrompt) {
293
- const idx = _outstandingAgentSpawns.findIndex((e) => finishedPrompt.startsWith(e.prompt));
294
- if (idx !== -1) _outstandingAgentSpawns.splice(idx, 1);
295
- }
296
- function outstandingAgentSpawnKey(prompt, ts) {
297
- return `${prompt} ${ts}`;
298
- }
299
- function outstandingAgentSpawnsAtLoad() {
300
- return _outstandingAgentSpawnsAtLoad;
301
- }
302
- function consumedOutstandingAgentSpawnKeys() {
303
- const currentKeys = new Set(_outstandingAgentSpawns.map((e) => outstandingAgentSpawnKey(e.prompt, e.ts)));
304
- const consumed = [];
305
- for (const e of _outstandingAgentSpawnsAtLoad) {
306
- const key = outstandingAgentSpawnKey(e.prompt, e.ts);
307
- if (!currentKeys.has(key)) consumed.push(key);
308
- }
309
- return consumed;
310
- }
311
- function curlDownloadKey(url) {
312
- return shortFingerprint(url);
313
- }
314
- function recordCurlDownload(url, savedPath) {
315
- _curlDownloads.set(curlDownloadKey(url), savedPath);
316
- }
317
- function getCurlDownloadPath(url) {
318
- return _curlDownloads.get(curlDownloadKey(url)) ?? null;
319
- }
320
- function clearCurlDownload(url) {
321
- _curlDownloads.delete(curlDownloadKey(url));
322
- }
323
- function curlDownloadsAtLoad() {
324
- return _curlDownloadsAtLoad;
325
- }
326
- function consumedCurlDownloadKeys() {
327
- const consumed = [];
328
- for (const url of _curlDownloadsAtLoad.keys()) {
329
- if (!_curlDownloads.has(url)) consumed.push(url);
330
- }
331
- return consumed;
332
- }
333
- function consumedFileLineRangeKeys() {
334
- const consumed = [];
335
- for (const key of _fileLineRangesAtLoad.keys()) {
336
- if (!_fileLineRanges.has(key)) consumed.push(key);
337
- }
338
- return consumed;
339
- }
340
- function consumedFileServedOutputKeys() {
341
- const consumed = [];
342
- for (const key of _fileServedOutputsAtLoad.keys()) {
343
- if (!_fileServedOutputs.has(key)) consumed.push(key);
344
- }
345
- return consumed;
346
- }
347
- var MAX_RANGES_PER_FILE = 64;
348
- function statIdentity(absPath) {
349
- try {
350
- const st = fs.statSync(absPath);
351
- return { size: st.size, mtimeMs: st.mtimeMs };
352
- } catch {
353
- return void 0;
354
- }
355
- }
356
- function recordFileLineRange(filePath, start, end) {
357
- const normalized = normalizePath(filePath);
358
- const key = foldPath(normalized);
359
- const ranges = _fileLineRanges.get(key) ?? [];
360
- if (!ranges.some(([s, e]) => s === start && e === end)) {
361
- ranges.push([start, end]);
362
- if (ranges.length > MAX_RANGES_PER_FILE) ranges.splice(0, ranges.length - MAX_RANGES_PER_FILE);
363
- _fileLineRanges.set(key, ranges);
364
- }
365
- const entryKey = resolveFilesKey(normalized);
366
- const entry = _files.get(entryKey);
367
- const identity = statIdentity(normalized);
368
- if (entry && identity) _files.set(entryKey, { ...entry, rangeFileIdentity: identity });
369
- }
370
- function getFileLineRanges(filePath) {
371
- return _fileLineRanges.get(foldPath(normalizePath(filePath))) ?? [];
372
- }
373
- function resetFileLineRanges(filePath) {
374
- _fileLineRanges.delete(foldPath(normalizePath(filePath)));
375
- }
376
- var MAX_SERVED_OUTPUTS_PER_FILE = 8;
377
- var GENERIC_SERVED_OUTPUT_KEY = "\0<bash-generic-served>";
378
- var GENERIC_SERVED_OUTPUT_FOLDED_KEY = foldPath(normalizePath(GENERIC_SERVED_OUTPUT_KEY));
379
- var MAX_GENERIC_SERVED_OUTPUTS = 32;
380
- function recordFileServedOutput(filePath, outputId) {
381
- const key = foldPath(normalizePath(filePath));
382
- const cap = key === GENERIC_SERVED_OUTPUT_FOLDED_KEY ? MAX_GENERIC_SERVED_OUTPUTS : MAX_SERVED_OUTPUTS_PER_FILE;
383
- const ids = (_fileServedOutputs.get(key) ?? []).filter((id) => id !== outputId);
384
- ids.push(outputId);
385
- if (ids.length > cap) ids.splice(0, ids.length - cap);
386
- _fileServedOutputs.set(key, ids);
387
- }
388
- function getFileServedOutputs(filePath) {
389
- return _fileServedOutputs.get(foldPath(normalizePath(filePath))) ?? [];
390
- }
391
- function markFileTruncated(filePath, isFullRead = true) {
392
- const normalized = normalizePath(filePath);
393
- const key = resolveFilesKey(normalized);
394
- const prev = _files.get(key);
395
- const now = Date.now();
396
- if (prev === void 0) {
397
- _files.set(key, {
398
- path: key,
399
- readCount: 1,
400
- lastReadAt: now,
401
- wasEdited: false,
402
- sizeBytes: fileSize(normalized),
403
- wasTruncated: true,
404
- ...isFullRead ? { lastFullReadAt: now, fullReadCount: 1 } : {}
405
- });
406
- return;
407
- }
408
- _files.set(key, { ...prev, wasTruncated: true });
409
- }
410
- function wasFileTruncatedThisSession(filePath) {
411
- const entry = _files.get(resolveFilesKey(normalizePath(filePath)));
412
- return entry?.wasTruncated === true;
413
- }
414
- function generateSessionId() {
415
- try {
416
- return randomUUID();
417
- } catch {
418
- return randomBytes(16).toString("hex");
419
- }
420
- }
421
- function getSessionId() {
422
- if (_sessionId !== null) return _sessionId;
423
- const fromEnv = process.env["CLAUDE_CODE_SESSION_ID"];
424
- _sessionId = fromEnv !== void 0 && fromEnv !== "" ? fromEnv : generateSessionId();
425
- return _sessionId;
426
- }
427
- function setTranscriptPath(path4, sessionId) {
428
- if (path4 === "") return;
429
- _transcriptPath = { path: path4, sessionId };
430
- }
431
- function getTranscriptPath() {
432
- if (_transcriptPath === null) return void 0;
433
- return _transcriptPath.sessionId === getSessionId() ? _transcriptPath.path : void 0;
434
- }
435
- function exportSessionState() {
436
- return {
437
- files: Array.from(_files.values()),
438
- hintsShown: Array.from(_hintsShown),
439
- ..._scheduledPromptCounts.size > 0 ? { scheduledPromptCounts: Array.from(_scheduledPromptCounts.entries()) } : {},
440
- webFetches: Array.from(_webFetches.entries()),
441
- bashOutputs: Array.from(_bashOutputs.entries()),
442
- bashReruns: Array.from(_bashReruns),
443
- curlDownloads: Array.from(_curlDownloads.entries()),
444
- fileLineRanges: Array.from(_fileLineRanges.entries()),
445
- ..._fileServedOutputs.size > 0 ? { fileServedOutputs: Array.from(_fileServedOutputs.entries()) } : {},
446
- cliReads: Array.from(_cliReads),
447
- pendingLargeFileHints: Array.from(_pendingLargeFileHints.entries()),
448
- grepQueries: Array.from(_grepQueries.entries()),
449
- globQueries: Array.from(_globQueries.entries()),
450
- outstandingAgentSpawns: _outstandingAgentSpawns.map((e) => [e.prompt, e.ts]),
451
- ..._lastTabContext !== null ? { lastTabContextDigest: _lastTabContext } : {},
452
- ..._seenImageHashes.length > 0 ? { seenImageHashes: [..._seenImageHashes] } : {},
453
- ..._compactedAt > 0 ? { compactedAt: _compactedAt } : {}
454
- };
455
- }
456
- function importSessionState(s) {
457
- _files = /* @__PURE__ */ new Map();
458
- for (const e of s.files) {
459
- if (e && typeof e.path === "string") _files.set(e.path, e);
460
- }
461
- _filesAtLoad = new Map(Array.from(_files, ([key, e]) => [key, e.readCount]));
462
- _filesFullReadCountAtLoad = new Map(Array.from(_files, ([key, e]) => [key, e.fullReadCount ?? 0]));
463
- _hintsShown = new Set(s.hintsShown);
464
- _scheduledPromptCounts = new Map(s.scheduledPromptCounts ?? []);
465
- _webFetches = new Map(s.webFetches);
466
- _bashOutputs = new Map(s.bashOutputs);
467
- _bashReruns = new Set(s.bashReruns ?? []);
468
- _curlDownloads = new Map(s.curlDownloads);
469
- _curlDownloadsAtLoad = new Map(_curlDownloads);
470
- _fileLineRanges = new Map(s.fileLineRanges ?? []);
471
- _fileLineRangesAtLoad = new Map(_fileLineRanges);
472
- _fileServedOutputs = new Map(s.fileServedOutputs ?? []);
473
- _fileServedOutputsAtLoad = new Map(_fileServedOutputs);
474
- _cliReads = new Set(s.cliReads ?? []);
475
- _pendingLargeFileHints = new Map(s.pendingLargeFileHints ?? []);
476
- _pendingLargeFileHintsAtLoad = new Map(_pendingLargeFileHints);
477
- _grepQueries = new Map(s.grepQueries ?? []);
478
- _globQueries = new Map(s.globQueries ?? []);
479
- _outstandingAgentSpawns = (s.outstandingAgentSpawns ?? []).map(([prompt, ts]) => ({ prompt, ts }));
480
- _outstandingAgentSpawnsAtLoad = [..._outstandingAgentSpawns];
481
- _lastTabContext = s.lastTabContextDigest ?? null;
482
- _seenImageHashes = [...s.seenImageHashes ?? []];
483
- _compactedAt = s.compactedAt ?? 0;
484
- }
485
- registerReset(() => {
486
- _files = /* @__PURE__ */ new Map();
487
- _filesAtLoad = /* @__PURE__ */ new Map();
488
- _filesFullReadCountAtLoad = /* @__PURE__ */ new Map();
489
- _hintsShown = /* @__PURE__ */ new Set();
490
- _scheduledPromptCounts = /* @__PURE__ */ new Map();
491
- _webFetches = /* @__PURE__ */ new Map();
492
- _bashOutputs = /* @__PURE__ */ new Map();
493
- _bashReruns = /* @__PURE__ */ new Set();
494
- _curlDownloads = /* @__PURE__ */ new Map();
495
- _curlDownloadsAtLoad = /* @__PURE__ */ new Map();
496
- _fileLineRanges = /* @__PURE__ */ new Map();
497
- _fileLineRangesAtLoad = /* @__PURE__ */ new Map();
498
- _fileServedOutputs = /* @__PURE__ */ new Map();
499
- _fileServedOutputsAtLoad = /* @__PURE__ */ new Map();
500
- _cliReads = /* @__PURE__ */ new Set();
501
- _pendingLargeFileHints = /* @__PURE__ */ new Map();
502
- _pendingLargeFileHintsAtLoad = /* @__PURE__ */ new Map();
503
- _grepQueries = /* @__PURE__ */ new Map();
504
- _globQueries = /* @__PURE__ */ new Map();
505
- _outstandingAgentSpawns = [];
506
- _outstandingAgentSpawnsAtLoad = [];
507
- _lastTabContext = null;
508
- _seenImageHashes = [];
509
- _compactedAt = 0;
510
- _sessionId = null;
511
- _transcriptPath = null;
512
- });
513
-
514
72
  // src/sessions_dir.ts
515
73
  init_define_import_meta_env();
516
74
  import * as path from "node:path";
@@ -522,7 +80,7 @@ function sessionsDir() {
522
80
  // src/session_store.ts
523
81
  init_define_import_meta_env();
524
82
  import { createHash } from "node:crypto";
525
- import * as fs2 from "node:fs";
83
+ import * as fs from "node:fs";
526
84
  import * as path2 from "node:path";
527
85
  var MAX_FILES = 500;
528
86
  var AGENT_SALT_MARKER = sanitizeIdForFilename(":agent:");
@@ -547,6 +105,7 @@ function sessionSidecarPath(sessionId, suffix) {
547
105
  const safe = sessionFileStem(sessionId);
548
106
  if (!safe) return null;
549
107
  if (suffix.includes("/") || suffix.includes("\\") || suffix.includes("..")) return null;
108
+ if (suffix !== ".json" && suffix.endsWith(".json")) return null;
550
109
  const dir = sessionsDir();
551
110
  const candidate = path2.join(dir, `${safe}${suffix}`);
552
111
  try {
@@ -738,14 +297,14 @@ function mergeLineRanges(disk, mem) {
738
297
  }
739
298
  return Array.from(byPath.entries());
740
299
  }
741
- var GENERIC_SERVED_OUTPUT_FOLDED_KEY2 = foldPath(normalizePath(GENERIC_SERVED_OUTPUT_KEY));
300
+ var GENERIC_SERVED_OUTPUT_FOLDED_KEY = foldPath(normalizePath(GENERIC_SERVED_OUTPUT_KEY));
742
301
  function mergeServedOutputs(disk, mem) {
743
302
  const byPath = /* @__PURE__ */ new Map();
744
303
  for (const [filePath, ids] of disk) byPath.set(filePath, [...ids]);
745
304
  for (const [filePath, ids] of mem) {
746
305
  const prev = byPath.get(filePath) ?? [];
747
306
  const merged = [...prev.filter((id) => !ids.includes(id)), ...ids];
748
- const cap = filePath === GENERIC_SERVED_OUTPUT_FOLDED_KEY2 ? MAX_GENERIC_SERVED_OUTPUTS : MAX_SERVED_OUTPUTS_PER_FILE;
307
+ const cap = filePath === GENERIC_SERVED_OUTPUT_FOLDED_KEY ? MAX_GENERIC_SERVED_OUTPUTS : MAX_SERVED_OUTPUTS_PER_FILE;
749
308
  if (merged.length > cap) merged.splice(0, merged.length - cap);
750
309
  byPath.set(filePath, merged);
751
310
  }
@@ -838,8 +397,23 @@ function capFiles(s, max) {
838
397
  }
839
398
  function readDiskState(p) {
840
399
  try {
841
- if (!fs2.existsSync(p)) return null;
842
- return coerce(JSON.parse(fs2.readFileSync(p, "utf8")));
400
+ return readDiskStateForMerge(p);
401
+ } catch {
402
+ return null;
403
+ }
404
+ }
405
+ function readDiskStateForMerge(p) {
406
+ let text = "";
407
+ try {
408
+ withRetryOnLock(() => {
409
+ text = fs.readFileSync(p, "utf8");
410
+ });
411
+ } catch (err) {
412
+ if (err.code === "ENOENT") return null;
413
+ throw err;
414
+ }
415
+ try {
416
+ return coerce(JSON.parse(text));
843
417
  } catch {
844
418
  return null;
845
419
  }
@@ -856,8 +430,8 @@ function listSiblingSessionStates(sessionId) {
856
430
  const dir = sessionsDir();
857
431
  const out = [];
858
432
  try {
859
- if (!fs2.existsSync(dir)) return out;
860
- for (const file of fs2.readdirSync(dir)) {
433
+ if (!fs.existsSync(dir)) return out;
434
+ for (const file of fs.readdirSync(dir)) {
861
435
  if (!file.endsWith(".json") || !file.startsWith(prefix)) continue;
862
436
  const state = readDiskState(path2.join(dir, file));
863
437
  if (state !== null) out.push(state);
@@ -867,22 +441,20 @@ function listSiblingSessionStates(sessionId) {
867
441
  }
868
442
  return out;
869
443
  }
444
+ var EMPTY_SESSION = { files: [], hintsShown: [], webFetches: [], bashOutputs: [], curlDownloads: [] };
870
445
  function loadSessionState(sessionId) {
871
446
  const p = sessionPath(sessionId);
872
- if (!p) return;
873
- const disk = readDiskState(p);
874
- if (disk === null) return;
875
- importSessionState(disk);
447
+ importSessionState((p ? readDiskState(p) : null) ?? EMPTY_SESSION);
876
448
  }
877
449
  function saveSessionState(sessionId) {
878
450
  const p = sessionPath(sessionId);
879
451
  if (!p) return;
880
452
  try {
881
453
  const dir = path2.dirname(p);
882
- if (!fs2.existsSync(dir)) ensureDirSync(dir);
454
+ if (!fs.existsSync(dir)) ensureDirSync(dir);
883
455
  const mem = exportSessionState();
884
456
  const writeMerged = () => {
885
- const disk = readDiskState(p);
457
+ const disk = readDiskStateForMerge(p);
886
458
  const merged = capFiles(disk ? mergeSessionState(disk, mem) : mem, MAX_FILES);
887
459
  if (merged.created_ts === void 0) merged.created_ts = Date.now() / 1e3;
888
460
  let json;
@@ -901,9 +473,9 @@ function saveSessionState(sessionId) {
901
473
 
902
474
  // src/skill_cache.ts
903
475
  init_define_import_meta_env();
904
- import * as fs3 from "fs/promises";
476
+ import * as fs2 from "fs/promises";
905
477
  import { resolve } from "path";
906
- import { readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2, statSync as statSync2, unlinkSync } from "node:fs";
478
+ import { readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2, statSync, unlinkSync } from "node:fs";
907
479
  var COMPACT_END_MARKER = "<!-- COMPACT_END -->";
908
480
  var SKILLS_OUTPUT_SUBDIR = "skills";
909
481
  var _skillOutputsDirOverride = null;
@@ -1068,14 +640,14 @@ function extractChecklistSection(body) {
1068
640
  async function listOutputs() {
1069
641
  try {
1070
642
  const dir = skillOutputsDir();
1071
- const entries = await fs3.readdir(dir, { withFileTypes: true });
643
+ const entries = await fs2.readdir(dir, { withFileTypes: true });
1072
644
  const metas = [];
1073
645
  for (const entry of entries) {
1074
646
  if (!entry.isFile() || !entry.name.endsWith(".meta")) {
1075
647
  continue;
1076
648
  }
1077
649
  try {
1078
- const content = await fs3.readFile(resolve(dir, entry.name), "utf-8");
650
+ const content = await fs2.readFile(resolve(dir, entry.name), "utf-8");
1079
651
  const meta = JSON.parse(content);
1080
652
  metas.push(meta);
1081
653
  } catch {
@@ -1126,7 +698,7 @@ async function findCrossSessionEntry(skillName, contentSha) {
1126
698
  const dir = skillOutputsDir();
1127
699
  const bodyPath = resolve(dir, `${meta.outputId}.txt`);
1128
700
  try {
1129
- const bodyExists = await fs3.access(bodyPath).then(() => true).catch(() => false);
701
+ const bodyExists = await fs2.access(bodyPath).then(() => true).catch(() => false);
1130
702
  if (bodyExists) {
1131
703
  return meta;
1132
704
  }
@@ -1262,7 +834,7 @@ async function readSkillHits(skillName) {
1262
834
  if (!name) return { count: 0, lastTs: 0 };
1263
835
  const dir = skillOutputsDir();
1264
836
  const hitsFile = resolve(dir, `${sanitizeSkillId(name)}.hits`);
1265
- const content = await fs3.readFile(hitsFile, "utf-8").catch(() => null);
837
+ const content = await fs2.readFile(hitsFile, "utf-8").catch(() => null);
1266
838
  if (content) {
1267
839
  const parsed = JSON.parse(content);
1268
840
  return parsed;
@@ -1290,14 +862,14 @@ function runExclusiveInProcess(key, fn) {
1290
862
  async function acquireSkillHitLock(lockPath) {
1291
863
  for (let attempt = 0; attempt < SKILL_HIT_LOCK_MAX_ATTEMPTS; attempt++) {
1292
864
  try {
1293
- await fs3.mkdir(lockPath);
865
+ await fs2.mkdir(lockPath);
1294
866
  return true;
1295
867
  } catch (err) {
1296
868
  if (err.code !== "EEXIST") return false;
1297
869
  try {
1298
- const st = await fs3.stat(lockPath);
870
+ const st = await fs2.stat(lockPath);
1299
871
  if (Date.now() - st.mtimeMs > SKILL_HIT_LOCK_STALE_MS) {
1300
- await fs3.rmdir(lockPath).catch(() => {
872
+ await fs2.rmdir(lockPath).catch(() => {
1301
873
  });
1302
874
  continue;
1303
875
  }
@@ -1326,7 +898,7 @@ async function incrementSkillHit(skillName) {
1326
898
  hits.lastTs = Date.now();
1327
899
  await atomicWriteText(hitsFile, JSON.stringify(hits, null, 2));
1328
900
  } finally {
1329
- await fs3.rmdir(lockPath).catch(() => {
901
+ await fs2.rmdir(lockPath).catch(() => {
1330
902
  });
1331
903
  }
1332
904
  });
@@ -1362,14 +934,14 @@ async function listSkills(sessionId) {
1362
934
  let compactLen = 0;
1363
935
  let compactText = "";
1364
936
  try {
1365
- const stat2 = await fs3.stat(resolve(dir, compactFileId));
937
+ const stat2 = await fs2.stat(resolve(dir, compactFileId));
1366
938
  compactLen = stat2.size;
1367
- compactText = await fs3.readFile(resolve(dir, compactFileId), "utf-8").catch(() => "");
939
+ compactText = await fs2.readFile(resolve(dir, compactFileId), "utf-8").catch(() => "");
1368
940
  } catch {
1369
941
  compactLen = 0;
1370
942
  }
1371
943
  const hasMarker = extractCompactFromMarker(
1372
- await fs3.readFile(resolve(dir, `${meta.outputId}.txt`), "utf-8").catch(() => "")
944
+ await fs2.readFile(resolve(dir, `${meta.outputId}.txt`), "utf-8").catch(() => "")
1373
945
  ) !== null;
1374
946
  const compactStale = isCompactStale(compactText, meta.skillName, meta.contentSha);
1375
947
  const { count: hitCount } = await readSkillHits(meta.skillName);
@@ -1408,7 +980,7 @@ async function resolvePluginSkillPath(pluginName, skillSlug) {
1408
980
  const manifestPath = _pluginsManifestPathOverride ?? resolve(claudeConfigDir(), "plugins", "installed_plugins.json");
1409
981
  let raw;
1410
982
  try {
1411
- raw = await fs3.readFile(manifestPath, "utf8");
983
+ raw = await fs2.readFile(manifestPath, "utf8");
1412
984
  } catch {
1413
985
  return null;
1414
986
  }
@@ -1430,7 +1002,7 @@ async function resolvePluginSkillPath(pluginName, skillSlug) {
1430
1002
  if (typeof installPath !== "string" || installPath === "") continue;
1431
1003
  const diskPath = resolve(installPath, "skills", skillSlug, "SKILL.md");
1432
1004
  try {
1433
- await fs3.access(diskPath);
1005
+ await fs2.access(diskPath);
1434
1006
  return diskPath;
1435
1007
  } catch {
1436
1008
  continue;
@@ -1449,7 +1021,7 @@ async function installedSkillPath(skillName) {
1449
1021
  }
1450
1022
  const diskPath = resolve(skillsSourceDir(), name, "SKILL.md");
1451
1023
  try {
1452
- await fs3.access(diskPath);
1024
+ await fs2.access(diskPath);
1453
1025
  return diskPath;
1454
1026
  } catch {
1455
1027
  return null;
@@ -1471,7 +1043,7 @@ function pruneSkillOutputs(maxCount = DEFAULT_MAX_COUNT, maxAgeMs = DEFAULT_MAX_
1471
1043
  ts = parsed.ts;
1472
1044
  } catch {
1473
1045
  try {
1474
- ts = statSync2(resolve(dir, file)).mtimeMs;
1046
+ ts = statSync(resolve(dir, file)).mtimeMs;
1475
1047
  } catch {
1476
1048
  continue;
1477
1049
  }
@@ -1509,7 +1081,7 @@ function pruneSkillOutputs(maxCount = DEFAULT_MAX_COUNT, maxAgeMs = DEFAULT_MAX_
1509
1081
 
1510
1082
  // src/compact.ts
1511
1083
  init_define_import_meta_env();
1512
- import * as fs4 from "node:fs";
1084
+ import * as fs3 from "node:fs";
1513
1085
  import * as path3 from "node:path";
1514
1086
  var CONTEXT_AUTOCOMPACT_TOKENS = 66e4;
1515
1087
  var CATALOG_TOKENS = 10800;
@@ -1747,10 +1319,10 @@ function isNoisePath(inputPath) {
1747
1319
  function findLatestSessionId() {
1748
1320
  try {
1749
1321
  const sessionsDir2 = path3.join(tokenGoatHome(), "sessions");
1750
- if (!fs4.existsSync(sessionsDir2)) {
1322
+ if (!fs3.existsSync(sessionsDir2)) {
1751
1323
  return null;
1752
1324
  }
1753
- const files = fs4.readdirSync(sessionsDir2);
1325
+ const files = fs3.readdirSync(sessionsDir2);
1754
1326
  const jsonFiles = files.filter((f) => f.endsWith(".json") && !f.includes(AGENT_SALT_MARKER));
1755
1327
  if (jsonFiles.length === 0) {
1756
1328
  return null;
@@ -1760,9 +1332,9 @@ function findLatestSessionId() {
1760
1332
  return null;
1761
1333
  }
1762
1334
  let latestFile = firstFile;
1763
- let latestMtime = fs4.statSync(path3.join(sessionsDir2, firstFile)).mtimeMs;
1335
+ let latestMtime = fs3.statSync(path3.join(sessionsDir2, firstFile)).mtimeMs;
1764
1336
  for (const file of jsonFiles) {
1765
- const mtime = fs4.statSync(path3.join(sessionsDir2, file)).mtimeMs;
1337
+ const mtime = fs3.statSync(path3.join(sessionsDir2, file)).mtimeMs;
1766
1338
  if (mtime > latestMtime) {
1767
1339
  latestFile = file;
1768
1340
  latestMtime = mtime;
@@ -1785,7 +1357,7 @@ function writeSessionManifest(projectHash, sessionId, manifestJson) {
1785
1357
  const safeSessionId = sessionFileStem(sessionId);
1786
1358
  if (!safeSessionId) return;
1787
1359
  const sessionsDir2 = path3.join(dataDir(), "projects", projectHash, "sessions");
1788
- if (!fs4.existsSync(sessionsDir2)) {
1360
+ if (!fs3.existsSync(sessionsDir2)) {
1789
1361
  ensureDirSync(sessionsDir2);
1790
1362
  }
1791
1363
  const dest = path3.join(sessionsDir2, `${safeSessionId}.json`);
@@ -1793,28 +1365,28 @@ function writeSessionManifest(projectHash, sessionId, manifestJson) {
1793
1365
  }
1794
1366
  function readAllSessionManifests(projectHash, maxAgeSecs = 3600) {
1795
1367
  const sessionsDir2 = path3.join(dataDir(), "projects", projectHash, "sessions");
1796
- if (!fs4.existsSync(sessionsDir2)) {
1368
+ if (!fs3.existsSync(sessionsDir2)) {
1797
1369
  return [];
1798
1370
  }
1799
1371
  const now = Date.now() / 1e3;
1800
1372
  const results = [];
1801
1373
  try {
1802
- const files = fs4.readdirSync(sessionsDir2);
1374
+ const files = fs3.readdirSync(sessionsDir2);
1803
1375
  for (const file of files) {
1804
1376
  if (!file.endsWith(".json")) {
1805
1377
  continue;
1806
1378
  }
1807
1379
  try {
1808
1380
  const fullPath = path3.join(sessionsDir2, file);
1809
- const stat2 = fs4.statSync(fullPath);
1381
+ const stat2 = fs3.statSync(fullPath);
1810
1382
  if (now - stat2.mtimeMs / 1e3 > maxAgeSecs) {
1811
1383
  try {
1812
- fs4.unlinkSync(fullPath);
1384
+ fs3.unlinkSync(fullPath);
1813
1385
  } catch {
1814
1386
  }
1815
1387
  continue;
1816
1388
  }
1817
- const text = fs4.readFileSync(fullPath, "utf8");
1389
+ const text = fs3.readFileSync(fullPath, "utf8");
1818
1390
  const data = JSON.parse(text);
1819
1391
  if (typeof data === "object" && data !== null && "files" in data) {
1820
1392
  results.push(data);
@@ -1901,56 +1473,6 @@ function computeAdaptiveBudget(cache, ageSecs = 0, opts) {
1901
1473
  }
1902
1474
 
1903
1475
  export {
1904
- recordFileRead,
1905
- recordSymbolRead,
1906
- recordFileEdit,
1907
- getSessionFiles,
1908
- wasFileReadThisSession,
1909
- wasFileFullyReadThisSession,
1910
- getCompactedAt,
1911
- markCompacted,
1912
- getSessionFileEntry,
1913
- wasHintShown,
1914
- markHintShown,
1915
- recordScheduledPrompt,
1916
- wasCliReadThisSession,
1917
- recordCliRead,
1918
- recordLargeFileHintPending,
1919
- takePendingLargeFileHint,
1920
- WEB_FETCH_KEY_SEP,
1921
- recordWebFetch,
1922
- getSessionWebFetches,
1923
- recordBashOutput,
1924
- getSessionBashOutputs,
1925
- recordBashRerun,
1926
- getSessionBashReruns,
1927
- getBashOutputId,
1928
- recordGrepQuery,
1929
- getGrepMatchCount,
1930
- recordGlobQuery,
1931
- getGlobMatchCount,
1932
- setLastTabContext,
1933
- lastTabContextMatches,
1934
- hasSeenImage,
1935
- recordSeenImage,
1936
- recordOutstandingAgentSpawn,
1937
- getOutstandingAgentSpawns,
1938
- removeOutstandingAgentSpawn,
1939
- recordCurlDownload,
1940
- getCurlDownloadPath,
1941
- clearCurlDownload,
1942
- recordFileLineRange,
1943
- getFileLineRanges,
1944
- resetFileLineRanges,
1945
- GENERIC_SERVED_OUTPUT_KEY,
1946
- recordFileServedOutput,
1947
- getFileServedOutputs,
1948
- markFileTruncated,
1949
- wasFileTruncatedThisSession,
1950
- getSessionId,
1951
- setTranscriptPath,
1952
- getTranscriptPath,
1953
- exportSessionState,
1954
1476
  SESSIONS_SUBDIR,
1955
1477
  sessionsDir,
1956
1478
  AGENT_SALT_MARKER,