token-goat 2.9.26 → 2.9.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -88
- package/SECURITY.md +14 -0
- package/dist/{token-goat-chunk-CQHY4SL7.mjs → token-goat-chunk-4JJBFT7V.mjs} +3 -3
- package/dist/token-goat-chunk-4JMWPWCS.mjs +96 -0
- package/dist/token-goat-chunk-4RN64ZND.mjs +954 -0
- package/dist/{token-goat-chunk-5M3NRJD2.mjs → token-goat-chunk-4STDIGYC.mjs} +2 -2
- package/dist/{token-goat-chunk-BH4ZVRB2.mjs → token-goat-chunk-5NNYIUGV.mjs} +2 -2
- package/dist/{token-goat-chunk-LHUP4DXZ.mjs → token-goat-chunk-66LODAUT.mjs} +1 -1
- package/dist/{token-goat-chunk-M6CVNHTW.mjs → token-goat-chunk-6CCQDAYY.mjs} +69 -566
- package/dist/{token-goat-chunk-62IHOU6L.mjs → token-goat-chunk-6DQNNFJ6.mjs} +5 -3
- package/dist/{token-goat-chunk-H2CPLEMP.mjs → token-goat-chunk-6SGLIPQB.mjs} +40 -20
- package/dist/{token-goat-chunk-MBDJR6HU.mjs → token-goat-chunk-6Z5ULNE5.mjs} +3570 -3970
- package/dist/token-goat-chunk-7MAFDRVR.mjs +47 -0
- package/dist/{token-goat-chunk-POOI26O6.mjs → token-goat-chunk-7R2XYKC5.mjs} +6 -5
- package/dist/{token-goat-chunk-E6B2UFDF.mjs → token-goat-chunk-BCN2YQC6.mjs} +10 -8
- package/dist/token-goat-chunk-BJBRGPBX.mjs +244 -0
- package/dist/{token-goat-chunk-TG5ZPD6B.mjs → token-goat-chunk-CBMY2FGI.mjs} +479 -544
- package/dist/{token-goat-chunk-LRIZ7K3F.mjs → token-goat-chunk-CC2PYJM7.mjs} +2 -1
- package/dist/{token-goat-chunk-7EPYB34H.mjs → token-goat-chunk-D5ICEPSB.mjs} +14 -14
- package/dist/token-goat-chunk-D7GHQKQD.mjs +30 -0
- package/dist/{token-goat-chunk-JALB3KWJ.mjs → token-goat-chunk-EL7M26WP.mjs} +7623 -8462
- package/dist/{token-goat-chunk-ZZT6PVB3.mjs → token-goat-chunk-F7QZRIWM.mjs} +69 -20
- package/dist/{token-goat-chunk-FLEYOCAS.mjs → token-goat-chunk-FSTWAOW6.mjs} +3 -3
- package/dist/token-goat-chunk-GGLEE35R.mjs +564 -0
- package/dist/{token-goat-chunk-IKZLSRII.mjs → token-goat-chunk-HUDC5GS5.mjs} +2 -2
- package/dist/{token-goat-chunk-43JFN26X.mjs → token-goat-chunk-HXNAC4ZF.mjs} +22 -964
- package/dist/token-goat-chunk-I7CB3X4K.mjs +1379 -0
- package/dist/{token-goat-chunk-GKZ2US5B.mjs → token-goat-chunk-IFORDBGC.mjs} +32 -27
- package/dist/{token-goat-chunk-CXBOFPF4.mjs → token-goat-chunk-IHKZ3QNA.mjs} +26 -15
- package/dist/token-goat-chunk-IZXKVT4A.mjs +711 -0
- package/dist/{token-goat-chunk-PAV6NNY7.mjs → token-goat-chunk-JXK2HQXS.mjs} +22 -8
- package/dist/{token-goat-chunk-6E2IDLHF.mjs → token-goat-chunk-L45ZQRT7.mjs} +1 -1
- package/dist/{token-goat-chunk-MDV5VWF4.mjs → token-goat-chunk-L7SDVGBT.mjs} +196 -14
- package/dist/token-goat-chunk-LEG3JNJ6.mjs +139 -0
- package/dist/{token-goat-chunk-7SXPJOSZ.mjs → token-goat-chunk-M56BWPBN.mjs} +1 -1
- package/dist/{token-goat-chunk-G6EYO5CD.mjs → token-goat-chunk-MAMQPC43.mjs} +2 -87
- package/dist/{token-goat-chunk-VVROQBQJ.mjs → token-goat-chunk-MMLMALWK.mjs} +5 -3
- package/dist/{token-goat-chunk-D2X7XN5M.mjs → token-goat-chunk-MVSWBNMD.mjs} +7 -231
- package/dist/{token-goat-chunk-C2PG4K5D.mjs → token-goat-chunk-NILVK7XM.mjs} +4 -4
- package/dist/{token-goat-chunk-BAWKGODL.mjs → token-goat-chunk-Q4S3UQGO.mjs} +1 -1
- package/dist/{token-goat-chunk-MWID3YOY.mjs → token-goat-chunk-QM76S6YS.mjs} +3 -3
- package/dist/{token-goat-chunk-4GEDH2WU.mjs → token-goat-chunk-RJH64KQH.mjs} +81 -70
- package/dist/{token-goat-chunk-STYRLQIW.mjs → token-goat-chunk-RSS3TLXU.mjs} +2 -2
- package/dist/{token-goat-chunk-5BQ7W7D7.mjs → token-goat-chunk-SJEKA7Y2.mjs} +21 -16
- package/dist/{token-goat-chunk-RIB6XY2V.mjs → token-goat-chunk-UBUKHVYW.mjs} +1 -1
- package/dist/{token-goat-chunk-7Y6GWTII.mjs → token-goat-chunk-VE27HPIF.mjs} +14 -10
- package/dist/{token-goat-chunk-RH27ZSPF.mjs → token-goat-chunk-VWZKZPSR.mjs} +100 -23
- package/dist/{token-goat-chunk-L45IWWMC.mjs → token-goat-chunk-XI2VFAV6.mjs} +6 -6
- package/dist/{token-goat-chunk-WNBSCSAI.mjs → token-goat-chunk-XKY4VKJ4.mjs} +1 -1
- package/dist/{token-goat-chunk-L43RKNHA.mjs → token-goat-chunk-YWSP6IU7.mjs} +1 -1
- package/dist/token-goat-hook.mjs +23 -17
- package/dist/token-goat.core.mjs +32 -27
- package/docs/cli.md +32 -21
- package/docs/install.md +2 -0
- package/package.json +1 -1
- package/dist/token-goat-chunk-ADMR3QVF.mjs +0 -41
- package/dist/token-goat-chunk-MZTO4FXH.mjs +0 -26
|
@@ -1,21 +1,46 @@
|
|
|
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-GGLEE35R.mjs";
|
|
3
26
|
import {
|
|
4
27
|
claudeConfigDir,
|
|
5
28
|
readTranscriptTail
|
|
6
|
-
} from "./token-goat-chunk-
|
|
29
|
+
} from "./token-goat-chunk-MAMQPC43.mjs";
|
|
7
30
|
import {
|
|
8
31
|
DEFAULT_MAX_AGE_MS,
|
|
9
|
-
DEFAULT_MAX_COUNT
|
|
32
|
+
DEFAULT_MAX_COUNT
|
|
33
|
+
} from "./token-goat-chunk-BJBRGPBX.mjs";
|
|
34
|
+
import {
|
|
10
35
|
recordStat,
|
|
11
36
|
redactSecrets
|
|
12
|
-
} from "./token-goat-chunk-
|
|
37
|
+
} from "./token-goat-chunk-MVSWBNMD.mjs";
|
|
13
38
|
import {
|
|
14
39
|
detectHarness,
|
|
15
40
|
isAutoTriggerMultiplierExplicit,
|
|
16
41
|
loadConfig,
|
|
17
42
|
shortFingerprint
|
|
18
|
-
} from "./token-goat-chunk-
|
|
43
|
+
} from "./token-goat-chunk-CC2PYJM7.mjs";
|
|
19
44
|
import {
|
|
20
45
|
registerReset
|
|
21
46
|
} from "./token-goat-chunk-EEIDFMEM.mjs";
|
|
@@ -31,7 +56,7 @@ import {
|
|
|
31
56
|
stripLower,
|
|
32
57
|
tokenGoatHome,
|
|
33
58
|
withFileLock
|
|
34
|
-
} from "./token-goat-chunk-
|
|
59
|
+
} from "./token-goat-chunk-L45ZQRT7.mjs";
|
|
35
60
|
import {
|
|
36
61
|
normalizePath
|
|
37
62
|
} from "./token-goat-chunk-NMTKNYGF.mjs";
|
|
@@ -39,478 +64,6 @@ import {
|
|
|
39
64
|
init_define_import_meta_env
|
|
40
65
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
41
66
|
|
|
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
67
|
// src/sessions_dir.ts
|
|
515
68
|
init_define_import_meta_env();
|
|
516
69
|
import * as path from "node:path";
|
|
@@ -522,7 +75,7 @@ function sessionsDir() {
|
|
|
522
75
|
// src/session_store.ts
|
|
523
76
|
init_define_import_meta_env();
|
|
524
77
|
import { createHash } from "node:crypto";
|
|
525
|
-
import * as
|
|
78
|
+
import * as fs from "node:fs";
|
|
526
79
|
import * as path2 from "node:path";
|
|
527
80
|
var MAX_FILES = 500;
|
|
528
81
|
var AGENT_SALT_MARKER = sanitizeIdForFilename(":agent:");
|
|
@@ -547,6 +100,7 @@ function sessionSidecarPath(sessionId, suffix) {
|
|
|
547
100
|
const safe = sessionFileStem(sessionId);
|
|
548
101
|
if (!safe) return null;
|
|
549
102
|
if (suffix.includes("/") || suffix.includes("\\") || suffix.includes("..")) return null;
|
|
103
|
+
if (suffix !== ".json" && suffix.endsWith(".json")) return null;
|
|
550
104
|
const dir = sessionsDir();
|
|
551
105
|
const candidate = path2.join(dir, `${safe}${suffix}`);
|
|
552
106
|
try {
|
|
@@ -738,14 +292,14 @@ function mergeLineRanges(disk, mem) {
|
|
|
738
292
|
}
|
|
739
293
|
return Array.from(byPath.entries());
|
|
740
294
|
}
|
|
741
|
-
var
|
|
295
|
+
var GENERIC_SERVED_OUTPUT_FOLDED_KEY = foldPath(normalizePath(GENERIC_SERVED_OUTPUT_KEY));
|
|
742
296
|
function mergeServedOutputs(disk, mem) {
|
|
743
297
|
const byPath = /* @__PURE__ */ new Map();
|
|
744
298
|
for (const [filePath, ids] of disk) byPath.set(filePath, [...ids]);
|
|
745
299
|
for (const [filePath, ids] of mem) {
|
|
746
300
|
const prev = byPath.get(filePath) ?? [];
|
|
747
301
|
const merged = [...prev.filter((id) => !ids.includes(id)), ...ids];
|
|
748
|
-
const cap = filePath ===
|
|
302
|
+
const cap = filePath === GENERIC_SERVED_OUTPUT_FOLDED_KEY ? MAX_GENERIC_SERVED_OUTPUTS : MAX_SERVED_OUTPUTS_PER_FILE;
|
|
749
303
|
if (merged.length > cap) merged.splice(0, merged.length - cap);
|
|
750
304
|
byPath.set(filePath, merged);
|
|
751
305
|
}
|
|
@@ -838,8 +392,8 @@ function capFiles(s, max) {
|
|
|
838
392
|
}
|
|
839
393
|
function readDiskState(p) {
|
|
840
394
|
try {
|
|
841
|
-
if (!
|
|
842
|
-
return coerce(JSON.parse(
|
|
395
|
+
if (!fs.existsSync(p)) return null;
|
|
396
|
+
return coerce(JSON.parse(fs.readFileSync(p, "utf8")));
|
|
843
397
|
} catch {
|
|
844
398
|
return null;
|
|
845
399
|
}
|
|
@@ -856,8 +410,8 @@ function listSiblingSessionStates(sessionId) {
|
|
|
856
410
|
const dir = sessionsDir();
|
|
857
411
|
const out = [];
|
|
858
412
|
try {
|
|
859
|
-
if (!
|
|
860
|
-
for (const file of
|
|
413
|
+
if (!fs.existsSync(dir)) return out;
|
|
414
|
+
for (const file of fs.readdirSync(dir)) {
|
|
861
415
|
if (!file.endsWith(".json") || !file.startsWith(prefix)) continue;
|
|
862
416
|
const state = readDiskState(path2.join(dir, file));
|
|
863
417
|
if (state !== null) out.push(state);
|
|
@@ -867,19 +421,18 @@ function listSiblingSessionStates(sessionId) {
|
|
|
867
421
|
}
|
|
868
422
|
return out;
|
|
869
423
|
}
|
|
424
|
+
var EMPTY_SESSION = { files: [], hintsShown: [], webFetches: [], bashOutputs: [], curlDownloads: [] };
|
|
870
425
|
function loadSessionState(sessionId) {
|
|
871
426
|
const p = sessionPath(sessionId);
|
|
872
427
|
if (!p) return;
|
|
873
|
-
|
|
874
|
-
if (disk === null) return;
|
|
875
|
-
importSessionState(disk);
|
|
428
|
+
importSessionState(readDiskState(p) ?? EMPTY_SESSION);
|
|
876
429
|
}
|
|
877
430
|
function saveSessionState(sessionId) {
|
|
878
431
|
const p = sessionPath(sessionId);
|
|
879
432
|
if (!p) return;
|
|
880
433
|
try {
|
|
881
434
|
const dir = path2.dirname(p);
|
|
882
|
-
if (!
|
|
435
|
+
if (!fs.existsSync(dir)) ensureDirSync(dir);
|
|
883
436
|
const mem = exportSessionState();
|
|
884
437
|
const writeMerged = () => {
|
|
885
438
|
const disk = readDiskState(p);
|
|
@@ -901,9 +454,9 @@ function saveSessionState(sessionId) {
|
|
|
901
454
|
|
|
902
455
|
// src/skill_cache.ts
|
|
903
456
|
init_define_import_meta_env();
|
|
904
|
-
import * as
|
|
457
|
+
import * as fs2 from "fs/promises";
|
|
905
458
|
import { resolve } from "path";
|
|
906
|
-
import { readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2, statSync
|
|
459
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2, statSync, unlinkSync } from "node:fs";
|
|
907
460
|
var COMPACT_END_MARKER = "<!-- COMPACT_END -->";
|
|
908
461
|
var SKILLS_OUTPUT_SUBDIR = "skills";
|
|
909
462
|
var _skillOutputsDirOverride = null;
|
|
@@ -1068,14 +621,14 @@ function extractChecklistSection(body) {
|
|
|
1068
621
|
async function listOutputs() {
|
|
1069
622
|
try {
|
|
1070
623
|
const dir = skillOutputsDir();
|
|
1071
|
-
const entries = await
|
|
624
|
+
const entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
1072
625
|
const metas = [];
|
|
1073
626
|
for (const entry of entries) {
|
|
1074
627
|
if (!entry.isFile() || !entry.name.endsWith(".meta")) {
|
|
1075
628
|
continue;
|
|
1076
629
|
}
|
|
1077
630
|
try {
|
|
1078
|
-
const content = await
|
|
631
|
+
const content = await fs2.readFile(resolve(dir, entry.name), "utf-8");
|
|
1079
632
|
const meta = JSON.parse(content);
|
|
1080
633
|
metas.push(meta);
|
|
1081
634
|
} catch {
|
|
@@ -1126,7 +679,7 @@ async function findCrossSessionEntry(skillName, contentSha) {
|
|
|
1126
679
|
const dir = skillOutputsDir();
|
|
1127
680
|
const bodyPath = resolve(dir, `${meta.outputId}.txt`);
|
|
1128
681
|
try {
|
|
1129
|
-
const bodyExists = await
|
|
682
|
+
const bodyExists = await fs2.access(bodyPath).then(() => true).catch(() => false);
|
|
1130
683
|
if (bodyExists) {
|
|
1131
684
|
return meta;
|
|
1132
685
|
}
|
|
@@ -1262,7 +815,7 @@ async function readSkillHits(skillName) {
|
|
|
1262
815
|
if (!name) return { count: 0, lastTs: 0 };
|
|
1263
816
|
const dir = skillOutputsDir();
|
|
1264
817
|
const hitsFile = resolve(dir, `${sanitizeSkillId(name)}.hits`);
|
|
1265
|
-
const content = await
|
|
818
|
+
const content = await fs2.readFile(hitsFile, "utf-8").catch(() => null);
|
|
1266
819
|
if (content) {
|
|
1267
820
|
const parsed = JSON.parse(content);
|
|
1268
821
|
return parsed;
|
|
@@ -1290,14 +843,14 @@ function runExclusiveInProcess(key, fn) {
|
|
|
1290
843
|
async function acquireSkillHitLock(lockPath) {
|
|
1291
844
|
for (let attempt = 0; attempt < SKILL_HIT_LOCK_MAX_ATTEMPTS; attempt++) {
|
|
1292
845
|
try {
|
|
1293
|
-
await
|
|
846
|
+
await fs2.mkdir(lockPath);
|
|
1294
847
|
return true;
|
|
1295
848
|
} catch (err) {
|
|
1296
849
|
if (err.code !== "EEXIST") return false;
|
|
1297
850
|
try {
|
|
1298
|
-
const st = await
|
|
851
|
+
const st = await fs2.stat(lockPath);
|
|
1299
852
|
if (Date.now() - st.mtimeMs > SKILL_HIT_LOCK_STALE_MS) {
|
|
1300
|
-
await
|
|
853
|
+
await fs2.rmdir(lockPath).catch(() => {
|
|
1301
854
|
});
|
|
1302
855
|
continue;
|
|
1303
856
|
}
|
|
@@ -1326,7 +879,7 @@ async function incrementSkillHit(skillName) {
|
|
|
1326
879
|
hits.lastTs = Date.now();
|
|
1327
880
|
await atomicWriteText(hitsFile, JSON.stringify(hits, null, 2));
|
|
1328
881
|
} finally {
|
|
1329
|
-
await
|
|
882
|
+
await fs2.rmdir(lockPath).catch(() => {
|
|
1330
883
|
});
|
|
1331
884
|
}
|
|
1332
885
|
});
|
|
@@ -1362,14 +915,14 @@ async function listSkills(sessionId) {
|
|
|
1362
915
|
let compactLen = 0;
|
|
1363
916
|
let compactText = "";
|
|
1364
917
|
try {
|
|
1365
|
-
const stat2 = await
|
|
918
|
+
const stat2 = await fs2.stat(resolve(dir, compactFileId));
|
|
1366
919
|
compactLen = stat2.size;
|
|
1367
|
-
compactText = await
|
|
920
|
+
compactText = await fs2.readFile(resolve(dir, compactFileId), "utf-8").catch(() => "");
|
|
1368
921
|
} catch {
|
|
1369
922
|
compactLen = 0;
|
|
1370
923
|
}
|
|
1371
924
|
const hasMarker = extractCompactFromMarker(
|
|
1372
|
-
await
|
|
925
|
+
await fs2.readFile(resolve(dir, `${meta.outputId}.txt`), "utf-8").catch(() => "")
|
|
1373
926
|
) !== null;
|
|
1374
927
|
const compactStale = isCompactStale(compactText, meta.skillName, meta.contentSha);
|
|
1375
928
|
const { count: hitCount } = await readSkillHits(meta.skillName);
|
|
@@ -1408,7 +961,7 @@ async function resolvePluginSkillPath(pluginName, skillSlug) {
|
|
|
1408
961
|
const manifestPath = _pluginsManifestPathOverride ?? resolve(claudeConfigDir(), "plugins", "installed_plugins.json");
|
|
1409
962
|
let raw;
|
|
1410
963
|
try {
|
|
1411
|
-
raw = await
|
|
964
|
+
raw = await fs2.readFile(manifestPath, "utf8");
|
|
1412
965
|
} catch {
|
|
1413
966
|
return null;
|
|
1414
967
|
}
|
|
@@ -1430,7 +983,7 @@ async function resolvePluginSkillPath(pluginName, skillSlug) {
|
|
|
1430
983
|
if (typeof installPath !== "string" || installPath === "") continue;
|
|
1431
984
|
const diskPath = resolve(installPath, "skills", skillSlug, "SKILL.md");
|
|
1432
985
|
try {
|
|
1433
|
-
await
|
|
986
|
+
await fs2.access(diskPath);
|
|
1434
987
|
return diskPath;
|
|
1435
988
|
} catch {
|
|
1436
989
|
continue;
|
|
@@ -1449,7 +1002,7 @@ async function installedSkillPath(skillName) {
|
|
|
1449
1002
|
}
|
|
1450
1003
|
const diskPath = resolve(skillsSourceDir(), name, "SKILL.md");
|
|
1451
1004
|
try {
|
|
1452
|
-
await
|
|
1005
|
+
await fs2.access(diskPath);
|
|
1453
1006
|
return diskPath;
|
|
1454
1007
|
} catch {
|
|
1455
1008
|
return null;
|
|
@@ -1471,7 +1024,7 @@ function pruneSkillOutputs(maxCount = DEFAULT_MAX_COUNT, maxAgeMs = DEFAULT_MAX_
|
|
|
1471
1024
|
ts = parsed.ts;
|
|
1472
1025
|
} catch {
|
|
1473
1026
|
try {
|
|
1474
|
-
ts =
|
|
1027
|
+
ts = statSync(resolve(dir, file)).mtimeMs;
|
|
1475
1028
|
} catch {
|
|
1476
1029
|
continue;
|
|
1477
1030
|
}
|
|
@@ -1509,7 +1062,7 @@ function pruneSkillOutputs(maxCount = DEFAULT_MAX_COUNT, maxAgeMs = DEFAULT_MAX_
|
|
|
1509
1062
|
|
|
1510
1063
|
// src/compact.ts
|
|
1511
1064
|
init_define_import_meta_env();
|
|
1512
|
-
import * as
|
|
1065
|
+
import * as fs3 from "node:fs";
|
|
1513
1066
|
import * as path3 from "node:path";
|
|
1514
1067
|
var CONTEXT_AUTOCOMPACT_TOKENS = 66e4;
|
|
1515
1068
|
var CATALOG_TOKENS = 10800;
|
|
@@ -1747,10 +1300,10 @@ function isNoisePath(inputPath) {
|
|
|
1747
1300
|
function findLatestSessionId() {
|
|
1748
1301
|
try {
|
|
1749
1302
|
const sessionsDir2 = path3.join(tokenGoatHome(), "sessions");
|
|
1750
|
-
if (!
|
|
1303
|
+
if (!fs3.existsSync(sessionsDir2)) {
|
|
1751
1304
|
return null;
|
|
1752
1305
|
}
|
|
1753
|
-
const files =
|
|
1306
|
+
const files = fs3.readdirSync(sessionsDir2);
|
|
1754
1307
|
const jsonFiles = files.filter((f) => f.endsWith(".json") && !f.includes(AGENT_SALT_MARKER));
|
|
1755
1308
|
if (jsonFiles.length === 0) {
|
|
1756
1309
|
return null;
|
|
@@ -1760,9 +1313,9 @@ function findLatestSessionId() {
|
|
|
1760
1313
|
return null;
|
|
1761
1314
|
}
|
|
1762
1315
|
let latestFile = firstFile;
|
|
1763
|
-
let latestMtime =
|
|
1316
|
+
let latestMtime = fs3.statSync(path3.join(sessionsDir2, firstFile)).mtimeMs;
|
|
1764
1317
|
for (const file of jsonFiles) {
|
|
1765
|
-
const mtime =
|
|
1318
|
+
const mtime = fs3.statSync(path3.join(sessionsDir2, file)).mtimeMs;
|
|
1766
1319
|
if (mtime > latestMtime) {
|
|
1767
1320
|
latestFile = file;
|
|
1768
1321
|
latestMtime = mtime;
|
|
@@ -1785,7 +1338,7 @@ function writeSessionManifest(projectHash, sessionId, manifestJson) {
|
|
|
1785
1338
|
const safeSessionId = sessionFileStem(sessionId);
|
|
1786
1339
|
if (!safeSessionId) return;
|
|
1787
1340
|
const sessionsDir2 = path3.join(dataDir(), "projects", projectHash, "sessions");
|
|
1788
|
-
if (!
|
|
1341
|
+
if (!fs3.existsSync(sessionsDir2)) {
|
|
1789
1342
|
ensureDirSync(sessionsDir2);
|
|
1790
1343
|
}
|
|
1791
1344
|
const dest = path3.join(sessionsDir2, `${safeSessionId}.json`);
|
|
@@ -1793,28 +1346,28 @@ function writeSessionManifest(projectHash, sessionId, manifestJson) {
|
|
|
1793
1346
|
}
|
|
1794
1347
|
function readAllSessionManifests(projectHash, maxAgeSecs = 3600) {
|
|
1795
1348
|
const sessionsDir2 = path3.join(dataDir(), "projects", projectHash, "sessions");
|
|
1796
|
-
if (!
|
|
1349
|
+
if (!fs3.existsSync(sessionsDir2)) {
|
|
1797
1350
|
return [];
|
|
1798
1351
|
}
|
|
1799
1352
|
const now = Date.now() / 1e3;
|
|
1800
1353
|
const results = [];
|
|
1801
1354
|
try {
|
|
1802
|
-
const files =
|
|
1355
|
+
const files = fs3.readdirSync(sessionsDir2);
|
|
1803
1356
|
for (const file of files) {
|
|
1804
1357
|
if (!file.endsWith(".json")) {
|
|
1805
1358
|
continue;
|
|
1806
1359
|
}
|
|
1807
1360
|
try {
|
|
1808
1361
|
const fullPath = path3.join(sessionsDir2, file);
|
|
1809
|
-
const stat2 =
|
|
1362
|
+
const stat2 = fs3.statSync(fullPath);
|
|
1810
1363
|
if (now - stat2.mtimeMs / 1e3 > maxAgeSecs) {
|
|
1811
1364
|
try {
|
|
1812
|
-
|
|
1365
|
+
fs3.unlinkSync(fullPath);
|
|
1813
1366
|
} catch {
|
|
1814
1367
|
}
|
|
1815
1368
|
continue;
|
|
1816
1369
|
}
|
|
1817
|
-
const text =
|
|
1370
|
+
const text = fs3.readFileSync(fullPath, "utf8");
|
|
1818
1371
|
const data = JSON.parse(text);
|
|
1819
1372
|
if (typeof data === "object" && data !== null && "files" in data) {
|
|
1820
1373
|
results.push(data);
|
|
@@ -1901,56 +1454,6 @@ function computeAdaptiveBudget(cache, ageSecs = 0, opts) {
|
|
|
1901
1454
|
}
|
|
1902
1455
|
|
|
1903
1456
|
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
1457
|
SESSIONS_SUBDIR,
|
|
1955
1458
|
sessionsDir,
|
|
1956
1459
|
AGENT_SALT_MARKER,
|