token-goat 2.6.33 → 2.6.34
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 +4 -0
- package/dist/{token-goat-chunk-WFRR2DBG.mjs → token-goat-chunk-7FWBSPCT.mjs} +446 -339
- package/dist/{token-goat-chunk-HPWPUBAK.mjs → token-goat-chunk-CKRATWCJ.mjs} +5 -5
- package/dist/{token-goat-chunk-TDYTBCT4.mjs → token-goat-chunk-CN7GUPX6.mjs} +328 -86
- package/dist/{token-goat-chunk-L6FVTDPD.mjs → token-goat-chunk-FRMEOIRU.mjs} +361 -23
- package/dist/{token-goat-chunk-RPOXYJWK.mjs → token-goat-chunk-GXBPEQR2.mjs} +70 -25
- package/dist/{token-goat-chunk-77CX3MCN.mjs → token-goat-chunk-I6EQH27G.mjs} +2 -2
- package/dist/{token-goat-chunk-FN6WLFIX.mjs → token-goat-chunk-IYYQOPY4.mjs} +801 -51
- package/dist/{token-goat-chunk-72R7M5H7.mjs → token-goat-chunk-L7QLEVO7.mjs} +3 -3
- package/dist/{token-goat-chunk-OHQ7RBLL.mjs → token-goat-chunk-OA3GFKP2.mjs} +2 -2
- package/dist/{token-goat-hook-chunk-HXHFLKEL.mjs → token-goat-chunk-WA2ER6TZ.mjs} +7 -2
- package/dist/{token-goat-chunk-RQQ4SY2P.mjs → token-goat-hook-chunk-2ISZ4AZR.mjs} +7 -2
- package/dist/{token-goat-hook-chunk-ZT47M3IA.mjs → token-goat-hook-chunk-6C5RN3CM.mjs} +2 -2
- package/dist/{token-goat-hook-chunk-UWV4MTYI.mjs → token-goat-hook-chunk-6QTWMSRO.mjs} +328 -86
- package/dist/{token-goat-hook-chunk-XBOWDNJB.mjs → token-goat-hook-chunk-ATEGFQAU.mjs} +5 -5
- package/dist/{token-goat-hook-chunk-QD2DX2U7.mjs → token-goat-hook-chunk-BU5OFDGQ.mjs} +361 -23
- package/dist/{token-goat-hook-chunk-E6AIPKNF.mjs → token-goat-hook-chunk-CNLMPHXT.mjs} +442 -335
- package/dist/{token-goat-hook-chunk-WBBHV6TZ.mjs → token-goat-hook-chunk-I5VM5PO5.mjs} +70 -25
- package/dist/{token-goat-hook-chunk-VDXQXYJK.mjs → token-goat-hook-chunk-KGLMNOGD.mjs} +801 -51
- package/dist/{token-goat-hook-chunk-EKGDLI4D.mjs → token-goat-hook-chunk-OQML5EMA.mjs} +3 -3
- package/dist/{token-goat-hook-chunk-26DLRODR.mjs → token-goat-hook-chunk-QTZ6YUMQ.mjs} +2 -2
- package/dist/token-goat-hook.mjs +5 -5
- package/dist/token-goat.core.mjs +5 -5
- package/package.json +8 -8
|
@@ -10,15 +10,20 @@ import {
|
|
|
10
10
|
atomicWriteText,
|
|
11
11
|
backupFile,
|
|
12
12
|
buildLineIndex,
|
|
13
|
+
countContentLines,
|
|
13
14
|
countNoun,
|
|
14
15
|
dataDir,
|
|
16
|
+
decodeSource,
|
|
15
17
|
detectHarness,
|
|
16
18
|
detectLanguage,
|
|
19
|
+
displaySafePath,
|
|
20
|
+
displaySafeText,
|
|
17
21
|
ensureDirSync,
|
|
18
22
|
escapeRegExp,
|
|
19
23
|
extractEnv,
|
|
20
24
|
extractErrorMessage,
|
|
21
25
|
extractIni,
|
|
26
|
+
fileIsAbsent,
|
|
22
27
|
findHtmlHeadingMatches,
|
|
23
28
|
findMatchingBraceEndLine,
|
|
24
29
|
findProject,
|
|
@@ -82,7 +87,7 @@ import {
|
|
|
82
87
|
withFileLock,
|
|
83
88
|
writeIfDifferent,
|
|
84
89
|
writeJsonSettings
|
|
85
|
-
} from "./token-goat-hook-chunk-
|
|
90
|
+
} from "./token-goat-hook-chunk-CNLMPHXT.mjs";
|
|
86
91
|
import {
|
|
87
92
|
registerReset
|
|
88
93
|
} from "./token-goat-hook-chunk-BUOCULAM.mjs";
|
|
@@ -336,12 +341,12 @@ function buildGuidanceBody(fallbackToolClause, opts = {}) {
|
|
|
336
341
|
'- searching for a *concept* rather than a literal string \u2192 `semantic "description"`',
|
|
337
342
|
"- re-reading output you already captured \u2192 `bash-output`/`web-output`/`mcp-output` by ID",
|
|
338
343
|
"- a directory listing or recursive wildcard walk to orient in an unfamiliar repo \u2192 `map --compact`",
|
|
339
|
-
"- pulling one value or subtree out of a JSON/YAML file (manifest, lockfile, spec, config) \u2192 `json-query file 'a.b.c'` / `yaml-query file 'a.b.c'`",
|
|
344
|
+
"- pulling one value or subtree out of a JSON/YAML/XML file (manifest, lockfile, spec, config) \u2192 `json-query file 'a.b.c'` / `yaml-query file 'a.b.c'` / `xml-query file 'a.b.c'`",
|
|
340
345
|
"- opening an image to check its dimensions, format, or size \u2192 `image-meta file`",
|
|
341
346
|
"- opening a screenshot, diagram, or scan to read the text in it \u2192 `image-text file`",
|
|
342
347
|
"- opening a PDF or Office document \u2192 inspect its format first, then read a narrow slice: PDF `pdf-meta`/`pdf-outline` then `pdf-extract`; Word `docx-outline` then `docx-text`; PowerPoint `pptx-outline` then `pptx-slide`/`pptx-notes`; Excel `xlsx-sheets` then `xlsx-head`/`xlsx-range`/`xlsx-query`",
|
|
343
348
|
"",
|
|
344
|
-
'Commands: `symbol NAME`, `read "file::symbol"`, `brief "file::symbol"`, `section "file::Heading"`, `semantic "description"`, `outline file`/`skeleton file`, `map --compact`, `refs file::symbol --callers`, `changed --symbol`, `config-get file KEY`, `json-query file \'a.b.c\'`/`yaml-query`, `json-outline file`/`yaml-outline`, `bash-output`/`web-output`/`mcp-output`, ' + (gdrive ? "`gdrive-sections <file-id>`, " : "") + "`image-meta file`/`image-text file`, `pdf-meta`/`pdf-outline`/`pdf-extract`, `docx-outline`/`docx-text`, `pptx-outline`/`pptx-slide`/`pptx-notes`/`pptx-text`, `xlsx-sheets`/`xlsx-head`/`xlsx-range`/`xlsx-query`.",
|
|
349
|
+
'Commands: `symbol NAME`, `read "file::symbol"`, `brief "file::symbol"`, `section "file::Heading"`, `semantic "description"`, `outline file`/`skeleton file`, `map --compact`, `refs file::symbol --callers`, `changed --symbol`, `config-get file KEY`, `json-query file \'a.b.c\'`/`yaml-query`/`xml-query`, `json-outline file`/`yaml-outline`/`xml-outline`, `bash-output`/`web-output`/`mcp-output`, ' + (gdrive ? "`gdrive-sections <file-id>`, " : "") + "`image-meta file`/`image-text file`, `pdf-meta`/`pdf-outline`/`pdf-extract`, `docx-outline`/`docx-text`, `pptx-outline`/`pptx-slide`/`pptx-notes`/`pptx-text`, `xlsx-sheets`/`xlsx-head`/`xlsx-range`/`xlsx-query`.",
|
|
345
350
|
"",
|
|
346
351
|
"Sub-agent briefs must carry this gate verbatim: a sub-agent inherits none of this context and its reads spend the same token budget.",
|
|
347
352
|
"",
|
|
@@ -3211,10 +3216,11 @@ function logHintEmission(category, sessionId, correlator, compensateSelfResolve
|
|
|
3211
3216
|
try {
|
|
3212
3217
|
const db = getDb(globalDbPath());
|
|
3213
3218
|
const resolved = correlator === null ? 1 : 0;
|
|
3219
|
+
const actedOn = resolved === 1 && isSuppressionCategory(category) ? 1 : 0;
|
|
3214
3220
|
const window = ACTED_ON_WINDOW + (compensateSelfResolve ? 1 : 0);
|
|
3215
3221
|
db.prepare(
|
|
3216
3222
|
`INSERT INTO hint_emissions (category, session_id, harness, correlator, emitted_at, resolved, acted_on, calls_remaining, bytes_emitted)
|
|
3217
|
-
VALUES (@category, @sessionId, @harness, @correlator, @emittedAt, @resolved,
|
|
3223
|
+
VALUES (@category, @sessionId, @harness, @correlator, @emittedAt, @resolved, @actedOn, @callsRemaining, @bytesEmitted)`
|
|
3218
3224
|
).run({
|
|
3219
3225
|
category,
|
|
3220
3226
|
sessionId,
|
|
@@ -3222,6 +3228,7 @@ function logHintEmission(category, sessionId, correlator, compensateSelfResolve
|
|
|
3222
3228
|
correlator,
|
|
3223
3229
|
emittedAt: Date.now(),
|
|
3224
3230
|
resolved,
|
|
3231
|
+
actedOn,
|
|
3225
3232
|
callsRemaining: correlator === null ? 0 : window,
|
|
3226
3233
|
bytesEmitted
|
|
3227
3234
|
});
|
|
@@ -3241,6 +3248,30 @@ function commandMentionsCorrelator(command, correlator) {
|
|
|
3241
3248
|
}
|
|
3242
3249
|
return false;
|
|
3243
3250
|
}
|
|
3251
|
+
var SUPPRESSION_HINT_CATEGORIES = /* @__PURE__ */ new Set([
|
|
3252
|
+
"read_reread_dedup",
|
|
3253
|
+
"edit_reread_suggest"
|
|
3254
|
+
]);
|
|
3255
|
+
function isSuppressionCategory(category) {
|
|
3256
|
+
return SUPPRESSION_HINT_CATEGORIES.has(category);
|
|
3257
|
+
}
|
|
3258
|
+
var EVENT_PATH_KEYS = ["file_path", "filePath", "notebook_path", "path"];
|
|
3259
|
+
function eventTargetText(event) {
|
|
3260
|
+
if (event.toolName === "Bash") {
|
|
3261
|
+
const c = event.toolInput["command"];
|
|
3262
|
+
return typeof c === "string" ? c : "";
|
|
3263
|
+
}
|
|
3264
|
+
for (const key of EVENT_PATH_KEYS) {
|
|
3265
|
+
const v = event.toolInput[key];
|
|
3266
|
+
if (typeof v === "string" && v !== "") return v;
|
|
3267
|
+
}
|
|
3268
|
+
return "";
|
|
3269
|
+
}
|
|
3270
|
+
function isDefiance(correlator, target) {
|
|
3271
|
+
if (target === "") return false;
|
|
3272
|
+
if (TOKEN_GOAT_INVOCATION_RE.test(target)) return false;
|
|
3273
|
+
return commandMentionsCorrelator(target, correlator);
|
|
3274
|
+
}
|
|
3244
3275
|
function isActedOn(category, correlator, command) {
|
|
3245
3276
|
if (!TOKEN_GOAT_INVOCATION_RE.test(command)) return false;
|
|
3246
3277
|
if (category === "bash_recall") {
|
|
@@ -3252,10 +3283,29 @@ function resolvePendingHintsForEvent(event) {
|
|
|
3252
3283
|
try {
|
|
3253
3284
|
const db = getDb(globalDbPath());
|
|
3254
3285
|
const command = event.toolName === "Bash" && typeof event.toolInput["command"] === "string" ? event.toolInput["command"] : "";
|
|
3286
|
+
const target = eventTargetText(event);
|
|
3255
3287
|
const pending = db.prepare(`SELECT id, category, correlator, calls_remaining FROM hint_emissions WHERE session_id = ? AND resolved = 0`).all(event.sessionId);
|
|
3256
3288
|
for (const row of pending) {
|
|
3257
3289
|
if (!isHintCategory(row.category) || row.correlator === null) {
|
|
3258
|
-
|
|
3290
|
+
const unobservable = isHintCategory(row.category) && isSuppressionCategory(row.category) ? 1 : 0;
|
|
3291
|
+
db.prepare(`UPDATE hint_emissions SET acted_on = ?, resolved = 1 WHERE id = ?`).run(unobservable, row.id);
|
|
3292
|
+
continue;
|
|
3293
|
+
}
|
|
3294
|
+
if (isSuppressionCategory(row.category)) {
|
|
3295
|
+
if (isDefiance(row.correlator, target)) {
|
|
3296
|
+
db.prepare(`UPDATE hint_emissions SET acted_on = 0, resolved = 1 WHERE id = ?`).run(row.id);
|
|
3297
|
+
continue;
|
|
3298
|
+
}
|
|
3299
|
+
if (command !== "" && isActedOn(row.category, row.correlator, command)) {
|
|
3300
|
+
db.prepare(`UPDATE hint_emissions SET acted_on = 1, resolved = 1 WHERE id = ?`).run(row.id);
|
|
3301
|
+
continue;
|
|
3302
|
+
}
|
|
3303
|
+
const left = row.calls_remaining - 1;
|
|
3304
|
+
if (left <= 0) {
|
|
3305
|
+
db.prepare(`UPDATE hint_emissions SET acted_on = 1, resolved = 1 WHERE id = ?`).run(row.id);
|
|
3306
|
+
} else {
|
|
3307
|
+
db.prepare(`UPDATE hint_emissions SET calls_remaining = ? WHERE id = ?`).run(left, row.id);
|
|
3308
|
+
}
|
|
3259
3309
|
continue;
|
|
3260
3310
|
}
|
|
3261
3311
|
if (command !== "" && isActedOn(row.category, row.correlator, command)) {
|
|
@@ -3313,15 +3363,18 @@ function manualMarks(category) {
|
|
|
3313
3363
|
}
|
|
3314
3364
|
}
|
|
3315
3365
|
function getHintStatsSummary() {
|
|
3366
|
+
const probeThresholds = loadConfig().hints.backoff_thresholds.filter((t) => t > 0);
|
|
3316
3367
|
return HINT_CATEGORIES.map((category) => {
|
|
3317
3368
|
const { emitted, actedOn, bytesEmitted, legacyEmissions } = categoryStats(category);
|
|
3318
3369
|
const marks = manualMarks(category);
|
|
3370
|
+
const suppressed = shouldSuppress(category, "");
|
|
3319
3371
|
return {
|
|
3320
3372
|
category,
|
|
3321
3373
|
emitted,
|
|
3322
3374
|
actedOn: actedOn ?? 0,
|
|
3323
3375
|
efficacyPct: emitted === 0 ? null : Math.round(1e3 * (actedOn ?? 0) / emitted) / 10,
|
|
3324
|
-
suppressed
|
|
3376
|
+
suppressed,
|
|
3377
|
+
suppressionPermanent: suppressed && probeThresholds.length === 0,
|
|
3325
3378
|
manualEffective: marks.effective,
|
|
3326
3379
|
manualIneffective: marks.ineffective,
|
|
3327
3380
|
bytesEmitted,
|
|
@@ -4057,7 +4110,7 @@ async function ocrImage(input) {
|
|
|
4057
4110
|
const entryPath = resolveTesseractEntry();
|
|
4058
4111
|
if (entryPath === null) return null;
|
|
4059
4112
|
if (ocrBlockedOffline()) return null;
|
|
4060
|
-
return new Promise((
|
|
4113
|
+
return new Promise((resolve10) => {
|
|
4061
4114
|
let settled = false;
|
|
4062
4115
|
let child;
|
|
4063
4116
|
try {
|
|
@@ -4066,7 +4119,7 @@ async function ocrImage(input) {
|
|
|
4066
4119
|
});
|
|
4067
4120
|
} catch {
|
|
4068
4121
|
_ocrUnavailableThisProcess = true;
|
|
4069
|
-
|
|
4122
|
+
resolve10(null);
|
|
4070
4123
|
return;
|
|
4071
4124
|
}
|
|
4072
4125
|
const chunks = [];
|
|
@@ -4079,7 +4132,7 @@ async function ocrImage(input) {
|
|
|
4079
4132
|
child.kill();
|
|
4080
4133
|
} catch {
|
|
4081
4134
|
}
|
|
4082
|
-
|
|
4135
|
+
resolve10(result);
|
|
4083
4136
|
};
|
|
4084
4137
|
const timer = setTimeout(() => finish(null, true), _ocrTimeoutMs);
|
|
4085
4138
|
child.stdout?.on("data", (c) => chunks.push(c));
|
|
@@ -4204,11 +4257,11 @@ function statInfo(absPath) {
|
|
|
4204
4257
|
function imageShrinkCacheDir() {
|
|
4205
4258
|
return path10.join(tokenGoatHome(), "image_shrink_cache");
|
|
4206
4259
|
}
|
|
4207
|
-
function shrinkCacheKey(originalPath, size, mtimeMs) {
|
|
4208
|
-
return createHash2("sha256").update(`${originalPath}:${size}:${mtimeMs}`).digest("hex").slice(0, 16);
|
|
4260
|
+
function shrinkCacheKey(originalPath, size, mtimeMs, quality) {
|
|
4261
|
+
return createHash2("sha256").update(`${originalPath}:${size}:${mtimeMs}:${quality}`).digest("hex").slice(0, 16);
|
|
4209
4262
|
}
|
|
4210
|
-
function findCachedShrink(originalPath, size, mtimeMs) {
|
|
4211
|
-
const key = shrinkCacheKey(originalPath, size, mtimeMs);
|
|
4263
|
+
function findCachedShrink(originalPath, size, mtimeMs, quality) {
|
|
4264
|
+
const key = shrinkCacheKey(originalPath, size, mtimeMs, quality);
|
|
4212
4265
|
const dir = imageShrinkCacheDir();
|
|
4213
4266
|
const candidates = [
|
|
4214
4267
|
{ ext: ".webp", format: "webp" },
|
|
@@ -4220,11 +4273,11 @@ function findCachedShrink(originalPath, size, mtimeMs) {
|
|
|
4220
4273
|
}
|
|
4221
4274
|
return null;
|
|
4222
4275
|
}
|
|
4223
|
-
function writeCachedShrink(originalPath, result, mtimeMs) {
|
|
4276
|
+
function writeCachedShrink(originalPath, result, mtimeMs, quality) {
|
|
4224
4277
|
try {
|
|
4225
4278
|
const dir = imageShrinkCacheDir();
|
|
4226
4279
|
ensureDirSync(dir);
|
|
4227
|
-
const key = shrinkCacheKey(originalPath, result.originalBytes, mtimeMs);
|
|
4280
|
+
const key = shrinkCacheKey(originalPath, result.originalBytes, mtimeMs, quality);
|
|
4228
4281
|
const ext = result.format === "jpeg" ? ".jpg" : ".webp";
|
|
4229
4282
|
atomicWriteBytes(path10.join(dir, `token-goat-shrink-${key}${ext}`), result.data);
|
|
4230
4283
|
} catch {
|
|
@@ -4278,7 +4331,8 @@ async function preReadImageHandler(event) {
|
|
|
4278
4331
|
const stat2 = statInfo(filePath);
|
|
4279
4332
|
if (stat2 === null) return passOutput();
|
|
4280
4333
|
const size = stat2.size;
|
|
4281
|
-
const
|
|
4334
|
+
const quality = loadConfig().image_shrink.jpeg_quality;
|
|
4335
|
+
const cached = findCachedShrink(filePath, stat2.size, stat2.mtimeMs, quality);
|
|
4282
4336
|
if (cached !== null) {
|
|
4283
4337
|
let cachedData;
|
|
4284
4338
|
try {
|
|
@@ -4331,12 +4385,12 @@ async function preReadImageHandler(event) {
|
|
|
4331
4385
|
return passOutput();
|
|
4332
4386
|
}
|
|
4333
4387
|
}
|
|
4334
|
-
const result = await shrinkImage(input, { sizeThresholdBytes: 0 });
|
|
4388
|
+
const result = await shrinkImage(input, { quality, sizeThresholdBytes: 0 });
|
|
4335
4389
|
if (result === null) {
|
|
4336
4390
|
recordStat("image_shrink_skipped");
|
|
4337
4391
|
return passOutput();
|
|
4338
4392
|
}
|
|
4339
|
-
writeCachedShrink(filePath, result, stat2.mtimeMs);
|
|
4393
|
+
writeCachedShrink(filePath, result, stat2.mtimeMs, quality);
|
|
4340
4394
|
return finalizeShrinkResult(result, filePath);
|
|
4341
4395
|
}
|
|
4342
4396
|
registerHook("pre_tool_use", preReadImageHandler, { toolName: "Read" });
|
|
@@ -4398,7 +4452,7 @@ registerReset(() => {
|
|
|
4398
4452
|
PIPELINE_RETRY_DELAY_MS = DEFAULT_PIPELINE_RETRY_DELAY_MS;
|
|
4399
4453
|
});
|
|
4400
4454
|
function sleep(ms) {
|
|
4401
|
-
return new Promise((
|
|
4455
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
4402
4456
|
}
|
|
4403
4457
|
async function buildExtractorWithRetry(pipelineFn, modelName) {
|
|
4404
4458
|
let lastError;
|
|
@@ -4948,6 +5002,7 @@ function trimToBudget(text, budgetTokens, command) {
|
|
|
4948
5002
|
return text;
|
|
4949
5003
|
}
|
|
4950
5004
|
const lines2 = text.split("\n");
|
|
5005
|
+
if (lines2.length > 1 && lines2[lines2.length - 1] === "") lines2.pop();
|
|
4951
5006
|
const totalLines = lines2.length;
|
|
4952
5007
|
const bodyBudget = Math.max(1, budgetTokens - markerMarginTokens);
|
|
4953
5008
|
const charBudget = bodyBudget * 3;
|
|
@@ -6231,7 +6286,7 @@ var ResizeableBuffer = class {
|
|
|
6231
6286
|
}
|
|
6232
6287
|
toString(encoding) {
|
|
6233
6288
|
if (encoding) {
|
|
6234
|
-
return this.buf.
|
|
6289
|
+
return this.buf.toString(encoding, 0, this.length);
|
|
6235
6290
|
} else {
|
|
6236
6291
|
return Uint8Array.prototype.slice.call(this.buf.slice(0, this.length));
|
|
6237
6292
|
}
|
|
@@ -7483,14 +7538,19 @@ var transform = function(original_options = {}) {
|
|
|
7483
7538
|
const obj = {};
|
|
7484
7539
|
for (let i = 0, l = record.length; i < l; i++) {
|
|
7485
7540
|
if (columns[i] === void 0 || columns[i].disabled) continue;
|
|
7486
|
-
if (group_columns_by_name === true && obj
|
|
7541
|
+
if (group_columns_by_name === true && Object.hasOwn(obj, columns[i].name)) {
|
|
7487
7542
|
if (Array.isArray(obj[columns[i].name])) {
|
|
7488
7543
|
obj[columns[i].name] = obj[columns[i].name].concat(record[i]);
|
|
7489
7544
|
} else {
|
|
7490
7545
|
obj[columns[i].name] = [obj[columns[i].name], record[i]];
|
|
7491
7546
|
}
|
|
7492
7547
|
} else {
|
|
7493
|
-
obj
|
|
7548
|
+
Object.defineProperty(obj, columns[i].name, {
|
|
7549
|
+
value: record[i],
|
|
7550
|
+
enumerable: true,
|
|
7551
|
+
writable: true,
|
|
7552
|
+
configurable: true
|
|
7553
|
+
});
|
|
7494
7554
|
}
|
|
7495
7555
|
}
|
|
7496
7556
|
if (raw === true || info2 === true) {
|
|
@@ -7917,6 +7977,7 @@ ${recall}`
|
|
|
7917
7977
|
if (htmlResult.shouldBlock) return htmlResult;
|
|
7918
7978
|
}
|
|
7919
7979
|
const lines2 = content.split("\n");
|
|
7980
|
+
if (lines2.length > 1 && lines2[lines2.length - 1] === "") lines2.pop();
|
|
7920
7981
|
const preview = [
|
|
7921
7982
|
"--- first 5 lines ---",
|
|
7922
7983
|
...lines2.slice(0, 5),
|
|
@@ -8532,7 +8593,8 @@ function isSessionArtifactFile(filePath) {
|
|
|
8532
8593
|
if (/[/\\]tool-results[/\\][a-z0-9]+\.txt$/i.test(filePath)) return true;
|
|
8533
8594
|
return false;
|
|
8534
8595
|
}
|
|
8535
|
-
function sessionArtifactRecall(
|
|
8596
|
+
function sessionArtifactRecall(rawPath) {
|
|
8597
|
+
const filePath = displaySafePath(rawPath);
|
|
8536
8598
|
return 'Use `token-goat bash-output --file "' + filePath + '" --tail 50` (or `--grep PATTERN`) to read a slice instead of the full file.';
|
|
8537
8599
|
}
|
|
8538
8600
|
function readIntToolInput(event, key) {
|
|
@@ -8599,7 +8661,8 @@ function estimateRequestedSlice(event, absPath) {
|
|
|
8599
8661
|
if (scan.trustworthy) return { kind: "bytes", bytes: scan.bytes };
|
|
8600
8662
|
return { kind: "unbounded" };
|
|
8601
8663
|
}
|
|
8602
|
-
function describeSliceAdvice(slice,
|
|
8664
|
+
function describeSliceAdvice(slice, rawAbsPath) {
|
|
8665
|
+
const absPath = displaySafePath(rawAbsPath);
|
|
8603
8666
|
if (slice.kind === "nearSingleLine") {
|
|
8604
8667
|
return BYTE_RANGE_ADVICE(absPath);
|
|
8605
8668
|
}
|
|
@@ -8758,6 +8821,7 @@ function preReadHandlerInner(event) {
|
|
|
8758
8821
|
}
|
|
8759
8822
|
if (filePath === void 0) return passOutput();
|
|
8760
8823
|
const normalized = normalizePath(filePath);
|
|
8824
|
+
const shown = displaySafePath(normalized);
|
|
8761
8825
|
if (isNodeModulesPath(normalized)) {
|
|
8762
8826
|
return denyOutput(
|
|
8763
8827
|
"node_modules is typically noise; use npm ls, npm outdated, or npm audit instead for dependency info. To force access, use: token-goat read node_modules/package/file.js::symbol-name or token-goat section node_modules/package/file.js::heading"
|
|
@@ -8781,7 +8845,7 @@ function preReadHandlerInner(event) {
|
|
|
8781
8845
|
const basename12 = path16.basename(normalized);
|
|
8782
8846
|
if (isLockFile(basename12)) {
|
|
8783
8847
|
return denyOutput(
|
|
8784
|
-
'Lock files are rarely useful to read in full. Use `token-goat section "' +
|
|
8848
|
+
'Lock files are rarely useful to read in full. Use `token-goat section "' + shown + '::<section>"` to extract a specific dependency, or read the relevant manifest instead.'
|
|
8785
8849
|
);
|
|
8786
8850
|
}
|
|
8787
8851
|
if (normalized.toLowerCase().endsWith(".tsbuildinfo")) {
|
|
@@ -8805,13 +8869,13 @@ function preReadHandlerInner(event) {
|
|
|
8805
8869
|
if (isTsConfigFile(basename12) && wasFileReadThisSession(normalized)) {
|
|
8806
8870
|
recordActualRead(event, normalized);
|
|
8807
8871
|
return quietContextOutput(
|
|
8808
|
-
"Already read " + basename12 + '. Use `token-goat section "' +
|
|
8872
|
+
"Already read " + basename12 + '. Use `token-goat section "' + shown + '::compilerOptions"` to extract compiler options, or `token-goat config-get ' + shown + " compilerOptions.target` for a single value."
|
|
8809
8873
|
);
|
|
8810
8874
|
}
|
|
8811
8875
|
if (isManifestFile(basename12) && wasFileReadThisSession(normalized)) {
|
|
8812
8876
|
recordActualRead(event, normalized);
|
|
8813
8877
|
return quietContextOutput(
|
|
8814
|
-
"You've already read " + basename12 + '. Use `token-goat section "' +
|
|
8878
|
+
"You've already read " + basename12 + '. Use `token-goat section "' + shown + '::<field>"` or `token-goat config-get ' + shown + " <key>` to extract just the value you need."
|
|
8815
8879
|
);
|
|
8816
8880
|
}
|
|
8817
8881
|
const skillName = detectSkillFile(normalized);
|
|
@@ -8840,7 +8904,7 @@ function preReadHandlerInner(event) {
|
|
|
8840
8904
|
const savedBytes = Math.max(0, fullSize - compactBody.length);
|
|
8841
8905
|
recordStat("session_hint", savedBytes, Math.round(savedBytes / 4));
|
|
8842
8906
|
return denyOutput(
|
|
8843
|
-
"Serving the extractive compact sidecar in place of the full file (source unchanged since the last `compact-doc` build):\n\n" + fenceUntrustedFileContent(compactBody) + '\n\nUse `token-goat compact-doc "' +
|
|
8907
|
+
"Serving the extractive compact sidecar in place of the full file (source unchanged since the last `compact-doc` build):\n\n" + fenceUntrustedFileContent(compactBody) + '\n\nUse `token-goat compact-doc "' + shown + '" --force` to rebuild it, or `token-goat compact-doc "' + shown + '" --show` to view it directly. ' + editAnywayHint(normalized)
|
|
8844
8908
|
);
|
|
8845
8909
|
}
|
|
8846
8910
|
}
|
|
@@ -8881,7 +8945,7 @@ function preReadHandlerInner(event) {
|
|
|
8881
8945
|
const hintText = formatHeadingTree(headings, normalized);
|
|
8882
8946
|
const headingTextsLower = new Set(headings.map((h) => h.text.trim().toLowerCase()));
|
|
8883
8947
|
const wellKnown = getWellKnownSections(basename12).filter((s) => headingTextsLower.has(s.trim().toLowerCase()));
|
|
8884
|
-
const wellKnownText = wellKnown.length > 0 ? "\nQuick access: " + wellKnown.map((s) => 'token-goat section "' +
|
|
8948
|
+
const wellKnownText = wellKnown.length > 0 ? "\nQuick access: " + wellKnown.map((s) => 'token-goat section "' + shown + "::" + s + '"').join(" | ") : "";
|
|
8885
8949
|
const changelogExtra = basename12.toLowerCase() === "changelog.md" ? extractChangelogVersionHint(fileContent, normalized) : "";
|
|
8886
8950
|
let message = fenceUntrustedFileContent(hintText + changelogExtra) + wellKnownText;
|
|
8887
8951
|
const slice = estimateRequestedSlice(event, normalized);
|
|
@@ -8905,7 +8969,7 @@ function preReadHandlerInner(event) {
|
|
|
8905
8969
|
recordStat("session_hint", 0, 0);
|
|
8906
8970
|
const isMainMemory = basename12.toLowerCase() === "memory.md";
|
|
8907
8971
|
return denyOutput(
|
|
8908
|
-
isMainMemory ? "MEMORY.md was read this session. Its content is in the compact manifest as 'session memory'." :
|
|
8972
|
+
isMainMemory ? "MEMORY.md was read this session. Its content is in the compact manifest as 'session memory'." : shown + ' was already read this session. Memory files rarely change mid-session. Use `token-goat section "' + shown + '::SectionHeading"` to extract one section.'
|
|
8909
8973
|
);
|
|
8910
8974
|
}
|
|
8911
8975
|
if (/^\.improve-state-.*\.json$/.test(basename12) && wasFileReadThisSession(normalized)) {
|
|
@@ -8919,7 +8983,7 @@ function preReadHandlerInner(event) {
|
|
|
8919
8983
|
recordActualRead(event, normalized);
|
|
8920
8984
|
recordStat("session_hint", 0, 0);
|
|
8921
8985
|
return denyOutput(
|
|
8922
|
-
|
|
8986
|
+
shown + " was already read this session. Environment files rarely change mid-session. Use `token-goat config-get " + shown + " KEY_NAME` to extract a specific variable."
|
|
8923
8987
|
);
|
|
8924
8988
|
}
|
|
8925
8989
|
if (isSessionArtifactFile(normalized)) {
|
|
@@ -8950,7 +9014,7 @@ function preReadHandlerInner(event) {
|
|
|
8950
9014
|
recordActualRead(event, normalized);
|
|
8951
9015
|
recordStat("session_hint", 0, 0);
|
|
8952
9016
|
return denyOutput(
|
|
8953
|
-
|
|
9017
|
+
shown + " was already read this session. " + sessionArtifactRecall(normalized)
|
|
8954
9018
|
);
|
|
8955
9019
|
}
|
|
8956
9020
|
{
|
|
@@ -9009,7 +9073,7 @@ function preReadHandlerInner(event) {
|
|
|
9009
9073
|
if (scanCrossSessionManifests(project.root, project.hash, normalized, ttlSecs)) {
|
|
9010
9074
|
recordActualRead(event, normalized);
|
|
9011
9075
|
return quietContextOutput(
|
|
9012
|
-
"This file may have already been read by another agent/session working in this project recently. If you are a subagent continuing shared work, consider whether you already have this content from context, or use `token-goat read " +
|
|
9076
|
+
"This file may have already been read by another agent/session working in this project recently. If you are a subagent continuing shared work, consider whether you already have this content from context, or use `token-goat read " + shown + "::SymbolName` for a narrower slice instead of a full re-read."
|
|
9013
9077
|
);
|
|
9014
9078
|
}
|
|
9015
9079
|
}
|
|
@@ -9041,7 +9105,7 @@ function preReadHandlerInner(event) {
|
|
|
9041
9105
|
if (/\.(md|mdx|markdown|rst)$/i.test(basename12)) {
|
|
9042
9106
|
recordStat("session_hint", rereadCredit, Math.round(rereadCredit / 4));
|
|
9043
9107
|
return denyOutput(
|
|
9044
|
-
'Markdown file already read this session. Use `token-goat section "' +
|
|
9108
|
+
'Markdown file already read this session. Use `token-goat section "' + shown + '::HeadingName"` to read one section. ' + editAnywayHint(normalized)
|
|
9045
9109
|
);
|
|
9046
9110
|
}
|
|
9047
9111
|
const isSourceExt = isSourceExtension(basename12);
|
|
@@ -9049,22 +9113,22 @@ function preReadHandlerInner(event) {
|
|
|
9049
9113
|
recordStat("read_count_deny", rereadCredit, Math.round(rereadCredit / 4));
|
|
9050
9114
|
recordStat("session_hint", rereadCredit, Math.round(rereadCredit / 4));
|
|
9051
9115
|
return denyOutput(
|
|
9052
|
-
"Read this file " + reads + ' times already \u2014 use `token-goat read "' +
|
|
9116
|
+
"Read this file " + reads + ' times already \u2014 use `token-goat read "' + shown + '::Symbol"`, `token-goat skeleton ' + shown + "`, or `token-goat outline " + shown + "` to pull just the part you need. " + editAnywayHint(normalized)
|
|
9053
9117
|
);
|
|
9054
9118
|
}
|
|
9055
9119
|
}
|
|
9056
|
-
const hint = _isDocFile(normalized) ? 'Use `token-goat section "' +
|
|
9120
|
+
const hint = _isDocFile(normalized) ? 'Use `token-goat section "' + shown + '::SectionName"` to read one section.' : "Use token-goat read/section/symbol to re-read surgically.";
|
|
9057
9121
|
if (config2.hints.reread_deny && !protectedRead && (rereadBytes >= config2.hints.reread_deny_min_bytes || reads >= 2)) {
|
|
9058
9122
|
recordStat("session_hint", rereadCredit, Math.round(rereadCredit / 4));
|
|
9059
9123
|
return denyOutput(
|
|
9060
|
-
|
|
9124
|
+
shown + " was already read this session (" + reads + " " + plural + "). " + hint + " " + editAnywayHint(normalized)
|
|
9061
9125
|
);
|
|
9062
9126
|
}
|
|
9063
9127
|
if (!isWithinQuietHours(config2.hints.quiet_hours)) {
|
|
9064
9128
|
recordStat("session_hint", 0, 0);
|
|
9065
9129
|
}
|
|
9066
9130
|
return quietContextOutput(
|
|
9067
|
-
"Note: " +
|
|
9131
|
+
"Note: " + shown + " was already read this session (" + reads + " " + plural + "). " + hint
|
|
9068
9132
|
);
|
|
9069
9133
|
}
|
|
9070
9134
|
const size = statSize(normalized);
|
|
@@ -9077,12 +9141,12 @@ function preReadHandlerInner(event) {
|
|
|
9077
9141
|
}
|
|
9078
9142
|
const kb = toKB(size);
|
|
9079
9143
|
const config2 = loadConfig();
|
|
9080
|
-
const hint = _isDocFile(normalized) ? 'Use `token-goat section "' +
|
|
9144
|
+
const hint = _isDocFile(normalized) ? 'Use `token-goat section "' + shown + '::SectionName"` to read one section.' : "Consider token-goat skeleton or token-goat section.";
|
|
9081
9145
|
if (gateSize >= largeFileDenyBytes()) {
|
|
9082
9146
|
const denyCredit = Math.min(size, PER_FILE_COUNTERFACTUAL_CEILING);
|
|
9083
9147
|
recordStat("session_hint", denyCredit, Math.round(denyCredit / 4));
|
|
9084
9148
|
return denyOutput(
|
|
9085
|
-
|
|
9149
|
+
shown + " is very large (" + kb + "KB). " + hint + " " + describeSliceAdvice(slice, normalized) + " " + editAnywayHint(normalized)
|
|
9086
9150
|
);
|
|
9087
9151
|
}
|
|
9088
9152
|
recordActualRead(event, normalized);
|
|
@@ -9096,7 +9160,7 @@ function preReadHandlerInner(event) {
|
|
|
9096
9160
|
recordStat("session_hint", 0, 0);
|
|
9097
9161
|
}
|
|
9098
9162
|
return quietContextOutput(
|
|
9099
|
-
"Note: " +
|
|
9163
|
+
"Note: " + shown + " is large (" + kb + "KB). " + hint + contextPressureAdvisorySuffix()
|
|
9100
9164
|
);
|
|
9101
9165
|
}
|
|
9102
9166
|
const fileTypeExt = path16.extname(normalized).slice(1).toLowerCase();
|
|
@@ -9144,16 +9208,19 @@ function estimateTruncatedLineCount(normalized) {
|
|
|
9144
9208
|
}
|
|
9145
9209
|
return Infinity;
|
|
9146
9210
|
}
|
|
9147
|
-
function editAnywayHint(
|
|
9211
|
+
function editAnywayHint(rawPath) {
|
|
9212
|
+
const normalized = displaySafePath(rawPath);
|
|
9148
9213
|
return 'To edit it anyway, use `token-goat replace "' + normalized + '" --old-b64 <base64> --new-b64 <base64>` (preferred \u2014 no temp files needed) or `--old-from <oldfile> --new-from <newfile>` for a snippet edit, or `token-goat write-file "' + normalized + "\" --b64 <base64>` (or `--from <newfile>`) to rewrite the whole file \u2014 Read/Edit's own precondition can't be satisfied after this deny.";
|
|
9149
9214
|
}
|
|
9150
|
-
function truncatedReadDenyMessage(
|
|
9215
|
+
function truncatedReadDenyMessage(rawPath) {
|
|
9216
|
+
const normalized = displaySafePath(rawPath);
|
|
9151
9217
|
return 'File was truncated on last read (>33K tokens). Use `token-goat skeleton "' + normalized + '"` for structure or `token-goat read "' + normalized + '::SymbolName"` for one function. ' + editAnywayHint(normalized);
|
|
9152
9218
|
}
|
|
9153
9219
|
function postReadHandlerInner(event) {
|
|
9154
9220
|
const filePath = getFilePath(event);
|
|
9155
9221
|
if (filePath === void 0) return passOutput();
|
|
9156
9222
|
const normalized = normalizePath(filePath);
|
|
9223
|
+
const shown = displaySafePath(normalized);
|
|
9157
9224
|
const respText = extractReadOutput(event.raw);
|
|
9158
9225
|
if (respText.includes("[Truncated:") || respText.includes("Truncated: PARTIAL view")) {
|
|
9159
9226
|
markFileTruncated(normalized);
|
|
@@ -9174,7 +9241,7 @@ function postReadHandlerInner(event) {
|
|
|
9174
9241
|
try {
|
|
9175
9242
|
const cwd = getCwd(event) ?? process.cwd();
|
|
9176
9243
|
const project = findProject(cwd) ?? makeProjectAt(cwd);
|
|
9177
|
-
const source = fs18.readFileSync(normalized
|
|
9244
|
+
const source = decodeSource(fs18.readFileSync(normalized));
|
|
9178
9245
|
recordEvidence({ projectRoot: project.root, source: normalized, representation: "file", text: source });
|
|
9179
9246
|
} catch {
|
|
9180
9247
|
}
|
|
@@ -9210,7 +9277,7 @@ function postReadHandlerInner(event) {
|
|
|
9210
9277
|
if (lineCount >= minLines && meetsSavingsFloor(sz)) {
|
|
9211
9278
|
recordStat("session_hint", 0, 0);
|
|
9212
9279
|
return quietContextOutput(
|
|
9213
|
-
|
|
9280
|
+
shown + " is " + lineCount + ' lines. Use `token-goat skeleton "' + shown + '"` or `token-goat outline "' + shown + '"` for structural navigation instead of a future full re-read.'
|
|
9214
9281
|
);
|
|
9215
9282
|
}
|
|
9216
9283
|
}
|
|
@@ -9688,9 +9755,12 @@ function profileCsv(content, opts = {}) {
|
|
|
9688
9755
|
}
|
|
9689
9756
|
function formatCsvProfile(profiles) {
|
|
9690
9757
|
return profiles.map((p) => {
|
|
9691
|
-
const lines2 = [
|
|
9692
|
-
|
|
9693
|
-
|
|
9758
|
+
const lines2 = [
|
|
9759
|
+
`${displaySafeText(p.name)} (${p.inferredType})`,
|
|
9760
|
+
` nulls: ${p.nullCount} distinct: ${p.distinctCount}`
|
|
9761
|
+
];
|
|
9762
|
+
if (p.min !== void 0) lines2.push(` range: ${displaySafeText(p.min)} .. ${displaySafeText(p.max ?? "")}`);
|
|
9763
|
+
if (p.topValues !== void 0) lines2.push(` values: ${p.topValues.map((t) => `${displaySafeText(t.value)} (${t.count})`).join(", ")}`);
|
|
9694
9764
|
return lines2.join("\n");
|
|
9695
9765
|
}).join("\n\n");
|
|
9696
9766
|
}
|
|
@@ -10607,7 +10677,7 @@ function extractHtml(content, filePath) {
|
|
|
10607
10677
|
}
|
|
10608
10678
|
}
|
|
10609
10679
|
sections.sort((a, b) => a.line - b.line);
|
|
10610
|
-
const totalLines = code
|
|
10680
|
+
const totalLines = countContentLines(code);
|
|
10611
10681
|
assignFlatEndLines(sections, totalLines);
|
|
10612
10682
|
const seenId = /* @__PURE__ */ new Set();
|
|
10613
10683
|
const seenClass = /* @__PURE__ */ new Set();
|
|
@@ -10710,7 +10780,7 @@ function extractLiquid(content, filePath, relPath) {
|
|
|
10710
10780
|
const stem = path18.basename(resolvedRel, path18.extname(resolvedRel));
|
|
10711
10781
|
symbols.push({ filePath, name: stem, kind: "liquid_section_file", lineStart: 1, lineEnd: 1, body: "", docstring: "", parent: "" });
|
|
10712
10782
|
}
|
|
10713
|
-
const totalLines = content
|
|
10783
|
+
const totalLines = countContentLines(content);
|
|
10714
10784
|
for (const hm of findHtmlHeadingMatches(content)) {
|
|
10715
10785
|
if (hm.heading) {
|
|
10716
10786
|
const line = offsetToLine(lineIndex, hm.offset);
|
|
@@ -11687,12 +11757,64 @@ function extractZig(content, filePath) {
|
|
|
11687
11757
|
|
|
11688
11758
|
// src/languages/r.ts
|
|
11689
11759
|
var FUNC_ASSIGN_RE = /^([A-Za-z_][A-Za-z0-9_.]*)\s*(?:<-|=)\s*(?:function|\\)\s*\(/;
|
|
11690
|
-
var SETCLASS_RE =
|
|
11691
|
-
var SETMETHOD_RE =
|
|
11760
|
+
var SETCLASS_RE = /^(?:[A-Za-z_][A-Za-z0-9_.]*\s*(?:<-|=)\s*)?setClass\s*\(\s*["']([A-Za-z_][A-Za-z0-9_.]*)/;
|
|
11761
|
+
var SETMETHOD_RE = /^(?:[A-Za-z_][A-Za-z0-9_.]*\s*(?:<-|=)\s*)?setMethod\s*\(\s*["']([A-Za-z_][A-Za-z0-9_.]*)/;
|
|
11762
|
+
function matchingParenIndex(content, openIndex) {
|
|
11763
|
+
let depth = 0;
|
|
11764
|
+
let quote = null;
|
|
11765
|
+
for (let i = openIndex; i < content.length; i++) {
|
|
11766
|
+
const ch = content[i];
|
|
11767
|
+
if (quote !== null) {
|
|
11768
|
+
if (ch === "\\") {
|
|
11769
|
+
i++;
|
|
11770
|
+
continue;
|
|
11771
|
+
}
|
|
11772
|
+
if (ch === quote) quote = null;
|
|
11773
|
+
continue;
|
|
11774
|
+
}
|
|
11775
|
+
if (ch === "#") {
|
|
11776
|
+
while (i < content.length && content[i] !== "\n") i++;
|
|
11777
|
+
continue;
|
|
11778
|
+
}
|
|
11779
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
11780
|
+
quote = ch;
|
|
11781
|
+
continue;
|
|
11782
|
+
}
|
|
11783
|
+
if (ch === "(") depth++;
|
|
11784
|
+
else if (ch === ")") {
|
|
11785
|
+
depth--;
|
|
11786
|
+
if (depth === 0) return i;
|
|
11787
|
+
}
|
|
11788
|
+
}
|
|
11789
|
+
return null;
|
|
11790
|
+
}
|
|
11791
|
+
function bracedBodyEndLine(content, lineIndex, parenIndex, totalLines, fallback) {
|
|
11792
|
+
const close = matchingParenIndex(content, parenIndex);
|
|
11793
|
+
if (close === null) return fallback;
|
|
11794
|
+
let j = close + 1;
|
|
11795
|
+
while (j < content.length) {
|
|
11796
|
+
const ch = content[j];
|
|
11797
|
+
if (ch === "#") {
|
|
11798
|
+
while (j < content.length && content[j] !== "\n") j++;
|
|
11799
|
+
continue;
|
|
11800
|
+
}
|
|
11801
|
+
if (ch !== " " && ch !== " " && ch !== "\r" && ch !== "\n") break;
|
|
11802
|
+
j++;
|
|
11803
|
+
}
|
|
11804
|
+
if (content[j] !== "{") return fallback;
|
|
11805
|
+
return findMatchingBraceEndLine(content, j, totalLines, lineIndex, "#");
|
|
11806
|
+
}
|
|
11807
|
+
function callEndLine(content, lineIndex, parenIndex, fallback) {
|
|
11808
|
+
const close = matchingParenIndex(content, parenIndex);
|
|
11809
|
+
return close === null ? fallback : offsetToLine(lineIndex, close);
|
|
11810
|
+
}
|
|
11692
11811
|
function extractR(content, filePath) {
|
|
11693
11812
|
const symbols = [];
|
|
11694
11813
|
const imports = [];
|
|
11695
11814
|
const lines2 = content.split(/\r?\n/);
|
|
11815
|
+
const lineIndex = buildLineIndex(content);
|
|
11816
|
+
const totalLines = countContentLines(content);
|
|
11817
|
+
const spanBody = (startLine, endLine) => lines2.slice(startLine - 1, endLine).join("\n");
|
|
11696
11818
|
for (let i = 0; i < lines2.length; i++) {
|
|
11697
11819
|
const rawLine = lines2[i] ?? "";
|
|
11698
11820
|
const lineNum = i + 1;
|
|
@@ -11705,17 +11827,21 @@ function extractR(content, filePath) {
|
|
|
11705
11827
|
if (!isIndented) {
|
|
11706
11828
|
const fm = FUNC_ASSIGN_RE.exec(stripped);
|
|
11707
11829
|
if (fm) {
|
|
11708
|
-
|
|
11830
|
+
const parenIndex = (lineIndex[i] ?? 0) + fm[0].length - 1;
|
|
11831
|
+
const endLine = bracedBodyEndLine(content, lineIndex, parenIndex, totalLines, lineNum);
|
|
11832
|
+
symbols.push(makeSpanSymbol(filePath, fm[1] ?? "", "function", { startLine: lineNum, endLine, body: spanBody(lineNum, endLine) }, void 0, lines2, "hash"));
|
|
11709
11833
|
continue;
|
|
11710
11834
|
}
|
|
11711
11835
|
const cm = SETCLASS_RE.exec(stripped);
|
|
11712
11836
|
if (cm) {
|
|
11713
|
-
|
|
11837
|
+
const endLine = callEndLine(content, lineIndex, (lineIndex[i] ?? 0) + (cm.index + cm[0].indexOf("(")), lineNum);
|
|
11838
|
+
symbols.push(makeSpanSymbol(filePath, cm[1] ?? "", "class", { startLine: lineNum, endLine, body: spanBody(lineNum, endLine) }, void 0, lines2, "hash"));
|
|
11714
11839
|
continue;
|
|
11715
11840
|
}
|
|
11716
11841
|
const mm = SETMETHOD_RE.exec(stripped);
|
|
11717
11842
|
if (mm) {
|
|
11718
|
-
|
|
11843
|
+
const endLine = callEndLine(content, lineIndex, (lineIndex[i] ?? 0) + (mm.index + mm[0].indexOf("(")), lineNum);
|
|
11844
|
+
symbols.push(makeSpanSymbol(filePath, mm[1] ?? "", "function", { startLine: lineNum, endLine, body: spanBody(lineNum, endLine) }, void 0, lines2, "hash"));
|
|
11719
11845
|
}
|
|
11720
11846
|
}
|
|
11721
11847
|
}
|
|
@@ -11782,7 +11908,7 @@ function extractGraphql(content, filePath) {
|
|
|
11782
11908
|
}
|
|
11783
11909
|
}
|
|
11784
11910
|
const stripped = stripHashComments(descriptionsStripped);
|
|
11785
|
-
const totalLines = content
|
|
11911
|
+
const totalLines = countContentLines(content);
|
|
11786
11912
|
const lineIndex = buildLineIndex(stripped);
|
|
11787
11913
|
for (const m of stripped.matchAll(TYPE_RE)) {
|
|
11788
11914
|
const keyword = m.groups?.["keyword"] ?? "";
|
|
@@ -12058,7 +12184,7 @@ function extractSql(content, filePath) {
|
|
|
12058
12184
|
const sections = [];
|
|
12059
12185
|
const seen = /* @__PURE__ */ new Set();
|
|
12060
12186
|
const emit2 = makeSymbolEmitter(symbols, sections, seen, filePath, MAX_SYMBOLS3, MAX_HEADING_LEN2);
|
|
12061
|
-
const totalLines = content
|
|
12187
|
+
const totalLines = countContentLines(content);
|
|
12062
12188
|
const lineIndex = buildLineIndex(content);
|
|
12063
12189
|
const noStrings = stripSqlStringLiterals(content);
|
|
12064
12190
|
const singleLineEndLines = /* @__PURE__ */ new Map();
|
|
@@ -12260,7 +12386,7 @@ function extractMakefile(content, filePath) {
|
|
|
12260
12386
|
const seen = /* @__PURE__ */ new Set();
|
|
12261
12387
|
const emit2 = makeSymbolEmitter(symbols, sections, seen, filePath, MAX_SYMBOLS5, MAX_HEADING_LEN3);
|
|
12262
12388
|
const stripped = stripComments(content);
|
|
12263
|
-
const totalLines = content
|
|
12389
|
+
const totalLines = countContentLines(content);
|
|
12264
12390
|
const lineIndex = buildLineIndex(stripped);
|
|
12265
12391
|
const { noContinuation: strippedNoContinuation, forTargets: strippedForTargets } = maskContinuationAndDefines(stripped);
|
|
12266
12392
|
for (const m of strippedForTargets.matchAll(TARGET_RE)) {
|
|
@@ -12340,7 +12466,7 @@ function extractProto(content, filePath) {
|
|
|
12340
12466
|
const imports = [];
|
|
12341
12467
|
const emit2 = makeSymbolEmitter(symbols, sections, seen, filePath, MAX_SYMBOLS6, MAX_HEADING_LEN4);
|
|
12342
12468
|
const stripped = stripComments2(content);
|
|
12343
|
-
const totalLines = content
|
|
12469
|
+
const totalLines = countContentLines(content);
|
|
12344
12470
|
const lineIndex = buildLineIndex(stripped);
|
|
12345
12471
|
const blockEndLines = /* @__PURE__ */ new Map();
|
|
12346
12472
|
for (const m of stripped.matchAll(IMPORT_RE4)) {
|
|
@@ -12473,7 +12599,7 @@ function extractTerraform(content, filePath) {
|
|
|
12473
12599
|
const seen = /* @__PURE__ */ new Set();
|
|
12474
12600
|
const emit2 = makeSymbolEmitter(symbols, sections, seen, filePath, MAX_SYMBOLS7, MAX_HEADING_LEN5);
|
|
12475
12601
|
const stripped = stripComments3(maskHeredocs(content));
|
|
12476
|
-
const totalLines = content
|
|
12602
|
+
const totalLines = countContentLines(content);
|
|
12477
12603
|
const lineIndex = buildLineIndex(stripped);
|
|
12478
12604
|
const blockEndLines = /* @__PURE__ */ new Map();
|
|
12479
12605
|
const matches = [
|
|
@@ -13271,8 +13397,8 @@ function extractLwcJavaScript(content, filePath) {
|
|
|
13271
13397
|
const sourceLines = lines(content);
|
|
13272
13398
|
const bundle = bundleName(filePath);
|
|
13273
13399
|
const symbols = [
|
|
13274
|
-
symbol(filePath, bundle, "lwc_bundle", 1,
|
|
13275
|
-
symbol(filePath, lwcTagAlias(bundle), "lwc_component_alias", 1,
|
|
13400
|
+
symbol(filePath, bundle, "lwc_bundle", 1, countContentLines(content)),
|
|
13401
|
+
symbol(filePath, lwcTagAlias(bundle), "lwc_component_alias", 1, countContentLines(content))
|
|
13276
13402
|
];
|
|
13277
13403
|
const refs = [];
|
|
13278
13404
|
const commentFree = stripJsComments(content);
|
|
@@ -13370,10 +13496,9 @@ function attributeRefs(refs, content, filePath, attribute, split = false) {
|
|
|
13370
13496
|
function extractSalesforceMarkup(content, filePath) {
|
|
13371
13497
|
const normalized = filePath.replaceAll("\\", "/");
|
|
13372
13498
|
const extension = path20.posix.extname(normalized).toLowerCase();
|
|
13373
|
-
const sourceLines = lines(content);
|
|
13374
13499
|
const kind = MARKUP_KIND[extension] ?? "salesforce_markup";
|
|
13375
13500
|
const symbols = [
|
|
13376
|
-
symbol(filePath, markupArtifactName(normalized, extension), kind, 1,
|
|
13501
|
+
symbol(filePath, markupArtifactName(normalized, extension), kind, 1, countContentLines(content))
|
|
13377
13502
|
];
|
|
13378
13503
|
const refs = [];
|
|
13379
13504
|
const isAura = [".cmp", ".app", ".evt", ".intf", ".design", ".auradoc", ".tokens"].includes(extension);
|
|
@@ -13525,7 +13650,7 @@ function componentSymbol(filePath, name, kind, totalLines) {
|
|
|
13525
13650
|
return { filePath, name, kind, lineStart: 1, lineEnd: totalLines, body: "", docstring: "", parent: "" };
|
|
13526
13651
|
}
|
|
13527
13652
|
function extractVue(content, filePath) {
|
|
13528
|
-
const totalLines = content
|
|
13653
|
+
const totalLines = countContentLines(content);
|
|
13529
13654
|
const lineIndex = buildLineIndex(content);
|
|
13530
13655
|
const name = componentName(filePath);
|
|
13531
13656
|
const symbols = [componentSymbol(filePath, name, "vue_component", totalLines)];
|
|
@@ -13540,7 +13665,7 @@ function extractVue(content, filePath) {
|
|
|
13540
13665
|
return finalize(symbols, refs);
|
|
13541
13666
|
}
|
|
13542
13667
|
function extractSvelte(content, filePath) {
|
|
13543
|
-
const totalLines = content
|
|
13668
|
+
const totalLines = countContentLines(content);
|
|
13544
13669
|
const lineIndex = buildLineIndex(content);
|
|
13545
13670
|
const name = componentName(filePath);
|
|
13546
13671
|
const symbols = [componentSymbol(filePath, name, "svelte_component", totalLines)];
|
|
@@ -13573,7 +13698,7 @@ function detectAstroFrontmatter(content) {
|
|
|
13573
13698
|
return null;
|
|
13574
13699
|
}
|
|
13575
13700
|
function extractAstro(content, filePath) {
|
|
13576
|
-
const totalLines = content
|
|
13701
|
+
const totalLines = countContentLines(content);
|
|
13577
13702
|
const lineIndex = buildLineIndex(content);
|
|
13578
13703
|
const name = componentName(filePath);
|
|
13579
13704
|
const symbols = [componentSymbol(filePath, name, "astro_component", totalLines)];
|
|
@@ -13788,6 +13913,12 @@ var TSJS_KIND_BY_TYPE = /* @__PURE__ */ new Map([
|
|
|
13788
13913
|
["method_signature", "method"],
|
|
13789
13914
|
["property_signature", "var"],
|
|
13790
13915
|
["abstract_method_signature", "method"],
|
|
13916
|
+
// `declare function f(): void` parses as a `function_signature` inside an
|
|
13917
|
+
// ambient_declaration -- a distinct node type from `function_declaration`, which always
|
|
13918
|
+
// carries a body. Without an entry here every ambient function in a .d.ts file was
|
|
13919
|
+
// missing from the index entirely, the same container-drop shape as the module entries
|
|
13920
|
+
// below rather than a wrong span.
|
|
13921
|
+
["function_signature", "function"],
|
|
13791
13922
|
// `namespace Foo { ... }` (and the legacy `module Foo { ... }` synonym) parses as
|
|
13792
13923
|
// `internal_module`; `declare module "some-string" { ... }` (an ambient module declaration,
|
|
13793
13924
|
// common in .d.ts files) parses as `module` -- a distinct node type from either. Neither had a
|
|
@@ -13836,15 +13967,41 @@ function nodeName(node) {
|
|
|
13836
13967
|
if (named !== null) return named.text;
|
|
13837
13968
|
return null;
|
|
13838
13969
|
}
|
|
13970
|
+
var SPEC_DECLARATION_OWNER = /* @__PURE__ */ new Map([
|
|
13971
|
+
["variable_declarator", /* @__PURE__ */ new Set(["lexical_declaration", "variable_declaration"])],
|
|
13972
|
+
["var_spec", /* @__PURE__ */ new Set(["var_declaration"])],
|
|
13973
|
+
["const_spec", /* @__PURE__ */ new Set(["const_declaration"])],
|
|
13974
|
+
["type_spec", /* @__PURE__ */ new Set(["type_declaration"])]
|
|
13975
|
+
]);
|
|
13976
|
+
var PREFIX_WRAPPER_TYPES = /* @__PURE__ */ new Set(["export_statement", "ambient_declaration"]);
|
|
13977
|
+
function widenToDeclaration(node) {
|
|
13978
|
+
let widened = node;
|
|
13979
|
+
const owner = SPEC_DECLARATION_OWNER.get(widened.type);
|
|
13980
|
+
if (owner !== void 0) {
|
|
13981
|
+
const decl = widened.parent;
|
|
13982
|
+
if (decl === null || !owner.has(decl.type)) return widened;
|
|
13983
|
+
let specs = 0;
|
|
13984
|
+
for (const c of decl.namedChildren) if (c.type === widened.type) specs++;
|
|
13985
|
+
if (specs !== 1) return widened;
|
|
13986
|
+
if (decl.startPosition.row !== widened.startPosition.row) return widened;
|
|
13987
|
+
widened = decl;
|
|
13988
|
+
}
|
|
13989
|
+
for (; ; ) {
|
|
13990
|
+
const parent = widened.parent;
|
|
13991
|
+
if (parent === null || !PREFIX_WRAPPER_TYPES.has(parent.type)) return widened;
|
|
13992
|
+
widened = parent;
|
|
13993
|
+
}
|
|
13994
|
+
}
|
|
13839
13995
|
function makeSymbol(filePath, name, kind, node, lines2, style) {
|
|
13840
|
-
const
|
|
13996
|
+
const ranged = widenToDeclaration(node);
|
|
13997
|
+
const lineStart = ranged.startPosition.row + 1;
|
|
13841
13998
|
return {
|
|
13842
13999
|
filePath,
|
|
13843
14000
|
name,
|
|
13844
14001
|
kind,
|
|
13845
14002
|
lineStart,
|
|
13846
|
-
lineEnd:
|
|
13847
|
-
body:
|
|
14003
|
+
lineEnd: ranged.endPosition.row + 1,
|
|
14004
|
+
body: ranged.text,
|
|
13848
14005
|
docstring: lines2 !== void 0 && style !== void 0 ? precedingDocComment(lines2, lineStart, style) : "",
|
|
13849
14006
|
parent: ""
|
|
13850
14007
|
};
|
|
@@ -13883,13 +14040,23 @@ function extractTsJsSymbols(root, filePath, lines2) {
|
|
|
13883
14040
|
out.push(makeSymbol(filePath, name, kind, node, lines2, "c"));
|
|
13884
14041
|
} else {
|
|
13885
14042
|
const lineStart = decorators[0].startPosition.row + 1;
|
|
14043
|
+
const decoratedEnd = widenToDeclaration(node).endPosition.row + 1;
|
|
13886
14044
|
out.push({
|
|
13887
14045
|
filePath,
|
|
13888
14046
|
name,
|
|
13889
14047
|
kind,
|
|
13890
14048
|
lineStart,
|
|
13891
|
-
lineEnd:
|
|
13892
|
-
body
|
|
14049
|
+
lineEnd: decoratedEnd,
|
|
14050
|
+
// Read the body off the file rather than gluing the decorator and the node
|
|
14051
|
+
// together with a newline: `@dec export class X {}` has no newline between
|
|
14052
|
+
// them, and the glued form both invents one and drops the `export` that sits
|
|
14053
|
+
// between the two nodes. A decorated declaration yields one symbol, so taking
|
|
14054
|
+
// its whole span cannot fan out.
|
|
14055
|
+
// The trailing replace keeps a convention the rest of the index follows: a
|
|
14056
|
+
// tree-sitter node never carries the indentation of its own first line,
|
|
14057
|
+
// because it starts at the first real character. Reading the span off the
|
|
14058
|
+
// file would otherwise make decorated symbols the one shape that does.
|
|
14059
|
+
body: lines2.slice(lineStart - 1, decoratedEnd).join("\n").replace(/^[ \t]+/, ""),
|
|
13893
14060
|
docstring: precedingDocComment(lines2, lineStart, "c"),
|
|
13894
14061
|
parent: ""
|
|
13895
14062
|
});
|
|
@@ -13906,8 +14073,11 @@ function extractTsJsSymbols(root, filePath, lines2) {
|
|
|
13906
14073
|
const isFn = value !== null && (value.type === "arrow_function" || value.type === "function_expression" || value.type === "function");
|
|
13907
14074
|
out.push(makeSymbol(filePath, name.text, isFn ? "function" : "variable", child, lines2, "c"));
|
|
13908
14075
|
} else {
|
|
13909
|
-
|
|
13910
|
-
|
|
14076
|
+
const bindings = collectPatternBindings(name);
|
|
14077
|
+
const elideBodies = bindings.length > 1 && bindings.length * child.text.length > MAX_SYMBOL_BODY_CHARS;
|
|
14078
|
+
for (const bound of bindings) {
|
|
14079
|
+
const sym = makeSymbol(filePath, bound, "variable", child, lines2, "c");
|
|
14080
|
+
out.push(elideBodies ? { ...sym, body: "" } : sym);
|
|
13911
14081
|
}
|
|
13912
14082
|
}
|
|
13913
14083
|
}
|
|
@@ -15419,7 +15589,7 @@ function indexFileSync(filePath, dbPath = globalDbPath(), preReadBytes) {
|
|
|
15419
15589
|
throw err;
|
|
15420
15590
|
}
|
|
15421
15591
|
}
|
|
15422
|
-
const content = raw
|
|
15592
|
+
const content = decodeSource(raw);
|
|
15423
15593
|
const { symbols, refs } = parseContent(content, filePath, language);
|
|
15424
15594
|
writeParseResult(filePath, raw, { symbols, refs, language, duration: 0 }, dbPath);
|
|
15425
15595
|
}
|
|
@@ -15444,6 +15614,19 @@ var UNAVAILABLE_EMBED_SHA_PREFIX = "unavailable:";
|
|
|
15444
15614
|
function unavailableEmbedSha(sha) {
|
|
15445
15615
|
return UNAVAILABLE_EMBED_SHA_PREFIX + sha;
|
|
15446
15616
|
}
|
|
15617
|
+
function indexedPathSpellingIsStale(storedPath, absPath) {
|
|
15618
|
+
if (!isCaseInsensitiveFs()) return false;
|
|
15619
|
+
const stored = normalizePath(storedPath);
|
|
15620
|
+
const candidate = normalizePath(path22.resolve(absPath));
|
|
15621
|
+
if (foldPath(stored) !== foldPath(candidate)) return false;
|
|
15622
|
+
let real;
|
|
15623
|
+
try {
|
|
15624
|
+
real = normalizePath(fs21.realpathSync.native(absPath));
|
|
15625
|
+
} catch {
|
|
15626
|
+
return false;
|
|
15627
|
+
}
|
|
15628
|
+
return real !== stored && foldPath(real) === foldPath(stored);
|
|
15629
|
+
}
|
|
15447
15630
|
function isEmbedFresh(storedEmbedSha, sha, embeddingsEnabled, depsAvailable) {
|
|
15448
15631
|
if (storedEmbedSha === void 0) return false;
|
|
15449
15632
|
if (!embeddingsEnabled) return storedEmbedSha === disabledEmbedSha(sha);
|
|
@@ -15488,7 +15671,7 @@ async function indexFileEmbeddings(filePath, dbPath = globalDbPath(), sha, onErr
|
|
|
15488
15671
|
}
|
|
15489
15672
|
let content;
|
|
15490
15673
|
try {
|
|
15491
|
-
content = await fs21.promises.readFile(filePath
|
|
15674
|
+
content = decodeSource(await fs21.promises.readFile(filePath));
|
|
15492
15675
|
} catch {
|
|
15493
15676
|
return;
|
|
15494
15677
|
}
|
|
@@ -15626,6 +15809,41 @@ function pruneSystemTempFiles(dbPath = globalDbPath()) {
|
|
|
15626
15809
|
const db = getDb(dbPath);
|
|
15627
15810
|
return removeFilesBestEffort(db, findSystemTempFiles(dbPath));
|
|
15628
15811
|
}
|
|
15812
|
+
function findOrphanedChunkPaths(dbPath = globalDbPath()) {
|
|
15813
|
+
return orphanedChunkGroups(getDb(dbPath)).map((g) => g.representative);
|
|
15814
|
+
}
|
|
15815
|
+
function orphanedChunkGroups(db) {
|
|
15816
|
+
const known = new Set(
|
|
15817
|
+
db.prepare("SELECT DISTINCT path FROM files").all().map(
|
|
15818
|
+
(r) => foldPath(normalizePath(r.path))
|
|
15819
|
+
)
|
|
15820
|
+
);
|
|
15821
|
+
const rows = db.prepare("SELECT DISTINCT file_path FROM chunks").all();
|
|
15822
|
+
const byFolded = /* @__PURE__ */ new Map();
|
|
15823
|
+
for (const { file_path: raw } of rows) {
|
|
15824
|
+
const folded = foldPath(normalizePath(raw));
|
|
15825
|
+
if (known.has(folded)) continue;
|
|
15826
|
+
const group = byFolded.get(folded);
|
|
15827
|
+
if (group === void 0) byFolded.set(folded, { representative: raw, spellings: [raw] });
|
|
15828
|
+
else group.spellings.push(raw);
|
|
15829
|
+
}
|
|
15830
|
+
return [...byFolded.values()];
|
|
15831
|
+
}
|
|
15832
|
+
function pruneOrphanedChunks(dbPath = globalDbPath()) {
|
|
15833
|
+
const db = getDb(dbPath);
|
|
15834
|
+
const removed = [];
|
|
15835
|
+
const run = db.transaction(() => {
|
|
15836
|
+
for (const group of orphanedChunkGroups(db)) {
|
|
15837
|
+
try {
|
|
15838
|
+
for (const spelling of group.spellings) deleteFileEmbeddings(db, spelling);
|
|
15839
|
+
removed.push(group.representative);
|
|
15840
|
+
} catch {
|
|
15841
|
+
}
|
|
15842
|
+
}
|
|
15843
|
+
});
|
|
15844
|
+
run.immediate();
|
|
15845
|
+
return removed;
|
|
15846
|
+
}
|
|
15629
15847
|
function recordKnownRoot(filePath, dbPath = globalDbPath()) {
|
|
15630
15848
|
const project = findProject(path23.dirname(filePath));
|
|
15631
15849
|
if (project === null || isTooShallowToPrune(project.root)) return;
|
|
@@ -15680,7 +15898,8 @@ function sweepKnownRoots(dbPath = globalDbPath(), opts) {
|
|
|
15680
15898
|
prunedRows += removeDeletedFilesBestEffort(db, deletable).length;
|
|
15681
15899
|
prunedRoots.push(root);
|
|
15682
15900
|
}
|
|
15683
|
-
|
|
15901
|
+
const prunedOrphanChunkPaths = pruneOrphanedChunks(dbPath);
|
|
15902
|
+
return { prunedRows, prunedRoots, flaggedRoots, prunedOrphanChunkPaths };
|
|
15684
15903
|
}
|
|
15685
15904
|
var KNOWN_ROOT_RECORD_MIN_INTERVAL_MS = 60 * 60 * 1e3;
|
|
15686
15905
|
function knownRootRecordMarkerPath(dir, filePath) {
|
|
@@ -15821,11 +16040,25 @@ function pidFileIsWithinStartupGrace(dir) {
|
|
|
15821
16040
|
return false;
|
|
15822
16041
|
}
|
|
15823
16042
|
}
|
|
16043
|
+
var ENCODED_LINE_MARKER = "!";
|
|
16044
|
+
function encodeDirtyQueueLine(absPath) {
|
|
16045
|
+
const needsEncoding = /[\r\n]/.test(absPath) || absPath !== absPath.trim();
|
|
16046
|
+
return needsEncoding ? ENCODED_LINE_MARKER + JSON.stringify(absPath) : absPath;
|
|
16047
|
+
}
|
|
16048
|
+
function decodeDirtyQueueLine(line) {
|
|
16049
|
+
if (!line.startsWith(ENCODED_LINE_MARKER)) return line;
|
|
16050
|
+
try {
|
|
16051
|
+
const decoded = JSON.parse(line.slice(ENCODED_LINE_MARKER.length));
|
|
16052
|
+
return typeof decoded === "string" ? decoded : line;
|
|
16053
|
+
} catch {
|
|
16054
|
+
return line;
|
|
16055
|
+
}
|
|
16056
|
+
}
|
|
15824
16057
|
function parseDirtyQueueLines(raw) {
|
|
15825
16058
|
const seen = /* @__PURE__ */ new Set();
|
|
15826
16059
|
const out = [];
|
|
15827
16060
|
for (const line of raw.split("\n")) {
|
|
15828
|
-
const trimmed = line.trim();
|
|
16061
|
+
const trimmed = decodeDirtyQueueLine(line.trim());
|
|
15829
16062
|
if (trimmed === "") continue;
|
|
15830
16063
|
const normalized = normalizePath(trimmed);
|
|
15831
16064
|
const dedupeKey = foldPath(normalized);
|
|
@@ -15913,10 +16146,10 @@ function embedFileSerialized(absPath, dbPath, sha) {
|
|
|
15913
16146
|
activeEmbedSlots += 1;
|
|
15914
16147
|
return dispatchEmbed();
|
|
15915
16148
|
}
|
|
15916
|
-
return new Promise((
|
|
16149
|
+
return new Promise((resolve10) => {
|
|
15917
16150
|
embedSlotWaiters.push(() => {
|
|
15918
16151
|
activeEmbedSlots += 1;
|
|
15919
|
-
|
|
16152
|
+
resolve10(dispatchEmbed());
|
|
15920
16153
|
});
|
|
15921
16154
|
});
|
|
15922
16155
|
};
|
|
@@ -15970,7 +16203,7 @@ function appendToDirtyQueue(dir, absPath) {
|
|
|
15970
16203
|
if (existing.length > 0 && !existing.endsWith("\n")) leadingNewline = "\n";
|
|
15971
16204
|
} catch {
|
|
15972
16205
|
}
|
|
15973
|
-
fs23.appendFileSync(queuePath, `${leadingNewline}${absPath}
|
|
16206
|
+
fs23.appendFileSync(queuePath, `${leadingNewline}${encodeDirtyQueueLine(absPath)}
|
|
15974
16207
|
`);
|
|
15975
16208
|
} catch {
|
|
15976
16209
|
}
|
|
@@ -15988,7 +16221,7 @@ function makeIndexer(dbPath) {
|
|
|
15988
16221
|
return true;
|
|
15989
16222
|
}
|
|
15990
16223
|
const entry = getFileEntry(absPath, dbPath);
|
|
15991
|
-
const parseUnchanged = entry?.sha === sha;
|
|
16224
|
+
const parseUnchanged = entry?.sha === sha && !(entry !== null && indexedPathSpellingIsStale(entry.filePath, absPath));
|
|
15992
16225
|
if (!parseUnchanged) {
|
|
15993
16226
|
indexFileSync(absPath, dbPath);
|
|
15994
16227
|
}
|
|
@@ -16021,7 +16254,7 @@ function processDirtyBatch(paths, index = makeIndexer(globalDbPath()), remove =
|
|
|
16021
16254
|
if (!p) continue;
|
|
16022
16255
|
writeDrainHeartbeat(dir);
|
|
16023
16256
|
if (isUnderBlockedRoot(p, blockedRoots)) continue;
|
|
16024
|
-
if (
|
|
16257
|
+
if (fileIsAbsent(p)) {
|
|
16025
16258
|
remove(p);
|
|
16026
16259
|
continue;
|
|
16027
16260
|
}
|
|
@@ -16253,6 +16486,12 @@ function claimWorkerPidFile(dir, pid) {
|
|
|
16253
16486
|
if (existingPid !== null && pidAlive(existingPid) && (hasFreshWorkerHeartbeat(dir, existingPid) || pidFileIsWithinStartupGrace(dir))) {
|
|
16254
16487
|
return false;
|
|
16255
16488
|
}
|
|
16489
|
+
if (existingPid !== null && pidAlive(existingPid) && existingPid !== pid && existingPid !== process.pid) {
|
|
16490
|
+
try {
|
|
16491
|
+
process.kill(existingPid, "SIGTERM");
|
|
16492
|
+
} catch {
|
|
16493
|
+
}
|
|
16494
|
+
}
|
|
16256
16495
|
try {
|
|
16257
16496
|
fs23.rmSync(pidPath, { force: true });
|
|
16258
16497
|
} catch {
|
|
@@ -16352,7 +16591,7 @@ async function runWorkerLoop(dir, pollIntervalMs, shouldStop = () => false) {
|
|
|
16352
16591
|
lastKnownRootsSweepMs = Date.now();
|
|
16353
16592
|
}
|
|
16354
16593
|
if (shouldStop()) break;
|
|
16355
|
-
await new Promise((
|
|
16594
|
+
await new Promise((resolve10) => setTimeout(resolve10, pollIntervalMs));
|
|
16356
16595
|
}
|
|
16357
16596
|
}
|
|
16358
16597
|
function runDetachedWorkerDaemon() {
|
|
@@ -16391,7 +16630,7 @@ function appendDirtyPath(normalizedPath2) {
|
|
|
16391
16630
|
if (existing.length > 0 && !existing.endsWith("\n")) leadingNewline = "\n";
|
|
16392
16631
|
} catch {
|
|
16393
16632
|
}
|
|
16394
|
-
fs24.appendFileSync(queuePath, `${leadingNewline}${normalizedPath2}
|
|
16633
|
+
fs24.appendFileSync(queuePath, `${leadingNewline}${encodeDirtyQueueLine(normalizedPath2)}
|
|
16395
16634
|
`);
|
|
16396
16635
|
}
|
|
16397
16636
|
function enqueueDirtyPathSafe(filePath, opts) {
|
|
@@ -16482,7 +16721,7 @@ import * as readline from "node:readline";
|
|
|
16482
16721
|
async function defaultConfirm(question) {
|
|
16483
16722
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
16484
16723
|
try {
|
|
16485
|
-
const answer = await new Promise((
|
|
16724
|
+
const answer = await new Promise((resolve10) => rl.question(question, resolve10));
|
|
16486
16725
|
return /^y(es)?$/i.test(answer.trim());
|
|
16487
16726
|
} finally {
|
|
16488
16727
|
rl.close();
|
|
@@ -17533,6 +17772,7 @@ export {
|
|
|
17533
17772
|
tomlBracketDelta,
|
|
17534
17773
|
isParseSkipEligible,
|
|
17535
17774
|
indexFileSync,
|
|
17775
|
+
indexedPathSpellingIsStale,
|
|
17536
17776
|
isEmbedFresh,
|
|
17537
17777
|
indexFileEmbeddings,
|
|
17538
17778
|
removeFileFromIndex,
|
|
@@ -17540,6 +17780,8 @@ export {
|
|
|
17540
17780
|
pruneBlockedRoot,
|
|
17541
17781
|
findSystemTempFiles,
|
|
17542
17782
|
pruneSystemTempFiles,
|
|
17783
|
+
findOrphanedChunkPaths,
|
|
17784
|
+
pruneOrphanedChunks,
|
|
17543
17785
|
recordKnownRootThrottled,
|
|
17544
17786
|
WORKER_HEARTBEAT_STALE_MS,
|
|
17545
17787
|
dirtyQueuePathFor,
|