@cortexkit/aft-pi 0.52.1 → 0.53.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/config.d.ts +46 -20
- package/dist/config.d.ts.map +1 -1
- package/dist/index.js +627 -402
- package/dist/shared/status.d.ts +3 -0
- package/dist/shared/status.d.ts.map +1 -1
- package/dist/tool-registration.d.ts +2 -0
- package/dist/tool-registration.d.ts.map +1 -1
- package/dist/tools/_shared.d.ts.map +1 -1
- package/dist/tools/ast.d.ts +2 -2
- package/dist/tools/ast.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/conflicts.d.ts +3 -3
- package/dist/tools/conflicts.d.ts.map +1 -1
- package/dist/tools/diff-format.d.ts.map +1 -1
- package/dist/tools/fs.d.ts +2 -2
- package/dist/tools/fs.d.ts.map +1 -1
- package/dist/tools/hoisted.d.ts +7 -3
- package/dist/tools/hoisted.d.ts.map +1 -1
- package/dist/tools/imports.d.ts +2 -2
- package/dist/tools/imports.d.ts.map +1 -1
- package/dist/tools/inspect.d.ts +2 -2
- package/dist/tools/inspect.d.ts.map +1 -1
- package/dist/tools/navigate.d.ts +2 -2
- package/dist/tools/navigate.d.ts.map +1 -1
- package/dist/tools/reading.d.ts +3 -3
- package/dist/tools/reading.d.ts.map +1 -1
- package/dist/tools/refactor.d.ts +2 -2
- package/dist/tools/refactor.d.ts.map +1 -1
- package/dist/tools/render-helpers.d.ts +25 -1
- package/dist/tools/render-helpers.d.ts.map +1 -1
- package/dist/tools/safety.d.ts +2 -2
- package/dist/tools/safety.d.ts.map +1 -1
- package/dist/tools/semantic.d.ts +2 -2
- package/dist/tools/semantic.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
|
@@ -7948,7 +7948,7 @@ function error(message, meta) {
|
|
|
7948
7948
|
}
|
|
7949
7949
|
// ../aft-bridge/dist/bash-format.js
|
|
7950
7950
|
function isTerminalStatus(status) {
|
|
7951
|
-
return status === "completed" || status === "failed" || status === "killed" || status === "timed_out";
|
|
7951
|
+
return status === "completed" || status === "failed" || status === "killed" || status === "timed_out" || status === "fate_unknown";
|
|
7952
7952
|
}
|
|
7953
7953
|
function sleep(ms) {
|
|
7954
7954
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -8491,6 +8491,7 @@ var TERMINAL_BASH_STATUSES = new Set([
|
|
|
8491
8491
|
"failed",
|
|
8492
8492
|
"killed",
|
|
8493
8493
|
"timed_out",
|
|
8494
|
+
"fate_unknown",
|
|
8494
8495
|
"cancelled",
|
|
8495
8496
|
"timeout"
|
|
8496
8497
|
]);
|
|
@@ -9921,7 +9922,7 @@ function isEmptyParam(value) {
|
|
|
9921
9922
|
return false;
|
|
9922
9923
|
}
|
|
9923
9924
|
// ../aft-bridge/dist/config-keys.js
|
|
9924
|
-
var OPENCODE_ONLY_KEYS = ["
|
|
9925
|
+
var OPENCODE_ONLY_KEYS = ["auto_update"];
|
|
9925
9926
|
function stripHarnessSpecificConfigKeys(value, keys) {
|
|
9926
9927
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
9927
9928
|
return value;
|
|
@@ -10359,34 +10360,54 @@ async function fetchLatestTag() {
|
|
|
10359
10360
|
}
|
|
10360
10361
|
// ../aft-bridge/dist/durable-log.js
|
|
10361
10362
|
import { appendFile, mkdir, rename, rm, stat } from "node:fs/promises";
|
|
10363
|
+
import { dirname } from "node:path";
|
|
10364
|
+
|
|
10365
|
+
// ../aft-bridge/dist/storage-paths.js
|
|
10362
10366
|
import { homedir as homedir5 } from "node:os";
|
|
10363
|
-
import {
|
|
10364
|
-
var DEFAULT_LOG_BYTES = 32 * 1024 * 1024;
|
|
10365
|
-
var DEFAULT_LOG_GENERATIONS = 1;
|
|
10367
|
+
import { join as join5, resolve as resolve3 } from "node:path";
|
|
10366
10368
|
function homeDir2() {
|
|
10367
10369
|
if (process.platform === "win32")
|
|
10368
10370
|
return process.env.USERPROFILE || process.env.HOME || homedir5();
|
|
10369
10371
|
return process.env.HOME || homedir5();
|
|
10370
10372
|
}
|
|
10371
10373
|
function dataHome() {
|
|
10372
|
-
|
|
10373
|
-
|
|
10374
|
+
const xdg = process.env.XDG_DATA_HOME;
|
|
10375
|
+
if (xdg)
|
|
10376
|
+
return xdg;
|
|
10374
10377
|
if (process.platform === "win32") {
|
|
10375
10378
|
return process.env.LOCALAPPDATA || process.env.APPDATA || join5(homeDir2(), "AppData", "Local");
|
|
10376
10379
|
}
|
|
10377
10380
|
return join5(homeDir2(), ".local", "share");
|
|
10378
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
|
+
}
|
|
10379
10397
|
function resolveAftStorageRoot(configuredRoot) {
|
|
10398
|
+
if (process.env.AFT_STORAGE_DIR)
|
|
10399
|
+
return resolveCortexKitStorageRoot();
|
|
10380
10400
|
if (configuredRoot)
|
|
10381
10401
|
return configuredRoot;
|
|
10382
|
-
|
|
10383
|
-
return join5(process.env.AFT_CACHE_DIR, "aft");
|
|
10384
|
-
return join5(dataHome(), "cortexkit", "aft");
|
|
10402
|
+
return resolveCortexKitStorageRoot();
|
|
10385
10403
|
}
|
|
10386
10404
|
function resolveAftLogPath(filename, configuredRoot) {
|
|
10387
10405
|
return join5(resolveAftStorageRoot(configuredRoot), "logs", filename);
|
|
10388
10406
|
}
|
|
10389
10407
|
|
|
10408
|
+
// ../aft-bridge/dist/durable-log.js
|
|
10409
|
+
var DEFAULT_LOG_BYTES = 32 * 1024 * 1024;
|
|
10410
|
+
var DEFAULT_LOG_GENERATIONS = 1;
|
|
10390
10411
|
class RotatingLogSink {
|
|
10391
10412
|
path;
|
|
10392
10413
|
maxBytes;
|
|
@@ -10758,7 +10779,7 @@ class SubcSocket {
|
|
|
10758
10779
|
return this.sock.localPort ?? null;
|
|
10759
10780
|
}
|
|
10760
10781
|
static connect(host, port, deadlineMs) {
|
|
10761
|
-
return new Promise((
|
|
10782
|
+
return new Promise((resolve4, reject) => {
|
|
10762
10783
|
const sock = net.connect({ host, port });
|
|
10763
10784
|
sock.setNoDelay(true);
|
|
10764
10785
|
const timer = setTimeout(() => {
|
|
@@ -10767,7 +10788,7 @@ class SubcSocket {
|
|
|
10767
10788
|
}, Math.max(0, deadlineMs - Date.now()));
|
|
10768
10789
|
sock.once("connect", () => {
|
|
10769
10790
|
clearTimeout(timer);
|
|
10770
|
-
|
|
10791
|
+
resolve4(new SubcSocket(sock));
|
|
10771
10792
|
});
|
|
10772
10793
|
sock.once("error", (err) => {
|
|
10773
10794
|
clearTimeout(timer);
|
|
@@ -10799,7 +10820,7 @@ class SubcSocket {
|
|
|
10799
10820
|
}
|
|
10800
10821
|
if (n === 0)
|
|
10801
10822
|
return Promise.resolve(new Uint8Array(0));
|
|
10802
|
-
return new Promise((
|
|
10823
|
+
return new Promise((resolve4, reject) => {
|
|
10803
10824
|
let timer = null;
|
|
10804
10825
|
if (Number.isFinite(deadlineMs)) {
|
|
10805
10826
|
const remaining = deadlineMs - Date.now();
|
|
@@ -10812,7 +10833,7 @@ class SubcSocket {
|
|
|
10812
10833
|
reject(new SocketTimeoutError(`timed out waiting for ${n} bytes`));
|
|
10813
10834
|
}, remaining);
|
|
10814
10835
|
}
|
|
10815
|
-
this.waiter = { need: n, resolve:
|
|
10836
|
+
this.waiter = { need: n, resolve: resolve4, reject, timer };
|
|
10816
10837
|
this.tryServe();
|
|
10817
10838
|
});
|
|
10818
10839
|
}
|
|
@@ -10848,7 +10869,7 @@ class SubcSocket {
|
|
|
10848
10869
|
let queued = false;
|
|
10849
10870
|
let settled = false;
|
|
10850
10871
|
let timer = null;
|
|
10851
|
-
const completed = new Promise((
|
|
10872
|
+
const completed = new Promise((resolve4, reject) => {
|
|
10852
10873
|
const settle = (run) => {
|
|
10853
10874
|
if (settled)
|
|
10854
10875
|
return;
|
|
@@ -10872,7 +10893,7 @@ class SubcSocket {
|
|
|
10872
10893
|
if (err) {
|
|
10873
10894
|
reject(new SocketWriteQueuedError("subc socket reported a write error after bytes were handed to the socket", err instanceof Error ? err : new Error(String(err))));
|
|
10874
10895
|
} else {
|
|
10875
|
-
|
|
10896
|
+
resolve4();
|
|
10876
10897
|
}
|
|
10877
10898
|
});
|
|
10878
10899
|
});
|
|
@@ -11295,15 +11316,15 @@ class SubcClient {
|
|
|
11295
11316
|
const key = pendingKey(handle, corr);
|
|
11296
11317
|
let subscriptionPending = null;
|
|
11297
11318
|
let resolveClosed = null;
|
|
11298
|
-
const closed = new Promise((
|
|
11319
|
+
const closed = new Promise((resolve4, reject) => {
|
|
11299
11320
|
if (this.closedErr) {
|
|
11300
11321
|
reject(this.closedErr);
|
|
11301
11322
|
return;
|
|
11302
11323
|
}
|
|
11303
|
-
resolveClosed =
|
|
11324
|
+
resolveClosed = resolve4;
|
|
11304
11325
|
subscriptionPending = {
|
|
11305
11326
|
handle,
|
|
11306
|
-
resolve: () =>
|
|
11327
|
+
resolve: () => resolve4(),
|
|
11307
11328
|
reject,
|
|
11308
11329
|
onProgress: onEvent,
|
|
11309
11330
|
timer: null,
|
|
@@ -11392,11 +11413,11 @@ class SubcClient {
|
|
|
11392
11413
|
const waiters = [];
|
|
11393
11414
|
for (const pending of this.pending.values()) {
|
|
11394
11415
|
if (pending.handle === handle && !pending.subscription) {
|
|
11395
|
-
waiters.push(new Promise((
|
|
11416
|
+
waiters.push(new Promise((resolve4) => {
|
|
11396
11417
|
const previous = pending.onSettle;
|
|
11397
11418
|
pending.onSettle = () => {
|
|
11398
11419
|
previous?.();
|
|
11399
|
-
|
|
11420
|
+
resolve4();
|
|
11400
11421
|
};
|
|
11401
11422
|
}));
|
|
11402
11423
|
}
|
|
@@ -11452,11 +11473,11 @@ class SubcClient {
|
|
|
11452
11473
|
const channel = handle?.channel ?? 0;
|
|
11453
11474
|
const epoch = handle?.epoch ?? 0;
|
|
11454
11475
|
const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), channel, epoch, corr, body);
|
|
11455
|
-
return new Promise((
|
|
11476
|
+
return new Promise((resolve4, reject) => {
|
|
11456
11477
|
const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
11457
11478
|
const pending = {
|
|
11458
11479
|
handle,
|
|
11459
|
-
resolve:
|
|
11480
|
+
resolve: resolve4,
|
|
11460
11481
|
reject,
|
|
11461
11482
|
onProgress,
|
|
11462
11483
|
timer: null,
|
|
@@ -11530,11 +11551,11 @@ class SubcClient {
|
|
|
11530
11551
|
}
|
|
11531
11552
|
return this.outcomeUnknownCallError("connection dropped before the managed call returned a response", error2);
|
|
11532
11553
|
};
|
|
11533
|
-
return new Promise((
|
|
11554
|
+
return new Promise((resolve4, reject) => {
|
|
11534
11555
|
const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
11535
11556
|
const pending = {
|
|
11536
11557
|
handle,
|
|
11537
|
-
resolve:
|
|
11558
|
+
resolve: resolve4,
|
|
11538
11559
|
reject,
|
|
11539
11560
|
onProgress,
|
|
11540
11561
|
timer: null,
|
|
@@ -11983,7 +12004,7 @@ function normalizeConnectOptions(opts) {
|
|
|
11983
12004
|
identity: opts.identity,
|
|
11984
12005
|
targetKind: opts.targetKind ?? DEFAULT_MANAGED_TARGET_KIND,
|
|
11985
12006
|
reconnectBackoff: opts.reconnectBackoff ?? DEFAULT_RECONNECT_BACKOFF,
|
|
11986
|
-
sleep: opts.sleep ?? ((ms) => new Promise((
|
|
12007
|
+
sleep: opts.sleep ?? ((ms) => new Promise((resolve4) => setTimeout(resolve4, ms))),
|
|
11987
12008
|
timeoutArbitrationGraceMs: opts.timeoutArbitrationGraceMs ?? TIMEOUT_ARBITRATION_GRACE_MS,
|
|
11988
12009
|
livenessProbeWindowMs: opts.livenessProbeWindowMs ?? LIVENESS_PROBE_WINDOW_MS,
|
|
11989
12010
|
onControlPush: opts.onControlPush
|
|
@@ -12442,14 +12463,14 @@ function getLifecycleRegistry() {
|
|
|
12442
12463
|
|
|
12443
12464
|
// ../aft-bridge/dist/project-identity.js
|
|
12444
12465
|
import { realpathSync } from "node:fs";
|
|
12445
|
-
import { resolve as
|
|
12466
|
+
import { resolve as resolve4 } from "node:path";
|
|
12446
12467
|
function canonicalizeProjectRoot(dir) {
|
|
12447
12468
|
const trimmed = dir.replace(/[/\\]+$/, "");
|
|
12448
12469
|
let canonical;
|
|
12449
12470
|
try {
|
|
12450
12471
|
canonical = realpathSync(trimmed);
|
|
12451
12472
|
} catch {
|
|
12452
|
-
canonical =
|
|
12473
|
+
canonical = resolve4(trimmed);
|
|
12453
12474
|
}
|
|
12454
12475
|
return normalizeWindowsRoot(canonical);
|
|
12455
12476
|
}
|
|
@@ -12945,8 +12966,8 @@ class SubcTransportPool {
|
|
|
12945
12966
|
this.connectFn = options.connect ?? ((opts) => SubcClient.connect(opts));
|
|
12946
12967
|
this.onBgEventsNudge = options.onBgEventsNudge;
|
|
12947
12968
|
this.onBgEventsNudgeRef = options.onBgEventsNudgeRef;
|
|
12948
|
-
this.bgBackoffSleep = options.bgBackoffSleep ?? ((ms) => new Promise((
|
|
12949
|
-
this.routeRetrySleep = options.routeRetrySleep ?? ((ms) => new Promise((
|
|
12969
|
+
this.bgBackoffSleep = options.bgBackoffSleep ?? ((ms) => new Promise((resolve5) => setTimeout(resolve5, ms)));
|
|
12970
|
+
this.routeRetrySleep = options.routeRetrySleep ?? ((ms) => new Promise((resolve5) => setTimeout(resolve5, ms)));
|
|
12950
12971
|
this.bgDispatchProbeIntervalMs = options.bgDispatchProbeIntervalMs ?? BG_DISPATCH_PROBE_INTERVAL_MS;
|
|
12951
12972
|
const lifecycle = options.lifecycle;
|
|
12952
12973
|
const demandCheck = options.lifecycleDemandCheck ?? options.demandCheck ?? lifecycle?.demandCheck;
|
|
@@ -13862,12 +13883,12 @@ function stripJsoncSymbols(value) {
|
|
|
13862
13883
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
13863
13884
|
import { closeSync as closeSync3, existsSync as existsSync6, 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";
|
|
13864
13885
|
import { homedir as homedir8, tmpdir } from "node:os";
|
|
13865
|
-
import { basename, dirname as dirname3, join as join8, resolve as
|
|
13886
|
+
import { basename, dirname as dirname3, join as join8, resolve as resolve6 } from "node:path";
|
|
13866
13887
|
|
|
13867
13888
|
// ../aft-bridge/dist/paths.js
|
|
13868
13889
|
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync } from "node:fs";
|
|
13869
13890
|
import { homedir as homedir6 } from "node:os";
|
|
13870
|
-
import { dirname as dirname2, isAbsolute as isAbsolute2, join as join6, resolve as
|
|
13891
|
+
import { dirname as dirname2, isAbsolute as isAbsolute2, join as join6, resolve as resolve5 } from "node:path";
|
|
13871
13892
|
function homeDir3() {
|
|
13872
13893
|
if (process.platform === "win32")
|
|
13873
13894
|
return process.env.USERPROFILE || process.env.HOME || homedir6();
|
|
@@ -13882,7 +13903,7 @@ function configHome() {
|
|
|
13882
13903
|
function legacyOpenCodeConfigDir() {
|
|
13883
13904
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
13884
13905
|
if (envDir)
|
|
13885
|
-
return
|
|
13906
|
+
return resolve5(envDir);
|
|
13886
13907
|
return join6(configHome(), "opencode");
|
|
13887
13908
|
}
|
|
13888
13909
|
function legacyPiAgentDir() {
|
|
@@ -14247,9 +14268,6 @@ function resolveLegacyStorageRoot(harness) {
|
|
|
14247
14268
|
return join8(homeDir4(), ".pi", "agent", "aft");
|
|
14248
14269
|
return join8(dataHome2(), "opencode", "storage", "plugin", "aft");
|
|
14249
14270
|
}
|
|
14250
|
-
function resolveCortexKitStorageRoot() {
|
|
14251
|
-
return join8(dataHome2(), "cortexkit", "aft");
|
|
14252
|
-
}
|
|
14253
14271
|
function stripJsoncForParse(input) {
|
|
14254
14272
|
let out = "";
|
|
14255
14273
|
let inString = false;
|
|
@@ -14519,8 +14537,8 @@ function visibleConfigMigrationWarning(scope, targetPath, paths, reason) {
|
|
|
14519
14537
|
}
|
|
14520
14538
|
function migrateAftConfigFile(opts) {
|
|
14521
14539
|
const warnings = [];
|
|
14522
|
-
const resolvedTarget =
|
|
14523
|
-
const existingSources = opts.legacySources.filter((source) => existsSync6(source.path) &&
|
|
14540
|
+
const resolvedTarget = resolve6(opts.targetPath);
|
|
14541
|
+
const existingSources = opts.legacySources.filter((source) => existsSync6(source.path) && resolve6(source.path) !== resolvedTarget);
|
|
14524
14542
|
const info = opts.logger?.info ?? opts.logger?.log;
|
|
14525
14543
|
if (existingSources.length === 0) {
|
|
14526
14544
|
return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
|
|
@@ -14766,7 +14784,7 @@ function npmSpawnEnv(resolved, baseEnv = process.env) {
|
|
|
14766
14784
|
import { execFileSync } from "node:child_process";
|
|
14767
14785
|
import { createHash as createHash3 } from "node:crypto";
|
|
14768
14786
|
import { chmodSync as chmodSync3, closeSync as closeSync4, copyFileSync as copyFileSync3, createWriteStream as createWriteStream2, existsSync as existsSync7, 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";
|
|
14769
|
-
import { basename as basename2, dirname as dirname5, isAbsolute as isAbsolute4, join as join10, relative as relative2, resolve as
|
|
14787
|
+
import { basename as basename2, dirname as dirname5, isAbsolute as isAbsolute4, join as join10, relative as relative2, resolve as resolve7, win32 } from "node:path";
|
|
14770
14788
|
import { Readable as Readable2 } from "node:stream";
|
|
14771
14789
|
import { pipeline as pipeline2 } from "node:stream/promises";
|
|
14772
14790
|
var ORT_VERSION = "1.24.4";
|
|
@@ -15071,7 +15089,7 @@ function findSystemOnnxRuntime(libName) {
|
|
|
15071
15089
|
const normalizeCase = process.platform === "win32" || process.platform === "darwin";
|
|
15072
15090
|
const seen = new Set;
|
|
15073
15091
|
const uniquePaths = searchPaths.filter((p) => {
|
|
15074
|
-
let key =
|
|
15092
|
+
let key = resolve7(p).replace(/[/\\]+$/, "");
|
|
15075
15093
|
if (normalizeCase)
|
|
15076
15094
|
key = key.toLowerCase();
|
|
15077
15095
|
if (seen.has(key))
|
|
@@ -15155,7 +15173,7 @@ function validateExtractedTree(stagingRoot) {
|
|
|
15155
15173
|
const lst = lstatSync(fullPath);
|
|
15156
15174
|
if (lst.isSymbolicLink()) {
|
|
15157
15175
|
const linkTarget = readlinkSync(fullPath);
|
|
15158
|
-
const resolvedTarget =
|
|
15176
|
+
const resolvedTarget = resolve7(dirname5(fullPath), linkTarget);
|
|
15159
15177
|
const rel2 = relative2(realRoot, resolvedTarget);
|
|
15160
15178
|
if (rel2.startsWith("..") || isAbsolute4(rel2) || win32.isAbsolute(rel2)) {
|
|
15161
15179
|
throw new Error(`extracted symlink ${fullPath} points outside staging root: ${linkTarget}`);
|
|
@@ -15273,7 +15291,7 @@ function copyOnnxLibraries(info, extractedDir, targetDir, realFiles, symlinks, c
|
|
|
15273
15291
|
unlinkSync4(dst);
|
|
15274
15292
|
} catch {}
|
|
15275
15293
|
const dstForContainment = join10(targetRoot, link.name);
|
|
15276
|
-
const resolvedTarget =
|
|
15294
|
+
const resolvedTarget = resolve7(dirname5(dstForContainment), link.target);
|
|
15277
15295
|
if (!isPathInsideRoot(targetRoot, resolvedTarget)) {
|
|
15278
15296
|
const message = `ONNX Runtime symlink ${link.name} points outside install dir: ${link.target}`;
|
|
15279
15297
|
if (requiredLibs.has(link.name)) {
|
|
@@ -16340,7 +16358,7 @@ class RevivableTransportPool {
|
|
|
16340
16358
|
const delay = Math.max(0, this.revivalRetryNotBefore - Date.now());
|
|
16341
16359
|
if (delay > 0) {
|
|
16342
16360
|
let scheduled;
|
|
16343
|
-
scheduled = new Promise((
|
|
16361
|
+
scheduled = new Promise((resolve8) => setTimeout(resolve8, delay)).then(() => {
|
|
16344
16362
|
if (this.revival === scheduled)
|
|
16345
16363
|
this.revival = null;
|
|
16346
16364
|
return this.ensureActivePool();
|
|
@@ -17443,7 +17461,7 @@ import {
|
|
|
17443
17461
|
// package.json
|
|
17444
17462
|
var package_default = {
|
|
17445
17463
|
name: "@cortexkit/aft-pi",
|
|
17446
|
-
version: "0.
|
|
17464
|
+
version: "0.53.0",
|
|
17447
17465
|
type: "module",
|
|
17448
17466
|
description: "Pi coding agent extension for Agent File Tools (AFT) — tree-sitter and LSP-powered code analysis",
|
|
17449
17467
|
main: "dist/index.js",
|
|
@@ -17466,19 +17484,19 @@ var package_default = {
|
|
|
17466
17484
|
"test:unit": "bun test src/__tests__ --path-ignore-patterns 'src/__tests__/e2e/**'"
|
|
17467
17485
|
},
|
|
17468
17486
|
dependencies: {
|
|
17469
|
-
"@cortexkit/aft-bridge": "0.
|
|
17487
|
+
"@cortexkit/aft-bridge": "0.53.0",
|
|
17470
17488
|
"comment-json": "^5.0.0",
|
|
17471
17489
|
diff: "^8.0.4",
|
|
17472
17490
|
typebox: "1.1.38",
|
|
17473
17491
|
zod: "^4.4.3"
|
|
17474
17492
|
},
|
|
17475
17493
|
optionalDependencies: {
|
|
17476
|
-
"@cortexkit/aft-darwin-arm64": "0.
|
|
17477
|
-
"@cortexkit/aft-darwin-x64": "0.
|
|
17478
|
-
"@cortexkit/aft-linux-arm64": "0.
|
|
17479
|
-
"@cortexkit/aft-linux-x64": "0.
|
|
17480
|
-
"@cortexkit/aft-win32-arm64": "0.
|
|
17481
|
-
"@cortexkit/aft-win32-x64": "0.
|
|
17494
|
+
"@cortexkit/aft-darwin-arm64": "0.53.0",
|
|
17495
|
+
"@cortexkit/aft-darwin-x64": "0.53.0",
|
|
17496
|
+
"@cortexkit/aft-linux-arm64": "0.53.0",
|
|
17497
|
+
"@cortexkit/aft-linux-x64": "0.53.0",
|
|
17498
|
+
"@cortexkit/aft-win32-arm64": "0.53.0",
|
|
17499
|
+
"@cortexkit/aft-win32-x64": "0.53.0"
|
|
17482
17500
|
},
|
|
17483
17501
|
devDependencies: {
|
|
17484
17502
|
"@earendil-works/pi-coding-agent": "^0.80.2",
|
|
@@ -17622,13 +17640,16 @@ function coerceAftStatus(response) {
|
|
|
17622
17640
|
project_root: readNullableString(response.project_root),
|
|
17623
17641
|
canonical_root: readNullableString(response.canonical_root),
|
|
17624
17642
|
cache_role: readString(response.cache_role, "not_initialized"),
|
|
17643
|
+
degraded: readBoolean(response.degraded),
|
|
17644
|
+
degraded_reasons: Array.isArray(response.degraded_reasons) ? response.degraded_reasons.filter((r) => typeof r === "string") : [],
|
|
17625
17645
|
message: typeof response.message === "string" ? response.message : undefined,
|
|
17626
17646
|
features: {
|
|
17627
17647
|
format_on_edit: readBoolean(features.format_on_edit),
|
|
17628
17648
|
validate_on_edit: readString(features.validate_on_edit, "off"),
|
|
17629
17649
|
restrict_to_project_root: readBoolean(features.restrict_to_project_root),
|
|
17630
17650
|
search_index: readBoolean(features.search_index ?? features.experimental_search_index),
|
|
17631
|
-
semantic_search: readBoolean(features.semantic_search ?? features.experimental_semantic_search)
|
|
17651
|
+
semantic_search: readBoolean(features.semantic_search ?? features.experimental_semantic_search),
|
|
17652
|
+
callgraph_store: readBoolean(features.callgraph_store)
|
|
17632
17653
|
},
|
|
17633
17654
|
search_index: {
|
|
17634
17655
|
status: readString(searchIndex.status, "unknown"),
|
|
@@ -17679,21 +17700,10 @@ function formatStatusDialogMessage(status) {
|
|
|
17679
17700
|
`AFT version: ${status.version}`,
|
|
17680
17701
|
`Project root: ${status.project_root ?? "(not configured)"}`,
|
|
17681
17702
|
`Canonical root: ${status.canonical_root ?? "(not configured)"}`,
|
|
17682
|
-
`Cache role: ${formatCacheRoleLabel(status.cache_role)}
|
|
17683
|
-
"",
|
|
17684
|
-
"Enabled features",
|
|
17685
|
-
`- format_on_edit: ${formatFlag(status.features.format_on_edit)}`,
|
|
17686
|
-
`- search_index: ${formatFlag(status.features.search_index)}`,
|
|
17687
|
-
`- semantic_search: ${formatFlag(status.features.semantic_search)}`,
|
|
17688
|
-
"",
|
|
17689
|
-
"Search index",
|
|
17690
|
-
`- status: ${status.search_index.status}`,
|
|
17691
|
-
`- files: ${formatCount(status.search_index.files)}`,
|
|
17692
|
-
`- trigrams: ${formatCount(status.search_index.trigrams)}`,
|
|
17693
|
-
"",
|
|
17694
|
-
"Semantic index",
|
|
17695
|
-
`- status: ${formatSemanticIndexStatus(status.semantic_index.status, status.semantic_index.stage)}`
|
|
17703
|
+
`Cache role: ${formatCacheRoleLabel(status.cache_role)}`
|
|
17696
17704
|
];
|
|
17705
|
+
appendDegradedStatus(lines, status, false);
|
|
17706
|
+
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)}`);
|
|
17697
17707
|
const refreshing = formatSemanticRefreshing(status.semantic_index.refreshing_count);
|
|
17698
17708
|
if (refreshing) {
|
|
17699
17709
|
lines.push(`- ${refreshing}`);
|
|
@@ -17743,6 +17753,15 @@ function formatStatusDialogMessage(status) {
|
|
|
17743
17753
|
return lines.join(`
|
|
17744
17754
|
`);
|
|
17745
17755
|
}
|
|
17756
|
+
function appendDegradedStatus(lines, status, markdown) {
|
|
17757
|
+
if (!status.degraded || status.degraded_reasons.length === 0)
|
|
17758
|
+
return;
|
|
17759
|
+
lines.push("", markdown ? "### Degraded mode" : "Degraded mode");
|
|
17760
|
+
for (const reason of status.degraded_reasons) {
|
|
17761
|
+
const detail = reason === "home_root" ? "project root is your home directory; heavy indexes are disabled" : reason;
|
|
17762
|
+
lines.push(`- ${detail}`);
|
|
17763
|
+
}
|
|
17764
|
+
}
|
|
17746
17765
|
|
|
17747
17766
|
// src/tools/_shared.ts
|
|
17748
17767
|
import { existsSync as existsSync9 } from "node:fs";
|
|
@@ -17753,7 +17772,8 @@ var optionalInt = (min, max, description = "(integer)") => Type.Optional(Type.Un
|
|
|
17753
17772
|
function withPathAliasPreparation(tool) {
|
|
17754
17773
|
const existing = tool.prepareArguments;
|
|
17755
17774
|
const prepare = (args) => {
|
|
17756
|
-
const
|
|
17775
|
+
const isEditTool = tool.name === "edit" || tool.name === "aft_edit";
|
|
17776
|
+
const prepared = isEditTool ? prepareCanonicalEditArguments("edit", args) : prepareCanonicalPathArguments(tool.name, args);
|
|
17757
17777
|
return existing ? existing(prepared) : prepared;
|
|
17758
17778
|
};
|
|
17759
17779
|
return {
|
|
@@ -17980,7 +18000,7 @@ function renderInner(s, error3, theme, innerWidth) {
|
|
|
17980
18000
|
lines.push(line);
|
|
17981
18001
|
lines.push("");
|
|
17982
18002
|
lines.push(theme.fg("muted", "Features"));
|
|
17983
|
-
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)}`);
|
|
18003
|
+
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)}`);
|
|
17984
18004
|
const compressionRows = formatCompressionStatusRows(s.compression);
|
|
17985
18005
|
if (compressionRows.length > 0) {
|
|
17986
18006
|
lines.push("");
|
|
@@ -18138,6 +18158,8 @@ function registerStatusCommand(pi, ctx) {
|
|
|
18138
18158
|
|
|
18139
18159
|
// src/config.ts
|
|
18140
18160
|
import { existsSync as existsSync10, readFileSync as readFileSync7, renameSync as renameSync5, unlinkSync as unlinkSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
18161
|
+
import { homedir as homedir12 } from "node:os";
|
|
18162
|
+
import { isAbsolute as isAbsolute6 } from "node:path";
|
|
18141
18163
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
18142
18164
|
|
|
18143
18165
|
// ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
@@ -32501,6 +32523,32 @@ var CheckerEnum = exports_external.enum([
|
|
|
32501
32523
|
"none"
|
|
32502
32524
|
]);
|
|
32503
32525
|
var ConfigureWarningsDeliveryEnum = exports_external.enum(["toast", "log", "chat"]);
|
|
32526
|
+
var IndexKindSchema = exports_external.enum(["search", "semantic", "callgraph"]);
|
|
32527
|
+
function isSupportedAbsoluteIndexPath(path2) {
|
|
32528
|
+
if (path2 === "~" || path2.startsWith("~/") || path2.startsWith("~\\")) {
|
|
32529
|
+
return isAbsolute6(homedir12());
|
|
32530
|
+
}
|
|
32531
|
+
return isAbsolute6(path2);
|
|
32532
|
+
}
|
|
32533
|
+
var IndexRootSchema = exports_external.object({
|
|
32534
|
+
path: exports_external.string().refine(isSupportedAbsoluteIndexPath, {
|
|
32535
|
+
message: "index.roots path must be absolute after ~ expansion"
|
|
32536
|
+
}),
|
|
32537
|
+
indexes: exports_external.array(IndexKindSchema).min(1, "index.roots indexes must be non-empty")
|
|
32538
|
+
}).superRefine(({ indexes }, context) => {
|
|
32539
|
+
if (new Set(indexes).size !== indexes.length) {
|
|
32540
|
+
context.addIssue({
|
|
32541
|
+
code: "custom",
|
|
32542
|
+
message: "index.roots indexes must not contain duplicates"
|
|
32543
|
+
});
|
|
32544
|
+
}
|
|
32545
|
+
}).transform(({ path: path2, indexes }) => ({
|
|
32546
|
+
path: path2,
|
|
32547
|
+
indexes: ["search", "semantic", "callgraph"].filter((kind) => indexes.includes(kind) || kind === "search" && indexes.includes("semantic"))
|
|
32548
|
+
}));
|
|
32549
|
+
var IndexConfigSchema = exports_external.object({
|
|
32550
|
+
roots: exports_external.array(IndexRootSchema).optional()
|
|
32551
|
+
});
|
|
32504
32552
|
var SemanticConfigSchema = exports_external.object({
|
|
32505
32553
|
backend: exports_external.enum(["fastembed", "openai_compatible", "ollama"]).optional(),
|
|
32506
32554
|
model: exports_external.string().trim().min(1).optional(),
|
|
@@ -32566,7 +32614,12 @@ var SubcConfigSchema = exports_external.object({
|
|
|
32566
32614
|
connection_file: exports_external.string().optional()
|
|
32567
32615
|
});
|
|
32568
32616
|
var GhShimConfigSchema = exports_external.object({
|
|
32569
|
-
enabled: exports_external.boolean().optional()
|
|
32617
|
+
enabled: exports_external.boolean().optional(),
|
|
32618
|
+
binary_path: exports_external.string().trim().refine(isAbsolute6, "gh_shim.binary_path must be absolute").optional()
|
|
32619
|
+
});
|
|
32620
|
+
var GitCoAuthorSchema = exports_external.string().trim().refine((value) => value === "off" || value === "auto" || /^[^<>\r\n]+\s+<[^<>\s@]+@[^<>\s@]+>$/.test(value), "git.co_author must be 'off', 'auto', or an explicit 'Name <email>' identity");
|
|
32621
|
+
var GitConfigSchema = exports_external.object({
|
|
32622
|
+
co_author: GitCoAuthorSchema.optional()
|
|
32570
32623
|
});
|
|
32571
32624
|
var InspectConfigSchema = exports_external.object({
|
|
32572
32625
|
enabled: exports_external.boolean().optional(),
|
|
@@ -32597,10 +32650,12 @@ var AftConfigSchema = exports_external.preprocess((value) => stripHarnessSpecifi
|
|
|
32597
32650
|
formatter: exports_external.record(exports_external.string(), FormatterEnum).optional(),
|
|
32598
32651
|
checker: exports_external.record(exports_external.string(), CheckerEnum).optional(),
|
|
32599
32652
|
configure_warnings_delivery: ConfigureWarningsDeliveryEnum.optional(),
|
|
32653
|
+
hoist_builtin_tools: exports_external.boolean().optional(),
|
|
32600
32654
|
tool_surface: exports_external.enum(["minimal", "recommended", "all"]).optional(),
|
|
32601
32655
|
disabled_tools: exports_external.array(exports_external.string()).optional(),
|
|
32602
32656
|
restrict_to_project_root: exports_external.boolean().optional(),
|
|
32603
32657
|
search_index: exports_external.boolean().optional(),
|
|
32658
|
+
index: IndexConfigSchema.optional(),
|
|
32604
32659
|
semantic_search: exports_external.boolean().optional(),
|
|
32605
32660
|
callgraph_store: exports_external.boolean().optional(),
|
|
32606
32661
|
callgraph_chunk_size: exports_external.number().optional(),
|
|
@@ -32615,7 +32670,8 @@ var AftConfigSchema = exports_external.preprocess((value) => stripHarnessSpecifi
|
|
|
32615
32670
|
semantic: SemanticConfigSchema.optional(),
|
|
32616
32671
|
bridge: BridgeConfigSchema.optional(),
|
|
32617
32672
|
subc: SubcConfigSchema.optional(),
|
|
32618
|
-
gh_shim: GhShimConfigSchema.optional()
|
|
32673
|
+
gh_shim: GhShimConfigSchema.optional(),
|
|
32674
|
+
git: GitConfigSchema.optional()
|
|
32619
32675
|
}).strict());
|
|
32620
32676
|
var CONFIG_MIGRATIONS = [
|
|
32621
32677
|
{ oldKey: "experimental_search_index", newPath: ["search_index"] },
|
|
@@ -32778,6 +32834,12 @@ function recordConfigParseFailure(configPath, errorMessage) {
|
|
|
32778
32834
|
configLoadErrors.push({ path: configPath, message: errorMessage });
|
|
32779
32835
|
warn2(formatConfigParseFailureMessage(configPath, errorMessage));
|
|
32780
32836
|
}
|
|
32837
|
+
function warnIgnoredHarnessSpecificConfigKeys(config2, configPath) {
|
|
32838
|
+
const ignored = OPENCODE_ONLY_KEYS.filter((key) => Object.hasOwn(config2, key));
|
|
32839
|
+
if (ignored.length === 0)
|
|
32840
|
+
return;
|
|
32841
|
+
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.`);
|
|
32842
|
+
}
|
|
32781
32843
|
function loadConfigFromPath(configPath) {
|
|
32782
32844
|
try {
|
|
32783
32845
|
if (!existsSync10(configPath))
|
|
@@ -32790,6 +32852,7 @@ function loadConfigFromPath(configPath) {
|
|
|
32790
32852
|
}
|
|
32791
32853
|
migrateRawConfig(rawConfig, configPath, { log: log2, warn: warn2 });
|
|
32792
32854
|
const cleanConfig = stripJsoncSymbols(rawConfig);
|
|
32855
|
+
warnIgnoredHarnessSpecificConfigKeys(cleanConfig, configPath);
|
|
32793
32856
|
const result = AftConfigSchema.safeParse(cleanConfig);
|
|
32794
32857
|
if (result.success) {
|
|
32795
32858
|
log2(`Config loaded from ${configPath}`);
|
|
@@ -32953,6 +33016,7 @@ var PROJECT_SAFE_TOP_LEVEL_FIELDS = new Set([
|
|
|
32953
33016
|
"enabled",
|
|
32954
33017
|
"edit_mode",
|
|
32955
33018
|
"tool_surface",
|
|
33019
|
+
"hoist_builtin_tools",
|
|
32956
33020
|
"format_on_edit",
|
|
32957
33021
|
"validate_on_edit",
|
|
32958
33022
|
"configure_warnings_delivery",
|
|
@@ -32962,6 +33026,7 @@ var PROJECT_SAFE_TOP_LEVEL_FIELDS = new Set([
|
|
|
32962
33026
|
"callgraph_chunk_size",
|
|
32963
33027
|
"inspect",
|
|
32964
33028
|
"worktree",
|
|
33029
|
+
"git",
|
|
32965
33030
|
"experimental",
|
|
32966
33031
|
"bash"
|
|
32967
33032
|
]);
|
|
@@ -32984,6 +33049,8 @@ function getStrippedTopLevelKeys(override) {
|
|
|
32984
33049
|
stripped.push("bridge");
|
|
32985
33050
|
if (override.backup !== undefined)
|
|
32986
33051
|
stripped.push("backup");
|
|
33052
|
+
if (override.index?.roots !== undefined)
|
|
33053
|
+
stripped.push("index.roots");
|
|
32987
33054
|
if (override.sandbox?.enabled === false)
|
|
32988
33055
|
stripped.push("sandbox.enabled");
|
|
32989
33056
|
if (override.sandbox?.write_allow !== undefined)
|
|
@@ -33690,18 +33757,18 @@ function ensureInstallAnchor(cwd) {
|
|
|
33690
33757
|
}
|
|
33691
33758
|
}
|
|
33692
33759
|
function runInstall(spec, version2, cwd, signal) {
|
|
33693
|
-
return new Promise((
|
|
33760
|
+
return new Promise((resolve8) => {
|
|
33694
33761
|
const target = `${spec.npm}@${version2}`;
|
|
33695
33762
|
log2(`[lsp] installing ${target} to ${cwd}`);
|
|
33696
33763
|
if (signal?.aborted) {
|
|
33697
33764
|
warn2(`[lsp] install ${target} aborted before spawn`);
|
|
33698
|
-
|
|
33765
|
+
resolve8(false);
|
|
33699
33766
|
return;
|
|
33700
33767
|
}
|
|
33701
33768
|
const npm = resolveNpm();
|
|
33702
33769
|
if (!npm) {
|
|
33703
33770
|
warn2(`[lsp] npm not found on PATH or known locations; cannot install ${target}`);
|
|
33704
|
-
|
|
33771
|
+
resolve8(false);
|
|
33705
33772
|
return;
|
|
33706
33773
|
}
|
|
33707
33774
|
ensureInstallAnchor(cwd);
|
|
@@ -33724,7 +33791,7 @@ function runInstall(spec, version2, cwd, signal) {
|
|
|
33724
33791
|
return;
|
|
33725
33792
|
settled = true;
|
|
33726
33793
|
cleanup();
|
|
33727
|
-
|
|
33794
|
+
resolve8(ok);
|
|
33728
33795
|
};
|
|
33729
33796
|
const onAbort = () => {
|
|
33730
33797
|
warn2(`[lsp] install ${target} aborted during shutdown`);
|
|
@@ -33825,7 +33892,7 @@ function cachedPackageDir(npmPackage) {
|
|
|
33825
33892
|
return lspBinDir(npmPackage).replace(/[\\/]node_modules[\\/]\.bin[\\/]?$/, "");
|
|
33826
33893
|
}
|
|
33827
33894
|
function hashInstalledBinary(spec) {
|
|
33828
|
-
return new Promise((
|
|
33895
|
+
return new Promise((resolve8, reject) => {
|
|
33829
33896
|
const candidates = process.platform === "win32" ? [
|
|
33830
33897
|
lspBinaryPath(spec.npm, spec.binary),
|
|
33831
33898
|
lspBinaryPath(spec.npm, `${spec.binary}.cmd`),
|
|
@@ -33849,7 +33916,7 @@ function hashInstalledBinary(spec) {
|
|
|
33849
33916
|
const stream = createReadStream(pathToHash);
|
|
33850
33917
|
stream.on("error", reject);
|
|
33851
33918
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
33852
|
-
stream.on("end", () =>
|
|
33919
|
+
stream.on("end", () => resolve8(hash2.digest("hex")));
|
|
33853
33920
|
});
|
|
33854
33921
|
}
|
|
33855
33922
|
function installedBinaryPath(spec) {
|
|
@@ -33976,7 +34043,7 @@ import {
|
|
|
33976
34043
|
unlinkSync as unlinkSync7,
|
|
33977
34044
|
writeFileSync as writeFileSync7
|
|
33978
34045
|
} from "node:fs";
|
|
33979
|
-
import { dirname as dirname6, join as join15, relative as relative3, resolve as
|
|
34046
|
+
import { dirname as dirname6, join as join15, relative as relative3, resolve as resolve8 } from "node:path";
|
|
33980
34047
|
import { Readable as Readable3 } from "node:stream";
|
|
33981
34048
|
import { pipeline as pipeline3 } from "node:stream/promises";
|
|
33982
34049
|
|
|
@@ -34133,12 +34200,12 @@ function writeGithubInstalledMetaIn(installDir, version2, binarySha256, archiveS
|
|
|
34133
34200
|
var MAX_DOWNLOAD_BYTES3 = 256 * 1024 * 1024;
|
|
34134
34201
|
var MAX_EXTRACT_BYTES2 = 1024 * 1024 * 1024;
|
|
34135
34202
|
function sha256OfFile(path2) {
|
|
34136
|
-
return new Promise((
|
|
34203
|
+
return new Promise((resolve9, reject) => {
|
|
34137
34204
|
const hash2 = createHash5("sha256");
|
|
34138
34205
|
const stream = createReadStream2(path2);
|
|
34139
34206
|
stream.on("error", reject);
|
|
34140
34207
|
stream.on("data", (chunk) => hash2.update(chunk));
|
|
34141
|
-
stream.on("end", () =>
|
|
34208
|
+
stream.on("end", () => resolve9(hash2.digest("hex")));
|
|
34142
34209
|
});
|
|
34143
34210
|
}
|
|
34144
34211
|
function sha256OfFileSync2(path2) {
|
|
@@ -34395,7 +34462,7 @@ function validateExtraction(stagingRoot) {
|
|
|
34395
34462
|
throw new Error(`failed to realpath ${full}: ${err}`);
|
|
34396
34463
|
}
|
|
34397
34464
|
const rel = relative3(realStagingRoot, realFull);
|
|
34398
|
-
if (rel.startsWith("..") ||
|
|
34465
|
+
if (rel.startsWith("..") || resolve8(realStagingRoot, rel) !== realFull) {
|
|
34399
34466
|
throw new Error(`archive entry escapes staging root: ${full} → ${realFull} (zip-slip defense)`);
|
|
34400
34467
|
}
|
|
34401
34468
|
if (lst.isDirectory()) {
|
|
@@ -34978,8 +35045,8 @@ function installProcessHandlers() {
|
|
|
34978
35045
|
}
|
|
34979
35046
|
signalShutdownStarted = true;
|
|
34980
35047
|
process.exitCode = SIGNAL_EXIT_CODES[sig];
|
|
34981
|
-
const timeout = new Promise((
|
|
34982
|
-
setTimeout(
|
|
35048
|
+
const timeout = new Promise((resolve9) => {
|
|
35049
|
+
setTimeout(resolve9, SIGNAL_CLEANUP_TIMEOUT_MS);
|
|
34983
35050
|
});
|
|
34984
35051
|
Promise.race([runCleanups(sig), timeout]).finally(() => {
|
|
34985
35052
|
process.exit(SIGNAL_EXIT_CODES[sig]);
|
|
@@ -35021,16 +35088,222 @@ import { Type as Type3 } from "typebox";
|
|
|
35021
35088
|
|
|
35022
35089
|
// src/tools/hoisted.ts
|
|
35023
35090
|
import { stat as stat2 } from "node:fs/promises";
|
|
35024
|
-
import { homedir as
|
|
35025
|
-
import { isAbsolute as
|
|
35091
|
+
import { homedir as homedir14 } from "node:os";
|
|
35092
|
+
import { isAbsolute as isAbsolute7, relative as relative4, resolve as resolve9, sep } from "node:path";
|
|
35026
35093
|
import {
|
|
35027
|
-
renderDiff
|
|
35094
|
+
renderDiff as renderDiff2
|
|
35028
35095
|
} from "@earendil-works/pi-coding-agent";
|
|
35029
|
-
import { Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
35096
|
+
import { Container as Container2, Spacer as Spacer2, Text as Text2 } from "@earendil-works/pi-tui";
|
|
35030
35097
|
import { Type as Type2 } from "typebox";
|
|
35031
35098
|
|
|
35032
35099
|
// src/tools/diff-format.ts
|
|
35033
35100
|
import { diffLines } from "diff";
|
|
35101
|
+
|
|
35102
|
+
// src/tools/render-helpers.ts
|
|
35103
|
+
import { homedir as homedir13 } from "node:os";
|
|
35104
|
+
import { renderDiff } from "@earendil-works/pi-coding-agent";
|
|
35105
|
+
import { Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
35106
|
+
var NATIVE_COLLAPSED_RESULT_MAX_LINES = 5;
|
|
35107
|
+
function normalizeTerminalText(text) {
|
|
35108
|
+
return text.replace(/\r/g, "");
|
|
35109
|
+
}
|
|
35110
|
+
|
|
35111
|
+
class TerminalSafeComponent {
|
|
35112
|
+
component;
|
|
35113
|
+
constructor(component) {
|
|
35114
|
+
this.component = component;
|
|
35115
|
+
}
|
|
35116
|
+
render(width) {
|
|
35117
|
+
return this.component.render(width).map(normalizeTerminalText);
|
|
35118
|
+
}
|
|
35119
|
+
invalidate() {
|
|
35120
|
+
this.component.invalidate?.();
|
|
35121
|
+
}
|
|
35122
|
+
handleInput(data) {
|
|
35123
|
+
this.component.handleInput?.(data);
|
|
35124
|
+
}
|
|
35125
|
+
}
|
|
35126
|
+
function reuseText(last) {
|
|
35127
|
+
return last instanceof Text ? last : new Text("", 0, 0);
|
|
35128
|
+
}
|
|
35129
|
+
function reuseContainer(last) {
|
|
35130
|
+
return last instanceof Container ? last : new Container;
|
|
35131
|
+
}
|
|
35132
|
+
function shortenPath2(path2) {
|
|
35133
|
+
const home = homedir13();
|
|
35134
|
+
if (path2.startsWith(home))
|
|
35135
|
+
return `~${path2.slice(home.length)}`;
|
|
35136
|
+
return path2;
|
|
35137
|
+
}
|
|
35138
|
+
function renderToolCall(toolName, summary, theme, context) {
|
|
35139
|
+
const text = reuseText(context.lastComponent);
|
|
35140
|
+
const suffix = summary ? ` ${summary}` : "";
|
|
35141
|
+
text.setText(`${theme.fg("toolTitle", theme.bold(toolName))}${suffix}`);
|
|
35142
|
+
return text;
|
|
35143
|
+
}
|
|
35144
|
+
function accentPath(theme, path2) {
|
|
35145
|
+
if (!path2)
|
|
35146
|
+
return theme.fg("toolOutput", "...");
|
|
35147
|
+
return theme.fg("accent", shortenPath2(path2));
|
|
35148
|
+
}
|
|
35149
|
+
function collectTextContent(result) {
|
|
35150
|
+
return result.content.filter((part) => part.type === "text").map((part) => part.text ?? "").join(`
|
|
35151
|
+
`).trim();
|
|
35152
|
+
}
|
|
35153
|
+
function extractStructuredPayload(result) {
|
|
35154
|
+
if (result.details !== undefined)
|
|
35155
|
+
return result.details;
|
|
35156
|
+
const text = collectTextContent(result);
|
|
35157
|
+
if (!text)
|
|
35158
|
+
return;
|
|
35159
|
+
try {
|
|
35160
|
+
return JSON.parse(text);
|
|
35161
|
+
} catch {
|
|
35162
|
+
return;
|
|
35163
|
+
}
|
|
35164
|
+
}
|
|
35165
|
+
function renderErrorResult(result, fallback, theme, context) {
|
|
35166
|
+
const text = reuseText(context.lastComponent);
|
|
35167
|
+
const message = collectTextContent(result) || fallback;
|
|
35168
|
+
text.setText(`
|
|
35169
|
+
${theme.fg("error", message)}`);
|
|
35170
|
+
return text;
|
|
35171
|
+
}
|
|
35172
|
+
function collapsibleResult({
|
|
35173
|
+
summary,
|
|
35174
|
+
full,
|
|
35175
|
+
expanded,
|
|
35176
|
+
context
|
|
35177
|
+
}) {
|
|
35178
|
+
const renderedAtCollapseWidth = full.render(200);
|
|
35179
|
+
const terminalSafeFull = renderedAtCollapseWidth.some((line) => line.includes("\r")) ? new TerminalSafeComponent(full) : full;
|
|
35180
|
+
if (expanded === true || renderedAtCollapseWidth.length <= NATIVE_COLLAPSED_RESULT_MAX_LINES) {
|
|
35181
|
+
return terminalSafeFull;
|
|
35182
|
+
}
|
|
35183
|
+
const text = reuseText(context.lastComponent);
|
|
35184
|
+
text.setText(`
|
|
35185
|
+
${summary.replace(/[\r\n]+/g, " ").trim()}`);
|
|
35186
|
+
return text;
|
|
35187
|
+
}
|
|
35188
|
+
function renderSections(sections, context) {
|
|
35189
|
+
const container = reuseContainer(context.lastComponent);
|
|
35190
|
+
container.clear();
|
|
35191
|
+
const visibleSections = sections.filter((section) => section.trim().length > 0);
|
|
35192
|
+
if (visibleSections.length === 0)
|
|
35193
|
+
return container;
|
|
35194
|
+
container.addChild(new Spacer(1));
|
|
35195
|
+
visibleSections.forEach((section, index) => {
|
|
35196
|
+
if (index > 0)
|
|
35197
|
+
container.addChild(new Spacer(1));
|
|
35198
|
+
container.addChild(new Text(section, 0, 0));
|
|
35199
|
+
});
|
|
35200
|
+
return container;
|
|
35201
|
+
}
|
|
35202
|
+
function asRecord3(value) {
|
|
35203
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
35204
|
+
return;
|
|
35205
|
+
return value;
|
|
35206
|
+
}
|
|
35207
|
+
function asRecords2(value) {
|
|
35208
|
+
return Array.isArray(value) ? value.map(asRecord3).filter(Boolean) : [];
|
|
35209
|
+
}
|
|
35210
|
+
function asString2(value) {
|
|
35211
|
+
return typeof value === "string" ? value : undefined;
|
|
35212
|
+
}
|
|
35213
|
+
function asNumber2(value) {
|
|
35214
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
35215
|
+
}
|
|
35216
|
+
function formatValue(value) {
|
|
35217
|
+
if (Array.isArray(value))
|
|
35218
|
+
return value.map(formatValue).join(", ");
|
|
35219
|
+
if (typeof value === "string")
|
|
35220
|
+
return value;
|
|
35221
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
35222
|
+
return String(value);
|
|
35223
|
+
if (value === null || value === undefined)
|
|
35224
|
+
return "—";
|
|
35225
|
+
try {
|
|
35226
|
+
return JSON.stringify(value);
|
|
35227
|
+
} catch {
|
|
35228
|
+
return String(value);
|
|
35229
|
+
}
|
|
35230
|
+
}
|
|
35231
|
+
function groupByFile(items, getFile) {
|
|
35232
|
+
const groups = new Map;
|
|
35233
|
+
items.forEach((item) => {
|
|
35234
|
+
const file2 = getFile(item) ?? "(unknown file)";
|
|
35235
|
+
const current = groups.get(file2) ?? [];
|
|
35236
|
+
current.push(item);
|
|
35237
|
+
groups.set(file2, current);
|
|
35238
|
+
});
|
|
35239
|
+
return groups;
|
|
35240
|
+
}
|
|
35241
|
+
function formatTimestamp(value) {
|
|
35242
|
+
if (typeof value === "string" && value.length > 0)
|
|
35243
|
+
return value;
|
|
35244
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
35245
|
+
return;
|
|
35246
|
+
const millis = value > 1000000000000 ? value : value * 1000;
|
|
35247
|
+
const date5 = new Date(millis);
|
|
35248
|
+
if (Number.isNaN(date5.getTime()))
|
|
35249
|
+
return String(value);
|
|
35250
|
+
return date5.toISOString().replace("T", " ").replace(".000Z", "Z");
|
|
35251
|
+
}
|
|
35252
|
+
function formatUnifiedDiffForPi(unifiedDiff) {
|
|
35253
|
+
if (!unifiedDiff.trim())
|
|
35254
|
+
return "";
|
|
35255
|
+
const entries = [];
|
|
35256
|
+
const hunkHeader = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
|
|
35257
|
+
let oldLine = 1;
|
|
35258
|
+
let newLine = 1;
|
|
35259
|
+
for (const line of unifiedDiff.split(`
|
|
35260
|
+
`)) {
|
|
35261
|
+
if (!line)
|
|
35262
|
+
continue;
|
|
35263
|
+
if (line.startsWith("--- ") || line.startsWith("+++ "))
|
|
35264
|
+
continue;
|
|
35265
|
+
if (line.startsWith("\"))
|
|
35266
|
+
continue;
|
|
35267
|
+
const headerMatch = line.match(hunkHeader);
|
|
35268
|
+
if (headerMatch) {
|
|
35269
|
+
oldLine = Number(headerMatch[1]);
|
|
35270
|
+
newLine = Number(headerMatch[2]);
|
|
35271
|
+
continue;
|
|
35272
|
+
}
|
|
35273
|
+
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
35274
|
+
entries.push({ prefix: "+", line: newLine, text: line.slice(1) });
|
|
35275
|
+
newLine += 1;
|
|
35276
|
+
continue;
|
|
35277
|
+
}
|
|
35278
|
+
if (line.startsWith("-") && !line.startsWith("---")) {
|
|
35279
|
+
entries.push({ prefix: "-", line: oldLine, text: line.slice(1) });
|
|
35280
|
+
oldLine += 1;
|
|
35281
|
+
continue;
|
|
35282
|
+
}
|
|
35283
|
+
if (line.startsWith(" ")) {
|
|
35284
|
+
entries.push({ prefix: " ", line: oldLine, text: line.slice(1) });
|
|
35285
|
+
oldLine += 1;
|
|
35286
|
+
newLine += 1;
|
|
35287
|
+
}
|
|
35288
|
+
}
|
|
35289
|
+
if (entries.length === 0)
|
|
35290
|
+
return "";
|
|
35291
|
+
const width = String(entries.reduce((max, entry) => Math.max(max, entry.line), 1)).length;
|
|
35292
|
+
return normalizeTerminalText(entries.map((entry) => `${entry.prefix}${String(entry.line).padStart(width, " ")} ${entry.text}`).join(`
|
|
35293
|
+
`));
|
|
35294
|
+
}
|
|
35295
|
+
function renderUnifiedDiff(unifiedDiff) {
|
|
35296
|
+
const piDiff = formatUnifiedDiffForPi(unifiedDiff);
|
|
35297
|
+
if (!piDiff)
|
|
35298
|
+
return "";
|
|
35299
|
+
try {
|
|
35300
|
+
return normalizeTerminalText(renderDiff(piDiff));
|
|
35301
|
+
} catch {
|
|
35302
|
+
return normalizeTerminalText(piDiff);
|
|
35303
|
+
}
|
|
35304
|
+
}
|
|
35305
|
+
|
|
35306
|
+
// src/tools/diff-format.ts
|
|
35034
35307
|
var DEFAULT_CONTEXT_LINES = 4;
|
|
35035
35308
|
function formatDiffForPi(oldContent, newContent, contextLines = DEFAULT_CONTEXT_LINES) {
|
|
35036
35309
|
const parts = diffLines(oldContent, newContent);
|
|
@@ -35127,8 +35400,11 @@ function formatDiffForPi(oldContent, newContent, contextLines = DEFAULT_CONTEXT_
|
|
|
35127
35400
|
}
|
|
35128
35401
|
lastWasChange = false;
|
|
35129
35402
|
}
|
|
35130
|
-
return {
|
|
35131
|
-
`
|
|
35403
|
+
return {
|
|
35404
|
+
diff: normalizeTerminalText(output.join(`
|
|
35405
|
+
`)),
|
|
35406
|
+
firstChangedLine
|
|
35407
|
+
};
|
|
35132
35408
|
}
|
|
35133
35409
|
|
|
35134
35410
|
// src/tools/hoisted.ts
|
|
@@ -35163,22 +35439,22 @@ function modelSupportsImages(extCtx) {
|
|
|
35163
35439
|
var NON_VISION_IMAGE_NOTE = "[Current model does not support images. The image will be omitted from this request.]";
|
|
35164
35440
|
function containsPath(parent, child) {
|
|
35165
35441
|
const rel = relative4(parent, child);
|
|
35166
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
35442
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute7(rel);
|
|
35167
35443
|
}
|
|
35168
35444
|
function normalizePathInput(path2) {
|
|
35169
35445
|
const decoded = decodeFileUrl(path2);
|
|
35170
35446
|
if (!decoded || !decoded.startsWith("~"))
|
|
35171
35447
|
return decoded;
|
|
35172
35448
|
if (decoded === "~")
|
|
35173
|
-
return
|
|
35449
|
+
return homedir14();
|
|
35174
35450
|
if (decoded.startsWith(`~${sep}`) || decoded.startsWith("~/")) {
|
|
35175
|
-
return
|
|
35451
|
+
return resolve9(homedir14(), decoded.slice(2));
|
|
35176
35452
|
}
|
|
35177
35453
|
return decoded;
|
|
35178
35454
|
}
|
|
35179
35455
|
function absoluteSearchPath(cwd, target) {
|
|
35180
35456
|
const expanded = normalizePathInput(target);
|
|
35181
|
-
return
|
|
35457
|
+
return isAbsolute7(expanded) ? expanded : resolve9(cwd, expanded);
|
|
35182
35458
|
}
|
|
35183
35459
|
async function searchPathExists(cwd, target) {
|
|
35184
35460
|
try {
|
|
@@ -35234,7 +35510,7 @@ async function assertExternalDirectoryPermission(extCtx, target, options = {}) {
|
|
|
35234
35510
|
if (!target)
|
|
35235
35511
|
return;
|
|
35236
35512
|
const expanded = normalizePathInput(target);
|
|
35237
|
-
const absoluteTarget =
|
|
35513
|
+
const absoluteTarget = isAbsolute7(expanded) ? expanded : resolve9(extCtx.cwd, expanded);
|
|
35238
35514
|
if (containsPath(extCtx.cwd, absoluteTarget))
|
|
35239
35515
|
return;
|
|
35240
35516
|
if (options.restrictToProjectRoot === false)
|
|
@@ -35360,20 +35636,25 @@ function validateBatchEdits(edits) {
|
|
|
35360
35636
|
});
|
|
35361
35637
|
}
|
|
35362
35638
|
function renderReadCall(args, theme, context) {
|
|
35363
|
-
const text =
|
|
35639
|
+
const text = reuseText2(context.lastComponent);
|
|
35364
35640
|
const filePath = args ? readPathArg(args) : undefined;
|
|
35365
|
-
const pathDisplay = filePath ? theme.fg("accent",
|
|
35641
|
+
const pathDisplay = filePath ? theme.fg("accent", shortenPath3(filePath)) : theme.fg("toolOutput", "...");
|
|
35366
35642
|
text.setText(`${theme.fg("toolTitle", theme.bold("read"))} ${pathDisplay}`);
|
|
35367
35643
|
return text;
|
|
35368
35644
|
}
|
|
35369
35645
|
function registerHoistedTools(pi, ctx, surface) {
|
|
35646
|
+
const prefix = surface.hoistBuiltinTools === false ? "aft_" : "";
|
|
35647
|
+
const readName = `${prefix}read`;
|
|
35648
|
+
const writeName = `${prefix}write`;
|
|
35649
|
+
const editName = `${prefix}edit`;
|
|
35650
|
+
const grepName = `${prefix}grep`;
|
|
35370
35651
|
if (surface.hoistRead) {
|
|
35371
35652
|
pi.registerTool(withPathAliasPreparation({
|
|
35372
|
-
name:
|
|
35373
|
-
label:
|
|
35653
|
+
name: readName,
|
|
35654
|
+
label: readName,
|
|
35374
35655
|
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.",
|
|
35375
35656
|
promptSnippet: "Read file contents (supports offset/limit for large files)",
|
|
35376
|
-
promptGuidelines: [
|
|
35657
|
+
promptGuidelines: [`Use ${readName} to examine files instead of cat or sed.`],
|
|
35377
35658
|
parameters: ReadParams,
|
|
35378
35659
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
35379
35660
|
const bridge = bridgeFor(ctx, extCtx.cwd);
|
|
@@ -35435,11 +35716,11 @@ PDFs aren't supported on the Pi harness yet.`, response);
|
|
|
35435
35716
|
if (surface.hoistWrite) {
|
|
35436
35717
|
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).";
|
|
35437
35718
|
pi.registerTool(withPathAliasPreparation({
|
|
35438
|
-
name:
|
|
35439
|
-
label:
|
|
35440
|
-
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 \`
|
|
35719
|
+
name: writeName,
|
|
35720
|
+
label: writeName,
|
|
35721
|
+
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.`,
|
|
35441
35722
|
promptSnippet: "Create or overwrite files (uses path; auto-formats)",
|
|
35442
|
-
promptGuidelines: [
|
|
35723
|
+
promptGuidelines: [`Use ${writeName} only for new files or complete rewrites.`],
|
|
35443
35724
|
parameters: WriteParams,
|
|
35444
35725
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
35445
35726
|
const filePathArg = mutationFilePathArg(params);
|
|
@@ -35464,17 +35745,17 @@ PDFs aren't supported on the Pi harness yet.`, response);
|
|
|
35464
35745
|
renderCall(args, theme, context) {
|
|
35465
35746
|
return renderMutationCall("write", mutationFilePathArg(args ?? {}), theme, context);
|
|
35466
35747
|
},
|
|
35467
|
-
renderResult(result,
|
|
35468
|
-
return renderMutationResult(result, theme, context);
|
|
35748
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
35749
|
+
return renderMutationResult(result, theme, context, options);
|
|
35469
35750
|
}
|
|
35470
35751
|
}));
|
|
35471
35752
|
}
|
|
35472
35753
|
if (surface.hoistEdit && ctx.hashlineEffective === true) {
|
|
35473
35754
|
pi.registerTool({
|
|
35474
|
-
name:
|
|
35475
|
-
label:
|
|
35755
|
+
name: editName,
|
|
35756
|
+
label: editName,
|
|
35476
35757
|
description: HASHLINE_EDIT_DESCRIPTION,
|
|
35477
|
-
promptSnippet:
|
|
35758
|
+
promptSnippet: `Apply a tagged hashline patch through the ${editName} tool`,
|
|
35478
35759
|
promptGuidelines: [
|
|
35479
35760
|
"Read a file to obtain its current hashline tag before editing it.",
|
|
35480
35761
|
"Pass exactly one patch string; paths and tags belong in patch section headers."
|
|
@@ -35506,13 +35787,13 @@ PDFs aren't supported on the Pi harness yet.`, response);
|
|
|
35506
35787
|
}
|
|
35507
35788
|
if (surface.hoistEdit && ctx.hashlineEffective !== true) {
|
|
35508
35789
|
pi.registerTool(withPathAliasPreparation({
|
|
35509
|
-
name:
|
|
35510
|
-
label:
|
|
35790
|
+
name: editName,
|
|
35791
|
+
label: editName,
|
|
35511
35792
|
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).",
|
|
35512
35793
|
promptSnippet: "Partial file edits via appendContent, edits[], or symbol plus content (exactly one mode per call).",
|
|
35513
35794
|
promptGuidelines: [
|
|
35514
|
-
|
|
35515
|
-
|
|
35795
|
+
`Prefer ${editName} over ${writeName} when changing part of an existing file.`,
|
|
35796
|
+
`Use ${editName} with appendContent when adding text to the end of a file.`,
|
|
35516
35797
|
"Use edits[] for multiple atomic changes in one file.",
|
|
35517
35798
|
"Include enough surrounding context in an edits[] find/replace item to make the match unique, or set replaceAll/occurrence explicitly."
|
|
35518
35799
|
],
|
|
@@ -35547,18 +35828,18 @@ PDFs aren't supported on the Pi harness yet.`, response);
|
|
|
35547
35828
|
renderCall(args, theme, context) {
|
|
35548
35829
|
return renderMutationCall("edit", mutationFilePathArg(args ?? {}), theme, context);
|
|
35549
35830
|
},
|
|
35550
|
-
renderResult(result,
|
|
35551
|
-
return renderMutationResult(result, theme, context);
|
|
35831
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
35832
|
+
return renderMutationResult(result, theme, context, options);
|
|
35552
35833
|
}
|
|
35553
35834
|
}));
|
|
35554
35835
|
}
|
|
35555
35836
|
if (surface.hoistGrep) {
|
|
35556
35837
|
pi.registerTool(withPathAliasPreparation({
|
|
35557
|
-
name:
|
|
35558
|
-
label:
|
|
35838
|
+
name: grepName,
|
|
35839
|
+
label: grepName,
|
|
35559
35840
|
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.",
|
|
35560
35841
|
promptSnippet: "Fast regex search across files (trigram-indexed inside the project root)",
|
|
35561
|
-
promptGuidelines: [
|
|
35842
|
+
promptGuidelines: [`Prefer ${grepName} over bash-invoked find/rg for in-project searches.`],
|
|
35562
35843
|
parameters: GrepParams,
|
|
35563
35844
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
35564
35845
|
const bridge = bridgeFor(ctx, extCtx.cwd);
|
|
@@ -35688,23 +35969,23 @@ function formatDiagnosticsText(diagnostics) {
|
|
|
35688
35969
|
return JSON.stringify(diagnostics, null, 2);
|
|
35689
35970
|
}
|
|
35690
35971
|
}
|
|
35691
|
-
function
|
|
35692
|
-
return last instanceof
|
|
35972
|
+
function reuseText2(last) {
|
|
35973
|
+
return last instanceof Text2 ? last : new Text2("", 0, 0);
|
|
35693
35974
|
}
|
|
35694
|
-
function
|
|
35695
|
-
return last instanceof
|
|
35975
|
+
function reuseContainer2(last) {
|
|
35976
|
+
return last instanceof Container2 ? last : new Container2;
|
|
35696
35977
|
}
|
|
35697
35978
|
function renderMutationCall(toolName, filePath, theme, context) {
|
|
35698
|
-
const text =
|
|
35699
|
-
const pathDisplay = filePath ? theme.fg("accent",
|
|
35979
|
+
const text = reuseText2(context.lastComponent);
|
|
35980
|
+
const pathDisplay = filePath ? theme.fg("accent", shortenPath3(filePath)) : theme.fg("toolOutput", "...");
|
|
35700
35981
|
text.setText(`${theme.fg("toolTitle", theme.bold(toolName))} ${pathDisplay}`);
|
|
35701
35982
|
return text;
|
|
35702
35983
|
}
|
|
35703
|
-
function renderMutationResult(result, theme, context) {
|
|
35984
|
+
function renderMutationResult(result, theme, context, options = { expanded: true }) {
|
|
35704
35985
|
if (context.isError) {
|
|
35705
35986
|
const errorText = result.content.filter((c) => c.type === "text").map((c) => c.text ?? "").join(`
|
|
35706
35987
|
`).trim();
|
|
35707
|
-
const text =
|
|
35988
|
+
const text = reuseText2(context.lastComponent);
|
|
35708
35989
|
text.setText(`
|
|
35709
35990
|
${theme.fg("error", errorText || "edit failed")}`);
|
|
35710
35991
|
return text;
|
|
@@ -35714,27 +35995,46 @@ ${theme.fg("error", errorText || "edit failed")}`);
|
|
|
35714
35995
|
if (!diff) {
|
|
35715
35996
|
const additions = details?.additions ?? 0;
|
|
35716
35997
|
const deletions = details?.deletions ?? 0;
|
|
35717
|
-
const text = reuseText(context.lastComponent);
|
|
35718
35998
|
const countDetail = typeof details?.editsApplied === "number" && details.editsApplied > 1 ? `, ${details.editsApplied} edits` : typeof details?.replacements === "number" && details.replacements > 1 ? `, ${details.replacements} replacements` : "";
|
|
35719
|
-
const
|
|
35999
|
+
const summary2 = theme.fg("success", `+${additions}/-${deletions}${countDetail}`);
|
|
35720
36000
|
let suffix = "";
|
|
35721
36001
|
if (details?.truncated) {
|
|
35722
36002
|
suffix = ` ${theme.fg("muted", "(diff truncated)")}`;
|
|
35723
36003
|
} else if (details?.noOp) {
|
|
35724
36004
|
suffix = ` ${theme.fg("muted", "(no net change)")}`;
|
|
35725
36005
|
}
|
|
35726
|
-
|
|
35727
|
-
|
|
35728
|
-
|
|
36006
|
+
const full = reuseText2(context.lastComponent);
|
|
36007
|
+
full.setText(`
|
|
36008
|
+
${summary2}${suffix}`);
|
|
36009
|
+
return collapsibleResult({
|
|
36010
|
+
summary: `${summary2}${suffix}`,
|
|
36011
|
+
full,
|
|
36012
|
+
expanded: options.expanded,
|
|
36013
|
+
context
|
|
36014
|
+
});
|
|
35729
36015
|
}
|
|
35730
|
-
const container =
|
|
36016
|
+
const container = reuseContainer2(context.lastComponent);
|
|
35731
36017
|
container.clear();
|
|
35732
|
-
container.addChild(new
|
|
35733
|
-
|
|
35734
|
-
|
|
36018
|
+
container.addChild(new Spacer2(1));
|
|
36019
|
+
let renderedDiff;
|
|
36020
|
+
try {
|
|
36021
|
+
renderedDiff = renderDiff2(diff);
|
|
36022
|
+
} catch {
|
|
36023
|
+
renderedDiff = diff;
|
|
36024
|
+
}
|
|
36025
|
+
container.addChild(new Text2(normalizeTerminalText(renderedDiff), 1, 0));
|
|
36026
|
+
const rawPath = context.args && typeof context.args === "object" && typeof context.args.path === "string" ? context.args.path : undefined;
|
|
36027
|
+
const summaryPath = rawPath ? ` ${shortenPath3(rawPath)}` : "";
|
|
36028
|
+
const summary = `edited${summaryPath} (+${details?.additions ?? 0}/-${details?.deletions ?? 0})`;
|
|
36029
|
+
return collapsibleResult({
|
|
36030
|
+
summary,
|
|
36031
|
+
full: container,
|
|
36032
|
+
expanded: options.expanded,
|
|
36033
|
+
context
|
|
36034
|
+
});
|
|
35735
36035
|
}
|
|
35736
|
-
function
|
|
35737
|
-
const home =
|
|
36036
|
+
function shortenPath3(path2) {
|
|
36037
|
+
const home = homedir14();
|
|
35738
36038
|
if (path2.startsWith(home))
|
|
35739
36039
|
return `~${path2.slice(home.length)}`;
|
|
35740
36040
|
return path2;
|
|
@@ -35750,174 +36050,6 @@ async function resolvePathArg(cwd, path2) {
|
|
|
35750
36050
|
}
|
|
35751
36051
|
}
|
|
35752
36052
|
|
|
35753
|
-
// src/tools/render-helpers.ts
|
|
35754
|
-
import { homedir as homedir13 } from "node:os";
|
|
35755
|
-
import { renderDiff as renderDiff2 } from "@earendil-works/pi-coding-agent";
|
|
35756
|
-
import { Container as Container2, Spacer as Spacer2, Text as Text2 } from "@earendil-works/pi-tui";
|
|
35757
|
-
function reuseText2(last) {
|
|
35758
|
-
return last instanceof Text2 ? last : new Text2("", 0, 0);
|
|
35759
|
-
}
|
|
35760
|
-
function reuseContainer2(last) {
|
|
35761
|
-
return last instanceof Container2 ? last : new Container2;
|
|
35762
|
-
}
|
|
35763
|
-
function shortenPath3(path2) {
|
|
35764
|
-
const home = homedir13();
|
|
35765
|
-
if (path2.startsWith(home))
|
|
35766
|
-
return `~${path2.slice(home.length)}`;
|
|
35767
|
-
return path2;
|
|
35768
|
-
}
|
|
35769
|
-
function renderToolCall(toolName, summary, theme, context) {
|
|
35770
|
-
const text = reuseText2(context.lastComponent);
|
|
35771
|
-
const suffix = summary ? ` ${summary}` : "";
|
|
35772
|
-
text.setText(`${theme.fg("toolTitle", theme.bold(toolName))}${suffix}`);
|
|
35773
|
-
return text;
|
|
35774
|
-
}
|
|
35775
|
-
function accentPath(theme, path2) {
|
|
35776
|
-
if (!path2)
|
|
35777
|
-
return theme.fg("toolOutput", "...");
|
|
35778
|
-
return theme.fg("accent", shortenPath3(path2));
|
|
35779
|
-
}
|
|
35780
|
-
function collectTextContent(result) {
|
|
35781
|
-
return result.content.filter((part) => part.type === "text").map((part) => part.text ?? "").join(`
|
|
35782
|
-
`).trim();
|
|
35783
|
-
}
|
|
35784
|
-
function extractStructuredPayload(result) {
|
|
35785
|
-
if (result.details !== undefined)
|
|
35786
|
-
return result.details;
|
|
35787
|
-
const text = collectTextContent(result);
|
|
35788
|
-
if (!text)
|
|
35789
|
-
return;
|
|
35790
|
-
try {
|
|
35791
|
-
return JSON.parse(text);
|
|
35792
|
-
} catch {
|
|
35793
|
-
return;
|
|
35794
|
-
}
|
|
35795
|
-
}
|
|
35796
|
-
function renderErrorResult(result, fallback, theme, context) {
|
|
35797
|
-
const text = reuseText2(context.lastComponent);
|
|
35798
|
-
const message = collectTextContent(result) || fallback;
|
|
35799
|
-
text.setText(`
|
|
35800
|
-
${theme.fg("error", message)}`);
|
|
35801
|
-
return text;
|
|
35802
|
-
}
|
|
35803
|
-
function renderSections(sections, context) {
|
|
35804
|
-
const container = reuseContainer2(context.lastComponent);
|
|
35805
|
-
container.clear();
|
|
35806
|
-
const visibleSections = sections.filter((section) => section.trim().length > 0);
|
|
35807
|
-
if (visibleSections.length === 0)
|
|
35808
|
-
return container;
|
|
35809
|
-
container.addChild(new Spacer2(1));
|
|
35810
|
-
visibleSections.forEach((section, index) => {
|
|
35811
|
-
if (index > 0)
|
|
35812
|
-
container.addChild(new Spacer2(1));
|
|
35813
|
-
container.addChild(new Text2(section, 0, 0));
|
|
35814
|
-
});
|
|
35815
|
-
return container;
|
|
35816
|
-
}
|
|
35817
|
-
function asRecord3(value) {
|
|
35818
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
35819
|
-
return;
|
|
35820
|
-
return value;
|
|
35821
|
-
}
|
|
35822
|
-
function asRecords2(value) {
|
|
35823
|
-
return Array.isArray(value) ? value.map(asRecord3).filter(Boolean) : [];
|
|
35824
|
-
}
|
|
35825
|
-
function asString2(value) {
|
|
35826
|
-
return typeof value === "string" ? value : undefined;
|
|
35827
|
-
}
|
|
35828
|
-
function asNumber2(value) {
|
|
35829
|
-
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
35830
|
-
}
|
|
35831
|
-
function formatValue(value) {
|
|
35832
|
-
if (Array.isArray(value))
|
|
35833
|
-
return value.map(formatValue).join(", ");
|
|
35834
|
-
if (typeof value === "string")
|
|
35835
|
-
return value;
|
|
35836
|
-
if (typeof value === "number" || typeof value === "boolean")
|
|
35837
|
-
return String(value);
|
|
35838
|
-
if (value === null || value === undefined)
|
|
35839
|
-
return "—";
|
|
35840
|
-
try {
|
|
35841
|
-
return JSON.stringify(value);
|
|
35842
|
-
} catch {
|
|
35843
|
-
return String(value);
|
|
35844
|
-
}
|
|
35845
|
-
}
|
|
35846
|
-
function groupByFile(items, getFile) {
|
|
35847
|
-
const groups = new Map;
|
|
35848
|
-
items.forEach((item) => {
|
|
35849
|
-
const file2 = getFile(item) ?? "(unknown file)";
|
|
35850
|
-
const current = groups.get(file2) ?? [];
|
|
35851
|
-
current.push(item);
|
|
35852
|
-
groups.set(file2, current);
|
|
35853
|
-
});
|
|
35854
|
-
return groups;
|
|
35855
|
-
}
|
|
35856
|
-
function formatTimestamp(value) {
|
|
35857
|
-
if (typeof value === "string" && value.length > 0)
|
|
35858
|
-
return value;
|
|
35859
|
-
if (typeof value !== "number" || !Number.isFinite(value))
|
|
35860
|
-
return;
|
|
35861
|
-
const millis = value > 1000000000000 ? value : value * 1000;
|
|
35862
|
-
const date5 = new Date(millis);
|
|
35863
|
-
if (Number.isNaN(date5.getTime()))
|
|
35864
|
-
return String(value);
|
|
35865
|
-
return date5.toISOString().replace("T", " ").replace(".000Z", "Z");
|
|
35866
|
-
}
|
|
35867
|
-
function formatUnifiedDiffForPi(unifiedDiff) {
|
|
35868
|
-
if (!unifiedDiff.trim())
|
|
35869
|
-
return "";
|
|
35870
|
-
const entries = [];
|
|
35871
|
-
const hunkHeader = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
|
|
35872
|
-
let oldLine = 1;
|
|
35873
|
-
let newLine = 1;
|
|
35874
|
-
for (const line of unifiedDiff.split(`
|
|
35875
|
-
`)) {
|
|
35876
|
-
if (!line)
|
|
35877
|
-
continue;
|
|
35878
|
-
if (line.startsWith("--- ") || line.startsWith("+++ "))
|
|
35879
|
-
continue;
|
|
35880
|
-
if (line.startsWith("\"))
|
|
35881
|
-
continue;
|
|
35882
|
-
const headerMatch = line.match(hunkHeader);
|
|
35883
|
-
if (headerMatch) {
|
|
35884
|
-
oldLine = Number(headerMatch[1]);
|
|
35885
|
-
newLine = Number(headerMatch[2]);
|
|
35886
|
-
continue;
|
|
35887
|
-
}
|
|
35888
|
-
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
35889
|
-
entries.push({ prefix: "+", line: newLine, text: line.slice(1) });
|
|
35890
|
-
newLine += 1;
|
|
35891
|
-
continue;
|
|
35892
|
-
}
|
|
35893
|
-
if (line.startsWith("-") && !line.startsWith("---")) {
|
|
35894
|
-
entries.push({ prefix: "-", line: oldLine, text: line.slice(1) });
|
|
35895
|
-
oldLine += 1;
|
|
35896
|
-
continue;
|
|
35897
|
-
}
|
|
35898
|
-
if (line.startsWith(" ")) {
|
|
35899
|
-
entries.push({ prefix: " ", line: oldLine, text: line.slice(1) });
|
|
35900
|
-
oldLine += 1;
|
|
35901
|
-
newLine += 1;
|
|
35902
|
-
}
|
|
35903
|
-
}
|
|
35904
|
-
if (entries.length === 0)
|
|
35905
|
-
return "";
|
|
35906
|
-
const width = String(entries.reduce((max, entry) => Math.max(max, entry.line), 1)).length;
|
|
35907
|
-
return entries.map((entry) => `${entry.prefix}${String(entry.line).padStart(width, " ")} ${entry.text}`).join(`
|
|
35908
|
-
`);
|
|
35909
|
-
}
|
|
35910
|
-
function renderUnifiedDiff(unifiedDiff) {
|
|
35911
|
-
const piDiff = formatUnifiedDiffForPi(unifiedDiff);
|
|
35912
|
-
if (!piDiff)
|
|
35913
|
-
return "";
|
|
35914
|
-
try {
|
|
35915
|
-
return renderDiff2(piDiff);
|
|
35916
|
-
} catch {
|
|
35917
|
-
return piDiff;
|
|
35918
|
-
}
|
|
35919
|
-
}
|
|
35920
|
-
|
|
35921
36053
|
// src/tools/ast.ts
|
|
35922
36054
|
var AstLang = StringEnum(["typescript", "tsx", "javascript", "python", "rust", "go", "pascal", "r", "objc"], {
|
|
35923
36055
|
description: "Target language"
|
|
@@ -35995,7 +36127,7 @@ function buildAstSearchSections(payload, theme) {
|
|
|
35995
36127
|
const grouped = groupByFile(matches, (match) => asString2(match.file));
|
|
35996
36128
|
const sections = [header];
|
|
35997
36129
|
for (const [file2, fileMatches] of grouped.entries()) {
|
|
35998
|
-
const lines = [theme.fg("accent",
|
|
36130
|
+
const lines = [theme.fg("accent", shortenPath2(file2))];
|
|
35999
36131
|
fileMatches.forEach((match, index) => {
|
|
36000
36132
|
const line = asNumber2(match.line) ?? 0;
|
|
36001
36133
|
const column = asNumber2(match.column) ?? 0;
|
|
@@ -36042,7 +36174,7 @@ function buildAstReplaceSections(payload, theme) {
|
|
|
36042
36174
|
return sections;
|
|
36043
36175
|
}
|
|
36044
36176
|
files.forEach((fileResult) => {
|
|
36045
|
-
const file2 =
|
|
36177
|
+
const file2 = shortenPath2(asString2(fileResult.file) ?? "(unknown file)");
|
|
36046
36178
|
const replacements = asNumber2(fileResult.replacements) ?? 0;
|
|
36047
36179
|
const error53 = asString2(fileResult.error);
|
|
36048
36180
|
const diff = asString2(fileResult.diff);
|
|
@@ -36068,17 +36200,27 @@ function renderAstCall(toolName, args, theme, context) {
|
|
|
36068
36200
|
const summary = toolName === "ast_grep_replace" ? `${lang} ${theme.fg("toolOutput", `${args.pattern} → ${args.rewrite}`)}` : `${lang} ${theme.fg("toolOutput", args.pattern)}`;
|
|
36069
36201
|
return renderToolCall(toolName === "ast_grep_replace" ? "ast replace" : "ast search", summary, theme, context);
|
|
36070
36202
|
}
|
|
36071
|
-
function renderAstResult(toolName, result, theme, context) {
|
|
36203
|
+
function renderAstResult(toolName, result, theme, context, options = { expanded: true }) {
|
|
36072
36204
|
if (context.isError) {
|
|
36073
36205
|
return renderErrorResult(result, `${toolName} failed`, theme, context);
|
|
36074
36206
|
}
|
|
36075
36207
|
const payload = extractStructuredPayload(result);
|
|
36076
36208
|
if (!payload) {
|
|
36077
|
-
const text = collectTextContent(result);
|
|
36078
|
-
return
|
|
36209
|
+
const text = collectTextContent(result) || theme.fg("muted", "No result.");
|
|
36210
|
+
return collapsibleResult({
|
|
36211
|
+
summary: text,
|
|
36212
|
+
full: renderSections([text], context),
|
|
36213
|
+
expanded: options.expanded,
|
|
36214
|
+
context
|
|
36215
|
+
});
|
|
36079
36216
|
}
|
|
36080
36217
|
const sections = toolName === "ast_grep_replace" ? buildAstReplaceSections(payload, theme) : buildAstSearchSections(payload, theme);
|
|
36081
|
-
return
|
|
36218
|
+
return collapsibleResult({
|
|
36219
|
+
summary: sections[0] ?? `${toolName} completed`,
|
|
36220
|
+
full: renderSections(sections, context),
|
|
36221
|
+
expanded: options.expanded,
|
|
36222
|
+
context
|
|
36223
|
+
});
|
|
36082
36224
|
}
|
|
36083
36225
|
function registerAstTools(pi, ctx, surface) {
|
|
36084
36226
|
if (surface.astSearch) {
|
|
@@ -36110,8 +36252,8 @@ function registerAstTools(pi, ctx, surface) {
|
|
|
36110
36252
|
renderCall(args, theme, context) {
|
|
36111
36253
|
return renderAstCall("ast_grep_search", args, theme, context);
|
|
36112
36254
|
},
|
|
36113
|
-
renderResult(result,
|
|
36114
|
-
return renderAstResult("ast_grep_search", result, theme, context);
|
|
36255
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
36256
|
+
return renderAstResult("ast_grep_search", result, theme, context, options);
|
|
36115
36257
|
}
|
|
36116
36258
|
});
|
|
36117
36259
|
}
|
|
@@ -36144,8 +36286,8 @@ function registerAstTools(pi, ctx, surface) {
|
|
|
36144
36286
|
renderCall(args, theme, context) {
|
|
36145
36287
|
return renderAstCall("ast_grep_replace", args, theme, context);
|
|
36146
36288
|
},
|
|
36147
|
-
renderResult(result,
|
|
36148
|
-
return renderAstResult("ast_grep_replace", result, theme, context);
|
|
36289
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
36290
|
+
return renderAstResult("ast_grep_replace", result, theme, context, options);
|
|
36149
36291
|
}
|
|
36150
36292
|
});
|
|
36151
36293
|
}
|
|
@@ -36335,16 +36477,18 @@ function getBashSpawnHook(pi) {
|
|
|
36335
36477
|
}
|
|
36336
36478
|
return api2.hooks?.bashSpawn;
|
|
36337
36479
|
}
|
|
36338
|
-
function registerBashTool(pi, ctx, aftSearchRegistered = false) {
|
|
36480
|
+
function registerBashTool(pi, ctx, aftSearchRegistered = false, registeredName = "bash", registerCompanions = true) {
|
|
36339
36481
|
const spawnHook = getBashSpawnHook(pi);
|
|
36340
|
-
const
|
|
36482
|
+
const readToolName = registeredName === "bash" ? "read" : "aft_read";
|
|
36483
|
+
const grepToolName = registeredName === "bash" ? "grep" : "aft_grep";
|
|
36484
|
+
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`;
|
|
36341
36485
|
const bashCfg = resolveBashConfig(ctx.config);
|
|
36342
36486
|
let hostFallbackActive = false;
|
|
36343
36487
|
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`." : "";
|
|
36344
36488
|
const tasksSentence = bashCfg.background ? ' Commands run in the foreground and return inline; `wait: true` blocks until a long command finishes instead of auto-promoting, but detaches to background if you send a new message — 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).";
|
|
36345
36489
|
pi.registerTool({
|
|
36346
|
-
name:
|
|
36347
|
-
label:
|
|
36490
|
+
name: registeredName,
|
|
36491
|
+
label: registeredName,
|
|
36348
36492
|
description: `Execute shell commands.${compressionSentence}${tasksSentence}
|
|
36349
36493
|
|
|
36350
36494
|
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}.`,
|
|
@@ -36470,16 +36614,20 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
36470
36614
|
renderCall(args, theme, context) {
|
|
36471
36615
|
return renderBashCall(args?.command, args?.description, theme, context);
|
|
36472
36616
|
},
|
|
36473
|
-
renderResult(result,
|
|
36474
|
-
return renderBashResult(result, theme, context);
|
|
36617
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
36618
|
+
return renderBashResult(result, theme, context, options);
|
|
36475
36619
|
}
|
|
36476
36620
|
});
|
|
36477
|
-
if (
|
|
36478
|
-
pi
|
|
36479
|
-
|
|
36480
|
-
|
|
36481
|
-
|
|
36482
|
-
|
|
36621
|
+
if (registerCompanions)
|
|
36622
|
+
registerBashCompanionTools(pi, ctx);
|
|
36623
|
+
}
|
|
36624
|
+
function registerBashCompanionTools(pi, ctx) {
|
|
36625
|
+
if (!resolveBashConfig(ctx.config).background)
|
|
36626
|
+
return;
|
|
36627
|
+
pi.registerTool(createBashStatusTool(ctx));
|
|
36628
|
+
pi.registerTool(createBashWatchTool(ctx));
|
|
36629
|
+
pi.registerTool(createBashWriteTool(ctx));
|
|
36630
|
+
pi.registerTool(createBashKillTool(ctx));
|
|
36483
36631
|
}
|
|
36484
36632
|
function withBashHints(output, command, aftSearchRegistered, projectRoot) {
|
|
36485
36633
|
return maybeAppendGrepSearchHint(maybeAppendConflictsHint(output), command, aftSearchRegistered, projectRoot);
|
|
@@ -36908,7 +37056,7 @@ function renderBashCall(command, description, theme, context) {
|
|
|
36908
37056
|
text.setText(`${theme.fg("toolTitle", theme.bold("bash"))} ${theme.fg("accent", display)}`);
|
|
36909
37057
|
return text;
|
|
36910
37058
|
}
|
|
36911
|
-
function renderBashResult(result, theme, context) {
|
|
37059
|
+
function renderBashResult(result, theme, context, options = { expanded: true }) {
|
|
36912
37060
|
if (context.isError) {
|
|
36913
37061
|
const errorText = result.content.filter((c) => c.type === "text").map((c) => c.text ?? "").join(`
|
|
36914
37062
|
`).trim();
|
|
@@ -36955,7 +37103,14 @@ ${theme.fg("error", errorText || "bash failed")}`);
|
|
|
36955
37103
|
const truncText = theme.fg("warning", "(output truncated)");
|
|
36956
37104
|
container.addChild(new Text3(truncText, 1, 0));
|
|
36957
37105
|
}
|
|
36958
|
-
|
|
37106
|
+
const firstOutputLine = rawOutput.split(/\r?\n/, 1)[0] || "(no output)";
|
|
37107
|
+
const exitSummary = exitCode === undefined ? "completed" : `exit ${exitCode}`;
|
|
37108
|
+
return collapsibleResult({
|
|
37109
|
+
summary: `${exitSummary}: ${firstOutputLine}`,
|
|
37110
|
+
full: container,
|
|
37111
|
+
expanded: options.expanded,
|
|
37112
|
+
context
|
|
37113
|
+
});
|
|
36959
37114
|
}
|
|
36960
37115
|
function shortenCommand(command) {
|
|
36961
37116
|
if (command.length <= 60)
|
|
@@ -36987,14 +37142,19 @@ function buildConflictSections(text) {
|
|
|
36987
37142
|
sections.push(...rest.map((section) => section.trim()).filter(Boolean));
|
|
36988
37143
|
return sections;
|
|
36989
37144
|
}
|
|
36990
|
-
function renderConflictResult(text, theme, context) {
|
|
37145
|
+
function renderConflictResult(text, theme, context, options = { expanded: true }) {
|
|
36991
37146
|
const sections = buildConflictSections(text).map((section, index) => index === 0 ? theme.fg("warning", section) : section);
|
|
36992
|
-
return
|
|
37147
|
+
return collapsibleResult({
|
|
37148
|
+
summary: sections[0] ?? "No merge conflicts found.",
|
|
37149
|
+
full: renderSections(sections, context),
|
|
37150
|
+
expanded: options.expanded,
|
|
37151
|
+
context
|
|
37152
|
+
});
|
|
36993
37153
|
}
|
|
36994
|
-
function renderConflictToolResult(result, theme, context) {
|
|
37154
|
+
function renderConflictToolResult(result, theme, context, options = { expanded: true }) {
|
|
36995
37155
|
if (context.isError)
|
|
36996
37156
|
return renderErrorResult(result, "conflicts failed", theme, context);
|
|
36997
|
-
return renderConflictResult(collectTextContent(result), theme, context);
|
|
37157
|
+
return renderConflictResult(collectTextContent(result), theme, context, options);
|
|
36998
37158
|
}
|
|
36999
37159
|
function registerConflictsTool(pi, ctx) {
|
|
37000
37160
|
pi.registerTool(withPathAliasPreparation({
|
|
@@ -37021,8 +37181,8 @@ function registerConflictsTool(pi, ctx) {
|
|
|
37021
37181
|
renderCall(_args, theme, context) {
|
|
37022
37182
|
return renderConflictCall(theme, context);
|
|
37023
37183
|
},
|
|
37024
|
-
renderResult(result,
|
|
37025
|
-
return renderConflictToolResult(result, theme, context);
|
|
37184
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
37185
|
+
return renderConflictToolResult(result, theme, context, options);
|
|
37026
37186
|
}
|
|
37027
37187
|
}));
|
|
37028
37188
|
}
|
|
@@ -37065,7 +37225,7 @@ function renderFsCall(toolName, args, theme, context) {
|
|
|
37065
37225
|
const moveArgs = args;
|
|
37066
37226
|
return renderToolCall("move", `${accentPath(theme, moveArgs.path)} ${theme.fg("muted", "→")} ${accentPath(theme, moveArgs.destination)}`, theme, context);
|
|
37067
37227
|
}
|
|
37068
|
-
function renderFsResult(toolName, args, result, theme, context) {
|
|
37228
|
+
function renderFsResult(toolName, args, result, theme, context, options = { expanded: true }) {
|
|
37069
37229
|
if (context.isError) {
|
|
37070
37230
|
return renderErrorResult(result, `${toolName} failed`, theme, context);
|
|
37071
37231
|
}
|
|
@@ -37076,22 +37236,33 @@ function renderFsResult(toolName, args, result, theme, context) {
|
|
|
37076
37236
|
const skipped = data.skipped_files ?? [];
|
|
37077
37237
|
const lines = [];
|
|
37078
37238
|
for (const entry of deletedPaths) {
|
|
37079
|
-
lines.push(`${theme.fg("success", "✓ deleted")} ${theme.fg("accent",
|
|
37239
|
+
lines.push(`${theme.fg("success", "✓ deleted")} ${theme.fg("accent", shortenPath2(entry))}`);
|
|
37080
37240
|
}
|
|
37081
37241
|
for (const entry of skipped) {
|
|
37082
|
-
lines.push(`${theme.fg("error", "✗ skipped")} ${theme.fg("accent",
|
|
37242
|
+
lines.push(`${theme.fg("error", "✗ skipped")} ${theme.fg("accent", shortenPath2(entry.file))} ${theme.fg("muted", `(${entry.reason})`)}`);
|
|
37083
37243
|
}
|
|
37084
37244
|
if (lines.length === 0) {
|
|
37085
37245
|
lines.push(theme.fg("muted", "(no files deleted)"));
|
|
37086
37246
|
}
|
|
37087
|
-
return
|
|
37088
|
-
|
|
37247
|
+
return collapsibleResult({
|
|
37248
|
+
summary: `${deletedPaths.length} deleted, ${skipped.length} skipped`,
|
|
37249
|
+
full: renderSections([lines.join(`
|
|
37250
|
+
`)], context),
|
|
37251
|
+
expanded: options.expanded,
|
|
37252
|
+
context
|
|
37253
|
+
});
|
|
37089
37254
|
}
|
|
37090
37255
|
const moveArgs = args;
|
|
37091
|
-
|
|
37092
|
-
`${theme.fg("success", "✓ moved")} ${theme.fg("accent",
|
|
37093
|
-
`${theme.fg("muted", "to")} ${theme.fg("accent",
|
|
37094
|
-
]
|
|
37256
|
+
const sections = [
|
|
37257
|
+
`${theme.fg("success", "✓ moved")} ${theme.fg("accent", shortenPath2(moveArgs.path ?? ""))}`,
|
|
37258
|
+
`${theme.fg("muted", "to")} ${theme.fg("accent", shortenPath2(moveArgs.destination))}`
|
|
37259
|
+
];
|
|
37260
|
+
return collapsibleResult({
|
|
37261
|
+
summary: `moved ${shortenPath2(moveArgs.path ?? "")} to ${shortenPath2(moveArgs.destination)}`,
|
|
37262
|
+
full: renderSections(sections, context),
|
|
37263
|
+
expanded: options.expanded,
|
|
37264
|
+
context
|
|
37265
|
+
});
|
|
37095
37266
|
}
|
|
37096
37267
|
function registerFsTools(pi, ctx, surface) {
|
|
37097
37268
|
const backupsDisabled = ctx.config.backup?.enabled === false;
|
|
@@ -37137,8 +37308,8 @@ function registerFsTools(pi, ctx, surface) {
|
|
|
37137
37308
|
renderCall(args, theme, context) {
|
|
37138
37309
|
return renderFsCall("aft_delete", args, theme, context);
|
|
37139
37310
|
},
|
|
37140
|
-
renderResult(result,
|
|
37141
|
-
return renderFsResult("aft_delete", context.args, result, theme, context);
|
|
37311
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
37312
|
+
return renderFsResult("aft_delete", context.args, result, theme, context, options);
|
|
37142
37313
|
}
|
|
37143
37314
|
}));
|
|
37144
37315
|
}
|
|
@@ -37170,8 +37341,8 @@ function registerFsTools(pi, ctx, surface) {
|
|
|
37170
37341
|
renderCall(args, theme, context) {
|
|
37171
37342
|
return renderFsCall("aft_move", args, theme, context);
|
|
37172
37343
|
},
|
|
37173
|
-
renderResult(result,
|
|
37174
|
-
return renderFsResult("aft_move", context.args, result, theme, context);
|
|
37344
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
37345
|
+
return renderFsResult("aft_move", context.args, result, theme, context, options);
|
|
37175
37346
|
}
|
|
37176
37347
|
}));
|
|
37177
37348
|
}
|
|
@@ -37245,11 +37416,17 @@ function renderImportCall(args, theme, context) {
|
|
|
37245
37416
|
].filter(Boolean).join(" ");
|
|
37246
37417
|
return renderToolCall("import", summary, theme, context);
|
|
37247
37418
|
}
|
|
37248
|
-
function renderImportResult(result, args, theme, context) {
|
|
37419
|
+
function renderImportResult(result, args, theme, context, options = { expanded: true }) {
|
|
37249
37420
|
if (context.isError)
|
|
37250
37421
|
return renderErrorResult(result, "import failed", theme, context);
|
|
37251
37422
|
const payload = extractStructuredPayload(result);
|
|
37252
|
-
|
|
37423
|
+
const sections = buildImportSections(args, payload, theme);
|
|
37424
|
+
return collapsibleResult({
|
|
37425
|
+
summary: sections[0] ?? `${args.op} import completed`,
|
|
37426
|
+
full: renderSections(sections, context),
|
|
37427
|
+
expanded: options.expanded,
|
|
37428
|
+
context
|
|
37429
|
+
});
|
|
37253
37430
|
}
|
|
37254
37431
|
function registerImportTools(pi, ctx) {
|
|
37255
37432
|
const organizeRecovery = ctx.config.backup?.enabled === false ? "Backup capture is disabled by user config; review broad cleanup changes before proceeding." : "Use aft_safety checkpoint/undo before broad cleanup.";
|
|
@@ -37297,8 +37474,8 @@ function registerImportTools(pi, ctx) {
|
|
|
37297
37474
|
renderCall(args, theme, context) {
|
|
37298
37475
|
return renderImportCall(args, theme, context);
|
|
37299
37476
|
},
|
|
37300
|
-
renderResult(result,
|
|
37301
|
-
return renderImportResult(result, context.args, theme, context);
|
|
37477
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
37478
|
+
return renderImportResult(result, context.args, theme, context, options);
|
|
37302
37479
|
}
|
|
37303
37480
|
}));
|
|
37304
37481
|
}
|
|
@@ -37582,14 +37759,18 @@ function renderInspectCall(args, theme, context) {
|
|
|
37582
37759
|
const summary = [sections, scope, args.topK ? `topK=${args.topK}` : undefined].filter(Boolean).join(" ");
|
|
37583
37760
|
return renderToolCall("inspect", summary ? theme.fg("toolOutput", summary) : undefined, theme, context);
|
|
37584
37761
|
}
|
|
37585
|
-
function renderInspectResult(result, theme, context) {
|
|
37762
|
+
function renderInspectResult(result, theme, context, options = { expanded: true }) {
|
|
37586
37763
|
const payload = extractStructuredPayload(result);
|
|
37587
37764
|
const terminal = parseInspectTerminal(payload);
|
|
37588
|
-
if (terminal)
|
|
37589
|
-
return renderSections([renderInspectTerminal(terminal, asString2(asRecord3(payload)?.text))], context);
|
|
37590
37765
|
if (context.isError)
|
|
37591
37766
|
return renderErrorResult(result, "inspect failed", theme, context);
|
|
37592
|
-
|
|
37767
|
+
const sections = terminal ? [renderInspectTerminal(terminal, asString2(asRecord3(payload)?.text))] : buildInspectSections(payload, theme);
|
|
37768
|
+
return collapsibleResult({
|
|
37769
|
+
summary: sections[0] ?? "inspect completed",
|
|
37770
|
+
full: renderSections(sections, context),
|
|
37771
|
+
expanded: options.expanded,
|
|
37772
|
+
context
|
|
37773
|
+
});
|
|
37593
37774
|
}
|
|
37594
37775
|
function registerInspectTool(pi, ctx) {
|
|
37595
37776
|
pi.registerTool({
|
|
@@ -37624,8 +37805,8 @@ function registerInspectTool(pi, ctx) {
|
|
|
37624
37805
|
renderCall(args, theme, context) {
|
|
37625
37806
|
return renderInspectCall(args, theme, context);
|
|
37626
37807
|
},
|
|
37627
|
-
renderResult(result,
|
|
37628
|
-
return renderInspectResult(result, theme, context);
|
|
37808
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
37809
|
+
return renderInspectResult(result, theme, context, options);
|
|
37629
37810
|
}
|
|
37630
37811
|
});
|
|
37631
37812
|
}
|
|
@@ -37676,10 +37857,16 @@ function renderNavigateCall(args, theme, context) {
|
|
|
37676
37857
|
].filter(Boolean).join(" ");
|
|
37677
37858
|
return renderToolCall("callgraph", summary, theme, context);
|
|
37678
37859
|
}
|
|
37679
|
-
function renderNavigateResult(result, args, theme, context) {
|
|
37860
|
+
function renderNavigateResult(result, args, theme, context, options = { expanded: true }) {
|
|
37680
37861
|
if (context.isError)
|
|
37681
37862
|
return renderErrorResult(result, "navigate failed", theme, context);
|
|
37682
|
-
|
|
37863
|
+
const sections = buildNavigateSections(args, extractStructuredPayload(result), theme);
|
|
37864
|
+
return collapsibleResult({
|
|
37865
|
+
summary: sections[0] ?? `${args.op} completed`,
|
|
37866
|
+
full: renderSections(sections, context),
|
|
37867
|
+
expanded: options.expanded,
|
|
37868
|
+
context
|
|
37869
|
+
});
|
|
37683
37870
|
}
|
|
37684
37871
|
function registerNavigateTool(pi, ctx) {
|
|
37685
37872
|
pi.registerTool(withPathAliasPreparation({
|
|
@@ -37747,8 +37934,8 @@ function registerNavigateTool(pi, ctx) {
|
|
|
37747
37934
|
renderCall(args, theme, context) {
|
|
37748
37935
|
return renderNavigateCall(args, theme, context);
|
|
37749
37936
|
},
|
|
37750
|
-
renderResult(result,
|
|
37751
|
-
return renderNavigateResult(result, context.args, theme, context);
|
|
37937
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
37938
|
+
return renderNavigateResult(result, context.args, theme, context, options);
|
|
37752
37939
|
}
|
|
37753
37940
|
}));
|
|
37754
37941
|
}
|
|
@@ -37825,7 +38012,7 @@ function renderZoomRecord(record2, targetLabel, theme) {
|
|
|
37825
38012
|
const range = asRecord3(record2.range);
|
|
37826
38013
|
const startLine = range && typeof range.start_line === "number" ? range.start_line : undefined;
|
|
37827
38014
|
const endLine = range && typeof range.end_line === "number" ? range.end_line : undefined;
|
|
37828
|
-
const location = startLine !== undefined ? `${
|
|
38015
|
+
const location = startLine !== undefined ? `${shortenPath2(targetLabel)}:${startLine}${endLine && endLine !== startLine ? `-${endLine}` : ""}` : shortenPath2(targetLabel);
|
|
37829
38016
|
const lines = [`${theme.fg("accent", name)} ${theme.fg("muted", `[${kind}] ${location}`)}`];
|
|
37830
38017
|
const content = asString2(record2.content);
|
|
37831
38018
|
if (content) {
|
|
@@ -37862,7 +38049,7 @@ function buildZoomSections(args, payload, theme) {
|
|
|
37862
38049
|
const name = asString2(record2.name) ?? asString2(response.name) ?? "(unknown symbol)";
|
|
37863
38050
|
const itemTargetLabel = asString2(record2.targetLabel) ?? zoomTargetLabel(args);
|
|
37864
38051
|
if (response.success === false || record2.success === false) {
|
|
37865
|
-
const location = record2.targetLabel ? ` in ${
|
|
38052
|
+
const location = record2.targetLabel ? ` in ${shortenPath2(itemTargetLabel)}` : "";
|
|
37866
38053
|
return theme.fg("error", `Symbol "${name}" not found${location}: ${asString2(response.message) ?? asString2(record2.error) ?? "zoom failed"}`);
|
|
37867
38054
|
}
|
|
37868
38055
|
if (record2.response) {
|
|
@@ -37871,7 +38058,7 @@ function buildZoomSections(args, payload, theme) {
|
|
|
37871
38058
|
const content = asString2(record2.content);
|
|
37872
38059
|
if (content) {
|
|
37873
38060
|
return [
|
|
37874
|
-
`${theme.fg("accent", name)} ${theme.fg("muted",
|
|
38061
|
+
`${theme.fg("accent", name)} ${theme.fg("muted", shortenPath2(itemTargetLabel))}`,
|
|
37875
38062
|
content
|
|
37876
38063
|
].filter(Boolean).join(`
|
|
37877
38064
|
`);
|
|
@@ -37894,10 +38081,16 @@ function renderOutlineCall(args, theme, context) {
|
|
|
37894
38081
|
const summary = Array.isArray(args.target) ? theme.fg("accent", `${args.target.length} ${args.files ? "directories" : "files"}`) : typeof args.target === "string" ? `${accentPath(theme, args.target)}${args.files ? " files" : ""}` : undefined;
|
|
37895
38082
|
return renderToolCall("outline", summary, theme, context);
|
|
37896
38083
|
}
|
|
37897
|
-
function renderOutlineResult(result, theme, context) {
|
|
38084
|
+
function renderOutlineResult(result, theme, context, options = { expanded: true }) {
|
|
37898
38085
|
if (context.isError)
|
|
37899
38086
|
return renderErrorResult(result, "outline failed", theme, context);
|
|
37900
|
-
|
|
38087
|
+
const sections = buildOutlineSections(collectTextContent(result), theme);
|
|
38088
|
+
return collapsibleResult({
|
|
38089
|
+
summary: sections[0] ?? "outline completed",
|
|
38090
|
+
full: renderSections(sections, context),
|
|
38091
|
+
expanded: options.expanded,
|
|
38092
|
+
context
|
|
38093
|
+
});
|
|
37901
38094
|
}
|
|
37902
38095
|
function renderZoomCall(args, theme, context) {
|
|
37903
38096
|
const symbols = args.symbols;
|
|
@@ -37916,10 +38109,16 @@ function renderZoomCall(args, theme, context) {
|
|
|
37916
38109
|
}
|
|
37917
38110
|
return renderToolCall("zoom", `${accentPath(theme, zoomTargetLabel(args))} ${summary}`, theme, context);
|
|
37918
38111
|
}
|
|
37919
|
-
function renderZoomResult(result, args, theme, context) {
|
|
38112
|
+
function renderZoomResult(result, args, theme, context, options = { expanded: true }) {
|
|
37920
38113
|
if (context.isError)
|
|
37921
38114
|
return renderErrorResult(result, "zoom failed", theme, context);
|
|
37922
|
-
|
|
38115
|
+
const sections = buildZoomSections(args, extractStructuredPayload(result), theme);
|
|
38116
|
+
return collapsibleResult({
|
|
38117
|
+
summary: sections[0] ?? "zoom completed",
|
|
38118
|
+
full: renderSections(sections, context),
|
|
38119
|
+
expanded: options.expanded,
|
|
38120
|
+
context
|
|
38121
|
+
});
|
|
37923
38122
|
}
|
|
37924
38123
|
function registerReadingTools(pi, ctx, surface) {
|
|
37925
38124
|
if (surface.outline) {
|
|
@@ -37981,8 +38180,8 @@ Pass a single \`target\`:
|
|
|
37981
38180
|
renderCall(args, theme, context) {
|
|
37982
38181
|
return renderOutlineCall(args, theme, context);
|
|
37983
38182
|
},
|
|
37984
|
-
renderResult(result,
|
|
37985
|
-
return renderOutlineResult(result, theme, context);
|
|
38183
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
38184
|
+
return renderOutlineResult(result, theme, context, options);
|
|
37986
38185
|
}
|
|
37987
38186
|
}));
|
|
37988
38187
|
}
|
|
@@ -38073,8 +38272,8 @@ Pass a single \`target\`:
|
|
|
38073
38272
|
renderCall(args, theme, context) {
|
|
38074
38273
|
return renderZoomCall(args, theme, context);
|
|
38075
38274
|
},
|
|
38076
|
-
renderResult(result,
|
|
38077
|
-
return renderZoomResult(result, context.args, theme, context);
|
|
38275
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
38276
|
+
return renderZoomResult(result, context.args, theme, context, options);
|
|
38078
38277
|
}
|
|
38079
38278
|
}));
|
|
38080
38279
|
}
|
|
@@ -38106,21 +38305,21 @@ function buildRefactorSections(args, payload, theme) {
|
|
|
38106
38305
|
`${theme.fg("success", "moved symbol")} ${theme.fg("toolOutput", args.symbol ?? "(symbol)")}`,
|
|
38107
38306
|
`${theme.fg("muted", "files modified")} ${asNumber2(response.files_modified) ?? results.length}`,
|
|
38108
38307
|
`${theme.fg("muted", "consumers updated")} ${asNumber2(response.consumers_updated) ?? 0}`,
|
|
38109
|
-
results.length > 0 ? results.map((entry) => ` ↳ ${
|
|
38308
|
+
results.length > 0 ? results.map((entry) => ` ↳ ${shortenPath2(asString2(entry.file) ?? "(unknown file)")}`).join(`
|
|
38110
38309
|
`) : theme.fg("muted", "No files reported.")
|
|
38111
38310
|
];
|
|
38112
38311
|
}
|
|
38113
38312
|
if (args.op === "extract") {
|
|
38114
38313
|
return [
|
|
38115
38314
|
`${theme.fg("success", "extracted")} ${theme.fg("toolOutput", asString2(response.name) ?? args.name ?? "(function)")}`,
|
|
38116
|
-
`${theme.fg("muted", "file")} ${theme.fg("accent",
|
|
38315
|
+
`${theme.fg("muted", "file")} ${theme.fg("accent", shortenPath2(asString2(response.file) ?? args.path ?? ""))}`,
|
|
38117
38316
|
`${theme.fg("muted", "params")} ${Array.isArray(response.parameters) ? response.parameters.join(", ") || "none" : "none"}`,
|
|
38118
38317
|
`${theme.fg("muted", "return type")} ${asString2(response.return_type) ?? "unknown"}`
|
|
38119
38318
|
];
|
|
38120
38319
|
}
|
|
38121
38320
|
return [
|
|
38122
38321
|
`${theme.fg("success", "inlined")} ${theme.fg("toolOutput", asString2(response.symbol) ?? args.symbol ?? "(symbol)")}`,
|
|
38123
|
-
`${theme.fg("muted", "file")} ${theme.fg("accent",
|
|
38322
|
+
`${theme.fg("muted", "file")} ${theme.fg("accent", shortenPath2(asString2(response.file) ?? args.path ?? ""))}`,
|
|
38124
38323
|
`${theme.fg("muted", "context")} ${asString2(response.call_context) ?? "unknown"}`,
|
|
38125
38324
|
`${theme.fg("muted", "substitutions")} ${asNumber2(response.substitutions) ?? 0}`
|
|
38126
38325
|
];
|
|
@@ -38133,10 +38332,16 @@ function renderRefactorCall(args, theme, context) {
|
|
|
38133
38332
|
].filter(Boolean).join(" ");
|
|
38134
38333
|
return renderToolCall("refactor", summary, theme, context);
|
|
38135
38334
|
}
|
|
38136
|
-
function renderRefactorResult(result, args, theme, context) {
|
|
38335
|
+
function renderRefactorResult(result, args, theme, context, options = { expanded: true }) {
|
|
38137
38336
|
if (context.isError)
|
|
38138
38337
|
return renderErrorResult(result, "refactor failed", theme, context);
|
|
38139
|
-
|
|
38338
|
+
const sections = buildRefactorSections(args, extractStructuredPayload(result), theme);
|
|
38339
|
+
return collapsibleResult({
|
|
38340
|
+
summary: sections[0] ?? `${args.op} completed`,
|
|
38341
|
+
full: renderSections(sections, context),
|
|
38342
|
+
expanded: options.expanded,
|
|
38343
|
+
context
|
|
38344
|
+
});
|
|
38140
38345
|
}
|
|
38141
38346
|
function registerRefactorTool(pi, ctx) {
|
|
38142
38347
|
pi.registerTool(withPathAliasPreparation({
|
|
@@ -38203,8 +38408,8 @@ function registerRefactorTool(pi, ctx) {
|
|
|
38203
38408
|
renderCall(args, theme, context) {
|
|
38204
38409
|
return renderRefactorCall(args, theme, context);
|
|
38205
38410
|
},
|
|
38206
|
-
renderResult(result,
|
|
38207
|
-
return renderRefactorResult(result, context.args, theme, context);
|
|
38411
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
38412
|
+
return renderRefactorResult(result, context.args, theme, context, options);
|
|
38208
38413
|
}
|
|
38209
38414
|
}));
|
|
38210
38415
|
}
|
|
@@ -38239,14 +38444,14 @@ function buildSafetySections(args, payload, theme) {
|
|
|
38239
38444
|
];
|
|
38240
38445
|
}
|
|
38241
38446
|
return [
|
|
38242
|
-
`${theme.fg("success", "restored")} ${theme.fg("accent",
|
|
38447
|
+
`${theme.fg("success", "restored")} ${theme.fg("accent", shortenPath2(asString2(response.path) ?? args.path ?? "(file)"))}`,
|
|
38243
38448
|
`${theme.fg("muted", "backup")} ${asString2(response.backup_id) ?? "—"}`
|
|
38244
38449
|
];
|
|
38245
38450
|
}
|
|
38246
38451
|
if (args.op === "history") {
|
|
38247
38452
|
const entries = asRecords2(response.entries);
|
|
38248
38453
|
const sections2 = [
|
|
38249
|
-
theme.fg("accent",
|
|
38454
|
+
theme.fg("accent", shortenPath2(asString2(response.file) ?? args.path ?? "(file)"))
|
|
38250
38455
|
];
|
|
38251
38456
|
if (entries.length === 0) {
|
|
38252
38457
|
sections2.push(theme.fg("muted", "No history entries."));
|
|
@@ -38268,7 +38473,7 @@ function buildSafetySections(args, payload, theme) {
|
|
|
38268
38473
|
`${theme.fg("success", "checkpoint created")} ${theme.fg("accent", asString2(response.name) ?? args.name ?? "(checkpoint)")}`,
|
|
38269
38474
|
`${theme.fg("muted", "files")} ${asNumber2(response.file_count) ?? 0}`,
|
|
38270
38475
|
skipped.length > 0 ? `${theme.fg("warning", "skipped")}
|
|
38271
|
-
${skipped.map((entry) => ` ↳ ${
|
|
38476
|
+
${skipped.map((entry) => ` ↳ ${shortenPath2(asString2(entry.file) ?? "(file)")}: ${asString2(entry.error) ?? "unknown error"}`).join(`
|
|
38272
38477
|
`)}` : theme.fg("muted", "No skipped files.")
|
|
38273
38478
|
];
|
|
38274
38479
|
}
|
|
@@ -38300,10 +38505,16 @@ function renderSafetyCall(args, theme, context) {
|
|
|
38300
38505
|
const summary = [theme.fg("accent", args.op), target ? accentPath(theme, target) : undefined].filter(Boolean).join(" ");
|
|
38301
38506
|
return renderToolCall("safety", summary, theme, context);
|
|
38302
38507
|
}
|
|
38303
|
-
function renderSafetyResult(result, args, theme, context) {
|
|
38508
|
+
function renderSafetyResult(result, args, theme, context, options = { expanded: true }) {
|
|
38304
38509
|
if (context.isError)
|
|
38305
38510
|
return renderErrorResult(result, "safety failed", theme, context);
|
|
38306
|
-
|
|
38511
|
+
const sections = buildSafetySections(args, extractStructuredPayload(result), theme);
|
|
38512
|
+
return collapsibleResult({
|
|
38513
|
+
summary: `${args.op}: ${sections[0] ?? "completed"}`,
|
|
38514
|
+
full: renderSections(sections, context),
|
|
38515
|
+
expanded: options.expanded,
|
|
38516
|
+
context
|
|
38517
|
+
});
|
|
38307
38518
|
}
|
|
38308
38519
|
function registerSafetyTool(pi, ctx) {
|
|
38309
38520
|
pi.registerTool(withPathAliasPreparation({
|
|
@@ -38372,8 +38583,8 @@ function registerSafetyTool(pi, ctx) {
|
|
|
38372
38583
|
renderCall(args, theme, context) {
|
|
38373
38584
|
return renderSafetyCall(args, theme, context);
|
|
38374
38585
|
},
|
|
38375
|
-
renderResult(result,
|
|
38376
|
-
return renderSafetyResult(result, context.args, theme, context);
|
|
38586
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
38587
|
+
return renderSafetyResult(result, context.args, theme, context, options);
|
|
38377
38588
|
}
|
|
38378
38589
|
}));
|
|
38379
38590
|
}
|
|
@@ -38440,7 +38651,7 @@ function buildSemanticSections(args, payload, theme) {
|
|
|
38440
38651
|
}
|
|
38441
38652
|
const grouped = groupByFile(results, (result) => asString2(result.file));
|
|
38442
38653
|
for (const [file2, fileResults] of grouped.entries()) {
|
|
38443
|
-
const lines = [theme.fg("accent",
|
|
38654
|
+
const lines = [theme.fg("accent", shortenPath2(file2))];
|
|
38444
38655
|
fileResults.forEach((result) => {
|
|
38445
38656
|
if (asString2(result.kind) === "GrepLine") {
|
|
38446
38657
|
const line = asNumber2(result.line);
|
|
@@ -38487,10 +38698,16 @@ function buildSemanticSections(args, payload, theme) {
|
|
|
38487
38698
|
function renderSemanticCall(args, theme, context) {
|
|
38488
38699
|
return renderToolCall("search", theme.fg("toolOutput", args.query), theme, context);
|
|
38489
38700
|
}
|
|
38490
|
-
function renderSemanticResult(result, args, theme, context) {
|
|
38701
|
+
function renderSemanticResult(result, args, theme, context, options = { expanded: true }) {
|
|
38491
38702
|
if (context.isError)
|
|
38492
38703
|
return renderErrorResult(result, "search failed", theme, context);
|
|
38493
|
-
|
|
38704
|
+
const sections = buildSemanticSections(args, extractStructuredPayload(result), theme);
|
|
38705
|
+
return collapsibleResult({
|
|
38706
|
+
summary: sections[0] ?? "search completed",
|
|
38707
|
+
full: renderSections(sections, context),
|
|
38708
|
+
expanded: options.expanded,
|
|
38709
|
+
context
|
|
38710
|
+
});
|
|
38494
38711
|
}
|
|
38495
38712
|
function registerSemanticTool(pi, ctx) {
|
|
38496
38713
|
pi.registerTool(withPathAliasPreparation({
|
|
@@ -38522,8 +38739,8 @@ function registerSemanticTool(pi, ctx) {
|
|
|
38522
38739
|
renderCall(args, theme, context) {
|
|
38523
38740
|
return renderSemanticCall(args, theme, context);
|
|
38524
38741
|
},
|
|
38525
|
-
renderResult(result,
|
|
38526
|
-
return renderSemanticResult(result, context.args, theme, context);
|
|
38742
|
+
renderResult(result, options = { expanded: false, isPartial: false }, theme, context) {
|
|
38743
|
+
return renderSemanticResult(result, context.args, theme, context, options);
|
|
38527
38744
|
}
|
|
38528
38745
|
}));
|
|
38529
38746
|
}
|
|
@@ -38533,12 +38750,15 @@ var ALL_ONLY_TOOLS = new Set(["aft_callgraph", "aft_delete", "aft_move", "aft_re
|
|
|
38533
38750
|
function resolvePiToolSurface(config2) {
|
|
38534
38751
|
const surface = config2.tool_surface ?? "recommended";
|
|
38535
38752
|
const disabled = new Set(config2.disabled_tools ?? []);
|
|
38753
|
+
const hoistBuiltinTools = config2.hoist_builtin_tools !== false;
|
|
38536
38754
|
const ok = (name) => !disabled.has(name);
|
|
38755
|
+
const builtinToolEnabled = (bareName) => ok(hoistBuiltinTools ? bareName : `aft_${bareName}`);
|
|
38537
38756
|
const allOnly = (name) => ALL_ONLY_TOOLS.has(name) && ok(name);
|
|
38538
38757
|
const restrictToProjectRoot = config2.restrict_to_project_root ?? false;
|
|
38539
38758
|
if (surface === "minimal") {
|
|
38540
38759
|
return {
|
|
38541
|
-
|
|
38760
|
+
hoistBuiltinTools,
|
|
38761
|
+
hoistBash: builtinToolEnabled("bash"),
|
|
38542
38762
|
hoistRead: false,
|
|
38543
38763
|
hoistWrite: false,
|
|
38544
38764
|
hoistEdit: false,
|
|
@@ -38560,11 +38780,12 @@ function resolvePiToolSurface(config2) {
|
|
|
38560
38780
|
};
|
|
38561
38781
|
}
|
|
38562
38782
|
const base = {
|
|
38563
|
-
|
|
38564
|
-
|
|
38565
|
-
|
|
38566
|
-
|
|
38567
|
-
|
|
38783
|
+
hoistBuiltinTools,
|
|
38784
|
+
hoistBash: builtinToolEnabled("bash"),
|
|
38785
|
+
hoistRead: builtinToolEnabled("read"),
|
|
38786
|
+
hoistWrite: builtinToolEnabled("write"),
|
|
38787
|
+
hoistEdit: builtinToolEnabled("edit"),
|
|
38788
|
+
hoistGrep: builtinToolEnabled("grep") && config2.search_index === true,
|
|
38568
38789
|
restrictToProjectRoot,
|
|
38569
38790
|
outline: ok("aft_outline"),
|
|
38570
38791
|
zoom: ok("aft_zoom"),
|
|
@@ -38593,7 +38814,8 @@ function resolvePiToolSurface(config2) {
|
|
|
38593
38814
|
}
|
|
38594
38815
|
function registerPiToolSurface(pi, ctx, surface) {
|
|
38595
38816
|
if (surface.hoistBash && resolveBashConfig(ctx.config).enabled) {
|
|
38596
|
-
registerBashTool(pi, ctx, surface.semantic);
|
|
38817
|
+
registerBashTool(pi, ctx, surface.semantic, surface.hoistBuiltinTools ? "bash" : "aft_bash", false);
|
|
38818
|
+
registerBashCompanionTools(pi, ctx);
|
|
38597
38819
|
}
|
|
38598
38820
|
registerHoistedTools(pi, ctx, surface);
|
|
38599
38821
|
if (surface.outline || surface.zoom) {
|
|
@@ -38704,6 +38926,9 @@ function buildHintsFromConfig(config2, absentTools, hoistBuiltins) {
|
|
|
38704
38926
|
});
|
|
38705
38927
|
}
|
|
38706
38928
|
function registerWorkflowHints(pi, config2, surface) {
|
|
38929
|
+
const hoistBuiltins = surface.hoistBuiltinTools;
|
|
38930
|
+
const grepName = hoistBuiltins ? "grep" : "aft_grep";
|
|
38931
|
+
const bashName = hoistBuiltins ? "bash" : "aft_bash";
|
|
38707
38932
|
const absent = new Set;
|
|
38708
38933
|
if (!surface.outline)
|
|
38709
38934
|
absent.add("aft_outline");
|
|
@@ -38716,12 +38941,12 @@ function registerWorkflowHints(pi, config2, surface) {
|
|
|
38716
38941
|
if (!surface.inspect)
|
|
38717
38942
|
absent.add("aft_inspect");
|
|
38718
38943
|
if (!surface.hoistGrep)
|
|
38719
|
-
absent.add(
|
|
38944
|
+
absent.add(grepName);
|
|
38720
38945
|
if (!surface.hoistBash) {
|
|
38721
|
-
absent.add(
|
|
38946
|
+
absent.add(bashName);
|
|
38722
38947
|
absent.add("bash_status");
|
|
38723
38948
|
}
|
|
38724
|
-
const hintsBlock = buildHintsFromConfig(config2, absent,
|
|
38949
|
+
const hintsBlock = buildHintsFromConfig(config2, absent, hoistBuiltins);
|
|
38725
38950
|
if (!hintsBlock)
|
|
38726
38951
|
return;
|
|
38727
38952
|
log2(`Workflow hints injected (${hintsBlock.length} chars)`);
|
|
@@ -38778,7 +39003,7 @@ var PLUGIN_VERSION = (() => {
|
|
|
38778
39003
|
return "0.0.0";
|
|
38779
39004
|
}
|
|
38780
39005
|
})();
|
|
38781
|
-
var ANNOUNCEMENT_VERSION = "0.
|
|
39006
|
+
var ANNOUNCEMENT_VERSION = "0.53.0";
|
|
38782
39007
|
var ANNOUNCEMENT_FEATURES = [
|
|
38783
39008
|
"Callgraph stays consistent under load: edits arriving mid-rebuild can no longer be silently lost from navigation results.",
|
|
38784
39009
|
"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).",
|
|
@@ -39129,7 +39354,7 @@ ${lines}
|
|
|
39129
39354
|
if (onnxRuntimePromise) {
|
|
39130
39355
|
await Promise.race([
|
|
39131
39356
|
onnxRuntimePromise,
|
|
39132
|
-
new Promise((
|
|
39357
|
+
new Promise((resolve10) => setTimeout(() => resolve10(null), 60000))
|
|
39133
39358
|
]);
|
|
39134
39359
|
}
|
|
39135
39360
|
const bridge = pool.getBridge(cwd);
|