@cortexkit/aft-opencode 0.43.1 → 0.45.0
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/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +241 -97
- package/dist/tools/ast.d.ts.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tui/badge-contrast.d.ts +15 -0
- package/dist/tui/badge-contrast.d.ts.map +1 -0
- package/dist/tui.js +176 -22
- package/package.json +8 -8
- package/src/tui/badge-contrast.ts +43 -0
- package/src/tui/sidebar.tsx +3 -2
package/dist/index.js
CHANGED
|
@@ -8233,6 +8233,8 @@ function resolveBashKillTimeout(modelTimeout, foregroundWaitMs) {
|
|
|
8233
8233
|
}
|
|
8234
8234
|
// ../aft-bridge/dist/bridge.js
|
|
8235
8235
|
import { spawn } from "node:child_process";
|
|
8236
|
+
import { createHash } from "node:crypto";
|
|
8237
|
+
import { readFileSync } from "node:fs";
|
|
8236
8238
|
import { homedir as homedir2 } from "node:os";
|
|
8237
8239
|
import { join as join2 } from "node:path";
|
|
8238
8240
|
import { StringDecoder } from "node:string_decoder";
|
|
@@ -8332,6 +8334,22 @@ function bashTaskIdFrom(response) {
|
|
|
8332
8334
|
return camelCase;
|
|
8333
8335
|
return;
|
|
8334
8336
|
}
|
|
8337
|
+
function hashBinaryOnDisk(binaryPath) {
|
|
8338
|
+
try {
|
|
8339
|
+
return createHash("sha256").update(readFileSync(binaryPath)).digest("hex");
|
|
8340
|
+
} catch {
|
|
8341
|
+
return null;
|
|
8342
|
+
}
|
|
8343
|
+
}
|
|
8344
|
+
var binaryFingerprintReader = hashBinaryOnDisk;
|
|
8345
|
+
function readBinaryFingerprint(binaryPath) {
|
|
8346
|
+
try {
|
|
8347
|
+
const fingerprint = binaryFingerprintReader(binaryPath);
|
|
8348
|
+
return typeof fingerprint === "string" && fingerprint.length > 0 ? fingerprint : null;
|
|
8349
|
+
} catch {
|
|
8350
|
+
return null;
|
|
8351
|
+
}
|
|
8352
|
+
}
|
|
8335
8353
|
function tagStderrLine(line) {
|
|
8336
8354
|
return /^\[aft(-\w+)?\] /.test(line) ? line : `[aft] ${line}`;
|
|
8337
8355
|
}
|
|
@@ -8427,6 +8445,9 @@ class BinaryBridge {
|
|
|
8427
8445
|
binaryPath;
|
|
8428
8446
|
cwd;
|
|
8429
8447
|
process = null;
|
|
8448
|
+
spawnedBinaryFingerprint = null;
|
|
8449
|
+
lastBinaryFingerprintCheckAt = 0;
|
|
8450
|
+
_retiringDueToBinaryChange = false;
|
|
8430
8451
|
pending = new Map;
|
|
8431
8452
|
outstandingBackgroundTaskIds = new Set;
|
|
8432
8453
|
nextId = 1;
|
|
@@ -8546,6 +8567,24 @@ class BinaryBridge {
|
|
|
8546
8567
|
hasOutstandingBackgroundTasks() {
|
|
8547
8568
|
return this.outstandingBackgroundTaskIds.size > 0;
|
|
8548
8569
|
}
|
|
8570
|
+
maybeScheduleRespawnForUpdatedBinary(checkIntervalMs, now = Date.now()) {
|
|
8571
|
+
if (this._shuttingDown || this._retiringDueToBinaryChange || !this.isAlive())
|
|
8572
|
+
return false;
|
|
8573
|
+
if (this.pending.size > 0 || this.outstandingBackgroundTaskIds.size > 0)
|
|
8574
|
+
return false;
|
|
8575
|
+
if (now - this.lastBinaryFingerprintCheckAt < checkIntervalMs)
|
|
8576
|
+
return false;
|
|
8577
|
+
this.lastBinaryFingerprintCheckAt = now;
|
|
8578
|
+
const spawnedFingerprint = this.spawnedBinaryFingerprint;
|
|
8579
|
+
if (!spawnedFingerprint)
|
|
8580
|
+
return false;
|
|
8581
|
+
const currentFingerprint = readBinaryFingerprint(this.binaryPath);
|
|
8582
|
+
if (!currentFingerprint || currentFingerprint === spawnedFingerprint)
|
|
8583
|
+
return false;
|
|
8584
|
+
this._retiringDueToBinaryChange = true;
|
|
8585
|
+
this.logVia(`Binary contents changed on disk for ${this.binaryPath}; retiring this bridge so the next tool call respawns onto the updated binary.`);
|
|
8586
|
+
return true;
|
|
8587
|
+
}
|
|
8549
8588
|
getCwd() {
|
|
8550
8589
|
return this.cwd;
|
|
8551
8590
|
}
|
|
@@ -8578,6 +8617,9 @@ class BinaryBridge {
|
|
|
8578
8617
|
}
|
|
8579
8618
|
async sendWithVersionMismatchRetry(command, params, options, canRetryAfterVersionSwap) {
|
|
8580
8619
|
try {
|
|
8620
|
+
if (this._retiringDueToBinaryChange) {
|
|
8621
|
+
throw new Error(`${this.errorPrefix} Bridge is retiring after the on-disk binary changed; retry to respawn on the updated binary`);
|
|
8622
|
+
}
|
|
8581
8623
|
if (this._shuttingDown) {
|
|
8582
8624
|
throw new Error(`${this.errorPrefix} Bridge is shutting down, cannot send "${command}"`);
|
|
8583
8625
|
}
|
|
@@ -8776,6 +8818,7 @@ class BinaryBridge {
|
|
|
8776
8818
|
}
|
|
8777
8819
|
async shutdown() {
|
|
8778
8820
|
this._shuttingDown = true;
|
|
8821
|
+
this.spawnedBinaryFingerprint = null;
|
|
8779
8822
|
this.clearRestartResetTimer();
|
|
8780
8823
|
this.configureWarningClients.clear();
|
|
8781
8824
|
this.rejectAllPending(new Error(`${this.errorPrefix} Bridge shutting down`));
|
|
@@ -8829,6 +8872,9 @@ class BinaryBridge {
|
|
|
8829
8872
|
async replaceCurrentBinary(newBinaryPath) {
|
|
8830
8873
|
this.binaryPath = newBinaryPath;
|
|
8831
8874
|
this.configured = false;
|
|
8875
|
+
this.spawnedBinaryFingerprint = null;
|
|
8876
|
+
this.lastBinaryFingerprintCheckAt = 0;
|
|
8877
|
+
this._retiringDueToBinaryChange = false;
|
|
8832
8878
|
this.clearRestartResetTimer();
|
|
8833
8879
|
this.rejectAllPending(new Error(`${this.errorPrefix} Bridge restarting with updated binary: ${newBinaryPath}`));
|
|
8834
8880
|
if (!this.process)
|
|
@@ -8854,6 +8900,7 @@ class BinaryBridge {
|
|
|
8854
8900
|
this.spawnProcess(triggeringSessionId);
|
|
8855
8901
|
}
|
|
8856
8902
|
spawnProcess(triggeringSessionId) {
|
|
8903
|
+
this._retiringDueToBinaryChange = false;
|
|
8857
8904
|
this.lastStatusBar = undefined;
|
|
8858
8905
|
if (triggeringSessionId) {
|
|
8859
8906
|
this.sessionLogVia(triggeringSessionId, `Spawning binary: ${this.binaryPath} (cwd: ${this.cwd})`);
|
|
@@ -8944,6 +8991,8 @@ class BinaryBridge {
|
|
|
8944
8991
|
this.handleCrash();
|
|
8945
8992
|
});
|
|
8946
8993
|
this.process = child;
|
|
8994
|
+
this.spawnedBinaryFingerprint = readBinaryFingerprint(this.binaryPath);
|
|
8995
|
+
this.lastBinaryFingerprintCheckAt = Date.now();
|
|
8947
8996
|
this.stdoutBuffer = "";
|
|
8948
8997
|
this.stdoutReadOffset = 0;
|
|
8949
8998
|
this.stderrBuffer = "";
|
|
@@ -9122,6 +9171,7 @@ class BinaryBridge {
|
|
|
9122
9171
|
}
|
|
9123
9172
|
handleTimeout(triggeringSessionId) {
|
|
9124
9173
|
this.consecutiveRequestTimeouts = 0;
|
|
9174
|
+
this.spawnedBinaryFingerprint = null;
|
|
9125
9175
|
this.rejectAllPending(new Error(`${this.errorPrefix} bridge killed during sibling timeout — request aborted`));
|
|
9126
9176
|
this.outstandingBackgroundTaskIds.clear();
|
|
9127
9177
|
if (this.process) {
|
|
@@ -9148,6 +9198,7 @@ class BinaryBridge {
|
|
|
9148
9198
|
handleCrash(cause) {
|
|
9149
9199
|
const proc = this.process;
|
|
9150
9200
|
this.process = null;
|
|
9201
|
+
this.spawnedBinaryFingerprint = null;
|
|
9151
9202
|
if (proc && proc.exitCode === null && !proc.killed) {
|
|
9152
9203
|
proc.kill("SIGKILL");
|
|
9153
9204
|
}
|
|
@@ -9159,6 +9210,10 @@ class BinaryBridge {
|
|
|
9159
9210
|
this.errorVia(`Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""}.${tail}`);
|
|
9160
9211
|
}
|
|
9161
9212
|
this.rejectAllPending(new Error(`${this.errorPrefix} Binary crashed (restarts: ${this._restartCount})${cause ? `: ${cause.message}` : ""} (see ${this.getLogFilePathVia()})`));
|
|
9213
|
+
if (this._retiringDueToBinaryChange) {
|
|
9214
|
+
this.logVia("Binary exited while retiring after an on-disk update; skipping auto-restart");
|
|
9215
|
+
return;
|
|
9216
|
+
}
|
|
9162
9217
|
if (this._restartCount < this.maxRestarts) {
|
|
9163
9218
|
const delay = 100 * 2 ** this._restartCount;
|
|
9164
9219
|
this._restartCount++;
|
|
@@ -9288,13 +9343,13 @@ function isEmptyParam(value) {
|
|
|
9288
9343
|
return false;
|
|
9289
9344
|
}
|
|
9290
9345
|
// ../aft-bridge/dist/config-tiers.js
|
|
9291
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
9346
|
+
import { existsSync, readFileSync as readFileSync2 } from "node:fs";
|
|
9292
9347
|
import { resolve as resolve2 } from "node:path";
|
|
9293
9348
|
function readConfigTiers(opts) {
|
|
9294
9349
|
const tiers = [];
|
|
9295
9350
|
try {
|
|
9296
9351
|
if (existsSync(opts.userConfigPath)) {
|
|
9297
|
-
const doc =
|
|
9352
|
+
const doc = readFileSync2(opts.userConfigPath, "utf-8");
|
|
9298
9353
|
tiers.push({
|
|
9299
9354
|
tier: "user",
|
|
9300
9355
|
source: resolve2(opts.userConfigPath),
|
|
@@ -9304,7 +9359,7 @@ function readConfigTiers(opts) {
|
|
|
9304
9359
|
} catch {}
|
|
9305
9360
|
try {
|
|
9306
9361
|
if (existsSync(opts.projectConfigPath)) {
|
|
9307
|
-
const doc =
|
|
9362
|
+
const doc = readFileSync2(opts.projectConfigPath, "utf-8");
|
|
9308
9363
|
tiers.push({
|
|
9309
9364
|
tier: "project",
|
|
9310
9365
|
source: resolve2(opts.projectConfigPath),
|
|
@@ -9322,8 +9377,8 @@ function formatDroppedKeyWarnings(dropped) {
|
|
|
9322
9377
|
}
|
|
9323
9378
|
// ../aft-bridge/dist/downloader.js
|
|
9324
9379
|
import { spawnSync } from "node:child_process";
|
|
9325
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
9326
|
-
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync as existsSync2, mkdirSync, openSync, readFileSync as
|
|
9380
|
+
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
9381
|
+
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync as existsSync2, mkdirSync, openSync, readFileSync as readFileSync3, renameSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
9327
9382
|
import { homedir as homedir3 } from "node:os";
|
|
9328
9383
|
import { join as join3 } from "node:path";
|
|
9329
9384
|
import { Readable } from "node:stream";
|
|
@@ -9467,7 +9522,7 @@ async function downloadBinary(version) {
|
|
|
9467
9522
|
warn(`Checksum verification failed: checksums.sha256 found but no entry for ${assetName}. ` + "Binary download aborted for security reasons.");
|
|
9468
9523
|
return null;
|
|
9469
9524
|
}
|
|
9470
|
-
const hash =
|
|
9525
|
+
const hash = createHash2("sha256");
|
|
9471
9526
|
let bytesWritten = 0;
|
|
9472
9527
|
const guard = new TransformStream({
|
|
9473
9528
|
transform(chunk, controller) {
|
|
@@ -9551,7 +9606,7 @@ async function acquireDownloadLock(lockPath) {
|
|
|
9551
9606
|
closeSync(fd);
|
|
9552
9607
|
} catch {}
|
|
9553
9608
|
try {
|
|
9554
|
-
if (
|
|
9609
|
+
if (readFileSync3(lockPath, "utf-8") === owner) {
|
|
9555
9610
|
rmSync(lockPath, { force: true });
|
|
9556
9611
|
}
|
|
9557
9612
|
} catch {}
|
|
@@ -9623,12 +9678,12 @@ function stripJsoncSymbols(value) {
|
|
|
9623
9678
|
}
|
|
9624
9679
|
// ../aft-bridge/dist/migration.js
|
|
9625
9680
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
9626
|
-
import { closeSync as closeSync3, existsSync as existsSync5, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as
|
|
9681
|
+
import { closeSync as closeSync3, existsSync as existsSync5, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as readFileSync5, renameSync as renameSync4, rmSync as rmSync2, statSync as statSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
9627
9682
|
import { homedir as homedir6, tmpdir } from "node:os";
|
|
9628
9683
|
import { basename, dirname as dirname2, join as join6, resolve as resolve4 } from "node:path";
|
|
9629
9684
|
|
|
9630
9685
|
// ../aft-bridge/dist/paths.js
|
|
9631
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as
|
|
9686
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync } from "node:fs";
|
|
9632
9687
|
import { homedir as homedir4 } from "node:os";
|
|
9633
9688
|
import { dirname, isAbsolute as isAbsolute2, join as join4, resolve as resolve3 } from "node:path";
|
|
9634
9689
|
function homeDir() {
|
|
@@ -9702,7 +9757,7 @@ function shouldShowAnnouncement(storageRoot, harness, currentVersion) {
|
|
|
9702
9757
|
let lastVersion = "";
|
|
9703
9758
|
try {
|
|
9704
9759
|
if (existsSync3(versionFile)) {
|
|
9705
|
-
lastVersion =
|
|
9760
|
+
lastVersion = readFileSync4(versionFile, "utf-8").trim();
|
|
9706
9761
|
}
|
|
9707
9762
|
} catch {
|
|
9708
9763
|
return false;
|
|
@@ -10099,7 +10154,7 @@ function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
|
10099
10154
|
let fd = null;
|
|
10100
10155
|
try {
|
|
10101
10156
|
fd = openSync3(tmpPath, "wx", 384);
|
|
10102
|
-
writeFileSync2(fd,
|
|
10157
|
+
writeFileSync2(fd, readFileSync5(sourcePath));
|
|
10103
10158
|
closeSync3(fd);
|
|
10104
10159
|
fd = null;
|
|
10105
10160
|
renameSync4(tmpPath, targetPath);
|
|
@@ -10178,7 +10233,7 @@ function markLegacySourcesMovedAside(sources, targetPath, logger) {
|
|
|
10178
10233
|
const desiredMarkerPath = `${source.path}${MOVED_MARKER_SUFFIX}`;
|
|
10179
10234
|
const markerPath = nonClobberingSidecarPath(desiredMarkerPath);
|
|
10180
10235
|
try {
|
|
10181
|
-
const original =
|
|
10236
|
+
const original = readFileSync5(source.path, "utf-8");
|
|
10182
10237
|
if (markerPath !== desiredMarkerPath) {
|
|
10183
10238
|
logger?.warn?.(`Preserving existing legacy AFT marker ${desiredMarkerPath}; writing new marker to ${markerPath}`);
|
|
10184
10239
|
}
|
|
@@ -10247,10 +10302,10 @@ function migrateAftConfigFile(opts) {
|
|
|
10247
10302
|
try {
|
|
10248
10303
|
const sources = existingSources.map((source) => ({
|
|
10249
10304
|
...source,
|
|
10250
|
-
content:
|
|
10305
|
+
content: readFileSync5(source.path, "utf-8")
|
|
10251
10306
|
}));
|
|
10252
10307
|
if (existsSync5(opts.targetPath)) {
|
|
10253
|
-
const targetContent =
|
|
10308
|
+
const targetContent = readFileSync5(opts.targetPath, "utf-8");
|
|
10254
10309
|
for (const source of sources) {
|
|
10255
10310
|
if (fileSemanticsMatch(source.content, targetContent))
|
|
10256
10311
|
continue;
|
|
@@ -10484,8 +10539,8 @@ function isNpmAvailable(deps = defaultDeps()) {
|
|
|
10484
10539
|
}
|
|
10485
10540
|
// ../aft-bridge/dist/onnx-runtime.js
|
|
10486
10541
|
import { execFileSync } from "node:child_process";
|
|
10487
|
-
import { createHash as
|
|
10488
|
-
import { chmodSync as chmodSync3, closeSync as closeSync4, copyFileSync as copyFileSync3, createWriteStream as createWriteStream2, existsSync as existsSync6, lstatSync, mkdirSync as mkdirSync5, openSync as openSync4, readdirSync as readdirSync2, readFileSync as
|
|
10542
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
10543
|
+
import { chmodSync as chmodSync3, closeSync as closeSync4, copyFileSync as copyFileSync3, createWriteStream as createWriteStream2, existsSync as existsSync6, lstatSync, mkdirSync as mkdirSync5, openSync as openSync4, readdirSync as readdirSync2, readFileSync as readFileSync6, readlinkSync, realpathSync, rmSync as rmSync3, statSync as statSync4, symlinkSync, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
10489
10544
|
import { basename as basename2, dirname as dirname4, isAbsolute as isAbsolute4, join as join8, relative as relative2, resolve as resolve5, win32 } from "node:path";
|
|
10490
10545
|
import { Readable as Readable2 } from "node:stream";
|
|
10491
10546
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
@@ -11038,7 +11093,7 @@ function readOnnxInstalledMeta(installDir) {
|
|
|
11038
11093
|
try {
|
|
11039
11094
|
if (!statSync4(path2).isFile())
|
|
11040
11095
|
return null;
|
|
11041
|
-
const raw =
|
|
11096
|
+
const raw = readFileSync6(path2, "utf8");
|
|
11042
11097
|
const parsed = JSON.parse(raw);
|
|
11043
11098
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
11044
11099
|
return null;
|
|
@@ -11053,8 +11108,8 @@ function readOnnxInstalledMeta(installDir) {
|
|
|
11053
11108
|
}
|
|
11054
11109
|
}
|
|
11055
11110
|
function sha256File(path2) {
|
|
11056
|
-
const hash =
|
|
11057
|
-
hash.update(
|
|
11111
|
+
const hash = createHash3("sha256");
|
|
11112
|
+
hash.update(readFileSync6(path2));
|
|
11058
11113
|
return hash.digest("hex");
|
|
11059
11114
|
}
|
|
11060
11115
|
function acquireLock(lockPath) {
|
|
@@ -11082,7 +11137,7 @@ ${new Date().toISOString()}
|
|
|
11082
11137
|
let owningPid = null;
|
|
11083
11138
|
let lockMtimeMs = 0;
|
|
11084
11139
|
try {
|
|
11085
|
-
const raw =
|
|
11140
|
+
const raw = readFileSync6(lockPath, "utf8");
|
|
11086
11141
|
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
11087
11142
|
const parsed = Number.parseInt(firstLine, 10);
|
|
11088
11143
|
if (Number.isFinite(parsed) && parsed > 0)
|
|
@@ -11107,7 +11162,7 @@ function releaseLock(lockPath) {
|
|
|
11107
11162
|
try {
|
|
11108
11163
|
let owningPid = null;
|
|
11109
11164
|
try {
|
|
11110
|
-
const raw =
|
|
11165
|
+
const raw = readFileSync6(lockPath, "utf8");
|
|
11111
11166
|
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
11112
11167
|
const parsed = Number.parseInt(firstLine, 10);
|
|
11113
11168
|
if (Number.isFinite(parsed) && parsed > 0)
|
|
@@ -11171,7 +11226,7 @@ function isProcessAlive(pid) {
|
|
|
11171
11226
|
}
|
|
11172
11227
|
}
|
|
11173
11228
|
// ../aft-bridge/dist/project-identity.js
|
|
11174
|
-
import { createHash as
|
|
11229
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
11175
11230
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
11176
11231
|
import { resolve as resolve6 } from "node:path";
|
|
11177
11232
|
function canonicalizeProjectRoot(dir) {
|
|
@@ -11202,7 +11257,7 @@ function normalizeWindowsRoot(p) {
|
|
|
11202
11257
|
return s;
|
|
11203
11258
|
}
|
|
11204
11259
|
function projectRootKeyHash(dir) {
|
|
11205
|
-
return
|
|
11260
|
+
return createHash4("sha256").update(canonicalizeProjectRoot(dir)).digest("hex").slice(0, 16);
|
|
11206
11261
|
}
|
|
11207
11262
|
|
|
11208
11263
|
// ../aft-bridge/dist/pool.js
|
|
@@ -11286,6 +11341,11 @@ class BridgePool {
|
|
|
11286
11341
|
for (const [dir, entry] of this.bridges) {
|
|
11287
11342
|
if (entry.bridge.hasPendingRequests() || entry.bridge.hasOutstandingBackgroundTasks())
|
|
11288
11343
|
continue;
|
|
11344
|
+
if (entry.bridge.maybeScheduleRespawnForUpdatedBinary(CLEANUP_INTERVAL_MS, now)) {
|
|
11345
|
+
this.staleBridges.add(entry.bridge);
|
|
11346
|
+
this.bridges.delete(dir);
|
|
11347
|
+
continue;
|
|
11348
|
+
}
|
|
11289
11349
|
if (now - entry.lastUsed > this.idleTimeoutMs) {
|
|
11290
11350
|
entry.bridge.shutdown().catch((err) => this.error("cleanup shutdown failed:", err));
|
|
11291
11351
|
this.bridges.delete(dir);
|
|
@@ -11382,10 +11442,11 @@ class BridgePool {
|
|
|
11382
11442
|
function normalizeKey(projectRoot) {
|
|
11383
11443
|
return canonicalizeProjectRoot(projectRoot);
|
|
11384
11444
|
}
|
|
11385
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
11445
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.3.0/node_modules/@cortexkit/subc-client/src/client.ts
|
|
11386
11446
|
import { promises as fs2 } from "node:fs";
|
|
11447
|
+
import { debuglog } from "node:util";
|
|
11387
11448
|
|
|
11388
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
11449
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.3.0/node_modules/@cortexkit/subc-client/src/auth.ts
|
|
11389
11450
|
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
11390
11451
|
var NONCE_LEN = 32;
|
|
11391
11452
|
var MAX_AUTH_MESSAGE_LEN = 4096;
|
|
@@ -11449,7 +11510,7 @@ async function authenticateClient(sock, conn, deadlineMs) {
|
|
|
11449
11510
|
await writeMessage(sock, { client_auth: Array.from(clientAuth) }, deadlineMs);
|
|
11450
11511
|
}
|
|
11451
11512
|
|
|
11452
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
11513
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.3.0/node_modules/@cortexkit/subc-client/src/connection-file.ts
|
|
11453
11514
|
import { promises as fs } from "node:fs";
|
|
11454
11515
|
var SCHEMA_VERSION = 1;
|
|
11455
11516
|
var MIN_KEY_LEN = 32;
|
|
@@ -11518,7 +11579,7 @@ async function readConnectionFile(path2) {
|
|
|
11518
11579
|
return info;
|
|
11519
11580
|
}
|
|
11520
11581
|
|
|
11521
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
11582
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.3.0/node_modules/@cortexkit/subc-client/src/envelope.ts
|
|
11522
11583
|
var PROTOCOL_VERSION = 1;
|
|
11523
11584
|
var HEADER_LEN = 17;
|
|
11524
11585
|
var FROZEN_PREFIX_LEN = 5;
|
|
@@ -11625,7 +11686,7 @@ function encodeFrame(frame) {
|
|
|
11625
11686
|
return out;
|
|
11626
11687
|
}
|
|
11627
11688
|
|
|
11628
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
11689
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.3.0/node_modules/@cortexkit/subc-client/src/socket.ts
|
|
11629
11690
|
import net from "node:net";
|
|
11630
11691
|
|
|
11631
11692
|
class SocketClosedError extends Error {
|
|
@@ -11656,6 +11717,9 @@ class SubcSocket {
|
|
|
11656
11717
|
buffered = 0;
|
|
11657
11718
|
waiter = null;
|
|
11658
11719
|
closedErr = null;
|
|
11720
|
+
bufferedBytes() {
|
|
11721
|
+
return this.buffered;
|
|
11722
|
+
}
|
|
11659
11723
|
constructor(sock) {
|
|
11660
11724
|
this.sock = sock;
|
|
11661
11725
|
sock.on("data", (chunk) => {
|
|
@@ -11672,6 +11736,9 @@ class SubcSocket {
|
|
|
11672
11736
|
sock.on("end", () => fail(new SocketClosedError("subc closed the connection")));
|
|
11673
11737
|
sock.on("close", () => fail(new SocketClosedError("subc connection closed")));
|
|
11674
11738
|
}
|
|
11739
|
+
localPort() {
|
|
11740
|
+
return this.sock.localPort ?? null;
|
|
11741
|
+
}
|
|
11675
11742
|
static connect(host, port, deadlineMs) {
|
|
11676
11743
|
return new Promise((resolve7, reject) => {
|
|
11677
11744
|
const sock = net.connect({ host, port });
|
|
@@ -11811,9 +11878,14 @@ class SubcSocket {
|
|
|
11811
11878
|
}
|
|
11812
11879
|
}
|
|
11813
11880
|
|
|
11814
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
11881
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.3.0/node_modules/@cortexkit/subc-client/src/client.ts
|
|
11882
|
+
var debug = debuglog("subc-client");
|
|
11815
11883
|
var DEFAULT_HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
11816
11884
|
var DEFAULT_REQUEST_TIMEOUT_MS = 30000;
|
|
11885
|
+
var TIMEOUT_ARBITRATION_GRACE_MS = 50;
|
|
11886
|
+
var REQUEST_DEADLINE_MARKER = "request_deadline";
|
|
11887
|
+
var DEADLINE_NO_DROP_CODE = "deadline_exceeded_no_drop_observed";
|
|
11888
|
+
var ROUTE_OPEN_RETRY_DEADLINE_MS = 1e4;
|
|
11817
11889
|
var BODY_READ_TIMEOUT_MS = 30000;
|
|
11818
11890
|
var EMPTY_BODY = new Uint8Array(0);
|
|
11819
11891
|
var DEFAULT_MANAGED_TARGET_KIND = "management_surface";
|
|
@@ -11857,6 +11929,7 @@ class SubcClient {
|
|
|
11857
11929
|
closeStarted = false;
|
|
11858
11930
|
reconnecting = null;
|
|
11859
11931
|
generation = 1;
|
|
11932
|
+
readerActive = false;
|
|
11860
11933
|
constructor(sock, currentConn, opts) {
|
|
11861
11934
|
this.sock = sock;
|
|
11862
11935
|
this.currentConn = currentConn;
|
|
@@ -11915,7 +11988,7 @@ class SubcClient {
|
|
|
11915
11988
|
}
|
|
11916
11989
|
continue;
|
|
11917
11990
|
}
|
|
11918
|
-
if (err.kind === "outcome_unknown") {
|
|
11991
|
+
if (err.kind === "outcome_unknown" && err.code !== DEADLINE_NO_DROP_CODE) {
|
|
11919
11992
|
this.scheduleReconnectAfterDrop(err);
|
|
11920
11993
|
}
|
|
11921
11994
|
throw err;
|
|
@@ -12038,7 +12111,7 @@ class SubcClient {
|
|
|
12038
12111
|
timer: null
|
|
12039
12112
|
};
|
|
12040
12113
|
pending.timer = setTimeout(() => {
|
|
12041
|
-
this.
|
|
12114
|
+
this.arbitrateTimeout(key, pending, channel, corr, ms);
|
|
12042
12115
|
}, ms);
|
|
12043
12116
|
this.pending.set(key, pending);
|
|
12044
12117
|
this.sock.write(encodeFrame(frame), Date.now() + ms).catch((err) => {
|
|
@@ -12048,6 +12121,23 @@ class SubcClient {
|
|
|
12048
12121
|
});
|
|
12049
12122
|
});
|
|
12050
12123
|
}
|
|
12124
|
+
arbitrateTimeout(key, pending, channel, corr, ms) {
|
|
12125
|
+
const settleAsTimeout = () => {
|
|
12126
|
+
this.rejectPending(key, pending, new SubcError(this.timeoutMessage(channel, corr, ms), REQUEST_DEADLINE_MARKER));
|
|
12127
|
+
};
|
|
12128
|
+
const graceDeadline = Date.now() + this.opts.timeoutArbitrationGraceMs;
|
|
12129
|
+
const arbitrate = () => {
|
|
12130
|
+
if (this.pending.get(key) !== pending)
|
|
12131
|
+
return;
|
|
12132
|
+
const readerDraining = this.readerActive || this.sock.bufferedBytes() > 0;
|
|
12133
|
+
if (readerDraining && Date.now() < graceDeadline) {
|
|
12134
|
+
setImmediate(arbitrate);
|
|
12135
|
+
return;
|
|
12136
|
+
}
|
|
12137
|
+
settleAsTimeout();
|
|
12138
|
+
};
|
|
12139
|
+
setImmediate(arbitrate);
|
|
12140
|
+
}
|
|
12051
12141
|
async managedRequest(routeChannel, body, opts) {
|
|
12052
12142
|
const bytes = body instanceof Uint8Array ? body : this.encode(body);
|
|
12053
12143
|
const priority = opts.priority ?? 1 /* Interactive */;
|
|
@@ -12072,6 +12162,9 @@ class SubcClient {
|
|
|
12072
12162
|
if (!handedToSocket) {
|
|
12073
12163
|
return this.notSentCallError("request bytes were not queued to the subc socket", err);
|
|
12074
12164
|
}
|
|
12165
|
+
if (err instanceof SubcError && err.code === REQUEST_DEADLINE_MARKER) {
|
|
12166
|
+
return new SubcCallError("outcome_unknown", `managed call deadline exceeded after request bytes were queued to the local socket; no terminal response was observed; outcome unknown${causeMessage(err)}`, DEADLINE_NO_DROP_CODE, err);
|
|
12167
|
+
}
|
|
12075
12168
|
return this.outcomeUnknownCallError("connection dropped before the managed call returned a response", err);
|
|
12076
12169
|
};
|
|
12077
12170
|
return new Promise((resolve7, reject) => {
|
|
@@ -12085,7 +12178,7 @@ class SubcClient {
|
|
|
12085
12178
|
classifyFailure
|
|
12086
12179
|
};
|
|
12087
12180
|
pending.timer = setTimeout(() => {
|
|
12088
|
-
this.
|
|
12181
|
+
this.arbitrateTimeout(key, pending, channel, corr, ms);
|
|
12089
12182
|
}, ms);
|
|
12090
12183
|
this.pending.set(key, pending);
|
|
12091
12184
|
const write = this.sock.writeTracked(encodeFrame(frame), Date.now() + ms);
|
|
@@ -12130,6 +12223,9 @@ class SubcClient {
|
|
|
12130
12223
|
return cached.opening;
|
|
12131
12224
|
}
|
|
12132
12225
|
async openCachedRoute(cached) {
|
|
12226
|
+
const routeRetryDeadline = Date.now() + ROUTE_OPEN_RETRY_DEADLINE_MS;
|
|
12227
|
+
let routeRetryDelay = this.opts.reconnectBackoff.baseMs;
|
|
12228
|
+
let routeRetryAttempt = 0;
|
|
12133
12229
|
for (;; ) {
|
|
12134
12230
|
if (cached.closed)
|
|
12135
12231
|
throw this.routeClosedDuringOpen();
|
|
@@ -12163,6 +12259,15 @@ class SubcClient {
|
|
|
12163
12259
|
}
|
|
12164
12260
|
continue;
|
|
12165
12261
|
}
|
|
12262
|
+
if (!this.closeStarted && err instanceof SubcError && isRetryableRouteOpenCode(err.code)) {
|
|
12263
|
+
routeRetryAttempt += 1;
|
|
12264
|
+
if (routeRetryAttempt < this.opts.reconnectBackoff.maxAttempts && Date.now() < routeRetryDeadline) {
|
|
12265
|
+
await this.opts.sleep(routeRetryDelay);
|
|
12266
|
+
routeRetryDelay = Math.min(routeRetryDelay * 2, this.opts.reconnectBackoff.capMs);
|
|
12267
|
+
continue;
|
|
12268
|
+
}
|
|
12269
|
+
throw this.notSentCallError(`route.open failed for module ${cached.moduleId}: ${err.code} (retry budget exhausted)`, err);
|
|
12270
|
+
}
|
|
12166
12271
|
throw this.terminalCallError(`route.open failed for module ${cached.moduleId}`, err);
|
|
12167
12272
|
}
|
|
12168
12273
|
}
|
|
@@ -12233,7 +12338,9 @@ class SubcClient {
|
|
|
12233
12338
|
for (const cached of this.routes.values()) {
|
|
12234
12339
|
if (cached.closed)
|
|
12235
12340
|
continue;
|
|
12236
|
-
const channel = await this.routeOpen(cached.target, cached.identity
|
|
12341
|
+
const channel = await this.routeOpen(cached.target, cached.identity, {
|
|
12342
|
+
consumerIdentity: cached.consumerIdentity ?? null
|
|
12343
|
+
});
|
|
12237
12344
|
if (cached.closed) {
|
|
12238
12345
|
this.sendRouteGoodbye(channel);
|
|
12239
12346
|
continue;
|
|
@@ -12242,6 +12349,11 @@ class SubcClient {
|
|
|
12242
12349
|
cached.generation = this.generation;
|
|
12243
12350
|
}
|
|
12244
12351
|
}
|
|
12352
|
+
timeoutMessage(channel, corr, ms) {
|
|
12353
|
+
const port = this.sock.localPort();
|
|
12354
|
+
const where = port === null ? "channel" : `local_port=${port} channel`;
|
|
12355
|
+
return `request on ${where} ${channel} corr ${corr} timed out after ${ms}ms`;
|
|
12356
|
+
}
|
|
12245
12357
|
routeClosedDuringOpen() {
|
|
12246
12358
|
return new SubcCallError("not_sent", "route was closed before route.open completed", "route_closed");
|
|
12247
12359
|
}
|
|
@@ -12249,9 +12361,16 @@ class SubcClient {
|
|
|
12249
12361
|
try {
|
|
12250
12362
|
for (;; ) {
|
|
12251
12363
|
const headerBytes = await sock.readExact(HEADER_LEN, Number.POSITIVE_INFINITY);
|
|
12252
|
-
|
|
12253
|
-
|
|
12254
|
-
|
|
12364
|
+
this.readerActive = true;
|
|
12365
|
+
try {
|
|
12366
|
+
const header = decodeHeader(headerBytes);
|
|
12367
|
+
const body = header.len === 0 ? new Uint8Array(0) : await sock.readExact(header.len, Date.now() + BODY_READ_TIMEOUT_MS);
|
|
12368
|
+
if (this.sock === sock && this.generation === generation) {
|
|
12369
|
+
this.dispatch({ header, body });
|
|
12370
|
+
}
|
|
12371
|
+
} finally {
|
|
12372
|
+
this.readerActive = false;
|
|
12373
|
+
}
|
|
12255
12374
|
}
|
|
12256
12375
|
} catch (err) {
|
|
12257
12376
|
if (this.sock === sock && this.generation === generation) {
|
|
@@ -12283,13 +12402,20 @@ class SubcClient {
|
|
|
12283
12402
|
this.failChannel(frame.header.channel, new SubcError("route closed by subc (GOODBYE)"));
|
|
12284
12403
|
return;
|
|
12285
12404
|
}
|
|
12405
|
+
if (frame.header.ty === 1 /* Response */ || frame.header.ty === 5 /* Error */ || frame.header.ty === 4 /* StreamEnd */) {
|
|
12406
|
+
debug("dropped terminal frame with no waiter: type=%d channel=%d corr=%s port=%s", frame.header.ty, frame.header.channel, frame.header.corr, this.sock.localPort() ?? "?");
|
|
12407
|
+
return;
|
|
12408
|
+
}
|
|
12286
12409
|
}
|
|
12287
12410
|
settle(key, pending, run) {
|
|
12411
|
+
if (this.pending.get(key) !== pending)
|
|
12412
|
+
return false;
|
|
12288
12413
|
this.pending.delete(key);
|
|
12289
12414
|
if (pending.timer)
|
|
12290
12415
|
clearTimeout(pending.timer);
|
|
12291
12416
|
run();
|
|
12292
12417
|
pending.onSettle?.();
|
|
12418
|
+
return true;
|
|
12293
12419
|
}
|
|
12294
12420
|
rejectPending(key, pending, err) {
|
|
12295
12421
|
this.settle(key, pending, () => pending.reject(pending.classifyFailure?.(err) ?? err));
|
|
@@ -12353,6 +12479,9 @@ function isConsumerReconnectTransient(err) {
|
|
|
12353
12479
|
const code = errorCode(err);
|
|
12354
12480
|
return code === "ECONNREFUSED" || code === "ECONNRESET" || code === "EPIPE" || code === "ETIMEDOUT" || code === "ENOENT";
|
|
12355
12481
|
}
|
|
12482
|
+
function isRetryableRouteOpenCode(code) {
|
|
12483
|
+
return code === "unknown_module" || code === "module_reloading" || code === "target_unavailable" || code === "module_timeout";
|
|
12484
|
+
}
|
|
12356
12485
|
async function connectionFileExists(path2) {
|
|
12357
12486
|
try {
|
|
12358
12487
|
await fs2.access(path2);
|
|
@@ -12368,7 +12497,8 @@ function normalizeConnectOptions(opts) {
|
|
|
12368
12497
|
identity: opts.identity,
|
|
12369
12498
|
targetKind: opts.targetKind ?? DEFAULT_MANAGED_TARGET_KIND,
|
|
12370
12499
|
reconnectBackoff: opts.reconnectBackoff ?? DEFAULT_RECONNECT_BACKOFF,
|
|
12371
|
-
sleep: opts.sleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms)))
|
|
12500
|
+
sleep: opts.sleep ?? ((ms) => new Promise((resolve7) => setTimeout(resolve7, ms))),
|
|
12501
|
+
timeoutArbitrationGraceMs: opts.timeoutArbitrationGraceMs ?? TIMEOUT_ARBITRATION_GRACE_MS
|
|
12372
12502
|
};
|
|
12373
12503
|
}
|
|
12374
12504
|
function routeCacheKey(target, identity, consumerIdentity) {
|
|
@@ -12397,7 +12527,7 @@ function causeMessage(cause) {
|
|
|
12397
12527
|
return "";
|
|
12398
12528
|
return `: ${cause instanceof Error ? cause.message : String(cause)}`;
|
|
12399
12529
|
}
|
|
12400
|
-
// ../../node_modules/.bun/@cortexkit+subc-client@0.
|
|
12530
|
+
// ../../node_modules/.bun/@cortexkit+subc-client@0.3.0/node_modules/@cortexkit/subc-client/src/provider.ts
|
|
12401
12531
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
12402
12532
|
var DEFAULT_HANDSHAKE_TIMEOUT_MS2 = 1e4;
|
|
12403
12533
|
var BODY_READ_TIMEOUT_MS2 = 30000;
|
|
@@ -13426,7 +13556,7 @@ async function createAftTransportPool(opts) {
|
|
|
13426
13556
|
return new BridgePool(opts.binaryPath, opts.poolOptions, opts.configOverrides);
|
|
13427
13557
|
}
|
|
13428
13558
|
// src/bg-notifications.ts
|
|
13429
|
-
import { createHash as
|
|
13559
|
+
import { createHash as createHash5, randomUUID as randomUUID2 } from "node:crypto";
|
|
13430
13560
|
|
|
13431
13561
|
// src/logger.ts
|
|
13432
13562
|
import * as fs3 from "node:fs";
|
|
@@ -13590,7 +13720,7 @@ async function resolvePromptContext(client, sessionId) {
|
|
|
13590
13720
|
|
|
13591
13721
|
// src/bg-notifications.ts
|
|
13592
13722
|
function hashReminder(text) {
|
|
13593
|
-
return
|
|
13723
|
+
return createHash5("sha256").update(text).digest("hex").slice(0, 16);
|
|
13594
13724
|
}
|
|
13595
13725
|
var CONSUMED_TASKIDS_CAP = 256;
|
|
13596
13726
|
var DELIVERED_AWAITING_ACK_CAP = 4096;
|
|
@@ -14354,7 +14484,7 @@ function formatDuration(completion) {
|
|
|
14354
14484
|
}
|
|
14355
14485
|
|
|
14356
14486
|
// src/config.ts
|
|
14357
|
-
import { existsSync as existsSync7, readFileSync as
|
|
14487
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7, renameSync as renameSync5, unlinkSync as unlinkSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
14358
14488
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
14359
14489
|
|
|
14360
14490
|
// ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
@@ -28728,6 +28858,7 @@ var InspectConfigSchema = exports_external.object({
|
|
|
28728
28858
|
duplicates: exports_external.object({
|
|
28729
28859
|
lower_bound: exports_external.number().int().positive().optional(),
|
|
28730
28860
|
discard_cost: exports_external.number().int().min(0).optional(),
|
|
28861
|
+
expected_mirrors: exports_external.array(exports_external.tuple([exports_external.string().trim().min(1), exports_external.string().trim().min(1)])).optional(),
|
|
28731
28862
|
anonymize: exports_external.object({
|
|
28732
28863
|
variables: exports_external.boolean().optional(),
|
|
28733
28864
|
fields: exports_external.boolean().optional(),
|
|
@@ -28945,7 +29076,7 @@ function migrateAftConfigFile2(configPath, logger = { log: log2, warn: warn2 })
|
|
|
28945
29076
|
let tmpPath = null;
|
|
28946
29077
|
let oldKeys = [];
|
|
28947
29078
|
try {
|
|
28948
|
-
const content =
|
|
29079
|
+
const content = readFileSync7(configPath, "utf-8");
|
|
28949
29080
|
const rawConfig = import_comment_json.parse(content);
|
|
28950
29081
|
if (!rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
|
|
28951
29082
|
return { migrated: false, oldKeys: [] };
|
|
@@ -29022,7 +29153,7 @@ function loadConfigFromPath(configPath) {
|
|
|
29022
29153
|
if (!existsSync7(configPath)) {
|
|
29023
29154
|
return null;
|
|
29024
29155
|
}
|
|
29025
|
-
const content =
|
|
29156
|
+
const content = readFileSync7(configPath, "utf-8");
|
|
29026
29157
|
const rawConfig = import_comment_json.parse(content);
|
|
29027
29158
|
migrateRawConfig(rawConfig, configPath, { log: log2, warn: warn2 });
|
|
29028
29159
|
const cleanConfig = stripJsoncSymbols(rawConfig);
|
|
@@ -29290,7 +29421,7 @@ function loadAftConfig(projectDirectory) {
|
|
|
29290
29421
|
}
|
|
29291
29422
|
|
|
29292
29423
|
// src/notifications.ts
|
|
29293
|
-
import { existsSync as existsSync8, readFileSync as
|
|
29424
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8 } from "node:fs";
|
|
29294
29425
|
import { homedir as homedir9, platform } from "node:os";
|
|
29295
29426
|
import { join as join11 } from "node:path";
|
|
29296
29427
|
function isTuiMode() {
|
|
@@ -29333,7 +29464,7 @@ function readDesktopState() {
|
|
|
29333
29464
|
return { serverUrl: null };
|
|
29334
29465
|
}
|
|
29335
29466
|
try {
|
|
29336
|
-
const raw =
|
|
29467
|
+
const raw = readFileSync8(statePath, "utf-8");
|
|
29337
29468
|
const state = JSON.parse(raw);
|
|
29338
29469
|
let serverUrl = null;
|
|
29339
29470
|
const serverStr = state.server;
|
|
@@ -29832,7 +29963,7 @@ import {
|
|
|
29832
29963
|
existsSync as existsSync11,
|
|
29833
29964
|
mkdirSync as mkdirSync6,
|
|
29834
29965
|
openSync as openSync5,
|
|
29835
|
-
readFileSync as
|
|
29966
|
+
readFileSync as readFileSync11,
|
|
29836
29967
|
renameSync as renameSync6,
|
|
29837
29968
|
rmSync as rmSync5,
|
|
29838
29969
|
writeFileSync as writeFileSync7
|
|
@@ -29841,14 +29972,14 @@ import { dirname as dirname7 } from "node:path";
|
|
|
29841
29972
|
|
|
29842
29973
|
// src/hooks/auto-update-checker/cache.ts
|
|
29843
29974
|
import { spawn as spawn2 } from "node:child_process";
|
|
29844
|
-
import { cpSync, existsSync as existsSync10, mkdtempSync, readFileSync as
|
|
29975
|
+
import { cpSync, existsSync as existsSync10, mkdtempSync, readFileSync as readFileSync10, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
29845
29976
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
29846
29977
|
import { basename as basename3, dirname as dirname6, join as join14 } from "node:path";
|
|
29847
29978
|
var import_comment_json3 = __toESM(require_src2(), 1);
|
|
29848
29979
|
|
|
29849
29980
|
// src/hooks/auto-update-checker/checker.ts
|
|
29850
29981
|
var import_comment_json2 = __toESM(require_src2(), 1);
|
|
29851
|
-
import { existsSync as existsSync9, readFileSync as
|
|
29982
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9, statSync as statSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
29852
29983
|
import { homedir as homedir11 } from "node:os";
|
|
29853
29984
|
import { dirname as dirname5, isAbsolute as isAbsolute6, join as join13, resolve as resolve7 } from "node:path";
|
|
29854
29985
|
import { fileURLToPath } from "node:url";
|
|
@@ -29954,7 +30085,7 @@ function getLocalDevPath(directory) {
|
|
|
29954
30085
|
try {
|
|
29955
30086
|
if (!existsSync9(configPath))
|
|
29956
30087
|
continue;
|
|
29957
|
-
const rawConfig = parseJsonConfig(
|
|
30088
|
+
const rawConfig = parseJsonConfig(readFileSync9(configPath, "utf-8"));
|
|
29958
30089
|
const plugins = getPluginEntries(rawConfig);
|
|
29959
30090
|
for (const entry of plugins) {
|
|
29960
30091
|
if (entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))
|
|
@@ -29964,7 +30095,7 @@ function getLocalDevPath(directory) {
|
|
|
29964
30095
|
const pkgPath = findPackageJsonUp(localPath);
|
|
29965
30096
|
if (!pkgPath)
|
|
29966
30097
|
continue;
|
|
29967
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
30098
|
+
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync9(pkgPath, "utf-8")));
|
|
29968
30099
|
if (pkg.success && pkg.data.name === PACKAGE_NAME)
|
|
29969
30100
|
return localPath;
|
|
29970
30101
|
}
|
|
@@ -29981,7 +30112,7 @@ function findPackageJsonUp(startPath) {
|
|
|
29981
30112
|
const pkgPath = join13(dir, "package.json");
|
|
29982
30113
|
if (existsSync9(pkgPath)) {
|
|
29983
30114
|
try {
|
|
29984
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
30115
|
+
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync9(pkgPath, "utf-8")));
|
|
29985
30116
|
if (pkg.success && pkg.data.name === PACKAGE_NAME)
|
|
29986
30117
|
return pkgPath;
|
|
29987
30118
|
} catch {}
|
|
@@ -30002,7 +30133,7 @@ function getLocalDevVersion(directory) {
|
|
|
30002
30133
|
const pkgPath = findPackageJsonUp(localPath);
|
|
30003
30134
|
if (!pkgPath)
|
|
30004
30135
|
return null;
|
|
30005
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
30136
|
+
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync9(pkgPath, "utf-8")));
|
|
30006
30137
|
return pkg.success ? pkg.data.version ?? null : null;
|
|
30007
30138
|
} catch {
|
|
30008
30139
|
return null;
|
|
@@ -30021,7 +30152,7 @@ function findPluginEntry(directory) {
|
|
|
30021
30152
|
try {
|
|
30022
30153
|
if (!existsSync9(configPath))
|
|
30023
30154
|
continue;
|
|
30024
|
-
const rawConfig = parseJsonConfig(
|
|
30155
|
+
const rawConfig = parseJsonConfig(readFileSync9(configPath, "utf-8"));
|
|
30025
30156
|
const plugins = getPluginEntries(rawConfig);
|
|
30026
30157
|
for (const entry of plugins) {
|
|
30027
30158
|
if (entry === PACKAGE_NAME) {
|
|
@@ -30054,7 +30185,7 @@ function getCachedVersion(spec) {
|
|
|
30054
30185
|
try {
|
|
30055
30186
|
if (!existsSync9(packageJsonPath))
|
|
30056
30187
|
continue;
|
|
30057
|
-
const pkg = PackageJsonSchema.safeParse(JSON.parse(
|
|
30188
|
+
const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync9(packageJsonPath, "utf-8")));
|
|
30058
30189
|
if (pkg.success && pkg.data.version) {
|
|
30059
30190
|
if (!spec)
|
|
30060
30191
|
cachedPackageVersion = pkg.data.version;
|
|
@@ -30104,9 +30235,9 @@ function createAutoUpdateSnapshot(installDir, packageJsonPath, packageName) {
|
|
|
30104
30235
|
cpSync(packageDir, stagedPackageDir, { recursive: true });
|
|
30105
30236
|
return {
|
|
30106
30237
|
packageJsonPath,
|
|
30107
|
-
packageJson: existsSync10(packageJsonPath) ?
|
|
30238
|
+
packageJson: existsSync10(packageJsonPath) ? readFileSync10(packageJsonPath, "utf-8") : null,
|
|
30108
30239
|
lockfilePath,
|
|
30109
|
-
lockfile: existsSync10(lockfilePath) ?
|
|
30240
|
+
lockfile: existsSync10(lockfilePath) ? readFileSync10(lockfilePath, "utf-8") : null,
|
|
30110
30241
|
packageDir,
|
|
30111
30242
|
stagedPackageDir,
|
|
30112
30243
|
tempDir
|
|
@@ -30144,7 +30275,7 @@ function removeFromPackageLock(installDir, packageName) {
|
|
|
30144
30275
|
if (!existsSync10(lockPath))
|
|
30145
30276
|
return false;
|
|
30146
30277
|
try {
|
|
30147
|
-
const lock = import_comment_json3.parse(
|
|
30278
|
+
const lock = import_comment_json3.parse(readFileSync10(lockPath, "utf-8"));
|
|
30148
30279
|
let modified = false;
|
|
30149
30280
|
if (lock.packages) {
|
|
30150
30281
|
const key = `node_modules/${packageName}`;
|
|
@@ -30170,7 +30301,7 @@ function ensureDependencyVersion(packageJsonPath, packageName, version2) {
|
|
|
30170
30301
|
if (!existsSync10(packageJsonPath))
|
|
30171
30302
|
return false;
|
|
30172
30303
|
try {
|
|
30173
|
-
const raw = import_comment_json3.parse(
|
|
30304
|
+
const raw = import_comment_json3.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
30174
30305
|
const pkgJson = PackageJsonSchema.safeParse(raw);
|
|
30175
30306
|
if (!pkgJson.success)
|
|
30176
30307
|
return false;
|
|
@@ -30424,7 +30555,7 @@ function hasRecentCheckTimestamp(file2, intervalMs) {
|
|
|
30424
30555
|
if (!existsSync11(file2))
|
|
30425
30556
|
return false;
|
|
30426
30557
|
try {
|
|
30427
|
-
const raw = JSON.parse(
|
|
30558
|
+
const raw = JSON.parse(readFileSync11(file2, "utf-8"));
|
|
30428
30559
|
const last = typeof raw.lastCheckedMs === "number" ? raw.lastCheckedMs : 0;
|
|
30429
30560
|
return Number.isFinite(last) && Date.now() - last < intervalMs;
|
|
30430
30561
|
} catch {
|
|
@@ -30528,12 +30659,12 @@ function showToast(ctx, title, message, variant = "info", duration3 = 3000) {
|
|
|
30528
30659
|
|
|
30529
30660
|
// src/lsp-auto-install.ts
|
|
30530
30661
|
import { spawn as spawn3 } from "node:child_process";
|
|
30531
|
-
import { createHash as
|
|
30662
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
30532
30663
|
import {
|
|
30533
30664
|
createReadStream,
|
|
30534
30665
|
existsSync as existsSync13,
|
|
30535
30666
|
mkdirSync as mkdirSync8,
|
|
30536
|
-
readFileSync as
|
|
30667
|
+
readFileSync as readFileSync14,
|
|
30537
30668
|
renameSync as renameSync7,
|
|
30538
30669
|
rmSync as rmSync6,
|
|
30539
30670
|
statSync as statSync7,
|
|
@@ -30546,7 +30677,7 @@ import {
|
|
|
30546
30677
|
closeSync as closeSync6,
|
|
30547
30678
|
mkdirSync as mkdirSync7,
|
|
30548
30679
|
openSync as openSync6,
|
|
30549
|
-
readFileSync as
|
|
30680
|
+
readFileSync as readFileSync12,
|
|
30550
30681
|
statSync as statSync6,
|
|
30551
30682
|
unlinkSync as unlinkSync6,
|
|
30552
30683
|
writeFileSync as writeFileSync8
|
|
@@ -30610,7 +30741,7 @@ function readInstalledMetaIn(installDir) {
|
|
|
30610
30741
|
try {
|
|
30611
30742
|
if (!statSync6(path3).isFile())
|
|
30612
30743
|
return null;
|
|
30613
|
-
const raw =
|
|
30744
|
+
const raw = readFileSync12(path3, "utf8");
|
|
30614
30745
|
const parsed = JSON.parse(raw);
|
|
30615
30746
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
30616
30747
|
return null;
|
|
@@ -30660,7 +30791,7 @@ ${new Date().toISOString()}
|
|
|
30660
30791
|
let owningPid = null;
|
|
30661
30792
|
let lockMtimeMs = 0;
|
|
30662
30793
|
try {
|
|
30663
|
-
const raw =
|
|
30794
|
+
const raw = readFileSync12(lock, "utf8");
|
|
30664
30795
|
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
30665
30796
|
const parsed = Number.parseInt(firstLine, 10);
|
|
30666
30797
|
if (Number.isFinite(parsed) && parsed > 0)
|
|
@@ -30698,7 +30829,7 @@ function releaseInstallLock(lockKey) {
|
|
|
30698
30829
|
try {
|
|
30699
30830
|
let owningPid = null;
|
|
30700
30831
|
try {
|
|
30701
|
-
const raw =
|
|
30832
|
+
const raw = readFileSync12(lock, "utf8");
|
|
30702
30833
|
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
30703
30834
|
const parsed = Number.parseInt(firstLine, 10);
|
|
30704
30835
|
if (Number.isFinite(parsed) && parsed > 0)
|
|
@@ -30739,7 +30870,7 @@ var VERSION_CHECK_FILE = ".aft-version-check";
|
|
|
30739
30870
|
function readVersionCheck(npmPackage) {
|
|
30740
30871
|
const file2 = join15(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
30741
30872
|
try {
|
|
30742
|
-
const raw =
|
|
30873
|
+
const raw = readFileSync12(file2, "utf8");
|
|
30743
30874
|
const parsed = JSON.parse(raw);
|
|
30744
30875
|
if (typeof parsed.last_checked === "string") {
|
|
30745
30876
|
return {
|
|
@@ -30916,7 +31047,7 @@ var NPM_LSP_TABLE = [
|
|
|
30916
31047
|
];
|
|
30917
31048
|
|
|
30918
31049
|
// src/lsp-project-relevance.ts
|
|
30919
|
-
import { existsSync as existsSync12, readdirSync as readdirSync3, readFileSync as
|
|
31050
|
+
import { existsSync as existsSync12, readdirSync as readdirSync3, readFileSync as readFileSync13 } from "node:fs";
|
|
30920
31051
|
import { join as join16 } from "node:path";
|
|
30921
31052
|
var MAX_WALK_DIRS = 200;
|
|
30922
31053
|
var MAX_WALK_DEPTH = 4;
|
|
@@ -30958,7 +31089,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
|
|
|
30958
31089
|
}
|
|
30959
31090
|
function readPackageJson(projectRoot) {
|
|
30960
31091
|
try {
|
|
30961
|
-
const raw =
|
|
31092
|
+
const raw = readFileSync13(join16(projectRoot, "package.json"), "utf8");
|
|
30962
31093
|
const parsed = JSON.parse(raw);
|
|
30963
31094
|
if (typeof parsed !== "object" || parsed === null)
|
|
30964
31095
|
return null;
|
|
@@ -31280,7 +31411,7 @@ function hashInstalledBinary(spec) {
|
|
|
31280
31411
|
reject(new Error(`installed binary not found at any of: ${candidates.join(", ")}`));
|
|
31281
31412
|
return;
|
|
31282
31413
|
}
|
|
31283
|
-
const hash2 =
|
|
31414
|
+
const hash2 = createHash6("sha256");
|
|
31284
31415
|
const stream = createReadStream(pathToHash);
|
|
31285
31416
|
stream.on("error", reject);
|
|
31286
31417
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
@@ -31303,7 +31434,7 @@ function installedBinaryPath(spec) {
|
|
|
31303
31434
|
return null;
|
|
31304
31435
|
}
|
|
31305
31436
|
function sha256OfFileSync(path3) {
|
|
31306
|
-
return
|
|
31437
|
+
return createHash6("sha256").update(readFileSync14(path3)).digest("hex");
|
|
31307
31438
|
}
|
|
31308
31439
|
function quarantineCachedNpmInstall(spec, reason) {
|
|
31309
31440
|
const packageDir = lspPackageDir(spec.npm);
|
|
@@ -31388,7 +31519,7 @@ function runAutoInstall(projectRoot, config2, fetchImpl = fetch) {
|
|
|
31388
31519
|
|
|
31389
31520
|
// src/lsp-github-install.ts
|
|
31390
31521
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
31391
|
-
import { createHash as
|
|
31522
|
+
import { createHash as createHash7, randomBytes as randomBytes2 } from "node:crypto";
|
|
31392
31523
|
import {
|
|
31393
31524
|
copyFileSync as copyFileSync4,
|
|
31394
31525
|
createReadStream as createReadStream2,
|
|
@@ -31397,7 +31528,7 @@ import {
|
|
|
31397
31528
|
lstatSync as lstatSync2,
|
|
31398
31529
|
mkdirSync as mkdirSync9,
|
|
31399
31530
|
readdirSync as readdirSync4,
|
|
31400
|
-
readFileSync as
|
|
31531
|
+
readFileSync as readFileSync15,
|
|
31401
31532
|
readlinkSync as readlinkSync2,
|
|
31402
31533
|
realpathSync as realpathSync3,
|
|
31403
31534
|
renameSync as renameSync8,
|
|
@@ -31531,7 +31662,7 @@ function readGithubInstalledMetaIn(installDir) {
|
|
|
31531
31662
|
const path3 = join18(installDir, INSTALLED_META_FILE2);
|
|
31532
31663
|
if (!statSync8(path3).isFile())
|
|
31533
31664
|
return null;
|
|
31534
|
-
const parsed = JSON.parse(
|
|
31665
|
+
const parsed = JSON.parse(readFileSync15(path3, "utf8"));
|
|
31535
31666
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
31536
31667
|
return null;
|
|
31537
31668
|
return {
|
|
@@ -31564,7 +31695,7 @@ var MAX_DOWNLOAD_BYTES3 = 256 * 1024 * 1024;
|
|
|
31564
31695
|
var MAX_EXTRACT_BYTES2 = 1024 * 1024 * 1024;
|
|
31565
31696
|
function sha256OfFile(path3) {
|
|
31566
31697
|
return new Promise((resolve9, reject) => {
|
|
31567
|
-
const hash2 =
|
|
31698
|
+
const hash2 = createHash7("sha256");
|
|
31568
31699
|
const stream = createReadStream2(path3);
|
|
31569
31700
|
stream.on("error", reject);
|
|
31570
31701
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
@@ -31572,7 +31703,7 @@ function sha256OfFile(path3) {
|
|
|
31572
31703
|
});
|
|
31573
31704
|
}
|
|
31574
31705
|
function sha256OfFileSync2(path3) {
|
|
31575
|
-
return
|
|
31706
|
+
return createHash7("sha256").update(readFileSync15(path3)).digest("hex");
|
|
31576
31707
|
}
|
|
31577
31708
|
async function fetchReleaseByTag(githubRepo, tag, fetchImpl, signal) {
|
|
31578
31709
|
const candidates = [];
|
|
@@ -32351,7 +32482,7 @@ import {
|
|
|
32351
32482
|
existsSync as existsSync15,
|
|
32352
32483
|
mkdirSync as mkdirSync10,
|
|
32353
32484
|
readdirSync as readdirSync5,
|
|
32354
|
-
readFileSync as
|
|
32485
|
+
readFileSync as readFileSync16,
|
|
32355
32486
|
renameSync as renameSync9,
|
|
32356
32487
|
unlinkSync as unlinkSync8,
|
|
32357
32488
|
writeFileSync as writeFileSync11
|
|
@@ -32531,7 +32662,7 @@ class AftRpcServer {
|
|
|
32531
32662
|
if (filePath === this.portFilePath)
|
|
32532
32663
|
continue;
|
|
32533
32664
|
try {
|
|
32534
|
-
const record2 = parseRpcPortRecord(
|
|
32665
|
+
const record2 = parseRpcPortRecord(readFileSync16(filePath, "utf-8"));
|
|
32535
32666
|
if (record2 === null) {
|
|
32536
32667
|
unlinkSync8(filePath);
|
|
32537
32668
|
continue;
|
|
@@ -33561,17 +33692,18 @@ var SUPPORTED_LANGS = [
|
|
|
33561
33692
|
"rust",
|
|
33562
33693
|
"go",
|
|
33563
33694
|
"pascal",
|
|
33564
|
-
"r"
|
|
33695
|
+
"r",
|
|
33696
|
+
"objc"
|
|
33565
33697
|
];
|
|
33566
33698
|
function astTools(ctx) {
|
|
33567
33699
|
const searchTool = {
|
|
33568
|
-
description: `Search code patterns across filesystem using AST-aware matching. Supports
|
|
33700
|
+
description: `Search code patterns across filesystem using AST-aware matching. Supports 9 languages.
|
|
33569
33701
|
|
|
33570
33702
|
` + `Use meta-variables: $VAR matches a single AST node, $$$ matches multiple nodes (variadic).
|
|
33571
33703
|
` + `IMPORTANT: Patterns must be complete AST nodes (valid code fragments).
|
|
33572
33704
|
` + `For functions, include params and body: 'export async function $NAME($$$) { $$$ }' not just 'export async function $NAME'.
|
|
33573
33705
|
|
|
33574
|
-
` + "Examples: pattern='console.log($MSG)' lang='typescript', pattern='async function $NAME($$$) { $$$ }' lang='javascript', pattern='def $FUNC($$$): $$$' lang='python', pattern='Writeln($MSG);' lang='pascal', pattern='$X <- $Y' lang='r'",
|
|
33706
|
+
` + "Examples: pattern='console.log($MSG)' lang='typescript', pattern='async function $NAME($$$) { $$$ }' lang='javascript', pattern='def $FUNC($$$): $$$' lang='python', pattern='Writeln($MSG);' lang='pascal', pattern='$X <- $Y' lang='r', pattern='[obj foo:$ARG]' lang='objc'",
|
|
33575
33707
|
args: {
|
|
33576
33708
|
pattern: z3.string().describe("AST pattern with meta-variables ($VAR, $$$). Must be complete AST node."),
|
|
33577
33709
|
lang: z3.enum(SUPPORTED_LANGS).describe("Target language"),
|
|
@@ -33734,14 +33866,14 @@ function resolveForegroundWaitMs(configured) {
|
|
|
33734
33866
|
}
|
|
33735
33867
|
return configured;
|
|
33736
33868
|
}
|
|
33737
|
-
function orchestratedTransportTimeoutMs(blockToCompletion, effectiveTimeout, foregroundWaitMs) {
|
|
33738
|
-
const waitBudget = blockToCompletion ? effectiveTimeout ?? DEFAULT_HARD_TIMEOUT_MS : foregroundWaitMs;
|
|
33869
|
+
function orchestratedTransportTimeoutMs(blockToCompletion, wait, effectiveTimeout, foregroundWaitMs) {
|
|
33870
|
+
const waitBudget = blockToCompletion || wait ? effectiveTimeout ?? DEFAULT_HARD_TIMEOUT_MS : foregroundWaitMs;
|
|
33739
33871
|
return waitBudget + BASH_TRANSPORT_MARGIN_MS;
|
|
33740
33872
|
}
|
|
33741
33873
|
function bashToolDescription(aftSearchRegistered, compressionOn, backgroundOn) {
|
|
33742
33874
|
const searchSteer = aftSearchRegistered ? "use aft_search (concepts, identifiers, regex, literals), read, aft_outline, or aft_zoom instead" : "use the grep tool, read, aft_outline, or aft_zoom instead";
|
|
33743
33875
|
const compression = compressionOn ? " Output is compressed by default; pass compressed: false for raw output. Piped commands run verbatim and show the pipeline's output; for AFT's test/build summary, run the runner without | head, | tail, or | grep." : "";
|
|
33744
|
-
const tasks = backgroundOn ? ' Commands run in the foreground and return inline;
|
|
33876
|
+
const tasks = backgroundOn ? ' Commands run in the foreground and return inline; wait: true blocks until a long command finishes instead of auto-promoting — use it when you need the result before doing anything else; keep it off otherwise so auto-promote can remind you while you work. Use background: true yourself ONLY when you have other useful work to do while it runs; then bash_watch waits on the task (sync blocks until exit/pattern, async notifies) and bash_status peeks at it — never background a command and immediately bash_watch it (that wastes a turn for what foreground returns in one), and never loop bash_status to wait. pty: true runs interactive programs (REPLs, TUIs), implies background, and is driven with bash_status({ outputMode: "screen" }) plus bash_write.' : " Commands run in the foreground to completion; timeout is the hard kill cap (default 30 minutes).";
|
|
33745
33877
|
return `Execute shell commands.${compression}${tasks}
|
|
33746
33878
|
|
|
33747
33879
|
DO NOT use bash for code search or code exploration. If you are about to run grep, rg, sed, awk, find, or cat through bash to locate or read code: STOP — ${searchSteer}.`;
|
|
@@ -33807,6 +33939,7 @@ function createBashTool(ctx, aftSearchRegisteredOverride) {
|
|
|
33807
33939
|
timeout: optionalInt(1, Number.MAX_SAFE_INTEGER).describe(initialBashCfg.background ? "Hard kill cap in milliseconds (positive integer). When omitted, the task can run up to 30 minutes. Foreground bash returns inline if the command finishes within ~8s (configurable via bash.foreground_wait_window_ms); otherwise it's automatically promoted to background and a completion reminder is delivered when the task actually finishes." : "Hard kill cap in milliseconds (positive integer). When omitted, the foreground command can run up to 30 minutes and returns inline when it finishes."),
|
|
33808
33940
|
workdir: z4.string().optional().describe("Working directory for command execution. Relative paths resolve through the bridge; defaults to the current tool context/project root when omitted."),
|
|
33809
33941
|
description: z4.string().optional().describe("Short 5-10 word human-readable summary shown in OpenCode UI metadata instead of raw shell syntax."),
|
|
33942
|
+
wait: z4.boolean().optional().describe("When true, run in the foreground without auto-promoting and wait until the command finishes or reaches its timeout. Use only when you know the result is required before doing anything else."),
|
|
33810
33943
|
...backgroundFlagArg,
|
|
33811
33944
|
compressed: z4.boolean().optional().describe("When true or omitted, return compressed output with noisy terminal control sequences reduced. Set to false for raw output."),
|
|
33812
33945
|
...ptyArgs
|
|
@@ -33826,21 +33959,30 @@ function createBashTool(ctx, aftSearchRegisteredOverride) {
|
|
|
33826
33959
|
const cwd = args2.workdir ?? context.directory;
|
|
33827
33960
|
const isSubagent = await resolveIsSubagent(ctx.client, context.sessionID, context.directory);
|
|
33828
33961
|
const backgroundDisabled = !bashCfg.background;
|
|
33829
|
-
const
|
|
33830
|
-
const
|
|
33962
|
+
const requestedWait = coerceBoolean(args2.wait);
|
|
33963
|
+
const rawRequestedPty = coerceBoolean(args2.pty);
|
|
33964
|
+
const rawRequestedBackground = coerceBoolean(args2.background);
|
|
33965
|
+
if (requestedWait && rawRequestedPty) {
|
|
33966
|
+
throw new Error("wait:true cannot be used with pty:true because PTY sessions run in background.");
|
|
33967
|
+
}
|
|
33968
|
+
if (requestedWait && rawRequestedBackground) {
|
|
33969
|
+
throw new Error("wait:true cannot be used with background:true.");
|
|
33970
|
+
}
|
|
33971
|
+
const requestedPty = !backgroundDisabled && rawRequestedPty;
|
|
33972
|
+
const requestedBackground = !backgroundDisabled && (rawRequestedBackground || requestedPty);
|
|
33831
33973
|
if (requestedPty && isSubagent) {
|
|
33832
33974
|
throw new Error("PTY mode is not available in subagent sessions; subagents cannot drive interactive terminals.");
|
|
33833
33975
|
}
|
|
33834
33976
|
const allowSubagentBg = bashCfg.subagent_background;
|
|
33835
33977
|
const subagentForcedForeground = isSubagent && !allowSubagentBg;
|
|
33836
|
-
const blockToCompletion = subagentForcedForeground || backgroundDisabled;
|
|
33978
|
+
const blockToCompletion = subagentForcedForeground || backgroundDisabled || requestedWait;
|
|
33837
33979
|
const effectiveBackground = blockToCompletion ? false : requestedBackground;
|
|
33838
33980
|
const rawTimeout = coerceOptionalInt(args2.timeout, "timeout", 1, Number.MAX_SAFE_INTEGER);
|
|
33839
33981
|
const ptyRows = coerceOptionalInt(args2.ptyRows, "ptyRows", 1, 60);
|
|
33840
33982
|
const ptyCols = coerceOptionalInt(args2.ptyCols, "ptyCols", 1, 140);
|
|
33841
33983
|
const compressed = coerceBoolean(args2.compressed, true);
|
|
33842
33984
|
const foregroundWaitMs = resolveForegroundWaitMs(bashCfg.foreground_wait_window_ms);
|
|
33843
|
-
const effectiveTimeout = effectiveBackground || backgroundDisabled ? rawTimeout : resolveBashKillTimeout(rawTimeout, foregroundWaitMs);
|
|
33985
|
+
const effectiveTimeout = requestedWait || effectiveBackground || backgroundDisabled ? rawTimeout : resolveBashKillTimeout(rawTimeout, foregroundWaitMs);
|
|
33844
33986
|
if (subagentForcedForeground && requestedBackground) {
|
|
33845
33987
|
sessionLog(context.sessionID, "[bash] subagent + background:true → converting to foreground (subagent would lose task_id)");
|
|
33846
33988
|
}
|
|
@@ -33859,9 +34001,10 @@ function createBashTool(ctx, aftSearchRegisteredOverride) {
|
|
|
33859
34001
|
pty_cols: ptyCols,
|
|
33860
34002
|
permissions_requested: true,
|
|
33861
34003
|
foreground_orchestrate: true,
|
|
33862
|
-
block_to_completion: blockToCompletion
|
|
34004
|
+
block_to_completion: blockToCompletion,
|
|
34005
|
+
wait: requestedWait
|
|
33863
34006
|
}, callBashBridge, {
|
|
33864
|
-
transportTimeoutMs: orchestratedTransportTimeoutMs(blockToCompletion, effectiveTimeout, foregroundWaitMs),
|
|
34007
|
+
transportTimeoutMs: orchestratedTransportTimeoutMs(blockToCompletion, requestedWait, effectiveTimeout, foregroundWaitMs),
|
|
33865
34008
|
onProgress: ({ text }) => {
|
|
33866
34009
|
accumulatedOutput = preview(accumulatedOutput + text);
|
|
33867
34010
|
metadata?.({ output: accumulatedOutput, description });
|
|
@@ -35319,11 +35462,11 @@ function createInspectTier2IdleScheduler(options) {
|
|
|
35319
35462
|
}
|
|
35320
35463
|
function inspectTools(ctx) {
|
|
35321
35464
|
const inspectTool = {
|
|
35322
|
-
description: "Codebase health snapshot. One call returns summary stats for: TODOs, diagnostics, file/symbol metrics, dead code, unused exports, code duplicates. Pass `sections` for per-category drill-down details.\n\n" + "Categories run in tiers — Tier 1 (todos, metrics) return synchronously from cache. Tier 2 (dead_code, unused_exports, duplicates) waits for a fresh reuse scan up to a short deadline; if a category is still scanning the response reports `complete: false` with `pending_categories: [...]` rather than a fabricated clean count
|
|
35465
|
+
description: "Codebase health snapshot. One call returns summary stats for: TODOs, diagnostics, file/symbol metrics, dead code, unused exports, code duplicates, and TS/JS import cycles. Pass `sections` for per-category drill-down details.\n\n" + "Categories run in tiers — Tier 1 (todos, metrics) return synchronously from cache. Tier 2 (dead_code, unused_exports, duplicates, cycles) waits for a fresh reuse scan up to a short deadline; if a category is still scanning the response reports `complete: false` with `pending_categories: [...]` rather than a fabricated clean count. Rust module cycles are out of scope for `cycles`.\n\n" + `Use when: starting work on unfamiliar code, after multi-edit batches to check diagnostics, before a refactor, before review, or to verify cleanup completeness.
|
|
35323
35466
|
|
|
35324
35467
|
` + "Treat `dead_code` as a hint, not proof: reachability is call-based, so symbols reached only via method dispatch or referenced only in type position may be false positives — verify before deleting.",
|
|
35325
35468
|
args: {
|
|
35326
|
-
sections: arg(z10.union([z10.string(), z10.array(z10.string())]).optional().describe("Categories to include in detailed drill-down (e.g. 'todos' or ['todos', 'dead_code']). Use 'all' for every active category. Omit for summary-only mode.")),
|
|
35469
|
+
sections: arg(z10.union([z10.string(), z10.array(z10.string())]).optional().describe("Categories to include in detailed drill-down (e.g. 'todos' or ['todos', 'dead_code', 'cycles']). Use 'all' for every active category. Omit for summary-only mode.")),
|
|
35327
35470
|
scope: arg(z10.union([z10.string(), z10.array(z10.string())]).optional().describe("Restrict scan/results to paths under this scope (file or directory, absolute or relative to project root). Tier 1 scopes the scan; Tier 2 scans project-wide and applies scope as a result filter.")),
|
|
35328
35471
|
topK: arg(z10.number().int().positive().max(100).optional().describe("Max drill-down items per category. Default 20, max 100."))
|
|
35329
35472
|
},
|
|
@@ -36235,7 +36378,7 @@ function buildWorkflowHints(opts) {
|
|
|
36235
36378
|
}
|
|
36236
36379
|
if (hasBash && hasBgBash) {
|
|
36237
36380
|
sections.push([
|
|
36238
|
-
`**Long-running commands** (builds, installs, full test suites): run them in the FOREGROUND — \`${bashName}({ command })\`
|
|
36381
|
+
`**Long-running commands** (builds, installs, full test suites): run them in the FOREGROUND — use \`${bashName}({ command, wait: true })\` when you know it is long and need the result before anything else; otherwise omit \`wait\` so auto-promote can hand you a reminder while you work.`,
|
|
36239
36382
|
"- `background: true` is ONLY for when you have OTHER useful work to do while it runs: start it, do the other work, and the completion reminder delivers the result (or spawn a subagent for the side work). Do NOT background a command and then immediately `bash_watch` it — that spends a whole extra turn waiting for something foreground returns in one.",
|
|
36240
36383
|
"- `bash_watch` is for blocking on an ALREADY-backgrounded task once you've run out of parallel work (sync — the user can interrupt), or reacting to a specific early output line (async: background:true + pattern). Never loop `bash_status` to wait — it's a one-shot inspector."
|
|
36241
36384
|
].join(`
|
|
@@ -36292,12 +36435,13 @@ var PLUGIN_VERSION = (() => {
|
|
|
36292
36435
|
return "0.0.0";
|
|
36293
36436
|
}
|
|
36294
36437
|
})();
|
|
36295
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
36438
|
+
var ANNOUNCEMENT_VERSION = "0.45.0";
|
|
36296
36439
|
var ANNOUNCEMENT_FEATURES = [
|
|
36297
|
-
"
|
|
36298
|
-
|
|
36299
|
-
"
|
|
36300
|
-
"
|
|
36440
|
+
"Code Health verified against 12 real repositories: dead code is only reported for languages we can actually analyze (Java/Kotlin now say 'not analyzed' instead of guessing), and generated code (gen/ trees, *_pb.ts, DO NOT EDIT banners) moves out of the headline counts into its own bucket.",
|
|
36441
|
+
"Config files (playwright/eslint/tsup/vitest *.config.ts), Storybook stories, Mocha hooks, and SvelteKit hooks/$lib imports are no longer flagged as dead code.",
|
|
36442
|
+
"Rust module aliases, inline-module calls, and cross-crate pub use re-exports now resolve; Go interface methods (sort.Interface, Bubble Tea) are no longer flagged dead.",
|
|
36443
|
+
"Fixed npx @cortexkit/aft doctor --fix and setup failing to download the binary on fresh installs.",
|
|
36444
|
+
"Bridges now detect an updated aft binary on disk and respawn onto it automatically."
|
|
36301
36445
|
];
|
|
36302
36446
|
var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/DSa65w8wuf";
|
|
36303
36447
|
var plugin = async (input) => initializePluginForDirectory(input);
|