@cortexkit/aft-pi 0.52.2 → 0.54.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/README.md +6 -2
- package/dist/bash-wait-detach.d.ts +6 -0
- package/dist/bash-wait-detach.d.ts.map +1 -1
- package/dist/config.d.ts +182 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +730 -480
- package/dist/shared/status.d.ts +3 -0
- package/dist/shared/status.d.ts.map +1 -1
- package/dist/tool-registration.d.ts +6 -1
- package/dist/tool-registration.d.ts.map +1 -1
- package/dist/tools/_shared.d.ts +7 -0
- package/dist/tools/_shared.d.ts.map +1 -1
- package/dist/tools/bash.d.ts +10 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/diff-format.d.ts.map +1 -1
- package/dist/tools/hoisted.d.ts +2 -0
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tools/inspect.d.ts +1 -1
- package/dist/tools/inspect.d.ts.map +1 -1
- package/dist/tools/render-helpers.d.ts +7 -0
- package/dist/tools/render-helpers.d.ts.map +1 -1
- package/dist/tools/safety.d.ts.map +1 -1
- package/dist/workflow-hints.d.ts +1 -0
- package/dist/workflow-hints.d.ts.map +1 -1
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -7711,9 +7711,9 @@ var require_stringify = __commonJS(function(exports, module) {
|
|
|
7711
7711
|
value
|
|
7712
7712
|
} = comment;
|
|
7713
7713
|
const line_breaks_before = blank_lines > 0 ? blank_lines + (inline ? 0 : 1) : null;
|
|
7714
|
-
const
|
|
7714
|
+
const delimiter3 = line_breaks_before > 0 ? repeat_line_breaks(line_breaks_before, deeper_gap) : inline ? SPACE : i === 0 && symbol_tag === PREFIX_BEFORE_ALL && deeper_gap === EMPTY ? EMPTY : LF + deeper_gap;
|
|
7715
7715
|
const is_line_comment = type === "LineComment";
|
|
7716
|
-
str +=
|
|
7716
|
+
str += delimiter3 + comment_stringify(value, is_line_comment);
|
|
7717
7717
|
blank_lines = 0;
|
|
7718
7718
|
last_comment = comment;
|
|
7719
7719
|
});
|
|
@@ -7730,10 +7730,10 @@ var require_stringify = __commonJS(function(exports, module) {
|
|
|
7730
7730
|
replacer = null;
|
|
7731
7731
|
indent = EMPTY;
|
|
7732
7732
|
};
|
|
7733
|
-
var
|
|
7733
|
+
var join13 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two)), gap) : EMPTY;
|
|
7734
7734
|
var join_content = (inside, value, gap) => {
|
|
7735
7735
|
const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
|
|
7736
|
-
return
|
|
7736
|
+
return join13(comment, inside, gap);
|
|
7737
7737
|
};
|
|
7738
7738
|
var stringify_string = (holder, key, value) => {
|
|
7739
7739
|
const raw = get_raw_string_literal(holder, key);
|
|
@@ -7755,13 +7755,13 @@ var require_stringify = __commonJS(function(exports, module) {
|
|
|
7755
7755
|
if (i !== 0) {
|
|
7756
7756
|
inside += COMMA;
|
|
7757
7757
|
}
|
|
7758
|
-
const before =
|
|
7758
|
+
const before = join13(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
|
|
7759
7759
|
inside += before || LF + deeper_gap;
|
|
7760
7760
|
inside += stringify(i, value, deeper_gap) || STR_NULL;
|
|
7761
7761
|
inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
|
|
7762
7762
|
after_comma = process_comments(value, AFTER(i), deeper_gap);
|
|
7763
7763
|
}
|
|
7764
|
-
inside +=
|
|
7764
|
+
inside += join13(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
7765
7765
|
return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
|
|
7766
7766
|
};
|
|
7767
7767
|
var object_stringify = (value, gap) => {
|
|
@@ -7782,13 +7782,13 @@ var require_stringify = __commonJS(function(exports, module) {
|
|
|
7782
7782
|
inside += COMMA;
|
|
7783
7783
|
}
|
|
7784
7784
|
first = false;
|
|
7785
|
-
const before =
|
|
7785
|
+
const before = join13(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
|
|
7786
7786
|
inside += before || LF + deeper_gap;
|
|
7787
7787
|
inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap);
|
|
7788
7788
|
after_comma = process_comments(value, AFTER(key), deeper_gap);
|
|
7789
7789
|
};
|
|
7790
7790
|
keys.forEach(iteratee);
|
|
7791
|
-
inside +=
|
|
7791
|
+
inside += join13(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
7792
7792
|
return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
|
|
7793
7793
|
};
|
|
7794
7794
|
function stringify(key, holder, gap) {
|
|
@@ -8329,10 +8329,68 @@ function skipSpaces(input, start) {
|
|
|
8329
8329
|
}
|
|
8330
8330
|
// ../aft-bridge/dist/bash-host-fallback.js
|
|
8331
8331
|
import { spawn } from "node:child_process";
|
|
8332
|
+
import { existsSync } from "node:fs";
|
|
8333
|
+
import { delimiter, join as join3 } from "node:path";
|
|
8334
|
+
|
|
8335
|
+
// ../aft-bridge/dist/storage-paths.js
|
|
8336
|
+
import { homedir as homedir2 } from "node:os";
|
|
8337
|
+
import { join as join2, resolve as resolve2 } from "node:path";
|
|
8338
|
+
function homeDir() {
|
|
8339
|
+
if (process.platform === "win32")
|
|
8340
|
+
return process.env.USERPROFILE || process.env.HOME || homedir2();
|
|
8341
|
+
return process.env.HOME || homedir2();
|
|
8342
|
+
}
|
|
8343
|
+
function dataHome() {
|
|
8344
|
+
const xdg = process.env.XDG_DATA_HOME;
|
|
8345
|
+
if (xdg)
|
|
8346
|
+
return xdg;
|
|
8347
|
+
if (process.platform === "win32") {
|
|
8348
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join2(homeDir(), "AppData", "Local");
|
|
8349
|
+
}
|
|
8350
|
+
return join2(homeDir(), ".local", "share");
|
|
8351
|
+
}
|
|
8352
|
+
function resolveStoragePath(raw) {
|
|
8353
|
+
let expanded = raw;
|
|
8354
|
+
if (raw === "~") {
|
|
8355
|
+
expanded = homeDir();
|
|
8356
|
+
} else if (raw.startsWith("~/") || raw.startsWith("~\\")) {
|
|
8357
|
+
expanded = join2(homeDir(), raw.slice(2));
|
|
8358
|
+
}
|
|
8359
|
+
return resolve2(expanded);
|
|
8360
|
+
}
|
|
8361
|
+
function resolveCortexKitStorageRoot() {
|
|
8362
|
+
const override = process.env.AFT_STORAGE_DIR;
|
|
8363
|
+
if (override)
|
|
8364
|
+
return resolveStoragePath(override);
|
|
8365
|
+
return resolveStoragePath(join2(dataHome(), "cortexkit", "aft"));
|
|
8366
|
+
}
|
|
8367
|
+
function resolveAftStorageRoot(configuredRoot) {
|
|
8368
|
+
if (process.env.AFT_STORAGE_DIR)
|
|
8369
|
+
return resolveCortexKitStorageRoot();
|
|
8370
|
+
if (configuredRoot)
|
|
8371
|
+
return configuredRoot;
|
|
8372
|
+
return resolveCortexKitStorageRoot();
|
|
8373
|
+
}
|
|
8374
|
+
function resolveAftLogPath(filename, configuredRoot) {
|
|
8375
|
+
return join2(resolveAftStorageRoot(configuredRoot), "logs", filename);
|
|
8376
|
+
}
|
|
8377
|
+
|
|
8378
|
+
// ../aft-bridge/dist/bash-host-fallback.js
|
|
8332
8379
|
var BASH_HOST_FALLBACK_BANNER = "[AFT host fallback - module transport down; no rewrites/compression/background]";
|
|
8333
8380
|
var BASH_HOST_FALLBACK_MAX_OUTPUT_BYTES = 100 * 1024;
|
|
8334
8381
|
var BASH_HOST_FALLBACK_MAX_TIMEOUT_MS = 10 * 60 * 1000;
|
|
8335
8382
|
var BASH_HOST_FALLBACK_REFUSAL = "AFT transport is down; only foreground execution is available in host fallback";
|
|
8383
|
+
function hostFallbackPathWithShims(env) {
|
|
8384
|
+
const storageRoot = env.AFT_STORAGE_DIR ? resolveStoragePath(env.AFT_STORAGE_DIR) : resolveCortexKitStorageRoot();
|
|
8385
|
+
const shimsDir = join3(storageRoot, "shims");
|
|
8386
|
+
if (!existsSync(join3(shimsDir, "gh")))
|
|
8387
|
+
return env.PATH;
|
|
8388
|
+
const inherited = env.PATH ?? "";
|
|
8389
|
+
const entries = inherited.split(delimiter).filter((entry) => entry.length > 0);
|
|
8390
|
+
if (entries[0] === shimsDir)
|
|
8391
|
+
return inherited;
|
|
8392
|
+
return [shimsDir, ...entries.filter((entry) => entry !== shimsDir)].join(delimiter);
|
|
8393
|
+
}
|
|
8336
8394
|
function bashHostFallbackAskPattern(command, cwd) {
|
|
8337
8395
|
return `AFT UNAVAILABLE - host fallback execution:
|
|
8338
8396
|
|
|
@@ -8365,11 +8423,17 @@ async function runBashHostFallback(options) {
|
|
|
8365
8423
|
if (options.signal?.aborted) {
|
|
8366
8424
|
throw new DOMException("The host fallback command was aborted", "AbortError");
|
|
8367
8425
|
}
|
|
8368
|
-
return await new Promise((
|
|
8426
|
+
return await new Promise((resolve3, reject) => {
|
|
8369
8427
|
const child = spawn(options.command, {
|
|
8370
8428
|
cwd: options.projectRoot,
|
|
8371
8429
|
shell: true,
|
|
8372
|
-
env:
|
|
8430
|
+
env: (() => {
|
|
8431
|
+
const merged = { ...process.env, ...options.env };
|
|
8432
|
+
const path2 = hostFallbackPathWithShims(merged);
|
|
8433
|
+
if (path2 !== undefined)
|
|
8434
|
+
merged.PATH = path2;
|
|
8435
|
+
return merged;
|
|
8436
|
+
})(),
|
|
8373
8437
|
stdio: ["ignore", "pipe", "pipe"],
|
|
8374
8438
|
detached: process.platform !== "win32",
|
|
8375
8439
|
windowsHide: true
|
|
@@ -8432,7 +8496,7 @@ async function runBashHostFallback(options) {
|
|
|
8432
8496
|
return;
|
|
8433
8497
|
}
|
|
8434
8498
|
const exitCode = timedOut ? 124 : code ?? 1;
|
|
8435
|
-
|
|
8499
|
+
resolve3({
|
|
8436
8500
|
success: true,
|
|
8437
8501
|
output: renderOutput(Buffer.concat(chunks), exitCode),
|
|
8438
8502
|
exit_code: exitCode,
|
|
@@ -8452,8 +8516,8 @@ function resolveBashKillTimeout(modelTimeout, foregroundWaitMs) {
|
|
|
8452
8516
|
import { spawn as spawn2 } from "node:child_process";
|
|
8453
8517
|
import { createHash } from "node:crypto";
|
|
8454
8518
|
import { readFileSync } from "node:fs";
|
|
8455
|
-
import { homedir as
|
|
8456
|
-
import { join as
|
|
8519
|
+
import { homedir as homedir3 } from "node:os";
|
|
8520
|
+
import { join as join4 } from "node:path";
|
|
8457
8521
|
import { StringDecoder } from "node:string_decoder";
|
|
8458
8522
|
|
|
8459
8523
|
// ../aft-bridge/dist/command-timeouts.js
|
|
@@ -8953,7 +9017,7 @@ class BinaryBridge {
|
|
|
8953
9017
|
const keepBridgeOnTimeout = passive || options?.keepBridgeOnTimeout === true;
|
|
8954
9018
|
let requestSentAt = Date.now();
|
|
8955
9019
|
const child = this.process;
|
|
8956
|
-
const response = await new Promise((
|
|
9020
|
+
const response = await new Promise((resolve3, reject) => {
|
|
8957
9021
|
const timer = setTimeout(() => {
|
|
8958
9022
|
const entry = this.pending.get(id);
|
|
8959
9023
|
if (!entry)
|
|
@@ -8988,7 +9052,7 @@ class BinaryBridge {
|
|
|
8988
9052
|
entry.reject(new Error(`${this.errorPrefix} Request "${command}" (id=${id}) timed out after ${effectiveTimeoutMs}ms`));
|
|
8989
9053
|
this.handleTimeout(requestSessionId);
|
|
8990
9054
|
}, effectiveTimeoutMs);
|
|
8991
|
-
this.pending.set(id, { resolve:
|
|
9055
|
+
this.pending.set(id, { resolve: resolve3, reject, timer, onProgress: options?.onProgress, command });
|
|
8992
9056
|
if (!child?.stdin?.writable) {
|
|
8993
9057
|
this.pending.delete(id);
|
|
8994
9058
|
clearTimeout(timer);
|
|
@@ -9106,15 +9170,15 @@ class BinaryBridge {
|
|
|
9106
9170
|
if (this.process) {
|
|
9107
9171
|
const proc = this.process;
|
|
9108
9172
|
this.process = null;
|
|
9109
|
-
return new Promise((
|
|
9173
|
+
return new Promise((resolve3) => {
|
|
9110
9174
|
const forceKillTimer = setTimeout(() => {
|
|
9111
9175
|
proc.kill("SIGKILL");
|
|
9112
|
-
|
|
9176
|
+
resolve3();
|
|
9113
9177
|
}, 5000);
|
|
9114
9178
|
proc.once("exit", () => {
|
|
9115
9179
|
clearTimeout(forceKillTimer);
|
|
9116
9180
|
this.logVia("Process exited during shutdown");
|
|
9117
|
-
|
|
9181
|
+
resolve3();
|
|
9118
9182
|
});
|
|
9119
9183
|
proc.kill("SIGTERM");
|
|
9120
9184
|
});
|
|
@@ -9162,15 +9226,15 @@ class BinaryBridge {
|
|
|
9162
9226
|
return;
|
|
9163
9227
|
const proc = this.process;
|
|
9164
9228
|
this.process = null;
|
|
9165
|
-
await new Promise((
|
|
9229
|
+
await new Promise((resolve3) => {
|
|
9166
9230
|
const forceKillTimer = setTimeout(() => {
|
|
9167
9231
|
proc.kill("SIGKILL");
|
|
9168
|
-
|
|
9232
|
+
resolve3();
|
|
9169
9233
|
}, 5000);
|
|
9170
9234
|
proc.once("exit", () => {
|
|
9171
9235
|
clearTimeout(forceKillTimer);
|
|
9172
9236
|
this.logVia("Process exited during coordinated binary replacement");
|
|
9173
|
-
|
|
9237
|
+
resolve3();
|
|
9174
9238
|
});
|
|
9175
9239
|
proc.kill("SIGTERM");
|
|
9176
9240
|
});
|
|
@@ -9200,7 +9264,7 @@ class BinaryBridge {
|
|
|
9200
9264
|
})();
|
|
9201
9265
|
const useFastembedBackend = semanticBackend === undefined || semanticBackend === "fastembed" || semanticBackend === "";
|
|
9202
9266
|
const ortDir = typeof this.configOverrides._ort_dylib_dir === "string" && useFastembedBackend ? this.configOverrides._ort_dylib_dir : null;
|
|
9203
|
-
const ortLibraryPath = ortDir == null ? null :
|
|
9267
|
+
const ortLibraryPath = ortDir == null ? null : join4(ortDir, process.platform === "win32" ? "onnxruntime.dll" : process.platform === "darwin" ? "libonnxruntime.dylib" : "libonnxruntime.so");
|
|
9204
9268
|
const envPath = process.platform === "win32" && ortDir ? `${ortDir};${process.env.PATH ?? ""}` : process.env.PATH;
|
|
9205
9269
|
const env = {
|
|
9206
9270
|
...process.env,
|
|
@@ -9208,7 +9272,7 @@ class BinaryBridge {
|
|
|
9208
9272
|
};
|
|
9209
9273
|
this.logVia(`bridge.spawnProcess: useFastembedBackend=${useFastembedBackend}, ` + `parentORT=${process.env.ORT_DYLIB_PATH ?? "(unset)"}, ` + `ortLibraryPath=${ortLibraryPath ?? "(none)"}`);
|
|
9210
9274
|
if (useFastembedBackend) {
|
|
9211
|
-
env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ?
|
|
9275
|
+
env.FASTEMBED_CACHE_DIR = process.env.FASTEMBED_CACHE_DIR || (typeof this.configOverrides.storage_dir === "string" ? join4(this.configOverrides.storage_dir, "semantic", "models") : join4(homedir3() || "", ".cache", "fastembed"));
|
|
9212
9276
|
if (process.env.ORT_DYLIB_PATH) {
|
|
9213
9277
|
this.logVia(`ORT_DYLIB_PATH inherited from parent env: ${process.env.ORT_DYLIB_PATH}`);
|
|
9214
9278
|
} else if (ortLibraryPath) {
|
|
@@ -9537,32 +9601,32 @@ class BinaryBridge {
|
|
|
9537
9601
|
}
|
|
9538
9602
|
}
|
|
9539
9603
|
// ../aft-bridge/dist/cache-paths.js
|
|
9540
|
-
import { homedir as
|
|
9541
|
-
import { join as
|
|
9542
|
-
function
|
|
9543
|
-
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) ||
|
|
9604
|
+
import { homedir as homedir4 } from "node:os";
|
|
9605
|
+
import { join as join5 } from "node:path";
|
|
9606
|
+
function homeDir2(env) {
|
|
9607
|
+
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir4();
|
|
9544
9608
|
}
|
|
9545
9609
|
function getAftCacheRoot(env = process.env) {
|
|
9546
9610
|
if (env.AFT_CACHE_DIR)
|
|
9547
9611
|
return env.AFT_CACHE_DIR;
|
|
9548
9612
|
if (process.platform === "win32") {
|
|
9549
|
-
const base2 = env.LOCALAPPDATA || env.APPDATA ||
|
|
9550
|
-
return
|
|
9613
|
+
const base2 = env.LOCALAPPDATA || env.APPDATA || join5(homeDir2(env), "AppData", "Local");
|
|
9614
|
+
return join5(base2, "aft");
|
|
9551
9615
|
}
|
|
9552
|
-
const base = env.XDG_CACHE_HOME ||
|
|
9553
|
-
return
|
|
9616
|
+
const base = env.XDG_CACHE_HOME || join5(homeDir2(env), ".cache");
|
|
9617
|
+
return join5(base, "aft");
|
|
9554
9618
|
}
|
|
9555
9619
|
function getAftBinaryCacheDir(env = process.env) {
|
|
9556
|
-
return
|
|
9620
|
+
return join5(getAftCacheRoot(env), "bin");
|
|
9557
9621
|
}
|
|
9558
9622
|
function getAftLspPackagesDir(env = process.env) {
|
|
9559
|
-
return
|
|
9623
|
+
return join5(getAftCacheRoot(env), "lsp-packages");
|
|
9560
9624
|
}
|
|
9561
9625
|
function getAftLspBinariesDir(env = process.env) {
|
|
9562
|
-
return
|
|
9626
|
+
return join5(getAftCacheRoot(env), "lsp-binaries");
|
|
9563
9627
|
}
|
|
9564
9628
|
// ../aft-bridge/dist/callgraph-format.js
|
|
9565
|
-
import { homedir as
|
|
9629
|
+
import { homedir as homedir5 } from "node:os";
|
|
9566
9630
|
var UNRESOLVED_SUMMARY_NAME_LIMIT = 10;
|
|
9567
9631
|
var PLAIN_CALLGRAPH_THEME = {
|
|
9568
9632
|
fg: (_role, text) => text
|
|
@@ -9585,7 +9649,7 @@ function asBoolean(value) {
|
|
|
9585
9649
|
return typeof value === "boolean" ? value : undefined;
|
|
9586
9650
|
}
|
|
9587
9651
|
function shortenPath(path2) {
|
|
9588
|
-
const home =
|
|
9652
|
+
const home = homedir5();
|
|
9589
9653
|
if (path2.startsWith(home))
|
|
9590
9654
|
return `~${path2.slice(home.length)}`;
|
|
9591
9655
|
return path2;
|
|
@@ -9922,7 +9986,7 @@ function isEmptyParam(value) {
|
|
|
9922
9986
|
return false;
|
|
9923
9987
|
}
|
|
9924
9988
|
// ../aft-bridge/dist/config-keys.js
|
|
9925
|
-
var OPENCODE_ONLY_KEYS = ["
|
|
9989
|
+
var OPENCODE_ONLY_KEYS = ["auto_update"];
|
|
9926
9990
|
function stripHarnessSpecificConfigKeys(value, keys) {
|
|
9927
9991
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
9928
9992
|
return value;
|
|
@@ -9932,26 +9996,26 @@ function stripHarnessSpecificConfigKeys(value, keys) {
|
|
|
9932
9996
|
return stripped;
|
|
9933
9997
|
}
|
|
9934
9998
|
// ../aft-bridge/dist/config-tiers.js
|
|
9935
|
-
import { existsSync, readFileSync as readFileSync2 } from "node:fs";
|
|
9936
|
-
import { resolve as
|
|
9999
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
10000
|
+
import { resolve as resolve3 } from "node:path";
|
|
9937
10001
|
function readConfigTiers(opts) {
|
|
9938
10002
|
const tiers = [];
|
|
9939
10003
|
try {
|
|
9940
|
-
if (
|
|
10004
|
+
if (existsSync2(opts.userConfigPath)) {
|
|
9941
10005
|
const doc = readFileSync2(opts.userConfigPath, "utf-8");
|
|
9942
10006
|
tiers.push({
|
|
9943
10007
|
tier: "user",
|
|
9944
|
-
source:
|
|
10008
|
+
source: resolve3(opts.userConfigPath),
|
|
9945
10009
|
doc
|
|
9946
10010
|
});
|
|
9947
10011
|
}
|
|
9948
10012
|
} catch {}
|
|
9949
10013
|
try {
|
|
9950
|
-
if (
|
|
10014
|
+
if (existsSync2(opts.projectConfigPath)) {
|
|
9951
10015
|
const doc = readFileSync2(opts.projectConfigPath, "utf-8");
|
|
9952
10016
|
tiers.push({
|
|
9953
10017
|
tier: "project",
|
|
9954
|
-
source:
|
|
10018
|
+
source: resolve3(opts.projectConfigPath),
|
|
9955
10019
|
doc
|
|
9956
10020
|
});
|
|
9957
10021
|
}
|
|
@@ -9967,9 +10031,9 @@ function formatDroppedKeyWarnings(dropped) {
|
|
|
9967
10031
|
// ../aft-bridge/dist/downloader.js
|
|
9968
10032
|
import { spawnSync } from "node:child_process";
|
|
9969
10033
|
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
9970
|
-
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync as
|
|
10034
|
+
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync as existsSync3, mkdirSync, openSync, readdirSync, readFileSync as readFileSync3, renameSync, rmSync, statSync as statSync2, unlinkSync, writeSync } from "node:fs";
|
|
9971
10035
|
import { hostname } from "node:os";
|
|
9972
|
-
import { join as
|
|
10036
|
+
import { join as join6 } from "node:path";
|
|
9973
10037
|
import { Readable } from "node:stream";
|
|
9974
10038
|
import { pipeline } from "node:stream/promises";
|
|
9975
10039
|
|
|
@@ -10029,8 +10093,8 @@ function getBinaryName() {
|
|
|
10029
10093
|
function getCachedBinaryPath(version) {
|
|
10030
10094
|
if (!version)
|
|
10031
10095
|
return null;
|
|
10032
|
-
const binaryPath =
|
|
10033
|
-
return
|
|
10096
|
+
const binaryPath = join6(getAftBinaryCacheDir(), version, getBinaryName());
|
|
10097
|
+
return existsSync3(binaryPath) ? binaryPath : null;
|
|
10034
10098
|
}
|
|
10035
10099
|
async function downloadBinary(version) {
|
|
10036
10100
|
const archMap = PLATFORM_ARCH_MAP[process.platform] ?? {};
|
|
@@ -10046,16 +10110,16 @@ async function downloadBinary(version) {
|
|
|
10046
10110
|
return null;
|
|
10047
10111
|
}
|
|
10048
10112
|
const tag = rawTag.startsWith("v") ? rawTag : `v${rawTag}`;
|
|
10049
|
-
const versionedCacheDir =
|
|
10113
|
+
const versionedCacheDir = join6(getAftBinaryCacheDir(), tag);
|
|
10050
10114
|
const binaryName = getBinaryName();
|
|
10051
|
-
const binaryPath =
|
|
10052
|
-
if (
|
|
10115
|
+
const binaryPath = join6(versionedCacheDir, binaryName);
|
|
10116
|
+
if (existsSync3(binaryPath) && isExpectedCachedBinary(binaryPath, tag)) {
|
|
10053
10117
|
return binaryPath;
|
|
10054
10118
|
}
|
|
10055
10119
|
const downloadUrl = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
|
|
10056
10120
|
const checksumUrl = `https://github.com/${REPO}/releases/download/${tag}/checksums.sha256`;
|
|
10057
10121
|
log(`Downloading AFT binary (${tag}) for ${platformKey}...`);
|
|
10058
|
-
const lockPath =
|
|
10122
|
+
const lockPath = join6(versionedCacheDir, ".download.lock");
|
|
10059
10123
|
let releaseLock = null;
|
|
10060
10124
|
let binaryController = null;
|
|
10061
10125
|
let checksumController = null;
|
|
@@ -10064,7 +10128,7 @@ async function downloadBinary(version) {
|
|
|
10064
10128
|
const tmpPath = `${binaryPath}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`;
|
|
10065
10129
|
const cleanUpPartialDownload = () => {
|
|
10066
10130
|
try {
|
|
10067
|
-
if (
|
|
10131
|
+
if (existsSync3(tmpPath))
|
|
10068
10132
|
unlinkSync(tmpPath);
|
|
10069
10133
|
} catch {}
|
|
10070
10134
|
};
|
|
@@ -10088,12 +10152,12 @@ async function downloadBinary(version) {
|
|
|
10088
10152
|
process.once("SIGINT", handleSigint);
|
|
10089
10153
|
process.once("exit", handleExit);
|
|
10090
10154
|
try {
|
|
10091
|
-
if (!
|
|
10155
|
+
if (!existsSync3(versionedCacheDir)) {
|
|
10092
10156
|
mkdirSync(versionedCacheDir, { recursive: true });
|
|
10093
10157
|
}
|
|
10094
10158
|
releaseLock = await acquireDownloadLock(lockPath);
|
|
10095
10159
|
sweepStaleDownloadTemps(versionedCacheDir, binaryName);
|
|
10096
|
-
if (
|
|
10160
|
+
if (existsSync3(binaryPath) && isExpectedCachedBinary(binaryPath, tag)) {
|
|
10097
10161
|
return binaryPath;
|
|
10098
10162
|
}
|
|
10099
10163
|
binaryController = new AbortController;
|
|
@@ -10158,7 +10222,7 @@ async function downloadBinary(version) {
|
|
|
10158
10222
|
renameSync(tmpPath, binaryPath);
|
|
10159
10223
|
}
|
|
10160
10224
|
try {
|
|
10161
|
-
if (
|
|
10225
|
+
if (existsSync3(tmpPath))
|
|
10162
10226
|
unlinkSync(tmpPath);
|
|
10163
10227
|
} catch {
|
|
10164
10228
|
warn(`Could not clean up temporary download file ${tmpPath} — it can be removed manually.`);
|
|
@@ -10274,7 +10338,7 @@ function sweepStaleDownloadTemps(versionedCacheDir, binaryName) {
|
|
|
10274
10338
|
if (!entry.isFile() || !entry.name.startsWith(tempPrefix) || !entry.name.endsWith(".tmp")) {
|
|
10275
10339
|
continue;
|
|
10276
10340
|
}
|
|
10277
|
-
const tempPath =
|
|
10341
|
+
const tempPath = join6(versionedCacheDir, entry.name);
|
|
10278
10342
|
const ageMs = Date.now() - statSync2(tempPath).mtimeMs;
|
|
10279
10343
|
if (Math.abs(ageMs) > DOWNLOAD_LOCK_STALE_MS)
|
|
10280
10344
|
unlinkSync(tempPath);
|
|
@@ -10323,7 +10387,7 @@ async function acquireDownloadLock(lockPath, timing = {}) {
|
|
|
10323
10387
|
if (Date.now() - startedAt > timeoutMs) {
|
|
10324
10388
|
throw new Error(`Timed out waiting for download lock: ${lockPath}`);
|
|
10325
10389
|
}
|
|
10326
|
-
await new Promise((
|
|
10390
|
+
await new Promise((resolve4) => setTimeout(resolve4, pollIntervalMs));
|
|
10327
10391
|
}
|
|
10328
10392
|
}
|
|
10329
10393
|
}
|
|
@@ -10361,51 +10425,6 @@ async function fetchLatestTag() {
|
|
|
10361
10425
|
// ../aft-bridge/dist/durable-log.js
|
|
10362
10426
|
import { appendFile, mkdir, rename, rm, stat } from "node:fs/promises";
|
|
10363
10427
|
import { dirname } from "node:path";
|
|
10364
|
-
|
|
10365
|
-
// ../aft-bridge/dist/storage-paths.js
|
|
10366
|
-
import { homedir as homedir5 } from "node:os";
|
|
10367
|
-
import { join as join5, resolve as resolve3 } from "node:path";
|
|
10368
|
-
function homeDir2() {
|
|
10369
|
-
if (process.platform === "win32")
|
|
10370
|
-
return process.env.USERPROFILE || process.env.HOME || homedir5();
|
|
10371
|
-
return process.env.HOME || homedir5();
|
|
10372
|
-
}
|
|
10373
|
-
function dataHome() {
|
|
10374
|
-
const xdg = process.env.XDG_DATA_HOME;
|
|
10375
|
-
if (xdg)
|
|
10376
|
-
return xdg;
|
|
10377
|
-
if (process.platform === "win32") {
|
|
10378
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA || join5(homeDir2(), "AppData", "Local");
|
|
10379
|
-
}
|
|
10380
|
-
return join5(homeDir2(), ".local", "share");
|
|
10381
|
-
}
|
|
10382
|
-
function resolveStoragePath(raw) {
|
|
10383
|
-
let expanded = raw;
|
|
10384
|
-
if (raw === "~") {
|
|
10385
|
-
expanded = homeDir2();
|
|
10386
|
-
} else if (raw.startsWith("~/") || raw.startsWith("~\\")) {
|
|
10387
|
-
expanded = join5(homeDir2(), raw.slice(2));
|
|
10388
|
-
}
|
|
10389
|
-
return resolve3(expanded);
|
|
10390
|
-
}
|
|
10391
|
-
function resolveCortexKitStorageRoot() {
|
|
10392
|
-
const override = process.env.AFT_STORAGE_DIR;
|
|
10393
|
-
if (override)
|
|
10394
|
-
return resolveStoragePath(override);
|
|
10395
|
-
return resolveStoragePath(join5(dataHome(), "cortexkit", "aft"));
|
|
10396
|
-
}
|
|
10397
|
-
function resolveAftStorageRoot(configuredRoot) {
|
|
10398
|
-
if (process.env.AFT_STORAGE_DIR)
|
|
10399
|
-
return resolveCortexKitStorageRoot();
|
|
10400
|
-
if (configuredRoot)
|
|
10401
|
-
return configuredRoot;
|
|
10402
|
-
return resolveCortexKitStorageRoot();
|
|
10403
|
-
}
|
|
10404
|
-
function resolveAftLogPath(filename, configuredRoot) {
|
|
10405
|
-
return join5(resolveAftStorageRoot(configuredRoot), "logs", filename);
|
|
10406
|
-
}
|
|
10407
|
-
|
|
10408
|
-
// ../aft-bridge/dist/durable-log.js
|
|
10409
10428
|
var DEFAULT_LOG_BYTES = 32 * 1024 * 1024;
|
|
10410
10429
|
var DEFAULT_LOG_GENERATIONS = 1;
|
|
10411
10430
|
class RotatingLogSink {
|
|
@@ -12040,7 +12059,7 @@ function pendingKey(handle, corr) {
|
|
|
12040
12059
|
return handle ? `${handle.channel}:${handle.epoch}:${corr}` : `0:0:${corr}`;
|
|
12041
12060
|
}
|
|
12042
12061
|
// ../aft-bridge/dist/subc-transport.js
|
|
12043
|
-
import { existsSync as
|
|
12062
|
+
import { existsSync as existsSync4, statSync as statSync3 } from "node:fs";
|
|
12044
12063
|
|
|
12045
12064
|
// ../aft-bridge/dist/lifecycle-registry.js
|
|
12046
12065
|
import { lstat } from "node:fs/promises";
|
|
@@ -13049,7 +13068,7 @@ class SubcTransportPool {
|
|
|
13049
13068
|
this.dormantRoots.delete(root);
|
|
13050
13069
|
return true;
|
|
13051
13070
|
}
|
|
13052
|
-
const reclaimedMarkerPresent =
|
|
13071
|
+
const reclaimedMarkerPresent = existsSync4(`${root}.reclaimed`);
|
|
13053
13072
|
if (reclaimedMarkerPresent) {
|
|
13054
13073
|
this.markRootDormant(root);
|
|
13055
13074
|
return false;
|
|
@@ -13881,14 +13900,14 @@ function stripJsoncSymbols(value) {
|
|
|
13881
13900
|
}
|
|
13882
13901
|
// ../aft-bridge/dist/migration.js
|
|
13883
13902
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
13884
|
-
import { closeSync as closeSync3, existsSync as
|
|
13903
|
+
import { closeSync as closeSync3, existsSync as existsSync7, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as readFileSync5, renameSync as renameSync4, rmSync as rmSync2, statSync as statSync4, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
13885
13904
|
import { homedir as homedir8, tmpdir } from "node:os";
|
|
13886
|
-
import { basename, dirname as dirname3, join as
|
|
13905
|
+
import { basename, dirname as dirname3, join as join9, resolve as resolve6 } from "node:path";
|
|
13887
13906
|
|
|
13888
13907
|
// ../aft-bridge/dist/paths.js
|
|
13889
|
-
import { existsSync as
|
|
13908
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync } from "node:fs";
|
|
13890
13909
|
import { homedir as homedir6 } from "node:os";
|
|
13891
|
-
import { dirname as dirname2, isAbsolute as isAbsolute2, join as
|
|
13910
|
+
import { dirname as dirname2, isAbsolute as isAbsolute2, join as join7, resolve as resolve5 } from "node:path";
|
|
13892
13911
|
function homeDir3() {
|
|
13893
13912
|
if (process.platform === "win32")
|
|
13894
13913
|
return process.env.USERPROFILE || process.env.HOME || homedir6();
|
|
@@ -13898,16 +13917,16 @@ function configHome() {
|
|
|
13898
13917
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
13899
13918
|
if (xdg && isAbsolute2(xdg))
|
|
13900
13919
|
return xdg;
|
|
13901
|
-
return
|
|
13920
|
+
return join7(homeDir3(), ".config");
|
|
13902
13921
|
}
|
|
13903
13922
|
function legacyOpenCodeConfigDir() {
|
|
13904
13923
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
13905
13924
|
if (envDir)
|
|
13906
13925
|
return resolve5(envDir);
|
|
13907
|
-
return
|
|
13926
|
+
return join7(configHome(), "opencode");
|
|
13908
13927
|
}
|
|
13909
13928
|
function legacyPiAgentDir() {
|
|
13910
|
-
return
|
|
13929
|
+
return join7(homeDir3(), ".pi", "agent");
|
|
13911
13930
|
}
|
|
13912
13931
|
function legacySources(basePath, label, harness) {
|
|
13913
13932
|
return [
|
|
@@ -13916,10 +13935,10 @@ function legacySources(basePath, label, harness) {
|
|
|
13916
13935
|
];
|
|
13917
13936
|
}
|
|
13918
13937
|
function resolveCortexKitUserConfigPath() {
|
|
13919
|
-
return
|
|
13938
|
+
return join7(configHome(), "cortexkit", "aft.jsonc");
|
|
13920
13939
|
}
|
|
13921
13940
|
function resolveCortexKitProjectConfigPath(projectDirectory) {
|
|
13922
|
-
return
|
|
13941
|
+
return join7(projectDirectory, ".cortexkit", "aft.jsonc");
|
|
13923
13942
|
}
|
|
13924
13943
|
function resolveCortexKitConfigPaths(projectDirectory) {
|
|
13925
13944
|
return {
|
|
@@ -13930,22 +13949,22 @@ function resolveCortexKitConfigPaths(projectDirectory) {
|
|
|
13930
13949
|
function resolveLegacyAftConfigSources(projectDirectory) {
|
|
13931
13950
|
return {
|
|
13932
13951
|
user: [
|
|
13933
|
-
...legacySources(
|
|
13934
|
-
...legacySources(
|
|
13952
|
+
...legacySources(join7(legacyOpenCodeConfigDir(), "aft"), "OpenCode user", "opencode"),
|
|
13953
|
+
...legacySources(join7(legacyPiAgentDir(), "aft"), "Pi user", "pi")
|
|
13935
13954
|
],
|
|
13936
13955
|
project: [
|
|
13937
|
-
...legacySources(
|
|
13938
|
-
...legacySources(
|
|
13956
|
+
...legacySources(join7(projectDirectory, ".opencode", "aft"), "OpenCode project", "opencode"),
|
|
13957
|
+
...legacySources(join7(projectDirectory, ".pi", "aft"), "Pi project", "pi")
|
|
13939
13958
|
]
|
|
13940
13959
|
};
|
|
13941
13960
|
}
|
|
13942
13961
|
function resolveHarnessStoragePath(storageRoot, harness, ...segments) {
|
|
13943
|
-
return
|
|
13962
|
+
return join7(storageRoot, harness, ...segments);
|
|
13944
13963
|
}
|
|
13945
13964
|
function repairRootScopedStorageFile(storageRoot, harness, fileName) {
|
|
13946
13965
|
const harnessPath = resolveHarnessStoragePath(storageRoot, harness, fileName);
|
|
13947
|
-
const rootPath =
|
|
13948
|
-
if (
|
|
13966
|
+
const rootPath = join7(storageRoot, fileName);
|
|
13967
|
+
if (existsSync5(harnessPath) || !existsSync5(rootPath))
|
|
13949
13968
|
return harnessPath;
|
|
13950
13969
|
try {
|
|
13951
13970
|
mkdirSync2(dirname2(harnessPath), { recursive: true });
|
|
@@ -13959,7 +13978,7 @@ function shouldShowAnnouncement(storageRoot, harness, currentVersion) {
|
|
|
13959
13978
|
const versionFile = repairRootScopedStorageFile(storageRoot, harness, "last_announced_version");
|
|
13960
13979
|
let lastVersion = "";
|
|
13961
13980
|
try {
|
|
13962
|
-
if (
|
|
13981
|
+
if (existsSync5(versionFile)) {
|
|
13963
13982
|
lastVersion = readFileSync4(versionFile, "utf-8").trim();
|
|
13964
13983
|
}
|
|
13965
13984
|
} catch {
|
|
@@ -14031,10 +14050,10 @@ function decodeFileUrl(target) {
|
|
|
14031
14050
|
|
|
14032
14051
|
// ../aft-bridge/dist/resolver.js
|
|
14033
14052
|
import { execSync } from "node:child_process";
|
|
14034
|
-
import { chmodSync as chmodSync2, closeSync as closeSync2, copyFileSync as copyFileSync2, existsSync as
|
|
14053
|
+
import { chmodSync as chmodSync2, closeSync as closeSync2, copyFileSync as copyFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync3, openSync as openSync2, readSync, renameSync as renameSync3, unlinkSync as unlinkSync2 } from "node:fs";
|
|
14035
14054
|
import { createRequire as createRequire2 } from "node:module";
|
|
14036
14055
|
import { homedir as homedir7 } from "node:os";
|
|
14037
|
-
import { join as
|
|
14056
|
+
import { join as join8 } from "node:path";
|
|
14038
14057
|
var ensureBinaryForResolver = ensureBinary;
|
|
14039
14058
|
function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
14040
14059
|
try {
|
|
@@ -14043,10 +14062,10 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
|
14043
14062
|
return null;
|
|
14044
14063
|
const tag = version.startsWith("v") ? version : `v${version}`;
|
|
14045
14064
|
const cacheDir = getAftBinaryCacheDir();
|
|
14046
|
-
const versionedDir =
|
|
14065
|
+
const versionedDir = join8(cacheDir, tag);
|
|
14047
14066
|
const ext = process.platform === "win32" ? ".exe" : "";
|
|
14048
|
-
const cachedPath =
|
|
14049
|
-
if (
|
|
14067
|
+
const cachedPath = join8(versionedDir, `aft${ext}`);
|
|
14068
|
+
if (existsSync6(cachedPath)) {
|
|
14050
14069
|
const cachedVersion = readBinaryVersion(cachedPath);
|
|
14051
14070
|
if (cachedVersion === version)
|
|
14052
14071
|
return cachedPath;
|
|
@@ -14058,7 +14077,7 @@ function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
|
14058
14077
|
if (process.platform !== "win32") {
|
|
14059
14078
|
chmodSync2(tmpPath, 493);
|
|
14060
14079
|
}
|
|
14061
|
-
if (process.platform === "win32" &&
|
|
14080
|
+
if (process.platform === "win32" && existsSync6(cachedPath)) {
|
|
14062
14081
|
try {
|
|
14063
14082
|
unlinkSync2(cachedPath);
|
|
14064
14083
|
} catch {}
|
|
@@ -14078,8 +14097,8 @@ function homeDirFromEnv(env) {
|
|
|
14078
14097
|
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir7();
|
|
14079
14098
|
}
|
|
14080
14099
|
function cachedBinaryPathFromEnv(version, env, ext) {
|
|
14081
|
-
const binaryPath =
|
|
14082
|
-
return
|
|
14100
|
+
const binaryPath = join8(getAftBinaryCacheDir(env), version, `aft${ext}`);
|
|
14101
|
+
return existsSync6(binaryPath) ? binaryPath : null;
|
|
14083
14102
|
}
|
|
14084
14103
|
function isExpectedCachedBinary2(binaryPath, expectedVersion) {
|
|
14085
14104
|
const expected = normalizeBareVersion(expectedVersion);
|
|
@@ -14178,7 +14197,7 @@ function findBinarySyncInner(expectedVersion) {
|
|
|
14178
14197
|
const packageBin = `@cortexkit/aft-${key}/bin/aft${ext}`;
|
|
14179
14198
|
const req = createRequire2(import.meta.url);
|
|
14180
14199
|
const resolved = req.resolve(packageBin);
|
|
14181
|
-
if (
|
|
14200
|
+
if (existsSync6(resolved)) {
|
|
14182
14201
|
const npmVersion = readBinaryVersion(resolved);
|
|
14183
14202
|
if (npmVersion === null) {
|
|
14184
14203
|
warn(`npm platform package binary at ${resolved} did not report a version; skipping (continuing to PATH lookup)`);
|
|
@@ -14207,8 +14226,8 @@ function findBinarySyncInner(expectedVersion) {
|
|
|
14207
14226
|
return { path: usable, source: "PATH" };
|
|
14208
14227
|
}
|
|
14209
14228
|
} catch {}
|
|
14210
|
-
const cargoPath =
|
|
14211
|
-
if (
|
|
14229
|
+
const cargoPath = join8(homeDirFromEnv(env), ".cargo", "bin", `aft${ext}`);
|
|
14230
|
+
if (existsSync6(cargoPath)) {
|
|
14212
14231
|
const usable = probeBinaryCandidate(cargoPath, "cargo", expectedVersion);
|
|
14213
14232
|
if (usable)
|
|
14214
14233
|
return { path: usable, source: "cargo" };
|
|
@@ -14254,9 +14273,9 @@ function dataHome2() {
|
|
|
14254
14273
|
if (process.env.XDG_DATA_HOME)
|
|
14255
14274
|
return process.env.XDG_DATA_HOME;
|
|
14256
14275
|
if (process.platform === "win32") {
|
|
14257
|
-
return process.env.LOCALAPPDATA || process.env.APPDATA ||
|
|
14276
|
+
return process.env.LOCALAPPDATA || process.env.APPDATA || join9(homeDir4(), "AppData", "Local");
|
|
14258
14277
|
}
|
|
14259
|
-
return
|
|
14278
|
+
return join9(homeDir4(), ".local", "share");
|
|
14260
14279
|
}
|
|
14261
14280
|
function homeDir4() {
|
|
14262
14281
|
if (process.platform === "win32")
|
|
@@ -14265,8 +14284,8 @@ function homeDir4() {
|
|
|
14265
14284
|
}
|
|
14266
14285
|
function resolveLegacyStorageRoot(harness) {
|
|
14267
14286
|
if (harness === "pi")
|
|
14268
|
-
return
|
|
14269
|
-
return
|
|
14287
|
+
return join9(homeDir4(), ".pi", "agent", "aft");
|
|
14288
|
+
return join9(dataHome2(), "opencode", "storage", "plugin", "aft");
|
|
14270
14289
|
}
|
|
14271
14290
|
function stripJsoncForParse(input) {
|
|
14272
14291
|
let out = "";
|
|
@@ -14396,7 +14415,7 @@ function acquireConfigMigrationLock(lockDir) {
|
|
|
14396
14415
|
}
|
|
14397
14416
|
function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
14398
14417
|
mkdirSync4(dirname3(targetPath), { recursive: true });
|
|
14399
|
-
const tmpPath =
|
|
14418
|
+
const tmpPath = join9(dirname3(targetPath), `.${basename(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
14400
14419
|
let fd = null;
|
|
14401
14420
|
try {
|
|
14402
14421
|
fd = openSync3(tmpPath, "wx", 384);
|
|
@@ -14418,7 +14437,7 @@ function atomicCopyConfigFile(sourcePath, targetPath) {
|
|
|
14418
14437
|
}
|
|
14419
14438
|
function atomicWriteConfigFile(targetPath, content) {
|
|
14420
14439
|
mkdirSync4(dirname3(targetPath), { recursive: true });
|
|
14421
|
-
const tmpPath =
|
|
14440
|
+
const tmpPath = join9(dirname3(targetPath), `.${basename(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
14422
14441
|
let fd = null;
|
|
14423
14442
|
try {
|
|
14424
14443
|
fd = openSync3(tmpPath, "wx", 384);
|
|
@@ -14440,11 +14459,11 @@ function atomicWriteConfigFile(targetPath, content) {
|
|
|
14440
14459
|
}
|
|
14441
14460
|
var MOVED_MARKER_SUFFIX = ".MOVED_READPLEASE";
|
|
14442
14461
|
function nonClobberingSidecarPath(desiredPath) {
|
|
14443
|
-
if (!
|
|
14462
|
+
if (!existsSync7(desiredPath))
|
|
14444
14463
|
return desiredPath;
|
|
14445
14464
|
for (let index = 1;index < Number.MAX_SAFE_INTEGER; index++) {
|
|
14446
14465
|
const candidate = `${desiredPath}.${index}`;
|
|
14447
|
-
if (!
|
|
14466
|
+
if (!existsSync7(candidate))
|
|
14448
14467
|
return candidate;
|
|
14449
14468
|
}
|
|
14450
14469
|
throw new Error(`could not find available preservation sidecar path for ${desiredPath}`);
|
|
@@ -14538,7 +14557,7 @@ function visibleConfigMigrationWarning(scope, targetPath, paths, reason) {
|
|
|
14538
14557
|
function migrateAftConfigFile(opts) {
|
|
14539
14558
|
const warnings = [];
|
|
14540
14559
|
const resolvedTarget = resolve6(opts.targetPath);
|
|
14541
|
-
const existingSources = opts.legacySources.filter((source) =>
|
|
14560
|
+
const existingSources = opts.legacySources.filter((source) => existsSync7(source.path) && resolve6(source.path) !== resolvedTarget);
|
|
14542
14561
|
const info = opts.logger?.info ?? opts.logger?.log;
|
|
14543
14562
|
if (existingSources.length === 0) {
|
|
14544
14563
|
return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
|
|
@@ -14550,7 +14569,7 @@ function migrateAftConfigFile(opts) {
|
|
|
14550
14569
|
...source,
|
|
14551
14570
|
content: readFileSync5(source.path, "utf-8")
|
|
14552
14571
|
}));
|
|
14553
|
-
if (
|
|
14572
|
+
if (existsSync7(opts.targetPath)) {
|
|
14554
14573
|
const targetContent = readFileSync5(opts.targetPath, "utf-8");
|
|
14555
14574
|
for (const source of sources) {
|
|
14556
14575
|
if (fileSemanticsMatch(source.content, targetContent))
|
|
@@ -14600,12 +14619,12 @@ function spawnErrorLabel(error2) {
|
|
|
14600
14619
|
return [code, error2.message].filter(Boolean).join(": ");
|
|
14601
14620
|
}
|
|
14602
14621
|
function migrationLogPath(newRoot, harness, logger) {
|
|
14603
|
-
const desired =
|
|
14622
|
+
const desired = join9(newRoot, "logs", "migration", `${harness}-${Date.now()}.jsonl`);
|
|
14604
14623
|
try {
|
|
14605
14624
|
mkdirSync4(dirname3(desired), { recursive: true });
|
|
14606
14625
|
return desired;
|
|
14607
14626
|
} catch (err) {
|
|
14608
|
-
const fallback =
|
|
14627
|
+
const fallback = join9(tmpdir(), `aft-migration-${harness}-${Date.now()}.jsonl`);
|
|
14609
14628
|
logger?.warn?.(`Failed to create AFT migration log directory ${dirname3(desired)}: ${err instanceof Error ? err.message : String(err)}. ` + `Using fallback log path ${fallback}.`);
|
|
14610
14629
|
return fallback;
|
|
14611
14630
|
}
|
|
@@ -14615,11 +14634,11 @@ async function ensureStorageMigrated(opts) {
|
|
|
14615
14634
|
const newRoot = resolveCortexKitStorageRoot();
|
|
14616
14635
|
const targetMarker = resolveHarnessStoragePath(newRoot, opts.harness, TARGET_MARKER);
|
|
14617
14636
|
const info = opts.logger?.info ?? opts.logger?.log;
|
|
14618
|
-
if (
|
|
14637
|
+
if (existsSync7(targetMarker)) {
|
|
14619
14638
|
info?.(`AFT storage already migrated for ${opts.harness}; using ${newRoot}`);
|
|
14620
14639
|
return;
|
|
14621
14640
|
}
|
|
14622
|
-
if (!
|
|
14641
|
+
if (!existsSync7(legacyRoot)) {
|
|
14623
14642
|
info?.(`AFT storage migration skipped for ${opts.harness}: no legacy data at ${legacyRoot}; ` + `using ${newRoot} for fresh install`);
|
|
14624
14643
|
return;
|
|
14625
14644
|
}
|
|
@@ -14669,7 +14688,7 @@ async function ensureStorageMigrated(opts) {
|
|
|
14669
14688
|
// ../aft-bridge/dist/npm-resolver.js
|
|
14670
14689
|
import { readdirSync as readdirSync2, statSync as statSync5 } from "node:fs";
|
|
14671
14690
|
import { homedir as homedir9 } from "node:os";
|
|
14672
|
-
import { delimiter, dirname as dirname4, isAbsolute as isAbsolute3, join as
|
|
14691
|
+
import { delimiter as delimiter2, dirname as dirname4, isAbsolute as isAbsolute3, join as join10 } from "node:path";
|
|
14673
14692
|
function defaultDeps() {
|
|
14674
14693
|
return {
|
|
14675
14694
|
platform: process.platform,
|
|
@@ -14691,18 +14710,18 @@ function isFile(p) {
|
|
|
14691
14710
|
function npmFromPath(deps) {
|
|
14692
14711
|
const name = npmBinaryName(deps.platform);
|
|
14693
14712
|
const raw = deps.env.PATH ?? deps.env.Path ?? "";
|
|
14694
|
-
for (const entry of raw.split(
|
|
14713
|
+
for (const entry of raw.split(delimiter2)) {
|
|
14695
14714
|
const dir = entry.trim().replace(/^"|"$/g, "");
|
|
14696
14715
|
if (!dir || !isAbsolute3(dir))
|
|
14697
14716
|
continue;
|
|
14698
|
-
if (isFile(
|
|
14717
|
+
if (isFile(join10(dir, name)))
|
|
14699
14718
|
return dir;
|
|
14700
14719
|
}
|
|
14701
14720
|
return null;
|
|
14702
14721
|
}
|
|
14703
14722
|
function npmAdjacentToNode(deps) {
|
|
14704
14723
|
const dir = dirname4(deps.execPath);
|
|
14705
|
-
return isFile(
|
|
14724
|
+
return isFile(join10(dir, npmBinaryName(deps.platform))) ? dir : null;
|
|
14706
14725
|
}
|
|
14707
14726
|
function highestVersionedNodeBin(installsDir, name) {
|
|
14708
14727
|
let entries;
|
|
@@ -14711,8 +14730,8 @@ function highestVersionedNodeBin(installsDir, name) {
|
|
|
14711
14730
|
} catch {
|
|
14712
14731
|
return null;
|
|
14713
14732
|
}
|
|
14714
|
-
const candidates = entries.filter((v) => isFile(
|
|
14715
|
-
return candidates.length > 0 ?
|
|
14733
|
+
const candidates = entries.filter((v) => isFile(join10(installsDir, v, "bin", name))).sort((a, b) => compareVersionsDesc(a, b));
|
|
14734
|
+
return candidates.length > 0 ? join10(installsDir, candidates[0], "bin") : null;
|
|
14716
14735
|
}
|
|
14717
14736
|
function compareVersionsDesc(a, b) {
|
|
14718
14737
|
const pa = a.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10));
|
|
@@ -14737,22 +14756,22 @@ function wellKnownNpmDirs(deps) {
|
|
|
14737
14756
|
const programFiles = env.ProgramFiles || "C:\\Program Files";
|
|
14738
14757
|
const appData = env.APPDATA;
|
|
14739
14758
|
const localAppData = env.LOCALAPPDATA;
|
|
14740
|
-
push(
|
|
14759
|
+
push(join10(programFiles, "nodejs"));
|
|
14741
14760
|
if (appData)
|
|
14742
|
-
push(
|
|
14761
|
+
push(join10(appData, "npm"));
|
|
14743
14762
|
if (localAppData)
|
|
14744
|
-
push(
|
|
14763
|
+
push(join10(localAppData, "Volta", "bin"));
|
|
14745
14764
|
if (env.NVM_SYMLINK)
|
|
14746
14765
|
push(env.NVM_SYMLINK);
|
|
14747
14766
|
} else {
|
|
14748
14767
|
if (env.NVM_BIN)
|
|
14749
14768
|
push(env.NVM_BIN);
|
|
14750
|
-
push(highestVersionedNodeBin(
|
|
14751
|
-
push(highestVersionedNodeBin(
|
|
14752
|
-
push(highestVersionedNodeBin(
|
|
14753
|
-
push(
|
|
14754
|
-
push(
|
|
14755
|
-
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin",
|
|
14769
|
+
push(highestVersionedNodeBin(join10(home, ".nvm", "versions", "node"), name));
|
|
14770
|
+
push(highestVersionedNodeBin(join10(home, ".local", "share", "mise", "installs", "node"), name));
|
|
14771
|
+
push(highestVersionedNodeBin(join10(home, ".asdf", "installs", "nodejs"), name));
|
|
14772
|
+
push(join10(home, ".volta", "bin"));
|
|
14773
|
+
push(join10(home, ".asdf", "shims"));
|
|
14774
|
+
const systemDirs = deps.systemNpmDirs ?? (platform === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin", "/usr/bin", join10(home, ".local", "bin")]);
|
|
14756
14775
|
for (const dir of systemDirs)
|
|
14757
14776
|
push(dir);
|
|
14758
14777
|
}
|
|
@@ -14762,12 +14781,12 @@ function resolveNpm(deps = defaultDeps()) {
|
|
|
14762
14781
|
const name = npmBinaryName(deps.platform);
|
|
14763
14782
|
const onPath = npmFromPath(deps);
|
|
14764
14783
|
if (onPath)
|
|
14765
|
-
return { command:
|
|
14784
|
+
return { command: join10(onPath, name), binDir: onPath };
|
|
14766
14785
|
const adjacent = npmAdjacentToNode(deps);
|
|
14767
14786
|
if (adjacent)
|
|
14768
|
-
return { command:
|
|
14787
|
+
return { command: join10(adjacent, name), binDir: adjacent };
|
|
14769
14788
|
for (const dir of wellKnownNpmDirs(deps)) {
|
|
14770
|
-
const candidate =
|
|
14789
|
+
const candidate = join10(dir, name);
|
|
14771
14790
|
if (isFile(candidate))
|
|
14772
14791
|
return { command: candidate, binDir: dir };
|
|
14773
14792
|
}
|
|
@@ -14777,14 +14796,14 @@ function npmSpawnEnv(resolved, baseEnv = process.env) {
|
|
|
14777
14796
|
if (!resolved.binDir)
|
|
14778
14797
|
return { ...baseEnv };
|
|
14779
14798
|
const existing = baseEnv.PATH ?? baseEnv.Path ?? "";
|
|
14780
|
-
const next = existing ? `${resolved.binDir}${
|
|
14799
|
+
const next = existing ? `${resolved.binDir}${delimiter2}${existing}` : resolved.binDir;
|
|
14781
14800
|
return { ...baseEnv, PATH: next };
|
|
14782
14801
|
}
|
|
14783
14802
|
// ../aft-bridge/dist/onnx-runtime.js
|
|
14784
14803
|
import { execFileSync } from "node:child_process";
|
|
14785
14804
|
import { createHash as createHash3 } from "node:crypto";
|
|
14786
|
-
import { chmodSync as chmodSync3, closeSync as closeSync4, copyFileSync as copyFileSync3, createWriteStream as createWriteStream2, existsSync as
|
|
14787
|
-
import { basename as basename2, dirname as dirname5, isAbsolute as isAbsolute4, join as
|
|
14805
|
+
import { chmodSync as chmodSync3, closeSync as closeSync4, copyFileSync as copyFileSync3, createWriteStream as createWriteStream2, existsSync as existsSync8, lstatSync, mkdirSync as mkdirSync5, openSync as openSync4, readdirSync as readdirSync3, readFileSync as readFileSync6, readlinkSync, realpathSync as realpathSync2, rmSync as rmSync3, statSync as statSync6, symlinkSync, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
14806
|
+
import { basename as basename2, dirname as dirname5, isAbsolute as isAbsolute4, join as join11, relative as relative2, resolve as resolve7, win32 } from "node:path";
|
|
14788
14807
|
import { Readable as Readable2 } from "node:stream";
|
|
14789
14808
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
14790
14809
|
var ORT_VERSION = "1.24.4";
|
|
@@ -14847,11 +14866,11 @@ function getManualInstallHint() {
|
|
|
14847
14866
|
}
|
|
14848
14867
|
async function ensureOnnxRuntime(storageDir) {
|
|
14849
14868
|
const info = getPlatformInfo();
|
|
14850
|
-
const ortVersionDir =
|
|
14869
|
+
const ortVersionDir = join11(storageDir, "onnxruntime", ORT_VERSION);
|
|
14851
14870
|
const libName = info?.libName ?? "libonnxruntime.dylib";
|
|
14852
14871
|
const resolvedOrtDir = resolveCachedOnnxRuntimeDir(ortVersionDir, libName);
|
|
14853
|
-
const libPath =
|
|
14854
|
-
if (
|
|
14872
|
+
const libPath = join11(resolvedOrtDir, libName);
|
|
14873
|
+
if (existsSync8(libPath)) {
|
|
14855
14874
|
const meta = readOnnxInstalledMeta(ortVersionDir);
|
|
14856
14875
|
if (meta?.sha256) {
|
|
14857
14876
|
try {
|
|
@@ -14880,9 +14899,9 @@ async function ensureOnnxRuntime(storageDir) {
|
|
|
14880
14899
|
warn(`ONNX Runtime auto-download not available for ${process.platform}/${process.arch}. Install manually: ${getManualInstallHint()}`);
|
|
14881
14900
|
return null;
|
|
14882
14901
|
}
|
|
14883
|
-
const onnxBaseDir =
|
|
14902
|
+
const onnxBaseDir = join11(storageDir, "onnxruntime");
|
|
14884
14903
|
mkdirSync5(onnxBaseDir, { recursive: true });
|
|
14885
|
-
const lockPath =
|
|
14904
|
+
const lockPath = join11(onnxBaseDir, ONNX_LOCK_FILE);
|
|
14886
14905
|
cleanupAbandonedStagingDirs(onnxBaseDir);
|
|
14887
14906
|
if (!acquireLock(lockPath)) {
|
|
14888
14907
|
warn(`ONNX Runtime install already in progress in another process (lock: ${lockPath}). Skipping.`);
|
|
@@ -14901,7 +14920,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
14901
14920
|
for (const entry of entries) {
|
|
14902
14921
|
if (!entry.startsWith(`${ORT_VERSION}.tmp.`))
|
|
14903
14922
|
continue;
|
|
14904
|
-
const stagingDir =
|
|
14923
|
+
const stagingDir = join11(onnxBaseDir, entry);
|
|
14905
14924
|
const parts = entry.split(".");
|
|
14906
14925
|
const pidStr = parts[parts.length - 2];
|
|
14907
14926
|
const pid = pidStr ? Number.parseInt(pidStr, 10) : NaN;
|
|
@@ -14938,7 +14957,7 @@ function cleanupAbandonedStagingDirs(onnxBaseDir) {
|
|
|
14938
14957
|
}
|
|
14939
14958
|
function cleanupIncompleteTargetIfUnowned(ortDir) {
|
|
14940
14959
|
try {
|
|
14941
|
-
if (
|
|
14960
|
+
if (existsSync8(ortDir) && !existsSync8(join11(ortDir, ONNX_INSTALLED_META_FILE))) {
|
|
14942
14961
|
log(`[onnx] removing half-populated install dir ${ortDir} (no meta file)`);
|
|
14943
14962
|
rmSync3(ortDir, { recursive: true, force: true });
|
|
14944
14963
|
}
|
|
@@ -14982,8 +15001,8 @@ function detectOnnxVersion(libDir, libName) {
|
|
|
14982
15001
|
if (version)
|
|
14983
15002
|
return version;
|
|
14984
15003
|
}
|
|
14985
|
-
const base =
|
|
14986
|
-
if (
|
|
15004
|
+
const base = join11(libDir, libName);
|
|
15005
|
+
if (existsSync8(base)) {
|
|
14987
15006
|
try {
|
|
14988
15007
|
const real = realpathSync2(base);
|
|
14989
15008
|
const version = parseOnnxVersionFromPath(real) ?? parseOnnxVersionFromDirectoryPath(real);
|
|
@@ -15014,8 +15033,8 @@ function pathEnvValue() {
|
|
|
15014
15033
|
return process.env.PATH ?? process.env.Path ?? process.env.path ?? "";
|
|
15015
15034
|
}
|
|
15016
15035
|
function pathEntriesForPlatform() {
|
|
15017
|
-
const
|
|
15018
|
-
return pathEnvValue().split(
|
|
15036
|
+
const delimiter3 = process.platform === "win32" ? ";" : ":";
|
|
15037
|
+
return pathEnvValue().split(delimiter3).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
|
|
15019
15038
|
if (!entry || entry === "." || entry.includes("\x00"))
|
|
15020
15039
|
return false;
|
|
15021
15040
|
return isAbsolute4(entry) || win32.isAbsolute(entry);
|
|
@@ -15045,10 +15064,10 @@ function directoryContainsLibrary(dir, libName) {
|
|
|
15045
15064
|
}
|
|
15046
15065
|
}
|
|
15047
15066
|
function resolveCachedOnnxRuntimeDir(ortVersionDir, libName) {
|
|
15048
|
-
if (
|
|
15067
|
+
if (existsSync8(join11(ortVersionDir, libName)))
|
|
15049
15068
|
return ortVersionDir;
|
|
15050
|
-
const libSubdir =
|
|
15051
|
-
if (
|
|
15069
|
+
const libSubdir = join11(ortVersionDir, "lib");
|
|
15070
|
+
if (existsSync8(join11(libSubdir, libName)))
|
|
15052
15071
|
return libSubdir;
|
|
15053
15072
|
return ortVersionDir;
|
|
15054
15073
|
}
|
|
@@ -15063,13 +15082,13 @@ function findSystemOnnxRuntime(libName) {
|
|
|
15063
15082
|
} else if (process.platform === "win32") {
|
|
15064
15083
|
const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
|
|
15065
15084
|
const programFilesX86 = process.env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
15066
|
-
searchPaths.push(
|
|
15085
|
+
searchPaths.push(join11(programFiles, "onnxruntime", "lib"), join11(programFiles, "Microsoft ONNX Runtime", "lib"), join11(programFiles, "Microsoft Machine Learning", "lib"), join11(programFilesX86, "onnxruntime", "lib"), ...(() => {
|
|
15067
15086
|
const nugetPaths = [];
|
|
15068
15087
|
const userProfile = process.env.USERPROFILE ?? "";
|
|
15069
15088
|
if (!userProfile)
|
|
15070
15089
|
return nugetPaths;
|
|
15071
|
-
const nugetPackageDir =
|
|
15072
|
-
if (!
|
|
15090
|
+
const nugetPackageDir = join11(userProfile, ".nuget", "packages", "microsoft.ml.onnxruntime");
|
|
15091
|
+
if (!existsSync8(nugetPackageDir))
|
|
15073
15092
|
return nugetPaths;
|
|
15074
15093
|
try {
|
|
15075
15094
|
for (const entry of readdirSync3(nugetPackageDir, { withFileTypes: true })) {
|
|
@@ -15077,7 +15096,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
15077
15096
|
continue;
|
|
15078
15097
|
if (entry.name === "__globalPackagesFolder" || entry.name.startsWith("."))
|
|
15079
15098
|
continue;
|
|
15080
|
-
nugetPaths.push(
|
|
15099
|
+
nugetPaths.push(join11(nugetPackageDir, entry.name, "runtimes", "win-x64", "native"), join11(nugetPackageDir, entry.name, "runtimes", "win-arm64", "native"));
|
|
15081
15100
|
}
|
|
15082
15101
|
} catch (err) {
|
|
15083
15102
|
warn(`Failed to scan NuGet ONNX Runtime cache ${nugetPackageDir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -15099,11 +15118,11 @@ function findSystemOnnxRuntime(libName) {
|
|
|
15099
15118
|
});
|
|
15100
15119
|
const unknownVersionPaths = [];
|
|
15101
15120
|
for (const dir of uniquePaths) {
|
|
15102
|
-
const libPath =
|
|
15121
|
+
const libPath = join11(dir, libName);
|
|
15103
15122
|
if (process.platform === "win32") {
|
|
15104
15123
|
if (!directoryContainsLibrary(dir, libName))
|
|
15105
15124
|
continue;
|
|
15106
|
-
} else if (!
|
|
15125
|
+
} else if (!existsSync8(libPath)) {
|
|
15107
15126
|
continue;
|
|
15108
15127
|
}
|
|
15109
15128
|
const version = detectOnnxVersion(dir, libName);
|
|
@@ -15169,7 +15188,7 @@ function validateExtractedTree(stagingRoot) {
|
|
|
15169
15188
|
const walk = (dir) => {
|
|
15170
15189
|
const entries = readdirSync3(dir);
|
|
15171
15190
|
for (const entry of entries) {
|
|
15172
|
-
const fullPath =
|
|
15191
|
+
const fullPath = join11(dir, entry);
|
|
15173
15192
|
const lst = lstatSync(fullPath);
|
|
15174
15193
|
if (lst.isSymbolicLink()) {
|
|
15175
15194
|
const linkTarget = readlinkSync(fullPath);
|
|
@@ -15204,7 +15223,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
15204
15223
|
const tmpDir = `${targetDir}.tmp.${process.pid}.${Date.now().toString(36)}`;
|
|
15205
15224
|
try {
|
|
15206
15225
|
mkdirSync5(tmpDir, { recursive: true });
|
|
15207
|
-
const archivePath =
|
|
15226
|
+
const archivePath = join11(tmpDir, `onnxruntime.${info.archiveType}`);
|
|
15208
15227
|
await downloadFileWithCap(url, archivePath);
|
|
15209
15228
|
const archiveSha256 = sha256File(archivePath);
|
|
15210
15229
|
log(`ONNX Runtime archive sha256=${archiveSha256}`);
|
|
@@ -15220,8 +15239,8 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
15220
15239
|
unlinkSync4(archivePath);
|
|
15221
15240
|
} catch {}
|
|
15222
15241
|
validateExtractedTree(tmpDir);
|
|
15223
|
-
const extractedDir =
|
|
15224
|
-
if (!
|
|
15242
|
+
const extractedDir = join11(tmpDir, info.assetName, "lib");
|
|
15243
|
+
if (!existsSync8(extractedDir)) {
|
|
15225
15244
|
throw new Error(`Expected directory not found: ${extractedDir}`);
|
|
15226
15245
|
}
|
|
15227
15246
|
mkdirSync5(targetDir, { recursive: true });
|
|
@@ -15229,7 +15248,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
15229
15248
|
const realFiles = [];
|
|
15230
15249
|
const symlinks = [];
|
|
15231
15250
|
for (const libFile of libFiles) {
|
|
15232
|
-
const src =
|
|
15251
|
+
const src = join11(extractedDir, libFile);
|
|
15233
15252
|
try {
|
|
15234
15253
|
const stat2 = lstatSync(src);
|
|
15235
15254
|
log(`ORT extract: ${libFile} — isSymlink=${stat2.isSymbolicLink()}, isFile=${stat2.isFile()}, size=${stat2.size}`);
|
|
@@ -15244,7 +15263,7 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
15244
15263
|
}
|
|
15245
15264
|
}
|
|
15246
15265
|
copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks);
|
|
15247
|
-
const libPath =
|
|
15266
|
+
const libPath = join11(targetDir, info.libName);
|
|
15248
15267
|
let libHash = null;
|
|
15249
15268
|
try {
|
|
15250
15269
|
libHash = sha256File(libPath);
|
|
@@ -15269,8 +15288,8 @@ async function downloadOnnxRuntime(info, targetDir) {
|
|
|
15269
15288
|
function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, copyFile = copyFileSync3) {
|
|
15270
15289
|
const requiredLibs = new Set([info.libName]);
|
|
15271
15290
|
for (const libFile of realFiles) {
|
|
15272
|
-
const src =
|
|
15273
|
-
const dst =
|
|
15291
|
+
const src = join11(extractedDir, libFile);
|
|
15292
|
+
const dst = join11(targetDir, libFile);
|
|
15274
15293
|
try {
|
|
15275
15294
|
copyFile(src, dst);
|
|
15276
15295
|
if (process.platform !== "win32") {
|
|
@@ -15286,11 +15305,11 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
15286
15305
|
}
|
|
15287
15306
|
const targetRoot = realpathSync2(targetDir);
|
|
15288
15307
|
for (const link of symlinks) {
|
|
15289
|
-
const dst =
|
|
15308
|
+
const dst = join11(targetDir, link.name);
|
|
15290
15309
|
try {
|
|
15291
15310
|
unlinkSync4(dst);
|
|
15292
15311
|
} catch {}
|
|
15293
|
-
const dstForContainment =
|
|
15312
|
+
const dstForContainment = join11(targetRoot, link.name);
|
|
15294
15313
|
const resolvedTarget = resolve7(dirname5(dstForContainment), link.target);
|
|
15295
15314
|
if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
|
|
15296
15315
|
const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
|
|
@@ -15311,8 +15330,8 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
15311
15330
|
log(`ORT extract: failed to symlink optional ${link.name}: ${symlinkErr}`);
|
|
15312
15331
|
}
|
|
15313
15332
|
}
|
|
15314
|
-
const requiredPath =
|
|
15315
|
-
if (!
|
|
15333
|
+
const requiredPath = join11(targetDir, info.libName);
|
|
15334
|
+
if (!existsSync8(requiredPath)) {
|
|
15316
15335
|
rmSync3(targetDir, { recursive: true, force: true });
|
|
15317
15336
|
throw new Error(`Required ONNX Runtime library missing after install: ${requiredPath}`);
|
|
15318
15337
|
}
|
|
@@ -15338,13 +15357,13 @@ function writeOnnxInstalledMeta(installDir, version, sha256, archiveSha256) {
|
|
|
15338
15357
|
...sha256 ? { sha256 } : {},
|
|
15339
15358
|
archiveSha256
|
|
15340
15359
|
};
|
|
15341
|
-
writeFileSync3(
|
|
15360
|
+
writeFileSync3(join11(installDir, ONNX_INSTALLED_META_FILE), JSON.stringify(meta), "utf8");
|
|
15342
15361
|
} catch (err) {
|
|
15343
15362
|
log(`[onnx] failed to write installed-meta in ${installDir}: ${err}`);
|
|
15344
15363
|
}
|
|
15345
15364
|
}
|
|
15346
15365
|
function readOnnxInstalledMeta(installDir) {
|
|
15347
|
-
const path2 =
|
|
15366
|
+
const path2 = join11(installDir, ONNX_INSTALLED_META_FILE);
|
|
15348
15367
|
try {
|
|
15349
15368
|
if (!statSync6(path2).isFile())
|
|
15350
15369
|
return null;
|
|
@@ -15750,7 +15769,7 @@ function editModesPresent(record) {
|
|
|
15750
15769
|
const hasSymbol = isNonEmptyString(record.symbol);
|
|
15751
15770
|
if (!hasSymbol) {
|
|
15752
15771
|
delete record.symbol;
|
|
15753
|
-
if (record.content
|
|
15772
|
+
if (isNullOrEmptyString(record.content))
|
|
15754
15773
|
delete record.content;
|
|
15755
15774
|
} else if (record.content === null) {
|
|
15756
15775
|
delete record.content;
|
|
@@ -15779,17 +15798,24 @@ function editModesPresent(record) {
|
|
|
15779
15798
|
function isNonEmptyString(value) {
|
|
15780
15799
|
return typeof value === "string" && value.length > 0;
|
|
15781
15800
|
}
|
|
15801
|
+
function isNullOrEmptyString(value) {
|
|
15802
|
+
return value === null || value === "";
|
|
15803
|
+
}
|
|
15782
15804
|
var OMIT_OPTIONAL_FIELDS_STEERING = "Omit unused optional fields entirely; do not send empty strings or empty arrays for them.";
|
|
15783
15805
|
function isEditSentinelItem(item) {
|
|
15784
15806
|
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
15785
15807
|
return false;
|
|
15786
15808
|
const record = item;
|
|
15787
|
-
|
|
15809
|
+
const oldStringEmpty = hasOwn(record, "oldString") && isNullOrEmptyString(record.oldString);
|
|
15810
|
+
if (!oldStringEmpty)
|
|
15811
|
+
return false;
|
|
15812
|
+
if (record.oldString === null && ["startLine", "endLine"].some((key) => hasOwn(record, key) && record[key] !== null)) {
|
|
15788
15813
|
return false;
|
|
15789
|
-
|
|
15814
|
+
}
|
|
15815
|
+
const newStringEmpty = !hasOwn(record, "newString") || isNullOrEmptyString(record.newString);
|
|
15790
15816
|
if (!newStringEmpty)
|
|
15791
15817
|
return false;
|
|
15792
|
-
return !hasOwn(record, "content") || record.content
|
|
15818
|
+
return !hasOwn(record, "content") || isNullOrEmptyString(record.content);
|
|
15793
15819
|
}
|
|
15794
15820
|
function normalizeEditArraySentinels(record) {
|
|
15795
15821
|
const value = record.edits;
|
|
@@ -15844,6 +15870,18 @@ function parseEditArray(value) {
|
|
|
15844
15870
|
}
|
|
15845
15871
|
function stripLineRangeSentinels(item) {
|
|
15846
15872
|
const hasRangeField = ["startLine", "endLine", "content"].some((key) => hasOwn(item, key));
|
|
15873
|
+
for (const key of [
|
|
15874
|
+
"oldString",
|
|
15875
|
+
"newString",
|
|
15876
|
+
"replaceAll",
|
|
15877
|
+
"occurrence",
|
|
15878
|
+
"startLine",
|
|
15879
|
+
"endLine",
|
|
15880
|
+
"content"
|
|
15881
|
+
]) {
|
|
15882
|
+
if (item[key] === null)
|
|
15883
|
+
delete item[key];
|
|
15884
|
+
}
|
|
15847
15885
|
if (!hasRangeField)
|
|
15848
15886
|
return;
|
|
15849
15887
|
if (item.oldString === "")
|
|
@@ -16556,17 +16594,17 @@ function collectStructuredExtras(response) {
|
|
|
16556
16594
|
return stringifyData(extras);
|
|
16557
16595
|
}
|
|
16558
16596
|
// ../aft-bridge/dist/transport-factory.js
|
|
16559
|
-
import { existsSync as
|
|
16597
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
16560
16598
|
import { homedir as homedir11 } from "node:os";
|
|
16561
|
-
import { isAbsolute as isAbsolute5, join as
|
|
16599
|
+
import { isAbsolute as isAbsolute5, join as join12 } from "node:path";
|
|
16562
16600
|
function resolveConnectionFilePath(raw) {
|
|
16563
16601
|
const trimmed = raw.trim();
|
|
16564
16602
|
if (trimmed.startsWith("~")) {
|
|
16565
|
-
return
|
|
16603
|
+
return join12(homedir11(), trimmed.slice(1).replace(/^[/\\]/, ""));
|
|
16566
16604
|
}
|
|
16567
16605
|
if (isAbsolute5(trimmed))
|
|
16568
16606
|
return trimmed;
|
|
16569
|
-
return
|
|
16607
|
+
return join12(homedir11(), trimmed);
|
|
16570
16608
|
}
|
|
16571
16609
|
var SUBC_CLIENT_REAPER_PROCESS_KEY = "subc_client_reaper";
|
|
16572
16610
|
function booleanOption(value) {
|
|
@@ -16640,7 +16678,7 @@ async function createConcreteAftTransportPool(opts) {
|
|
|
16640
16678
|
consumerIdentity: opts.subcConsumerIdentity,
|
|
16641
16679
|
onBgEventsNudge: opts.onBgEventsNudge,
|
|
16642
16680
|
onBgEventsNudgeRef: opts.onBgEventsNudgeRef,
|
|
16643
|
-
lifecycleDemandCheck: opts.subcLifecycleDemandCheck ?? ((root) =>
|
|
16681
|
+
lifecycleDemandCheck: opts.subcLifecycleDemandCheck ?? ((root) => existsSync9(root))
|
|
16644
16682
|
});
|
|
16645
16683
|
}
|
|
16646
16684
|
return new BridgePool(opts.binaryPath, opts.poolOptions, opts.configOverrides);
|
|
@@ -17461,7 +17499,7 @@ import {
|
|
|
17461
17499
|
// package.json
|
|
17462
17500
|
var package_default = {
|
|
17463
17501
|
name: "@cortexkit/aft-pi",
|
|
17464
|
-
version: "0.
|
|
17502
|
+
version: "0.54.0",
|
|
17465
17503
|
type: "module",
|
|
17466
17504
|
description: "Pi coding agent extension for Agent File Tools (AFT) — tree-sitter and LSP-powered code analysis",
|
|
17467
17505
|
main: "dist/index.js",
|
|
@@ -17484,19 +17522,19 @@ var package_default = {
|
|
|
17484
17522
|
"test:unit": "bun test src/__tests__ --path-ignore-patterns 'src/__tests__/e2e/**'"
|
|
17485
17523
|
},
|
|
17486
17524
|
dependencies: {
|
|
17487
|
-
"@cortexkit/aft-bridge": "0.
|
|
17525
|
+
"@cortexkit/aft-bridge": "0.54.0",
|
|
17488
17526
|
"comment-json": "^5.0.0",
|
|
17489
17527
|
diff: "^8.0.4",
|
|
17490
17528
|
typebox: "1.1.38",
|
|
17491
17529
|
zod: "^4.4.3"
|
|
17492
17530
|
},
|
|
17493
17531
|
optionalDependencies: {
|
|
17494
|
-
"@cortexkit/aft-darwin-arm64": "0.
|
|
17495
|
-
"@cortexkit/aft-darwin-x64": "0.
|
|
17496
|
-
"@cortexkit/aft-linux-arm64": "0.
|
|
17497
|
-
"@cortexkit/aft-linux-x64": "0.
|
|
17498
|
-
"@cortexkit/aft-win32-arm64": "0.
|
|
17499
|
-
"@cortexkit/aft-win32-x64": "0.
|
|
17532
|
+
"@cortexkit/aft-darwin-arm64": "0.54.0",
|
|
17533
|
+
"@cortexkit/aft-darwin-x64": "0.54.0",
|
|
17534
|
+
"@cortexkit/aft-linux-arm64": "0.54.0",
|
|
17535
|
+
"@cortexkit/aft-linux-x64": "0.54.0",
|
|
17536
|
+
"@cortexkit/aft-win32-arm64": "0.54.0",
|
|
17537
|
+
"@cortexkit/aft-win32-x64": "0.54.0"
|
|
17500
17538
|
},
|
|
17501
17539
|
devDependencies: {
|
|
17502
17540
|
"@earendil-works/pi-coding-agent": "^0.80.2",
|
|
@@ -17640,13 +17678,16 @@ function coerceAftStatus(response) {
|
|
|
17640
17678
|
project_root: readNullableString(response.project_root),
|
|
17641
17679
|
canonical_root: readNullableString(response.canonical_root),
|
|
17642
17680
|
cache_role: readString(response.cache_role, "not_initialized"),
|
|
17681
|
+
degraded: readBoolean(response.degraded),
|
|
17682
|
+
degraded_reasons: Array.isArray(response.degraded_reasons) ? response.degraded_reasons.filter((r) => typeof r === "string") : [],
|
|
17643
17683
|
message: typeof response.message === "string" ? response.message : undefined,
|
|
17644
17684
|
features: {
|
|
17645
17685
|
format_on_edit: readBoolean(features.format_on_edit),
|
|
17646
17686
|
validate_on_edit: readString(features.validate_on_edit, "off"),
|
|
17647
17687
|
restrict_to_project_root: readBoolean(features.restrict_to_project_root),
|
|
17648
17688
|
search_index: readBoolean(features.search_index ?? features.experimental_search_index),
|
|
17649
|
-
semantic_search: readBoolean(features.semantic_search ?? features.experimental_semantic_search)
|
|
17689
|
+
semantic_search: readBoolean(features.semantic_search ?? features.experimental_semantic_search),
|
|
17690
|
+
callgraph_store: readBoolean(features.callgraph_store)
|
|
17650
17691
|
},
|
|
17651
17692
|
search_index: {
|
|
17652
17693
|
status: readString(searchIndex.status, "unknown"),
|
|
@@ -17697,21 +17738,10 @@ function formatStatusDialogMessage(status) {
|
|
|
17697
17738
|
`AFT version: ${status.version}`,
|
|
17698
17739
|
`Project root: ${status.project_root ?? "(not configured)"}`,
|
|
17699
17740
|
`Canonical root: ${status.canonical_root ?? "(not configured)"}`,
|
|
17700
|
-
`Cache role: ${formatCacheRoleLabel(status.cache_role)}
|
|
17701
|
-
"",
|
|
17702
|
-
"Enabled features",
|
|
17703
|
-
`- format_on_edit: ${formatFlag(status.features.format_on_edit)}`,
|
|
17704
|
-
`- search_index: ${formatFlag(status.features.search_index)}`,
|
|
17705
|
-
`- semantic_search: ${formatFlag(status.features.semantic_search)}`,
|
|
17706
|
-
"",
|
|
17707
|
-
"Search index",
|
|
17708
|
-
`- status: ${status.search_index.status}`,
|
|
17709
|
-
`- files: ${formatCount(status.search_index.files)}`,
|
|
17710
|
-
`- trigrams: ${formatCount(status.search_index.trigrams)}`,
|
|
17711
|
-
"",
|
|
17712
|
-
"Semantic index",
|
|
17713
|
-
`- status: ${formatSemanticIndexStatus(status.semantic_index.status, status.semantic_index.stage)}`
|
|
17741
|
+
`Cache role: ${formatCacheRoleLabel(status.cache_role)}`
|
|
17714
17742
|
];
|
|
17743
|
+
appendDegradedStatus(lines, status, false);
|
|
17744
|
+
lines.push("", "Enabled features", `- format_on_edit: ${formatFlag(status.features.format_on_edit)}`, `- search_index: ${formatFlag(status.features.search_index)}`, `- semantic_search: ${formatFlag(status.features.semantic_search)}`, `- callgraph_store: ${formatFlag(status.features.callgraph_store)}`, "", "Search index", `- status: ${status.search_index.status}`, `- files: ${formatCount(status.search_index.files)}`, `- trigrams: ${formatCount(status.search_index.trigrams)}`, "", "Semantic index", `- status: ${formatSemanticIndexStatus(status.semantic_index.status, status.semantic_index.stage)}`);
|
|
17715
17745
|
const refreshing = formatSemanticRefreshing(status.semantic_index.refreshing_count);
|
|
17716
17746
|
if (refreshing) {
|
|
17717
17747
|
lines.push(`- ${refreshing}`);
|
|
@@ -17761,9 +17791,18 @@ function formatStatusDialogMessage(status) {
|
|
|
17761
17791
|
return lines.join(`
|
|
17762
17792
|
`);
|
|
17763
17793
|
}
|
|
17794
|
+
function appendDegradedStatus(lines, status, markdown) {
|
|
17795
|
+
if (!status.degraded || status.degraded_reasons.length === 0)
|
|
17796
|
+
return;
|
|
17797
|
+
lines.push("", markdown ? "### Degraded mode" : "Degraded mode");
|
|
17798
|
+
for (const reason of status.degraded_reasons) {
|
|
17799
|
+
const detail = reason === "home_root" ? "project root is your home directory; heavy indexes are disabled" : reason;
|
|
17800
|
+
lines.push(`- ${detail}`);
|
|
17801
|
+
}
|
|
17802
|
+
}
|
|
17764
17803
|
|
|
17765
17804
|
// src/tools/_shared.ts
|
|
17766
|
-
import { existsSync as
|
|
17805
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
17767
17806
|
import { Type } from "typebox";
|
|
17768
17807
|
var optionalInt = (min, max, description = "(integer)") => Type.Optional(Type.Union([Type.Integer({ minimum: min, maximum: max }), Type.String()], {
|
|
17769
17808
|
description
|
|
@@ -17771,7 +17810,8 @@ var optionalInt = (min, max, description = "(integer)") => Type.Optional(Type.Un
|
|
|
17771
17810
|
function withPathAliasPreparation(tool) {
|
|
17772
17811
|
const existing = tool.prepareArguments;
|
|
17773
17812
|
const prepare = (args) => {
|
|
17774
|
-
const
|
|
17813
|
+
const isEditTool = tool.name === "edit" || tool.name === "aft_edit";
|
|
17814
|
+
const prepared = isEditTool ? prepareCanonicalEditArguments("edit", args) : prepareCanonicalPathArguments(tool.name, args);
|
|
17775
17815
|
return existing ? existing(prepared) : prepared;
|
|
17776
17816
|
};
|
|
17777
17817
|
return {
|
|
@@ -17783,7 +17823,7 @@ function withPathAliasPreparation(tool) {
|
|
|
17783
17823
|
};
|
|
17784
17824
|
}
|
|
17785
17825
|
function bridgeFor(ctx, cwd) {
|
|
17786
|
-
if (!
|
|
17826
|
+
if (!existsSync10(cwd)) {
|
|
17787
17827
|
throw new Error(`project directory no longer exists: ${cwd} (stale restored session?)`);
|
|
17788
17828
|
}
|
|
17789
17829
|
return ctx.pool.getBridge(cwd);
|
|
@@ -17831,8 +17871,10 @@ async function callBridge(bridge, command, params = {}, extCtx, options) {
|
|
|
17831
17871
|
return response;
|
|
17832
17872
|
}
|
|
17833
17873
|
async function callToolCall(bridge, name, rawArgs = {}, extCtx, options) {
|
|
17874
|
+
return callToolCallForSession(bridge, name, rawArgs, extCtx ? resolveSessionId(extCtx) : undefined, extCtx, options);
|
|
17875
|
+
}
|
|
17876
|
+
async function callToolCallForSession(bridge, name, rawArgs, sessionId, extCtx, options) {
|
|
17834
17877
|
const timeoutMs = timeoutForCommand(name);
|
|
17835
|
-
const sessionId = extCtx ? resolveSessionId(extCtx) : undefined;
|
|
17836
17878
|
const sendOptions = {
|
|
17837
17879
|
...timeoutMs !== undefined ? { timeoutMs } : {},
|
|
17838
17880
|
configureWarningClient: extCtx,
|
|
@@ -17998,7 +18040,7 @@ function renderInner(s, error3, theme, innerWidth) {
|
|
|
17998
18040
|
lines.push(line);
|
|
17999
18041
|
lines.push("");
|
|
18000
18042
|
lines.push(theme.fg("muted", "Features"));
|
|
18001
|
-
lines.push(` ${featureBadge("format_on_edit", s.features.format_on_edit, theme)} ${featureBadge("search_index", s.features.search_index, theme)} ${featureBadge("semantic_search", s.features.semantic_search, theme)}`);
|
|
18043
|
+
lines.push(` ${featureBadge("format_on_edit", s.features.format_on_edit, theme)} ${featureBadge("search_index", s.features.search_index, theme)} ${featureBadge("semantic_search", s.features.semantic_search, theme)} ${featureBadge("callgraph_store", s.features.callgraph_store, theme)}`);
|
|
18002
18044
|
const compressionRows = formatCompressionStatusRows(s.compression);
|
|
18003
18045
|
if (compressionRows.length > 0) {
|
|
18004
18046
|
lines.push("");
|
|
@@ -18155,7 +18197,7 @@ function registerStatusCommand(pi, ctx) {
|
|
|
18155
18197
|
}
|
|
18156
18198
|
|
|
18157
18199
|
// src/config.ts
|
|
18158
|
-
import { existsSync as
|
|
18200
|
+
import { existsSync as existsSync11, readFileSync as readFileSync7, renameSync as renameSync5, unlinkSync as unlinkSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
18159
18201
|
import { homedir as homedir12 } from "node:os";
|
|
18160
18202
|
import { isAbsolute as isAbsolute6 } from "node:path";
|
|
18161
18203
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
@@ -19771,8 +19813,8 @@ function emoji() {
|
|
|
19771
19813
|
}
|
|
19772
19814
|
var ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
|
|
19773
19815
|
var ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
|
|
19774
|
-
var mac = (
|
|
19775
|
-
const escapedDelim = escapeRegex(
|
|
19816
|
+
var mac = (delimiter3) => {
|
|
19817
|
+
const escapedDelim = escapeRegex(delimiter3 ?? ":");
|
|
19776
19818
|
return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
|
|
19777
19819
|
};
|
|
19778
19820
|
var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
|
|
@@ -32437,6 +32479,26 @@ function date4(params) {
|
|
|
32437
32479
|
// ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
32438
32480
|
config(en_default());
|
|
32439
32481
|
// src/config.ts
|
|
32482
|
+
var ACTIVE_HARNESS = "pi";
|
|
32483
|
+
function isConfigRecord(value) {
|
|
32484
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
32485
|
+
}
|
|
32486
|
+
function normalizeConfigForActiveHarness(value) {
|
|
32487
|
+
const config2 = stripHarnessSpecificConfigKeys(value, OPENCODE_ONLY_KEYS);
|
|
32488
|
+
if (!isConfigRecord(config2) || !isConfigRecord(config2.harnesses))
|
|
32489
|
+
return config2;
|
|
32490
|
+
const override = config2.harnesses[ACTIVE_HARNESS];
|
|
32491
|
+
return {
|
|
32492
|
+
...config2,
|
|
32493
|
+
harnesses: override === undefined ? {} : { [ACTIVE_HARNESS]: stripHarnessSpecificConfigKeys(override, OPENCODE_ONLY_KEYS) }
|
|
32494
|
+
};
|
|
32495
|
+
}
|
|
32496
|
+
function warnIgnoredNestedHarnesses(rawConfig, configPath) {
|
|
32497
|
+
const override = isConfigRecord(rawConfig.harnesses) ? rawConfig.harnesses[ACTIVE_HARNESS] : undefined;
|
|
32498
|
+
if (isConfigRecord(override) && Object.hasOwn(override, "harnesses")) {
|
|
32499
|
+
warn2(`Ignoring nested harnesses in harnesses.${ACTIVE_HARNESS} from ${configPath}; harness overrides cannot recurse`);
|
|
32500
|
+
}
|
|
32501
|
+
}
|
|
32440
32502
|
var DEFAULT_INSPECT_DIAGNOSTICS_TIMEOUT_MS = 120000;
|
|
32441
32503
|
var MIN_INSPECT_DIAGNOSTICS_TIMEOUT_MS = 1e4;
|
|
32442
32504
|
var MAX_INSPECT_DIAGNOSTICS_TIMEOUT_MS = 600000;
|
|
@@ -32455,6 +32517,7 @@ function resolveBashConfig(config2) {
|
|
|
32455
32517
|
const surfaceDefaultEnabled = surface !== "minimal";
|
|
32456
32518
|
const reminderEnabled = (typeof top === "object" && top !== null ? top.long_running_reminder_enabled : undefined) ?? legacy?.long_running_reminder_enabled;
|
|
32457
32519
|
const reminderInterval = (typeof top === "object" && top !== null ? top.long_running_reminder_interval_ms : undefined) ?? legacy?.long_running_reminder_interval_ms;
|
|
32520
|
+
const topDetachOnUserMessage = typeof top === "object" && top !== null ? top.detach_on_user_message ?? true : true;
|
|
32458
32521
|
const rawForegroundWait = typeof top === "object" && top !== null ? top.foreground_wait_window_ms : undefined;
|
|
32459
32522
|
const foregroundWaitWindowMs = Math.max(FOREGROUND_WAIT_WINDOW_MIN_MS, rawForegroundWait ?? FOREGROUND_WAIT_WINDOW_DEFAULT_MS);
|
|
32460
32523
|
const base = {
|
|
@@ -32463,9 +32526,11 @@ function resolveBashConfig(config2) {
|
|
|
32463
32526
|
compress: false,
|
|
32464
32527
|
background: false,
|
|
32465
32528
|
host_fallback: false,
|
|
32529
|
+
detach_on_user_message: true,
|
|
32466
32530
|
long_running_reminder_enabled: reminderEnabled,
|
|
32467
32531
|
long_running_reminder_interval_ms: reminderInterval,
|
|
32468
|
-
foreground_wait_window_ms: foregroundWaitWindowMs
|
|
32532
|
+
foreground_wait_window_ms: foregroundWaitWindowMs,
|
|
32533
|
+
powershell_tool: typeof top === "object" && top !== null ? top.powershell_tool ?? false : false
|
|
32469
32534
|
};
|
|
32470
32535
|
if (top === false)
|
|
32471
32536
|
return base;
|
|
@@ -32479,7 +32544,8 @@ function resolveBashConfig(config2) {
|
|
|
32479
32544
|
rewrite: top.rewrite ?? true,
|
|
32480
32545
|
compress: top.compress ?? true,
|
|
32481
32546
|
background: top.background ?? true,
|
|
32482
|
-
host_fallback: top.host_fallback ?? false
|
|
32547
|
+
host_fallback: top.host_fallback ?? false,
|
|
32548
|
+
detach_on_user_message: topDetachOnUserMessage
|
|
32483
32549
|
};
|
|
32484
32550
|
}
|
|
32485
32551
|
const hasLegacyFeatureFlag = legacy && (legacy.rewrite !== undefined || legacy.compress !== undefined || legacy.background !== undefined);
|
|
@@ -32593,9 +32659,11 @@ var BashFeaturesSchema = exports_external.object({
|
|
|
32593
32659
|
compress: exports_external.boolean().optional(),
|
|
32594
32660
|
background: exports_external.boolean().optional(),
|
|
32595
32661
|
host_fallback: exports_external.boolean().optional(),
|
|
32662
|
+
detach_on_user_message: exports_external.boolean().optional(),
|
|
32596
32663
|
long_running_reminder_enabled: exports_external.boolean().optional(),
|
|
32597
32664
|
long_running_reminder_interval_ms: exports_external.number().int().positive().optional(),
|
|
32598
|
-
foreground_wait_window_ms: exports_external.number().int().positive().optional()
|
|
32665
|
+
foreground_wait_window_ms: exports_external.number().int().positive().optional(),
|
|
32666
|
+
powershell_tool: exports_external.boolean().optional()
|
|
32599
32667
|
});
|
|
32600
32668
|
var BashConfigSchema = exports_external.union([exports_external.boolean(), BashFeaturesSchema]);
|
|
32601
32669
|
var SandboxConfigSchema = exports_external.object({
|
|
@@ -32638,7 +32706,7 @@ var BackupConfigSchema = exports_external.object({
|
|
|
32638
32706
|
max_depth: exports_external.number().int().positive().optional(),
|
|
32639
32707
|
max_file_size: exports_external.number().int().positive().optional()
|
|
32640
32708
|
});
|
|
32641
|
-
var
|
|
32709
|
+
var AftConfigFieldsSchema = exports_external.object({
|
|
32642
32710
|
$schema: exports_external.string().optional(),
|
|
32643
32711
|
enabled: exports_external.boolean().optional(),
|
|
32644
32712
|
edit_mode: exports_external.enum(["default", "hashline"]).optional(),
|
|
@@ -32648,6 +32716,7 @@ var AftConfigSchema = exports_external.preprocess((value) => stripHarnessSpecifi
|
|
|
32648
32716
|
formatter: exports_external.record(exports_external.string(), FormatterEnum).optional(),
|
|
32649
32717
|
checker: exports_external.record(exports_external.string(), CheckerEnum).optional(),
|
|
32650
32718
|
configure_warnings_delivery: ConfigureWarningsDeliveryEnum.optional(),
|
|
32719
|
+
hoist_builtin_tools: exports_external.boolean().optional(),
|
|
32651
32720
|
tool_surface: exports_external.enum(["minimal", "recommended", "all"]).optional(),
|
|
32652
32721
|
disabled_tools: exports_external.array(exports_external.string()).optional(),
|
|
32653
32722
|
restrict_to_project_root: exports_external.boolean().optional(),
|
|
@@ -32669,7 +32738,20 @@ var AftConfigSchema = exports_external.preprocess((value) => stripHarnessSpecifi
|
|
|
32669
32738
|
subc: SubcConfigSchema.optional(),
|
|
32670
32739
|
gh_shim: GhShimConfigSchema.optional(),
|
|
32671
32740
|
git: GitConfigSchema.optional()
|
|
32741
|
+
});
|
|
32742
|
+
var HarnessOverrideSchema = exports_external.preprocess((value) => {
|
|
32743
|
+
if (!isConfigRecord(value) || !Object.hasOwn(value, "harnesses"))
|
|
32744
|
+
return value;
|
|
32745
|
+
const { harnesses: _nestedHarnesses, ...override } = value;
|
|
32746
|
+
return override;
|
|
32747
|
+
}, AftConfigFieldsSchema.strict());
|
|
32748
|
+
var AftConfigSchema = exports_external.preprocess(normalizeConfigForActiveHarness, AftConfigFieldsSchema.extend({
|
|
32749
|
+
harnesses: exports_external.record(exports_external.string(), HarnessOverrideSchema).optional()
|
|
32672
32750
|
}).strict());
|
|
32751
|
+
function applyActiveHarnessOverride(config2) {
|
|
32752
|
+
const { harnesses: _harnesses, ...base } = config2;
|
|
32753
|
+
return { ...base, ...config2.harnesses?.[ACTIVE_HARNESS] };
|
|
32754
|
+
}
|
|
32673
32755
|
var CONFIG_MIGRATIONS = [
|
|
32674
32756
|
{ oldKey: "experimental_search_index", newPath: ["search_index"] },
|
|
32675
32757
|
{ oldKey: "experimental_semantic_search", newPath: ["semantic_search"] },
|
|
@@ -32780,7 +32862,7 @@ function migrateExperimentalBashBlock(rawConfig, configPath, logger) {
|
|
|
32780
32862
|
return movedKeys;
|
|
32781
32863
|
}
|
|
32782
32864
|
function migrateAftConfigFile2(configPath, logger = { log: log2, warn: warn2 }) {
|
|
32783
|
-
if (!
|
|
32865
|
+
if (!existsSync11(configPath)) {
|
|
32784
32866
|
return { migrated: false, oldKeys: [] };
|
|
32785
32867
|
}
|
|
32786
32868
|
let tmpPath = null;
|
|
@@ -32831,9 +32913,15 @@ function recordConfigParseFailure(configPath, errorMessage) {
|
|
|
32831
32913
|
configLoadErrors.push({ path: configPath, message: errorMessage });
|
|
32832
32914
|
warn2(formatConfigParseFailureMessage(configPath, errorMessage));
|
|
32833
32915
|
}
|
|
32916
|
+
function warnIgnoredHarnessSpecificConfigKeys(config2, configPath) {
|
|
32917
|
+
const ignored = OPENCODE_ONLY_KEYS.filter((key) => Object.hasOwn(config2, key));
|
|
32918
|
+
if (ignored.length === 0)
|
|
32919
|
+
return;
|
|
32920
|
+
warn2(`Ignoring OpenCode-only config key${ignored.length === 1 ? "" : "s"} ${ignored.map((key) => `\`${key}\``).join(", ")} in ${configPath}; ${ignored.length === 1 ? "it has" : "they have"} no effect on the Pi harness.`);
|
|
32921
|
+
}
|
|
32834
32922
|
function loadConfigFromPath(configPath) {
|
|
32835
32923
|
try {
|
|
32836
|
-
if (!
|
|
32924
|
+
if (!existsSync11(configPath))
|
|
32837
32925
|
return null;
|
|
32838
32926
|
const content = readFileSync7(configPath, "utf-8");
|
|
32839
32927
|
const rawConfig = import_comment_json.parse(content);
|
|
@@ -32843,14 +32931,16 @@ function loadConfigFromPath(configPath) {
|
|
|
32843
32931
|
}
|
|
32844
32932
|
migrateRawConfig(rawConfig, configPath, { log: log2, warn: warn2 });
|
|
32845
32933
|
const cleanConfig = stripJsoncSymbols(rawConfig);
|
|
32934
|
+
warnIgnoredHarnessSpecificConfigKeys(cleanConfig, configPath);
|
|
32935
|
+
warnIgnoredNestedHarnesses(cleanConfig, configPath);
|
|
32846
32936
|
const result = AftConfigSchema.safeParse(cleanConfig);
|
|
32847
32937
|
if (result.success) {
|
|
32848
32938
|
log2(`Config loaded from ${configPath}`);
|
|
32849
|
-
return result.data;
|
|
32939
|
+
return applyActiveHarnessOverride(result.data);
|
|
32850
32940
|
}
|
|
32851
32941
|
const errorMsg = result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join(", ");
|
|
32852
32942
|
warn2(`Config validation error in ${configPath}: ${errorMsg}`);
|
|
32853
|
-
return parseConfigPartially(cleanConfig);
|
|
32943
|
+
return applyActiveHarnessOverride(parseConfigPartially(cleanConfig));
|
|
32854
32944
|
} catch (err) {
|
|
32855
32945
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
32856
32946
|
error2(`Error loading config from ${configPath}: ${errorMsg}`);
|
|
@@ -33006,6 +33096,7 @@ var PROJECT_SAFE_TOP_LEVEL_FIELDS = new Set([
|
|
|
33006
33096
|
"enabled",
|
|
33007
33097
|
"edit_mode",
|
|
33008
33098
|
"tool_surface",
|
|
33099
|
+
"hoist_builtin_tools",
|
|
33009
33100
|
"format_on_edit",
|
|
33010
33101
|
"validate_on_edit",
|
|
33011
33102
|
"configure_warnings_delivery",
|
|
@@ -33165,7 +33256,7 @@ import { spawn as spawn3 } from "node:child_process";
|
|
|
33165
33256
|
import { createHash as createHash4 } from "node:crypto";
|
|
33166
33257
|
import {
|
|
33167
33258
|
createReadStream,
|
|
33168
|
-
existsSync as
|
|
33259
|
+
existsSync as existsSync13,
|
|
33169
33260
|
mkdirSync as mkdirSync7,
|
|
33170
33261
|
readFileSync as readFileSync10,
|
|
33171
33262
|
renameSync as renameSync6,
|
|
@@ -33173,7 +33264,7 @@ import {
|
|
|
33173
33264
|
statSync as statSync8,
|
|
33174
33265
|
writeFileSync as writeFileSync6
|
|
33175
33266
|
} from "node:fs";
|
|
33176
|
-
import { join as
|
|
33267
|
+
import { join as join15 } from "node:path";
|
|
33177
33268
|
|
|
33178
33269
|
// src/lsp-cache.ts
|
|
33179
33270
|
import {
|
|
@@ -33185,23 +33276,23 @@ import {
|
|
|
33185
33276
|
unlinkSync as unlinkSync6,
|
|
33186
33277
|
writeFileSync as writeFileSync5
|
|
33187
33278
|
} from "node:fs";
|
|
33188
|
-
import { join as
|
|
33279
|
+
import { join as join13 } from "node:path";
|
|
33189
33280
|
function lspCacheRoot() {
|
|
33190
33281
|
return getAftLspPackagesDir();
|
|
33191
33282
|
}
|
|
33192
33283
|
function lspPackageDir(npmPackage) {
|
|
33193
|
-
return
|
|
33284
|
+
return join13(lspCacheRoot(), encodeURIComponent(npmPackage));
|
|
33194
33285
|
}
|
|
33195
33286
|
function lspBinaryPath(npmPackage, binary) {
|
|
33196
|
-
return
|
|
33287
|
+
return join13(lspPackageDir(npmPackage), "node_modules", ".bin", binary);
|
|
33197
33288
|
}
|
|
33198
33289
|
function lspBinDir(npmPackage) {
|
|
33199
|
-
return
|
|
33290
|
+
return join13(lspPackageDir(npmPackage), "node_modules", ".bin");
|
|
33200
33291
|
}
|
|
33201
33292
|
function isInstalled(npmPackage, binary) {
|
|
33202
33293
|
for (const candidate of lspBinaryCandidates(binary)) {
|
|
33203
33294
|
try {
|
|
33204
|
-
if (statSync7(
|
|
33295
|
+
if (statSync7(join13(lspBinDir(npmPackage), candidate)).isFile())
|
|
33205
33296
|
return true;
|
|
33206
33297
|
} catch {}
|
|
33207
33298
|
}
|
|
@@ -33221,13 +33312,13 @@ function writeInstalledMetaIn(installDir, version2, sha256) {
|
|
|
33221
33312
|
installedAt: new Date().toISOString(),
|
|
33222
33313
|
...sha256 ? { sha256 } : {}
|
|
33223
33314
|
};
|
|
33224
|
-
writeFileSync5(
|
|
33315
|
+
writeFileSync5(join13(installDir, INSTALLED_META_FILE), JSON.stringify(meta3), "utf8");
|
|
33225
33316
|
} catch (err) {
|
|
33226
33317
|
log2(`[lsp-cache] failed to write installed-meta in ${installDir}: ${err}`);
|
|
33227
33318
|
}
|
|
33228
33319
|
}
|
|
33229
33320
|
function readInstalledMetaIn(installDir) {
|
|
33230
|
-
const path2 =
|
|
33321
|
+
const path2 = join13(installDir, INSTALLED_META_FILE);
|
|
33231
33322
|
try {
|
|
33232
33323
|
if (!statSync7(path2).isFile())
|
|
33233
33324
|
return null;
|
|
@@ -33251,7 +33342,7 @@ function readInstalledMeta(packageKey) {
|
|
|
33251
33342
|
return readInstalledMetaIn(lspPackageDir(packageKey));
|
|
33252
33343
|
}
|
|
33253
33344
|
function lockPath(npmPackage) {
|
|
33254
|
-
return
|
|
33345
|
+
return join13(lspPackageDir(npmPackage), ".aft-installing");
|
|
33255
33346
|
}
|
|
33256
33347
|
var STALE_LOCK_MS2 = 30 * 60 * 1000;
|
|
33257
33348
|
function acquireInstallLock(lockKey) {
|
|
@@ -33358,7 +33449,7 @@ async function withInstallLock(lockKey, task) {
|
|
|
33358
33449
|
}
|
|
33359
33450
|
var VERSION_CHECK_FILE = ".aft-version-check";
|
|
33360
33451
|
function readVersionCheck(npmPackage) {
|
|
33361
|
-
const file2 =
|
|
33452
|
+
const file2 = join13(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
33362
33453
|
try {
|
|
33363
33454
|
const raw = readFileSync8(file2, "utf8");
|
|
33364
33455
|
const parsed = JSON.parse(raw);
|
|
@@ -33375,7 +33466,7 @@ function readVersionCheck(npmPackage) {
|
|
|
33375
33466
|
}
|
|
33376
33467
|
function writeVersionCheck(npmPackage, latest) {
|
|
33377
33468
|
mkdirSync6(lspPackageDir(npmPackage), { recursive: true });
|
|
33378
|
-
const file2 =
|
|
33469
|
+
const file2 = join13(lspPackageDir(npmPackage), VERSION_CHECK_FILE);
|
|
33379
33470
|
const record2 = {
|
|
33380
33471
|
last_checked: new Date().toISOString(),
|
|
33381
33472
|
latest_eligible: latest
|
|
@@ -33537,8 +33628,8 @@ var NPM_LSP_TABLE = [
|
|
|
33537
33628
|
];
|
|
33538
33629
|
|
|
33539
33630
|
// src/lsp-project-relevance.ts
|
|
33540
|
-
import { existsSync as
|
|
33541
|
-
import { join as
|
|
33631
|
+
import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync9 } from "node:fs";
|
|
33632
|
+
import { join as join14 } from "node:path";
|
|
33542
33633
|
var MAX_WALK_DIRS = 200;
|
|
33543
33634
|
var MAX_WALK_DEPTH = 4;
|
|
33544
33635
|
var NOISE_DIRS = new Set([
|
|
@@ -33555,7 +33646,7 @@ function hasRootMarker(projectRoot, rootMarkers) {
|
|
|
33555
33646
|
if (!rootMarkers)
|
|
33556
33647
|
return false;
|
|
33557
33648
|
for (const marker of rootMarkers) {
|
|
33558
|
-
if (
|
|
33649
|
+
if (existsSync12(join14(projectRoot, marker)))
|
|
33559
33650
|
return true;
|
|
33560
33651
|
}
|
|
33561
33652
|
return false;
|
|
@@ -33579,7 +33670,7 @@ function hasPackageJsonDep(projectRoot, depNames) {
|
|
|
33579
33670
|
}
|
|
33580
33671
|
function readPackageJson(projectRoot) {
|
|
33581
33672
|
try {
|
|
33582
|
-
const raw = readFileSync9(
|
|
33673
|
+
const raw = readFileSync9(join14(projectRoot, "package.json"), "utf8");
|
|
33583
33674
|
const parsed = JSON.parse(raw);
|
|
33584
33675
|
if (typeof parsed !== "object" || parsed === null)
|
|
33585
33676
|
return null;
|
|
@@ -33609,7 +33700,7 @@ function relevantExtensionsInProject(projectRoot, extToServer) {
|
|
|
33609
33700
|
for (const entry of entries) {
|
|
33610
33701
|
if (entry.isDirectory()) {
|
|
33611
33702
|
if (current.depth < MAX_WALK_DEPTH && !NOISE_DIRS.has(entry.name.toLowerCase())) {
|
|
33612
|
-
queue.push({ dir:
|
|
33703
|
+
queue.push({ dir: join14(current.dir, entry.name), depth: current.depth + 1 });
|
|
33613
33704
|
}
|
|
33614
33705
|
continue;
|
|
33615
33706
|
}
|
|
@@ -33736,8 +33827,8 @@ async function resolveTargetVersion(spec, config2, fetchImpl = fetch) {
|
|
|
33736
33827
|
}
|
|
33737
33828
|
function ensureInstallAnchor(cwd) {
|
|
33738
33829
|
try {
|
|
33739
|
-
const stub =
|
|
33740
|
-
if (!
|
|
33830
|
+
const stub = join15(cwd, "package.json");
|
|
33831
|
+
if (!existsSync13(stub)) {
|
|
33741
33832
|
writeFileSync6(stub, `${JSON.stringify({ name: "aft-lsp-cache", version: "0.0.0", private: true })}
|
|
33742
33833
|
`);
|
|
33743
33834
|
}
|
|
@@ -33928,10 +34019,10 @@ function sha256OfFileSync(path2) {
|
|
|
33928
34019
|
}
|
|
33929
34020
|
function quarantineCachedNpmInstall(spec, reason) {
|
|
33930
34021
|
const packageDir = lspPackageDir(spec.npm);
|
|
33931
|
-
const dest =
|
|
34022
|
+
const dest = join15(packageDir, "..", ".quarantine", encodeURIComponent(spec.npm), `${Date.now()}`);
|
|
33932
34023
|
warn2(`[lsp] tofu_mismatch ${spec.npm}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
33933
34024
|
try {
|
|
33934
|
-
mkdirSync7(
|
|
34025
|
+
mkdirSync7(join15(dest, ".."), { recursive: true });
|
|
33935
34026
|
rmSync4(dest, { recursive: true, force: true });
|
|
33936
34027
|
renameSync6(packageDir, dest);
|
|
33937
34028
|
} catch (err) {
|
|
@@ -34019,7 +34110,7 @@ import {
|
|
|
34019
34110
|
copyFileSync as copyFileSync4,
|
|
34020
34111
|
createReadStream as createReadStream2,
|
|
34021
34112
|
createWriteStream as createWriteStream3,
|
|
34022
|
-
existsSync as
|
|
34113
|
+
existsSync as existsSync14,
|
|
34023
34114
|
lstatSync as lstatSync2,
|
|
34024
34115
|
mkdirSync as mkdirSync8,
|
|
34025
34116
|
readdirSync as readdirSync5,
|
|
@@ -34032,7 +34123,7 @@ import {
|
|
|
34032
34123
|
unlinkSync as unlinkSync7,
|
|
34033
34124
|
writeFileSync as writeFileSync7
|
|
34034
34125
|
} from "node:fs";
|
|
34035
|
-
import { dirname as dirname6, join as
|
|
34126
|
+
import { dirname as dirname6, join as join16, relative as relative3, resolve as resolve8 } from "node:path";
|
|
34036
34127
|
import { Readable as Readable3 } from "node:stream";
|
|
34037
34128
|
import { pipeline as pipeline3 } from "node:stream/promises";
|
|
34038
34129
|
|
|
@@ -34125,23 +34216,23 @@ function ghCacheRoot() {
|
|
|
34125
34216
|
return getAftLspBinariesDir();
|
|
34126
34217
|
}
|
|
34127
34218
|
function ghPackageDir(spec) {
|
|
34128
|
-
return
|
|
34219
|
+
return join16(ghCacheRoot(), spec.id);
|
|
34129
34220
|
}
|
|
34130
34221
|
function ghBinDir(spec) {
|
|
34131
|
-
return
|
|
34222
|
+
return join16(ghPackageDir(spec), "bin");
|
|
34132
34223
|
}
|
|
34133
34224
|
function ghExtractDir(spec) {
|
|
34134
|
-
return
|
|
34225
|
+
return join16(ghPackageDir(spec), "extracted");
|
|
34135
34226
|
}
|
|
34136
34227
|
var INSTALLED_META_FILE2 = ".aft-installed";
|
|
34137
34228
|
function ghBinaryPath(spec, platform) {
|
|
34138
34229
|
const ext = platform === "win32" ? ".exe" : "";
|
|
34139
|
-
return
|
|
34230
|
+
return join16(ghBinDir(spec), `${spec.binary}${ext}`);
|
|
34140
34231
|
}
|
|
34141
34232
|
function isGithubInstalled(spec, platform) {
|
|
34142
34233
|
for (const candidate of ghBinaryCandidates(spec, platform)) {
|
|
34143
34234
|
try {
|
|
34144
|
-
if (statSync9(
|
|
34235
|
+
if (statSync9(join16(ghBinDir(spec), candidate)).isFile())
|
|
34145
34236
|
return true;
|
|
34146
34237
|
} catch {}
|
|
34147
34238
|
}
|
|
@@ -34154,7 +34245,7 @@ function ghBinaryCandidates(spec, platform) {
|
|
|
34154
34245
|
}
|
|
34155
34246
|
function readGithubInstalledMetaIn(installDir) {
|
|
34156
34247
|
try {
|
|
34157
|
-
const path2 =
|
|
34248
|
+
const path2 = join16(installDir, INSTALLED_META_FILE2);
|
|
34158
34249
|
if (!statSync9(path2).isFile())
|
|
34159
34250
|
return null;
|
|
34160
34251
|
const parsed = JSON.parse(readFileSync11(path2, "utf8"));
|
|
@@ -34181,7 +34272,7 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
|
|
|
34181
34272
|
binarySha256,
|
|
34182
34273
|
...archiveSha256 ? { archiveSha256 } : {}
|
|
34183
34274
|
};
|
|
34184
|
-
writeFileSync7(
|
|
34275
|
+
writeFileSync7(join16(installDir, INSTALLED_META_FILE2), JSON.stringify(meta3), "utf8");
|
|
34185
34276
|
} catch (err) {
|
|
34186
34277
|
warn2(`[lsp] failed to write github installed metadata in ${installDir}: ${err}`);
|
|
34187
34278
|
}
|
|
@@ -34430,7 +34521,7 @@ function validateExtraction(stagingRoot) {
|
|
|
34430
34521
|
throw new Error(`failed to read staging dir ${dir}: ${err}`);
|
|
34431
34522
|
}
|
|
34432
34523
|
for (const entry of entries) {
|
|
34433
|
-
const full =
|
|
34524
|
+
const full = join16(dir, entry);
|
|
34434
34525
|
let lst;
|
|
34435
34526
|
try {
|
|
34436
34527
|
lst = lstatSync2(full);
|
|
@@ -34518,7 +34609,7 @@ function extractArchiveSafely(archivePath, destDir, archiveType) {
|
|
|
34518
34609
|
}
|
|
34519
34610
|
function quarantineCachedGithubInstall(spec, reason) {
|
|
34520
34611
|
const packageDir = ghPackageDir(spec);
|
|
34521
|
-
const dest =
|
|
34612
|
+
const dest = join16(ghCacheRoot(), ".quarantine", encodeURIComponent(spec.id), `${Date.now()}`);
|
|
34522
34613
|
warn2(`[lsp] tofu_mismatch ${spec.id}: ${reason}; quarantining ${packageDir} -> ${dest}`);
|
|
34523
34614
|
try {
|
|
34524
34615
|
mkdirSync8(dirname6(dest), { recursive: true });
|
|
@@ -34531,7 +34622,7 @@ function quarantineCachedGithubInstall(spec, reason) {
|
|
|
34531
34622
|
function validateCachedGithubInstall(spec, platform) {
|
|
34532
34623
|
const packageDir = ghPackageDir(spec);
|
|
34533
34624
|
const meta3 = readGithubInstalledMetaIn(packageDir);
|
|
34534
|
-
const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) =>
|
|
34625
|
+
const binaryPath = ghBinaryCandidates(spec, platform).map((candidate) => join16(ghBinDir(spec), candidate)).find((candidate) => {
|
|
34535
34626
|
try {
|
|
34536
34627
|
return statSync9(candidate).isFile();
|
|
34537
34628
|
} catch {
|
|
@@ -34609,7 +34700,7 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
|
|
|
34609
34700
|
}
|
|
34610
34701
|
const pkgDir = ghPackageDir(spec);
|
|
34611
34702
|
const extractDir = ghExtractDir(spec);
|
|
34612
|
-
const archivePath =
|
|
34703
|
+
const archivePath = join16(pkgDir, expected.name);
|
|
34613
34704
|
log2(`[lsp] downloading ${spec.id} ${tag} → ${matchingAsset.url}`);
|
|
34614
34705
|
try {
|
|
34615
34706
|
await downloadFile(matchingAsset.url, archivePath, fetchImpl, matchingAsset.size, signal);
|
|
@@ -34649,8 +34740,8 @@ async function downloadAndInstall(spec, tag, assets, platform, arch, fetchImpl,
|
|
|
34649
34740
|
unlinkSync7(archivePath);
|
|
34650
34741
|
} catch {}
|
|
34651
34742
|
}
|
|
34652
|
-
const innerBinaryPath =
|
|
34653
|
-
if (!
|
|
34743
|
+
const innerBinaryPath = join16(extractDir, spec.binaryPathInArchive(platform, arch, version2));
|
|
34744
|
+
if (!existsSync14(innerBinaryPath)) {
|
|
34654
34745
|
error2(`[lsp] ${spec.id}: extracted binary not found at ${innerBinaryPath}`);
|
|
34655
34746
|
return null;
|
|
34656
34747
|
}
|
|
@@ -34734,7 +34825,7 @@ function runGithubAutoInstall(relevantServers, config2, fetchImpl = fetch) {
|
|
|
34734
34825
|
if (!host) {
|
|
34735
34826
|
for (const spec of GITHUB_LSP_TABLE) {
|
|
34736
34827
|
try {
|
|
34737
|
-
if (
|
|
34828
|
+
if (existsSync14(ghBinDir(spec))) {
|
|
34738
34829
|
cachedBinDirs.push(ghBinDir(spec));
|
|
34739
34830
|
}
|
|
34740
34831
|
} catch {}
|
|
@@ -34961,6 +35052,17 @@ function sendFeatureAnnouncement(version2, features, footer, storageDir) {
|
|
|
34961
35052
|
|
|
34962
35053
|
// src/bash-wait-detach.ts
|
|
34963
35054
|
var BASH_TRANSPORT_TIMEOUT_MS = 30000;
|
|
35055
|
+
var BASH_WAIT_DETACH_MAGIC_KEYWORD = "&detach";
|
|
35056
|
+
var EMPTY_DETACH_MESSAGE = "(requested background detach)";
|
|
35057
|
+
function stripUserMessageDetachKeyword(messageText) {
|
|
35058
|
+
if (!messageText.includes(BASH_WAIT_DETACH_MAGIC_KEYWORD))
|
|
35059
|
+
return messageText;
|
|
35060
|
+
const stripped = messageText.replaceAll(BASH_WAIT_DETACH_MAGIC_KEYWORD, "").replace(/[ \t]{2,}/g, " ");
|
|
35061
|
+
return stripped.trim() === "" ? EMPTY_DETACH_MESSAGE : stripped;
|
|
35062
|
+
}
|
|
35063
|
+
function shouldDetachBashWaitOnUserMessage(config2, messageText) {
|
|
35064
|
+
return resolveBashConfig(config2).detach_on_user_message || messageText.includes(BASH_WAIT_DETACH_MAGIC_KEYWORD);
|
|
35065
|
+
}
|
|
34964
35066
|
async function sendBashWaitDetach(bridge, sessionID) {
|
|
34965
35067
|
const response = await bridge.send("bash_wait_detach", { session_id: sessionID }, { keepBridgeOnTimeout: true, transportTimeoutMs: BASH_TRANSPORT_TIMEOUT_MS });
|
|
34966
35068
|
if (response.success === false) {
|
|
@@ -35087,111 +35189,31 @@ import { Type as Type2 } from "typebox";
|
|
|
35087
35189
|
|
|
35088
35190
|
// src/tools/diff-format.ts
|
|
35089
35191
|
import { diffLines } from "diff";
|
|
35090
|
-
var DEFAULT_CONTEXT_LINES = 4;
|
|
35091
|
-
function formatDiffForPi(oldContent, newContent, contextLines = DEFAULT_CONTEXT_LINES) {
|
|
35092
|
-
const parts = diffLines(oldContent, newContent);
|
|
35093
|
-
const output = [];
|
|
35094
|
-
const oldLines = oldContent.split(`
|
|
35095
|
-
`);
|
|
35096
|
-
const newLines = newContent.split(`
|
|
35097
|
-
`);
|
|
35098
|
-
const maxLineNum = Math.max(oldLines.length, newLines.length);
|
|
35099
|
-
const lineNumWidth = String(maxLineNum).length;
|
|
35100
|
-
const pad = (n) => String(n).padStart(lineNumWidth, " ");
|
|
35101
|
-
const blank = " ".repeat(lineNumWidth);
|
|
35102
|
-
let oldLineNum = 1;
|
|
35103
|
-
let newLineNum = 1;
|
|
35104
|
-
let lastWasChange = false;
|
|
35105
|
-
let firstChangedLine;
|
|
35106
|
-
for (let i = 0;i < parts.length; i++) {
|
|
35107
|
-
const part = parts[i];
|
|
35108
|
-
const raw = part.value.split(`
|
|
35109
|
-
`);
|
|
35110
|
-
if (raw[raw.length - 1] === "")
|
|
35111
|
-
raw.pop();
|
|
35112
|
-
if (part.added || part.removed) {
|
|
35113
|
-
if (firstChangedLine === undefined)
|
|
35114
|
-
firstChangedLine = newLineNum;
|
|
35115
|
-
for (const line of raw) {
|
|
35116
|
-
if (part.added) {
|
|
35117
|
-
output.push(`+${pad(newLineNum)} ${line}`);
|
|
35118
|
-
newLineNum++;
|
|
35119
|
-
} else {
|
|
35120
|
-
output.push(`-${pad(oldLineNum)} ${line}`);
|
|
35121
|
-
oldLineNum++;
|
|
35122
|
-
}
|
|
35123
|
-
}
|
|
35124
|
-
lastWasChange = true;
|
|
35125
|
-
continue;
|
|
35126
|
-
}
|
|
35127
|
-
const nextIsChange = i < parts.length - 1 && (parts[i + 1].added || parts[i + 1].removed);
|
|
35128
|
-
const hasLeading = lastWasChange;
|
|
35129
|
-
const hasTrailing = nextIsChange;
|
|
35130
|
-
if (hasLeading && hasTrailing) {
|
|
35131
|
-
if (raw.length <= contextLines * 2) {
|
|
35132
|
-
for (const line of raw) {
|
|
35133
|
-
output.push(` ${pad(oldLineNum)} ${line}`);
|
|
35134
|
-
oldLineNum++;
|
|
35135
|
-
newLineNum++;
|
|
35136
|
-
}
|
|
35137
|
-
} else {
|
|
35138
|
-
for (const line of raw.slice(0, contextLines)) {
|
|
35139
|
-
output.push(` ${pad(oldLineNum)} ${line}`);
|
|
35140
|
-
oldLineNum++;
|
|
35141
|
-
newLineNum++;
|
|
35142
|
-
}
|
|
35143
|
-
const skipped = raw.length - contextLines * 2;
|
|
35144
|
-
output.push(` ${blank} ...`);
|
|
35145
|
-
oldLineNum += skipped;
|
|
35146
|
-
newLineNum += skipped;
|
|
35147
|
-
for (const line of raw.slice(raw.length - contextLines)) {
|
|
35148
|
-
output.push(` ${pad(oldLineNum)} ${line}`);
|
|
35149
|
-
oldLineNum++;
|
|
35150
|
-
newLineNum++;
|
|
35151
|
-
}
|
|
35152
|
-
}
|
|
35153
|
-
} else if (hasLeading) {
|
|
35154
|
-
const shown = raw.slice(0, contextLines);
|
|
35155
|
-
for (const line of shown) {
|
|
35156
|
-
output.push(` ${pad(oldLineNum)} ${line}`);
|
|
35157
|
-
oldLineNum++;
|
|
35158
|
-
newLineNum++;
|
|
35159
|
-
}
|
|
35160
|
-
const skipped = raw.length - shown.length;
|
|
35161
|
-
if (skipped > 0) {
|
|
35162
|
-
output.push(` ${blank} ...`);
|
|
35163
|
-
oldLineNum += skipped;
|
|
35164
|
-
newLineNum += skipped;
|
|
35165
|
-
}
|
|
35166
|
-
} else if (hasTrailing) {
|
|
35167
|
-
const shownCount = Math.min(contextLines, raw.length);
|
|
35168
|
-
const shown = raw.slice(raw.length - shownCount);
|
|
35169
|
-
const skipped = raw.length - shown.length;
|
|
35170
|
-
if (skipped > 0) {
|
|
35171
|
-
output.push(` ${blank} ...`);
|
|
35172
|
-
oldLineNum += skipped;
|
|
35173
|
-
newLineNum += skipped;
|
|
35174
|
-
}
|
|
35175
|
-
for (const line of shown) {
|
|
35176
|
-
output.push(` ${pad(oldLineNum)} ${line}`);
|
|
35177
|
-
oldLineNum++;
|
|
35178
|
-
newLineNum++;
|
|
35179
|
-
}
|
|
35180
|
-
} else {
|
|
35181
|
-
oldLineNum += raw.length;
|
|
35182
|
-
newLineNum += raw.length;
|
|
35183
|
-
}
|
|
35184
|
-
lastWasChange = false;
|
|
35185
|
-
}
|
|
35186
|
-
return { diff: output.join(`
|
|
35187
|
-
`), firstChangedLine };
|
|
35188
|
-
}
|
|
35189
35192
|
|
|
35190
35193
|
// src/tools/render-helpers.ts
|
|
35191
35194
|
import { homedir as homedir13 } from "node:os";
|
|
35192
35195
|
import { renderDiff } from "@earendil-works/pi-coding-agent";
|
|
35193
35196
|
import { Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
35194
35197
|
var NATIVE_COLLAPSED_RESULT_MAX_LINES = 5;
|
|
35198
|
+
function normalizeTerminalText(text) {
|
|
35199
|
+
return text.replace(/\r/g, "");
|
|
35200
|
+
}
|
|
35201
|
+
|
|
35202
|
+
class TerminalSafeComponent {
|
|
35203
|
+
component;
|
|
35204
|
+
constructor(component) {
|
|
35205
|
+
this.component = component;
|
|
35206
|
+
}
|
|
35207
|
+
render(width) {
|
|
35208
|
+
return this.component.render(width).map(normalizeTerminalText);
|
|
35209
|
+
}
|
|
35210
|
+
invalidate() {
|
|
35211
|
+
this.component.invalidate?.();
|
|
35212
|
+
}
|
|
35213
|
+
handleInput(data) {
|
|
35214
|
+
this.component.handleInput?.(data);
|
|
35215
|
+
}
|
|
35216
|
+
}
|
|
35195
35217
|
function reuseText(last) {
|
|
35196
35218
|
return last instanceof Text ? last : new Text("", 0, 0);
|
|
35197
35219
|
}
|
|
@@ -35244,8 +35266,10 @@ function collapsibleResult({
|
|
|
35244
35266
|
expanded,
|
|
35245
35267
|
context
|
|
35246
35268
|
}) {
|
|
35247
|
-
|
|
35248
|
-
|
|
35269
|
+
const renderedAtCollapseWidth = full.render(200);
|
|
35270
|
+
const terminalSafeFull = renderedAtCollapseWidth.some((line) => line.includes("\r")) ? new TerminalSafeComponent(full) : full;
|
|
35271
|
+
if (expanded === true || renderedAtCollapseWidth.length <= NATIVE_COLLAPSED_RESULT_MAX_LINES) {
|
|
35272
|
+
return terminalSafeFull;
|
|
35249
35273
|
}
|
|
35250
35274
|
const text = reuseText(context.lastComponent);
|
|
35251
35275
|
text.setText(`
|
|
@@ -35356,18 +35380,122 @@ function formatUnifiedDiffForPi(unifiedDiff) {
|
|
|
35356
35380
|
if (entries.length === 0)
|
|
35357
35381
|
return "";
|
|
35358
35382
|
const width = String(entries.reduce((max, entry) => Math.max(max, entry.line), 1)).length;
|
|
35359
|
-
return entries.map((entry) => `${entry.prefix}${String(entry.line).padStart(width, " ")} ${entry.text}`).join(`
|
|
35360
|
-
`);
|
|
35383
|
+
return normalizeTerminalText(entries.map((entry) => `${entry.prefix}${String(entry.line).padStart(width, " ")} ${entry.text}`).join(`
|
|
35384
|
+
`));
|
|
35361
35385
|
}
|
|
35362
35386
|
function renderUnifiedDiff(unifiedDiff) {
|
|
35363
35387
|
const piDiff = formatUnifiedDiffForPi(unifiedDiff);
|
|
35364
35388
|
if (!piDiff)
|
|
35365
35389
|
return "";
|
|
35366
35390
|
try {
|
|
35367
|
-
return renderDiff(piDiff);
|
|
35391
|
+
return normalizeTerminalText(renderDiff(piDiff));
|
|
35368
35392
|
} catch {
|
|
35369
|
-
return piDiff;
|
|
35393
|
+
return normalizeTerminalText(piDiff);
|
|
35394
|
+
}
|
|
35395
|
+
}
|
|
35396
|
+
|
|
35397
|
+
// src/tools/diff-format.ts
|
|
35398
|
+
var DEFAULT_CONTEXT_LINES = 4;
|
|
35399
|
+
function formatDiffForPi(oldContent, newContent, contextLines = DEFAULT_CONTEXT_LINES) {
|
|
35400
|
+
const parts = diffLines(oldContent, newContent);
|
|
35401
|
+
const output = [];
|
|
35402
|
+
const oldLines = oldContent.split(`
|
|
35403
|
+
`);
|
|
35404
|
+
const newLines = newContent.split(`
|
|
35405
|
+
`);
|
|
35406
|
+
const maxLineNum = Math.max(oldLines.length, newLines.length);
|
|
35407
|
+
const lineNumWidth = String(maxLineNum).length;
|
|
35408
|
+
const pad = (n) => String(n).padStart(lineNumWidth, " ");
|
|
35409
|
+
const blank = " ".repeat(lineNumWidth);
|
|
35410
|
+
let oldLineNum = 1;
|
|
35411
|
+
let newLineNum = 1;
|
|
35412
|
+
let lastWasChange = false;
|
|
35413
|
+
let firstChangedLine;
|
|
35414
|
+
for (let i = 0;i < parts.length; i++) {
|
|
35415
|
+
const part = parts[i];
|
|
35416
|
+
const raw = part.value.split(`
|
|
35417
|
+
`);
|
|
35418
|
+
if (raw[raw.length - 1] === "")
|
|
35419
|
+
raw.pop();
|
|
35420
|
+
if (part.added || part.removed) {
|
|
35421
|
+
if (firstChangedLine === undefined)
|
|
35422
|
+
firstChangedLine = newLineNum;
|
|
35423
|
+
for (const line of raw) {
|
|
35424
|
+
if (part.added) {
|
|
35425
|
+
output.push(`+${pad(newLineNum)} ${line}`);
|
|
35426
|
+
newLineNum++;
|
|
35427
|
+
} else {
|
|
35428
|
+
output.push(`-${pad(oldLineNum)} ${line}`);
|
|
35429
|
+
oldLineNum++;
|
|
35430
|
+
}
|
|
35431
|
+
}
|
|
35432
|
+
lastWasChange = true;
|
|
35433
|
+
continue;
|
|
35434
|
+
}
|
|
35435
|
+
const nextIsChange = i < parts.length - 1 && (parts[i + 1].added || parts[i + 1].removed);
|
|
35436
|
+
const hasLeading = lastWasChange;
|
|
35437
|
+
const hasTrailing = nextIsChange;
|
|
35438
|
+
if (hasLeading && hasTrailing) {
|
|
35439
|
+
if (raw.length <= contextLines * 2) {
|
|
35440
|
+
for (const line of raw) {
|
|
35441
|
+
output.push(` ${pad(oldLineNum)} ${line}`);
|
|
35442
|
+
oldLineNum++;
|
|
35443
|
+
newLineNum++;
|
|
35444
|
+
}
|
|
35445
|
+
} else {
|
|
35446
|
+
for (const line of raw.slice(0, contextLines)) {
|
|
35447
|
+
output.push(` ${pad(oldLineNum)} ${line}`);
|
|
35448
|
+
oldLineNum++;
|
|
35449
|
+
newLineNum++;
|
|
35450
|
+
}
|
|
35451
|
+
const skipped = raw.length - contextLines * 2;
|
|
35452
|
+
output.push(` ${blank} ...`);
|
|
35453
|
+
oldLineNum += skipped;
|
|
35454
|
+
newLineNum += skipped;
|
|
35455
|
+
for (const line of raw.slice(raw.length - contextLines)) {
|
|
35456
|
+
output.push(` ${pad(oldLineNum)} ${line}`);
|
|
35457
|
+
oldLineNum++;
|
|
35458
|
+
newLineNum++;
|
|
35459
|
+
}
|
|
35460
|
+
}
|
|
35461
|
+
} else if (hasLeading) {
|
|
35462
|
+
const shown = raw.slice(0, contextLines);
|
|
35463
|
+
for (const line of shown) {
|
|
35464
|
+
output.push(` ${pad(oldLineNum)} ${line}`);
|
|
35465
|
+
oldLineNum++;
|
|
35466
|
+
newLineNum++;
|
|
35467
|
+
}
|
|
35468
|
+
const skipped = raw.length - shown.length;
|
|
35469
|
+
if (skipped > 0) {
|
|
35470
|
+
output.push(` ${blank} ...`);
|
|
35471
|
+
oldLineNum += skipped;
|
|
35472
|
+
newLineNum += skipped;
|
|
35473
|
+
}
|
|
35474
|
+
} else if (hasTrailing) {
|
|
35475
|
+
const shownCount = Math.min(contextLines, raw.length);
|
|
35476
|
+
const shown = raw.slice(raw.length - shownCount);
|
|
35477
|
+
const skipped = raw.length - shown.length;
|
|
35478
|
+
if (skipped > 0) {
|
|
35479
|
+
output.push(` ${blank} ...`);
|
|
35480
|
+
oldLineNum += skipped;
|
|
35481
|
+
newLineNum += skipped;
|
|
35482
|
+
}
|
|
35483
|
+
for (const line of shown) {
|
|
35484
|
+
output.push(` ${pad(oldLineNum)} ${line}`);
|
|
35485
|
+
oldLineNum++;
|
|
35486
|
+
newLineNum++;
|
|
35487
|
+
}
|
|
35488
|
+
} else {
|
|
35489
|
+
oldLineNum += raw.length;
|
|
35490
|
+
newLineNum += raw.length;
|
|
35491
|
+
}
|
|
35492
|
+
lastWasChange = false;
|
|
35370
35493
|
}
|
|
35494
|
+
return {
|
|
35495
|
+
diff: normalizeTerminalText(output.join(`
|
|
35496
|
+
`)),
|
|
35497
|
+
firstChangedLine
|
|
35498
|
+
};
|
|
35371
35499
|
}
|
|
35372
35500
|
|
|
35373
35501
|
// src/tools/hoisted.ts
|
|
@@ -35606,13 +35734,18 @@ function renderReadCall(args, theme, context) {
|
|
|
35606
35734
|
return text;
|
|
35607
35735
|
}
|
|
35608
35736
|
function registerHoistedTools(pi, ctx, surface) {
|
|
35737
|
+
const prefix = surface.hoistBuiltinTools === false ? "aft_" : "";
|
|
35738
|
+
const readName = `${prefix}read`;
|
|
35739
|
+
const writeName = `${prefix}write`;
|
|
35740
|
+
const editName = `${prefix}edit`;
|
|
35741
|
+
const grepName = `${prefix}grep`;
|
|
35609
35742
|
if (surface.hoistRead) {
|
|
35610
35743
|
pi.registerTool(withPathAliasPreparation({
|
|
35611
|
-
name:
|
|
35612
|
-
label:
|
|
35744
|
+
name: readName,
|
|
35745
|
+
label: readName,
|
|
35613
35746
|
description: "Read file contents with line numbers. Backed by AFT's indexed Rust reader — faster than the built-in `read` on large repos. Images are returned as attachments on vision-capable models; PDFs and non-vision models are not yet supported.",
|
|
35614
35747
|
promptSnippet: "Read file contents (supports offset/limit for large files)",
|
|
35615
|
-
promptGuidelines: [
|
|
35748
|
+
promptGuidelines: [`Use ${readName} to examine files instead of cat or sed.`],
|
|
35616
35749
|
parameters: ReadParams,
|
|
35617
35750
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
35618
35751
|
const bridge = bridgeFor(ctx, extCtx.cwd);
|
|
@@ -35674,11 +35807,11 @@ PDFs aren't supported on the Pi harness yet.`, response);
|
|
|
35674
35807
|
if (surface.hoistWrite) {
|
|
35675
35808
|
const writeBackupText = ctx.config.backup?.enabled === false ? "Backup capture is disabled by user config." : "Existing files are backed up before overwriting (undo via aft_safety).";
|
|
35676
35809
|
pi.registerTool(withPathAliasPreparation({
|
|
35677
|
-
name:
|
|
35678
|
-
label:
|
|
35679
|
-
description: `Write content to a file, creating it and parent directories automatically. ${writeBackupText} Auto-formats when the project has a formatter configured. Uses \`path\`. For partial edits, use the \`
|
|
35810
|
+
name: writeName,
|
|
35811
|
+
label: writeName,
|
|
35812
|
+
description: `Write content to a file, creating it and parent directories automatically. ${writeBackupText} Auto-formats when the project has a formatter configured. Uses \`path\`. For partial edits, use the \`${editName}\` tool.`,
|
|
35680
35813
|
promptSnippet: "Create or overwrite files (uses path; auto-formats)",
|
|
35681
|
-
promptGuidelines: [
|
|
35814
|
+
promptGuidelines: [`Use ${writeName} only for new files or complete rewrites.`],
|
|
35682
35815
|
parameters: WriteParams,
|
|
35683
35816
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
35684
35817
|
const filePathArg = mutationFilePathArg(params);
|
|
@@ -35710,10 +35843,10 @@ PDFs aren't supported on the Pi harness yet.`, response);
|
|
|
35710
35843
|
}
|
|
35711
35844
|
if (surface.hoistEdit && ctx.hashlineEffective === true) {
|
|
35712
35845
|
pi.registerTool({
|
|
35713
|
-
name:
|
|
35714
|
-
label:
|
|
35846
|
+
name: editName,
|
|
35847
|
+
label: editName,
|
|
35715
35848
|
description: HASHLINE_EDIT_DESCRIPTION,
|
|
35716
|
-
promptSnippet:
|
|
35849
|
+
promptSnippet: `Apply a tagged hashline patch through the ${editName} tool`,
|
|
35717
35850
|
promptGuidelines: [
|
|
35718
35851
|
"Read a file to obtain its current hashline tag before editing it.",
|
|
35719
35852
|
"Pass exactly one patch string; paths and tags belong in patch section headers."
|
|
@@ -35721,8 +35854,9 @@ PDFs aren't supported on the Pi harness yet.`, response);
|
|
|
35721
35854
|
parameters: HashlineEditParams,
|
|
35722
35855
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
35723
35856
|
const bridge = bridgeFor(ctx, extCtx.cwd);
|
|
35857
|
+
const sessionId = resolveSessionId(extCtx);
|
|
35724
35858
|
const rawArgs = { patch: params.patch };
|
|
35725
|
-
const preflight = await
|
|
35859
|
+
const preflight = await callToolCallForSession(bridge, "hashline_preflight", rawArgs, sessionId, extCtx);
|
|
35726
35860
|
if (preflight.success === false)
|
|
35727
35861
|
throw toolErrorFromResponse("edit", preflight);
|
|
35728
35862
|
for (const target of [
|
|
@@ -35733,10 +35867,12 @@ PDFs aren't supported on the Pi harness yet.`, response);
|
|
|
35733
35867
|
restrictToProjectRoot: surface.restrictToProjectRoot
|
|
35734
35868
|
});
|
|
35735
35869
|
}
|
|
35736
|
-
const preview = await
|
|
35870
|
+
const preview = await callToolCallForSession(bridge, "edit", rawArgs, sessionId, extCtx, {
|
|
35871
|
+
preview: true
|
|
35872
|
+
});
|
|
35737
35873
|
if (preview.success === false)
|
|
35738
35874
|
throw toolErrorFromResponse("edit", preview);
|
|
35739
|
-
const response = await
|
|
35875
|
+
const response = await callToolCallForSession(bridge, "edit", rawArgs, sessionId, extCtx);
|
|
35740
35876
|
if (response.success === false)
|
|
35741
35877
|
throw toolErrorFromResponse("edit", response);
|
|
35742
35878
|
return buildMutationResult(response);
|
|
@@ -35745,13 +35881,13 @@ PDFs aren't supported on the Pi harness yet.`, response);
|
|
|
35745
35881
|
}
|
|
35746
35882
|
if (surface.hoistEdit && ctx.hashlineEffective !== true) {
|
|
35747
35883
|
pi.registerTool(withPathAliasPreparation({
|
|
35748
|
-
name:
|
|
35749
|
-
label:
|
|
35884
|
+
name: editName,
|
|
35885
|
+
label: editName,
|
|
35750
35886
|
description: "Edit part of a file via `appendContent`, batch `edits[]`, or symbol plus `content`. Batch `{ oldString, newString, replaceAll: true }` replaces every match. Provide exactly one mode per call: appendContent, edits[], or symbol plus content (mixing modes is rejected).",
|
|
35751
35887
|
promptSnippet: "Partial file edits via appendContent, edits[], or symbol plus content (exactly one mode per call).",
|
|
35752
35888
|
promptGuidelines: [
|
|
35753
|
-
|
|
35754
|
-
|
|
35889
|
+
`Prefer ${editName} over ${writeName} when changing part of an existing file.`,
|
|
35890
|
+
`Use ${editName} with appendContent when adding text to the end of a file.`,
|
|
35755
35891
|
"Use edits[] for multiple atomic changes in one file.",
|
|
35756
35892
|
"Include enough surrounding context in an edits[] find/replace item to make the match unique, or set replaceAll/occurrence explicitly."
|
|
35757
35893
|
],
|
|
@@ -35793,11 +35929,11 @@ PDFs aren't supported on the Pi harness yet.`, response);
|
|
|
35793
35929
|
}
|
|
35794
35930
|
if (surface.hoistGrep) {
|
|
35795
35931
|
pi.registerTool(withPathAliasPreparation({
|
|
35796
|
-
name:
|
|
35797
|
-
label:
|
|
35932
|
+
name: grepName,
|
|
35933
|
+
label: grepName,
|
|
35798
35934
|
description: "Search for a regex pattern across files. Uses AFT's trigram index inside the project root for fast repeated queries, and falls back to ripgrep for paths outside the project root.",
|
|
35799
35935
|
promptSnippet: "Fast regex search across files (trigram-indexed inside the project root)",
|
|
35800
|
-
promptGuidelines: [
|
|
35936
|
+
promptGuidelines: [`Prefer ${grepName} over bash-invoked find/rg for in-project searches.`],
|
|
35801
35937
|
parameters: GrepParams,
|
|
35802
35938
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
35803
35939
|
const bridge = bridgeFor(ctx, extCtx.cwd);
|
|
@@ -35980,7 +36116,7 @@ ${summary2}${suffix}`);
|
|
|
35980
36116
|
} catch {
|
|
35981
36117
|
renderedDiff = diff;
|
|
35982
36118
|
}
|
|
35983
|
-
container.addChild(new Text2(renderedDiff, 1, 0));
|
|
36119
|
+
container.addChild(new Text2(normalizeTerminalText(renderedDiff), 1, 0));
|
|
35984
36120
|
const rawPath = context.args && typeof context.args === "object" && typeof context.args.path === "string" ? context.args.path : undefined;
|
|
35985
36121
|
const summaryPath = rawPath ? ` ${shortenPath3(rawPath)}` : "";
|
|
35986
36122
|
const summary = `edited${summaryPath} (+${details?.additions ?? 0}/-${details?.deletions ?? 0})`;
|
|
@@ -36286,7 +36422,7 @@ var BashBaseParams = {
|
|
|
36286
36422
|
description: "Human-readable description shown in UI logs. Helps users understand what the command does without reading shell syntax."
|
|
36287
36423
|
})),
|
|
36288
36424
|
wait: Type4.Optional(Type4.Boolean({
|
|
36289
|
-
description: "When true, run in the foreground without auto-promoting and wait until the command finishes or reaches its timeout;
|
|
36425
|
+
description: "When true, run in the foreground without auto-promoting and wait until the command finishes or reaches its timeout; a new user message detaches by default, while `bash.detach_on_user_message: false` keeps it blocking unless the message contains the literal `&detach`. The token is stripped before delivery; the rest of the message is preserved, and a token-only message becomes `(requested background detach)`. Use only when you know the result is required before doing anything else."
|
|
36290
36426
|
})),
|
|
36291
36427
|
sandbox: Type4.Optional(Type4.Literal("host", {
|
|
36292
36428
|
description: "Request one-command approval to run unsandboxed on the host; use only when native sandboxing blocks required work, and note that it is a no-op when sandboxing is disabled."
|
|
@@ -36381,11 +36517,17 @@ ${ask.command ?? ""}
|
|
|
36381
36517
|
Working directory:
|
|
36382
36518
|
${ask.cwd ?? ""}`;
|
|
36383
36519
|
}
|
|
36384
|
-
|
|
36520
|
+
function piPowerShellAskText(command) {
|
|
36521
|
+
return `PowerShell commands are conservatively approved one at a time because AFT's POSIX shell scanner cannot safely interpret PowerShell syntax.
|
|
36522
|
+
|
|
36523
|
+
Exact command:
|
|
36524
|
+
${command}`;
|
|
36525
|
+
}
|
|
36526
|
+
async function callBashWithPermissionLoop(bridge, params, extCtx, options, bridgeCommand = "bash") {
|
|
36385
36527
|
const granted = Array.isArray(params.permissions_granted) ? params.permissions_granted.filter((value) => typeof value === "string") : [];
|
|
36386
36528
|
for (let round = 0;round < 8; round++) {
|
|
36387
36529
|
try {
|
|
36388
|
-
return await callBashBridge(bridge,
|
|
36530
|
+
return await callBashBridge(bridge, bridgeCommand, { ...params, ...granted.length > 0 ? { permissions_granted: granted } : {} }, extCtx, options);
|
|
36389
36531
|
} catch (error53) {
|
|
36390
36532
|
if (!(error53 instanceof BridgeError)) {
|
|
36391
36533
|
if (error53 instanceof Error && error53.message.includes("permission_required")) {
|
|
@@ -36396,19 +36538,30 @@ async function callBashWithPermissionLoop(bridge, params, extCtx, options) {
|
|
|
36396
36538
|
if (error53.code !== "permission_required")
|
|
36397
36539
|
throw error53;
|
|
36398
36540
|
const asks = Array.isArray(error53.response?.asks) ? error53.response.asks : [];
|
|
36399
|
-
if (asks.length === 0 ||
|
|
36400
|
-
throw new
|
|
36401
|
-
}
|
|
36402
|
-
if (!extCtx.hasUI || typeof extCtx.ui?.confirm !== "function") {
|
|
36403
|
-
throw new BridgeError("Permission denied: host escalation approval requires an interactive UI.", "permission_denied");
|
|
36541
|
+
if (asks.length === 0 || !extCtx.hasUI || typeof extCtx.ui?.confirm !== "function") {
|
|
36542
|
+
throw new BridgeError("Permission denied: command approval requires an interactive UI.", "permission_denied");
|
|
36404
36543
|
}
|
|
36405
36544
|
for (const ask of asks) {
|
|
36406
|
-
|
|
36545
|
+
if (ask.kind === "escalation") {
|
|
36546
|
+
const approved2 = await extCtx.ui.confirm("Run command unsandboxed on host?", piEscalationAskText(ask), { signal: extCtx.signal });
|
|
36547
|
+
if (!approved2) {
|
|
36548
|
+
throw new BridgeError("Permission denied: unsandboxed host execution was denied.", "permission_denied");
|
|
36549
|
+
}
|
|
36550
|
+
if (ask.grant_id && !granted.includes(ask.grant_id))
|
|
36551
|
+
granted.push(ask.grant_id);
|
|
36552
|
+
continue;
|
|
36553
|
+
}
|
|
36554
|
+
if (bridgeCommand !== "powershell") {
|
|
36555
|
+
throw new Error("Permission ask reached Pi adapter without a host escalation grant — this is a bug.");
|
|
36556
|
+
}
|
|
36557
|
+
const approved = await extCtx.ui.confirm("Allow PowerShell command?", piPowerShellAskText(String(params.command ?? "")), { signal: extCtx.signal });
|
|
36407
36558
|
if (!approved) {
|
|
36408
|
-
throw new BridgeError("Permission denied:
|
|
36559
|
+
throw new BridgeError("Permission denied: PowerShell command was denied.", "permission_denied");
|
|
36560
|
+
}
|
|
36561
|
+
for (const grant of [...ask.always ?? [], ...ask.patterns ?? []]) {
|
|
36562
|
+
if (!granted.includes(grant))
|
|
36563
|
+
granted.push(grant);
|
|
36409
36564
|
}
|
|
36410
|
-
if (ask.grant_id && !granted.includes(ask.grant_id))
|
|
36411
|
-
granted.push(ask.grant_id);
|
|
36412
36565
|
}
|
|
36413
36566
|
}
|
|
36414
36567
|
}
|
|
@@ -36435,21 +36588,27 @@ function getBashSpawnHook(pi) {
|
|
|
36435
36588
|
}
|
|
36436
36589
|
return api2.hooks?.bashSpawn;
|
|
36437
36590
|
}
|
|
36438
|
-
function registerBashTool(pi, ctx, aftSearchRegistered = false) {
|
|
36439
|
-
const
|
|
36440
|
-
const
|
|
36591
|
+
function registerBashTool(pi, ctx, aftSearchRegistered = false, registeredName = "bash", registerCompanions = true, shell = "bash") {
|
|
36592
|
+
const isPowerShell = shell === "powershell";
|
|
36593
|
+
const spawnHook = isPowerShell ? undefined : getBashSpawnHook(pi);
|
|
36594
|
+
const readToolName = registeredName === "bash" ? "read" : "aft_read";
|
|
36595
|
+
const grepToolName = registeredName === "bash" ? "grep" : "aft_grep";
|
|
36596
|
+
const searchSteer = aftSearchRegistered ? `use \`aft_search\` (concepts, identifiers, regex, literals), \`${readToolName}\`, \`aft_outline\`, or \`aft_zoom\` instead` : `use the \`${grepToolName}\` tool, \`${readToolName}\`, \`aft_outline\`, or \`aft_zoom\` instead`;
|
|
36441
36597
|
const bashCfg = resolveBashConfig(ctx.config);
|
|
36442
36598
|
let hostFallbackActive = false;
|
|
36443
36599
|
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`." : "";
|
|
36444
|
-
const
|
|
36600
|
+
const detachSentence = bashCfg.detach_on_user_message ? "A new user message detaches this wait. Set `bash.detach_on_user_message: false` to keep it blocking; even then, a message containing the literal `&detach` forces detachment, and the token is stripped before delivery; the rest of the message is preserved, while a token-only message becomes `(requested background detach)`." : "Because `bash.detach_on_user_message` is false, a new user message leaves this wait blocking; include the literal `&detach` anywhere to force detachment, and the token is stripped before delivery; the rest of the message is preserved, while a token-only message becomes `(requested background detach)`.";
|
|
36601
|
+
const tasksSentence = bashCfg.background ? ` Commands run in the foreground and return inline; \`wait: true\` blocks until a long command finishes instead of auto-promoting; ${detachSentence} Use it when you need the result before doing anything else; keep it off otherwise so auto-promote can remind you while you work. Use \`background: true\` yourself ONLY when you have other useful work to do while it runs; then \`bash_watch\` waits on the task (sync blocks until exit/pattern, async notifies) and \`bash_status\` peeks at it — never background a command and immediately \`bash_watch\` it (that wastes a turn for what foreground returns in one), and never loop \`bash_status\` to wait. \`pty: true\` runs interactive programs (REPLs, TUIs), implies background, and is driven with \`bash_status({ output_mode: "screen" })\` plus \`bash_write\`.` : " Commands run in the foreground to completion; `timeout` is the hard kill cap (default 30 minutes).";
|
|
36445
36602
|
pi.registerTool({
|
|
36446
|
-
name:
|
|
36447
|
-
label:
|
|
36448
|
-
description: `Execute
|
|
36603
|
+
name: registeredName,
|
|
36604
|
+
label: registeredName,
|
|
36605
|
+
description: isPowerShell ? `Execute PowerShell commands through AFT.${compressionSentence}${tasksSentence}
|
|
36606
|
+
|
|
36607
|
+
PowerShell syntax is not analyzed as POSIX shell. Each command requires explicit approval so syntax AFT cannot safely interpret is never auto-allowed.` : `Execute shell commands.${compressionSentence}${tasksSentence}
|
|
36449
36608
|
|
|
36450
36609
|
DO NOT use bash for code search or code exploration. If you are about to run grep, rg, sed, awk, find, or cat through bash to locate or read code: STOP — ${searchSteer}.`,
|
|
36451
|
-
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)",
|
|
36452
|
-
promptGuidelines: [
|
|
36610
|
+
promptSnippet: isPowerShell ? "Run PowerShell commands (timeout in milliseconds; supports workdir, background tasks, compressed output, PTY mode)" : 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)",
|
|
36611
|
+
promptGuidelines: isPowerShell ? ["Use PowerShell syntax. Every command requires explicit approval."] : [
|
|
36453
36612
|
`DO NOT use bash for code search or exploration — ${searchSteer}.`,
|
|
36454
36613
|
"Set compressed: false when you need ANSI color codes in the output.",
|
|
36455
36614
|
"Piped commands run verbatim and show the pipeline's output; run test/build tools without pipes when you need AFT's summary."
|
|
@@ -36508,7 +36667,8 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
36508
36667
|
foreground_orchestrate: true,
|
|
36509
36668
|
block_to_completion: blockToCompletion,
|
|
36510
36669
|
wait: requestedWait,
|
|
36511
|
-
sandbox: params.sandbox
|
|
36670
|
+
sandbox: params.sandbox,
|
|
36671
|
+
...isPowerShell ? { shell: "powershell" } : {}
|
|
36512
36672
|
}, extCtx, {
|
|
36513
36673
|
transportTimeoutMs: orchestratedTransportTimeoutMs(blockToCompletion, requestedWait, effectiveTimeout, foregroundWaitMs),
|
|
36514
36674
|
onProgress: ({ text }) => {
|
|
@@ -36516,9 +36676,9 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
36516
36676
|
const displayText = truncateToVisualLines(streamed, 100);
|
|
36517
36677
|
onUpdate?.(bashResult(displayText, { streaming: true }));
|
|
36518
36678
|
}
|
|
36519
|
-
});
|
|
36679
|
+
}, isPowerShell ? "powershell" : "bash");
|
|
36520
36680
|
} catch (error53) {
|
|
36521
|
-
if (!bashCfg2.host_fallback || !isBashTransportDeadError(error53))
|
|
36681
|
+
if (isPowerShell || !bashCfg2.host_fallback || !isBashTransportDeadError(error53))
|
|
36522
36682
|
throw error53;
|
|
36523
36683
|
if (rawRequestedBackground) {
|
|
36524
36684
|
throw new Error(`${BASH_HOST_FALLBACK_REFUSAL}; background:true is unsupported.`);
|
|
@@ -36565,7 +36725,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
36565
36725
|
task_id: taskId
|
|
36566
36726
|
};
|
|
36567
36727
|
const output = response.output ?? "";
|
|
36568
|
-
return bashResult(usedHostFallback ? output : withBashHints(output, bridgeCommand, aftSearchRegistered, extCtx.cwd), details);
|
|
36728
|
+
return bashResult(usedHostFallback || isPowerShell ? output : withBashHints(output, bridgeCommand, aftSearchRegistered, extCtx.cwd), details);
|
|
36569
36729
|
},
|
|
36570
36730
|
renderCall(args, theme, context) {
|
|
36571
36731
|
return renderBashCall(args?.command, args?.description, theme, context);
|
|
@@ -36574,12 +36734,16 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
36574
36734
|
return renderBashResult(result, theme, context, options);
|
|
36575
36735
|
}
|
|
36576
36736
|
});
|
|
36577
|
-
if (
|
|
36578
|
-
pi
|
|
36579
|
-
|
|
36580
|
-
|
|
36581
|
-
|
|
36582
|
-
|
|
36737
|
+
if (registerCompanions)
|
|
36738
|
+
registerBashCompanionTools(pi, ctx);
|
|
36739
|
+
}
|
|
36740
|
+
function registerBashCompanionTools(pi, ctx) {
|
|
36741
|
+
if (!resolveBashConfig(ctx.config).background)
|
|
36742
|
+
return;
|
|
36743
|
+
pi.registerTool(createBashStatusTool(ctx));
|
|
36744
|
+
pi.registerTool(createBashWatchTool(ctx));
|
|
36745
|
+
pi.registerTool(createBashWriteTool(ctx));
|
|
36746
|
+
pi.registerTool(createBashKillTool(ctx));
|
|
36583
36747
|
}
|
|
36584
36748
|
function withBashHints(output, command, aftSearchRegistered, projectRoot) {
|
|
36585
36749
|
return maybeAppendGrepSearchHint(maybeAppendConflictsHint(output), command, aftSearchRegistered, projectRoot);
|
|
@@ -37574,25 +37738,39 @@ function formatPhase(entry) {
|
|
|
37574
37738
|
return details.length > 0 ? `${entry.id} (${details.join("; ")})` : entry.id;
|
|
37575
37739
|
}
|
|
37576
37740
|
function renderInspectTerminal(terminal, serverText) {
|
|
37577
|
-
const lines = [terminal.kind];
|
|
37578
37741
|
if (terminal.kind === "FRESH") {
|
|
37579
|
-
lines
|
|
37742
|
+
const lines = [
|
|
37743
|
+
terminal.kind,
|
|
37744
|
+
`wait-stamp: ${terminal.waitStampText ?? "not supplied"}`
|
|
37745
|
+
];
|
|
37746
|
+
lines.push(terminal.phases.length > 0 ? `completed phases:
|
|
37747
|
+
${terminal.phases.map((phase) => `- ${formatPhase(phase)}`).join(`
|
|
37748
|
+
`)}` : "completed phases: none");
|
|
37749
|
+
if (serverText?.trim())
|
|
37750
|
+
lines.push(serverText);
|
|
37751
|
+
return lines.join(`
|
|
37752
|
+
`);
|
|
37580
37753
|
}
|
|
37581
37754
|
if (terminal.kind === "PHASE-FAILED") {
|
|
37582
|
-
|
|
37583
|
-
|
|
37584
|
-
|
|
37585
|
-
|
|
37586
|
-
|
|
37755
|
+
const detail = compactTerminalField(terminal.failureDetail, "not supplied");
|
|
37756
|
+
const reason = compactTerminalField(terminal.failureReason, "not supplied");
|
|
37757
|
+
return [
|
|
37758
|
+
`inspect could not complete: ${detail} (${reason}).`,
|
|
37759
|
+
`Completed phases: ${terminal.phases.length}. Retry, or narrow with sections=...`
|
|
37760
|
+
].join(`
|
|
37761
|
+
`);
|
|
37587
37762
|
}
|
|
37588
|
-
|
|
37589
|
-
|
|
37590
|
-
`
|
|
37591
|
-
|
|
37592
|
-
|
|
37593
|
-
return lines.join(`
|
|
37763
|
+
const phaseLabel = terminal.phases.length === 1 ? "phase" : "phases";
|
|
37764
|
+
return [
|
|
37765
|
+
`inspect was interrupted before it could complete (after ${terminal.phases.length} completed ${phaseLabel}); no fresh snapshot was produced.`,
|
|
37766
|
+
"Retry is safe; retry inspect, or narrow with sections=..."
|
|
37767
|
+
].join(`
|
|
37594
37768
|
`);
|
|
37595
37769
|
}
|
|
37770
|
+
function compactTerminalField(value, fallback) {
|
|
37771
|
+
const compact = value?.trim().replace(/\s+/g, " ");
|
|
37772
|
+
return compact || fallback;
|
|
37773
|
+
}
|
|
37596
37774
|
function diagnosticsSummaryPart(summary) {
|
|
37597
37775
|
const section = asRecord3(summary?.diagnostics);
|
|
37598
37776
|
if (!section)
|
|
@@ -37714,9 +37892,19 @@ function renderInspectCall(args, theme, context) {
|
|
|
37714
37892
|
function renderInspectResult(result, theme, context, options = { expanded: true }) {
|
|
37715
37893
|
const payload = extractStructuredPayload(result);
|
|
37716
37894
|
const terminal = parseInspectTerminal(payload);
|
|
37895
|
+
if (terminal) {
|
|
37896
|
+
const sections2 = [renderInspectTerminal(terminal, asString2(asRecord3(payload)?.text))];
|
|
37897
|
+
return collapsibleResult({
|
|
37898
|
+
summary: sections2[0]?.split(`
|
|
37899
|
+
`)[0] ?? "inspect",
|
|
37900
|
+
full: renderSections(sections2, context),
|
|
37901
|
+
expanded: options.expanded,
|
|
37902
|
+
context
|
|
37903
|
+
});
|
|
37904
|
+
}
|
|
37717
37905
|
if (context.isError)
|
|
37718
37906
|
return renderErrorResult(result, "inspect failed", theme, context);
|
|
37719
|
-
const sections =
|
|
37907
|
+
const sections = buildInspectSections(payload, theme);
|
|
37720
37908
|
return collapsibleResult({
|
|
37721
37909
|
summary: sections[0] ?? "inspect completed",
|
|
37722
37910
|
full: renderSections(sections, context),
|
|
@@ -38381,7 +38569,7 @@ var SafetyParams = Type12.Object({
|
|
|
38381
38569
|
})),
|
|
38382
38570
|
name: Type12.Optional(Type12.String({ description: "Checkpoint name (required for checkpoint, restore)" })),
|
|
38383
38571
|
files: Type12.Optional(Type12.Array(Type12.String(), {
|
|
38384
|
-
description: "Specific files for checkpoint (optional, defaults to all tracked)"
|
|
38572
|
+
description: "Specific files for checkpoint (optional, defaults to all backup-tracked files; explicit files may be untracked or gitignored)"
|
|
38385
38573
|
}))
|
|
38386
38574
|
});
|
|
38387
38575
|
function buildSafetySections(args, payload, theme) {
|
|
@@ -38426,14 +38614,16 @@ function buildSafetySections(args, payload, theme) {
|
|
|
38426
38614
|
`${theme.fg("muted", "files")} ${asNumber2(response.file_count) ?? 0}`,
|
|
38427
38615
|
skipped.length > 0 ? `${theme.fg("warning", "skipped")}
|
|
38428
38616
|
${skipped.map((entry) => ` ↳ ${shortenPath2(asString2(entry.file) ?? "(file)")}: ${asString2(entry.error) ?? "unknown error"}`).join(`
|
|
38429
|
-
`)}` : theme.fg("muted", "No skipped files.")
|
|
38430
|
-
|
|
38617
|
+
`)}` : theme.fg("muted", "No skipped files."),
|
|
38618
|
+
asString2(response.durability)
|
|
38619
|
+
].filter((section) => Boolean(section));
|
|
38431
38620
|
}
|
|
38432
38621
|
if (args.op === "restore") {
|
|
38433
38622
|
return [
|
|
38434
38623
|
`${theme.fg("success", "checkpoint restored")} ${theme.fg("accent", asString2(response.name) ?? args.name ?? "(checkpoint)")}`,
|
|
38435
|
-
`${theme.fg("muted", "files")} ${asNumber2(response.file_count) ?? 0}
|
|
38436
|
-
|
|
38624
|
+
`${theme.fg("muted", "files")} ${asNumber2(response.file_count) ?? 0}`,
|
|
38625
|
+
asString2(response.durability)
|
|
38626
|
+
].filter((section) => Boolean(section));
|
|
38437
38627
|
}
|
|
38438
38628
|
const checkpoints = asRecords2(response.checkpoints);
|
|
38439
38629
|
const sections = [
|
|
@@ -38441,6 +38631,9 @@ ${skipped.map((entry) => ` ↳ ${shortenPath2(asString2(entry.file) ?? "(file)"
|
|
|
38441
38631
|
];
|
|
38442
38632
|
if (checkpoints.length === 0) {
|
|
38443
38633
|
sections.push(theme.fg("muted", "No checkpoints saved."));
|
|
38634
|
+
const durability2 = asString2(response.durability);
|
|
38635
|
+
if (durability2)
|
|
38636
|
+
sections.push(theme.fg("muted", durability2));
|
|
38444
38637
|
return sections;
|
|
38445
38638
|
}
|
|
38446
38639
|
sections.push(checkpoints.map((checkpoint, index) => {
|
|
@@ -38450,6 +38643,9 @@ ${skipped.map((entry) => ` ↳ ${shortenPath2(asString2(entry.file) ?? "(file)"
|
|
|
38450
38643
|
return `${index + 1}. ${name} ${theme.fg("muted", `${count} file${count === 1 ? "" : "s"} · ${created}`)}`;
|
|
38451
38644
|
}).join(`
|
|
38452
38645
|
`));
|
|
38646
|
+
const durability = asString2(response.durability);
|
|
38647
|
+
if (durability)
|
|
38648
|
+
sections.push(theme.fg("muted", durability));
|
|
38453
38649
|
return sections;
|
|
38454
38650
|
}
|
|
38455
38651
|
function renderSafetyCall(args, theme, context) {
|
|
@@ -38699,15 +38895,38 @@ function registerSemanticTool(pi, ctx) {
|
|
|
38699
38895
|
|
|
38700
38896
|
// src/tool-registration.ts
|
|
38701
38897
|
var ALL_ONLY_TOOLS = new Set(["aft_callgraph", "aft_delete", "aft_move", "aft_refactor"]);
|
|
38702
|
-
function
|
|
38898
|
+
function resolvePiPowerShellFallback(config2) {
|
|
38899
|
+
return resolveBashConfig(config2).powershell_tool;
|
|
38900
|
+
}
|
|
38901
|
+
function piPowerShellEnabledFromHost(pi) {
|
|
38902
|
+
const api2 = pi;
|
|
38903
|
+
if (typeof api2.getActiveTools !== "function" || typeof api2.getAllTools !== "function") {
|
|
38904
|
+
return;
|
|
38905
|
+
}
|
|
38906
|
+
try {
|
|
38907
|
+
const tool = api2.getAllTools().find((candidate) => candidate.name === "powershell");
|
|
38908
|
+
const source = tool?.sourceInfo?.source ?? tool?.source;
|
|
38909
|
+
if (!tool || source === undefined)
|
|
38910
|
+
return;
|
|
38911
|
+
return source === "builtin" && api2.getActiveTools().some((active) => (typeof active === "string" ? active : active.name) === "powershell");
|
|
38912
|
+
} catch {
|
|
38913
|
+
return;
|
|
38914
|
+
}
|
|
38915
|
+
}
|
|
38916
|
+
function resolvePiToolSurface(config2, pi) {
|
|
38703
38917
|
const surface = config2.tool_surface ?? "recommended";
|
|
38704
38918
|
const disabled = new Set(config2.disabled_tools ?? []);
|
|
38919
|
+
const hoistBuiltinTools = config2.hoist_builtin_tools !== false;
|
|
38705
38920
|
const ok = (name) => !disabled.has(name);
|
|
38921
|
+
const builtinToolEnabled = (bareName) => ok(hoistBuiltinTools ? bareName : `aft_${bareName}`);
|
|
38706
38922
|
const allOnly = (name) => ALL_ONLY_TOOLS.has(name) && ok(name);
|
|
38707
38923
|
const restrictToProjectRoot = config2.restrict_to_project_root ?? false;
|
|
38924
|
+
const powershellEnabled = (pi ? piPowerShellEnabledFromHost(pi) : undefined) ?? resolvePiPowerShellFallback(config2);
|
|
38708
38925
|
if (surface === "minimal") {
|
|
38709
38926
|
return {
|
|
38710
|
-
|
|
38927
|
+
hoistBuiltinTools,
|
|
38928
|
+
hoistBash: builtinToolEnabled("bash"),
|
|
38929
|
+
hoistPowershell: powershellEnabled && builtinToolEnabled("powershell"),
|
|
38711
38930
|
hoistRead: false,
|
|
38712
38931
|
hoistWrite: false,
|
|
38713
38932
|
hoistEdit: false,
|
|
@@ -38729,11 +38948,13 @@ function resolvePiToolSurface(config2) {
|
|
|
38729
38948
|
};
|
|
38730
38949
|
}
|
|
38731
38950
|
const base = {
|
|
38732
|
-
|
|
38733
|
-
|
|
38734
|
-
|
|
38735
|
-
|
|
38736
|
-
|
|
38951
|
+
hoistBuiltinTools,
|
|
38952
|
+
hoistBash: builtinToolEnabled("bash"),
|
|
38953
|
+
hoistPowershell: powershellEnabled && builtinToolEnabled("powershell"),
|
|
38954
|
+
hoistRead: builtinToolEnabled("read"),
|
|
38955
|
+
hoistWrite: builtinToolEnabled("write"),
|
|
38956
|
+
hoistEdit: builtinToolEnabled("edit"),
|
|
38957
|
+
hoistGrep: builtinToolEnabled("grep") && config2.search_index === true,
|
|
38737
38958
|
restrictToProjectRoot,
|
|
38738
38959
|
outline: ok("aft_outline"),
|
|
38739
38960
|
zoom: ok("aft_zoom"),
|
|
@@ -38761,13 +38982,20 @@ function resolvePiToolSurface(config2) {
|
|
|
38761
38982
|
return base;
|
|
38762
38983
|
}
|
|
38763
38984
|
function registerPiToolSurface(pi, ctx, surface) {
|
|
38764
|
-
|
|
38765
|
-
|
|
38985
|
+
const bashCfg = resolveBashConfig(ctx.config);
|
|
38986
|
+
const bashRegistered = surface.hoistBash && bashCfg.enabled;
|
|
38987
|
+
const powershellRegistered = surface.hoistPowershell && bashCfg.enabled;
|
|
38988
|
+
if (bashRegistered) {
|
|
38989
|
+
registerBashTool(pi, ctx, surface.semantic, surface.hoistBuiltinTools ? "bash" : "aft_bash", false);
|
|
38990
|
+
}
|
|
38991
|
+
if (powershellRegistered) {
|
|
38992
|
+
registerBashTool(pi, ctx, surface.semantic, surface.hoistBuiltinTools ? "powershell" : "aft_powershell", false, "powershell");
|
|
38766
38993
|
}
|
|
38994
|
+
if (bashRegistered || powershellRegistered)
|
|
38995
|
+
registerBashCompanionTools(pi, ctx);
|
|
38767
38996
|
registerHoistedTools(pi, ctx, surface);
|
|
38768
|
-
if (surface.outline || surface.zoom)
|
|
38997
|
+
if (surface.outline || surface.zoom)
|
|
38769
38998
|
registerReadingTools(pi, ctx, surface);
|
|
38770
|
-
}
|
|
38771
38999
|
if (surface.semantic)
|
|
38772
39000
|
registerSemanticTool(pi, ctx);
|
|
38773
39001
|
if (surface.inspect)
|
|
@@ -38873,6 +39101,9 @@ function buildHintsFromConfig(config2, absentTools, hoistBuiltins) {
|
|
|
38873
39101
|
});
|
|
38874
39102
|
}
|
|
38875
39103
|
function registerWorkflowHints(pi, config2, surface) {
|
|
39104
|
+
const hoistBuiltins = surface.hoistBuiltinTools;
|
|
39105
|
+
const grepName = hoistBuiltins ? "grep" : "aft_grep";
|
|
39106
|
+
const bashName = hoistBuiltins ? "bash" : "aft_bash";
|
|
38876
39107
|
const absent = new Set;
|
|
38877
39108
|
if (!surface.outline)
|
|
38878
39109
|
absent.add("aft_outline");
|
|
@@ -38885,12 +39116,12 @@ function registerWorkflowHints(pi, config2, surface) {
|
|
|
38885
39116
|
if (!surface.inspect)
|
|
38886
39117
|
absent.add("aft_inspect");
|
|
38887
39118
|
if (!surface.hoistGrep)
|
|
38888
|
-
absent.add(
|
|
39119
|
+
absent.add(grepName);
|
|
38889
39120
|
if (!surface.hoistBash) {
|
|
38890
|
-
absent.add(
|
|
39121
|
+
absent.add(bashName);
|
|
38891
39122
|
absent.add("bash_status");
|
|
38892
39123
|
}
|
|
38893
|
-
const hintsBlock = buildHintsFromConfig(config2, absent,
|
|
39124
|
+
const hintsBlock = buildHintsFromConfig(config2, absent, hoistBuiltins);
|
|
38894
39125
|
if (!hintsBlock)
|
|
38895
39126
|
return;
|
|
38896
39127
|
log2(`Workflow hints injected (${hintsBlock.length} chars)`);
|
|
@@ -38947,7 +39178,7 @@ var PLUGIN_VERSION = (() => {
|
|
|
38947
39178
|
return "0.0.0";
|
|
38948
39179
|
}
|
|
38949
39180
|
})();
|
|
38950
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
39181
|
+
var ANNOUNCEMENT_VERSION = "0.54.0";
|
|
38951
39182
|
var ANNOUNCEMENT_FEATURES = [
|
|
38952
39183
|
"Callgraph stays consistent under load: edits arriving mid-rebuild can no longer be silently lost from navigation results.",
|
|
38953
39184
|
"aft_zoom handles real-world .jsonc: files with comment banners above the opening brace now resolve, and not-found errors point at the segment that actually failed (thanks @iceteaSA).",
|
|
@@ -39266,7 +39497,7 @@ ${lines}
|
|
|
39266
39497
|
});
|
|
39267
39498
|
}
|
|
39268
39499
|
pool.setConfigureOverride("harness", "pi");
|
|
39269
|
-
const surface = resolvePiToolSurface(config2);
|
|
39500
|
+
const surface = resolvePiToolSurface(config2, pi);
|
|
39270
39501
|
const hashlineEditRegistered = config2.edit_mode === "hashline" && surface.hoistEdit;
|
|
39271
39502
|
pool.setConfigureOverride("edit_slot_survives", hashlineEditRegistered);
|
|
39272
39503
|
pool.setConfigureOverride("aft_search_registered", surface.semantic);
|
|
@@ -39314,6 +39545,17 @@ ${lines}
|
|
|
39314
39545
|
sendFeatureAnnouncement(ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER, storageDir);
|
|
39315
39546
|
}
|
|
39316
39547
|
registerPiToolSurface(pi, ctx, surface);
|
|
39548
|
+
let powershellRegistered = surface.hoistPowershell && resolveBashConfig(config2).enabled;
|
|
39549
|
+
pi.on("session_start", () => {
|
|
39550
|
+
if (powershellRegistered)
|
|
39551
|
+
return;
|
|
39552
|
+
const liveSurface = resolvePiToolSurface(config2, pi);
|
|
39553
|
+
if (!liveSurface.hoistPowershell || !resolveBashConfig(config2).enabled)
|
|
39554
|
+
return;
|
|
39555
|
+
registerBashTool(pi, ctx, liveSurface.semantic, liveSurface.hoistBuiltinTools ? "powershell" : "aft_powershell", false, "powershell");
|
|
39556
|
+
registerBashCompanionTools(pi, ctx);
|
|
39557
|
+
powershellRegistered = true;
|
|
39558
|
+
});
|
|
39317
39559
|
registerWorkflowHints(pi, config2, surface);
|
|
39318
39560
|
registerStatusCommand(pi, ctx);
|
|
39319
39561
|
pi.on("tool_result", async (event, extCtx) => {
|
|
@@ -39345,10 +39587,18 @@ ${lines}
|
|
|
39345
39587
|
});
|
|
39346
39588
|
}
|
|
39347
39589
|
});
|
|
39348
|
-
pi.on("input", (
|
|
39590
|
+
pi.on("input", (event, extCtx) => {
|
|
39349
39591
|
const sessionId = resolveSessionId(extCtx);
|
|
39350
39592
|
signalSyncWatchAbort(sessionId);
|
|
39351
|
-
|
|
39593
|
+
const originalText = event.text;
|
|
39594
|
+
const transformedText = stripUserMessageDetachKeyword(originalText);
|
|
39595
|
+
const shouldDetach = shouldDetachBashWaitOnUserMessage(config2, originalText);
|
|
39596
|
+
if (shouldDetach) {
|
|
39597
|
+
signalBashWaitDetachForProject(pool, extCtx.cwd, sessionId);
|
|
39598
|
+
}
|
|
39599
|
+
if (transformedText !== originalText) {
|
|
39600
|
+
return { action: "transform", text: transformedText };
|
|
39601
|
+
}
|
|
39352
39602
|
});
|
|
39353
39603
|
const unregisterShutdownCleanup = registerShutdownCleanup(async () => {
|
|
39354
39604
|
try {
|