@cortexkit/aft-pi 0.39.4 → 0.40.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 +12 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +995 -1044
- package/dist/lsp-cache.d.ts +3 -3
- package/dist/lsp-github-install.d.ts +5 -5
- package/dist/lsp-github-install.d.ts.map +1 -1
- package/dist/lsp-github-probe.d.ts +1 -1
- package/dist/lsp-github-probe.d.ts.map +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.d.ts.map +1 -1
- package/dist/tools/ast.d.ts.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/fs.d.ts.map +1 -1
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tools/inspect.d.ts.map +1 -1
- package/dist/tools/reading.d.ts.map +1 -1
- package/dist/tools/semantic.d.ts +1 -0
- package/dist/tools/semantic.d.ts.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/workflow-hints.d.ts.map +1 -1
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -11675,11 +11675,6 @@ function error(message, meta) {
|
|
|
11675
11675
|
}
|
|
11676
11676
|
}
|
|
11677
11677
|
// ../aft-bridge/dist/bash-format.js
|
|
11678
|
-
function appendPipeStripNote(output, note) {
|
|
11679
|
-
return note ? `${output}
|
|
11680
|
-
|
|
11681
|
-
${note}` : output;
|
|
11682
|
-
}
|
|
11683
11678
|
function formatSeconds(ms) {
|
|
11684
11679
|
return `${Number((ms / 1000).toFixed(1))}s`;
|
|
11685
11680
|
}
|
|
@@ -11757,12 +11752,16 @@ function maybeAppendGrepSearchHint(output, command, aftSearchRegistered, project
|
|
|
11757
11752
|
${hint}`;
|
|
11758
11753
|
}
|
|
11759
11754
|
function shouldSuppressGrepSearchHint(command, projectRoot) {
|
|
11760
|
-
const root = projectRoot?.trim();
|
|
11761
|
-
if (!root)
|
|
11762
|
-
return false;
|
|
11763
11755
|
const statements = splitTopLevelStatements(command);
|
|
11764
11756
|
if (statements === null)
|
|
11765
11757
|
return false;
|
|
11758
|
+
if (allSearchPathOperandsAreDynamic(statements))
|
|
11759
|
+
return true;
|
|
11760
|
+
const root = projectRoot?.trim();
|
|
11761
|
+
if (!root)
|
|
11762
|
+
return false;
|
|
11763
|
+
const resolvedRoot = path.resolve(root);
|
|
11764
|
+
let effectiveCwd = resolvedRoot;
|
|
11766
11765
|
let sawCodeSearchStatement = false;
|
|
11767
11766
|
for (const statement of statements) {
|
|
11768
11767
|
const firstStage = firstPipelineStage(statement);
|
|
@@ -11771,19 +11770,84 @@ function shouldSuppressGrepSearchHint(command, projectRoot) {
|
|
|
11771
11770
|
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
|
|
11772
11771
|
if (firstToken === null)
|
|
11773
11772
|
continue;
|
|
11774
|
-
|
|
11773
|
+
const head = firstToken.token;
|
|
11774
|
+
if (head === "cd") {
|
|
11775
|
+
effectiveCwd = nextCwdAfterCd(effectiveCwd, firstStage, firstToken.end);
|
|
11776
|
+
continue;
|
|
11777
|
+
}
|
|
11778
|
+
if (head !== "grep" && head !== "rg")
|
|
11775
11779
|
continue;
|
|
11776
11780
|
sawCodeSearchStatement = true;
|
|
11781
|
+
if (effectiveCwd === null)
|
|
11782
|
+
continue;
|
|
11783
|
+
if (!isDirInsideProject(resolvedRoot, effectiveCwd))
|
|
11784
|
+
continue;
|
|
11777
11785
|
const operands = collectPathOperands(firstStage, firstToken.end);
|
|
11778
11786
|
if (operands.length === 0)
|
|
11779
11787
|
return false;
|
|
11780
11788
|
for (const operand of operands) {
|
|
11781
|
-
if (
|
|
11789
|
+
if (isDynamicPathOperand(operand))
|
|
11790
|
+
continue;
|
|
11791
|
+
if (isPathInsideProject(resolvedRoot, effectiveCwd, operand))
|
|
11782
11792
|
return false;
|
|
11783
11793
|
}
|
|
11784
11794
|
}
|
|
11785
11795
|
return sawCodeSearchStatement;
|
|
11786
11796
|
}
|
|
11797
|
+
function allSearchPathOperandsAreDynamic(statements) {
|
|
11798
|
+
let sawDynamicOnlySearch = false;
|
|
11799
|
+
for (const statement of statements) {
|
|
11800
|
+
const firstStage = firstPipelineStage(statement);
|
|
11801
|
+
if (firstStage === null)
|
|
11802
|
+
continue;
|
|
11803
|
+
const firstToken = readShellToken(firstStage, skipSpaces(firstStage, 0));
|
|
11804
|
+
if (firstToken === null)
|
|
11805
|
+
continue;
|
|
11806
|
+
const head = firstToken.token;
|
|
11807
|
+
if (head !== "grep" && head !== "rg")
|
|
11808
|
+
continue;
|
|
11809
|
+
const operands = collectPathOperands(firstStage, firstToken.end);
|
|
11810
|
+
if (operands.length === 0)
|
|
11811
|
+
return false;
|
|
11812
|
+
if (operands.some((operand) => !isDynamicPathOperand(operand)))
|
|
11813
|
+
return false;
|
|
11814
|
+
sawDynamicOnlySearch = true;
|
|
11815
|
+
}
|
|
11816
|
+
return sawDynamicOnlySearch;
|
|
11817
|
+
}
|
|
11818
|
+
function nextCwdAfterCd(currentCwd, firstStage, afterCd) {
|
|
11819
|
+
let index = skipSpaces(firstStage, afterCd);
|
|
11820
|
+
let target = null;
|
|
11821
|
+
while (index < firstStage.length) {
|
|
11822
|
+
const tokenResult = readShellToken(firstStage, index);
|
|
11823
|
+
if (tokenResult === null)
|
|
11824
|
+
break;
|
|
11825
|
+
const { token, end } = tokenResult;
|
|
11826
|
+
if (end <= index)
|
|
11827
|
+
break;
|
|
11828
|
+
index = skipSpaces(firstStage, end);
|
|
11829
|
+
if (token === "-")
|
|
11830
|
+
return null;
|
|
11831
|
+
if (token.length > 1 && token.startsWith("-"))
|
|
11832
|
+
continue;
|
|
11833
|
+
target = token;
|
|
11834
|
+
break;
|
|
11835
|
+
}
|
|
11836
|
+
if (target === null)
|
|
11837
|
+
return path.resolve(os.homedir());
|
|
11838
|
+
if (target.includes("$") || target.includes("`"))
|
|
11839
|
+
return null;
|
|
11840
|
+
const expanded = expandTilde(target);
|
|
11841
|
+
if (path.isAbsolute(expanded))
|
|
11842
|
+
return path.resolve(expanded);
|
|
11843
|
+
if (currentCwd === null)
|
|
11844
|
+
return null;
|
|
11845
|
+
return path.resolve(currentCwd, expanded);
|
|
11846
|
+
}
|
|
11847
|
+
function isDirInsideProject(resolvedRoot, dir) {
|
|
11848
|
+
const rel = path.relative(resolvedRoot, path.resolve(dir));
|
|
11849
|
+
return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
11850
|
+
}
|
|
11787
11851
|
function collectPathOperands(firstStage, startAfterCommand) {
|
|
11788
11852
|
const operands = [];
|
|
11789
11853
|
let index = skipSpaces(firstStage, startAfterCommand);
|
|
@@ -11805,6 +11869,9 @@ function collectPathOperands(firstStage, startAfterCommand) {
|
|
|
11805
11869
|
function looksLikePathOperand(token) {
|
|
11806
11870
|
return token.includes("/") || token.startsWith("~") || token.startsWith("./") || token.startsWith("../");
|
|
11807
11871
|
}
|
|
11872
|
+
function isDynamicPathOperand(token) {
|
|
11873
|
+
return token.startsWith("~") || token.includes("$") || token.includes("`");
|
|
11874
|
+
}
|
|
11808
11875
|
function expandTilde(target) {
|
|
11809
11876
|
if (!target.startsWith("~"))
|
|
11810
11877
|
return target;
|
|
@@ -11817,10 +11884,9 @@ function resolvePathOperand(projectRoot, operand) {
|
|
|
11817
11884
|
const expanded = expandTilde(operand);
|
|
11818
11885
|
return path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(projectRoot, expanded);
|
|
11819
11886
|
}
|
|
11820
|
-
function isPathInsideProject(
|
|
11821
|
-
const
|
|
11822
|
-
const
|
|
11823
|
-
const rel = path.relative(root, resolved);
|
|
11887
|
+
function isPathInsideProject(resolvedRoot, baseCwd, operand) {
|
|
11888
|
+
const resolved = resolvePathOperand(baseCwd, operand);
|
|
11889
|
+
const rel = path.relative(resolvedRoot, resolved);
|
|
11824
11890
|
return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
11825
11891
|
}
|
|
11826
11892
|
function splitTopLevelStatements(command) {
|
|
@@ -12013,6 +12079,7 @@ var LONG_RUNNING_COMMAND_TIMEOUT_MS = {
|
|
|
12013
12079
|
trace_to_symbol: 60000,
|
|
12014
12080
|
trace_data: 60000,
|
|
12015
12081
|
impact: 60000,
|
|
12082
|
+
inspect: 60000,
|
|
12016
12083
|
grep: 60000,
|
|
12017
12084
|
glob: 60000,
|
|
12018
12085
|
semantic_search: 60000
|
|
@@ -12071,7 +12138,6 @@ function formatStatusBar(counts) {
|
|
|
12071
12138
|
// ../aft-bridge/dist/bridge.js
|
|
12072
12139
|
var DEFAULT_BRIDGE_TIMEOUT_MS = 30000;
|
|
12073
12140
|
var BRIDGE_HANG_TIMEOUT_THRESHOLD = 2;
|
|
12074
|
-
var SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS = 5000;
|
|
12075
12141
|
var MAX_STDOUT_BUFFER = 64 * 1024 * 1024;
|
|
12076
12142
|
var STDOUT_BUFFER_COMPACT_THRESHOLD = 64 * 1024;
|
|
12077
12143
|
var TERMINAL_BASH_STATUSES = new Set([
|
|
@@ -12144,28 +12210,19 @@ function compareSemver(a, b) {
|
|
|
12144
12210
|
}
|
|
12145
12211
|
return 0;
|
|
12146
12212
|
}
|
|
12147
|
-
function
|
|
12148
|
-
|
|
12149
|
-
|
|
12150
|
-
|
|
12151
|
-
|
|
12152
|
-
|
|
12153
|
-
|
|
12154
|
-
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
const maxSemanticTimeoutMs = semanticTransportBudgetMs > SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS ? semanticTransportBudgetMs - SEMANTIC_TIMEOUT_SAFETY_MARGIN_MS : Math.max(1, semanticTransportBudgetMs - 1);
|
|
12158
|
-
if (timeoutMs <= maxSemanticTimeoutMs) {
|
|
12159
|
-
return configOverrides;
|
|
12160
|
-
}
|
|
12161
|
-
warn(`semantic.timeout_ms=${timeoutMs} exceeds the semantic transport budget; clamping to ${maxSemanticTimeoutMs}ms (budget: ${semanticTransportBudgetMs}ms)`);
|
|
12162
|
-
return {
|
|
12163
|
-
...configOverrides,
|
|
12164
|
-
semantic: {
|
|
12165
|
-
...semantic,
|
|
12166
|
-
timeout_ms: maxSemanticTimeoutMs
|
|
12213
|
+
function coerceConfigureDroppedKeys(value) {
|
|
12214
|
+
if (!Array.isArray(value))
|
|
12215
|
+
return [];
|
|
12216
|
+
const dropped = [];
|
|
12217
|
+
for (const item of value) {
|
|
12218
|
+
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
12219
|
+
continue;
|
|
12220
|
+
const record = item;
|
|
12221
|
+
if (typeof record.key === "string" && typeof record.tier === "string" && typeof record.reason === "string") {
|
|
12222
|
+
dropped.push({ key: record.key, tier: record.tier, reason: record.reason });
|
|
12167
12223
|
}
|
|
12168
|
-
}
|
|
12224
|
+
}
|
|
12225
|
+
return dropped;
|
|
12169
12226
|
}
|
|
12170
12227
|
|
|
12171
12228
|
class BridgeReplacedDuringVersionCheck extends Error {
|
|
@@ -12235,7 +12292,7 @@ class BinaryBridge {
|
|
|
12235
12292
|
this.timeoutMs = options?.timeoutMs ?? DEFAULT_BRIDGE_TIMEOUT_MS;
|
|
12236
12293
|
this.hangThreshold = options?.hangThreshold ?? BRIDGE_HANG_TIMEOUT_THRESHOLD;
|
|
12237
12294
|
this.maxRestarts = options?.maxRestarts ?? 3;
|
|
12238
|
-
this.configOverrides =
|
|
12295
|
+
this.configOverrides = configOverrides ?? {};
|
|
12239
12296
|
this.minVersion = options?.minVersion;
|
|
12240
12297
|
this.onVersionMismatch = options?.onVersionMismatch;
|
|
12241
12298
|
this.onConfigureWarnings = options?.onConfigureWarnings;
|
|
@@ -12472,18 +12529,24 @@ class BinaryBridge {
|
|
|
12472
12529
|
}
|
|
12473
12530
|
}
|
|
12474
12531
|
async deliverConfigureWarnings(configResult, params, options) {
|
|
12475
|
-
if (!this.onConfigureWarnings
|
|
12532
|
+
if (!this.onConfigureWarnings)
|
|
12476
12533
|
return;
|
|
12477
|
-
|
|
12534
|
+
const warnings = Array.isArray(configResult.warnings) ? configResult.warnings : [];
|
|
12535
|
+
const configDroppedKeys = coerceConfigureDroppedKeys(configResult.config_dropped_keys);
|
|
12536
|
+
if (warnings.length === 0 && configDroppedKeys.length === 0)
|
|
12478
12537
|
return;
|
|
12479
12538
|
const sessionId = typeof params.session_id === "string" ? params.session_id : undefined;
|
|
12539
|
+
const context = {
|
|
12540
|
+
projectRoot: this.cwd,
|
|
12541
|
+
sessionId,
|
|
12542
|
+
client: options?.configureWarningClient ?? (sessionId ? this.configureWarningClients.get(sessionId) : undefined),
|
|
12543
|
+
warnings
|
|
12544
|
+
};
|
|
12545
|
+
if (configDroppedKeys.length > 0) {
|
|
12546
|
+
context.configDroppedKeys = configDroppedKeys;
|
|
12547
|
+
}
|
|
12480
12548
|
try {
|
|
12481
|
-
await this.onConfigureWarnings(
|
|
12482
|
-
projectRoot: this.cwd,
|
|
12483
|
-
sessionId,
|
|
12484
|
-
client: options?.configureWarningClient ?? (sessionId ? this.configureWarningClients.get(sessionId) : undefined),
|
|
12485
|
-
warnings: configResult.warnings
|
|
12486
|
-
});
|
|
12549
|
+
await this.onConfigureWarnings(context);
|
|
12487
12550
|
} catch (err) {
|
|
12488
12551
|
this.warnVia(`configure warning delivery failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
12489
12552
|
} finally {
|
|
@@ -13190,6 +13253,48 @@ function coerceStringArray(value) {
|
|
|
13190
13253
|
}
|
|
13191
13254
|
return [];
|
|
13192
13255
|
}
|
|
13256
|
+
function coerceTargetParam(value) {
|
|
13257
|
+
if (Array.isArray(value)) {
|
|
13258
|
+
return value.filter((entry) => typeof entry === "string" && entry.length > 0);
|
|
13259
|
+
}
|
|
13260
|
+
if (typeof value === "string") {
|
|
13261
|
+
const trimmed = value.trim();
|
|
13262
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
13263
|
+
try {
|
|
13264
|
+
const parsed = JSON.parse(trimmed);
|
|
13265
|
+
if (Array.isArray(parsed)) {
|
|
13266
|
+
return parsed.filter((entry) => typeof entry === "string" && entry.length > 0);
|
|
13267
|
+
}
|
|
13268
|
+
} catch {}
|
|
13269
|
+
}
|
|
13270
|
+
return value;
|
|
13271
|
+
}
|
|
13272
|
+
return value;
|
|
13273
|
+
}
|
|
13274
|
+
function coerceBoolean(value, defaultValue = false) {
|
|
13275
|
+
if (defaultValue) {
|
|
13276
|
+
if (value === undefined)
|
|
13277
|
+
return true;
|
|
13278
|
+
if (typeof value === "boolean")
|
|
13279
|
+
return value;
|
|
13280
|
+
if (typeof value === "number")
|
|
13281
|
+
return value !== 0;
|
|
13282
|
+
if (typeof value === "string") {
|
|
13283
|
+
const normalized = value.trim().toLowerCase();
|
|
13284
|
+
return normalized !== "false" && normalized !== "0";
|
|
13285
|
+
}
|
|
13286
|
+
return true;
|
|
13287
|
+
}
|
|
13288
|
+
if (typeof value === "boolean")
|
|
13289
|
+
return value;
|
|
13290
|
+
if (typeof value === "number")
|
|
13291
|
+
return value === 1;
|
|
13292
|
+
if (typeof value === "string") {
|
|
13293
|
+
const normalized = value.trim().toLowerCase();
|
|
13294
|
+
return normalized === "true" || normalized === "1";
|
|
13295
|
+
}
|
|
13296
|
+
return false;
|
|
13297
|
+
}
|
|
13193
13298
|
function coerceOptionalInt(v, paramName, min, max) {
|
|
13194
13299
|
if (v === undefined || v === null || v === "")
|
|
13195
13300
|
return;
|
|
@@ -13215,10 +13320,43 @@ function isEmptyParam(value) {
|
|
|
13215
13320
|
return Object.keys(value).length === 0;
|
|
13216
13321
|
return false;
|
|
13217
13322
|
}
|
|
13323
|
+
// ../aft-bridge/dist/config-tiers.js
|
|
13324
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
13325
|
+
import { resolve as resolve2 } from "node:path";
|
|
13326
|
+
function readConfigTiers(opts) {
|
|
13327
|
+
const tiers = [];
|
|
13328
|
+
try {
|
|
13329
|
+
if (existsSync(opts.userConfigPath)) {
|
|
13330
|
+
const doc = readFileSync(opts.userConfigPath, "utf-8");
|
|
13331
|
+
tiers.push({
|
|
13332
|
+
tier: "user",
|
|
13333
|
+
source: resolve2(opts.userConfigPath),
|
|
13334
|
+
doc
|
|
13335
|
+
});
|
|
13336
|
+
}
|
|
13337
|
+
} catch {}
|
|
13338
|
+
try {
|
|
13339
|
+
if (existsSync(opts.projectConfigPath)) {
|
|
13340
|
+
const doc = readFileSync(opts.projectConfigPath, "utf-8");
|
|
13341
|
+
tiers.push({
|
|
13342
|
+
tier: "project",
|
|
13343
|
+
source: resolve2(opts.projectConfigPath),
|
|
13344
|
+
doc
|
|
13345
|
+
});
|
|
13346
|
+
}
|
|
13347
|
+
} catch {}
|
|
13348
|
+
return tiers;
|
|
13349
|
+
}
|
|
13350
|
+
function formatDroppedKeyWarnings(dropped) {
|
|
13351
|
+
if (!dropped || !Array.isArray(dropped)) {
|
|
13352
|
+
return [];
|
|
13353
|
+
}
|
|
13354
|
+
return dropped.map((item) => `Ignoring ${item.key} from ${item.tier} config (${item.reason})`);
|
|
13355
|
+
}
|
|
13218
13356
|
// ../aft-bridge/dist/downloader.js
|
|
13219
13357
|
import { spawnSync } from "node:child_process";
|
|
13220
13358
|
import { createHash, randomUUID } from "node:crypto";
|
|
13221
|
-
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
13359
|
+
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync as existsSync2, mkdirSync, openSync, readFileSync as readFileSync2, renameSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
13222
13360
|
import { homedir as homedir4 } from "node:os";
|
|
13223
13361
|
import { join as join3 } from "node:path";
|
|
13224
13362
|
import { Readable } from "node:stream";
|
|
@@ -13290,7 +13428,7 @@ function getCachedBinaryPath(version) {
|
|
|
13290
13428
|
if (!version)
|
|
13291
13429
|
return null;
|
|
13292
13430
|
const binaryPath = join3(getCacheDir(), version, getBinaryName());
|
|
13293
|
-
return
|
|
13431
|
+
return existsSync2(binaryPath) ? binaryPath : null;
|
|
13294
13432
|
}
|
|
13295
13433
|
async function downloadBinary(version) {
|
|
13296
13434
|
const archMap = PLATFORM_ARCH_MAP[process.platform] ?? {};
|
|
@@ -13309,7 +13447,7 @@ async function downloadBinary(version) {
|
|
|
13309
13447
|
const versionedCacheDir = join3(getCacheDir(), tag);
|
|
13310
13448
|
const binaryName = getBinaryName();
|
|
13311
13449
|
const binaryPath = join3(versionedCacheDir, binaryName);
|
|
13312
|
-
if (
|
|
13450
|
+
if (existsSync2(binaryPath) && isExpectedCachedBinary(binaryPath, tag)) {
|
|
13313
13451
|
return binaryPath;
|
|
13314
13452
|
}
|
|
13315
13453
|
const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
|
|
@@ -13323,11 +13461,11 @@ async function downloadBinary(version) {
|
|
|
13323
13461
|
let checksumTimeout = null;
|
|
13324
13462
|
const tmpPath = `${binaryPath}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`;
|
|
13325
13463
|
try {
|
|
13326
|
-
if (!
|
|
13464
|
+
if (!existsSync2(versionedCacheDir)) {
|
|
13327
13465
|
mkdirSync(versionedCacheDir, { recursive: true });
|
|
13328
13466
|
}
|
|
13329
13467
|
releaseLock = await acquireDownloadLock(lockPath);
|
|
13330
|
-
if (
|
|
13468
|
+
if (existsSync2(binaryPath) && isExpectedCachedBinary(binaryPath, tag)) {
|
|
13331
13469
|
return binaryPath;
|
|
13332
13470
|
}
|
|
13333
13471
|
binaryController = new AbortController;
|
|
@@ -13392,7 +13530,7 @@ async function downloadBinary(version) {
|
|
|
13392
13530
|
renameSync(tmpPath, binaryPath);
|
|
13393
13531
|
}
|
|
13394
13532
|
try {
|
|
13395
|
-
if (
|
|
13533
|
+
if (existsSync2(tmpPath))
|
|
13396
13534
|
unlinkSync(tmpPath);
|
|
13397
13535
|
} catch {
|
|
13398
13536
|
warn(`Could not clean up temporary download file ${tmpPath} — it can be removed manually.`);
|
|
@@ -13402,7 +13540,7 @@ async function downloadBinary(version) {
|
|
|
13402
13540
|
} catch (err) {
|
|
13403
13541
|
const msg = err instanceof Error ? err.message : String(err);
|
|
13404
13542
|
error(`Failed to download AFT binary: ${msg}`);
|
|
13405
|
-
if (
|
|
13543
|
+
if (existsSync2(tmpPath)) {
|
|
13406
13544
|
try {
|
|
13407
13545
|
unlinkSync(tmpPath);
|
|
13408
13546
|
} catch {}
|
|
@@ -13446,7 +13584,7 @@ async function acquireDownloadLock(lockPath) {
|
|
|
13446
13584
|
closeSync(fd);
|
|
13447
13585
|
} catch {}
|
|
13448
13586
|
try {
|
|
13449
|
-
if (
|
|
13587
|
+
if (readFileSync2(lockPath, "utf-8") === owner) {
|
|
13450
13588
|
rmSync(lockPath, { force: true });
|
|
13451
13589
|
}
|
|
13452
13590
|
} catch {}
|
|
@@ -13467,7 +13605,7 @@ async function acquireDownloadLock(lockPath) {
|
|
|
13467
13605
|
if (Date.now() - startedAt > DOWNLOAD_LOCK_TIMEOUT_MS) {
|
|
13468
13606
|
throw new Error(`Timed out waiting for download lock: ${lockPath}`);
|
|
13469
13607
|
}
|
|
13470
|
-
await new Promise((
|
|
13608
|
+
await new Promise((resolve3) => setTimeout(resolve3, 100));
|
|
13471
13609
|
}
|
|
13472
13610
|
}
|
|
13473
13611
|
}
|
|
@@ -13571,20 +13709,71 @@ function stripJsoncSymbols(value) {
|
|
|
13571
13709
|
}
|
|
13572
13710
|
// ../aft-bridge/dist/migration.js
|
|
13573
13711
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
13574
|
-
import { existsSync as
|
|
13575
|
-
import { homedir as
|
|
13576
|
-
import { dirname as dirname2, join as join6 } from "node:path";
|
|
13712
|
+
import { closeSync as closeSync3, existsSync as existsSync5, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as readFileSync4, renameSync as renameSync4, rmSync as rmSync2, statSync as statSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
13713
|
+
import { homedir as homedir7, tmpdir } from "node:os";
|
|
13714
|
+
import { basename, dirname as dirname2, join as join6, resolve as resolve4 } from "node:path";
|
|
13577
13715
|
|
|
13578
13716
|
// ../aft-bridge/dist/paths.js
|
|
13579
|
-
import { existsSync as
|
|
13580
|
-
import {
|
|
13717
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync } from "node:fs";
|
|
13718
|
+
import { homedir as homedir5 } from "node:os";
|
|
13719
|
+
import { dirname, isAbsolute as isAbsolute2, join as join4, resolve as resolve3 } from "node:path";
|
|
13720
|
+
function homeDir() {
|
|
13721
|
+
if (process.platform === "win32")
|
|
13722
|
+
return process.env.USERPROFILE || process.env.HOME || homedir5();
|
|
13723
|
+
return process.env.HOME || homedir5();
|
|
13724
|
+
}
|
|
13725
|
+
function configHome() {
|
|
13726
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
13727
|
+
if (xdg && isAbsolute2(xdg))
|
|
13728
|
+
return xdg;
|
|
13729
|
+
return join4(homeDir(), ".config");
|
|
13730
|
+
}
|
|
13731
|
+
function legacyOpenCodeConfigDir() {
|
|
13732
|
+
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
13733
|
+
if (envDir)
|
|
13734
|
+
return resolve3(envDir);
|
|
13735
|
+
return join4(configHome(), "opencode");
|
|
13736
|
+
}
|
|
13737
|
+
function legacyPiAgentDir() {
|
|
13738
|
+
return join4(homeDir(), ".pi", "agent");
|
|
13739
|
+
}
|
|
13740
|
+
function legacySources(basePath, label, harness) {
|
|
13741
|
+
return [
|
|
13742
|
+
{ path: `${basePath}.jsonc`, label: `${label} aft.jsonc`, harness },
|
|
13743
|
+
{ path: `${basePath}.json`, label: `${label} aft.json`, harness }
|
|
13744
|
+
];
|
|
13745
|
+
}
|
|
13746
|
+
function resolveCortexKitUserConfigPath() {
|
|
13747
|
+
return join4(configHome(), "cortexkit", "aft.jsonc");
|
|
13748
|
+
}
|
|
13749
|
+
function resolveCortexKitProjectConfigPath(projectDirectory) {
|
|
13750
|
+
return join4(projectDirectory, ".cortexkit", "aft.jsonc");
|
|
13751
|
+
}
|
|
13752
|
+
function resolveCortexKitConfigPaths(projectDirectory) {
|
|
13753
|
+
return {
|
|
13754
|
+
userConfigPath: resolveCortexKitUserConfigPath(),
|
|
13755
|
+
projectConfigPath: resolveCortexKitProjectConfigPath(projectDirectory)
|
|
13756
|
+
};
|
|
13757
|
+
}
|
|
13758
|
+
function resolveLegacyAftConfigSources(projectDirectory) {
|
|
13759
|
+
return {
|
|
13760
|
+
user: [
|
|
13761
|
+
...legacySources(join4(legacyOpenCodeConfigDir(), "aft"), "OpenCode user", "opencode"),
|
|
13762
|
+
...legacySources(join4(legacyPiAgentDir(), "aft"), "Pi user", "pi")
|
|
13763
|
+
],
|
|
13764
|
+
project: [
|
|
13765
|
+
...legacySources(join4(projectDirectory, ".opencode", "aft"), "OpenCode project", "opencode"),
|
|
13766
|
+
...legacySources(join4(projectDirectory, ".pi", "aft"), "Pi project", "pi")
|
|
13767
|
+
]
|
|
13768
|
+
};
|
|
13769
|
+
}
|
|
13581
13770
|
function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
|
|
13582
13771
|
return join4(storageRoot, harness, ...segments);
|
|
13583
13772
|
}
|
|
13584
13773
|
function repairRootScopedStorageFile(storageRoot, harness, fileName) {
|
|
13585
13774
|
const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
|
|
13586
13775
|
const rootPath = join4(storageRoot, fileName);
|
|
13587
|
-
if (
|
|
13776
|
+
if (existsSync3(harnessPath) || !existsSync3(rootPath))
|
|
13588
13777
|
return harnessPath;
|
|
13589
13778
|
try {
|
|
13590
13779
|
mkdirSync2(dirname(harnessPath), { recursive: true });
|
|
@@ -13598,8 +13787,8 @@ function shouldShowAnnouncement(storageRoot, harness, currentVersion) {
|
|
|
13598
13787
|
const versionFile = repairRootScopedStorageFile(storageRoot, harness, "last_announced_version");
|
|
13599
13788
|
let lastVersion = "";
|
|
13600
13789
|
try {
|
|
13601
|
-
if (
|
|
13602
|
-
lastVersion =
|
|
13790
|
+
if (existsSync3(versionFile)) {
|
|
13791
|
+
lastVersion = readFileSync3(versionFile, "utf-8").trim();
|
|
13603
13792
|
}
|
|
13604
13793
|
} catch {
|
|
13605
13794
|
return false;
|
|
@@ -13627,9 +13816,9 @@ function markAnnouncementSeen(storageRoot, harness, currentVersion) {
|
|
|
13627
13816
|
|
|
13628
13817
|
// ../aft-bridge/dist/resolver.js
|
|
13629
13818
|
import { execSync } from "node:child_process";
|
|
13630
|
-
import { chmodSync as chmodSync2, closeSync as closeSync2, copyFileSync as copyFileSync2, existsSync as
|
|
13819
|
+
import { chmodSync as chmodSync2, closeSync as closeSync2, copyFileSync as copyFileSync2, existsSync as existsSync4, mkdirSync as mkdirSync3, openSync as openSync2, readSync, renameSync as renameSync3, unlinkSync as unlinkSync2 } from "node:fs";
|
|
13631
13820
|
import { createRequire as createRequire2 } from "node:module";
|
|
13632
|
-
import { homedir as
|
|
13821
|
+
import { homedir as homedir6 } from "node:os";
|
|
13633
13822
|
import { join as join5 } from "node:path";
|
|
13634
13823
|
var ensureBinaryForResolver = ensureBinary;
|
|
13635
13824
|
function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
@@ -13642,7 +13831,7 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
|
13642
13831
|
const versionedDir = join5(cacheDir, tag);
|
|
13643
13832
|
const ext = process.platform === "win32" ? ".exe" : "";
|
|
13644
13833
|
const cachedPath = join5(versionedDir, `aft${ext}`);
|
|
13645
|
-
if (
|
|
13834
|
+
if (existsSync4(cachedPath)) {
|
|
13646
13835
|
const cachedVersion = readBinaryVersion(cachedPath);
|
|
13647
13836
|
if (cachedVersion === version)
|
|
13648
13837
|
return cachedPath;
|
|
@@ -13654,7 +13843,7 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
|
13654
13843
|
if (process.platform !== "win32") {
|
|
13655
13844
|
chmodSync2(tmpPath, 493);
|
|
13656
13845
|
}
|
|
13657
|
-
if (process.platform === "win32" &&
|
|
13846
|
+
if (process.platform === "win32" && existsSync4(cachedPath)) {
|
|
13658
13847
|
try {
|
|
13659
13848
|
unlinkSync2(cachedPath);
|
|
13660
13849
|
} catch {}
|
|
@@ -13671,7 +13860,7 @@ function normalizeBareVersion(version) {
|
|
|
13671
13860
|
return version.startsWith("v") ? version.slice(1) : version;
|
|
13672
13861
|
}
|
|
13673
13862
|
function homeDirFromEnv(env) {
|
|
13674
|
-
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) ||
|
|
13863
|
+
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir6();
|
|
13675
13864
|
}
|
|
13676
13865
|
function cacheDirFromEnv(env) {
|
|
13677
13866
|
if (process.platform === "win32") {
|
|
@@ -13683,7 +13872,7 @@ function cacheDirFromEnv(env) {
|
|
|
13683
13872
|
}
|
|
13684
13873
|
function cachedBinaryPathFromEnv(version, env, ext) {
|
|
13685
13874
|
const binaryPath = join5(cacheDirFromEnv(env), version, `aft${ext}`);
|
|
13686
|
-
return
|
|
13875
|
+
return existsSync4(binaryPath) ? binaryPath : null;
|
|
13687
13876
|
}
|
|
13688
13877
|
function isExpectedCachedBinary2(binaryPath, expectedVersion) {
|
|
13689
13878
|
const expected = normalizeBareVersion(expectedVersion);
|
|
@@ -13772,7 +13961,7 @@ function findBinarySync(expectedVersion) {
|
|
|
13772
13961
|
const packageBin = `@cortexkit/aft-${key}/bin/aft${ext}`;
|
|
13773
13962
|
const req = createRequire2(import.meta.url);
|
|
13774
13963
|
const resolved = req.resolve(packageBin);
|
|
13775
|
-
if (
|
|
13964
|
+
if (existsSync4(resolved)) {
|
|
13776
13965
|
const npmVersion = readBinaryVersion(resolved);
|
|
13777
13966
|
if (npmVersion === null) {
|
|
13778
13967
|
warn(`npm platform package binary at ${resolved} did not report a version; skipping (continuing to PATH lookup)`);
|
|
@@ -13802,7 +13991,7 @@ function findBinarySync(expectedVersion) {
|
|
|
13802
13991
|
}
|
|
13803
13992
|
} catch {}
|
|
13804
13993
|
const cargoPath = join5(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
|
|
13805
|
-
if (
|
|
13994
|
+
if (existsSync4(cargoPath)) {
|
|
13806
13995
|
const usable = probeBinaryCandidate(cargoPath, "cargo", expectedVersion);
|
|
13807
13996
|
if (usable)
|
|
13808
13997
|
return usable;
|
|
@@ -13847,23 +14036,343 @@ function dataHome() {
|
|
|
13847
14036
|
if (process.env.XDG_DATA_HOME)
|
|
13848
14037
|
return process.env.XDG_DATA_HOME;
|
|
13849
14038
|
if (process.platform === "win32") {
|
|
13850
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA || join6(
|
|
14039
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join6(homeDir2(), "AppData", "Local");
|
|
13851
14040
|
}
|
|
13852
|
-
return join6(
|
|
14041
|
+
return join6(homeDir2(), ".local", "share");
|
|
13853
14042
|
}
|
|
13854
|
-
function
|
|
14043
|
+
function homeDir2() {
|
|
13855
14044
|
if (process.platform === "win32")
|
|
13856
|
-
return process.env.USERPROFILE || process.env.HOME ||
|
|
13857
|
-
return process.env.HOME ||
|
|
14045
|
+
return process.env.USERPROFILE || process.env.HOME || homedir7();
|
|
14046
|
+
return process.env.HOME || homedir7();
|
|
13858
14047
|
}
|
|
13859
14048
|
function resolveLegacyStorageRoot(harness) {
|
|
13860
14049
|
if (harness === "pi")
|
|
13861
|
-
return join6(
|
|
14050
|
+
return join6(homeDir2(), ".pi", "agent", "aft");
|
|
13862
14051
|
return join6(dataHome(), "opencode", "storage", "plugin", "aft");
|
|
13863
14052
|
}
|
|
13864
14053
|
function resolveCortexKitStorageRoot() {
|
|
13865
14054
|
return join6(dataHome(), "cortexkit", "aft");
|
|
13866
14055
|
}
|
|
14056
|
+
function stripJsoncForParse(input) {
|
|
14057
|
+
let out = "";
|
|
14058
|
+
let inString = false;
|
|
14059
|
+
let escaped = false;
|
|
14060
|
+
for (let i = 0;i < input.length; i++) {
|
|
14061
|
+
const ch = input[i];
|
|
14062
|
+
const next = input[i + 1];
|
|
14063
|
+
if (inString) {
|
|
14064
|
+
out += ch;
|
|
14065
|
+
if (escaped) {
|
|
14066
|
+
escaped = false;
|
|
14067
|
+
} else if (ch === "\\") {
|
|
14068
|
+
escaped = true;
|
|
14069
|
+
} else if (ch === '"') {
|
|
14070
|
+
inString = false;
|
|
14071
|
+
}
|
|
14072
|
+
continue;
|
|
14073
|
+
}
|
|
14074
|
+
if (ch === '"') {
|
|
14075
|
+
inString = true;
|
|
14076
|
+
out += ch;
|
|
14077
|
+
continue;
|
|
14078
|
+
}
|
|
14079
|
+
if (ch === "/" && next === "/") {
|
|
14080
|
+
while (i < input.length && input[i] !== `
|
|
14081
|
+
`)
|
|
14082
|
+
i++;
|
|
14083
|
+
out += `
|
|
14084
|
+
`;
|
|
14085
|
+
continue;
|
|
14086
|
+
}
|
|
14087
|
+
if (ch === "/" && next === "*") {
|
|
14088
|
+
i += 2;
|
|
14089
|
+
while (i < input.length && !(input[i] === "*" && input[i + 1] === "/"))
|
|
14090
|
+
i++;
|
|
14091
|
+
i++;
|
|
14092
|
+
out += " ";
|
|
14093
|
+
continue;
|
|
14094
|
+
}
|
|
14095
|
+
out += ch;
|
|
14096
|
+
}
|
|
14097
|
+
let withoutTrailingCommas = "";
|
|
14098
|
+
inString = false;
|
|
14099
|
+
escaped = false;
|
|
14100
|
+
for (let i = 0;i < out.length; i++) {
|
|
14101
|
+
const ch = out[i];
|
|
14102
|
+
if (inString) {
|
|
14103
|
+
withoutTrailingCommas += ch;
|
|
14104
|
+
if (escaped) {
|
|
14105
|
+
escaped = false;
|
|
14106
|
+
} else if (ch === "\\") {
|
|
14107
|
+
escaped = true;
|
|
14108
|
+
} else if (ch === '"') {
|
|
14109
|
+
inString = false;
|
|
14110
|
+
}
|
|
14111
|
+
continue;
|
|
14112
|
+
}
|
|
14113
|
+
if (ch === '"') {
|
|
14114
|
+
inString = true;
|
|
14115
|
+
withoutTrailingCommas += ch;
|
|
14116
|
+
continue;
|
|
14117
|
+
}
|
|
14118
|
+
if (ch === ",") {
|
|
14119
|
+
let j = i + 1;
|
|
14120
|
+
while (j < out.length && /\s/.test(out[j]))
|
|
14121
|
+
j++;
|
|
14122
|
+
if (out[j] === "}" || out[j] === "]")
|
|
14123
|
+
continue;
|
|
14124
|
+
}
|
|
14125
|
+
withoutTrailingCommas += ch;
|
|
14126
|
+
}
|
|
14127
|
+
return withoutTrailingCommas;
|
|
14128
|
+
}
|
|
14129
|
+
function sortJson(value) {
|
|
14130
|
+
if (Array.isArray(value))
|
|
14131
|
+
return value.map(sortJson);
|
|
14132
|
+
if (value && typeof value === "object") {
|
|
14133
|
+
const sorted = {};
|
|
14134
|
+
for (const key of Object.keys(value).sort()) {
|
|
14135
|
+
sorted[key] = sortJson(value[key]);
|
|
14136
|
+
}
|
|
14137
|
+
return sorted;
|
|
14138
|
+
}
|
|
14139
|
+
return value;
|
|
14140
|
+
}
|
|
14141
|
+
function normalizedJsoncSemantics(content) {
|
|
14142
|
+
return JSON.stringify(sortJson(JSON.parse(stripJsoncForParse(content))));
|
|
14143
|
+
}
|
|
14144
|
+
function fileSemanticsMatch(a, b) {
|
|
14145
|
+
try {
|
|
14146
|
+
return normalizedJsoncSemantics(a) === normalizedJsoncSemantics(b);
|
|
14147
|
+
} catch {
|
|
14148
|
+
return a === b;
|
|
14149
|
+
}
|
|
14150
|
+
}
|
|
14151
|
+
function sleepSync(ms) {
|
|
14152
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
14153
|
+
}
|
|
14154
|
+
function acquireConfigMigrationLock(lockDir) {
|
|
14155
|
+
const deadline = Date.now() + 30000;
|
|
14156
|
+
while (true) {
|
|
14157
|
+
try {
|
|
14158
|
+
mkdirSync4(lockDir, { recursive: false });
|
|
14159
|
+
return () => {
|
|
14160
|
+
try {
|
|
14161
|
+
rmSync2(lockDir, { recursive: true, force: true });
|
|
14162
|
+
} catch {}
|
|
14163
|
+
};
|
|
14164
|
+
} catch (err) {
|
|
14165
|
+
const code = err?.code;
|
|
14166
|
+
if (code !== "EEXIST")
|
|
14167
|
+
throw err;
|
|
14168
|
+
try {
|
|
14169
|
+
const ageMs = Date.now() - statSync2(lockDir).mtimeMs;
|
|
14170
|
+
if (ageMs > 60000) {
|
|
14171
|
+
rmSync2(lockDir, { recursive: true, force: true });
|
|
14172
|
+
continue;
|
|
14173
|
+
}
|
|
14174
|
+
} catch {}
|
|
14175
|
+
if (Date.now() >= deadline) {
|
|
14176
|
+
throw new Error(`timed out waiting for config migration lock ${lockDir}`);
|
|
14177
|
+
}
|
|
14178
|
+
sleepSync(25);
|
|
14179
|
+
}
|
|
14180
|
+
}
|
|
14181
|
+
}
|
|
14182
|
+
function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
14183
|
+
mkdirSync4(dirname2(targetPath), { recursive: true });
|
|
14184
|
+
const tmpPath = join6(dirname2(targetPath), `.${basename(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
14185
|
+
let fd = null;
|
|
14186
|
+
try {
|
|
14187
|
+
fd = openSync3(tmpPath, "wx", 384);
|
|
14188
|
+
writeFileSync2(fd, readFileSync4(sourcePath));
|
|
14189
|
+
closeSync3(fd);
|
|
14190
|
+
fd = null;
|
|
14191
|
+
renameSync4(tmpPath, targetPath);
|
|
14192
|
+
} catch (err) {
|
|
14193
|
+
if (fd !== null) {
|
|
14194
|
+
try {
|
|
14195
|
+
closeSync3(fd);
|
|
14196
|
+
} catch {}
|
|
14197
|
+
}
|
|
14198
|
+
try {
|
|
14199
|
+
unlinkSync3(tmpPath);
|
|
14200
|
+
} catch {}
|
|
14201
|
+
throw err;
|
|
14202
|
+
}
|
|
14203
|
+
}
|
|
14204
|
+
function atomicWriteConfigFile(targetPath, content) {
|
|
14205
|
+
mkdirSync4(dirname2(targetPath), { recursive: true });
|
|
14206
|
+
const tmpPath = join6(dirname2(targetPath), `.${basename(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
14207
|
+
let fd = null;
|
|
14208
|
+
try {
|
|
14209
|
+
fd = openSync3(tmpPath, "wx", 384);
|
|
14210
|
+
writeFileSync2(fd, content);
|
|
14211
|
+
closeSync3(fd);
|
|
14212
|
+
fd = null;
|
|
14213
|
+
renameSync4(tmpPath, targetPath);
|
|
14214
|
+
} catch (err) {
|
|
14215
|
+
if (fd !== null) {
|
|
14216
|
+
try {
|
|
14217
|
+
closeSync3(fd);
|
|
14218
|
+
} catch {}
|
|
14219
|
+
}
|
|
14220
|
+
try {
|
|
14221
|
+
unlinkSync3(tmpPath);
|
|
14222
|
+
} catch {}
|
|
14223
|
+
throw err;
|
|
14224
|
+
}
|
|
14225
|
+
}
|
|
14226
|
+
var MOVED_MARKER_SUFFIX = ".MOVED_READPLEASE";
|
|
14227
|
+
function nonClobberingSidecarPath(desiredPath) {
|
|
14228
|
+
if (!existsSync5(desiredPath))
|
|
14229
|
+
return desiredPath;
|
|
14230
|
+
for (let index = 1;index < Number.MAX_SAFE_INTEGER; index++) {
|
|
14231
|
+
const candidate = `${desiredPath}.${index}`;
|
|
14232
|
+
if (!existsSync5(candidate))
|
|
14233
|
+
return candidate;
|
|
14234
|
+
}
|
|
14235
|
+
throw new Error(`could not find available preservation sidecar path for ${desiredPath}`);
|
|
14236
|
+
}
|
|
14237
|
+
function movedMarkerContent(targetPath, originalName, originalContent) {
|
|
14238
|
+
const header = [
|
|
14239
|
+
"// AFT configuration moved.",
|
|
14240
|
+
"//",
|
|
14241
|
+
"// AFT now reads its configuration from one shared CortexKit location",
|
|
14242
|
+
"// instead of a per-agent path. The settings that were in this file have",
|
|
14243
|
+
"// been moved to:",
|
|
14244
|
+
"//",
|
|
14245
|
+
`// ${targetPath}`,
|
|
14246
|
+
"//",
|
|
14247
|
+
"// Edit that file to change AFT settings. This location is no longer read",
|
|
14248
|
+
"// by AFT.",
|
|
14249
|
+
"//",
|
|
14250
|
+
`// To undo, rename this file back to "${originalName}" (and remove the`,
|
|
14251
|
+
"// CortexKit copy above if you want this location to take precedence).",
|
|
14252
|
+
"//",
|
|
14253
|
+
"// Your original settings are preserved below for reference.",
|
|
14254
|
+
"",
|
|
14255
|
+
""
|
|
14256
|
+
].join(`
|
|
14257
|
+
`);
|
|
14258
|
+
return `${header}${originalContent}`;
|
|
14259
|
+
}
|
|
14260
|
+
function markLegacySourcesMovedAside(sources, targetPath, logger) {
|
|
14261
|
+
const warnings = [];
|
|
14262
|
+
const info = logger?.info ?? logger?.log;
|
|
14263
|
+
for (const source of sources) {
|
|
14264
|
+
const desiredMarkerPath = `${source.path}${MOVED_MARKER_SUFFIX}`;
|
|
14265
|
+
const markerPath = nonClobberingSidecarPath(desiredMarkerPath);
|
|
14266
|
+
try {
|
|
14267
|
+
const original = readFileSync4(source.path, "utf-8");
|
|
14268
|
+
if (markerPath !== desiredMarkerPath) {
|
|
14269
|
+
logger?.warn?.(`Preserving existing legacy AFT marker ${desiredMarkerPath}; writing new marker to ${markerPath}`);
|
|
14270
|
+
}
|
|
14271
|
+
atomicWriteConfigFile(markerPath, movedMarkerContent(targetPath, basename(source.path), original));
|
|
14272
|
+
unlinkSync3(source.path);
|
|
14273
|
+
info?.(`Moved legacy AFT config ${source.path} aside to ${markerPath}; AFT now reads ${targetPath}`);
|
|
14274
|
+
} catch (err) {
|
|
14275
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
14276
|
+
warnings.push(`AFT could not move legacy config ${source.path} aside (${msg}); it is now stale and ignored. Delete it manually — AFT reads ${targetPath}.`);
|
|
14277
|
+
logger?.warn?.(`Could not move legacy AFT config ${source.path} aside (${msg}); AFT reads ${targetPath}`);
|
|
14278
|
+
}
|
|
14279
|
+
}
|
|
14280
|
+
return warnings;
|
|
14281
|
+
}
|
|
14282
|
+
var PRESERVED_OLD_SUFFIX = "_OLD";
|
|
14283
|
+
function preservedOldContent(losingHarness, winningHarness, targetPath, originalContent) {
|
|
14284
|
+
const winnerLine = winningHarness ? `// configs differed, so ${winningHarness}'s config won (first harness to run the` : "// configs differed, so the config that was migrated first won and is the";
|
|
14285
|
+
const header = [
|
|
14286
|
+
`// AFT config from ${losingHarness} — preserved, NOT read.`,
|
|
14287
|
+
"//",
|
|
14288
|
+
"// AFT now reads one shared config for all harnesses. Your OpenCode and Pi",
|
|
14289
|
+
winnerLine,
|
|
14290
|
+
winningHarness ? "// migration) and is now the active config at:" : "// active config at:",
|
|
14291
|
+
"//",
|
|
14292
|
+
`// ${targetPath}`,
|
|
14293
|
+
"//",
|
|
14294
|
+
`// This file holds ${losingHarness}'s previous settings. Merge anything you`,
|
|
14295
|
+
"// want to keep into the active config above, then delete this file. AFT does",
|
|
14296
|
+
"// not read this path.",
|
|
14297
|
+
"",
|
|
14298
|
+
""
|
|
14299
|
+
].join(`
|
|
14300
|
+
`);
|
|
14301
|
+
return `${header}${originalContent}`;
|
|
14302
|
+
}
|
|
14303
|
+
function preserveDifferingSourceAsOld(source, winningHarness, targetPath, logger) {
|
|
14304
|
+
const losingHarness = source.harness ?? "pi";
|
|
14305
|
+
const desiredOldPath = `${targetPath}.${losingHarness}${PRESERVED_OLD_SUFFIX}`;
|
|
14306
|
+
const oldPath = nonClobberingSidecarPath(desiredOldPath);
|
|
14307
|
+
try {
|
|
14308
|
+
if (oldPath !== desiredOldPath) {
|
|
14309
|
+
logger?.warn?.(`Preserving existing ${losingHarness} config sidecar ${desiredOldPath}; writing new preserved config to ${oldPath}`);
|
|
14310
|
+
}
|
|
14311
|
+
atomicWriteConfigFile(oldPath, preservedOldContent(losingHarness, winningHarness, targetPath, source.content));
|
|
14312
|
+
} catch (err) {
|
|
14313
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
14314
|
+
logger?.warn?.(`Could not preserve ${losingHarness} config as ${oldPath} (${msg})`);
|
|
14315
|
+
}
|
|
14316
|
+
const usingDesc = winningHarness ? `${winningHarness}'s config` : "the existing shared config";
|
|
14317
|
+
return `AFT found different OpenCode and Pi configs during config unification. ` + `Using ${usingDesc} at ${targetPath}; preserved ${losingHarness}'s previous ` + `config at ${oldPath} — merge any settings you want to keep, then delete it.`;
|
|
14318
|
+
}
|
|
14319
|
+
function visibleConfigMigrationWarning(scope, targetPath, paths, reason) {
|
|
14320
|
+
const uniquePaths = [...new Set([targetPath, ...paths])];
|
|
14321
|
+
return `AFT ${scope} config migration refused: ${reason}. ` + `Legacy and CortexKit config paths collapse to one file, but AFT will not overwrite or merge them automatically. ` + `Please consolidate manually into ${targetPath}. Paths: ${uniquePaths.join(" ; ")}`;
|
|
14322
|
+
}
|
|
14323
|
+
function migrateAftConfigFile(opts) {
|
|
14324
|
+
const warnings = [];
|
|
14325
|
+
const resolvedTarget = resolve4(opts.targetPath);
|
|
14326
|
+
const existingSources = opts.legacySources.filter((source) => existsSync5(source.path) && resolve4(source.path) !== resolvedTarget);
|
|
14327
|
+
const info = opts.logger?.info ?? opts.logger?.log;
|
|
14328
|
+
if (existingSources.length === 0) {
|
|
14329
|
+
return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
|
|
14330
|
+
}
|
|
14331
|
+
mkdirSync4(dirname2(opts.targetPath), { recursive: true });
|
|
14332
|
+
const release = acquireConfigMigrationLock(`${opts.targetPath}.lock`);
|
|
14333
|
+
try {
|
|
14334
|
+
const sources = existingSources.map((source) => ({
|
|
14335
|
+
...source,
|
|
14336
|
+
content: readFileSync4(source.path, "utf-8")
|
|
14337
|
+
}));
|
|
14338
|
+
if (existsSync5(opts.targetPath)) {
|
|
14339
|
+
const targetContent = readFileSync4(opts.targetPath, "utf-8");
|
|
14340
|
+
for (const source of sources) {
|
|
14341
|
+
if (fileSemanticsMatch(source.content, targetContent))
|
|
14342
|
+
continue;
|
|
14343
|
+
warnings.push(preserveDifferingSourceAsOld(source, undefined, opts.targetPath, opts.logger));
|
|
14344
|
+
}
|
|
14345
|
+
info?.(`AFT ${opts.scope} config already present at ${opts.targetPath}; reconciled ${sources.length} legacy source(s)`);
|
|
14346
|
+
warnings.push(...markLegacySourcesMovedAside(sources, opts.targetPath, opts.logger));
|
|
14347
|
+
return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
|
|
14348
|
+
}
|
|
14349
|
+
const winner = (opts.operatingHarness ? sources.find((source) => source.harness === opts.operatingHarness) : undefined) ?? sources[0];
|
|
14350
|
+
atomicCopyConfigFile(winner.path, opts.targetPath);
|
|
14351
|
+
info?.(`Migrated AFT ${opts.scope} config from ${winner.path} to ${opts.targetPath}`);
|
|
14352
|
+
for (const source of sources) {
|
|
14353
|
+
if (source.path === winner.path)
|
|
14354
|
+
continue;
|
|
14355
|
+
if (fileSemanticsMatch(source.content, winner.content))
|
|
14356
|
+
continue;
|
|
14357
|
+
warnings.push(preserveDifferingSourceAsOld(source, winner.harness, opts.targetPath, opts.logger));
|
|
14358
|
+
}
|
|
14359
|
+
warnings.push(...markLegacySourcesMovedAside(sources, opts.targetPath, opts.logger));
|
|
14360
|
+
return {
|
|
14361
|
+
migrated: true,
|
|
14362
|
+
conflict: false,
|
|
14363
|
+
sourcePath: winner.path,
|
|
14364
|
+
targetPath: opts.targetPath,
|
|
14365
|
+
warnings
|
|
14366
|
+
};
|
|
14367
|
+
} catch (err) {
|
|
14368
|
+
const message = visibleConfigMigrationWarning(opts.scope, opts.targetPath, existingSources.map((source) => source.path), `migration failed (${err instanceof Error ? err.message : String(err)})`);
|
|
14369
|
+
warnings.push(message);
|
|
14370
|
+
opts.logger?.warn?.(message);
|
|
14371
|
+
return { migrated: false, conflict: true, targetPath: opts.targetPath, warnings };
|
|
14372
|
+
} finally {
|
|
14373
|
+
release();
|
|
14374
|
+
}
|
|
14375
|
+
}
|
|
13867
14376
|
function tail(value) {
|
|
13868
14377
|
if (!value)
|
|
13869
14378
|
return "";
|
|
@@ -13891,11 +14400,11 @@ async function ensureStorageMigrated(opts) {
|
|
|
13891
14400
|
const newRoot = resolveCortexKitStorageRoot();
|
|
13892
14401
|
const targetMarker = resolveHarnessStoragePath(newRoot, opts.harness, TARGET_MARKER);
|
|
13893
14402
|
const info = opts.logger?.info ?? opts.logger?.log;
|
|
13894
|
-
if (
|
|
14403
|
+
if (existsSync5(targetMarker)) {
|
|
13895
14404
|
info?.(`AFT storage already migrated for ${opts.harness}; using ${newRoot}`);
|
|
13896
14405
|
return;
|
|
13897
14406
|
}
|
|
13898
|
-
if (!
|
|
14407
|
+
if (!existsSync5(legacyRoot)) {
|
|
13899
14408
|
info?.(`AFT storage migration skipped for ${opts.harness}: no legacy data at ${legacyRoot}; ` + `using ${newRoot} for fresh install`);
|
|
13900
14409
|
return;
|
|
13901
14410
|
}
|
|
@@ -13943,14 +14452,14 @@ async function ensureStorageMigrated(opts) {
|
|
|
13943
14452
|
throw new Error(`AFT storage migration failed (${detail}). ` + `Harness: ${opts.harness}. Legacy: ${legacyRoot}. Target: ${newRoot}. ` + `See log: ${logPath}. ` + `Plugin load aborted to prevent legacy/new state divergence.` + (stderrTail ? ` Stderr tail: ${stderrTail}` : "") + (stdoutTail ? ` Stdout tail: ${stdoutTail}` : ""));
|
|
13944
14453
|
}
|
|
13945
14454
|
// ../aft-bridge/dist/npm-resolver.js
|
|
13946
|
-
import { readdirSync, statSync as
|
|
13947
|
-
import { homedir as
|
|
13948
|
-
import { delimiter, dirname as dirname3, isAbsolute as
|
|
14455
|
+
import { readdirSync, statSync as statSync3 } from "node:fs";
|
|
14456
|
+
import { homedir as homedir8 } from "node:os";
|
|
14457
|
+
import { delimiter, dirname as dirname3, isAbsolute as isAbsolute3, join as join7 } from "node:path";
|
|
13949
14458
|
function defaultDeps() {
|
|
13950
14459
|
return {
|
|
13951
14460
|
platform: process.platform,
|
|
13952
14461
|
env: process.env,
|
|
13953
|
-
home:
|
|
14462
|
+
home: homedir8(),
|
|
13954
14463
|
execPath: process.execPath
|
|
13955
14464
|
};
|
|
13956
14465
|
}
|
|
@@ -13959,7 +14468,7 @@ function npmBinaryName(platform) {
|
|
|
13959
14468
|
}
|
|
13960
14469
|
function isFile(p) {
|
|
13961
14470
|
try {
|
|
13962
|
-
return
|
|
14471
|
+
return statSync3(p).isFile();
|
|
13963
14472
|
} catch {
|
|
13964
14473
|
return false;
|
|
13965
14474
|
}
|
|
@@ -13969,7 +14478,7 @@ function npmFromPath(deps) {
|
|
|
13969
14478
|
const raw = deps.env.PATH ?? deps.env.Path ?? "";
|
|
13970
14479
|
for (const entry of raw.split(delimiter)) {
|
|
13971
14480
|
const dir = entry.trim().replace(/^"|"$/g, "");
|
|
13972
|
-
if (!dir || !
|
|
14481
|
+
if (!dir || !isAbsolute3(dir))
|
|
13973
14482
|
continue;
|
|
13974
14483
|
if (isFile(join7(dir, name)))
|
|
13975
14484
|
return dir;
|
|
@@ -14059,8 +14568,8 @@ function npmSpawnEnv(resolved, baseEnv = process.env) {
|
|
|
14059
14568
|
// ../aft-bridge/dist/onnx-runtime.js
|
|
14060
14569
|
import { execFileSync } from "node:child_process";
|
|
14061
14570
|
import { createHash as createHash2 } from "node:crypto";
|
|
14062
|
-
import { chmodSync as chmodSync3, closeSync as
|
|
14063
|
-
import { basename, dirname as dirname4, isAbsolute as
|
|
14571
|
+
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 readFileSync5, readlinkSync, realpathSync, rmSync as rmSync3, statSync as statSync4, symlinkSync, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
14572
|
+
import { basename as basename2, dirname as dirname4, isAbsolute as isAbsolute4, join as join8, relative as relative2, resolve as resolve5, win32 } from "node:path";
|
|
14064
14573
|
import { Readable as Readable2 } from "node:stream";
|
|
14065
14574
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
14066
14575
|
var ORT_VERSION = "1.24.4";
|
|
@@ -14127,7 +14636,7 @@ async function ensureOnnxRuntime(storageDir) {
|
|
|
14127
14636
|
const libName = info?.libName ?? "libonnxruntime.dylib";
|
|
14128
14637
|
const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
|
|
14129
14638
|
const libPath = join8(resolvedOrtDir, libName);
|
|
14130
|
-
if (
|
|
14639
|
+
if (existsSync6(libPath)) {
|
|
14131
14640
|
const meta = readOnnxInstalledMeta(ortVersionDir);
|
|
14132
14641
|
if (meta?.sha256) {
|
|
14133
14642
|
try {
|
|
@@ -14189,7 +14698,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
14189
14698
|
abandoned = true;
|
|
14190
14699
|
} else {
|
|
14191
14700
|
try {
|
|
14192
|
-
const ageMs = Date.now() -
|
|
14701
|
+
const ageMs = Date.now() - statSync4(stagingDir).mtimeMs;
|
|
14193
14702
|
abandoned = ageMs > STALE_LOCK_MS;
|
|
14194
14703
|
} catch {
|
|
14195
14704
|
abandoned = true;
|
|
@@ -14204,7 +14713,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
14204
14713
|
if (abandoned) {
|
|
14205
14714
|
log(`[onnx] removing abandoned staging dir ${stagingDir}`);
|
|
14206
14715
|
try {
|
|
14207
|
-
|
|
14716
|
+
rmSync3(stagingDir, { recursive: true, force: true });
|
|
14208
14717
|
} catch (err) {
|
|
14209
14718
|
warn(`[onnx] failed to remove ${stagingDir}: ${err}`);
|
|
14210
14719
|
}
|
|
@@ -14214,9 +14723,9 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
14214
14723
|
}
|
|
14215
14724
|
function cleanupIncompleteTargetIfUnowned(ortDir) {
|
|
14216
14725
|
try {
|
|
14217
|
-
if (
|
|
14726
|
+
if (existsSync6(ortDir) && !existsSync6(join8(ortDir, ONNX_INSTALLED_META_FILE))) {
|
|
14218
14727
|
log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
|
|
14219
|
-
|
|
14728
|
+
rmSync3(ortDir, { recursive: true, force: true });
|
|
14220
14729
|
}
|
|
14221
14730
|
} catch (err) {
|
|
14222
14731
|
warn(`[onnx] failed to sweep ${ortDir}: ${err}`);
|
|
@@ -14226,7 +14735,7 @@ var REQUIRED_ORT_MAJOR = 1;
|
|
|
14226
14735
|
var REQUIRED_ORT_MIN_MINOR = 20;
|
|
14227
14736
|
var INVALID_ORT_VERSION = "<invalid>";
|
|
14228
14737
|
function parseOnnxVersionFromPath(value) {
|
|
14229
|
-
const name =
|
|
14738
|
+
const name = basename2(value);
|
|
14230
14739
|
const semverish = name.match(/(?:^|[._-])(\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?)(?:\.(?:dylib|dll))?$/);
|
|
14231
14740
|
if (semverish)
|
|
14232
14741
|
return semverish[1].split(/[-+]/, 1)[0];
|
|
@@ -14243,7 +14752,7 @@ function parseOnnxVersionFromDirectoryPath(value) {
|
|
|
14243
14752
|
}
|
|
14244
14753
|
function isPathInsideRoot(root, candidate) {
|
|
14245
14754
|
const rel = relative2(root, candidate);
|
|
14246
|
-
return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !
|
|
14755
|
+
return rel === "" || !rel.startsWith("../") && !rel.startsWith("..\\") && rel !== ".." && !isAbsolute4(rel) && !win32.isAbsolute(rel);
|
|
14247
14756
|
}
|
|
14248
14757
|
function detectOnnxVersion(libDir, libName) {
|
|
14249
14758
|
try {
|
|
@@ -14259,7 +14768,7 @@ function detectOnnxVersion(libDir, libName) {
|
|
|
14259
14768
|
return version;
|
|
14260
14769
|
}
|
|
14261
14770
|
const base = join8(libDir, libName);
|
|
14262
|
-
if (
|
|
14771
|
+
if (existsSync6(base)) {
|
|
14263
14772
|
try {
|
|
14264
14773
|
const real = realpathSync(base);
|
|
14265
14774
|
const version = parseOnnxVersionFromPath(real) ?? parseOnnxVersionFromDirectoryPath(real);
|
|
@@ -14294,7 +14803,7 @@ function pathEntriesForPlatform() {
|
|
|
14294
14803
|
return pathEnvValue().split(delimiter2).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
|
|
14295
14804
|
if (!entry || entry === "." || entry.includes("\x00"))
|
|
14296
14805
|
return false;
|
|
14297
|
-
return
|
|
14806
|
+
return isAbsolute4(entry) || win32.isAbsolute(entry);
|
|
14298
14807
|
});
|
|
14299
14808
|
}
|
|
14300
14809
|
function directoryContainsLibrary(dir, libName) {
|
|
@@ -14310,10 +14819,10 @@ function directoryContainsLibrary(dir, libName) {
|
|
|
14310
14819
|
}
|
|
14311
14820
|
}
|
|
14312
14821
|
function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
|
|
14313
|
-
if (
|
|
14822
|
+
if (existsSync6(join8(ortVersionDir, libName)))
|
|
14314
14823
|
return ortVersionDir;
|
|
14315
14824
|
const libSubdir = join8(ortVersionDir, "lib");
|
|
14316
|
-
if (
|
|
14825
|
+
if (existsSync6(join8(libSubdir, libName)))
|
|
14317
14826
|
return libSubdir;
|
|
14318
14827
|
return ortVersionDir;
|
|
14319
14828
|
}
|
|
@@ -14334,7 +14843,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
14334
14843
|
if (!userProfile)
|
|
14335
14844
|
return nugetPaths;
|
|
14336
14845
|
const nugetPackageDir = join8(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
14337
|
-
if (!
|
|
14846
|
+
if (!existsSync6(nugetPackageDir))
|
|
14338
14847
|
return nugetPaths;
|
|
14339
14848
|
try {
|
|
14340
14849
|
for (const entry of readdirSync2(nugetPackageDir, { withFileTypes: true })) {
|
|
@@ -14354,7 +14863,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
14354
14863
|
const normalizeCase = process.platform === "win32" || process.platform === "darwin";
|
|
14355
14864
|
const seen = new Set;
|
|
14356
14865
|
const uniquePaths = searchPaths.filter((p) => {
|
|
14357
|
-
let key =
|
|
14866
|
+
let key = resolve5(p).replace(/[/\\]+$/, "");
|
|
14358
14867
|
if (normalizeCase)
|
|
14359
14868
|
key = key.toLowerCase();
|
|
14360
14869
|
if (seen.has(key))
|
|
@@ -14368,7 +14877,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
14368
14877
|
if (process.platform === "win32") {
|
|
14369
14878
|
if (!directoryContainsLibrary(dir, libName))
|
|
14370
14879
|
continue;
|
|
14371
|
-
} else if (!
|
|
14880
|
+
} else if (!existsSync6(libPath)) {
|
|
14372
14881
|
continue;
|
|
14373
14882
|
}
|
|
14374
14883
|
const version = detectOnnxVersion(dir, libName);
|
|
@@ -14417,7 +14926,7 @@ async function downloadFileWithCap(url, destPath) {
|
|
|
14417
14926
|
await pipeline2(nodeStream, createWriteStream2(destPath), { signal: controller.signal });
|
|
14418
14927
|
} catch (err) {
|
|
14419
14928
|
try {
|
|
14420
|
-
|
|
14929
|
+
unlinkSync4(destPath);
|
|
14421
14930
|
} catch {}
|
|
14422
14931
|
throw err;
|
|
14423
14932
|
} finally {
|
|
@@ -14434,15 +14943,15 @@ function validateExtractedTree(stagingRoot) {
|
|
|
14434
14943
|
const lst = lstatSync(fullPath);
|
|
14435
14944
|
if (lst.isSymbolicLink()) {
|
|
14436
14945
|
const linkTarget = readlinkSync(fullPath);
|
|
14437
|
-
const resolvedTarget =
|
|
14946
|
+
const resolvedTarget = resolve5(dirname4(fullPath), linkTarget);
|
|
14438
14947
|
const rel2 = relative2(realRoot, resolvedTarget);
|
|
14439
|
-
if (rel2.startsWith("..") ||
|
|
14948
|
+
if (rel2.startsWith("..") || isAbsolute4(rel2) || win32.isAbsolute(rel2)) {
|
|
14440
14949
|
throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
|
|
14441
14950
|
}
|
|
14442
14951
|
continue;
|
|
14443
14952
|
}
|
|
14444
14953
|
const rel = relative2(realRoot, fullPath);
|
|
14445
|
-
if (rel.startsWith("..") ||
|
|
14954
|
+
if (rel.startsWith("..") || isAbsolute4(rel) || win32.isAbsolute(rel)) {
|
|
14446
14955
|
throw new Error(`extracted entry ${fullPath} escapes staging root`);
|
|
14447
14956
|
}
|
|
14448
14957
|
if (lst.isDirectory()) {
|
|
@@ -14478,11 +14987,11 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14478
14987
|
await extractZipArchive(archivePath, tmpDir);
|
|
14479
14988
|
}
|
|
14480
14989
|
try {
|
|
14481
|
-
|
|
14990
|
+
unlinkSync4(archivePath);
|
|
14482
14991
|
} catch {}
|
|
14483
14992
|
validateExtractedTree(tmpDir);
|
|
14484
14993
|
const extractedDir = join8(tmpDir, info.assetName, "lib");
|
|
14485
|
-
if (!
|
|
14994
|
+
if (!existsSync6(extractedDir)) {
|
|
14486
14995
|
throw new Error(`Expected directory not found: ${extractedDir}`);
|
|
14487
14996
|
}
|
|
14488
14997
|
mkdirSync5(targetDir, { recursive: true });
|
|
@@ -14513,16 +15022,16 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
14513
15022
|
warn(`Could not hash newly-installed ONNX library at ${libPath}: ${err}`);
|
|
14514
15023
|
}
|
|
14515
15024
|
writeOnnxInstalledMeta(targetDir, ORT_VERSION, libHash, archiveSha256);
|
|
14516
|
-
|
|
15025
|
+
rmSync3(tmpDir, { recursive: true, force: true });
|
|
14517
15026
|
log(`ONNX Runtime v${ORT_VERSION} installed to ${targetDir}`);
|
|
14518
15027
|
return targetDir;
|
|
14519
15028
|
} catch (err) {
|
|
14520
15029
|
error(`Failed to download ONNX Runtime: ${err}`);
|
|
14521
15030
|
try {
|
|
14522
|
-
|
|
15031
|
+
rmSync3(tmpDir, { recursive: true, force: true });
|
|
14523
15032
|
} catch {}
|
|
14524
15033
|
try {
|
|
14525
|
-
|
|
15034
|
+
rmSync3(targetDir, { recursive: true, force: true });
|
|
14526
15035
|
} catch {}
|
|
14527
15036
|
return null;
|
|
14528
15037
|
}
|
|
@@ -14539,7 +15048,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
14539
15048
|
}
|
|
14540
15049
|
} catch (copyErr) {
|
|
14541
15050
|
if (requiredLibs.has(libFile)) {
|
|
14542
|
-
|
|
15051
|
+
rmSync3(targetDir, { recursive: true, force: true });
|
|
14543
15052
|
throw copyErr;
|
|
14544
15053
|
}
|
|
14545
15054
|
log(`ORT extract: failed to copy optional ${libFile}: ${copyErr}`);
|
|
@@ -14549,14 +15058,14 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
14549
15058
|
for (const link of symlinks) {
|
|
14550
15059
|
const dst = join8(targetDir, link.name);
|
|
14551
15060
|
try {
|
|
14552
|
-
|
|
15061
|
+
unlinkSync4(dst);
|
|
14553
15062
|
} catch {}
|
|
14554
15063
|
const dstForContainment = join8(targetRoot, link.name);
|
|
14555
|
-
const resolvedTarget =
|
|
15064
|
+
const resolvedTarget = resolve5(dirname4(dstForContainment), link.target);
|
|
14556
15065
|
if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
|
|
14557
15066
|
const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
|
|
14558
15067
|
if (requiredLibs.has(link.name)) {
|
|
14559
|
-
|
|
15068
|
+
rmSync3(targetDir, { recursive: true, force: true });
|
|
14560
15069
|
throw new Error(message);
|
|
14561
15070
|
}
|
|
14562
15071
|
log(`ORT extract: skipping optional symlink ${link.name}: ${message}`);
|
|
@@ -14566,15 +15075,15 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
14566
15075
|
symlinkSync(link.target, dst);
|
|
14567
15076
|
} catch (symlinkErr) {
|
|
14568
15077
|
if (requiredLibs.has(link.name)) {
|
|
14569
|
-
|
|
15078
|
+
rmSync3(targetDir, { recursive: true, force: true });
|
|
14570
15079
|
throw symlinkErr;
|
|
14571
15080
|
}
|
|
14572
15081
|
log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
|
|
14573
15082
|
}
|
|
14574
15083
|
}
|
|
14575
15084
|
const requiredPath = join8(targetDir, info.libName);
|
|
14576
|
-
if (!
|
|
14577
|
-
|
|
15085
|
+
if (!existsSync6(requiredPath)) {
|
|
15086
|
+
rmSync3(targetDir, { recursive: true, force: true });
|
|
14578
15087
|
throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
|
|
14579
15088
|
}
|
|
14580
15089
|
}
|
|
@@ -14599,7 +15108,7 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
14599
15108
|
...sha256 ? { sha256 } : {},
|
|
14600
15109
|
archiveSha256
|
|
14601
15110
|
};
|
|
14602
|
-
|
|
15111
|
+
writeFileSync3(join8(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
|
|
14603
15112
|
} catch (err) {
|
|
14604
15113
|
log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
|
|
14605
15114
|
}
|
|
@@ -14607,9 +15116,9 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
14607
15116
|
function readOnnxInstalledMeta(installDir) {
|
|
14608
15117
|
const path2 = join8(installDir, ONNX_INSTALLED_META_FILE);
|
|
14609
15118
|
try {
|
|
14610
|
-
if (!
|
|
15119
|
+
if (!statSync4(path2).isFile())
|
|
14611
15120
|
return null;
|
|
14612
|
-
const raw =
|
|
15121
|
+
const raw = readFileSync5(path2, "utf8");
|
|
14613
15122
|
const parsed = JSON.parse(raw);
|
|
14614
15123
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
14615
15124
|
return null;
|
|
@@ -14625,680 +15134,166 @@ function readOnnxInstalledMeta(installDir) {
|
|
|
14625
15134
|
}
|
|
14626
15135
|
function sha256File(path2) {
|
|
14627
15136
|
const hash = createHash2("sha256");
|
|
14628
|
-
hash.update(
|
|
15137
|
+
hash.update(readFileSync5(path2));
|
|
14629
15138
|
return hash.digest("hex");
|
|
14630
15139
|
}
|
|
14631
15140
|
function acquireLock(lockPath) {
|
|
14632
15141
|
const tryClaim = () => {
|
|
14633
15142
|
try {
|
|
14634
|
-
const fd =
|
|
15143
|
+
const fd = openSync4(lockPath, "wx");
|
|
14635
15144
|
try {
|
|
14636
|
-
|
|
15145
|
+
writeFileSync3(fd, `${process.pid}
|
|
14637
15146
|
${new Date().toISOString()}
|
|
14638
15147
|
`);
|
|
14639
15148
|
} finally {
|
|
14640
|
-
|
|
15149
|
+
closeSync4(fd);
|
|
14641
15150
|
}
|
|
14642
15151
|
return true;
|
|
14643
15152
|
} catch (err) {
|
|
14644
15153
|
const code = err.code;
|
|
14645
15154
|
if (code === "EEXIST")
|
|
14646
|
-
return false;
|
|
14647
|
-
warn(`[onnx] unexpected error acquiring lock ${lockPath}: ${err}`);
|
|
14648
|
-
return false;
|
|
14649
|
-
}
|
|
14650
|
-
};
|
|
14651
|
-
if (tryClaim())
|
|
14652
|
-
return true;
|
|
14653
|
-
let owningPid = null;
|
|
14654
|
-
let lockMtimeMs = 0;
|
|
14655
|
-
try {
|
|
14656
|
-
const raw = readFileSync3(lockPath, "utf8");
|
|
14657
|
-
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
14658
|
-
const parsed = Number.parseInt(firstLine, 10);
|
|
14659
|
-
if (Number.isFinite(parsed) && parsed > 0)
|
|
14660
|
-
owningPid = parsed;
|
|
14661
|
-
lockMtimeMs = statSync3(lockPath).mtimeMs;
|
|
14662
|
-
} catch {
|
|
14663
|
-
return tryClaim();
|
|
14664
|
-
}
|
|
14665
|
-
const age = Date.now() - lockMtimeMs;
|
|
14666
|
-
const ageWithinFresh = Math.abs(age) < STALE_LOCK_MS;
|
|
14667
|
-
const ownerAlive = owningPid !== null && isProcessAlive(owningPid);
|
|
14668
|
-
if (ownerAlive && ageWithinFresh) {
|
|
14669
|
-
return false;
|
|
14670
|
-
}
|
|
14671
|
-
log(`[onnx] reclaiming install lock (owner_pid=${owningPid ?? "unknown"}, alive=${ownerAlive}, age_ms=${age})`);
|
|
14672
|
-
try {
|
|
14673
|
-
unlinkSync3(lockPath);
|
|
14674
|
-
} catch {}
|
|
14675
|
-
return tryClaim();
|
|
14676
|
-
}
|
|
14677
|
-
function releaseLock(lockPath) {
|
|
14678
|
-
try {
|
|
14679
|
-
let owningPid = null;
|
|
14680
|
-
try {
|
|
14681
|
-
const raw = readFileSync3(lockPath, "utf8");
|
|
14682
|
-
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
14683
|
-
const parsed = Number.parseInt(firstLine, 10);
|
|
14684
|
-
if (Number.isFinite(parsed) && parsed > 0)
|
|
14685
|
-
owningPid = parsed;
|
|
14686
|
-
} catch (readErr) {
|
|
14687
|
-
const code = readErr.code;
|
|
14688
|
-
if (code === "ENOENT")
|
|
14689
|
-
return;
|
|
14690
|
-
warn(`[onnx] could not read lock ${lockPath} during release: ${readErr}`);
|
|
14691
|
-
return;
|
|
14692
|
-
}
|
|
14693
|
-
if (owningPid !== process.pid) {
|
|
14694
|
-
log(`[onnx] not releasing lock ${lockPath}: owned by pid ${owningPid ?? "unknown"} (we are ${process.pid})`);
|
|
14695
|
-
return;
|
|
14696
|
-
}
|
|
14697
|
-
try {
|
|
14698
|
-
unlinkSync3(lockPath);
|
|
14699
|
-
} catch (unlinkErr) {
|
|
14700
|
-
const code = unlinkErr.code;
|
|
14701
|
-
if (code !== "ENOENT") {
|
|
14702
|
-
warn(`[onnx] failed to release lock ${lockPath}: ${unlinkErr}`);
|
|
14703
|
-
}
|
|
14704
|
-
}
|
|
14705
|
-
} catch (err) {
|
|
14706
|
-
warn(`[onnx] unexpected error releasing lock ${lockPath}: ${err}`);
|
|
14707
|
-
}
|
|
14708
|
-
}
|
|
14709
|
-
function tasklistPidFromCsvLine(line) {
|
|
14710
|
-
const quoted = line.match(/"([^"]*)"/g);
|
|
14711
|
-
if (quoted && quoted.length >= 2)
|
|
14712
|
-
return quoted[1].slice(1, -1);
|
|
14713
|
-
const cells = line.split(",").map((cell) => cell.trim().replace(/^"|"$/g, ""));
|
|
14714
|
-
return cells[1] ?? null;
|
|
14715
|
-
}
|
|
14716
|
-
function isWindowsProcessAlive(pid) {
|
|
14717
|
-
if (!Number.isInteger(pid) || pid <= 0)
|
|
14718
|
-
return false;
|
|
14719
|
-
try {
|
|
14720
|
-
const output = execFileSync("tasklist.exe", ["/FI", `PID eq ${pid}`, "/FO", "CSV", "/NH"], {
|
|
14721
|
-
encoding: "utf8",
|
|
14722
|
-
timeout: 2000,
|
|
14723
|
-
windowsHide: true
|
|
14724
|
-
});
|
|
14725
|
-
const expected = String(pid);
|
|
14726
|
-
return output.split(/\r?\n/).some((line) => tasklistPidFromCsvLine(line) === expected);
|
|
14727
|
-
} catch {
|
|
14728
|
-
return false;
|
|
14729
|
-
}
|
|
14730
|
-
}
|
|
14731
|
-
function isProcessAlive(pid) {
|
|
14732
|
-
if (process.platform === "win32")
|
|
14733
|
-
return isWindowsProcessAlive(pid);
|
|
14734
|
-
try {
|
|
14735
|
-
process.kill(pid, 0);
|
|
14736
|
-
return true;
|
|
14737
|
-
} catch (err) {
|
|
14738
|
-
const code = err.code;
|
|
14739
|
-
if (code === "ESRCH")
|
|
14740
|
-
return false;
|
|
14741
|
-
return true;
|
|
14742
|
-
}
|
|
14743
|
-
}
|
|
14744
|
-
// ../aft-bridge/dist/pipe-strip.js
|
|
14745
|
-
var NOISE_FILTERS = new Set([
|
|
14746
|
-
"grep",
|
|
14747
|
-
"rg",
|
|
14748
|
-
"head",
|
|
14749
|
-
"tail",
|
|
14750
|
-
"cat",
|
|
14751
|
-
"less",
|
|
14752
|
-
"more",
|
|
14753
|
-
"sed",
|
|
14754
|
-
"awk",
|
|
14755
|
-
"cut",
|
|
14756
|
-
"sort",
|
|
14757
|
-
"uniq",
|
|
14758
|
-
"tr",
|
|
14759
|
-
"column",
|
|
14760
|
-
"fold"
|
|
14761
|
-
]);
|
|
14762
|
-
var GREP_GUARD_FLAGS = new Set([
|
|
14763
|
-
"c",
|
|
14764
|
-
"count",
|
|
14765
|
-
"q",
|
|
14766
|
-
"quiet",
|
|
14767
|
-
"o",
|
|
14768
|
-
"only-matching",
|
|
14769
|
-
"l",
|
|
14770
|
-
"files-with-matches"
|
|
14771
|
-
]);
|
|
14772
|
-
function maybeStripCompressorPipe(command, compressionEnabled) {
|
|
14773
|
-
if (!compressionEnabled)
|
|
14774
|
-
return { command, stripped: false };
|
|
14775
|
-
const chain = splitTopLevelCommandChain(command);
|
|
14776
|
-
if (chain === null)
|
|
14777
|
-
return { command, stripped: false };
|
|
14778
|
-
let stripped = false;
|
|
14779
|
-
const droppedFilterChains = [];
|
|
14780
|
-
const rebuilt = chain.map(({ segment, separator }) => {
|
|
14781
|
-
const result = stripSinglePipelineSegment(segment);
|
|
14782
|
-
if (result.stripped) {
|
|
14783
|
-
stripped = true;
|
|
14784
|
-
droppedFilterChains.push(result.filters);
|
|
14785
|
-
}
|
|
14786
|
-
return `${result.segment}${separator}`;
|
|
14787
|
-
}).join("");
|
|
14788
|
-
if (!stripped)
|
|
14789
|
-
return { command, stripped: false };
|
|
14790
|
-
return {
|
|
14791
|
-
command: rebuilt,
|
|
14792
|
-
stripped: true,
|
|
14793
|
-
note: formatStripNote(droppedFilterChains)
|
|
14794
|
-
};
|
|
14795
|
-
}
|
|
14796
|
-
function stripSinglePipelineSegment(segment) {
|
|
14797
|
-
const leading = /^\s*/.exec(segment)?.[0] ?? "";
|
|
14798
|
-
const trailing = /\s*$/.exec(segment)?.[0] ?? "";
|
|
14799
|
-
const coreStart = leading.length;
|
|
14800
|
-
const coreEnd = segment.length - trailing.length;
|
|
14801
|
-
if (coreEnd <= coreStart)
|
|
14802
|
-
return { segment, stripped: false };
|
|
14803
|
-
const core = segment.slice(coreStart, coreEnd);
|
|
14804
|
-
if (containsUnsplittableConstruct(core))
|
|
14805
|
-
return { segment, stripped: false };
|
|
14806
|
-
if (hasUnquotedBackground(core))
|
|
14807
|
-
return { segment, stripped: false };
|
|
14808
|
-
const stages = splitTopLevelPipeline(core);
|
|
14809
|
-
if (stages.length < 2)
|
|
14810
|
-
return { segment, stripped: false };
|
|
14811
|
-
const firstStage = stages[0]?.trim() ?? "";
|
|
14812
|
-
if (!isCompressorHandledRunner(firstStage))
|
|
14813
|
-
return { segment, stripped: false };
|
|
14814
|
-
const filterStages = stages.slice(1).map((stage) => stage.trim());
|
|
14815
|
-
for (const stage of filterStages) {
|
|
14816
|
-
if (!filterStageIsSafeToDrop(stage))
|
|
14817
|
-
return { segment, stripped: false };
|
|
14818
|
-
}
|
|
14819
|
-
return {
|
|
14820
|
-
segment: `${leading}${firstStage}${trailing}`,
|
|
14821
|
-
stripped: true,
|
|
14822
|
-
filters: filterStages.join(" | ")
|
|
14823
|
-
};
|
|
14824
|
-
}
|
|
14825
|
-
function formatStripNote(droppedFilterChains) {
|
|
14826
|
-
const filters = droppedFilterChains.map((filter) => `\`| ${filter}\``).join(", ");
|
|
14827
|
-
return `[AFT dropped ${filters} (compressed:false to keep)]`;
|
|
14828
|
-
}
|
|
14829
|
-
function splitTopLevelCommandChain(command) {
|
|
14830
|
-
const segments = [];
|
|
14831
|
-
let start = 0;
|
|
14832
|
-
let quote = null;
|
|
14833
|
-
let escaped = false;
|
|
14834
|
-
let inBacktick = false;
|
|
14835
|
-
let parenDepth = 0;
|
|
14836
|
-
for (let index = 0;index < command.length; index++) {
|
|
14837
|
-
const char = command[index];
|
|
14838
|
-
const next = command[index + 1];
|
|
14839
|
-
if (escaped) {
|
|
14840
|
-
escaped = false;
|
|
14841
|
-
continue;
|
|
14842
|
-
}
|
|
14843
|
-
if (inBacktick) {
|
|
14844
|
-
if (char === "\\")
|
|
14845
|
-
escaped = true;
|
|
14846
|
-
else if (char === "`")
|
|
14847
|
-
inBacktick = false;
|
|
14848
|
-
continue;
|
|
14849
|
-
}
|
|
14850
|
-
if (char === "\\" && quote !== "'") {
|
|
14851
|
-
escaped = true;
|
|
14852
|
-
continue;
|
|
14853
|
-
}
|
|
14854
|
-
if (quote) {
|
|
14855
|
-
if (char === quote)
|
|
14856
|
-
quote = null;
|
|
14857
|
-
continue;
|
|
14858
|
-
}
|
|
14859
|
-
if (char === "'" || char === '"') {
|
|
14860
|
-
quote = char;
|
|
14861
|
-
continue;
|
|
14862
|
-
}
|
|
14863
|
-
if (char === "`") {
|
|
14864
|
-
inBacktick = true;
|
|
14865
|
-
continue;
|
|
14866
|
-
}
|
|
14867
|
-
if (char === "(") {
|
|
14868
|
-
parenDepth++;
|
|
14869
|
-
continue;
|
|
14870
|
-
}
|
|
14871
|
-
if (char === ")") {
|
|
14872
|
-
if (parenDepth === 0)
|
|
14873
|
-
return null;
|
|
14874
|
-
parenDepth--;
|
|
14875
|
-
continue;
|
|
14876
|
-
}
|
|
14877
|
-
if (parenDepth > 0)
|
|
14878
|
-
continue;
|
|
14879
|
-
if (char === `
|
|
14880
|
-
` || char === "\r")
|
|
14881
|
-
return null;
|
|
14882
|
-
if (char === "#" && (index === 0 || command[index - 1] === " " || command[index - 1] === "\t"))
|
|
14883
|
-
return null;
|
|
14884
|
-
if (char === "&" && next === "&") {
|
|
14885
|
-
segments.push({ segment: command.slice(start, index), separator: "&&" });
|
|
14886
|
-
start = index + 2;
|
|
14887
|
-
index++;
|
|
14888
|
-
continue;
|
|
14889
|
-
}
|
|
14890
|
-
if (char === "|" && next === "|") {
|
|
14891
|
-
segments.push({ segment: command.slice(start, index), separator: "||" });
|
|
14892
|
-
start = index + 2;
|
|
14893
|
-
index++;
|
|
14894
|
-
continue;
|
|
14895
|
-
}
|
|
14896
|
-
if (char === ";") {
|
|
14897
|
-
segments.push({ segment: command.slice(start, index), separator: ";" });
|
|
14898
|
-
start = index + 1;
|
|
14899
|
-
}
|
|
14900
|
-
}
|
|
14901
|
-
if (escaped || quote || inBacktick || parenDepth !== 0)
|
|
14902
|
-
return null;
|
|
14903
|
-
segments.push({ segment: command.slice(start), separator: "" });
|
|
14904
|
-
return segments;
|
|
14905
|
-
}
|
|
14906
|
-
function splitTopLevelPipeline(command) {
|
|
14907
|
-
const stages = [];
|
|
14908
|
-
let start = 0;
|
|
14909
|
-
let quote = null;
|
|
14910
|
-
let escaped = false;
|
|
14911
|
-
for (let index = 0;index < command.length; index++) {
|
|
14912
|
-
const char = command[index];
|
|
14913
|
-
const next = command[index + 1];
|
|
14914
|
-
const previous = command[index - 1];
|
|
14915
|
-
if (escaped) {
|
|
14916
|
-
escaped = false;
|
|
14917
|
-
continue;
|
|
14918
|
-
}
|
|
14919
|
-
if (char === "\\" && quote !== "'") {
|
|
14920
|
-
escaped = true;
|
|
14921
|
-
continue;
|
|
14922
|
-
}
|
|
14923
|
-
if (quote) {
|
|
14924
|
-
if (char === quote)
|
|
14925
|
-
quote = null;
|
|
14926
|
-
continue;
|
|
14927
|
-
}
|
|
14928
|
-
if (char === "'" || char === '"') {
|
|
14929
|
-
quote = char;
|
|
14930
|
-
continue;
|
|
14931
|
-
}
|
|
14932
|
-
if (char === "|" && previous !== "|" && next !== "|") {
|
|
14933
|
-
stages.push(command.slice(start, index));
|
|
14934
|
-
start = index + 1;
|
|
14935
|
-
}
|
|
14936
|
-
}
|
|
14937
|
-
stages.push(command.slice(start));
|
|
14938
|
-
return stages;
|
|
14939
|
-
}
|
|
14940
|
-
function isCompressorHandledRunner(stage) {
|
|
14941
|
-
const tokens = tokenizeStage(stage);
|
|
14942
|
-
if (tokens.length === 0)
|
|
14943
|
-
return false;
|
|
14944
|
-
if (tokens.some((token) => token === "&&" || token === "||" || token.includes(";"))) {
|
|
14945
|
-
return false;
|
|
14946
|
-
}
|
|
14947
|
-
let tokenOffset = 0;
|
|
14948
|
-
while (tokenOffset < tokens.length && isEnvAssignment(tokens[tokenOffset])) {
|
|
14949
|
-
tokenOffset++;
|
|
14950
|
-
}
|
|
14951
|
-
const first = runnerName(tokens[tokenOffset]);
|
|
14952
|
-
const runnerArgs = tokens.slice(tokenOffset + 1);
|
|
14953
|
-
const second = runnerArgs[0];
|
|
14954
|
-
const third = runnerArgs[1];
|
|
14955
|
-
const rest = runnerArgs;
|
|
14956
|
-
if (!first)
|
|
14957
|
-
return false;
|
|
14958
|
-
if (first === "bun") {
|
|
14959
|
-
let args = rest;
|
|
14960
|
-
if (args[0] === "--cwd")
|
|
14961
|
-
args = args.slice(2);
|
|
14962
|
-
else if (args[0]?.startsWith("--cwd="))
|
|
14963
|
-
args = args.slice(1);
|
|
14964
|
-
const sub = args[0];
|
|
14965
|
-
const subNext = args[1];
|
|
14966
|
-
return sub === "test" || sub === "run" && isJsVerificationScript(subNext);
|
|
14967
|
-
}
|
|
14968
|
-
if (first === "npm" || first === "pnpm") {
|
|
14969
|
-
return second === "test" || second === "run" && isJsVerificationScript(third);
|
|
14970
|
-
}
|
|
14971
|
-
if (first === "yarn") {
|
|
14972
|
-
return isJsVerificationScript(second) || second === "run" && isJsVerificationScript(third);
|
|
14973
|
-
}
|
|
14974
|
-
if (first === "deno")
|
|
14975
|
-
return ["test", "lint", "check", "bench"].includes(second ?? "");
|
|
14976
|
-
if (first === "npx") {
|
|
14977
|
-
return ["tsc", "eslint", "vitest", "jest", "playwright", "biome"].includes(second ?? "");
|
|
14978
|
-
}
|
|
14979
|
-
if (first === "playwright")
|
|
14980
|
-
return second === "test";
|
|
14981
|
-
if (first === "cargo") {
|
|
14982
|
-
return ["test", "build", "check", "clippy", "nextest"].includes(second ?? "");
|
|
14983
|
-
}
|
|
14984
|
-
if (first === "go")
|
|
14985
|
-
return ["test", "build", "vet"].includes(second ?? "");
|
|
14986
|
-
if (first === "gradle" || first === "gradlew") {
|
|
14987
|
-
return hasBuildTask(rest, ["test", "check", "build", "assemble", "clean"]);
|
|
14988
|
-
}
|
|
14989
|
-
if (first === "mvn" || first === "mvnw") {
|
|
14990
|
-
return hasBuildTask(rest, ["test", "verify", "package", "install", "clean"]);
|
|
14991
|
-
}
|
|
14992
|
-
if (first === "dotnet")
|
|
14993
|
-
return ["test", "build"].includes(second ?? "");
|
|
14994
|
-
if (first === "rspec")
|
|
14995
|
-
return true;
|
|
14996
|
-
if (first === "rake") {
|
|
14997
|
-
const positionals = rest.filter((a) => !a.startsWith("-"));
|
|
14998
|
-
if (positionals.length === 0)
|
|
14999
|
-
return false;
|
|
15000
|
-
if (positionals.some((a) => a.includes("/") || a.includes(".") || a.includes("=")))
|
|
15001
|
-
return false;
|
|
15002
|
-
return positionals.some((a) => a === "test" || a === "spec");
|
|
15003
|
-
}
|
|
15004
|
-
if (first === "phpunit" || first === "pest")
|
|
15005
|
-
return true;
|
|
15006
|
-
if (first === "xcodebuild")
|
|
15007
|
-
return xcodebuildHasBuildAction(rest);
|
|
15008
|
-
if (first === "swift")
|
|
15009
|
-
return second === "test" || second === "build";
|
|
15010
|
-
if (first === "make" || first === "gmake") {
|
|
15011
|
-
return hasBuildTask(rest, ["test", "check", "lint", "clean"]);
|
|
15012
|
-
}
|
|
15013
|
-
return [
|
|
15014
|
-
"vitest",
|
|
15015
|
-
"jest",
|
|
15016
|
-
"pytest",
|
|
15017
|
-
"tsc",
|
|
15018
|
-
"eslint",
|
|
15019
|
-
"biome",
|
|
15020
|
-
"ruff",
|
|
15021
|
-
"mypy",
|
|
15022
|
-
"tox",
|
|
15023
|
-
"nox"
|
|
15024
|
-
].includes(first);
|
|
15025
|
-
}
|
|
15026
|
-
function isEnvAssignment(token) {
|
|
15027
|
-
if (!token)
|
|
15028
|
-
return false;
|
|
15029
|
-
return /^[a-zA-Z_][a-zA-Z0-9_]*=/.test(token);
|
|
15030
|
-
}
|
|
15031
|
-
function runnerName(token) {
|
|
15032
|
-
if (!token)
|
|
15033
|
-
return "";
|
|
15034
|
-
const slash = token.lastIndexOf("/");
|
|
15035
|
-
return slash === -1 ? token : token.slice(slash + 1);
|
|
15036
|
-
}
|
|
15037
|
-
function hasBuildTask(args, tasks) {
|
|
15038
|
-
const isAllowedTask = (arg) => tasks.some((task) => arg === task || arg.endsWith(`:${task}`));
|
|
15039
|
-
const isFlagOrProperty = (arg) => arg.startsWith("-") || arg.includes("=");
|
|
15040
|
-
let sawAllowed = false;
|
|
15041
|
-
for (const arg of args) {
|
|
15042
|
-
if (isFlagOrProperty(arg))
|
|
15043
|
-
continue;
|
|
15044
|
-
if (!isAllowedTask(arg))
|
|
15155
|
+
return false;
|
|
15156
|
+
warn(`[onnx] unexpected error acquiring lock ${lockPath}: ${err}`);
|
|
15045
15157
|
return false;
|
|
15046
|
-
|
|
15158
|
+
}
|
|
15159
|
+
};
|
|
15160
|
+
if (tryClaim())
|
|
15161
|
+
return true;
|
|
15162
|
+
let owningPid = null;
|
|
15163
|
+
let lockMtimeMs = 0;
|
|
15164
|
+
try {
|
|
15165
|
+
const raw = readFileSync5(lockPath, "utf8");
|
|
15166
|
+
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
15167
|
+
const parsed = Number.parseInt(firstLine, 10);
|
|
15168
|
+
if (Number.isFinite(parsed) && parsed > 0)
|
|
15169
|
+
owningPid = parsed;
|
|
15170
|
+
lockMtimeMs = statSync4(lockPath).mtimeMs;
|
|
15171
|
+
} catch {
|
|
15172
|
+
return tryClaim();
|
|
15047
15173
|
}
|
|
15048
|
-
|
|
15049
|
-
|
|
15050
|
-
|
|
15051
|
-
if (
|
|
15174
|
+
const age = Date.now() - lockMtimeMs;
|
|
15175
|
+
const ageWithinFresh = Math.abs(age) < STALE_LOCK_MS;
|
|
15176
|
+
const ownerAlive = owningPid !== null && isProcessAlive(owningPid);
|
|
15177
|
+
if (ownerAlive && ageWithinFresh) {
|
|
15052
15178
|
return false;
|
|
15053
|
-
return token.startsWith("test") || token === "typecheck" || token.startsWith("typecheck:");
|
|
15054
|
-
}
|
|
15055
|
-
var XCODEBUILD_VALUE_FLAGS = new Set([
|
|
15056
|
-
"-scheme",
|
|
15057
|
-
"-target",
|
|
15058
|
-
"-project",
|
|
15059
|
-
"-workspace",
|
|
15060
|
-
"-configuration",
|
|
15061
|
-
"-sdk",
|
|
15062
|
-
"-destination",
|
|
15063
|
-
"-arch",
|
|
15064
|
-
"-derivedDataPath",
|
|
15065
|
-
"-resultBundlePath",
|
|
15066
|
-
"-xcconfig",
|
|
15067
|
-
"-toolchain"
|
|
15068
|
-
]);
|
|
15069
|
-
var XCODEBUILD_BUILD_ACTIONS = new Set([
|
|
15070
|
-
"build",
|
|
15071
|
-
"test",
|
|
15072
|
-
"build-for-testing",
|
|
15073
|
-
"test-without-building",
|
|
15074
|
-
"analyze"
|
|
15075
|
-
]);
|
|
15076
|
-
function xcodebuildHasBuildAction(args) {
|
|
15077
|
-
for (let i = 0;i < args.length; i++) {
|
|
15078
|
-
const arg = args[i];
|
|
15079
|
-
if (arg.startsWith("-")) {
|
|
15080
|
-
if (XCODEBUILD_VALUE_FLAGS.has(arg))
|
|
15081
|
-
i++;
|
|
15082
|
-
continue;
|
|
15083
|
-
}
|
|
15084
|
-
if (XCODEBUILD_BUILD_ACTIONS.has(arg))
|
|
15085
|
-
return true;
|
|
15086
15179
|
}
|
|
15087
|
-
|
|
15180
|
+
log(`[onnx] reclaiming install lock (owner_pid=${owningPid ?? "unknown"}, alive=${ownerAlive}, age_ms=${age})`);
|
|
15181
|
+
try {
|
|
15182
|
+
unlinkSync4(lockPath);
|
|
15183
|
+
} catch {}
|
|
15184
|
+
return tryClaim();
|
|
15088
15185
|
}
|
|
15089
|
-
function
|
|
15090
|
-
|
|
15091
|
-
|
|
15092
|
-
|
|
15093
|
-
|
|
15094
|
-
|
|
15095
|
-
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15099
|
-
|
|
15100
|
-
|
|
15101
|
-
|
|
15102
|
-
|
|
15103
|
-
|
|
15104
|
-
quote = null;
|
|
15105
|
-
continue;
|
|
15186
|
+
function releaseLock(lockPath) {
|
|
15187
|
+
try {
|
|
15188
|
+
let owningPid = null;
|
|
15189
|
+
try {
|
|
15190
|
+
const raw = readFileSync5(lockPath, "utf8");
|
|
15191
|
+
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
15192
|
+
const parsed = Number.parseInt(firstLine, 10);
|
|
15193
|
+
if (Number.isFinite(parsed) && parsed > 0)
|
|
15194
|
+
owningPid = parsed;
|
|
15195
|
+
} catch (readErr) {
|
|
15196
|
+
const code = readErr.code;
|
|
15197
|
+
if (code === "ENOENT")
|
|
15198
|
+
return;
|
|
15199
|
+
warn(`[onnx] could not read lock ${lockPath} during release: ${readErr}`);
|
|
15200
|
+
return;
|
|
15106
15201
|
}
|
|
15107
|
-
if (
|
|
15108
|
-
|
|
15109
|
-
|
|
15110
|
-
else if (char === "`")
|
|
15111
|
-
return true;
|
|
15112
|
-
else if (char === "$" && command[i + 1] === "(")
|
|
15113
|
-
return true;
|
|
15114
|
-
continue;
|
|
15202
|
+
if (owningPid !== process.pid) {
|
|
15203
|
+
log(`[onnx] not releasing lock ${lockPath}: owned by pid ${owningPid ?? "unknown"} (we are ${process.pid})`);
|
|
15204
|
+
return;
|
|
15115
15205
|
}
|
|
15116
|
-
|
|
15117
|
-
|
|
15118
|
-
|
|
15206
|
+
try {
|
|
15207
|
+
unlinkSync4(lockPath);
|
|
15208
|
+
} catch (unlinkErr) {
|
|
15209
|
+
const code = unlinkErr.code;
|
|
15210
|
+
if (code !== "ENOENT") {
|
|
15211
|
+
warn(`[onnx] failed to release lock ${lockPath}: ${unlinkErr}`);
|
|
15212
|
+
}
|
|
15119
15213
|
}
|
|
15120
|
-
|
|
15121
|
-
|
|
15122
|
-
if (char === "(" || char === ")")
|
|
15123
|
-
return true;
|
|
15214
|
+
} catch (err) {
|
|
15215
|
+
warn(`[onnx] unexpected error releasing lock ${lockPath}: ${err}`);
|
|
15124
15216
|
}
|
|
15125
|
-
return false;
|
|
15126
15217
|
}
|
|
15127
|
-
|
|
15128
|
-
|
|
15129
|
-
|
|
15130
|
-
|
|
15131
|
-
|
|
15132
|
-
|
|
15133
|
-
|
|
15134
|
-
|
|
15135
|
-
|
|
15136
|
-
if (/[<>]/.test(stage))
|
|
15218
|
+
function tasklistPidFromCsvLine(line) {
|
|
15219
|
+
const quoted = line.match(/"([^"]*)"/g);
|
|
15220
|
+
if (quoted && quoted.length >= 2)
|
|
15221
|
+
return quoted[1].slice(1, -1);
|
|
15222
|
+
const cells = line.split(",").map((cell) => cell.trim().replace(/^"|"$/g, ""));
|
|
15223
|
+
return cells[1] ?? null;
|
|
15224
|
+
}
|
|
15225
|
+
function isWindowsProcessAlive(pid) {
|
|
15226
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
15137
15227
|
return false;
|
|
15138
|
-
|
|
15228
|
+
try {
|
|
15229
|
+
const output = execFileSync("tasklist.exe", ["/FI", `PID eq ${pid}`, "/FO", "CSV", "/NH"], {
|
|
15230
|
+
encoding: "utf8",
|
|
15231
|
+
timeout: 2000,
|
|
15232
|
+
windowsHide: true
|
|
15233
|
+
});
|
|
15234
|
+
const expected = String(pid);
|
|
15235
|
+
return output.split(/\r?\n/).some((line) => tasklistPidFromCsvLine(line) === expected);
|
|
15236
|
+
} catch {
|
|
15139
15237
|
return false;
|
|
15140
|
-
const args = tokenizeStage(stage).slice(1);
|
|
15141
|
-
const hasFlag = (...names) => args.some((a) => names.some((n) => a === n || a.startsWith(`${n}=`)));
|
|
15142
|
-
if (head === "grep" || head === "rg") {
|
|
15143
|
-
if (hasIntentChangingGrepFlag(args))
|
|
15144
|
-
return false;
|
|
15145
|
-
if (countBareOperands(args) > 1)
|
|
15146
|
-
return false;
|
|
15147
|
-
return true;
|
|
15148
|
-
}
|
|
15149
|
-
if (head === "head" || head === "tail") {
|
|
15150
|
-
if (bareOperands(args).some((op) => !/^\d+$/.test(op)))
|
|
15151
|
-
return false;
|
|
15152
|
-
return true;
|
|
15153
15238
|
}
|
|
15154
|
-
|
|
15155
|
-
|
|
15156
|
-
|
|
15157
|
-
return
|
|
15158
|
-
|
|
15159
|
-
|
|
15160
|
-
if (hasFlag("-i", "--in-place"))
|
|
15161
|
-
return false;
|
|
15162
|
-
if (countBareOperands(args) > 1)
|
|
15163
|
-
return false;
|
|
15239
|
+
}
|
|
15240
|
+
function isProcessAlive(pid) {
|
|
15241
|
+
if (process.platform === "win32")
|
|
15242
|
+
return isWindowsProcessAlive(pid);
|
|
15243
|
+
try {
|
|
15244
|
+
process.kill(pid, 0);
|
|
15164
15245
|
return true;
|
|
15165
|
-
}
|
|
15166
|
-
|
|
15167
|
-
if (
|
|
15246
|
+
} catch (err) {
|
|
15247
|
+
const code = err.code;
|
|
15248
|
+
if (code === "ESRCH")
|
|
15168
15249
|
return false;
|
|
15169
15250
|
return true;
|
|
15170
15251
|
}
|
|
15171
|
-
if (head === "sort" && hasFlag("-o", "--output"))
|
|
15172
|
-
return false;
|
|
15173
|
-
if (bareOperands(args).some((op) => op.includes("/") || op.includes(".")))
|
|
15174
|
-
return false;
|
|
15175
|
-
return true;
|
|
15176
|
-
}
|
|
15177
|
-
function bareOperands(args) {
|
|
15178
|
-
const out = [];
|
|
15179
|
-
let afterDoubleDash = false;
|
|
15180
|
-
for (const arg of args) {
|
|
15181
|
-
if (!afterDoubleDash && arg === "--") {
|
|
15182
|
-
afterDoubleDash = true;
|
|
15183
|
-
continue;
|
|
15184
|
-
}
|
|
15185
|
-
if (!afterDoubleDash && arg.startsWith("-") && arg !== "-")
|
|
15186
|
-
continue;
|
|
15187
|
-
out.push(arg);
|
|
15188
|
-
}
|
|
15189
|
-
return out;
|
|
15190
|
-
}
|
|
15191
|
-
function countBareOperands(args) {
|
|
15192
|
-
return bareOperands(args).length;
|
|
15193
15252
|
}
|
|
15194
|
-
|
|
15195
|
-
|
|
15196
|
-
|
|
15197
|
-
|
|
15198
|
-
|
|
15199
|
-
|
|
15200
|
-
|
|
15201
|
-
|
|
15202
|
-
|
|
15203
|
-
|
|
15204
|
-
|
|
15205
|
-
|
|
15206
|
-
|
|
15207
|
-
if (quote) {
|
|
15208
|
-
if (char === quote)
|
|
15209
|
-
quote = null;
|
|
15210
|
-
continue;
|
|
15211
|
-
}
|
|
15212
|
-
if (char === "'" || char === '"') {
|
|
15213
|
-
quote = char;
|
|
15214
|
-
continue;
|
|
15215
|
-
}
|
|
15216
|
-
if (char === "&") {
|
|
15217
|
-
const prev = stage[i - 1];
|
|
15218
|
-
const next = stage[i + 1];
|
|
15219
|
-
if (prev === "&" || next === "&" || prev === ">" || next === ">")
|
|
15220
|
-
continue;
|
|
15221
|
-
return true;
|
|
15222
|
-
}
|
|
15253
|
+
// ../aft-bridge/dist/pool.js
|
|
15254
|
+
import { homedir as homedir9 } from "node:os";
|
|
15255
|
+
|
|
15256
|
+
// ../aft-bridge/dist/project-identity.js
|
|
15257
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
15258
|
+
import { resolve as resolve6 } from "node:path";
|
|
15259
|
+
function canonicalizeProjectRoot(dir) {
|
|
15260
|
+
const trimmed = dir.replace(/[/\\]+$/, "");
|
|
15261
|
+
let canonical;
|
|
15262
|
+
try {
|
|
15263
|
+
canonical = realpathSync2(trimmed);
|
|
15264
|
+
} catch {
|
|
15265
|
+
canonical = resolve6(trimmed);
|
|
15223
15266
|
}
|
|
15224
|
-
return
|
|
15267
|
+
return normalizeWindowsRoot(canonical);
|
|
15225
15268
|
}
|
|
15226
|
-
function
|
|
15227
|
-
|
|
15228
|
-
|
|
15229
|
-
|
|
15230
|
-
|
|
15231
|
-
|
|
15232
|
-
|
|
15233
|
-
|
|
15234
|
-
if (GREP_GUARD_FLAGS.has(flag))
|
|
15235
|
-
return true;
|
|
15236
|
-
continue;
|
|
15237
|
-
}
|
|
15238
|
-
for (const flag of arg.slice(1)) {
|
|
15239
|
-
if (GREP_GUARD_FLAGS.has(flag))
|
|
15240
|
-
return true;
|
|
15241
|
-
}
|
|
15269
|
+
function normalizeWindowsRoot(p) {
|
|
15270
|
+
if (process.platform !== "win32")
|
|
15271
|
+
return p;
|
|
15272
|
+
let s = p;
|
|
15273
|
+
if (s.startsWith("\\\\?\\UNC\\")) {
|
|
15274
|
+
s = `\\\\${s.slice("\\\\?\\UNC\\".length)}`;
|
|
15275
|
+
} else if (s.startsWith("\\\\?\\")) {
|
|
15276
|
+
s = s.slice("\\\\?\\".length);
|
|
15242
15277
|
}
|
|
15243
|
-
|
|
15244
|
-
|
|
15245
|
-
|
|
15246
|
-
|
|
15247
|
-
let current = "";
|
|
15248
|
-
let quote = null;
|
|
15249
|
-
let escaped = false;
|
|
15250
|
-
for (let index = 0;index < stage.length; index++) {
|
|
15251
|
-
const char = stage[index];
|
|
15252
|
-
if (escaped) {
|
|
15253
|
-
current += char;
|
|
15254
|
-
escaped = false;
|
|
15255
|
-
continue;
|
|
15256
|
-
}
|
|
15257
|
-
if (char === "\\" && quote !== "'") {
|
|
15258
|
-
escaped = true;
|
|
15259
|
-
continue;
|
|
15260
|
-
}
|
|
15261
|
-
if (quote) {
|
|
15262
|
-
if (char === quote) {
|
|
15263
|
-
quote = null;
|
|
15264
|
-
} else {
|
|
15265
|
-
current += char;
|
|
15266
|
-
}
|
|
15267
|
-
continue;
|
|
15268
|
-
}
|
|
15269
|
-
if (char === "'" || char === '"') {
|
|
15270
|
-
quote = char;
|
|
15271
|
-
continue;
|
|
15272
|
-
}
|
|
15273
|
-
if (/\s/.test(char)) {
|
|
15274
|
-
if (current.length > 0) {
|
|
15275
|
-
tokens.push(current);
|
|
15276
|
-
current = "";
|
|
15277
|
-
}
|
|
15278
|
-
continue;
|
|
15278
|
+
if (s.length >= 2 && s[1] === ":") {
|
|
15279
|
+
const drive = s.charCodeAt(0);
|
|
15280
|
+
if (drive >= 97 && drive <= 122) {
|
|
15281
|
+
s = s[0].toUpperCase() + s.slice(1);
|
|
15279
15282
|
}
|
|
15280
|
-
current += char;
|
|
15281
15283
|
}
|
|
15282
|
-
|
|
15283
|
-
tokens.push(current);
|
|
15284
|
-
return tokens;
|
|
15284
|
+
return s;
|
|
15285
15285
|
}
|
|
15286
|
+
|
|
15286
15287
|
// ../aft-bridge/dist/pool.js
|
|
15287
|
-
import { realpathSync as realpathSync2 } from "node:fs";
|
|
15288
|
-
import { homedir as homedir8 } from "node:os";
|
|
15289
15288
|
var DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
|
|
15290
15289
|
var DEFAULT_MAX_POOL_SIZE = 8;
|
|
15291
15290
|
var CLEANUP_INTERVAL_MS = 60 * 1000;
|
|
15292
15291
|
function canonicalHomeDir() {
|
|
15293
15292
|
try {
|
|
15294
|
-
const home =
|
|
15293
|
+
const home = homedir9();
|
|
15295
15294
|
if (!home)
|
|
15296
15295
|
return null;
|
|
15297
|
-
|
|
15298
|
-
return realpathSync2(home);
|
|
15299
|
-
} catch {
|
|
15300
|
-
return home.replace(/[/\\]+$/, "");
|
|
15301
|
-
}
|
|
15296
|
+
return canonicalizeProjectRoot(home);
|
|
15302
15297
|
} catch {
|
|
15303
15298
|
return null;
|
|
15304
15299
|
}
|
|
@@ -15477,12 +15472,7 @@ class BridgePool {
|
|
|
15477
15472
|
}
|
|
15478
15473
|
}
|
|
15479
15474
|
function normalizeKey(projectRoot) {
|
|
15480
|
-
|
|
15481
|
-
try {
|
|
15482
|
-
return realpathSync2(stripped);
|
|
15483
|
-
} catch {
|
|
15484
|
-
return stripped;
|
|
15485
|
-
}
|
|
15475
|
+
return canonicalizeProjectRoot(projectRoot);
|
|
15486
15476
|
}
|
|
15487
15477
|
// ../aft-bridge/dist/tool-format.js
|
|
15488
15478
|
function asPlainObject(value) {
|
|
@@ -16314,7 +16304,7 @@ import {
|
|
|
16314
16304
|
// package.json
|
|
16315
16305
|
var package_default = {
|
|
16316
16306
|
name: "@cortexkit/aft-pi",
|
|
16317
|
-
version: "0.
|
|
16307
|
+
version: "0.40.0",
|
|
16318
16308
|
type: "module",
|
|
16319
16309
|
description: "Pi coding agent extension for Agent File Tools (AFT) — tree-sitter and LSP-powered code analysis",
|
|
16320
16310
|
main: "dist/index.js",
|
|
@@ -16337,7 +16327,7 @@ var package_default = {
|
|
|
16337
16327
|
"test:unit": "bun test src/__tests__ --path-ignore-patterns 'src/__tests__/e2e/**'"
|
|
16338
16328
|
},
|
|
16339
16329
|
dependencies: {
|
|
16340
|
-
"@cortexkit/aft-bridge": "0.
|
|
16330
|
+
"@cortexkit/aft-bridge": "0.40.0",
|
|
16341
16331
|
"@xterm/headless": "^5.5.0",
|
|
16342
16332
|
"comment-json": "^5.0.0",
|
|
16343
16333
|
diff: "^8.0.4",
|
|
@@ -16345,12 +16335,12 @@ var package_default = {
|
|
|
16345
16335
|
zod: "^4.1.8"
|
|
16346
16336
|
},
|
|
16347
16337
|
optionalDependencies: {
|
|
16348
|
-
"@cortexkit/aft-darwin-arm64": "0.
|
|
16349
|
-
"@cortexkit/aft-darwin-x64": "0.
|
|
16350
|
-
"@cortexkit/aft-linux-arm64": "0.
|
|
16351
|
-
"@cortexkit/aft-linux-x64": "0.
|
|
16352
|
-
"@cortexkit/aft-win32-arm64": "0.
|
|
16353
|
-
"@cortexkit/aft-win32-x64": "0.
|
|
16338
|
+
"@cortexkit/aft-darwin-arm64": "0.40.0",
|
|
16339
|
+
"@cortexkit/aft-darwin-x64": "0.40.0",
|
|
16340
|
+
"@cortexkit/aft-linux-arm64": "0.40.0",
|
|
16341
|
+
"@cortexkit/aft-linux-x64": "0.40.0",
|
|
16342
|
+
"@cortexkit/aft-win32-arm64": "0.40.0",
|
|
16343
|
+
"@cortexkit/aft-win32-x64": "0.40.0"
|
|
16354
16344
|
},
|
|
16355
16345
|
devDependencies: {
|
|
16356
16346
|
"@earendil-works/pi-coding-agent": "*",
|
|
@@ -16924,9 +16914,7 @@ function registerStatusCommand(pi, ctx) {
|
|
|
16924
16914
|
}
|
|
16925
16915
|
|
|
16926
16916
|
// src/config.ts
|
|
16927
|
-
import { existsSync as
|
|
16928
|
-
import { homedir as homedir9 } from "node:os";
|
|
16929
|
-
import { join as join10 } from "node:path";
|
|
16917
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, renameSync as renameSync5, unlinkSync as unlinkSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
16930
16918
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
16931
16919
|
|
|
16932
16920
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
@@ -30462,7 +30450,7 @@ function date4(params) {
|
|
|
30462
30450
|
// ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
|
|
30463
30451
|
config(en_default());
|
|
30464
30452
|
// src/config.ts
|
|
30465
|
-
var FOREGROUND_WAIT_WINDOW_DEFAULT_MS =
|
|
30453
|
+
var FOREGROUND_WAIT_WINDOW_DEFAULT_MS = 15000;
|
|
30466
30454
|
var FOREGROUND_WAIT_WINDOW_MIN_MS = 5000;
|
|
30467
30455
|
function resolveBashConfig(config2) {
|
|
30468
30456
|
const top = config2.bash;
|
|
@@ -30633,105 +30621,6 @@ var AftConfigSchema = exports_external.object({
|
|
|
30633
30621
|
max_callgraph_files: exports_external.number().int().positive().optional(),
|
|
30634
30622
|
bridge: BridgeConfigSchema.optional()
|
|
30635
30623
|
}).strict();
|
|
30636
|
-
function normalizeLspExtension(extension) {
|
|
30637
|
-
return extension.trim().replace(/^\.+/, "");
|
|
30638
|
-
}
|
|
30639
|
-
function resolveLspConfigForConfigure(config2) {
|
|
30640
|
-
const overrides = {};
|
|
30641
|
-
const disabled = new Set(config2.lsp?.disabled ?? []);
|
|
30642
|
-
let experimentalTy = config2.experimental?.lsp_ty;
|
|
30643
|
-
switch (config2.lsp?.python ?? "auto") {
|
|
30644
|
-
case "ty":
|
|
30645
|
-
experimentalTy = true;
|
|
30646
|
-
disabled.add("python");
|
|
30647
|
-
break;
|
|
30648
|
-
case "pyright":
|
|
30649
|
-
experimentalTy = false;
|
|
30650
|
-
disabled.add("ty");
|
|
30651
|
-
break;
|
|
30652
|
-
case "auto":
|
|
30653
|
-
break;
|
|
30654
|
-
}
|
|
30655
|
-
if (experimentalTy !== undefined) {
|
|
30656
|
-
overrides.experimental_lsp_ty = experimentalTy;
|
|
30657
|
-
}
|
|
30658
|
-
const servers = Object.entries(config2.lsp?.servers ?? {}).map(([id, server]) => {
|
|
30659
|
-
const entry = {
|
|
30660
|
-
id,
|
|
30661
|
-
args: server.args,
|
|
30662
|
-
root_markers: server.root_markers,
|
|
30663
|
-
disabled: server.disabled
|
|
30664
|
-
};
|
|
30665
|
-
if (server.extensions && server.extensions.length > 0) {
|
|
30666
|
-
entry.extensions = server.extensions.map(normalizeLspExtension);
|
|
30667
|
-
}
|
|
30668
|
-
if (server.binary) {
|
|
30669
|
-
entry.binary = server.binary;
|
|
30670
|
-
}
|
|
30671
|
-
if (server.env && Object.keys(server.env).length > 0) {
|
|
30672
|
-
entry.env = server.env;
|
|
30673
|
-
}
|
|
30674
|
-
if (server.initialization_options !== undefined) {
|
|
30675
|
-
entry.initialization_options = server.initialization_options;
|
|
30676
|
-
}
|
|
30677
|
-
return entry;
|
|
30678
|
-
});
|
|
30679
|
-
if (servers.length > 0) {
|
|
30680
|
-
overrides.lsp_servers = servers;
|
|
30681
|
-
}
|
|
30682
|
-
if (disabled.size > 0) {
|
|
30683
|
-
overrides.disabled_lsp = [...disabled];
|
|
30684
|
-
}
|
|
30685
|
-
return overrides;
|
|
30686
|
-
}
|
|
30687
|
-
function resolveProjectOverridesForConfigure(config2) {
|
|
30688
|
-
const overrides = {};
|
|
30689
|
-
if (config2.format_on_edit !== undefined)
|
|
30690
|
-
overrides.format_on_edit = config2.format_on_edit;
|
|
30691
|
-
if (config2.formatter_timeout_secs !== undefined)
|
|
30692
|
-
overrides.formatter_timeout_secs = config2.formatter_timeout_secs;
|
|
30693
|
-
if (config2.validate_on_edit !== undefined)
|
|
30694
|
-
overrides.validate_on_edit = config2.validate_on_edit;
|
|
30695
|
-
if (config2.formatter !== undefined)
|
|
30696
|
-
overrides.formatter = config2.formatter;
|
|
30697
|
-
if (config2.checker !== undefined)
|
|
30698
|
-
overrides.checker = config2.checker;
|
|
30699
|
-
overrides.restrict_to_project_root = config2.restrict_to_project_root ?? false;
|
|
30700
|
-
if (config2.search_index !== undefined)
|
|
30701
|
-
overrides.search_index = config2.search_index;
|
|
30702
|
-
if (config2.semantic_search !== undefined)
|
|
30703
|
-
overrides.semantic_search = config2.semantic_search;
|
|
30704
|
-
if (config2.callgraph_store !== undefined)
|
|
30705
|
-
overrides.callgraph_store = config2.callgraph_store;
|
|
30706
|
-
if (config2.callgraph_chunk_size !== undefined)
|
|
30707
|
-
overrides.callgraph_chunk_size = config2.callgraph_chunk_size;
|
|
30708
|
-
Object.assign(overrides, resolveExperimentalConfigForConfigure(config2));
|
|
30709
|
-
Object.assign(overrides, resolveLspConfigForConfigure(config2));
|
|
30710
|
-
if (config2.semantic !== undefined)
|
|
30711
|
-
overrides.semantic = config2.semantic;
|
|
30712
|
-
if (config2.inspect !== undefined)
|
|
30713
|
-
overrides.inspect = config2.inspect;
|
|
30714
|
-
if (config2.max_callgraph_files !== undefined)
|
|
30715
|
-
overrides.max_callgraph_files = config2.max_callgraph_files;
|
|
30716
|
-
return overrides;
|
|
30717
|
-
}
|
|
30718
|
-
function resolveExperimentalConfigForConfigure(config2) {
|
|
30719
|
-
const overrides = {};
|
|
30720
|
-
const bash = resolveBashConfig(config2);
|
|
30721
|
-
overrides.experimental_bash_rewrite = bash.rewrite;
|
|
30722
|
-
overrides.experimental_bash_compress = bash.compress;
|
|
30723
|
-
overrides.experimental_bash_background = bash.background;
|
|
30724
|
-
if (bash.long_running_reminder_enabled !== undefined) {
|
|
30725
|
-
overrides.bash_long_running_reminder_enabled = bash.long_running_reminder_enabled;
|
|
30726
|
-
}
|
|
30727
|
-
if (bash.long_running_reminder_interval_ms !== undefined) {
|
|
30728
|
-
overrides.bash_long_running_reminder_interval_ms = bash.long_running_reminder_interval_ms;
|
|
30729
|
-
}
|
|
30730
|
-
if (config2.experimental?.lsp_ty !== undefined) {
|
|
30731
|
-
overrides.experimental_lsp_ty = config2.experimental.lsp_ty;
|
|
30732
|
-
}
|
|
30733
|
-
return overrides;
|
|
30734
|
-
}
|
|
30735
30624
|
var CONFIG_MIGRATIONS = [
|
|
30736
30625
|
{ oldKey: "experimental_search_index", newPath: ["search_index"] },
|
|
30737
30626
|
{ oldKey: "experimental_semantic_search", newPath: ["semantic_search"] },
|
|
@@ -30841,14 +30730,14 @@ function migrateExperimentalBashBlock(rawConfig, configPath, logger) {
|
|
|
30841
30730
|
}
|
|
30842
30731
|
return movedKeys;
|
|
30843
30732
|
}
|
|
30844
|
-
function
|
|
30845
|
-
if (!
|
|
30733
|
+
function migrateAftConfigFile2(configPath, logger = { log: log2, warn: warn2 }) {
|
|
30734
|
+
if (!existsSync7(configPath)) {
|
|
30846
30735
|
return { migrated: false, oldKeys: [] };
|
|
30847
30736
|
}
|
|
30848
30737
|
let tmpPath = null;
|
|
30849
30738
|
let oldKeys = [];
|
|
30850
30739
|
try {
|
|
30851
|
-
const content =
|
|
30740
|
+
const content = readFileSync6(configPath, "utf-8");
|
|
30852
30741
|
const rawConfig = import_comment_json.parse(content);
|
|
30853
30742
|
if (!rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
|
|
30854
30743
|
return { migrated: false, oldKeys: [] };
|
|
@@ -30864,14 +30753,14 @@ function migrateAftConfigFile(configPath, logger = { log: log2, warn: warn2 }) {
|
|
|
30864
30753
|
`)}
|
|
30865
30754
|
${serialized}` : serialized;
|
|
30866
30755
|
tmpPath = `${configPath}.tmp.${process.pid}`;
|
|
30867
|
-
|
|
30868
|
-
|
|
30756
|
+
writeFileSync4(tmpPath, nextContent, "utf-8");
|
|
30757
|
+
renameSync5(tmpPath, configPath);
|
|
30869
30758
|
logger.log(`Migrated config at ${configPath}: removed ${oldKeys.join(", ")}`);
|
|
30870
30759
|
return { migrated: true, oldKeys };
|
|
30871
30760
|
} catch (err) {
|
|
30872
30761
|
if (tmpPath) {
|
|
30873
30762
|
try {
|
|
30874
|
-
|
|
30763
|
+
unlinkSync5(tmpPath);
|
|
30875
30764
|
} catch {}
|
|
30876
30765
|
}
|
|
30877
30766
|
if (isWritableMigrationError(err)) {
|
|
@@ -30882,15 +30771,6 @@ ${serialized}` : serialized;
|
|
|
30882
30771
|
return { migrated: false, oldKeys: [] };
|
|
30883
30772
|
}
|
|
30884
30773
|
}
|
|
30885
|
-
function detectConfigFile(basePath) {
|
|
30886
|
-
const jsoncPath = `${basePath}.jsonc`;
|
|
30887
|
-
const jsonPath = `${basePath}.json`;
|
|
30888
|
-
if (existsSync6(jsoncPath))
|
|
30889
|
-
return { format: "jsonc", path: jsoncPath };
|
|
30890
|
-
if (existsSync6(jsonPath))
|
|
30891
|
-
return { format: "json", path: jsonPath };
|
|
30892
|
-
return { format: "none", path: jsonPath };
|
|
30893
|
-
}
|
|
30894
30774
|
var configLoadErrors = [];
|
|
30895
30775
|
function getConfigLoadErrors() {
|
|
30896
30776
|
return configLoadErrors;
|
|
@@ -30904,9 +30784,9 @@ function recordConfigParseFailure(configPath, errorMessage) {
|
|
|
30904
30784
|
}
|
|
30905
30785
|
function loadConfigFromPath(configPath) {
|
|
30906
30786
|
try {
|
|
30907
|
-
if (!
|
|
30787
|
+
if (!existsSync7(configPath))
|
|
30908
30788
|
return null;
|
|
30909
|
-
const content =
|
|
30789
|
+
const content = readFileSync6(configPath, "utf-8");
|
|
30910
30790
|
const rawConfig = import_comment_json.parse(content);
|
|
30911
30791
|
if (!rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
|
|
30912
30792
|
recordConfigParseFailure(configPath, "root must be an object");
|
|
@@ -31123,21 +31003,43 @@ function resolveBridgePoolTransportOptions(config2) {
|
|
|
31123
31003
|
hangThreshold: config2.bridge?.hang_threshold ?? DEFAULT_BRIDGE_HANG_THRESHOLD
|
|
31124
31004
|
};
|
|
31125
31005
|
}
|
|
31126
|
-
function
|
|
31127
|
-
|
|
31006
|
+
function migrateAftConfigLocations(projectDirectory, logger = { log: log2, warn: warn2 }) {
|
|
31007
|
+
const paths = resolveCortexKitConfigPaths(projectDirectory);
|
|
31008
|
+
const legacy = resolveLegacyAftConfigSources(projectDirectory);
|
|
31009
|
+
return [
|
|
31010
|
+
migrateAftConfigFile({
|
|
31011
|
+
scope: "user",
|
|
31012
|
+
targetPath: paths.userConfigPath,
|
|
31013
|
+
legacySources: legacy.user,
|
|
31014
|
+
operatingHarness: "pi",
|
|
31015
|
+
logger
|
|
31016
|
+
}),
|
|
31017
|
+
migrateAftConfigFile({
|
|
31018
|
+
scope: "project",
|
|
31019
|
+
targetPath: paths.projectConfigPath,
|
|
31020
|
+
legacySources: legacy.project,
|
|
31021
|
+
operatingHarness: "pi",
|
|
31022
|
+
logger
|
|
31023
|
+
})
|
|
31024
|
+
];
|
|
31025
|
+
}
|
|
31026
|
+
function resolveAftConfigPaths(projectDirectory) {
|
|
31027
|
+
const paths = resolveCortexKitConfigPaths(projectDirectory);
|
|
31028
|
+
migrateAftConfigFile2(paths.userConfigPath);
|
|
31029
|
+
migrateAftConfigFile2(paths.projectConfigPath);
|
|
31030
|
+
return paths;
|
|
31031
|
+
}
|
|
31032
|
+
function buildConfigTierConfigureParams(projectDirectory, processState = {}) {
|
|
31033
|
+
const paths = resolveAftConfigPaths(projectDirectory);
|
|
31034
|
+
return {
|
|
31035
|
+
...processState,
|
|
31036
|
+
cortexkit_user_config_path: paths.userConfigPath,
|
|
31037
|
+
config: readConfigTiers(paths)
|
|
31038
|
+
};
|
|
31128
31039
|
}
|
|
31129
31040
|
function loadAftConfig(projectDirectory) {
|
|
31130
31041
|
configLoadErrors = [];
|
|
31131
|
-
const
|
|
31132
|
-
migrateAftConfigFile(`${userBasePath}.jsonc`);
|
|
31133
|
-
migrateAftConfigFile(`${userBasePath}.json`);
|
|
31134
|
-
const userDetected = detectConfigFile(userBasePath);
|
|
31135
|
-
const userConfigPath = userDetected.format !== "none" ? userDetected.path : `${userBasePath}.json`;
|
|
31136
|
-
const projectBasePath = join10(projectDirectory, ".pi", "aft");
|
|
31137
|
-
migrateAftConfigFile(`${projectBasePath}.jsonc`);
|
|
31138
|
-
migrateAftConfigFile(`${projectBasePath}.json`);
|
|
31139
|
-
const projectDetected = detectConfigFile(projectBasePath);
|
|
31140
|
-
const projectConfigPath = projectDetected.format !== "none" ? projectDetected.path : `${projectBasePath}.json`;
|
|
31042
|
+
const { userConfigPath, projectConfigPath } = resolveAftConfigPaths(projectDirectory);
|
|
31141
31043
|
let config2 = loadConfigFromPath(userConfigPath) ?? {};
|
|
31142
31044
|
const projectConfig = loadConfigFromPath(projectConfigPath);
|
|
31143
31045
|
if (projectConfig) {
|
|
@@ -31162,56 +31064,56 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
31162
31064
|
import { createHash as createHash3 } from "node:crypto";
|
|
31163
31065
|
import {
|
|
31164
31066
|
createReadStream,
|
|
31165
|
-
existsSync as
|
|
31067
|
+
existsSync as existsSync9,
|
|
31166
31068
|
mkdirSync as mkdirSync7,
|
|
31167
|
-
readFileSync as
|
|
31168
|
-
renameSync as
|
|
31169
|
-
rmSync as
|
|
31170
|
-
statSync as
|
|
31171
|
-
writeFileSync as
|
|
31069
|
+
readFileSync as readFileSync9,
|
|
31070
|
+
renameSync as renameSync6,
|
|
31071
|
+
rmSync as rmSync4,
|
|
31072
|
+
statSync as statSync6,
|
|
31073
|
+
writeFileSync as writeFileSync6
|
|
31172
31074
|
} from "node:fs";
|
|
31173
|
-
import { join as
|
|
31075
|
+
import { join as join12 } from "node:path";
|
|
31174
31076
|
|
|
31175
31077
|
// src/lsp-cache.ts
|
|
31176
31078
|
import {
|
|
31177
|
-
closeSync as
|
|
31079
|
+
closeSync as closeSync5,
|
|
31178
31080
|
mkdirSync as mkdirSync6,
|
|
31179
|
-
openSync as
|
|
31180
|
-
readFileSync as
|
|
31181
|
-
statSync as
|
|
31182
|
-
unlinkSync as
|
|
31183
|
-
writeFileSync as
|
|
31081
|
+
openSync as openSync5,
|
|
31082
|
+
readFileSync as readFileSync7,
|
|
31083
|
+
statSync as statSync5,
|
|
31084
|
+
unlinkSync as unlinkSync6,
|
|
31085
|
+
writeFileSync as writeFileSync5
|
|
31184
31086
|
} from "node:fs";
|
|
31185
31087
|
import { homedir as homedir10 } from "node:os";
|
|
31186
|
-
import { join as
|
|
31088
|
+
import { join as join10 } from "node:path";
|
|
31187
31089
|
function aftCacheBase() {
|
|
31188
31090
|
const override = process.env.AFT_CACHE_DIR;
|
|
31189
31091
|
if (override && override.length > 0)
|
|
31190
31092
|
return override;
|
|
31191
31093
|
if (process.platform === "win32") {
|
|
31192
31094
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
31193
|
-
const base2 = localAppData ||
|
|
31194
|
-
return
|
|
31095
|
+
const base2 = localAppData || join10(homedir10(), "AppData", "Local");
|
|
31096
|
+
return join10(base2, "aft");
|
|
31195
31097
|
}
|
|
31196
|
-
const base = process.env.XDG_CACHE_HOME ||
|
|
31197
|
-
return
|
|
31098
|
+
const base = process.env.XDG_CACHE_HOME || join10(homedir10(), ".cache");
|
|
31099
|
+
return join10(base, "aft");
|
|
31198
31100
|
}
|
|
31199
31101
|
function lspCacheRoot() {
|
|
31200
|
-
return
|
|
31102
|
+
return join10(aftCacheBase(), "lsp-packages");
|
|
31201
31103
|
}
|
|
31202
31104
|
function lspPackageDir(npmPackage) {
|
|
31203
|
-
return
|
|
31105
|
+
return join10(lspCacheRoot(), encodeURIComponent(npmPackage));
|
|
31204
31106
|
}
|
|
31205
31107
|
function lspBinaryPath(npmPackage, binary) {
|
|
31206
|
-
return
|
|
31108
|
+
return join10(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
|
|
31207
31109
|
}
|
|
31208
31110
|
function lspBinDir(npmPackage) {
|
|
31209
|
-
return
|
|
31111
|
+
return join10(lspPackageDir(npmPackage), "node_modules", ".bin");
|
|
31210
31112
|
}
|
|
31211
31113
|
function isInstalled(npmPackage, binary) {
|
|
31212
31114
|
for (const candidate of lspBinaryCandidates(binary)) {
|
|
31213
31115
|
try {
|
|
31214
|
-
if (
|
|
31116
|
+
if (statSync5(join10(lspBinDir(npmPackage), candidate)).isFile())
|
|
31215
31117
|
return true;
|
|
31216
31118
|
} catch {}
|
|
31217
31119
|
}
|
|
@@ -31231,17 +31133,17 @@ function writeInstalledMetaIn(installDir, version2, sha256) {
|
|
|
31231
31133
|
installedAt: new Date().toISOString(),
|
|
31232
31134
|
...sha256 ? { sha256 } : {}
|
|
31233
31135
|
};
|
|
31234
|
-
|
|
31136
|
+
writeFileSync5(join10(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
|
|
31235
31137
|
} catch (err) {
|
|
31236
31138
|
log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
|
|
31237
31139
|
}
|
|
31238
31140
|
}
|
|
31239
31141
|
function readInstalledMetaIn(installDir) {
|
|
31240
|
-
const path3 =
|
|
31142
|
+
const path3 = join10(installDir, INSTALLED_META_FILE);
|
|
31241
31143
|
try {
|
|
31242
|
-
if (!
|
|
31144
|
+
if (!statSync5(path3).isFile())
|
|
31243
31145
|
return null;
|
|
31244
|
-
const raw =
|
|
31146
|
+
const raw = readFileSync7(path3, "utf8");
|
|
31245
31147
|
const parsed = JSON.parse(raw);
|
|
31246
31148
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
31247
31149
|
return null;
|
|
@@ -31261,7 +31163,7 @@ function readInstalledMeta(packageKey) {
|
|
|
31261
31163
|
return readInstalledMetaIn(lspPackageDir(packageKey));
|
|
31262
31164
|
}
|
|
31263
31165
|
function lockPath(npmPackage) {
|
|
31264
|
-
return
|
|
31166
|
+
return join10(lspPackageDir(npmPackage), ".aft-installing");
|
|
31265
31167
|
}
|
|
31266
31168
|
var STALE_LOCK_MS2 = 30 * 60 * 1000;
|
|
31267
31169
|
function acquireInstallLock(lockKey) {
|
|
@@ -31269,13 +31171,13 @@ function acquireInstallLock(lockKey) {
|
|
|
31269
31171
|
const lock = lockPath(lockKey);
|
|
31270
31172
|
const tryClaim = () => {
|
|
31271
31173
|
try {
|
|
31272
|
-
const fd =
|
|
31174
|
+
const fd = openSync5(lock, "wx");
|
|
31273
31175
|
try {
|
|
31274
|
-
|
|
31176
|
+
writeFileSync5(fd, `${process.pid}
|
|
31275
31177
|
${new Date().toISOString()}
|
|
31276
31178
|
`);
|
|
31277
31179
|
} finally {
|
|
31278
|
-
|
|
31180
|
+
closeSync5(fd);
|
|
31279
31181
|
}
|
|
31280
31182
|
return true;
|
|
31281
31183
|
} catch (err) {
|
|
@@ -31291,12 +31193,12 @@ ${new Date().toISOString()}
|
|
|
31291
31193
|
let owningPid = null;
|
|
31292
31194
|
let lockMtimeMs = 0;
|
|
31293
31195
|
try {
|
|
31294
|
-
const raw =
|
|
31196
|
+
const raw = readFileSync7(lock, "utf8");
|
|
31295
31197
|
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
31296
31198
|
const parsed = Number.parseInt(firstLine, 10);
|
|
31297
31199
|
if (Number.isFinite(parsed) && parsed > 0)
|
|
31298
31200
|
owningPid = parsed;
|
|
31299
|
-
lockMtimeMs =
|
|
31201
|
+
lockMtimeMs = statSync5(lock).mtimeMs;
|
|
31300
31202
|
} catch {
|
|
31301
31203
|
return tryClaim();
|
|
31302
31204
|
}
|
|
@@ -31309,7 +31211,7 @@ ${new Date().toISOString()}
|
|
|
31309
31211
|
}
|
|
31310
31212
|
log2(`[lsp] reclaiming install lock for ${lockKey} (owner_pid=${owningPid ?? "unknown"}, alive=${ownerAlive}, age_ms=${age})`);
|
|
31311
31213
|
try {
|
|
31312
|
-
|
|
31214
|
+
unlinkSync6(lock);
|
|
31313
31215
|
} catch {}
|
|
31314
31216
|
return tryClaim();
|
|
31315
31217
|
}
|
|
@@ -31329,7 +31231,7 @@ function releaseInstallLock(lockKey) {
|
|
|
31329
31231
|
try {
|
|
31330
31232
|
let owningPid = null;
|
|
31331
31233
|
try {
|
|
31332
|
-
const raw =
|
|
31234
|
+
const raw = readFileSync7(lock, "utf8");
|
|
31333
31235
|
const firstLine = raw.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
31334
31236
|
const parsed = Number.parseInt(firstLine, 10);
|
|
31335
31237
|
if (Number.isFinite(parsed) && parsed > 0)
|
|
@@ -31346,7 +31248,7 @@ function releaseInstallLock(lockKey) {
|
|
|
31346
31248
|
return;
|
|
31347
31249
|
}
|
|
31348
31250
|
try {
|
|
31349
|
-
|
|
31251
|
+
unlinkSync6(lock);
|
|
31350
31252
|
} catch (unlinkErr) {
|
|
31351
31253
|
const code = unlinkErr.code;
|
|
31352
31254
|
if (code !== "ENOENT") {
|
|
@@ -31368,9 +31270,9 @@ async function withInstallLock(lockKey, task) {
|
|
|
31368
31270
|
}
|
|
31369
31271
|
var VERSION_CHECK_FILE = ".aft-version-check";
|
|
31370
31272
|
function readVersionCheck(npmPackage) {
|
|
31371
|
-
const file2 =
|
|
31273
|
+
const file2 = join10(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
31372
31274
|
try {
|
|
31373
|
-
const raw =
|
|
31275
|
+
const raw = readFileSync7(file2, "utf8");
|
|
31374
31276
|
const parsed = JSON.parse(raw);
|
|
31375
31277
|
if (typeof parsed.last_checked === "string") {
|
|
31376
31278
|
return {
|
|
@@ -31385,12 +31287,12 @@ function readVersionCheck(npmPackage) {
|
|
|
31385
31287
|
}
|
|
31386
31288
|
function writeVersionCheck(npmPackage, latest) {
|
|
31387
31289
|
mkdirSync6(lspPackageDir(npmPackage), { recursive: true });
|
|
31388
|
-
const file2 =
|
|
31290
|
+
const file2 = join10(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
31389
31291
|
const record2 = {
|
|
31390
31292
|
last_checked: new Date().toISOString(),
|
|
31391
31293
|
latest_eligible: latest
|
|
31392
31294
|
};
|
|
31393
|
-
|
|
31295
|
+
writeFileSync5(file2, JSON.stringify(record2, null, 2));
|
|
31394
31296
|
}
|
|
31395
31297
|
function shouldRecheckVersion(record2, weeklyCheckIntervalMs = 7 * 24 * 60 * 60 * 1000) {
|
|
31396
31298
|
if (!record2)
|
|
@@ -31547,8 +31449,8 @@ var NPM_LSP_TABLE = [
|
|
|
31547
31449
|
];
|
|
31548
31450
|
|
|
31549
31451
|
// src/lsp-project-relevance.ts
|
|
31550
|
-
import { existsSync as
|
|
31551
|
-
import { join as
|
|
31452
|
+
import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync8 } from "node:fs";
|
|
31453
|
+
import { join as join11 } from "node:path";
|
|
31552
31454
|
var MAX_WALK_DIRS = 200;
|
|
31553
31455
|
var MAX_WALK_DEPTH = 4;
|
|
31554
31456
|
var NOISE_DIRS = new Set([
|
|
@@ -31565,7 +31467,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
|
|
|
31565
31467
|
if (!rootMarkers)
|
|
31566
31468
|
return false;
|
|
31567
31469
|
for (const marker of rootMarkers) {
|
|
31568
|
-
if (
|
|
31470
|
+
if (existsSync8(join11(projectRoot, marker)))
|
|
31569
31471
|
return true;
|
|
31570
31472
|
}
|
|
31571
31473
|
return false;
|
|
@@ -31589,7 +31491,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
|
|
|
31589
31491
|
}
|
|
31590
31492
|
function readPackageJson(projectRoot) {
|
|
31591
31493
|
try {
|
|
31592
|
-
const raw =
|
|
31494
|
+
const raw = readFileSync8(join11(projectRoot, "package.json"), "utf8");
|
|
31593
31495
|
const parsed = JSON.parse(raw);
|
|
31594
31496
|
if (typeof parsed !== "object" || parsed === null)
|
|
31595
31497
|
return null;
|
|
@@ -31619,7 +31521,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
|
|
|
31619
31521
|
for (const entry of entries) {
|
|
31620
31522
|
if (entry.isDirectory()) {
|
|
31621
31523
|
if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
|
|
31622
|
-
queue.push({ dir:
|
|
31524
|
+
queue.push({ dir: join11(current.dir, entry.name), depth: current.depth + 1 });
|
|
31623
31525
|
}
|
|
31624
31526
|
continue;
|
|
31625
31527
|
}
|
|
@@ -31746,9 +31648,9 @@ async function resolveTargetVersion(spec, config2, fetchImpl = fetch) {
|
|
|
31746
31648
|
}
|
|
31747
31649
|
function ensureInstallAnchor(cwd) {
|
|
31748
31650
|
try {
|
|
31749
|
-
const stub =
|
|
31750
|
-
if (!
|
|
31751
|
-
|
|
31651
|
+
const stub = join12(cwd, "package.json");
|
|
31652
|
+
if (!existsSync9(stub)) {
|
|
31653
|
+
writeFileSync6(stub, `${JSON.stringify({ name: "aft-lsp-cache", version: "0.0.0", private: true })}
|
|
31752
31654
|
`);
|
|
31753
31655
|
}
|
|
31754
31656
|
} catch (err) {
|
|
@@ -31756,18 +31658,18 @@ function ensureInstallAnchor(cwd) {
|
|
|
31756
31658
|
}
|
|
31757
31659
|
}
|
|
31758
31660
|
function runInstall(spec, version2, cwd, signal) {
|
|
31759
|
-
return new Promise((
|
|
31661
|
+
return new Promise((resolve7) => {
|
|
31760
31662
|
const target = `${spec.npm}@${version2}`;
|
|
31761
31663
|
log2(`[lsp] installing ${target} to ${cwd}`);
|
|
31762
31664
|
if (signal?.aborted) {
|
|
31763
31665
|
warn2(`[lsp] install ${target} aborted before spawn`);
|
|
31764
|
-
|
|
31666
|
+
resolve7(false);
|
|
31765
31667
|
return;
|
|
31766
31668
|
}
|
|
31767
31669
|
const npm = resolveNpm();
|
|
31768
31670
|
if (!npm) {
|
|
31769
31671
|
warn2(`[lsp] npm not found on PATH or known locations; cannot install ${target}`);
|
|
31770
|
-
|
|
31672
|
+
resolve7(false);
|
|
31771
31673
|
return;
|
|
31772
31674
|
}
|
|
31773
31675
|
ensureInstallAnchor(cwd);
|
|
@@ -31790,7 +31692,7 @@ function runInstall(spec, version2, cwd, signal) {
|
|
|
31790
31692
|
return;
|
|
31791
31693
|
settled = true;
|
|
31792
31694
|
cleanup();
|
|
31793
|
-
|
|
31695
|
+
resolve7(ok);
|
|
31794
31696
|
};
|
|
31795
31697
|
const onAbort = () => {
|
|
31796
31698
|
warn2(`[lsp] install ${target} aborted during shutdown`);
|
|
@@ -31891,7 +31793,7 @@ function cachedPackageDir(npmPackage) {
|
|
|
31891
31793
|
return lspBinDir(npmPackage).replace(/[\\/]node_modules[\\/]\.bin[\\/]?$/, "");
|
|
31892
31794
|
}
|
|
31893
31795
|
function hashInstalledBinary(spec) {
|
|
31894
|
-
return new Promise((
|
|
31796
|
+
return new Promise((resolve7, reject) => {
|
|
31895
31797
|
const candidates = process.platform === "win32" ? [
|
|
31896
31798
|
lspBinaryPath(spec.npm, spec.binary),
|
|
31897
31799
|
lspBinaryPath(spec.npm, `${spec.binary}.cmd`),
|
|
@@ -31901,7 +31803,7 @@ function hashInstalledBinary(spec) {
|
|
|
31901
31803
|
let pathToHash = null;
|
|
31902
31804
|
for (const p of candidates) {
|
|
31903
31805
|
try {
|
|
31904
|
-
if (
|
|
31806
|
+
if (statSync6(p).isFile()) {
|
|
31905
31807
|
pathToHash = p;
|
|
31906
31808
|
break;
|
|
31907
31809
|
}
|
|
@@ -31915,7 +31817,7 @@ function hashInstalledBinary(spec) {
|
|
|
31915
31817
|
const stream = createReadStream(pathToHash);
|
|
31916
31818
|
stream.on("error", reject);
|
|
31917
31819
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
31918
|
-
stream.on("end", () =>
|
|
31820
|
+
stream.on("end", () => resolve7(hash2.digest("hex")));
|
|
31919
31821
|
});
|
|
31920
31822
|
}
|
|
31921
31823
|
function installedBinaryPath(spec) {
|
|
@@ -31927,23 +31829,23 @@ function installedBinaryPath(spec) {
|
|
|
31927
31829
|
] : [lspBinaryPath(spec.npm, spec.binary)];
|
|
31928
31830
|
for (const candidate of candidates) {
|
|
31929
31831
|
try {
|
|
31930
|
-
if (
|
|
31832
|
+
if (statSync6(candidate).isFile())
|
|
31931
31833
|
return candidate;
|
|
31932
31834
|
} catch {}
|
|
31933
31835
|
}
|
|
31934
31836
|
return null;
|
|
31935
31837
|
}
|
|
31936
31838
|
function sha256OfFileSync(path3) {
|
|
31937
|
-
return createHash3("sha256").update(
|
|
31839
|
+
return createHash3("sha256").update(readFileSync9(path3)).digest("hex");
|
|
31938
31840
|
}
|
|
31939
31841
|
function quarantineCachedNpmInstall(spec, reason) {
|
|
31940
31842
|
const packageDir = lspPackageDir(spec.npm);
|
|
31941
|
-
const dest =
|
|
31843
|
+
const dest = join12(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
|
|
31942
31844
|
warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
31943
31845
|
try {
|
|
31944
|
-
mkdirSync7(
|
|
31945
|
-
|
|
31946
|
-
|
|
31846
|
+
mkdirSync7(join12(dest, ".."), { recursive: true });
|
|
31847
|
+
rmSync4(dest, { recursive: true, force: true });
|
|
31848
|
+
renameSync6(packageDir, dest);
|
|
31947
31849
|
} catch (err) {
|
|
31948
31850
|
warn2(`[lsp] tofu_mismatch ${spec.npm}: failed to quarantine cache entry: ${err}`);
|
|
31949
31851
|
}
|
|
@@ -32023,20 +31925,20 @@ import {
|
|
|
32023
31925
|
copyFileSync as copyFileSync4,
|
|
32024
31926
|
createReadStream as createReadStream2,
|
|
32025
31927
|
createWriteStream as createWriteStream3,
|
|
32026
|
-
existsSync as
|
|
31928
|
+
existsSync as existsSync10,
|
|
32027
31929
|
lstatSync as lstatSync2,
|
|
32028
31930
|
mkdirSync as mkdirSync8,
|
|
32029
31931
|
readdirSync as readdirSync4,
|
|
32030
|
-
readFileSync as
|
|
31932
|
+
readFileSync as readFileSync10,
|
|
32031
31933
|
readlinkSync as readlinkSync2,
|
|
32032
31934
|
realpathSync as realpathSync3,
|
|
32033
|
-
renameSync as
|
|
32034
|
-
rmSync as
|
|
32035
|
-
statSync as
|
|
32036
|
-
unlinkSync as
|
|
32037
|
-
writeFileSync as
|
|
31935
|
+
renameSync as renameSync7,
|
|
31936
|
+
rmSync as rmSync5,
|
|
31937
|
+
statSync as statSync7,
|
|
31938
|
+
unlinkSync as unlinkSync7,
|
|
31939
|
+
writeFileSync as writeFileSync7
|
|
32038
31940
|
} from "node:fs";
|
|
32039
|
-
import { dirname as dirname5, join as
|
|
31941
|
+
import { dirname as dirname5, join as join13, relative as relative3, resolve as resolve7 } from "node:path";
|
|
32040
31942
|
import { Readable as Readable3 } from "node:stream";
|
|
32041
31943
|
import { pipeline as pipeline3 } from "node:stream/promises";
|
|
32042
31944
|
|
|
@@ -32126,26 +32028,26 @@ function detectHostPlatform() {
|
|
|
32126
32028
|
|
|
32127
32029
|
// src/lsp-github-install.ts
|
|
32128
32030
|
function ghCacheRoot() {
|
|
32129
|
-
return
|
|
32031
|
+
return join13(aftCacheBase(), "lsp-binaries");
|
|
32130
32032
|
}
|
|
32131
32033
|
function ghPackageDir(spec) {
|
|
32132
|
-
return
|
|
32034
|
+
return join13(ghCacheRoot(), spec.id);
|
|
32133
32035
|
}
|
|
32134
32036
|
function ghBinDir(spec) {
|
|
32135
|
-
return
|
|
32037
|
+
return join13(ghPackageDir(spec), "bin");
|
|
32136
32038
|
}
|
|
32137
32039
|
function ghExtractDir(spec) {
|
|
32138
|
-
return
|
|
32040
|
+
return join13(ghPackageDir(spec), "extracted");
|
|
32139
32041
|
}
|
|
32140
32042
|
var INSTALLED_META_FILE2 = ".aft-installed";
|
|
32141
32043
|
function ghBinaryPath(spec, platform) {
|
|
32142
32044
|
const ext = platform === "win32" ? ".exe" : "";
|
|
32143
|
-
return
|
|
32045
|
+
return join13(ghBinDir(spec), `${spec.binary}${ext}`);
|
|
32144
32046
|
}
|
|
32145
32047
|
function isGithubInstalled(spec, platform) {
|
|
32146
32048
|
for (const candidate of ghBinaryCandidates(spec, platform)) {
|
|
32147
32049
|
try {
|
|
32148
|
-
if (
|
|
32050
|
+
if (statSync7(join13(ghBinDir(spec), candidate)).isFile())
|
|
32149
32051
|
return true;
|
|
32150
32052
|
} catch {}
|
|
32151
32053
|
}
|
|
@@ -32158,10 +32060,10 @@ function ghBinaryCandidates(spec, platform) {
|
|
|
32158
32060
|
}
|
|
32159
32061
|
function readGithubInstalledMetaIn(installDir) {
|
|
32160
32062
|
try {
|
|
32161
|
-
const path3 =
|
|
32162
|
-
if (!
|
|
32063
|
+
const path3 = join13(installDir, INSTALLED_META_FILE2);
|
|
32064
|
+
if (!statSync7(path3).isFile())
|
|
32163
32065
|
return null;
|
|
32164
|
-
const parsed = JSON.parse(
|
|
32066
|
+
const parsed = JSON.parse(readFileSync10(path3, "utf8"));
|
|
32165
32067
|
if (typeof parsed.version !== "string" || parsed.version.length === 0)
|
|
32166
32068
|
return null;
|
|
32167
32069
|
return {
|
|
@@ -32185,7 +32087,7 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
|
|
|
32185
32087
|
binarySha256,
|
|
32186
32088
|
...archiveSha256 ? { archiveSha256 } : {}
|
|
32187
32089
|
};
|
|
32188
|
-
|
|
32090
|
+
writeFileSync7(join13(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
|
|
32189
32091
|
} catch (err) {
|
|
32190
32092
|
warn2(`[lsp] failed to write github installed metadata in ${installDir}: ${err}`);
|
|
32191
32093
|
}
|
|
@@ -32193,16 +32095,16 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
|
|
|
32193
32095
|
var MAX_DOWNLOAD_BYTES3 = 256 * 1024 * 1024;
|
|
32194
32096
|
var MAX_EXTRACT_BYTES2 = 1024 * 1024 * 1024;
|
|
32195
32097
|
function sha256OfFile(path3) {
|
|
32196
|
-
return new Promise((
|
|
32098
|
+
return new Promise((resolve8, reject) => {
|
|
32197
32099
|
const hash2 = createHash4("sha256");
|
|
32198
32100
|
const stream = createReadStream2(path3);
|
|
32199
32101
|
stream.on("error", reject);
|
|
32200
32102
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
32201
|
-
stream.on("end", () =>
|
|
32103
|
+
stream.on("end", () => resolve8(hash2.digest("hex")));
|
|
32202
32104
|
});
|
|
32203
32105
|
}
|
|
32204
32106
|
function sha256OfFileSync2(path3) {
|
|
32205
|
-
return createHash4("sha256").update(
|
|
32107
|
+
return createHash4("sha256").update(readFileSync10(path3)).digest("hex");
|
|
32206
32108
|
}
|
|
32207
32109
|
async function fetchReleaseByTag(githubRepo, tag, fetchImpl, signal) {
|
|
32208
32110
|
const candidates = [];
|
|
@@ -32395,7 +32297,7 @@ async function downloadFile(url2, destPath, fetchImpl, assetSize, signal) {
|
|
|
32395
32297
|
await pipeline3(nodeStream, createWriteStream3(destPath), { signal: timeout.signal });
|
|
32396
32298
|
} catch (err) {
|
|
32397
32299
|
try {
|
|
32398
|
-
|
|
32300
|
+
unlinkSync7(destPath);
|
|
32399
32301
|
} catch {}
|
|
32400
32302
|
throw err;
|
|
32401
32303
|
} finally {
|
|
@@ -32434,7 +32336,7 @@ function validateExtraction(stagingRoot) {
|
|
|
32434
32336
|
throw new Error(`failed to read staging dir ${dir}: ${err}`);
|
|
32435
32337
|
}
|
|
32436
32338
|
for (const entry of entries) {
|
|
32437
|
-
const full =
|
|
32339
|
+
const full = join13(dir, entry);
|
|
32438
32340
|
let lst;
|
|
32439
32341
|
try {
|
|
32440
32342
|
lst = lstatSync2(full);
|
|
@@ -32455,7 +32357,7 @@ function validateExtraction(stagingRoot) {
|
|
|
32455
32357
|
throw new Error(`failed to realpath ${full}: ${err}`);
|
|
32456
32358
|
}
|
|
32457
32359
|
const rel = relative3(realStagingRoot, realFull);
|
|
32458
|
-
if (rel.startsWith("..") ||
|
|
32360
|
+
if (rel.startsWith("..") || resolve7(realStagingRoot, rel) !== realFull) {
|
|
32459
32361
|
throw new Error(`archive entry escapes staging root: ${full} → ${realFull} (zip-slip defense)`);
|
|
32460
32362
|
}
|
|
32461
32363
|
if (lst.isDirectory()) {
|
|
@@ -32502,7 +32404,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
|
|
|
32502
32404
|
const suffix = randomBytes(8).toString("hex");
|
|
32503
32405
|
const stagingDir = `${destDir}.staging-${suffix}`;
|
|
32504
32406
|
try {
|
|
32505
|
-
|
|
32407
|
+
rmSync5(stagingDir, { recursive: true, force: true });
|
|
32506
32408
|
} catch {}
|
|
32507
32409
|
mkdirSync8(stagingDir, { recursive: true });
|
|
32508
32410
|
try {
|
|
@@ -32510,24 +32412,24 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
|
|
|
32510
32412
|
runPlatformExtractor(archivePath, stagingDir, archiveType);
|
|
32511
32413
|
validateExtraction(stagingDir);
|
|
32512
32414
|
try {
|
|
32513
|
-
|
|
32415
|
+
rmSync5(destDir, { recursive: true, force: true });
|
|
32514
32416
|
} catch {}
|
|
32515
|
-
|
|
32417
|
+
renameSync7(stagingDir, destDir);
|
|
32516
32418
|
} catch (err) {
|
|
32517
32419
|
try {
|
|
32518
|
-
|
|
32420
|
+
rmSync5(stagingDir, { recursive: true, force: true });
|
|
32519
32421
|
} catch {}
|
|
32520
32422
|
throw err;
|
|
32521
32423
|
}
|
|
32522
32424
|
}
|
|
32523
32425
|
function quarantineCachedGithubInstall(spec, reason) {
|
|
32524
32426
|
const packageDir = ghPackageDir(spec);
|
|
32525
|
-
const dest =
|
|
32427
|
+
const dest = join13(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
|
|
32526
32428
|
warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
32527
32429
|
try {
|
|
32528
32430
|
mkdirSync8(dirname5(dest), { recursive: true });
|
|
32529
|
-
|
|
32530
|
-
|
|
32431
|
+
rmSync5(dest, { recursive: true, force: true });
|
|
32432
|
+
renameSync7(packageDir, dest);
|
|
32531
32433
|
} catch (err) {
|
|
32532
32434
|
warn2(`[lsp] tofu_mismatch ${spec.id}: failed to quarantine cache entry: ${err}`);
|
|
32533
32435
|
}
|
|
@@ -32535,9 +32437,9 @@ function quarantineCachedGithubInstall(spec, reason) {
|
|
|
32535
32437
|
function validateCachedGithubInstall(spec, platform) {
|
|
32536
32438
|
const packageDir = ghPackageDir(spec);
|
|
32537
32439
|
const meta3 = readGithubInstalledMetaIn(packageDir);
|
|
32538
|
-
const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) =>
|
|
32440
|
+
const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join13(ghBinDir(spec), candidate)).find((candidate) => {
|
|
32539
32441
|
try {
|
|
32540
|
-
return
|
|
32442
|
+
return statSync7(candidate).isFile();
|
|
32541
32443
|
} catch {
|
|
32542
32444
|
return false;
|
|
32543
32445
|
}
|
|
@@ -32613,7 +32515,7 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
|
|
|
32613
32515
|
}
|
|
32614
32516
|
const pkgDir = ghPackageDir(spec);
|
|
32615
32517
|
const extractDir = ghExtractDir(spec);
|
|
32616
|
-
const archivePath =
|
|
32518
|
+
const archivePath = join13(pkgDir, expected.name);
|
|
32617
32519
|
log2(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
|
|
32618
32520
|
try {
|
|
32619
32521
|
await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
|
|
@@ -32627,7 +32529,7 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
|
|
|
32627
32529
|
} catch (err) {
|
|
32628
32530
|
error2(`[lsp] hash ${spec.id} failed: ${err}`);
|
|
32629
32531
|
try {
|
|
32630
|
-
|
|
32532
|
+
unlinkSync7(archivePath);
|
|
32631
32533
|
} catch {}
|
|
32632
32534
|
return null;
|
|
32633
32535
|
}
|
|
@@ -32638,7 +32540,7 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
|
|
|
32638
32540
|
if (previousArchiveSha256 !== archiveSha256) {
|
|
32639
32541
|
error2(`[lsp] ${spec.id} ${tag}: TOFU sha256 mismatch — refusing install. ` + `Previously installed archive sha256=${previousArchiveSha256}, downloaded sha256=${archiveSha256}. ` + `This means the published release for tag ${tag} changed. Investigate before proceeding.`);
|
|
32640
32542
|
try {
|
|
32641
|
-
|
|
32543
|
+
unlinkSync7(archivePath);
|
|
32642
32544
|
} catch {}
|
|
32643
32545
|
return null;
|
|
32644
32546
|
}
|
|
@@ -32650,11 +32552,11 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
|
|
|
32650
32552
|
return null;
|
|
32651
32553
|
} finally {
|
|
32652
32554
|
try {
|
|
32653
|
-
|
|
32555
|
+
unlinkSync7(archivePath);
|
|
32654
32556
|
} catch {}
|
|
32655
32557
|
}
|
|
32656
|
-
const innerBinaryPath =
|
|
32657
|
-
if (!
|
|
32558
|
+
const innerBinaryPath = join13(extractDir, spec.binaryPathInArchive(platform, arch, version2));
|
|
32559
|
+
if (!existsSync10(innerBinaryPath)) {
|
|
32658
32560
|
error2(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
|
|
32659
32561
|
return null;
|
|
32660
32562
|
}
|
|
@@ -32738,7 +32640,7 @@ function runGithubAutoInstall(relevantServers, config2, fetchImpl = fetch) {
|
|
|
32738
32640
|
if (!host) {
|
|
32739
32641
|
for (const spec of GITHUB_LSP_TABLE) {
|
|
32740
32642
|
try {
|
|
32741
|
-
if (
|
|
32643
|
+
if (existsSync10(ghBinDir(spec))) {
|
|
32742
32644
|
cachedBinDirs.push(ghBinDir(spec));
|
|
32743
32645
|
}
|
|
32744
32646
|
} catch {}
|
|
@@ -32908,9 +32810,13 @@ function warningTitle(warning) {
|
|
|
32908
32810
|
return "LSP binary is missing";
|
|
32909
32811
|
case "config_parse_failed":
|
|
32910
32812
|
return "Config failed to parse";
|
|
32813
|
+
case "config_key_dropped":
|
|
32814
|
+
return "Config key ignored";
|
|
32911
32815
|
}
|
|
32912
32816
|
}
|
|
32913
32817
|
function formatConfigureWarning(warning) {
|
|
32818
|
+
if (warning.kind === "config_key_dropped")
|
|
32819
|
+
return `${WARNING_MARKER} ${warning.hint}`;
|
|
32914
32820
|
const details = [];
|
|
32915
32821
|
if (warning.language)
|
|
32916
32822
|
details.push(`language: ${warning.language}`);
|
|
@@ -33053,7 +32959,7 @@ function renderScreen(state, rows = state.rows, cols = state.cols) {
|
|
|
33053
32959
|
`);
|
|
33054
32960
|
}
|
|
33055
32961
|
function writeTerminal(terminal, data) {
|
|
33056
|
-
return new Promise((
|
|
32962
|
+
return new Promise((resolve8) => terminal.write(data, resolve8));
|
|
33057
32963
|
}
|
|
33058
32964
|
|
|
33059
32965
|
// src/shutdown-hooks.ts
|
|
@@ -33110,8 +33016,8 @@ function installProcessHandlers() {
|
|
|
33110
33016
|
}
|
|
33111
33017
|
signalShutdownStarted = true;
|
|
33112
33018
|
process.exitCode = SIGNAL_EXIT_CODES[sig];
|
|
33113
|
-
const timeout = new Promise((
|
|
33114
|
-
setTimeout(
|
|
33019
|
+
const timeout = new Promise((resolve8) => {
|
|
33020
|
+
setTimeout(resolve8, SIGNAL_CLEANUP_TIMEOUT_MS);
|
|
33115
33021
|
});
|
|
33116
33022
|
Promise.race([runCleanups(sig), timeout]).finally(() => {
|
|
33117
33023
|
process.exit(SIGNAL_EXIT_CODES[sig]);
|
|
@@ -33154,7 +33060,7 @@ import { Type as Type3 } from "typebox";
|
|
|
33154
33060
|
// src/tools/hoisted.ts
|
|
33155
33061
|
import { stat } from "node:fs/promises";
|
|
33156
33062
|
import { homedir as homedir11 } from "node:os";
|
|
33157
|
-
import { isAbsolute as
|
|
33063
|
+
import { isAbsolute as isAbsolute5, relative as relative4, resolve as resolve8, sep } from "node:path";
|
|
33158
33064
|
import {
|
|
33159
33065
|
renderDiff
|
|
33160
33066
|
} from "@earendil-works/pi-coding-agent";
|
|
@@ -33269,7 +33175,7 @@ function diagnosticsOnEditDefault(ctx) {
|
|
|
33269
33175
|
}
|
|
33270
33176
|
function containsPath(parent, child) {
|
|
33271
33177
|
const rel = relative4(parent, child);
|
|
33272
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
33178
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute5(rel);
|
|
33273
33179
|
}
|
|
33274
33180
|
function expandTilde2(path3) {
|
|
33275
33181
|
if (!path3 || !path3.startsWith("~"))
|
|
@@ -33277,13 +33183,13 @@ function expandTilde2(path3) {
|
|
|
33277
33183
|
if (path3 === "~")
|
|
33278
33184
|
return homedir11();
|
|
33279
33185
|
if (path3.startsWith(`~${sep}`) || path3.startsWith("~/")) {
|
|
33280
|
-
return
|
|
33186
|
+
return resolve8(homedir11(), path3.slice(2));
|
|
33281
33187
|
}
|
|
33282
33188
|
return path3;
|
|
33283
33189
|
}
|
|
33284
33190
|
function absoluteSearchPath(cwd, target) {
|
|
33285
33191
|
const expanded = expandTilde2(target);
|
|
33286
|
-
return
|
|
33192
|
+
return isAbsolute5(expanded) ? expanded : resolve8(cwd, expanded);
|
|
33287
33193
|
}
|
|
33288
33194
|
async function searchPathExists(cwd, target) {
|
|
33289
33195
|
try {
|
|
@@ -33339,7 +33245,7 @@ async function assertExternalDirectoryPermission(extCtx, target, options = {}) {
|
|
|
33339
33245
|
if (!target)
|
|
33340
33246
|
return;
|
|
33341
33247
|
const expanded = expandTilde2(target);
|
|
33342
|
-
const absoluteTarget =
|
|
33248
|
+
const absoluteTarget = isAbsolute5(expanded) ? expanded : resolve8(extCtx.cwd, expanded);
|
|
33343
33249
|
if (containsPath(extCtx.cwd, absoluteTarget))
|
|
33344
33250
|
return;
|
|
33345
33251
|
if (options.restrictToProjectRoot === false)
|
|
@@ -33487,7 +33393,7 @@ function registerHoistedTools(pi, ctx, surface) {
|
|
|
33487
33393
|
diagnostics: diagnosticsOnEditDefault(ctx),
|
|
33488
33394
|
include_diff_content: true
|
|
33489
33395
|
};
|
|
33490
|
-
if (params.replaceAll
|
|
33396
|
+
if (coerceBoolean(params.replaceAll))
|
|
33491
33397
|
req.replace_all = true;
|
|
33492
33398
|
const occurrence = coerceOptionalInt(params.occurrence, "occurrence", 0, Number.MAX_SAFE_INTEGER);
|
|
33493
33399
|
if (occurrence !== undefined)
|
|
@@ -34108,7 +34014,7 @@ function registerAstTools(pi, ctx, surface) {
|
|
|
34108
34014
|
req.paths = paths;
|
|
34109
34015
|
if (!isEmptyParam(params.globs))
|
|
34110
34016
|
req.globs = params.globs;
|
|
34111
|
-
req.dry_run = params.dryRun
|
|
34017
|
+
req.dry_run = coerceBoolean(params.dryRun);
|
|
34112
34018
|
const response = await callBridge(bridge, "ast_replace", req, extCtx);
|
|
34113
34019
|
return textResult(response.text ?? JSON.stringify(response));
|
|
34114
34020
|
},
|
|
@@ -34259,8 +34165,8 @@ function registerBashTool(pi, ctx, aftSearchRegistered = false) {
|
|
|
34259
34165
|
const spawnHook = getBashSpawnHook(pi);
|
|
34260
34166
|
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";
|
|
34261
34167
|
const bashCfg = resolveBashConfig(ctx.config);
|
|
34262
|
-
const compressionSentence = bashCfg.compress ? " Output is compressed by default; pass `compressed: false` for raw output." : "";
|
|
34263
|
-
const tasksSentence = bashCfg.background ? '
|
|
34168
|
+
const compressionSentence = bashCfg.compress ? " 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`." : "";
|
|
34169
|
+
const tasksSentence = bashCfg.background ? ' Commands run in the foreground and return inline; a long-running one auto-promotes to background and delivers a completion reminder when it finishes — so for the common "I am waiting on this result" case, just run it and wait, no flags needed. 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({ output_mode: "screen" })` plus `bash_write`.' : " Commands run in the foreground to completion; `timeout` is the hard kill cap (default 30 minutes).";
|
|
34264
34170
|
pi.registerTool({
|
|
34265
34171
|
name: "bash",
|
|
34266
34172
|
label: "bash",
|
|
@@ -34270,7 +34176,8 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
34270
34176
|
promptSnippet: bashCfg.background ? "Run shell commands (timeout in milliseconds; supports workdir, background tasks, compressed output, PTY mode)" : "Run shell commands (timeout in milliseconds; supports workdir and compressed output)",
|
|
34271
34177
|
promptGuidelines: [
|
|
34272
34178
|
`DO NOT use bash for code search or exploration — ${searchSteer}.`,
|
|
34273
|
-
"Set compressed: false when you need ANSI color codes in the output."
|
|
34179
|
+
"Set compressed: false when you need ANSI color codes in the output.",
|
|
34180
|
+
"Piped commands run verbatim and show the pipeline's output; run test/build tools without pipes when you need AFT's summary."
|
|
34274
34181
|
],
|
|
34275
34182
|
parameters: bashParamsForConfig(bashCfg.background),
|
|
34276
34183
|
async execute(_toolCallId, params, _signal, onUpdate, extCtx) {
|
|
@@ -34281,8 +34188,9 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
34281
34188
|
const timeout = coerceOptionalInt(params.timeout, "timeout", 1, Number.MAX_SAFE_INTEGER);
|
|
34282
34189
|
const ptyRows = backgroundDisabled ? undefined : coerceOptionalInt(params.ptyRows, "ptyRows", 1, 60);
|
|
34283
34190
|
const ptyCols = backgroundDisabled ? undefined : coerceOptionalInt(params.ptyCols, "ptyCols", 1, 140);
|
|
34284
|
-
const
|
|
34285
|
-
const
|
|
34191
|
+
const compressed = coerceBoolean(params.compressed, true);
|
|
34192
|
+
const requestedPty = !backgroundDisabled && coerceBoolean(params.pty);
|
|
34193
|
+
const effectiveBackground = !backgroundDisabled && (coerceBoolean(params.background) || requestedPty);
|
|
34286
34194
|
const effectiveTimeout = effectiveBackground || backgroundDisabled ? timeout : resolveBashKillTimeout(timeout, foregroundWaitMs);
|
|
34287
34195
|
let spawnContext = {
|
|
34288
34196
|
command: params.command,
|
|
@@ -34295,9 +34203,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
34295
34203
|
throw new Error(`BashSpawnHook failed: ${hookErr instanceof Error ? hookErr.message : String(hookErr)}`);
|
|
34296
34204
|
}
|
|
34297
34205
|
}
|
|
34298
|
-
const
|
|
34299
|
-
const pipeStrip = maybeStripCompressorPipe(spawnContext.command, compressionEnabled);
|
|
34300
|
-
const bridgeCommand = pipeStrip.command;
|
|
34206
|
+
const bridgeCommand = spawnContext.command;
|
|
34301
34207
|
let streamed = "";
|
|
34302
34208
|
const response = await callBashBridge(bridge, "bash", {
|
|
34303
34209
|
command: bridgeCommand,
|
|
@@ -34307,7 +34213,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
34307
34213
|
description: params.description,
|
|
34308
34214
|
background: effectiveBackground,
|
|
34309
34215
|
notify_on_completion: effectiveBackground,
|
|
34310
|
-
compressed
|
|
34216
|
+
compressed,
|
|
34311
34217
|
pty: requestedPty,
|
|
34312
34218
|
pty_rows: ptyRows,
|
|
34313
34219
|
pty_cols: ptyCols
|
|
@@ -34330,7 +34236,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
34330
34236
|
if (response.status === "running" && taskId) {
|
|
34331
34237
|
if (effectiveBackground) {
|
|
34332
34238
|
trackBgTask(resolveSessionId(extCtx), taskId);
|
|
34333
|
-
return bashResult(
|
|
34239
|
+
return bashResult(formatBackgroundLaunch(taskId, requestedPty), { task_id: taskId });
|
|
34334
34240
|
}
|
|
34335
34241
|
const waitTimeoutMs = backgroundDisabled ? effectiveTimeout ?? DEFAULT_HARD_TIMEOUT_MS : effectiveTimeout !== undefined ? Math.min(effectiveTimeout, foregroundWaitMs) : foregroundWaitMs;
|
|
34336
34242
|
const startedAt = Date.now();
|
|
@@ -34340,7 +34246,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
34340
34246
|
throw new Error(status.message ?? "bash_status failed");
|
|
34341
34247
|
}
|
|
34342
34248
|
if (isTerminalStatus(status.status)) {
|
|
34343
|
-
return bashResult(
|
|
34249
|
+
return bashResult(withBashHints(formatForegroundResult(status), bridgeCommand, aftSearchRegistered, extCtx.cwd), {
|
|
34344
34250
|
exit_code: status.exit_code,
|
|
34345
34251
|
duration_ms: status.duration_ms,
|
|
34346
34252
|
truncated: status.output_truncated,
|
|
@@ -34358,7 +34264,9 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
34358
34264
|
throw new Error(promoted.message ?? "bash_promote failed");
|
|
34359
34265
|
}
|
|
34360
34266
|
trackBgTask(resolveSessionId(extCtx), taskId);
|
|
34361
|
-
return bashResult(
|
|
34267
|
+
return bashResult(formatPromotionMessage(taskId, effectiveTimeout, foregroundWaitMs), {
|
|
34268
|
+
task_id: taskId
|
|
34269
|
+
});
|
|
34362
34270
|
}
|
|
34363
34271
|
await sleep(FOREGROUND_POLL_INTERVAL_MS);
|
|
34364
34272
|
}
|
|
@@ -34371,7 +34279,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
34371
34279
|
task_id: taskId
|
|
34372
34280
|
};
|
|
34373
34281
|
const output = response.output ?? "";
|
|
34374
|
-
return bashResult(
|
|
34282
|
+
return bashResult(withBashHints(output, bridgeCommand, aftSearchRegistered, extCtx.cwd), details);
|
|
34375
34283
|
},
|
|
34376
34284
|
renderCall(args, theme, context) {
|
|
34377
34285
|
return renderBashCall(args?.command, args?.description, theme, context);
|
|
@@ -34425,13 +34333,13 @@ function createBashWatchTool(ctx) {
|
|
|
34425
34333
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
34426
34334
|
const bridge = bridgeFor(ctx, extCtx.cwd);
|
|
34427
34335
|
const waitFor = parseWaitPattern(params.pattern);
|
|
34428
|
-
if (params.background
|
|
34336
|
+
if (coerceBoolean(params.background)) {
|
|
34429
34337
|
if (!waitFor) {
|
|
34430
34338
|
throw new Error("invalid_request: Use auto-reminder; bash_watch without pattern in async mode is redundant");
|
|
34431
34339
|
}
|
|
34432
34340
|
const notifyParams = {
|
|
34433
34341
|
task_id: params.task_id,
|
|
34434
|
-
once: params.once
|
|
34342
|
+
once: coerceBoolean(params.once, true)
|
|
34435
34343
|
};
|
|
34436
34344
|
if (waitFor.kind === "regex")
|
|
34437
34345
|
notifyParams.regex = waitFor.source;
|
|
@@ -34457,7 +34365,7 @@ A notification will fire when the pattern matches or the task exits.`, watchDeta
|
|
|
34457
34365
|
}
|
|
34458
34366
|
const data = await waitForBashStatus(ctx, bridge, extCtx, params.task_id, undefined, waitFor, true, Math.min(coerceOptionalInt(params.timeout_ms, "timeout_ms", 1, MAX_BASH_STATUS_WAIT_TIMEOUT_MS) ?? DEFAULT_BASH_STATUS_WAIT_TIMEOUT_MS, MAX_BASH_STATUS_WAIT_TIMEOUT_MS));
|
|
34459
34367
|
if (data.waited?.reason === "user_message") {
|
|
34460
|
-
const convertedText = await convertToAsyncWatchOnAbort(bridge, extCtx, params.task_id, waitFor, params.once
|
|
34368
|
+
const convertedText = await convertToAsyncWatchOnAbort(bridge, extCtx, params.task_id, waitFor, coerceBoolean(params.once, true));
|
|
34461
34369
|
return textResult(convertedText, { waited: data.waited });
|
|
34462
34370
|
}
|
|
34463
34371
|
const text = await formatBashStatus(extCtx, params.task_id, data, undefined);
|
|
@@ -35059,7 +34967,7 @@ function registerFsTools(pi, ctx, surface) {
|
|
|
35059
34967
|
const bridge = bridgeFor(ctx, extCtx.cwd);
|
|
35060
34968
|
const response = await callBridge(bridge, "delete_file", {
|
|
35061
34969
|
files,
|
|
35062
|
-
recursive: params.recursive
|
|
34970
|
+
recursive: coerceBoolean(params.recursive)
|
|
35063
34971
|
}, extCtx);
|
|
35064
34972
|
const deletedEntries = response.deleted ?? [];
|
|
35065
34973
|
const skipped = response.skipped_files ?? [];
|
|
@@ -35500,7 +35408,7 @@ function registerInspectTool(pi, ctx) {
|
|
|
35500
35408
|
pi.registerTool({
|
|
35501
35409
|
name: "aft_inspect",
|
|
35502
35410
|
label: "inspect",
|
|
35503
|
-
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)
|
|
35411
|
+
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. Pi may still trigger a deduped background warmup for categories that remain pending.\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.
|
|
35504
35412
|
|
|
35505
35413
|
` + "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.",
|
|
35506
35414
|
parameters: InspectParams,
|
|
@@ -35509,7 +35417,9 @@ function registerInspectTool(pi, ctx) {
|
|
|
35509
35417
|
const sections = normalizeStringOrArray(params.sections);
|
|
35510
35418
|
const scope = await resolveAndGateScope(extCtx, ctx, normalizeStringOrArray(params.scope));
|
|
35511
35419
|
const topK = validateOptionalTopK(params.topK);
|
|
35512
|
-
const response = await callBridge(bridge, "inspect", { sections, scope, topK }, extCtx
|
|
35420
|
+
const response = await callBridge(bridge, "inspect", { sections, scope, topK }, extCtx, {
|
|
35421
|
+
keepBridgeOnTimeout: true
|
|
35422
|
+
});
|
|
35513
35423
|
runPendingTier2Categories(bridge, tier2RefreshCategories(response), extCtx);
|
|
35514
35424
|
const body = response.text;
|
|
35515
35425
|
if (typeof body === "string") {
|
|
@@ -35809,8 +35719,8 @@ Pass a single \`target\`:
|
|
|
35809
35719
|
parameters: OutlineParams,
|
|
35810
35720
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
35811
35721
|
const bridge = bridgeFor(ctx, extCtx.cwd);
|
|
35812
|
-
const target = params.target;
|
|
35813
|
-
const filesMode = params.files
|
|
35722
|
+
const target = coerceTargetParam(params.target);
|
|
35723
|
+
const filesMode = coerceBoolean(params.files);
|
|
35814
35724
|
const isArray = Array.isArray(target) && target.length > 0;
|
|
35815
35725
|
if (filesMode) {
|
|
35816
35726
|
if (Array.isArray(target)) {
|
|
@@ -35908,7 +35818,7 @@ Pass a single \`target\`:
|
|
|
35908
35818
|
const hasUrl = !isEmptyParam(params.url);
|
|
35909
35819
|
const hasTargets = hasTargetsProvided(params.targets);
|
|
35910
35820
|
const hasSymbols = !isEmptyParam(params.symbols);
|
|
35911
|
-
const wantCallgraph = params.callgraph
|
|
35821
|
+
const wantCallgraph = coerceBoolean(params.callgraph);
|
|
35912
35822
|
if (hasTargets) {
|
|
35913
35823
|
if (hasFilePath || hasUrl || hasSymbols) {
|
|
35914
35824
|
throw new Error("'targets' is mutually exclusive with 'filePath', 'url', and 'symbols'");
|
|
@@ -36430,6 +36340,10 @@ var SearchParams2 = Type13.Object({
|
|
|
36430
36340
|
Type13.Literal("auto")
|
|
36431
36341
|
], {
|
|
36432
36342
|
description: "Optional routing hint. Defaults to 'auto'."
|
|
36343
|
+
})),
|
|
36344
|
+
includeTests: Type13.Optional(Type13.Boolean({
|
|
36345
|
+
default: false,
|
|
36346
|
+
description: "Include test files (*.test.*, *_test.rs, __tests__/, …) plus test-support, fixture, mock, snapshot, and corpus files. Defaults to false."
|
|
36433
36347
|
}))
|
|
36434
36348
|
});
|
|
36435
36349
|
function buildSemanticSections(args, payload, theme) {
|
|
@@ -36535,6 +36449,8 @@ function registerSemanticTool(pi, ctx) {
|
|
|
36535
36449
|
req.top_k = params.topK;
|
|
36536
36450
|
if (params.hint !== undefined)
|
|
36537
36451
|
req.hint = params.hint;
|
|
36452
|
+
if (params.includeTests !== undefined)
|
|
36453
|
+
req.include_tests = params.includeTests;
|
|
36538
36454
|
const response = await callBridge(bridge, "semantic_search", req, extCtx);
|
|
36539
36455
|
let agentText = response.text ?? "No results.";
|
|
36540
36456
|
const extra = extraAgentHonestyNote(response);
|
|
@@ -36568,7 +36484,7 @@ function buildWorkflowHints(opts) {
|
|
|
36568
36484
|
const hasBgBash = opts.bashBackgroundEnabled && hasBash && !opts.absentTools.has("bash_status");
|
|
36569
36485
|
if (hasBash && opts.bashCompressionEnabled) {
|
|
36570
36486
|
sections.push([
|
|
36571
|
-
"**Test/build output**: bash output is auto-compressed
|
|
36487
|
+
"**Test/build output**: bash output is auto-compressed for non-piped commands. Piped commands run verbatim and show the pipeline's output. For AFT's test/build summary, run the runner without filters:",
|
|
36572
36488
|
"- `bun test | grep fail` → run `bun test`",
|
|
36573
36489
|
"- `cargo test 2>&1 | tail -20` → run `cargo test`",
|
|
36574
36490
|
"- `npm run build | head -50` → run `npm run build`"
|
|
@@ -36607,11 +36523,9 @@ function buildWorkflowHints(opts) {
|
|
|
36607
36523
|
}
|
|
36608
36524
|
if (hasBgBash) {
|
|
36609
36525
|
sections.push([
|
|
36610
|
-
`**Long-running commands** (builds, installs, full test suites): \`${bashName}({
|
|
36611
|
-
"
|
|
36612
|
-
"
|
|
36613
|
-
"3. Want to react to a specific early output line → async `bash_watch` (background:true + pattern).",
|
|
36614
|
-
"Never loop `bash_status` to wait — it's a one-shot inspector, not a wait primitive."
|
|
36526
|
+
`**Long-running commands** (builds, installs, full test suites): run them in the FOREGROUND — \`${bashName}({ command })\` waits and returns the result in ONE step, and if it outlives the short wait window it auto-promotes to background and delivers a completion reminder when it finishes. Don't reach for \`background: true\` for the common "I'm waiting on this result" case — that costs an extra turn.`,
|
|
36527
|
+
"- `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.",
|
|
36528
|
+
"- `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."
|
|
36615
36529
|
].join(`
|
|
36616
36530
|
`));
|
|
36617
36531
|
sections.push(`**PTY / interactive commands**: PTY mode is for interactive REPLs and terminal apps (python, node, bash itself, vim). Start with \`${bashName}({ command: "python", pty: true, background: true })\`, read the screen with \`bash_status({ task_id, output_mode: "screen" })\`, and send input with \`bash_write({ task_id, input: "..." })\`.`);
|
|
@@ -36713,11 +36627,12 @@ var PLUGIN_VERSION = (() => {
|
|
|
36713
36627
|
return "0.0.0";
|
|
36714
36628
|
}
|
|
36715
36629
|
})();
|
|
36716
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
36630
|
+
var ANNOUNCEMENT_VERSION = "0.40.0";
|
|
36717
36631
|
var ANNOUNCEMENT_FEATURES = [
|
|
36718
|
-
"
|
|
36719
|
-
"
|
|
36720
|
-
"
|
|
36632
|
+
"Groundwork for Subconscious, the CortexKit daemon: configuration now lives in one place under ~/.config/cortexkit/ and <project>/.cortexkit/ (auto-migrated). The daemon integration is dormant — nothing changes in how you run AFT today.",
|
|
36633
|
+
"Bash output never hides a failure: piped commands run exactly as written with their real exit status, cancelled tasks report as failed, and a failing run is never compressed to a clean-looking summary.",
|
|
36634
|
+
"The top aft_search result is now the complete, ready-to-edit symbol (no re-read needed); test files are hidden from results by default.",
|
|
36635
|
+
"format_on_edit is now off by default, and bash commands default to the foreground."
|
|
36721
36636
|
];
|
|
36722
36637
|
var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/DSa65w8wuf";
|
|
36723
36638
|
var ALL_ONLY_TOOLS = new Set(["aft_callgraph", "aft_delete", "aft_move", "aft_refactor"]);
|
|
@@ -36726,11 +36641,25 @@ function isConfigureWarning(value) {
|
|
|
36726
36641
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
36727
36642
|
return false;
|
|
36728
36643
|
const warning = value;
|
|
36729
|
-
return (warning.kind === "formatter_not_installed" || warning.kind === "checker_not_installed" || warning.kind === "lsp_binary_missing" || warning.kind === "config_parse_failed") && typeof warning.hint === "string";
|
|
36644
|
+
return (warning.kind === "formatter_not_installed" || warning.kind === "checker_not_installed" || warning.kind === "lsp_binary_missing" || warning.kind === "config_parse_failed" || warning.kind === "config_key_dropped") && typeof warning.hint === "string";
|
|
36730
36645
|
}
|
|
36731
36646
|
function coerceConfigureWarnings(warnings) {
|
|
36732
36647
|
return warnings.filter(isConfigureWarning);
|
|
36733
36648
|
}
|
|
36649
|
+
function isDroppedConfigKey(value) {
|
|
36650
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
36651
|
+
return false;
|
|
36652
|
+
const dropped = value;
|
|
36653
|
+
return typeof dropped.key === "string" && typeof dropped.tier === "string" && typeof dropped.reason === "string";
|
|
36654
|
+
}
|
|
36655
|
+
function coerceDroppedKeyWarnings(droppedKeys) {
|
|
36656
|
+
if (!Array.isArray(droppedKeys))
|
|
36657
|
+
return [];
|
|
36658
|
+
return formatDroppedKeyWarnings(droppedKeys.filter(isDroppedConfigKey)).map((hint) => ({
|
|
36659
|
+
kind: "config_key_dropped",
|
|
36660
|
+
hint
|
|
36661
|
+
}));
|
|
36662
|
+
}
|
|
36734
36663
|
function drainPendingEagerWarnings(projectRoot) {
|
|
36735
36664
|
const pending = pendingEagerWarnings.get(projectRoot) ?? [];
|
|
36736
36665
|
pendingEagerWarnings.delete(projectRoot);
|
|
@@ -36757,7 +36686,10 @@ function bridgeDirectoryFromCallback(bridge, fallback) {
|
|
|
36757
36686
|
return typeof cwd === "string" && cwd.length > 0 ? cwd : fallback;
|
|
36758
36687
|
}
|
|
36759
36688
|
async function handleConfigureWarningsForSession(context) {
|
|
36760
|
-
const validWarnings =
|
|
36689
|
+
const validWarnings = [
|
|
36690
|
+
...coerceConfigureWarnings(context.warnings),
|
|
36691
|
+
...coerceDroppedKeyWarnings(context.configDroppedKeys)
|
|
36692
|
+
];
|
|
36761
36693
|
if (!context.sessionId) {
|
|
36762
36694
|
if (validWarnings.length === 0)
|
|
36763
36695
|
return;
|
|
@@ -36855,6 +36787,25 @@ async function src_default(pi) {
|
|
|
36855
36787
|
return;
|
|
36856
36788
|
}
|
|
36857
36789
|
await ensureStorageMigrated({ harness: "pi", binaryPath, logger: bridgeLogger });
|
|
36790
|
+
const deliverConfigMigrationWarnings = (messages) => {
|
|
36791
|
+
for (const message of messages) {
|
|
36792
|
+
const notify = pi.ui?.notify;
|
|
36793
|
+
if (typeof notify === "function") {
|
|
36794
|
+
try {
|
|
36795
|
+
notify(message, "warning");
|
|
36796
|
+
continue;
|
|
36797
|
+
} catch (err) {
|
|
36798
|
+
warn2(`[config] failed to deliver migration notification: ${err}`);
|
|
36799
|
+
}
|
|
36800
|
+
}
|
|
36801
|
+
try {
|
|
36802
|
+
process.stderr.write(`
|
|
36803
|
+
[AFT] ${message}
|
|
36804
|
+
`);
|
|
36805
|
+
} catch {}
|
|
36806
|
+
}
|
|
36807
|
+
};
|
|
36808
|
+
deliverConfigMigrationWarnings(migrateAftConfigLocations(process.cwd(), bridgeLogger).flatMap((result) => result.warnings));
|
|
36858
36809
|
const config2 = loadAftConfig(process.cwd());
|
|
36859
36810
|
enqueueConfigParseWarnings(process.cwd(), getConfigLoadErrors());
|
|
36860
36811
|
const storageDir = resolveCortexKitStorageRoot();
|
|
@@ -36865,10 +36816,9 @@ async function src_default(pi) {
|
|
|
36865
36816
|
return null;
|
|
36866
36817
|
});
|
|
36867
36818
|
}
|
|
36868
|
-
const configOverrides =
|
|
36869
|
-
|
|
36870
|
-
|
|
36871
|
-
configOverrides.storage_dir = storageDir;
|
|
36819
|
+
const configOverrides = buildConfigTierConfigureParams(process.cwd(), {
|
|
36820
|
+
storage_dir: storageDir
|
|
36821
|
+
});
|
|
36872
36822
|
try {
|
|
36873
36823
|
const lspAutoInstall = config2.lsp?.auto_install ?? true;
|
|
36874
36824
|
const lspGraceDays = config2.lsp?.grace_days ?? 7;
|
|
@@ -36936,7 +36886,7 @@ ${lines}
|
|
|
36936
36886
|
errorPrefix: "[aft-pi]",
|
|
36937
36887
|
minVersion: PLUGIN_VERSION,
|
|
36938
36888
|
onVersionMismatch: createVersionMismatchHandler(() => pool),
|
|
36939
|
-
onConfigureWarnings: ({ projectRoot, sessionId, client, warnings }) => {
|
|
36889
|
+
onConfigureWarnings: ({ projectRoot, sessionId, client, warnings, configDroppedKeys }) => {
|
|
36940
36890
|
const bridge = pool.getActiveBridgeForRoot(projectRoot);
|
|
36941
36891
|
if (!bridge)
|
|
36942
36892
|
return;
|
|
@@ -36948,6 +36898,7 @@ ${lines}
|
|
|
36948
36898
|
client,
|
|
36949
36899
|
bridge,
|
|
36950
36900
|
warnings: [...pendingWarnings, ...warnings],
|
|
36901
|
+
configDroppedKeys,
|
|
36951
36902
|
storageDir,
|
|
36952
36903
|
pluginVersion: PLUGIN_VERSION
|
|
36953
36904
|
});
|
|
@@ -37007,7 +36958,7 @@ ${lines}
|
|
|
37007
36958
|
if (onnxRuntimePromise) {
|
|
37008
36959
|
await Promise.race([
|
|
37009
36960
|
onnxRuntimePromise,
|
|
37010
|
-
new Promise((
|
|
36961
|
+
new Promise((resolve9) => setTimeout(() => resolve9(null), 60000))
|
|
37011
36962
|
]);
|
|
37012
36963
|
}
|
|
37013
36964
|
const bridge = pool.getBridge(cwd);
|