@cortexkit/aft-pi 0.39.2 → 0.39.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.d.ts +21 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +543 -388
- package/dist/notifications.d.ts +5 -1
- package/dist/notifications.d.ts.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/navigate.d.ts.map +1 -1
- package/dist/workflow-hints.d.ts.map +1 -1
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -12940,6 +12940,208 @@ class BinaryBridge {
|
|
|
12940
12940
|
}
|
|
12941
12941
|
}
|
|
12942
12942
|
}
|
|
12943
|
+
// ../aft-bridge/dist/callgraph-format.js
|
|
12944
|
+
import { homedir as homedir3 } from "node:os";
|
|
12945
|
+
var PLAIN_CALLGRAPH_THEME = {
|
|
12946
|
+
fg: (_role, text) => text
|
|
12947
|
+
};
|
|
12948
|
+
function asRecord(value) {
|
|
12949
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
12950
|
+
return;
|
|
12951
|
+
return value;
|
|
12952
|
+
}
|
|
12953
|
+
function asRecords(value) {
|
|
12954
|
+
return Array.isArray(value) ? value.map(asRecord).filter(Boolean) : [];
|
|
12955
|
+
}
|
|
12956
|
+
function asString(value) {
|
|
12957
|
+
return typeof value === "string" ? value : undefined;
|
|
12958
|
+
}
|
|
12959
|
+
function asNumber(value) {
|
|
12960
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
12961
|
+
}
|
|
12962
|
+
function asBoolean(value) {
|
|
12963
|
+
return typeof value === "boolean" ? value : undefined;
|
|
12964
|
+
}
|
|
12965
|
+
function shortenPath(path2) {
|
|
12966
|
+
const home = homedir3();
|
|
12967
|
+
if (path2.startsWith(home))
|
|
12968
|
+
return `~${path2.slice(home.length)}`;
|
|
12969
|
+
return path2;
|
|
12970
|
+
}
|
|
12971
|
+
function joinNonEmpty(parts, separator = " · ") {
|
|
12972
|
+
return parts.filter((part) => Boolean(part && part.length > 0)).join(separator);
|
|
12973
|
+
}
|
|
12974
|
+
function treeLine(depth, text) {
|
|
12975
|
+
return `${" ".repeat(depth)}${depth === 0 ? "" : "↳ "}${text}`;
|
|
12976
|
+
}
|
|
12977
|
+
function renderCallTreeNode(node, depth, lines, theme) {
|
|
12978
|
+
const name = asString(node.name) ?? "(unknown)";
|
|
12979
|
+
const file = shortenPath(asString(node.file) ?? "(unknown file)");
|
|
12980
|
+
const line = asNumber(node.line);
|
|
12981
|
+
const unresolved = node.resolved === false ? ` ${theme.fg("warning", "[unresolved]")}` : "";
|
|
12982
|
+
const location = line !== undefined ? `[${file}:${line}]` : `[${file}]`;
|
|
12983
|
+
lines.push(treeLine(depth, `${name} ${location}${unresolved}`));
|
|
12984
|
+
asRecords(node.children).forEach((child) => {
|
|
12985
|
+
renderCallTreeNode(child, depth + 1, lines, theme);
|
|
12986
|
+
});
|
|
12987
|
+
}
|
|
12988
|
+
function depthWarning(response, theme, depthField = "depth_limited", truncatedField = "truncated") {
|
|
12989
|
+
const limited = asBoolean(response[depthField]);
|
|
12990
|
+
const truncated = asNumber(response[truncatedField]) ?? 0;
|
|
12991
|
+
if (!limited && truncated === 0)
|
|
12992
|
+
return "";
|
|
12993
|
+
const detail = truncated > 0 ? `, ${truncated} truncated` : "";
|
|
12994
|
+
return theme.fg("warning", `(depth limited${detail})`);
|
|
12995
|
+
}
|
|
12996
|
+
function renderTracePath(path2, index, lines) {
|
|
12997
|
+
lines.push(`Path ${index + 1}`);
|
|
12998
|
+
asRecords(path2.hops).forEach((hop, hopIndex) => {
|
|
12999
|
+
const symbol = asString(hop.symbol) ?? "(unknown)";
|
|
13000
|
+
const file = shortenPath(asString(hop.file) ?? "(unknown file)");
|
|
13001
|
+
const line = asNumber(hop.line);
|
|
13002
|
+
const entry = hop.is_entry_point === true ? " [entry]" : "";
|
|
13003
|
+
lines.push(treeLine(hopIndex + 1, `${symbol}${entry} ${line !== undefined ? `[${file}:${line}]` : `[${file}]`}`));
|
|
13004
|
+
});
|
|
13005
|
+
}
|
|
13006
|
+
function renderCallersGroupLines(group, theme) {
|
|
13007
|
+
const file = shortenPath(asString(group.file) ?? "(unknown file)");
|
|
13008
|
+
const lines = [theme.fg("accent", file)];
|
|
13009
|
+
const callers = asRecords(group.callers);
|
|
13010
|
+
const bySymbol = new Map;
|
|
13011
|
+
for (const caller of callers) {
|
|
13012
|
+
const symbol = asString(caller.symbol) ?? "(unknown)";
|
|
13013
|
+
const line = asNumber(caller.line);
|
|
13014
|
+
const bucket = bySymbol.get(symbol) ?? [];
|
|
13015
|
+
if (line !== undefined)
|
|
13016
|
+
bucket.push(line);
|
|
13017
|
+
bySymbol.set(symbol, bucket);
|
|
13018
|
+
}
|
|
13019
|
+
const symbols = [...bySymbol.keys()].sort((a, b) => a.localeCompare(b));
|
|
13020
|
+
for (const symbol of symbols) {
|
|
13021
|
+
const lineNums = (bySymbol.get(symbol) ?? []).sort((a, b) => a - b);
|
|
13022
|
+
const linePart = lineNums.length > 0 ? lineNums.map(String).join(", ") : "?";
|
|
13023
|
+
lines.push(` ↳ ${symbol}:${linePart}`);
|
|
13024
|
+
}
|
|
13025
|
+
return lines;
|
|
13026
|
+
}
|
|
13027
|
+
function formatCallgraphSections(op, response, theme = PLAIN_CALLGRAPH_THEME) {
|
|
13028
|
+
const record = asRecord(response);
|
|
13029
|
+
if (!record)
|
|
13030
|
+
return [theme.fg("muted", "No navigation result.")];
|
|
13031
|
+
if (op === "call_tree") {
|
|
13032
|
+
const lines = [];
|
|
13033
|
+
renderCallTreeNode(record, 0, lines, theme);
|
|
13034
|
+
const warning = depthWarning(record, theme);
|
|
13035
|
+
if (warning)
|
|
13036
|
+
lines.push(warning);
|
|
13037
|
+
return lines.length > 0 ? lines : [theme.fg("muted", "No call tree available.")];
|
|
13038
|
+
}
|
|
13039
|
+
if (op === "callers") {
|
|
13040
|
+
const groups = asRecords(record.callers);
|
|
13041
|
+
const warning = depthWarning(record, theme);
|
|
13042
|
+
const total = asNumber(record.total_callers) ?? 0;
|
|
13043
|
+
const sections2 = [
|
|
13044
|
+
joinNonEmpty([
|
|
13045
|
+
theme.fg("success", `${total} caller${total === 1 ? "" : "s"}`),
|
|
13046
|
+
theme.fg("muted", `${groups.length} file group${groups.length === 1 ? "" : "s"}`),
|
|
13047
|
+
warning
|
|
13048
|
+
])
|
|
13049
|
+
];
|
|
13050
|
+
groups.forEach((group) => {
|
|
13051
|
+
sections2.push(renderCallersGroupLines(group, theme).join(`
|
|
13052
|
+
`));
|
|
13053
|
+
});
|
|
13054
|
+
return sections2;
|
|
13055
|
+
}
|
|
13056
|
+
if (op === "trace_to_symbol") {
|
|
13057
|
+
const path2 = asRecords(record.path);
|
|
13058
|
+
const complete = asBoolean(record.complete);
|
|
13059
|
+
const reason = asString(record.reason);
|
|
13060
|
+
if (path2.length === 0) {
|
|
13061
|
+
const prefix = complete === false ? theme.fg("warning", "No complete path") : theme.fg("muted", "No path");
|
|
13062
|
+
return [`${prefix}${reason ? ` (${reason})` : ""}`];
|
|
13063
|
+
}
|
|
13064
|
+
const lines = [theme.fg("success", `${path2.length} hop${path2.length === 1 ? "" : "s"}`)];
|
|
13065
|
+
path2.forEach((hop, index) => {
|
|
13066
|
+
const symbol = asString(hop.symbol) ?? "(unknown)";
|
|
13067
|
+
const file = shortenPath(asString(hop.file) ?? "(unknown file)");
|
|
13068
|
+
const line = asNumber(hop.line);
|
|
13069
|
+
lines.push(treeLine(index + 1, `${symbol} ${line !== undefined ? `[${file}:${line}]` : `[${file}]`}`));
|
|
13070
|
+
});
|
|
13071
|
+
return lines;
|
|
13072
|
+
}
|
|
13073
|
+
if (op === "trace_to") {
|
|
13074
|
+
const paths = asRecords(record.paths);
|
|
13075
|
+
const warning = depthWarning(record, theme, "max_depth_reached", "truncated_paths");
|
|
13076
|
+
const totalPaths = asNumber(record.total_paths) ?? paths.length;
|
|
13077
|
+
const entryPoints = asNumber(record.entry_points_found) ?? 0;
|
|
13078
|
+
const sections2 = [
|
|
13079
|
+
joinNonEmpty([
|
|
13080
|
+
theme.fg("success", `${totalPaths} path${totalPaths === 1 ? "" : "s"}`),
|
|
13081
|
+
theme.fg("muted", `${entryPoints} entry point${entryPoints === 1 ? "" : "s"}`),
|
|
13082
|
+
warning
|
|
13083
|
+
])
|
|
13084
|
+
];
|
|
13085
|
+
if (paths.length === 0)
|
|
13086
|
+
sections2.push(theme.fg("muted", "No entry paths found."));
|
|
13087
|
+
paths.forEach((path2, index) => {
|
|
13088
|
+
const lines = [];
|
|
13089
|
+
renderTracePath(path2, index, lines);
|
|
13090
|
+
sections2.push(lines.join(`
|
|
13091
|
+
`));
|
|
13092
|
+
});
|
|
13093
|
+
return sections2;
|
|
13094
|
+
}
|
|
13095
|
+
if (op === "impact") {
|
|
13096
|
+
const callers = asRecords(record.callers);
|
|
13097
|
+
const warning = depthWarning(record, theme);
|
|
13098
|
+
const totalAffected = asNumber(record.total_affected) ?? callers.length;
|
|
13099
|
+
const affectedFiles = asNumber(record.affected_files) ?? 0;
|
|
13100
|
+
const sections2 = [
|
|
13101
|
+
joinNonEmpty([
|
|
13102
|
+
theme.fg("warning", `${totalAffected} affected call site${totalAffected === 1 ? "" : "s"}`),
|
|
13103
|
+
theme.fg("muted", `${affectedFiles} file${affectedFiles === 1 ? "" : "s"}`),
|
|
13104
|
+
warning
|
|
13105
|
+
])
|
|
13106
|
+
];
|
|
13107
|
+
if (callers.length === 0)
|
|
13108
|
+
sections2.push(theme.fg("muted", "No impacted callers found."));
|
|
13109
|
+
callers.forEach((caller) => {
|
|
13110
|
+
const file = shortenPath(asString(caller.caller_file) ?? "(unknown file)");
|
|
13111
|
+
const symbol = asString(caller.caller_symbol) ?? "(unknown)";
|
|
13112
|
+
const line = asNumber(caller.line) ?? 0;
|
|
13113
|
+
const entry = caller.is_entry_point === true ? ` ${theme.fg("warning", "[entry]")}` : "";
|
|
13114
|
+
const expression = asString(caller.call_expression);
|
|
13115
|
+
const params = Array.isArray(caller.parameters) ? caller.parameters.map(String).join(", ") : "";
|
|
13116
|
+
sections2.push([
|
|
13117
|
+
`${theme.fg("accent", file)}:${line}`,
|
|
13118
|
+
` ↳ ${symbol}${entry}`,
|
|
13119
|
+
expression ? ` ${theme.fg("muted", expression)}` : undefined,
|
|
13120
|
+
params ? ` ${theme.fg("muted", `params: ${params}`)}` : undefined
|
|
13121
|
+
].filter(Boolean).join(`
|
|
13122
|
+
`));
|
|
13123
|
+
});
|
|
13124
|
+
return sections2;
|
|
13125
|
+
}
|
|
13126
|
+
const hops = asRecords(record.hops);
|
|
13127
|
+
const sections = [
|
|
13128
|
+
joinNonEmpty([
|
|
13129
|
+
theme.fg("success", `${hops.length} hop${hops.length === 1 ? "" : "s"}`),
|
|
13130
|
+
asBoolean(record.depth_limited) ? theme.fg("warning", "(depth limited)") : undefined
|
|
13131
|
+
])
|
|
13132
|
+
];
|
|
13133
|
+
if (hops.length === 0)
|
|
13134
|
+
sections.push(theme.fg("muted", "No data-flow hops found."));
|
|
13135
|
+
hops.forEach((hop, index) => {
|
|
13136
|
+
const file = shortenPath(asString(hop.file) ?? "(unknown file)");
|
|
13137
|
+
const symbol = asString(hop.symbol) ?? "(unknown)";
|
|
13138
|
+
const variable = asString(hop.variable) ?? "(unknown)";
|
|
13139
|
+
const line = asNumber(hop.line) ?? 0;
|
|
13140
|
+
const approximate = hop.approximate === true ? ` ${theme.fg("warning", "[approx]")}` : "";
|
|
13141
|
+
sections.push(treeLine(index, `${variable} ${theme.fg("muted", `${asString(hop.flow_type) ?? "flow"}`)} ${symbol} [${file}:${line}]${approximate}`));
|
|
13142
|
+
});
|
|
13143
|
+
return sections;
|
|
13144
|
+
}
|
|
12943
13145
|
// ../aft-bridge/dist/coerce.js
|
|
12944
13146
|
function coerceStringArray(value) {
|
|
12945
13147
|
if (Array.isArray(value)) {
|
|
@@ -12990,7 +13192,7 @@ function isEmptyParam(value) {
|
|
|
12990
13192
|
import { spawnSync } from "node:child_process";
|
|
12991
13193
|
import { createHash, randomUUID } from "node:crypto";
|
|
12992
13194
|
import { chmodSync, closeSync, copyFileSync, createWriteStream, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
12993
|
-
import { homedir as
|
|
13195
|
+
import { homedir as homedir4 } from "node:os";
|
|
12994
13196
|
import { join as join3 } from "node:path";
|
|
12995
13197
|
import { Readable } from "node:stream";
|
|
12996
13198
|
import { pipeline } from "node:stream/promises";
|
|
@@ -13048,10 +13250,10 @@ function isExpectedCachedBinary(binaryPath, tag) {
|
|
|
13048
13250
|
function getCacheDir() {
|
|
13049
13251
|
if (process.platform === "win32") {
|
|
13050
13252
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
13051
|
-
const base2 = localAppData || join3(
|
|
13253
|
+
const base2 = localAppData || join3(homedir4(), "AppData", "Local");
|
|
13052
13254
|
return join3(base2, "aft", "bin");
|
|
13053
13255
|
}
|
|
13054
|
-
const base = process.env.XDG_CACHE_HOME || join3(
|
|
13256
|
+
const base = process.env.XDG_CACHE_HOME || join3(homedir4(), ".cache");
|
|
13055
13257
|
return join3(base, "aft", "bin");
|
|
13056
13258
|
}
|
|
13057
13259
|
function getBinaryName() {
|
|
@@ -13331,7 +13533,7 @@ function stripJsoncSymbols(value) {
|
|
|
13331
13533
|
// ../aft-bridge/dist/migration.js
|
|
13332
13534
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
13333
13535
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4 } from "node:fs";
|
|
13334
|
-
import { homedir as
|
|
13536
|
+
import { homedir as homedir6, tmpdir } from "node:os";
|
|
13335
13537
|
import { dirname as dirname2, join as join6 } from "node:path";
|
|
13336
13538
|
|
|
13337
13539
|
// ../aft-bridge/dist/paths.js
|
|
@@ -13388,7 +13590,7 @@ function markAnnouncementSeen(storageRoot, harness, currentVersion) {
|
|
|
13388
13590
|
import { execSync } from "node:child_process";
|
|
13389
13591
|
import { chmodSync as chmodSync2, closeSync as closeSync2, copyFileSync as copyFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, openSync as openSync2, readSync, renameSync as renameSync3, unlinkSync as unlinkSync2 } from "node:fs";
|
|
13390
13592
|
import { createRequire as createRequire2 } from "node:module";
|
|
13391
|
-
import { homedir as
|
|
13593
|
+
import { homedir as homedir5 } from "node:os";
|
|
13392
13594
|
import { join as join5 } from "node:path";
|
|
13393
13595
|
var ensureBinaryForResolver = ensureBinary;
|
|
13394
13596
|
function copyToVersionedCache(npmBinaryPath, knownVersion) {
|
|
@@ -13430,7 +13632,7 @@ function normalizeBareVersion(version) {
|
|
|
13430
13632
|
return version.startsWith("v") ? version.slice(1) : version;
|
|
13431
13633
|
}
|
|
13432
13634
|
function homeDirFromEnv(env) {
|
|
13433
|
-
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) ||
|
|
13635
|
+
return (process.platform === "win32" ? env.USERPROFILE || env.HOME : env.HOME) || homedir5();
|
|
13434
13636
|
}
|
|
13435
13637
|
function cacheDirFromEnv(env) {
|
|
13436
13638
|
if (process.platform === "win32") {
|
|
@@ -13612,8 +13814,8 @@ function dataHome() {
|
|
|
13612
13814
|
}
|
|
13613
13815
|
function homeDir() {
|
|
13614
13816
|
if (process.platform === "win32")
|
|
13615
|
-
return process.env.USERPROFILE || process.env.HOME ||
|
|
13616
|
-
return process.env.HOME ||
|
|
13817
|
+
return process.env.USERPROFILE || process.env.HOME || homedir6();
|
|
13818
|
+
return process.env.HOME || homedir6();
|
|
13617
13819
|
}
|
|
13618
13820
|
function resolveLegacyStorageRoot(harness) {
|
|
13619
13821
|
if (harness === "pi")
|
|
@@ -13703,13 +13905,13 @@ async function ensureStorageMigrated(opts) {
|
|
|
13703
13905
|
}
|
|
13704
13906
|
// ../aft-bridge/dist/npm-resolver.js
|
|
13705
13907
|
import { readdirSync, statSync as statSync2 } from "node:fs";
|
|
13706
|
-
import { homedir as
|
|
13908
|
+
import { homedir as homedir7 } from "node:os";
|
|
13707
13909
|
import { delimiter, dirname as dirname3, isAbsolute as isAbsolute2, join as join7 } from "node:path";
|
|
13708
13910
|
function defaultDeps() {
|
|
13709
13911
|
return {
|
|
13710
13912
|
platform: process.platform,
|
|
13711
13913
|
env: process.env,
|
|
13712
|
-
home:
|
|
13914
|
+
home: homedir7(),
|
|
13713
13915
|
execPath: process.execPath
|
|
13714
13916
|
};
|
|
13715
13917
|
}
|
|
@@ -15044,13 +15246,13 @@ function tokenizeStage(stage) {
|
|
|
15044
15246
|
}
|
|
15045
15247
|
// ../aft-bridge/dist/pool.js
|
|
15046
15248
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
15047
|
-
import { homedir as
|
|
15249
|
+
import { homedir as homedir8 } from "node:os";
|
|
15048
15250
|
var DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1000;
|
|
15049
15251
|
var DEFAULT_MAX_POOL_SIZE = 8;
|
|
15050
15252
|
var CLEANUP_INTERVAL_MS = 60 * 1000;
|
|
15051
15253
|
function canonicalHomeDir() {
|
|
15052
15254
|
try {
|
|
15053
|
-
const home =
|
|
15255
|
+
const home = homedir8();
|
|
15054
15256
|
if (!home)
|
|
15055
15257
|
return null;
|
|
15056
15258
|
try {
|
|
@@ -16073,7 +16275,7 @@ import {
|
|
|
16073
16275
|
// package.json
|
|
16074
16276
|
var package_default = {
|
|
16075
16277
|
name: "@cortexkit/aft-pi",
|
|
16076
|
-
version: "0.39.
|
|
16278
|
+
version: "0.39.3",
|
|
16077
16279
|
type: "module",
|
|
16078
16280
|
description: "Pi coding agent extension for Agent File Tools (AFT) — tree-sitter and LSP-powered code analysis",
|
|
16079
16281
|
main: "dist/index.js",
|
|
@@ -16096,7 +16298,7 @@ var package_default = {
|
|
|
16096
16298
|
"test:unit": "bun test src/__tests__ --path-ignore-patterns 'src/__tests__/e2e/**'"
|
|
16097
16299
|
},
|
|
16098
16300
|
dependencies: {
|
|
16099
|
-
"@cortexkit/aft-bridge": "0.39.
|
|
16301
|
+
"@cortexkit/aft-bridge": "0.39.3",
|
|
16100
16302
|
"@xterm/headless": "^5.5.0",
|
|
16101
16303
|
"comment-json": "^5.0.0",
|
|
16102
16304
|
diff: "^8.0.4",
|
|
@@ -16104,12 +16306,12 @@ var package_default = {
|
|
|
16104
16306
|
zod: "^4.1.8"
|
|
16105
16307
|
},
|
|
16106
16308
|
optionalDependencies: {
|
|
16107
|
-
"@cortexkit/aft-darwin-arm64": "0.39.
|
|
16108
|
-
"@cortexkit/aft-darwin-x64": "0.39.
|
|
16109
|
-
"@cortexkit/aft-linux-arm64": "0.39.
|
|
16110
|
-
"@cortexkit/aft-linux-x64": "0.39.
|
|
16111
|
-
"@cortexkit/aft-win32-arm64": "0.39.
|
|
16112
|
-
"@cortexkit/aft-win32-x64": "0.39.
|
|
16309
|
+
"@cortexkit/aft-darwin-arm64": "0.39.3",
|
|
16310
|
+
"@cortexkit/aft-darwin-x64": "0.39.3",
|
|
16311
|
+
"@cortexkit/aft-linux-arm64": "0.39.3",
|
|
16312
|
+
"@cortexkit/aft-linux-x64": "0.39.3",
|
|
16313
|
+
"@cortexkit/aft-win32-arm64": "0.39.3",
|
|
16314
|
+
"@cortexkit/aft-win32-x64": "0.39.3"
|
|
16113
16315
|
},
|
|
16114
16316
|
devDependencies: {
|
|
16115
16317
|
"@earendil-works/pi-coding-agent": "*",
|
|
@@ -16136,7 +16338,7 @@ var package_default = {
|
|
|
16136
16338
|
};
|
|
16137
16339
|
|
|
16138
16340
|
// src/shared/status.ts
|
|
16139
|
-
function
|
|
16341
|
+
function asRecord2(value) {
|
|
16140
16342
|
return typeof value === "object" && value !== null ? value : {};
|
|
16141
16343
|
}
|
|
16142
16344
|
function readString(value, fallback = "") {
|
|
@@ -16155,7 +16357,7 @@ function readOptionalNumber(value) {
|
|
|
16155
16357
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
16156
16358
|
}
|
|
16157
16359
|
function readCompressionAggregate(value) {
|
|
16158
|
-
const aggregate =
|
|
16360
|
+
const aggregate = asRecord2(value);
|
|
16159
16361
|
return {
|
|
16160
16362
|
events: readNumber(aggregate.events),
|
|
16161
16363
|
original_tokens: readNumber(aggregate.original_tokens),
|
|
@@ -16166,7 +16368,7 @@ function readCompressionAggregate(value) {
|
|
|
16166
16368
|
function readCompression(value) {
|
|
16167
16369
|
if (typeof value !== "object" || value === null)
|
|
16168
16370
|
return;
|
|
16169
|
-
const compression =
|
|
16371
|
+
const compression = asRecord2(value);
|
|
16170
16372
|
return {
|
|
16171
16373
|
project: readCompressionAggregate(compression.project),
|
|
16172
16374
|
session: readCompressionAggregate(compression.session)
|
|
@@ -16175,7 +16377,7 @@ function readCompression(value) {
|
|
|
16175
16377
|
function readStatusBar(value) {
|
|
16176
16378
|
if (typeof value !== "object" || value === null)
|
|
16177
16379
|
return;
|
|
16178
|
-
const bar =
|
|
16380
|
+
const bar = asRecord2(value);
|
|
16179
16381
|
return {
|
|
16180
16382
|
errors: readNumber(bar.errors),
|
|
16181
16383
|
warnings: readNumber(bar.warnings),
|
|
@@ -16219,16 +16421,16 @@ function formatBytes(bytes) {
|
|
|
16219
16421
|
return `${value.toFixed(decimals)} ${units[unitIndex]}`;
|
|
16220
16422
|
}
|
|
16221
16423
|
function coerceAftStatus(response) {
|
|
16222
|
-
const features =
|
|
16223
|
-
const searchIndex =
|
|
16224
|
-
const semanticIndex =
|
|
16424
|
+
const features = asRecord2(response.features);
|
|
16425
|
+
const searchIndex = asRecord2(response.search_index);
|
|
16426
|
+
const semanticIndex = asRecord2(response.semantic_index);
|
|
16225
16427
|
const semanticConfig = {
|
|
16226
|
-
...
|
|
16227
|
-
...
|
|
16428
|
+
...asRecord2(response.semantic),
|
|
16429
|
+
...asRecord2(response.semantic_config)
|
|
16228
16430
|
};
|
|
16229
|
-
const disk =
|
|
16230
|
-
const symbolCache =
|
|
16231
|
-
const session =
|
|
16431
|
+
const disk = asRecord2(response.disk);
|
|
16432
|
+
const symbolCache = asRecord2(response.symbol_cache);
|
|
16433
|
+
const session = asRecord2(response.session);
|
|
16232
16434
|
return {
|
|
16233
16435
|
version: readString(response.version, "unknown"),
|
|
16234
16436
|
project_root: readNullableString(response.project_root),
|
|
@@ -16684,7 +16886,7 @@ function registerStatusCommand(pi, ctx) {
|
|
|
16684
16886
|
|
|
16685
16887
|
// src/config.ts
|
|
16686
16888
|
import { existsSync as existsSync6, readFileSync as readFileSync4, renameSync as renameSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
16687
|
-
import { homedir as
|
|
16889
|
+
import { homedir as homedir9 } from "node:os";
|
|
16688
16890
|
import { join as join10 } from "node:path";
|
|
16689
16891
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
16690
16892
|
|
|
@@ -30381,6 +30583,8 @@ var AftConfigSchema = exports_external.object({
|
|
|
30381
30583
|
restrict_to_project_root: exports_external.boolean().optional(),
|
|
30382
30584
|
search_index: exports_external.boolean().optional(),
|
|
30383
30585
|
semantic_search: exports_external.boolean().optional(),
|
|
30586
|
+
callgraph_store: exports_external.boolean().optional(),
|
|
30587
|
+
callgraph_chunk_size: exports_external.number().optional(),
|
|
30384
30588
|
inspect: InspectConfigSchema.optional(),
|
|
30385
30589
|
bash: BashConfigSchema.optional(),
|
|
30386
30590
|
experimental: ExperimentalConfigSchema.optional(),
|
|
@@ -30441,6 +30645,37 @@ function resolveLspConfigForConfigure(config2) {
|
|
|
30441
30645
|
}
|
|
30442
30646
|
return overrides;
|
|
30443
30647
|
}
|
|
30648
|
+
function resolveProjectOverridesForConfigure(config2) {
|
|
30649
|
+
const overrides = {};
|
|
30650
|
+
if (config2.format_on_edit !== undefined)
|
|
30651
|
+
overrides.format_on_edit = config2.format_on_edit;
|
|
30652
|
+
if (config2.formatter_timeout_secs !== undefined)
|
|
30653
|
+
overrides.formatter_timeout_secs = config2.formatter_timeout_secs;
|
|
30654
|
+
if (config2.validate_on_edit !== undefined)
|
|
30655
|
+
overrides.validate_on_edit = config2.validate_on_edit;
|
|
30656
|
+
if (config2.formatter !== undefined)
|
|
30657
|
+
overrides.formatter = config2.formatter;
|
|
30658
|
+
if (config2.checker !== undefined)
|
|
30659
|
+
overrides.checker = config2.checker;
|
|
30660
|
+
overrides.restrict_to_project_root = config2.restrict_to_project_root ?? false;
|
|
30661
|
+
if (config2.search_index !== undefined)
|
|
30662
|
+
overrides.search_index = config2.search_index;
|
|
30663
|
+
if (config2.semantic_search !== undefined)
|
|
30664
|
+
overrides.semantic_search = config2.semantic_search;
|
|
30665
|
+
if (config2.callgraph_store !== undefined)
|
|
30666
|
+
overrides.callgraph_store = config2.callgraph_store;
|
|
30667
|
+
if (config2.callgraph_chunk_size !== undefined)
|
|
30668
|
+
overrides.callgraph_chunk_size = config2.callgraph_chunk_size;
|
|
30669
|
+
Object.assign(overrides, resolveExperimentalConfigForConfigure(config2));
|
|
30670
|
+
Object.assign(overrides, resolveLspConfigForConfigure(config2));
|
|
30671
|
+
if (config2.semantic !== undefined)
|
|
30672
|
+
overrides.semantic = config2.semantic;
|
|
30673
|
+
if (config2.inspect !== undefined)
|
|
30674
|
+
overrides.inspect = config2.inspect;
|
|
30675
|
+
if (config2.max_callgraph_files !== undefined)
|
|
30676
|
+
overrides.max_callgraph_files = config2.max_callgraph_files;
|
|
30677
|
+
return overrides;
|
|
30678
|
+
}
|
|
30444
30679
|
function resolveExperimentalConfigForConfigure(config2) {
|
|
30445
30680
|
const overrides = {};
|
|
30446
30681
|
const bash = resolveBashConfig(config2);
|
|
@@ -30617,6 +30852,17 @@ function detectConfigFile(basePath) {
|
|
|
30617
30852
|
return { format: "json", path: jsonPath };
|
|
30618
30853
|
return { format: "none", path: jsonPath };
|
|
30619
30854
|
}
|
|
30855
|
+
var configLoadErrors = [];
|
|
30856
|
+
function getConfigLoadErrors() {
|
|
30857
|
+
return configLoadErrors;
|
|
30858
|
+
}
|
|
30859
|
+
function formatConfigParseFailureMessage(configPath, errorMessage) {
|
|
30860
|
+
return `AFT config at ${configPath} failed to parse and was ignored (running on defaults): ${errorMessage}. ` + "Fix the syntax or run `npx @cortexkit/aft doctor`.";
|
|
30861
|
+
}
|
|
30862
|
+
function recordConfigParseFailure(configPath, errorMessage) {
|
|
30863
|
+
configLoadErrors.push({ path: configPath, message: errorMessage });
|
|
30864
|
+
warn2(formatConfigParseFailureMessage(configPath, errorMessage));
|
|
30865
|
+
}
|
|
30620
30866
|
function loadConfigFromPath(configPath) {
|
|
30621
30867
|
try {
|
|
30622
30868
|
if (!existsSync6(configPath))
|
|
@@ -30624,7 +30870,7 @@ function loadConfigFromPath(configPath) {
|
|
|
30624
30870
|
const content = readFileSync4(configPath, "utf-8");
|
|
30625
30871
|
const rawConfig = import_comment_json.parse(content);
|
|
30626
30872
|
if (!rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
|
|
30627
|
-
|
|
30873
|
+
recordConfigParseFailure(configPath, "root must be an object");
|
|
30628
30874
|
return null;
|
|
30629
30875
|
}
|
|
30630
30876
|
migrateRawConfig(rawConfig, configPath, { log: log2, warn: warn2 });
|
|
@@ -30640,6 +30886,7 @@ function loadConfigFromPath(configPath) {
|
|
|
30640
30886
|
} catch (err) {
|
|
30641
30887
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
30642
30888
|
error2(`Error loading config from ${configPath}: ${errorMsg}`);
|
|
30889
|
+
recordConfigParseFailure(configPath, errorMsg);
|
|
30643
30890
|
return null;
|
|
30644
30891
|
}
|
|
30645
30892
|
}
|
|
@@ -30775,6 +31022,8 @@ var PROJECT_SAFE_TOP_LEVEL_FIELDS = new Set([
|
|
|
30775
31022
|
"configure_warnings_delivery",
|
|
30776
31023
|
"search_index",
|
|
30777
31024
|
"semantic_search",
|
|
31025
|
+
"callgraph_store",
|
|
31026
|
+
"callgraph_chunk_size",
|
|
30778
31027
|
"inspect",
|
|
30779
31028
|
"experimental",
|
|
30780
31029
|
"bash"
|
|
@@ -30836,9 +31085,10 @@ function resolveBridgePoolTransportOptions(config2) {
|
|
|
30836
31085
|
};
|
|
30837
31086
|
}
|
|
30838
31087
|
function getGlobalPiDir() {
|
|
30839
|
-
return join10(
|
|
31088
|
+
return join10(homedir9(), ".pi", "agent");
|
|
30840
31089
|
}
|
|
30841
31090
|
function loadAftConfig(projectDirectory) {
|
|
31091
|
+
configLoadErrors = [];
|
|
30842
31092
|
const userBasePath = join10(getGlobalPiDir(), "aft");
|
|
30843
31093
|
migrateAftConfigFile(`${userBasePath}.jsonc`);
|
|
30844
31094
|
migrateAftConfigFile(`${userBasePath}.json`);
|
|
@@ -30893,7 +31143,7 @@ import {
|
|
|
30893
31143
|
unlinkSync as unlinkSync5,
|
|
30894
31144
|
writeFileSync as writeFileSync4
|
|
30895
31145
|
} from "node:fs";
|
|
30896
|
-
import { homedir as
|
|
31146
|
+
import { homedir as homedir10 } from "node:os";
|
|
30897
31147
|
import { join as join11 } from "node:path";
|
|
30898
31148
|
function aftCacheBase() {
|
|
30899
31149
|
const override = process.env.AFT_CACHE_DIR;
|
|
@@ -30901,10 +31151,10 @@ function aftCacheBase() {
|
|
|
30901
31151
|
return override;
|
|
30902
31152
|
if (process.platform === "win32") {
|
|
30903
31153
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
30904
|
-
const base2 = localAppData || join11(
|
|
31154
|
+
const base2 = localAppData || join11(homedir10(), "AppData", "Local");
|
|
30905
31155
|
return join11(base2, "aft");
|
|
30906
31156
|
}
|
|
30907
|
-
const base = process.env.XDG_CACHE_HOME || join11(
|
|
31157
|
+
const base = process.env.XDG_CACHE_HOME || join11(homedir10(), ".cache");
|
|
30908
31158
|
return join11(base, "aft");
|
|
30909
31159
|
}
|
|
30910
31160
|
function lspCacheRoot() {
|
|
@@ -32617,6 +32867,8 @@ function warningTitle(warning) {
|
|
|
32617
32867
|
return "Checker is not installed";
|
|
32618
32868
|
case "lsp_binary_missing":
|
|
32619
32869
|
return "LSP binary is missing";
|
|
32870
|
+
case "config_parse_failed":
|
|
32871
|
+
return "Config failed to parse";
|
|
32620
32872
|
}
|
|
32621
32873
|
}
|
|
32622
32874
|
function formatConfigureWarning(warning) {
|
|
@@ -32862,7 +33114,7 @@ import { Type as Type3 } from "typebox";
|
|
|
32862
33114
|
|
|
32863
33115
|
// src/tools/hoisted.ts
|
|
32864
33116
|
import { stat } from "node:fs/promises";
|
|
32865
|
-
import { homedir as
|
|
33117
|
+
import { homedir as homedir11 } from "node:os";
|
|
32866
33118
|
import { isAbsolute as isAbsolute4, relative as relative4, resolve as resolve4, sep } from "node:path";
|
|
32867
33119
|
import {
|
|
32868
33120
|
renderDiff
|
|
@@ -32984,9 +33236,9 @@ function expandTilde2(path3) {
|
|
|
32984
33236
|
if (!path3 || !path3.startsWith("~"))
|
|
32985
33237
|
return path3;
|
|
32986
33238
|
if (path3 === "~")
|
|
32987
|
-
return
|
|
33239
|
+
return homedir11();
|
|
32988
33240
|
if (path3.startsWith(`~${sep}`) || path3.startsWith("~/")) {
|
|
32989
|
-
return resolve4(
|
|
33241
|
+
return resolve4(homedir11(), path3.slice(2));
|
|
32990
33242
|
}
|
|
32991
33243
|
return path3;
|
|
32992
33244
|
}
|
|
@@ -33380,7 +33632,7 @@ function reuseContainer(last) {
|
|
|
33380
33632
|
}
|
|
33381
33633
|
function renderMutationCall(toolName, filePath, theme, context) {
|
|
33382
33634
|
const text = reuseText(context.lastComponent);
|
|
33383
|
-
const pathDisplay = filePath ? theme.fg("accent",
|
|
33635
|
+
const pathDisplay = filePath ? theme.fg("accent", shortenPath2(filePath)) : theme.fg("toolOutput", "...");
|
|
33384
33636
|
text.setText(`${theme.fg("toolTitle", theme.bold(toolName))} ${pathDisplay}`);
|
|
33385
33637
|
return text;
|
|
33386
33638
|
}
|
|
@@ -33416,8 +33668,8 @@ ${summary}${suffix}`);
|
|
|
33416
33668
|
container.addChild(new Text(renderDiff(diff), 1, 0));
|
|
33417
33669
|
return container;
|
|
33418
33670
|
}
|
|
33419
|
-
function
|
|
33420
|
-
const home =
|
|
33671
|
+
function shortenPath2(path3) {
|
|
33672
|
+
const home = homedir11();
|
|
33421
33673
|
if (path3.startsWith(home))
|
|
33422
33674
|
return `~${path3.slice(home.length)}`;
|
|
33423
33675
|
return path3;
|
|
@@ -33467,7 +33719,7 @@ function formatReadFooter2(agentSpecifiedRange, data) {
|
|
|
33467
33719
|
}
|
|
33468
33720
|
|
|
33469
33721
|
// src/tools/render-helpers.ts
|
|
33470
|
-
import { homedir as
|
|
33722
|
+
import { homedir as homedir12 } from "node:os";
|
|
33471
33723
|
import { renderDiff as renderDiff2 } from "@earendil-works/pi-coding-agent";
|
|
33472
33724
|
import { Container as Container2, Spacer as Spacer2, Text as Text2 } from "@earendil-works/pi-tui";
|
|
33473
33725
|
function reuseText2(last) {
|
|
@@ -33476,8 +33728,8 @@ function reuseText2(last) {
|
|
|
33476
33728
|
function reuseContainer2(last) {
|
|
33477
33729
|
return last instanceof Container2 ? last : new Container2;
|
|
33478
33730
|
}
|
|
33479
|
-
function
|
|
33480
|
-
const home =
|
|
33731
|
+
function shortenPath3(path3) {
|
|
33732
|
+
const home = homedir12();
|
|
33481
33733
|
if (path3.startsWith(home))
|
|
33482
33734
|
return `~${path3.slice(home.length)}`;
|
|
33483
33735
|
return path3;
|
|
@@ -33491,7 +33743,7 @@ function renderToolCall(toolName, summary, theme, context) {
|
|
|
33491
33743
|
function accentPath(theme, path3) {
|
|
33492
33744
|
if (!path3)
|
|
33493
33745
|
return theme.fg("toolOutput", "...");
|
|
33494
|
-
return theme.fg("accent",
|
|
33746
|
+
return theme.fg("accent", shortenPath3(path3));
|
|
33495
33747
|
}
|
|
33496
33748
|
function collectTextContent(result) {
|
|
33497
33749
|
return result.content.filter((part) => part.type === "text").map((part) => part.text ?? "").join(`
|
|
@@ -33530,23 +33782,20 @@ function renderSections(sections, context) {
|
|
|
33530
33782
|
});
|
|
33531
33783
|
return container;
|
|
33532
33784
|
}
|
|
33533
|
-
function
|
|
33785
|
+
function asRecord3(value) {
|
|
33534
33786
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
33535
33787
|
return;
|
|
33536
33788
|
return value;
|
|
33537
33789
|
}
|
|
33538
|
-
function
|
|
33539
|
-
return Array.isArray(value) ? value.map(
|
|
33790
|
+
function asRecords2(value) {
|
|
33791
|
+
return Array.isArray(value) ? value.map(asRecord3).filter(Boolean) : [];
|
|
33540
33792
|
}
|
|
33541
|
-
function
|
|
33793
|
+
function asString2(value) {
|
|
33542
33794
|
return typeof value === "string" ? value : undefined;
|
|
33543
33795
|
}
|
|
33544
|
-
function
|
|
33796
|
+
function asNumber2(value) {
|
|
33545
33797
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
33546
33798
|
}
|
|
33547
|
-
function asBoolean(value) {
|
|
33548
|
-
return typeof value === "boolean" ? value : undefined;
|
|
33549
|
-
}
|
|
33550
33799
|
function formatValue(value) {
|
|
33551
33800
|
if (Array.isArray(value))
|
|
33552
33801
|
return value.map(formatValue).join(", ");
|
|
@@ -33659,7 +33908,7 @@ var ReplaceParams = Type3.Object({
|
|
|
33659
33908
|
dryRun: Type3.Optional(Type3.Boolean({ description: "Preview without applying (default: false)" }))
|
|
33660
33909
|
});
|
|
33661
33910
|
function appendHintSection(response, sections, theme) {
|
|
33662
|
-
const hint =
|
|
33911
|
+
const hint = asString2(response.hint);
|
|
33663
33912
|
if (hint && hint.length > 0) {
|
|
33664
33913
|
sections.push(theme.fg("warning", hint));
|
|
33665
33914
|
}
|
|
@@ -33668,8 +33917,8 @@ function appendScopeSections(response, sections, theme) {
|
|
|
33668
33917
|
if (response.no_files_matched_scope === true) {
|
|
33669
33918
|
sections.push(theme.fg("warning", "No files matched the scope (paths/globs resolved to zero files)"));
|
|
33670
33919
|
}
|
|
33671
|
-
const warnings =
|
|
33672
|
-
const warningStrings = Array.isArray(response.scope_warnings) ? response.scope_warnings.filter((w) => typeof w === "string") : warnings.map((w) =>
|
|
33920
|
+
const warnings = asRecords2(response.scope_warnings);
|
|
33921
|
+
const warningStrings = Array.isArray(response.scope_warnings) ? response.scope_warnings.filter((w) => typeof w === "string") : warnings.map((w) => asString2(w.warning) ?? "").filter(Boolean);
|
|
33673
33922
|
if (warningStrings.length > 0) {
|
|
33674
33923
|
sections.push(`${theme.fg("muted", "Scope warnings:")}
|
|
33675
33924
|
${warningStrings.map((w) => ` ${w}`).join(`
|
|
@@ -33693,13 +33942,13 @@ async function assertAstPathsPermission(extCtx, paths, action, restrictToProject
|
|
|
33693
33942
|
}
|
|
33694
33943
|
}
|
|
33695
33944
|
function buildAstSearchSections(payload, theme) {
|
|
33696
|
-
const response =
|
|
33945
|
+
const response = asRecord3(payload);
|
|
33697
33946
|
if (!response)
|
|
33698
33947
|
return [theme.fg("muted", "No AST search results.")];
|
|
33699
|
-
const matches =
|
|
33700
|
-
const totalMatches =
|
|
33701
|
-
const filesWithMatches =
|
|
33702
|
-
const filesSearched =
|
|
33948
|
+
const matches = asRecords2(response.matches);
|
|
33949
|
+
const totalMatches = asNumber2(response.total_matches) ?? matches.length;
|
|
33950
|
+
const filesWithMatches = asNumber2(response.files_with_matches) ?? groupByFile(matches, (match) => asString2(match.file)).size;
|
|
33951
|
+
const filesSearched = asNumber2(response.files_searched);
|
|
33703
33952
|
const header = [
|
|
33704
33953
|
theme.fg("success", `${totalMatches} match${totalMatches === 1 ? "" : "es"}`),
|
|
33705
33954
|
theme.fg("accent", `${filesWithMatches} file${filesWithMatches === 1 ? "" : "s"}`),
|
|
@@ -33711,26 +33960,26 @@ function buildAstSearchSections(payload, theme) {
|
|
|
33711
33960
|
appendHintSection(response, sections2, theme);
|
|
33712
33961
|
return sections2;
|
|
33713
33962
|
}
|
|
33714
|
-
const grouped = groupByFile(matches, (match) =>
|
|
33963
|
+
const grouped = groupByFile(matches, (match) => asString2(match.file));
|
|
33715
33964
|
const sections = [header];
|
|
33716
33965
|
for (const [file2, fileMatches] of grouped.entries()) {
|
|
33717
|
-
const lines = [theme.fg("accent",
|
|
33966
|
+
const lines = [theme.fg("accent", shortenPath3(file2))];
|
|
33718
33967
|
fileMatches.forEach((match, index) => {
|
|
33719
|
-
const line =
|
|
33720
|
-
const column =
|
|
33721
|
-
const snippet =
|
|
33968
|
+
const line = asNumber2(match.line) ?? 0;
|
|
33969
|
+
const column = asNumber2(match.column) ?? 0;
|
|
33970
|
+
const snippet = asString2(match.text)?.trim() || "(empty match)";
|
|
33722
33971
|
lines.push(` ${index + 1}. ${theme.fg("muted", `${line}:${column}`)} ${snippet}`);
|
|
33723
|
-
const metaVars =
|
|
33972
|
+
const metaVars = asRecord3(match.meta_variables);
|
|
33724
33973
|
if (metaVars && Object.keys(metaVars).length > 0) {
|
|
33725
33974
|
Object.entries(metaVars).forEach(([name, value]) => {
|
|
33726
33975
|
lines.push(` ${theme.fg("muted", `${name} =`)} ${formatValue(value)}`);
|
|
33727
33976
|
});
|
|
33728
33977
|
}
|
|
33729
|
-
const context =
|
|
33978
|
+
const context = asRecords2(match.context);
|
|
33730
33979
|
context.forEach((ctxLine) => {
|
|
33731
|
-
const ctxNumber =
|
|
33980
|
+
const ctxNumber = asNumber2(ctxLine.line) ?? 0;
|
|
33732
33981
|
const prefix = ctxLine.is_match === true ? theme.fg("accent", ">") : theme.fg("muted", "|");
|
|
33733
|
-
lines.push(` ${prefix} ${ctxNumber}: ${
|
|
33982
|
+
lines.push(` ${prefix} ${ctxNumber}: ${asString2(ctxLine.text) ?? ""}`);
|
|
33734
33983
|
});
|
|
33735
33984
|
});
|
|
33736
33985
|
sections.push(lines.join(`
|
|
@@ -33739,13 +33988,13 @@ function buildAstSearchSections(payload, theme) {
|
|
|
33739
33988
|
return sections;
|
|
33740
33989
|
}
|
|
33741
33990
|
function buildAstReplaceSections(payload, theme) {
|
|
33742
|
-
const response =
|
|
33991
|
+
const response = asRecord3(payload);
|
|
33743
33992
|
if (!response)
|
|
33744
33993
|
return [theme.fg("muted", "No AST replace results.")];
|
|
33745
|
-
const files =
|
|
33746
|
-
const totalReplacements =
|
|
33747
|
-
const totalFiles =
|
|
33748
|
-
const filesWithMatches =
|
|
33994
|
+
const files = asRecords2(response.files);
|
|
33995
|
+
const totalReplacements = asNumber2(response.total_replacements) ?? 0;
|
|
33996
|
+
const totalFiles = asNumber2(response.total_files) ?? files.length;
|
|
33997
|
+
const filesWithMatches = asNumber2(response.files_with_matches);
|
|
33749
33998
|
const dryRun = response.dry_run === true;
|
|
33750
33999
|
const headerParts = [
|
|
33751
34000
|
dryRun ? theme.fg("warning", "[dry run]") : theme.fg("success", "[applied]"),
|
|
@@ -33761,10 +34010,10 @@ function buildAstReplaceSections(payload, theme) {
|
|
|
33761
34010
|
return sections;
|
|
33762
34011
|
}
|
|
33763
34012
|
files.forEach((fileResult) => {
|
|
33764
|
-
const file2 =
|
|
33765
|
-
const replacements =
|
|
33766
|
-
const error50 =
|
|
33767
|
-
const diff =
|
|
34013
|
+
const file2 = shortenPath3(asString2(fileResult.file) ?? "(unknown file)");
|
|
34014
|
+
const replacements = asNumber2(fileResult.replacements) ?? 0;
|
|
34015
|
+
const error50 = asString2(fileResult.error);
|
|
34016
|
+
const diff = asString2(fileResult.diff);
|
|
33768
34017
|
const lines = [
|
|
33769
34018
|
`${theme.fg("accent", file2)} ${theme.fg("muted", `(${replacements} replacement${replacements === 1 ? "" : "s"})`)}`
|
|
33770
34019
|
];
|
|
@@ -33774,7 +34023,7 @@ function buildAstReplaceSections(payload, theme) {
|
|
|
33774
34023
|
const rendered = renderUnifiedDiff(diff);
|
|
33775
34024
|
lines.push(rendered || theme.fg("muted", "No diff available."));
|
|
33776
34025
|
} else {
|
|
33777
|
-
const backupId =
|
|
34026
|
+
const backupId = asString2(fileResult.backup_id);
|
|
33778
34027
|
lines.push(backupId ? `${theme.fg("success", "saved")} ${theme.fg("muted", backupId)}` : theme.fg("success", "saved"));
|
|
33779
34028
|
}
|
|
33780
34029
|
sections.push(lines.join(`
|
|
@@ -33871,7 +34120,7 @@ import { Type as Type4 } from "typebox";
|
|
|
33871
34120
|
var FOREGROUND_POLL_INTERVAL_MS = 100;
|
|
33872
34121
|
var BASH_WAIT_POLL_INTERVAL_MS = 100;
|
|
33873
34122
|
var DEFAULT_BASH_STATUS_WAIT_TIMEOUT_MS = 30000;
|
|
33874
|
-
var MAX_BASH_STATUS_WAIT_TIMEOUT_MS =
|
|
34123
|
+
var MAX_BASH_STATUS_WAIT_TIMEOUT_MS = 30 * 60 * 1000;
|
|
33875
34124
|
var REGEX_WAIT_SCAN_WINDOW_BYTES = 64 * 1024;
|
|
33876
34125
|
function resolveForegroundWaitMs(configured) {
|
|
33877
34126
|
const override = process.env.AFT_TEST_FOREGROUND_WAIT_MS;
|
|
@@ -33883,7 +34132,8 @@ function resolveForegroundWaitMs(configured) {
|
|
|
33883
34132
|
return configured;
|
|
33884
34133
|
}
|
|
33885
34134
|
var BASH_TRANSPORT_TIMEOUT_MS = 30000;
|
|
33886
|
-
var
|
|
34135
|
+
var DEFAULT_HARD_TIMEOUT_MS = 30 * 60 * 1000;
|
|
34136
|
+
var BashBaseParams = {
|
|
33887
34137
|
command: Type4.String({
|
|
33888
34138
|
description: "Shell command to execute. Supports pipes, redirections, and shell syntax."
|
|
33889
34139
|
}),
|
|
@@ -33893,19 +34143,38 @@ var BashParams = Type4.Object({
|
|
|
33893
34143
|
})),
|
|
33894
34144
|
description: Type4.Optional(Type4.String({
|
|
33895
34145
|
description: "Human-readable description shown in UI logs. Helps users understand what the command does without reading shell syntax."
|
|
33896
|
-
}))
|
|
34146
|
+
}))
|
|
34147
|
+
};
|
|
34148
|
+
var BashBackgroundFlagParam = {
|
|
33897
34149
|
background: Type4.Optional(Type4.Boolean({
|
|
33898
|
-
description: "Spawn command in background and return immediately with a task_id. Use
|
|
33899
|
-
}))
|
|
34150
|
+
description: "Spawn command in background and return immediately with a task_id. Use bash_watch to wait for completion or output patterns; bash_status for a one-shot snapshot only. Use bash_kill to terminate. Ideal for long-running tasks like builds or dev servers."
|
|
34151
|
+
}))
|
|
34152
|
+
};
|
|
34153
|
+
var BashCompressionParam = {
|
|
33900
34154
|
compressed: Type4.Optional(Type4.Boolean({
|
|
33901
34155
|
description: "Compress output by removing ANSI codes, carriage returns, and excessive blank lines. Default: true. Set to false for raw terminal output including color codes."
|
|
33902
|
-
}))
|
|
34156
|
+
}))
|
|
34157
|
+
};
|
|
34158
|
+
var BashPtyParams = {
|
|
33903
34159
|
pty: Type4.Optional(Type4.Boolean({
|
|
33904
34160
|
description: 'Spawn the command in a real PTY for interactive programs. Implies background: true automatically. Inspect with bash_status({ task_id, output_mode: "screen" }) and send input with bash_write.'
|
|
33905
34161
|
})),
|
|
33906
34162
|
ptyRows: optionalInt(1, 60),
|
|
33907
34163
|
ptyCols: optionalInt(1, 140)
|
|
34164
|
+
};
|
|
34165
|
+
var BashParams = Type4.Object({
|
|
34166
|
+
...BashBaseParams,
|
|
34167
|
+
...BashBackgroundFlagParam,
|
|
34168
|
+
...BashCompressionParam,
|
|
34169
|
+
...BashPtyParams
|
|
33908
34170
|
});
|
|
34171
|
+
var BashForegroundOnlyParams = Type4.Object({
|
|
34172
|
+
...BashBaseParams,
|
|
34173
|
+
...BashCompressionParam
|
|
34174
|
+
});
|
|
34175
|
+
function bashParamsForConfig(backgroundEnabled) {
|
|
34176
|
+
return backgroundEnabled ? BashParams : BashForegroundOnlyParams;
|
|
34177
|
+
}
|
|
33909
34178
|
var BashTaskParams = Type4.Object({
|
|
33910
34179
|
task_id: Type4.String({
|
|
33911
34180
|
description: "Background bash task id returned by bash({ background: true })."
|
|
@@ -33979,28 +34248,30 @@ function registerBashTool(pi, ctx, aftSearchRegistered = false) {
|
|
|
33979
34248
|
const searchSteer = aftSearchRegistered ? "use `aft_search` (concepts, identifiers, regex, literals), `read`, `aft_outline`, or `aft_zoom` instead" : "use the `grep` tool, `read`, `aft_outline`, or `aft_zoom` instead";
|
|
33980
34249
|
const bashCfg = resolveBashConfig(ctx.config);
|
|
33981
34250
|
const compressionSentence = bashCfg.compress ? " Output is compressed by default; pass `compressed: false` for raw output." : "";
|
|
33982
|
-
const tasksSentence = bashCfg.background ? ' Pass `background: true` to run in the background and get a task_id for `bash_status`/`bash_kill`. Pass `pty: true` for interactive programs (REPLs, TUIs) and drive them with `bash_status({ output_mode: "screen" })` plus `bash_write`.' : " Commands
|
|
34251
|
+
const tasksSentence = bashCfg.background ? ' Pass `background: true` to run in the background and get a task_id for `bash_status`/`bash_watch`/`bash_kill`. Pass `pty: true` for interactive programs (REPLs, TUIs) and drive them with `bash_status({ output_mode: "screen" })` plus `bash_write`. Use `bash_watch` to wait for exit or output patterns (sync blocks, async notifies). Do not loop `bash_status` to wait.' : " Commands run in the foreground to completion; `timeout` is the hard kill cap (default 30 minutes).";
|
|
33983
34252
|
pi.registerTool({
|
|
33984
34253
|
name: "bash",
|
|
33985
34254
|
label: "bash",
|
|
33986
34255
|
description: `Execute shell commands.${compressionSentence}${tasksSentence}
|
|
33987
34256
|
|
|
33988
34257
|
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}.`,
|
|
33989
|
-
promptSnippet: "Run shell commands (timeout in milliseconds; supports workdir, background tasks, compressed output, PTY mode)",
|
|
34258
|
+
promptSnippet: bashCfg.background ? "Run shell commands (timeout in milliseconds; supports workdir, background tasks, compressed output, PTY mode)" : "Run shell commands (timeout in milliseconds; supports workdir and compressed output)",
|
|
33990
34259
|
promptGuidelines: [
|
|
33991
34260
|
`DO NOT use bash for code search or exploration — ${searchSteer}.`,
|
|
33992
34261
|
"Set compressed: false when you need ANSI color codes in the output."
|
|
33993
34262
|
],
|
|
33994
|
-
parameters:
|
|
34263
|
+
parameters: bashParamsForConfig(bashCfg.background),
|
|
33995
34264
|
async execute(_toolCallId, params, _signal, onUpdate, extCtx) {
|
|
33996
34265
|
const bridge = bridgeFor(ctx, extCtx.cwd);
|
|
33997
34266
|
const bashCfg2 = resolveBashConfig(ctx.config);
|
|
33998
34267
|
const foregroundWaitMs = resolveForegroundWaitMs(bashCfg2.foreground_wait_window_ms);
|
|
34268
|
+
const backgroundDisabled = !bashCfg2.background;
|
|
33999
34269
|
const timeout = coerceOptionalInt(params.timeout, "timeout", 1, Number.MAX_SAFE_INTEGER);
|
|
34000
|
-
const ptyRows = coerceOptionalInt(params.ptyRows, "ptyRows", 1, 60);
|
|
34001
|
-
const ptyCols = coerceOptionalInt(params.ptyCols, "ptyCols", 1, 140);
|
|
34002
|
-
const
|
|
34003
|
-
const
|
|
34270
|
+
const ptyRows = backgroundDisabled ? undefined : coerceOptionalInt(params.ptyRows, "ptyRows", 1, 60);
|
|
34271
|
+
const ptyCols = backgroundDisabled ? undefined : coerceOptionalInt(params.ptyCols, "ptyCols", 1, 140);
|
|
34272
|
+
const requestedPty = !backgroundDisabled && params.pty === true;
|
|
34273
|
+
const effectiveBackground = !backgroundDisabled && (params.background === true || requestedPty);
|
|
34274
|
+
const effectiveTimeout = effectiveBackground || backgroundDisabled ? timeout : resolveBashKillTimeout(timeout, foregroundWaitMs);
|
|
34004
34275
|
let spawnContext = {
|
|
34005
34276
|
command: params.command,
|
|
34006
34277
|
cwd: params.workdir
|
|
@@ -34025,7 +34296,7 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
34025
34296
|
background: effectiveBackground,
|
|
34026
34297
|
notify_on_completion: effectiveBackground,
|
|
34027
34298
|
compressed: params.compressed,
|
|
34028
|
-
pty:
|
|
34299
|
+
pty: requestedPty,
|
|
34029
34300
|
pty_rows: ptyRows,
|
|
34030
34301
|
pty_cols: ptyCols
|
|
34031
34302
|
}, extCtx, {
|
|
@@ -34047,9 +34318,9 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
34047
34318
|
if (response.status === "running" && taskId) {
|
|
34048
34319
|
if (effectiveBackground) {
|
|
34049
34320
|
trackBgTask(resolveSessionId(extCtx), taskId);
|
|
34050
|
-
return bashResult(appendPipeStripNote(formatBackgroundLaunch(taskId,
|
|
34321
|
+
return bashResult(appendPipeStripNote(formatBackgroundLaunch(taskId, requestedPty), pipeStrip.note), { task_id: taskId });
|
|
34051
34322
|
}
|
|
34052
|
-
const waitTimeoutMs = effectiveTimeout !== undefined ? Math.min(effectiveTimeout, foregroundWaitMs) : foregroundWaitMs;
|
|
34323
|
+
const waitTimeoutMs = backgroundDisabled ? effectiveTimeout ?? DEFAULT_HARD_TIMEOUT_MS : effectiveTimeout !== undefined ? Math.min(effectiveTimeout, foregroundWaitMs) : foregroundWaitMs;
|
|
34053
34324
|
const startedAt = Date.now();
|
|
34054
34325
|
while (true) {
|
|
34055
34326
|
const status = await callBashBridge(bridge, "bash_status", { task_id: taskId }, extCtx);
|
|
@@ -34066,6 +34337,10 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
34066
34337
|
});
|
|
34067
34338
|
}
|
|
34068
34339
|
if (Date.now() - startedAt >= waitTimeoutMs) {
|
|
34340
|
+
if (backgroundDisabled) {
|
|
34341
|
+
await sleep(FOREGROUND_POLL_INTERVAL_MS);
|
|
34342
|
+
continue;
|
|
34343
|
+
}
|
|
34069
34344
|
const promoted = await callBashBridge(bridge, "bash_promote", { task_id: taskId }, extCtx);
|
|
34070
34345
|
if (promoted.success === false) {
|
|
34071
34346
|
throw new Error(promoted.message ?? "bash_promote failed");
|
|
@@ -34093,10 +34368,12 @@ DO NOT use bash for code search or code exploration. If you are about to run gre
|
|
|
34093
34368
|
return renderBashResult(result, theme, context);
|
|
34094
34369
|
}
|
|
34095
34370
|
});
|
|
34096
|
-
|
|
34097
|
-
|
|
34098
|
-
|
|
34099
|
-
|
|
34371
|
+
if (bashCfg.background) {
|
|
34372
|
+
pi.registerTool(createBashStatusTool(ctx));
|
|
34373
|
+
pi.registerTool(createBashWatchTool(ctx));
|
|
34374
|
+
pi.registerTool(createBashWriteTool(ctx));
|
|
34375
|
+
pi.registerTool(createBashKillTool(ctx));
|
|
34376
|
+
}
|
|
34100
34377
|
}
|
|
34101
34378
|
function formatBackgroundLaunch(taskId, isPty) {
|
|
34102
34379
|
if (isPty) {
|
|
@@ -34115,7 +34392,7 @@ function createBashStatusTool(ctx) {
|
|
|
34115
34392
|
return {
|
|
34116
34393
|
name: "bash_status",
|
|
34117
34394
|
label: "bash_status",
|
|
34118
|
-
description: "Read-only snapshot of a background bash task. Returns immediately. Never waits.
|
|
34395
|
+
description: "Read-only snapshot of a background bash task. Returns immediately. Never waits. One look to check on a task is fine — never loop it to wait for completion. To wait, use bash_watch.",
|
|
34119
34396
|
promptSnippet: "Inspect a background bash task by task_id",
|
|
34120
34397
|
parameters: BashStatusParams,
|
|
34121
34398
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
@@ -34130,7 +34407,7 @@ function createBashWatchTool(ctx) {
|
|
|
34130
34407
|
return {
|
|
34131
34408
|
name: "bash_watch",
|
|
34132
34409
|
label: "bash_watch",
|
|
34133
|
-
description: "Watch a background bash task.
|
|
34410
|
+
description: "Watch a background bash task. Sync (default) blocks until a pattern matches, the task exits, or timeout — use it when the result is the next thing you need, even for long builds/tests/installs (pass timeout_ms up to 30 min for those). The user can interrupt anytime; the wait auto-converts to an async notification. Async (background:true, requires pattern) registers a non-blocking notification and returns immediately — use when you have parallel work or want to end your turn. Never loop bash_status to wait.",
|
|
34134
34411
|
promptSnippet: "Wait for or watch a background bash task",
|
|
34135
34412
|
parameters: BashWatchParams,
|
|
34136
34413
|
async execute(_toolCallId, params, _signal, _onUpdate, extCtx) {
|
|
@@ -34703,10 +34980,10 @@ function renderFsResult(toolName, args, result, theme, context) {
|
|
|
34703
34980
|
const skipped = data.skipped_files ?? [];
|
|
34704
34981
|
const lines = [];
|
|
34705
34982
|
for (const entry of deletedPaths) {
|
|
34706
|
-
lines.push(`${theme.fg("success", "✓ deleted")} ${theme.fg("accent",
|
|
34983
|
+
lines.push(`${theme.fg("success", "✓ deleted")} ${theme.fg("accent", shortenPath3(entry))}`);
|
|
34707
34984
|
}
|
|
34708
34985
|
for (const entry of skipped) {
|
|
34709
|
-
lines.push(`${theme.fg("error", "✗ skipped")} ${theme.fg("accent",
|
|
34986
|
+
lines.push(`${theme.fg("error", "✗ skipped")} ${theme.fg("accent", shortenPath3(entry.file))} ${theme.fg("muted", `(${entry.reason})`)}`);
|
|
34710
34987
|
}
|
|
34711
34988
|
if (lines.length === 0) {
|
|
34712
34989
|
lines.push(theme.fg("muted", "(no files deleted)"));
|
|
@@ -34716,8 +34993,8 @@ function renderFsResult(toolName, args, result, theme, context) {
|
|
|
34716
34993
|
}
|
|
34717
34994
|
const moveArgs = args;
|
|
34718
34995
|
return renderSections([
|
|
34719
|
-
`${theme.fg("success", "✓ moved")} ${theme.fg("accent",
|
|
34720
|
-
`${theme.fg("muted", "to")} ${theme.fg("accent",
|
|
34996
|
+
`${theme.fg("success", "✓ moved")} ${theme.fg("accent", shortenPath3(moveArgs.filePath))}`,
|
|
34997
|
+
`${theme.fg("muted", "to")} ${theme.fg("accent", shortenPath3(moveArgs.destination))}`
|
|
34721
34998
|
], context);
|
|
34722
34999
|
}
|
|
34723
35000
|
function registerFsTools(pi, ctx, surface) {
|
|
@@ -34831,33 +35108,33 @@ var ImportParams = Type7.Object({
|
|
|
34831
35108
|
}))
|
|
34832
35109
|
});
|
|
34833
35110
|
function buildImportSections(args, payload, theme) {
|
|
34834
|
-
const response =
|
|
35111
|
+
const response = asRecord3(payload);
|
|
34835
35112
|
if (!response)
|
|
34836
35113
|
return [theme.fg("muted", "No import result.")];
|
|
34837
35114
|
if (args.op === "organize") {
|
|
34838
|
-
const groups =
|
|
34839
|
-
const groupText = groups.length > 0 ? groups.map((group) => `${
|
|
35115
|
+
const groups = asRecords2(response.groups);
|
|
35116
|
+
const groupText = groups.length > 0 ? groups.map((group) => `${asString2(group.name) ?? "unknown"}: ${asNumber2(group.count) ?? 0}`).join(" · ") : "No imports found";
|
|
34840
35117
|
return [
|
|
34841
|
-
`${theme.fg("success", "organized")} ${theme.fg("accent",
|
|
35118
|
+
`${theme.fg("success", "organized")} ${theme.fg("accent", asString2(response.file) ?? args.filePath)}`,
|
|
34842
35119
|
`${theme.fg("muted", "groups")} ${groupText}`,
|
|
34843
|
-
`${theme.fg("muted", "duplicates removed")} ${
|
|
35120
|
+
`${theme.fg("muted", "duplicates removed")} ${asNumber2(response.removed_duplicates) ?? 0}`
|
|
34844
35121
|
];
|
|
34845
35122
|
}
|
|
34846
35123
|
if (args.op === "add") {
|
|
34847
|
-
const moduleName2 =
|
|
35124
|
+
const moduleName2 = asString2(response.module) ?? args.module ?? "(module)";
|
|
34848
35125
|
const status = response.already_present === true ? theme.fg("warning", "already present") : theme.fg("success", "added");
|
|
34849
35126
|
return [
|
|
34850
35127
|
`${status} ${theme.fg("accent", moduleName2)}`,
|
|
34851
|
-
`${theme.fg("muted", "file")} ${theme.fg("accent",
|
|
34852
|
-
`${theme.fg("muted", "group")} ${
|
|
35128
|
+
`${theme.fg("muted", "file")} ${theme.fg("accent", asString2(response.file) ?? args.filePath)}`,
|
|
35129
|
+
`${theme.fg("muted", "group")} ${asString2(response.group) ?? "—"}`
|
|
34853
35130
|
];
|
|
34854
35131
|
}
|
|
34855
|
-
const moduleName =
|
|
35132
|
+
const moduleName = asString2(response.module) ?? args.module ?? "(module)";
|
|
34856
35133
|
const didRemove = response.removed !== false;
|
|
34857
35134
|
const removeStatus = didRemove ? `${theme.fg("success", "removed")} ${theme.fg("accent", moduleName)}` : `${theme.fg("warning", "not present")} ${theme.fg("accent", moduleName)}`;
|
|
34858
35135
|
return [
|
|
34859
35136
|
removeStatus,
|
|
34860
|
-
`${theme.fg("muted", "file")} ${theme.fg("accent",
|
|
35137
|
+
`${theme.fg("muted", "file")} ${theme.fg("accent", asString2(response.file) ?? args.filePath)}`,
|
|
34861
35138
|
args.removeName ? `${theme.fg("muted", "name")} ${args.removeName}` : `${theme.fg("muted", "scope")} entire import`
|
|
34862
35139
|
];
|
|
34863
35140
|
}
|
|
@@ -34990,16 +35267,16 @@ function diagnosticsServerSummary(section) {
|
|
|
34990
35267
|
return parts.length > 0 ? parts.join("; ") : "none reported";
|
|
34991
35268
|
}
|
|
34992
35269
|
function diagnosticsSummaryPart(summary) {
|
|
34993
|
-
const section =
|
|
35270
|
+
const section = asRecord3(summary?.diagnostics);
|
|
34994
35271
|
if (!section)
|
|
34995
35272
|
return;
|
|
34996
|
-
const errors3 =
|
|
34997
|
-
const warnings =
|
|
34998
|
-
const info =
|
|
34999
|
-
const hints =
|
|
35273
|
+
const errors3 = asNumber2(section.errors);
|
|
35274
|
+
const warnings = asNumber2(section.warnings);
|
|
35275
|
+
const info = asNumber2(section.info);
|
|
35276
|
+
const hints = asNumber2(section.hints);
|
|
35000
35277
|
const hasCounts = [errors3, warnings, info, hints].some((value) => value !== undefined);
|
|
35001
35278
|
const counts = `${errors3 ?? 0} errors/${warnings ?? 0} warnings/${info ?? 0} info/${hints ?? 0} hints`;
|
|
35002
|
-
const status =
|
|
35279
|
+
const status = asString2(section.status);
|
|
35003
35280
|
if (status === "pending") {
|
|
35004
35281
|
return hasCounts ? `diagnostics ${counts} so far — still pending (servers: ${diagnosticsServerSummary(section)})` : `diagnostics pending (servers: ${diagnosticsServerSummary(section)})`;
|
|
35005
35282
|
}
|
|
@@ -35012,9 +35289,9 @@ function diagnosticsSummaryPart(summary) {
|
|
|
35012
35289
|
return;
|
|
35013
35290
|
}
|
|
35014
35291
|
function diagnosticLocation(diagnostic) {
|
|
35015
|
-
const file2 =
|
|
35016
|
-
const line =
|
|
35017
|
-
const column =
|
|
35292
|
+
const file2 = asString2(diagnostic.file) ?? "(unknown file)";
|
|
35293
|
+
const line = asNumber2(diagnostic.line);
|
|
35294
|
+
const column = asNumber2(diagnostic.column);
|
|
35018
35295
|
if (line === undefined)
|
|
35019
35296
|
return file2;
|
|
35020
35297
|
if (column === undefined)
|
|
@@ -35022,14 +35299,14 @@ function diagnosticLocation(diagnostic) {
|
|
|
35022
35299
|
return `${file2}:${line}:${column}`;
|
|
35023
35300
|
}
|
|
35024
35301
|
function diagnosticsDetailSection(details) {
|
|
35025
|
-
const diagnostics =
|
|
35302
|
+
const diagnostics = asRecords2(details?.diagnostics);
|
|
35026
35303
|
if (diagnostics.length === 0)
|
|
35027
35304
|
return;
|
|
35028
35305
|
const lines = ["diagnostics"];
|
|
35029
35306
|
for (const diagnostic of diagnostics) {
|
|
35030
|
-
const severity =
|
|
35031
|
-
const message =
|
|
35032
|
-
const source =
|
|
35307
|
+
const severity = asString2(diagnostic.severity) ?? "information";
|
|
35308
|
+
const message = asString2(diagnostic.message) ?? "(no message)";
|
|
35309
|
+
const source = asString2(diagnostic.source);
|
|
35033
35310
|
const suffix = source ? ` [${source}]` : "";
|
|
35034
35311
|
lines.push(`- ${diagnosticLocation(diagnostic)} ${severity} ${message}${suffix}`);
|
|
35035
35312
|
}
|
|
@@ -35037,15 +35314,15 @@ function diagnosticsDetailSection(details) {
|
|
|
35037
35314
|
`);
|
|
35038
35315
|
}
|
|
35039
35316
|
function countFrom(summary, key) {
|
|
35040
|
-
const section =
|
|
35041
|
-
return
|
|
35317
|
+
const section = asRecord3(summary?.[key]);
|
|
35318
|
+
return asNumber2(section?.count);
|
|
35042
35319
|
}
|
|
35043
35320
|
function tier2SummaryPart(summary, key, label) {
|
|
35044
|
-
const section =
|
|
35045
|
-
const count =
|
|
35321
|
+
const section = asRecord3(summary?.[key]);
|
|
35322
|
+
const count = asNumber2(section?.count);
|
|
35046
35323
|
if (count !== undefined)
|
|
35047
35324
|
return `${label} ${count}`;
|
|
35048
|
-
const status =
|
|
35325
|
+
const status = asString2(section?.status);
|
|
35049
35326
|
return `${label} ${status ?? "unavailable"}`;
|
|
35050
35327
|
}
|
|
35051
35328
|
function shortDupOccurrence(entry) {
|
|
@@ -35054,12 +35331,12 @@ function shortDupOccurrence(entry) {
|
|
|
35054
35331
|
}
|
|
35055
35332
|
function tier2TopPreview(summary, theme) {
|
|
35056
35333
|
const lines = [];
|
|
35057
|
-
const dup =
|
|
35334
|
+
const dup = asRecord3(summary?.duplicates);
|
|
35058
35335
|
const dupTop = Array.isArray(dup?.top) ? dup.top : [];
|
|
35059
35336
|
for (const group of dupTop) {
|
|
35060
|
-
const record2 =
|
|
35337
|
+
const record2 = asRecord3(group);
|
|
35061
35338
|
const files = Array.isArray(record2?.files) ? record2.files : [];
|
|
35062
|
-
const cost =
|
|
35339
|
+
const cost = asNumber2(record2?.cost);
|
|
35063
35340
|
if (files.length < 2)
|
|
35064
35341
|
continue;
|
|
35065
35342
|
const a = shortDupOccurrence(String(files[0]));
|
|
@@ -35070,12 +35347,12 @@ function tier2TopPreview(summary, theme) {
|
|
|
35070
35347
|
["dead_code", "dead"],
|
|
35071
35348
|
["unused_exports", "unused"]
|
|
35072
35349
|
]) {
|
|
35073
|
-
const section =
|
|
35350
|
+
const section = asRecord3(summary?.[key]);
|
|
35074
35351
|
const top = Array.isArray(section?.top) ? section.top : [];
|
|
35075
35352
|
for (const item of top) {
|
|
35076
|
-
const record2 =
|
|
35077
|
-
const file2 =
|
|
35078
|
-
const symbol2 =
|
|
35353
|
+
const record2 = asRecord3(item);
|
|
35354
|
+
const file2 = asString2(record2?.file);
|
|
35355
|
+
const symbol2 = asString2(record2?.symbol);
|
|
35079
35356
|
if (!file2 || !symbol2)
|
|
35080
35357
|
continue;
|
|
35081
35358
|
lines.push(` ${label} ${symbol2} (${file2.split("/").pop()})`);
|
|
@@ -35088,7 +35365,7 @@ ${lines.join(`
|
|
|
35088
35365
|
`)}`;
|
|
35089
35366
|
}
|
|
35090
35367
|
function tier2RefreshCategories(response) {
|
|
35091
|
-
const scannerState =
|
|
35368
|
+
const scannerState = asRecord3(response.scanner_state);
|
|
35092
35369
|
const categories = new Set;
|
|
35093
35370
|
for (const key of ["pending_categories", "stale_categories"]) {
|
|
35094
35371
|
const values = scannerState?.[key];
|
|
@@ -35135,18 +35412,18 @@ function runPendingTier2Categories(bridge, categories, extCtx) {
|
|
|
35135
35412
|
});
|
|
35136
35413
|
}
|
|
35137
35414
|
function buildInspectSections(payload, theme) {
|
|
35138
|
-
const response =
|
|
35415
|
+
const response = asRecord3(payload);
|
|
35139
35416
|
if (!response)
|
|
35140
35417
|
return [theme.fg("muted", "No inspect snapshot available.")];
|
|
35141
|
-
const summary =
|
|
35142
|
-
const metrics =
|
|
35143
|
-
const scannerState =
|
|
35418
|
+
const summary = asRecord3(response.summary);
|
|
35419
|
+
const metrics = asRecord3(summary?.metrics);
|
|
35420
|
+
const scannerState = asRecord3(response.scanner_state);
|
|
35144
35421
|
const stale = Array.isArray(scannerState?.stale_categories) ? scannerState.stale_categories.length : 0;
|
|
35145
35422
|
const pending = Array.isArray(scannerState?.pending_categories) ? scannerState.pending_categories.length : 0;
|
|
35146
35423
|
const parts = [
|
|
35147
35424
|
`todos ${countFrom(summary, "todos") ?? 0}`,
|
|
35148
35425
|
diagnosticsSummaryPart(summary),
|
|
35149
|
-
`metrics ${
|
|
35426
|
+
`metrics ${asNumber2(metrics?.files) ?? 0} files/${asNumber2(metrics?.symbols) ?? 0} symbols`,
|
|
35150
35427
|
tier2SummaryPart(summary, "dead_code", "dead code"),
|
|
35151
35428
|
tier2SummaryPart(summary, "unused_exports", "unused exports"),
|
|
35152
35429
|
tier2SummaryPart(summary, "duplicates", "duplicates")
|
|
@@ -35158,7 +35435,7 @@ function buildInspectSections(payload, theme) {
|
|
|
35158
35435
|
const topPreview = tier2TopPreview(summary, theme);
|
|
35159
35436
|
if (topPreview)
|
|
35160
35437
|
sections.push(topPreview);
|
|
35161
|
-
const details =
|
|
35438
|
+
const details = asRecord3(response.details);
|
|
35162
35439
|
if (details) {
|
|
35163
35440
|
const names = Object.keys(details);
|
|
35164
35441
|
sections.push(names.length > 0 ? `details: ${names.join(", ")}` : theme.fg("muted", "No drill-down details returned."));
|
|
@@ -35166,7 +35443,7 @@ function buildInspectSections(payload, theme) {
|
|
|
35166
35443
|
if (diagnosticsDetails)
|
|
35167
35444
|
sections.push(diagnosticsDetails);
|
|
35168
35445
|
}
|
|
35169
|
-
const text =
|
|
35446
|
+
const text = asString2(response.text);
|
|
35170
35447
|
if (text)
|
|
35171
35448
|
sections.push(text);
|
|
35172
35449
|
return sections;
|
|
@@ -35199,7 +35476,7 @@ function registerInspectTool(pi, ctx) {
|
|
|
35199
35476
|
runPendingTier2Categories(bridge, tier2RefreshCategories(response), extCtx);
|
|
35200
35477
|
const body = response.text;
|
|
35201
35478
|
if (typeof body === "string") {
|
|
35202
|
-
const diagnostics = diagnosticsSummaryPart(
|
|
35479
|
+
const diagnostics = diagnosticsSummaryPart(asRecord3(response.summary));
|
|
35203
35480
|
const text = diagnostics ? body ? `${body}
|
|
35204
35481
|
|
|
35205
35482
|
${diagnostics}` : diagnostics : body;
|
|
@@ -35239,138 +35516,11 @@ function navigateParamsSchema() {
|
|
|
35239
35516
|
}))
|
|
35240
35517
|
});
|
|
35241
35518
|
}
|
|
35242
|
-
function treeLine(depth, text) {
|
|
35243
|
-
return `${" ".repeat(depth)}${depth === 0 ? "" : "↳ "}${text}`;
|
|
35244
|
-
}
|
|
35245
|
-
function renderCallTreeNode(node, depth, lines) {
|
|
35246
|
-
const name = asString(node.name) ?? "(unknown)";
|
|
35247
|
-
const file2 = shortenPath2(asString(node.file) ?? "(unknown file)");
|
|
35248
|
-
const line = asNumber(node.line);
|
|
35249
|
-
lines.push(treeLine(depth, `${name} ${line !== undefined ? `[${file2}:${line}]` : `[${file2}]`}`));
|
|
35250
|
-
asRecords(node.children).forEach((child) => {
|
|
35251
|
-
renderCallTreeNode(child, depth + 1, lines);
|
|
35252
|
-
});
|
|
35253
|
-
}
|
|
35254
|
-
function depthWarning(response, theme, depthField = "depth_limited", truncatedField = "truncated") {
|
|
35255
|
-
const limited = asBoolean(response[depthField]);
|
|
35256
|
-
const truncated = asNumber(response[truncatedField]) ?? 0;
|
|
35257
|
-
if (!limited && truncated === 0)
|
|
35258
|
-
return "";
|
|
35259
|
-
const detail = truncated > 0 ? `, ${truncated} truncated` : "";
|
|
35260
|
-
return theme.fg("warning", `(depth limited${detail})`);
|
|
35261
|
-
}
|
|
35262
|
-
function renderTracePath(path3, index, lines) {
|
|
35263
|
-
lines.push(`Path ${index + 1}`);
|
|
35264
|
-
asRecords(path3.hops).forEach((hop, hopIndex) => {
|
|
35265
|
-
const symbol2 = asString(hop.symbol) ?? "(unknown)";
|
|
35266
|
-
const file2 = shortenPath2(asString(hop.file) ?? "(unknown file)");
|
|
35267
|
-
const line = asNumber(hop.line);
|
|
35268
|
-
const entry = hop.is_entry_point === true ? " [entry]" : "";
|
|
35269
|
-
lines.push(treeLine(hopIndex + 1, `${symbol2}${entry} ${line !== undefined ? `[${file2}:${line}]` : `[${file2}]`}`));
|
|
35270
|
-
});
|
|
35271
|
-
}
|
|
35272
35519
|
function buildNavigateSections(args, payload, theme) {
|
|
35273
|
-
const
|
|
35274
|
-
|
|
35275
|
-
|
|
35276
|
-
|
|
35277
|
-
const lines = [];
|
|
35278
|
-
renderCallTreeNode(response, 0, lines);
|
|
35279
|
-
const warning = depthWarning(response, theme);
|
|
35280
|
-
if (warning)
|
|
35281
|
-
lines.push(warning);
|
|
35282
|
-
return lines.length > 0 ? lines : [theme.fg("muted", "No call tree available.")];
|
|
35283
|
-
}
|
|
35284
|
-
if (args.op === "callers") {
|
|
35285
|
-
const groups = asRecords(response.callers);
|
|
35286
|
-
const warning = depthWarning(response, theme);
|
|
35287
|
-
const sections2 = [
|
|
35288
|
-
`${theme.fg("success", `${asNumber(response.total_callers) ?? 0} caller${(asNumber(response.total_callers) ?? 0) === 1 ? "" : "s"}`)} ${theme.fg("muted", `${groups.length} file group${groups.length === 1 ? "" : "s"}`)} ${warning}`.trim()
|
|
35289
|
-
];
|
|
35290
|
-
groups.forEach((group) => {
|
|
35291
|
-
const file2 = shortenPath2(asString(group.file) ?? "(unknown file)");
|
|
35292
|
-
const lines = [theme.fg("accent", file2)];
|
|
35293
|
-
asRecords(group.callers).forEach((caller) => {
|
|
35294
|
-
lines.push(` ↳ ${asString(caller.symbol) ?? "(unknown)"} ${theme.fg("muted", `line ${asNumber(caller.line) ?? "?"}`)}`);
|
|
35295
|
-
});
|
|
35296
|
-
sections2.push(lines.join(`
|
|
35297
|
-
`));
|
|
35298
|
-
});
|
|
35299
|
-
return sections2;
|
|
35300
|
-
}
|
|
35301
|
-
if (args.op === "trace_to_symbol") {
|
|
35302
|
-
const path3 = asRecords(response.path);
|
|
35303
|
-
const complete = asBoolean(response.complete);
|
|
35304
|
-
const reason = asString(response.reason);
|
|
35305
|
-
if (path3.length === 0) {
|
|
35306
|
-
const prefix = complete === false ? theme.fg("warning", "No complete path") : theme.fg("muted", "No path");
|
|
35307
|
-
return [`${prefix}${reason ? ` (${reason})` : ""}`];
|
|
35308
|
-
}
|
|
35309
|
-
const lines = [theme.fg("success", `${path3.length} hop${path3.length === 1 ? "" : "s"}`)];
|
|
35310
|
-
path3.forEach((hop, index) => {
|
|
35311
|
-
const symbol2 = asString(hop.symbol) ?? "(unknown)";
|
|
35312
|
-
const file2 = shortenPath2(asString(hop.file) ?? "(unknown file)");
|
|
35313
|
-
const line = asNumber(hop.line);
|
|
35314
|
-
lines.push(treeLine(index + 1, `${symbol2} ${line !== undefined ? `[${file2}:${line}]` : `[${file2}]`}`));
|
|
35315
|
-
});
|
|
35316
|
-
return lines;
|
|
35317
|
-
}
|
|
35318
|
-
if (args.op === "trace_to") {
|
|
35319
|
-
const paths = asRecords(response.paths);
|
|
35320
|
-
const warning = depthWarning(response, theme, "max_depth_reached", "truncated_paths");
|
|
35321
|
-
const sections2 = [
|
|
35322
|
-
`${theme.fg("success", `${asNumber(response.total_paths) ?? paths.length} path${(asNumber(response.total_paths) ?? paths.length) === 1 ? "" : "s"}`)} ${theme.fg("muted", `${asNumber(response.entry_points_found) ?? 0} entry point${(asNumber(response.entry_points_found) ?? 0) === 1 ? "" : "s"}`)} ${warning}`.trim()
|
|
35323
|
-
];
|
|
35324
|
-
if (paths.length === 0)
|
|
35325
|
-
sections2.push(theme.fg("muted", "No entry paths found."));
|
|
35326
|
-
paths.forEach((path3, index) => {
|
|
35327
|
-
const lines = [];
|
|
35328
|
-
renderTracePath(path3, index, lines);
|
|
35329
|
-
sections2.push(lines.join(`
|
|
35330
|
-
`));
|
|
35331
|
-
});
|
|
35332
|
-
return sections2;
|
|
35333
|
-
}
|
|
35334
|
-
if (args.op === "impact") {
|
|
35335
|
-
const callers = asRecords(response.callers);
|
|
35336
|
-
const warning = depthWarning(response, theme);
|
|
35337
|
-
const sections2 = [
|
|
35338
|
-
`${theme.fg("warning", `${asNumber(response.total_affected) ?? callers.length} affected call site${(asNumber(response.total_affected) ?? callers.length) === 1 ? "" : "s"}`)} ${theme.fg("muted", `${asNumber(response.affected_files) ?? 0} file${(asNumber(response.affected_files) ?? 0) === 1 ? "" : "s"}`)} ${warning}`.trim()
|
|
35339
|
-
];
|
|
35340
|
-
if (callers.length === 0)
|
|
35341
|
-
sections2.push(theme.fg("muted", "No impacted callers found."));
|
|
35342
|
-
callers.forEach((caller) => {
|
|
35343
|
-
const file2 = shortenPath2(asString(caller.caller_file) ?? "(unknown file)");
|
|
35344
|
-
const symbol2 = asString(caller.caller_symbol) ?? "(unknown)";
|
|
35345
|
-
const line = asNumber(caller.line) ?? 0;
|
|
35346
|
-
const entry = caller.is_entry_point === true ? ` ${theme.fg("warning", "[entry]")}` : "";
|
|
35347
|
-
const expression = asString(caller.call_expression);
|
|
35348
|
-
const params = Array.isArray(caller.parameters) ? caller.parameters.map(String).join(", ") : "";
|
|
35349
|
-
sections2.push([
|
|
35350
|
-
`${theme.fg("accent", file2)}:${line}`,
|
|
35351
|
-
` ↳ ${symbol2}${entry}`,
|
|
35352
|
-
expression ? ` ${theme.fg("muted", expression)}` : undefined,
|
|
35353
|
-
params ? ` ${theme.fg("muted", `params: ${params}`)}` : undefined
|
|
35354
|
-
].filter(Boolean).join(`
|
|
35355
|
-
`));
|
|
35356
|
-
});
|
|
35357
|
-
return sections2;
|
|
35358
|
-
}
|
|
35359
|
-
const hops = asRecords(response.hops);
|
|
35360
|
-
const sections = [
|
|
35361
|
-
`${theme.fg("success", `${hops.length} hop${hops.length === 1 ? "" : "s"}`)} ${asBoolean(response.depth_limited) ? theme.fg("warning", "(depth limited)") : ""}`.trim()
|
|
35362
|
-
];
|
|
35363
|
-
if (hops.length === 0)
|
|
35364
|
-
sections.push(theme.fg("muted", "No data-flow hops found."));
|
|
35365
|
-
hops.forEach((hop, index) => {
|
|
35366
|
-
const file2 = shortenPath2(asString(hop.file) ?? "(unknown file)");
|
|
35367
|
-
const symbol2 = asString(hop.symbol) ?? "(unknown)";
|
|
35368
|
-
const variable = asString(hop.variable) ?? "(unknown)";
|
|
35369
|
-
const line = asNumber(hop.line) ?? 0;
|
|
35370
|
-
const approximate = hop.approximate === true ? ` ${theme.fg("warning", "[approx]")}` : "";
|
|
35371
|
-
sections.push(treeLine(index, `${variable} ${theme.fg("muted", `${asString(hop.flow_type) ?? "flow"}`)} ${symbol2} [${file2}:${line}]${approximate}`));
|
|
35372
|
-
});
|
|
35373
|
-
return sections;
|
|
35520
|
+
const themeAdapter = {
|
|
35521
|
+
fg: (role, s) => theme.fg(role, s)
|
|
35522
|
+
};
|
|
35523
|
+
return formatCallgraphSections(args.op, payload, themeAdapter);
|
|
35374
35524
|
}
|
|
35375
35525
|
function renderNavigateCall(args, theme, context) {
|
|
35376
35526
|
const summary = [
|
|
@@ -35433,7 +35583,8 @@ function registerNavigateTool(pi, ctx) {
|
|
|
35433
35583
|
req.toFile = toFile;
|
|
35434
35584
|
try {
|
|
35435
35585
|
const response = await callBridge(bridge, params.op, req, extCtx);
|
|
35436
|
-
return textResult(
|
|
35586
|
+
return textResult(formatCallgraphSections(params.op, response, PLAIN_CALLGRAPH_THEME).join(`
|
|
35587
|
+
`), response);
|
|
35437
35588
|
} catch (error50) {
|
|
35438
35589
|
if (error50 instanceof BridgeError && CALLGRAPH_SOFT_CODES.has(error50.code)) {
|
|
35439
35590
|
return textResult(error50.message);
|
|
@@ -35511,25 +35662,25 @@ function buildOutlineSections(text, theme) {
|
|
|
35511
35662
|
`)];
|
|
35512
35663
|
}
|
|
35513
35664
|
function buildZoomSections(args, payload, theme) {
|
|
35514
|
-
const batch =
|
|
35665
|
+
const batch = asRecord3(payload);
|
|
35515
35666
|
const batchItems = Array.isArray(batch?.symbols) ? batch.symbols : Array.isArray(batch?.entries) ? batch.entries : null;
|
|
35516
35667
|
if (batchItems) {
|
|
35517
35668
|
const header = batch?.complete === false ? [theme.fg("warning", "Incomplete zoom results")] : [];
|
|
35518
35669
|
return [
|
|
35519
35670
|
...header,
|
|
35520
35671
|
...batchItems.map((item) => {
|
|
35521
|
-
const record2 =
|
|
35672
|
+
const record2 = asRecord3(item);
|
|
35522
35673
|
if (!record2)
|
|
35523
35674
|
return theme.fg("muted", "No zoom result available.");
|
|
35524
|
-
const name =
|
|
35525
|
-
const itemTargetLabel =
|
|
35675
|
+
const name = asString2(record2.name) ?? "(unknown symbol)";
|
|
35676
|
+
const itemTargetLabel = asString2(record2.targetLabel) ?? zoomTargetLabel(args);
|
|
35526
35677
|
if (record2.success === false) {
|
|
35527
|
-
const location = record2.targetLabel ? ` in ${
|
|
35528
|
-
return theme.fg("error", `Symbol "${name}" not found${location}: ${
|
|
35678
|
+
const location = record2.targetLabel ? ` in ${shortenPath3(itemTargetLabel)}` : "";
|
|
35679
|
+
return theme.fg("error", `Symbol "${name}" not found${location}: ${asString2(record2.error) ?? "zoom failed"}`);
|
|
35529
35680
|
}
|
|
35530
|
-
const content =
|
|
35681
|
+
const content = asString2(record2.content);
|
|
35531
35682
|
return [
|
|
35532
|
-
`${theme.fg("accent", name)} ${theme.fg("muted",
|
|
35683
|
+
`${theme.fg("accent", name)} ${theme.fg("muted", shortenPath3(itemTargetLabel))}`,
|
|
35533
35684
|
content
|
|
35534
35685
|
].filter(Boolean).join(`
|
|
35535
35686
|
`);
|
|
@@ -35540,32 +35691,32 @@ function buildZoomSections(args, payload, theme) {
|
|
|
35540
35691
|
if (items.length === 0)
|
|
35541
35692
|
return [theme.fg("muted", "No zoom result available.")];
|
|
35542
35693
|
return items.map((item) => {
|
|
35543
|
-
const record2 =
|
|
35694
|
+
const record2 = asRecord3(item);
|
|
35544
35695
|
if (!record2)
|
|
35545
35696
|
return theme.fg("muted", "No zoom result available.");
|
|
35546
|
-
const name =
|
|
35547
|
-
const kind =
|
|
35548
|
-
const range =
|
|
35697
|
+
const name = asString2(record2.name) ?? "(unknown symbol)";
|
|
35698
|
+
const kind = asString2(record2.kind) ?? "symbol";
|
|
35699
|
+
const range = asRecord3(record2.range);
|
|
35549
35700
|
const startLine = range && typeof range.start_line === "number" ? range.start_line : undefined;
|
|
35550
35701
|
const endLine = range && typeof range.end_line === "number" ? range.end_line : undefined;
|
|
35551
35702
|
const targetLabel = zoomTargetLabel(args);
|
|
35552
|
-
const location = startLine !== undefined ? `${
|
|
35703
|
+
const location = startLine !== undefined ? `${shortenPath3(targetLabel)}:${startLine}${endLine && endLine !== startLine ? `-${endLine}` : ""}` : shortenPath3(targetLabel);
|
|
35553
35704
|
const lines = [`${theme.fg("accent", name)} ${theme.fg("muted", `[${kind}] ${location}`)}`];
|
|
35554
|
-
const content =
|
|
35705
|
+
const content = asString2(record2.content);
|
|
35555
35706
|
if (content) {
|
|
35556
35707
|
lines.push(content.split(`
|
|
35557
35708
|
`).map((line) => ` ${line}`).join(`
|
|
35558
35709
|
`));
|
|
35559
35710
|
}
|
|
35560
|
-
const annotations =
|
|
35561
|
-
const callsOut = annotations ?
|
|
35562
|
-
const calledBy = annotations ?
|
|
35711
|
+
const annotations = asRecord3(record2.annotations);
|
|
35712
|
+
const callsOut = annotations ? asRecords2(annotations.calls_out) : [];
|
|
35713
|
+
const calledBy = annotations ? asRecords2(annotations.called_by) : [];
|
|
35563
35714
|
if (callsOut.length > 0) {
|
|
35564
|
-
lines.push(`${theme.fg("muted", "calls out")}`, callsOut.map((call) => ` ↳ ${
|
|
35715
|
+
lines.push(`${theme.fg("muted", "calls out")}`, callsOut.map((call) => ` ↳ ${asString2(call.name) ?? "(unknown)"}${typeof call.line === "number" ? `:${call.line}` : ""}`).join(`
|
|
35565
35716
|
`));
|
|
35566
35717
|
}
|
|
35567
35718
|
if (calledBy.length > 0) {
|
|
35568
|
-
lines.push(`${theme.fg("muted", "called by")}`, calledBy.map((call) => ` ↳ ${
|
|
35719
|
+
lines.push(`${theme.fg("muted", "called by")}`, calledBy.map((call) => ` ↳ ${asString2(call.name) ?? "(unknown)"}${typeof call.line === "number" ? `:${call.line}` : ""}`).join(`
|
|
35569
35720
|
`));
|
|
35570
35721
|
}
|
|
35571
35722
|
return lines.join(`
|
|
@@ -35904,32 +36055,32 @@ var RefactorParams = Type11.Object({
|
|
|
35904
36055
|
callSiteLine: optionalInt(1, Number.MAX_SAFE_INTEGER)
|
|
35905
36056
|
});
|
|
35906
36057
|
function buildRefactorSections(args, payload, theme) {
|
|
35907
|
-
const response =
|
|
36058
|
+
const response = asRecord3(payload);
|
|
35908
36059
|
if (!response)
|
|
35909
36060
|
return [theme.fg("muted", "No refactor result.")];
|
|
35910
36061
|
if (args.op === "move") {
|
|
35911
|
-
const results =
|
|
36062
|
+
const results = asRecords2(response.results);
|
|
35912
36063
|
return [
|
|
35913
36064
|
`${theme.fg("success", "moved symbol")} ${theme.fg("toolOutput", args.symbol ?? "(symbol)")}`,
|
|
35914
|
-
`${theme.fg("muted", "files modified")} ${
|
|
35915
|
-
`${theme.fg("muted", "consumers updated")} ${
|
|
35916
|
-
results.length > 0 ? results.map((entry) => ` ↳ ${
|
|
36065
|
+
`${theme.fg("muted", "files modified")} ${asNumber2(response.files_modified) ?? results.length}`,
|
|
36066
|
+
`${theme.fg("muted", "consumers updated")} ${asNumber2(response.consumers_updated) ?? 0}`,
|
|
36067
|
+
results.length > 0 ? results.map((entry) => ` ↳ ${shortenPath3(asString2(entry.file) ?? "(unknown file)")}`).join(`
|
|
35917
36068
|
`) : theme.fg("muted", "No files reported.")
|
|
35918
36069
|
];
|
|
35919
36070
|
}
|
|
35920
36071
|
if (args.op === "extract") {
|
|
35921
36072
|
return [
|
|
35922
|
-
`${theme.fg("success", "extracted")} ${theme.fg("toolOutput",
|
|
35923
|
-
`${theme.fg("muted", "file")} ${theme.fg("accent",
|
|
36073
|
+
`${theme.fg("success", "extracted")} ${theme.fg("toolOutput", asString2(response.name) ?? args.name ?? "(function)")}`,
|
|
36074
|
+
`${theme.fg("muted", "file")} ${theme.fg("accent", shortenPath3(asString2(response.file) ?? args.filePath))}`,
|
|
35924
36075
|
`${theme.fg("muted", "params")} ${Array.isArray(response.parameters) ? response.parameters.join(", ") || "none" : "none"}`,
|
|
35925
|
-
`${theme.fg("muted", "return type")} ${
|
|
36076
|
+
`${theme.fg("muted", "return type")} ${asString2(response.return_type) ?? "unknown"}`
|
|
35926
36077
|
];
|
|
35927
36078
|
}
|
|
35928
36079
|
return [
|
|
35929
|
-
`${theme.fg("success", "inlined")} ${theme.fg("toolOutput",
|
|
35930
|
-
`${theme.fg("muted", "file")} ${theme.fg("accent",
|
|
35931
|
-
`${theme.fg("muted", "context")} ${
|
|
35932
|
-
`${theme.fg("muted", "substitutions")} ${
|
|
36080
|
+
`${theme.fg("success", "inlined")} ${theme.fg("toolOutput", asString2(response.symbol) ?? args.symbol ?? "(symbol)")}`,
|
|
36081
|
+
`${theme.fg("muted", "file")} ${theme.fg("accent", shortenPath3(asString2(response.file) ?? args.filePath))}`,
|
|
36082
|
+
`${theme.fg("muted", "context")} ${asString2(response.call_context) ?? "unknown"}`,
|
|
36083
|
+
`${theme.fg("muted", "substitutions")} ${asNumber2(response.substitutions) ?? 0}`
|
|
35933
36084
|
];
|
|
35934
36085
|
}
|
|
35935
36086
|
function renderRefactorCall(args, theme, context) {
|
|
@@ -36038,34 +36189,34 @@ var SafetyParams = Type12.Object({
|
|
|
36038
36189
|
}))
|
|
36039
36190
|
});
|
|
36040
36191
|
function buildSafetySections(args, payload, theme) {
|
|
36041
|
-
const response =
|
|
36192
|
+
const response = asRecord3(payload);
|
|
36042
36193
|
if (!response)
|
|
36043
36194
|
return [theme.fg("muted", "No safety result.")];
|
|
36044
36195
|
if (args.op === "undo") {
|
|
36045
36196
|
if (response.operation === true) {
|
|
36046
36197
|
return [
|
|
36047
|
-
`${theme.fg("success", "restored operation")} ${theme.fg("accent",
|
|
36048
|
-
`${theme.fg("muted", "files")} ${
|
|
36198
|
+
`${theme.fg("success", "restored operation")} ${theme.fg("accent", asString2(response.op_id) ?? "(operation)")}`,
|
|
36199
|
+
`${theme.fg("muted", "files")} ${asNumber2(response.restored_count) ?? asRecords2(response.restored).length}`
|
|
36049
36200
|
];
|
|
36050
36201
|
}
|
|
36051
36202
|
return [
|
|
36052
|
-
`${theme.fg("success", "restored")} ${theme.fg("accent",
|
|
36053
|
-
`${theme.fg("muted", "backup")} ${
|
|
36203
|
+
`${theme.fg("success", "restored")} ${theme.fg("accent", shortenPath3(asString2(response.path) ?? args.filePath ?? "(file)"))}`,
|
|
36204
|
+
`${theme.fg("muted", "backup")} ${asString2(response.backup_id) ?? "—"}`
|
|
36054
36205
|
];
|
|
36055
36206
|
}
|
|
36056
36207
|
if (args.op === "history") {
|
|
36057
|
-
const entries =
|
|
36208
|
+
const entries = asRecords2(response.entries);
|
|
36058
36209
|
const sections2 = [
|
|
36059
|
-
theme.fg("accent",
|
|
36210
|
+
theme.fg("accent", shortenPath3(asString2(response.file) ?? args.filePath ?? "(file)"))
|
|
36060
36211
|
];
|
|
36061
36212
|
if (entries.length === 0) {
|
|
36062
36213
|
sections2.push(theme.fg("muted", "No history entries."));
|
|
36063
36214
|
return sections2;
|
|
36064
36215
|
}
|
|
36065
36216
|
sections2.push(entries.map((entry, index) => {
|
|
36066
|
-
const backupId =
|
|
36217
|
+
const backupId = asString2(entry.backup_id) ?? `entry-${index + 1}`;
|
|
36067
36218
|
const timestamp = formatTimestamp(entry.timestamp) ?? "unknown time";
|
|
36068
|
-
const description =
|
|
36219
|
+
const description = asString2(entry.description) ?? "";
|
|
36069
36220
|
return `${index + 1}. ${backupId} ${theme.fg("muted", timestamp)}${description ? `
|
|
36070
36221
|
${description}` : ""}`;
|
|
36071
36222
|
}).join(`
|
|
@@ -36073,22 +36224,22 @@ function buildSafetySections(args, payload, theme) {
|
|
|
36073
36224
|
return sections2;
|
|
36074
36225
|
}
|
|
36075
36226
|
if (args.op === "checkpoint") {
|
|
36076
|
-
const skipped =
|
|
36227
|
+
const skipped = asRecords2(response.skipped);
|
|
36077
36228
|
return [
|
|
36078
|
-
`${theme.fg("success", "checkpoint created")} ${theme.fg("accent",
|
|
36079
|
-
`${theme.fg("muted", "files")} ${
|
|
36229
|
+
`${theme.fg("success", "checkpoint created")} ${theme.fg("accent", asString2(response.name) ?? args.name ?? "(checkpoint)")}`,
|
|
36230
|
+
`${theme.fg("muted", "files")} ${asNumber2(response.file_count) ?? 0}`,
|
|
36080
36231
|
skipped.length > 0 ? `${theme.fg("warning", "skipped")}
|
|
36081
|
-
${skipped.map((entry) => ` ↳ ${
|
|
36232
|
+
${skipped.map((entry) => ` ↳ ${shortenPath3(asString2(entry.file) ?? "(file)")}: ${asString2(entry.error) ?? "unknown error"}`).join(`
|
|
36082
36233
|
`)}` : theme.fg("muted", "No skipped files.")
|
|
36083
36234
|
];
|
|
36084
36235
|
}
|
|
36085
36236
|
if (args.op === "restore") {
|
|
36086
36237
|
return [
|
|
36087
|
-
`${theme.fg("success", "checkpoint restored")} ${theme.fg("accent",
|
|
36088
|
-
`${theme.fg("muted", "files")} ${
|
|
36238
|
+
`${theme.fg("success", "checkpoint restored")} ${theme.fg("accent", asString2(response.name) ?? args.name ?? "(checkpoint)")}`,
|
|
36239
|
+
`${theme.fg("muted", "files")} ${asNumber2(response.file_count) ?? 0}`
|
|
36089
36240
|
];
|
|
36090
36241
|
}
|
|
36091
|
-
const checkpoints =
|
|
36242
|
+
const checkpoints = asRecords2(response.checkpoints);
|
|
36092
36243
|
const sections = [
|
|
36093
36244
|
theme.fg("accent", `${checkpoints.length} checkpoint${checkpoints.length === 1 ? "" : "s"}`)
|
|
36094
36245
|
];
|
|
@@ -36097,8 +36248,8 @@ ${skipped.map((entry) => ` ↳ ${shortenPath2(asString(entry.file) ?? "(file)")
|
|
|
36097
36248
|
return sections;
|
|
36098
36249
|
}
|
|
36099
36250
|
sections.push(checkpoints.map((checkpoint, index) => {
|
|
36100
|
-
const name =
|
|
36101
|
-
const count =
|
|
36251
|
+
const name = asString2(checkpoint.name) ?? `checkpoint-${index + 1}`;
|
|
36252
|
+
const count = asNumber2(checkpoint.file_count) ?? 0;
|
|
36102
36253
|
const created = formatTimestamp(checkpoint.created_at) ?? "unknown time";
|
|
36103
36254
|
return `${index + 1}. ${name} ${theme.fg("muted", `${count} file${count === 1 ? "" : "s"} · ${created}`)}`;
|
|
36104
36255
|
}).join(`
|
|
@@ -36242,13 +36393,13 @@ var SearchParams2 = Type13.Object({
|
|
|
36242
36393
|
}))
|
|
36243
36394
|
});
|
|
36244
36395
|
function buildSemanticSections(args, payload, theme) {
|
|
36245
|
-
const response =
|
|
36396
|
+
const response = asRecord3(payload);
|
|
36246
36397
|
if (!response)
|
|
36247
36398
|
return [theme.fg("muted", "No search result.")];
|
|
36248
|
-
const status =
|
|
36249
|
-
const semanticStatus =
|
|
36250
|
-
const interpretedAs =
|
|
36251
|
-
const queryKind =
|
|
36399
|
+
const status = asString2(response.status) ?? "unknown";
|
|
36400
|
+
const semanticStatus = asString2(response.semantic_status) ?? status;
|
|
36401
|
+
const interpretedAs = asString2(response.interpreted_as) ?? "unknown";
|
|
36402
|
+
const queryKind = asString2(response.query_kind);
|
|
36252
36403
|
const sections = [
|
|
36253
36404
|
`${theme.fg(semanticStatus === "ready" ? "success" : "warning", `semantic: ${semanticStatus}`)} ${theme.fg("muted", `mode=${interpretedAs}${queryKind ? ` kind=${queryKind}` : ""} query=${JSON.stringify(args.query)} topK=${args.topK ?? 10}`)}`
|
|
36254
36405
|
];
|
|
@@ -36260,34 +36411,34 @@ function buildSemanticSections(args, payload, theme) {
|
|
|
36260
36411
|
const honestyNote = semanticHonestyNote(response, theme);
|
|
36261
36412
|
if (honestyNote)
|
|
36262
36413
|
sections.push(honestyNote);
|
|
36263
|
-
const results =
|
|
36414
|
+
const results = asRecords2(response.results);
|
|
36264
36415
|
if (status !== "ready" && results.length === 0) {
|
|
36265
|
-
sections.push(
|
|
36416
|
+
sections.push(asString2(response.text) ?? theme.fg("muted", "Semantic index is not ready."));
|
|
36266
36417
|
return sections;
|
|
36267
36418
|
}
|
|
36268
36419
|
if (results.length === 0) {
|
|
36269
36420
|
sections.push(theme.fg("muted", "No matches found."));
|
|
36270
36421
|
return sections;
|
|
36271
36422
|
}
|
|
36272
|
-
const grouped = groupByFile(results, (result) =>
|
|
36423
|
+
const grouped = groupByFile(results, (result) => asString2(result.file));
|
|
36273
36424
|
for (const [file2, fileResults] of grouped.entries()) {
|
|
36274
|
-
const lines = [theme.fg("accent",
|
|
36425
|
+
const lines = [theme.fg("accent", shortenPath3(file2))];
|
|
36275
36426
|
fileResults.forEach((result) => {
|
|
36276
|
-
if (
|
|
36277
|
-
const line =
|
|
36278
|
-
const column =
|
|
36279
|
-
const lineText =
|
|
36427
|
+
if (asString2(result.kind) === "GrepLine") {
|
|
36428
|
+
const line = asNumber2(result.line);
|
|
36429
|
+
const column = asNumber2(result.column);
|
|
36430
|
+
const lineText = asString2(result.line_text) ?? "";
|
|
36280
36431
|
const location2 = line !== undefined ? `${line}${column !== undefined ? `:${column}` : ""}` : "?";
|
|
36281
36432
|
lines.push(` ↳ ${theme.fg("muted", `line ${location2}`)} ${lineText}`);
|
|
36282
36433
|
return;
|
|
36283
36434
|
}
|
|
36284
|
-
const score =
|
|
36285
|
-
const source =
|
|
36286
|
-
const kind =
|
|
36287
|
-
const location =
|
|
36435
|
+
const score = asNumber2(result.score);
|
|
36436
|
+
const source = asString2(result.source);
|
|
36437
|
+
const kind = asString2(result.kind) ?? "symbol";
|
|
36438
|
+
const location = asString2(result.location);
|
|
36288
36439
|
if (source === "lexical") {
|
|
36289
36440
|
lines.push(` ↳ ${theme.fg("muted", `[lexical match${score !== undefined ? ` — score ${score.toFixed(3)}` : ""}]`)}`);
|
|
36290
|
-
const snippet2 =
|
|
36441
|
+
const snippet2 = asString2(result.snippet);
|
|
36291
36442
|
if (snippet2) {
|
|
36292
36443
|
lines.push(...snippet2.split(`
|
|
36293
36444
|
`).map((line) => ` ${line}`));
|
|
@@ -36295,16 +36446,16 @@ function buildSemanticSections(args, payload, theme) {
|
|
|
36295
36446
|
return;
|
|
36296
36447
|
}
|
|
36297
36448
|
if (kind === "file_summary" || location === "[file summary]") {
|
|
36298
|
-
const summary =
|
|
36449
|
+
const summary = asString2(result.snippet) ?? asString2(result.name) ?? "(no summary)";
|
|
36299
36450
|
lines.push(` ↳ ${summary} ${theme.fg("muted", `[file summary${score !== undefined ? ` score ${score.toFixed(3)}` : ""}]`)}`);
|
|
36300
36451
|
return;
|
|
36301
36452
|
}
|
|
36302
|
-
const startLine =
|
|
36303
|
-
const endLine =
|
|
36453
|
+
const startLine = asNumber2(result.start_line);
|
|
36454
|
+
const endLine = asNumber2(result.end_line);
|
|
36304
36455
|
const range = startLine !== undefined ? `${startLine}${endLine && endLine !== startLine ? `-${endLine}` : ""}` : "?";
|
|
36305
|
-
const name =
|
|
36456
|
+
const name = asString2(result.name) ?? "(unknown)";
|
|
36306
36457
|
lines.push(` ↳ ${name} ${theme.fg("muted", `[${kind}] lines ${range}${score !== undefined ? ` score ${score.toFixed(3)}` : ""}`)}`);
|
|
36307
|
-
const snippet =
|
|
36458
|
+
const snippet = asString2(result.snippet);
|
|
36308
36459
|
if (snippet) {
|
|
36309
36460
|
lines.push(...snippet.split(`
|
|
36310
36461
|
`).map((line) => ` ${line}`));
|
|
@@ -36416,11 +36567,11 @@ function buildWorkflowHints(opts) {
|
|
|
36416
36567
|
}
|
|
36417
36568
|
if (hasBgBash) {
|
|
36418
36569
|
sections.push([
|
|
36419
|
-
`**Long-running commands** (builds, installs, full test suites): \`${bashName}({ background: true })\` returns a \`task_id\` immediately
|
|
36420
|
-
"1.
|
|
36421
|
-
"2.
|
|
36422
|
-
|
|
36423
|
-
|
|
36570
|
+
`**Long-running commands** (builds, installs, full test suites): \`${bashName}({ background: true })\` returns a \`task_id\` immediately.`,
|
|
36571
|
+
"1. Nothing else useful to do (a build/test/validation whose result is the next thing you need) → sync `bash_watch` to block until it exits (pass a longer timeout_ms for long commands; the user can interrupt).",
|
|
36572
|
+
"2. Useful parallel work available → end your turn; the completion reminder delivers the result. (Or spawn a subagent for the side work.)",
|
|
36573
|
+
"3. Want to react to a specific early output line → async `bash_watch` (background:true + pattern).",
|
|
36574
|
+
"Never loop `bash_status` to wait — it's a one-shot inspector, not a wait primitive."
|
|
36424
36575
|
].join(`
|
|
36425
36576
|
`));
|
|
36426
36577
|
sections.push(`**PTY / interactive commands**: PTY mode is for interactive REPLs and terminal apps (python, node, bash itself, vim). Start with \`${bashName}({ command: "python", pty: true, background: true })\`, read the screen with \`bash_status({ task_id, output_mode: "screen" })\`, and send input with \`bash_write({ task_id, input: "..." })\`.`);
|
|
@@ -36535,7 +36686,7 @@ function isConfigureWarning(value) {
|
|
|
36535
36686
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
36536
36687
|
return false;
|
|
36537
36688
|
const warning = value;
|
|
36538
|
-
return (warning.kind === "formatter_not_installed" || warning.kind === "checker_not_installed" || warning.kind === "lsp_binary_missing") && typeof warning.hint === "string";
|
|
36689
|
+
return (warning.kind === "formatter_not_installed" || warning.kind === "checker_not_installed" || warning.kind === "lsp_binary_missing" || warning.kind === "config_parse_failed") && typeof warning.hint === "string";
|
|
36539
36690
|
}
|
|
36540
36691
|
function coerceConfigureWarnings(warnings) {
|
|
36541
36692
|
return warnings.filter(isConfigureWarning);
|
|
@@ -36545,6 +36696,18 @@ function drainPendingEagerWarnings(projectRoot) {
|
|
|
36545
36696
|
pendingEagerWarnings.delete(projectRoot);
|
|
36546
36697
|
return pending;
|
|
36547
36698
|
}
|
|
36699
|
+
function enqueueConfigParseWarnings(projectRoot, errors3) {
|
|
36700
|
+
if (!projectRoot || errors3.length === 0)
|
|
36701
|
+
return;
|
|
36702
|
+
const pending = pendingEagerWarnings.get(projectRoot) ?? [];
|
|
36703
|
+
for (const entry of errors3) {
|
|
36704
|
+
const hint = formatConfigParseFailureMessage(entry.path, entry.message);
|
|
36705
|
+
if (!pending.some((item) => item.kind === "config_parse_failed" && item.hint === hint)) {
|
|
36706
|
+
pending.push({ kind: "config_parse_failed", hint });
|
|
36707
|
+
}
|
|
36708
|
+
}
|
|
36709
|
+
pendingEagerWarnings.set(projectRoot, pending);
|
|
36710
|
+
}
|
|
36548
36711
|
function shouldPrepareOnnxRuntime(config2) {
|
|
36549
36712
|
const isFastembedSemanticBackend = (config2.semantic?.backend ?? "fastembed") === "fastembed";
|
|
36550
36713
|
return config2.semantic_search === true && isFastembedSemanticBackend;
|
|
@@ -36653,6 +36816,7 @@ async function src_default(pi) {
|
|
|
36653
36816
|
}
|
|
36654
36817
|
await ensureStorageMigrated({ harness: "pi", binaryPath, logger: bridgeLogger });
|
|
36655
36818
|
const config2 = loadAftConfig(process.cwd());
|
|
36819
|
+
enqueueConfigParseWarnings(process.cwd(), getConfigLoadErrors());
|
|
36656
36820
|
const storageDir = resolveCortexKitStorageRoot();
|
|
36657
36821
|
let onnxRuntimePromise = null;
|
|
36658
36822
|
if (shouldPrepareOnnxRuntime(config2)) {
|
|
@@ -36661,30 +36825,7 @@ async function src_default(pi) {
|
|
|
36661
36825
|
return null;
|
|
36662
36826
|
});
|
|
36663
36827
|
}
|
|
36664
|
-
const configOverrides =
|
|
36665
|
-
if (config2.format_on_edit !== undefined)
|
|
36666
|
-
configOverrides.format_on_edit = config2.format_on_edit;
|
|
36667
|
-
if (config2.formatter_timeout_secs !== undefined)
|
|
36668
|
-
configOverrides.formatter_timeout_secs = config2.formatter_timeout_secs;
|
|
36669
|
-
if (config2.validate_on_edit !== undefined)
|
|
36670
|
-
configOverrides.validate_on_edit = config2.validate_on_edit;
|
|
36671
|
-
if (config2.formatter !== undefined)
|
|
36672
|
-
configOverrides.formatter = config2.formatter;
|
|
36673
|
-
if (config2.checker !== undefined)
|
|
36674
|
-
configOverrides.checker = config2.checker;
|
|
36675
|
-
configOverrides.restrict_to_project_root = config2.restrict_to_project_root ?? false;
|
|
36676
|
-
if (config2.search_index !== undefined)
|
|
36677
|
-
configOverrides.search_index = config2.search_index;
|
|
36678
|
-
if (config2.semantic_search !== undefined)
|
|
36679
|
-
configOverrides.semantic_search = config2.semantic_search;
|
|
36680
|
-
Object.assign(configOverrides, resolveExperimentalConfigForConfigure(config2));
|
|
36681
|
-
Object.assign(configOverrides, resolveLspConfigForConfigure(config2));
|
|
36682
|
-
if (config2.semantic !== undefined)
|
|
36683
|
-
configOverrides.semantic = config2.semantic;
|
|
36684
|
-
if (config2.inspect !== undefined)
|
|
36685
|
-
configOverrides.inspect = config2.inspect;
|
|
36686
|
-
if (config2.max_callgraph_files !== undefined)
|
|
36687
|
-
configOverrides.max_callgraph_files = config2.max_callgraph_files;
|
|
36828
|
+
const configOverrides = resolveProjectOverridesForConfigure(config2);
|
|
36688
36829
|
if (config2.url_fetch_allow_private !== undefined)
|
|
36689
36830
|
configOverrides.url_fetch_allow_private = config2.url_fetch_allow_private;
|
|
36690
36831
|
configOverrides.storage_dir = storageDir;
|
|
@@ -36892,12 +37033,25 @@ ${lines}
|
|
|
36892
37033
|
return { content, details: event.details, isError: event.isError };
|
|
36893
37034
|
});
|
|
36894
37035
|
pi.on("turn_end", async (_event, extCtx) => {
|
|
37036
|
+
const sessionID = resolveSessionId(extCtx);
|
|
36895
37037
|
await handleTurnEndBgCompletions({
|
|
36896
37038
|
ctx,
|
|
36897
37039
|
directory: extCtx.cwd,
|
|
36898
|
-
sessionID
|
|
37040
|
+
sessionID,
|
|
36899
37041
|
runtime: pi
|
|
36900
37042
|
});
|
|
37043
|
+
const bridge = pool.getActiveBridgeForRoot(extCtx.cwd);
|
|
37044
|
+
if (bridge && sessionID) {
|
|
37045
|
+
handleConfigureWarningsForSession({
|
|
37046
|
+
projectRoot: extCtx.cwd,
|
|
37047
|
+
sessionId: sessionID,
|
|
37048
|
+
client: pi,
|
|
37049
|
+
bridge,
|
|
37050
|
+
warnings: [],
|
|
37051
|
+
storageDir,
|
|
37052
|
+
pluginVersion: PLUGIN_VERSION
|
|
37053
|
+
});
|
|
37054
|
+
}
|
|
36901
37055
|
});
|
|
36902
37056
|
pi.on("input", (_event, extCtx) => {
|
|
36903
37057
|
signalSyncWatchAbort(resolveSessionId(extCtx));
|
|
@@ -36926,6 +37080,7 @@ ${lines}
|
|
|
36926
37080
|
log2(`AFT extension ready (surface=${config2.tool_surface ?? "recommended"})`);
|
|
36927
37081
|
}
|
|
36928
37082
|
var __test__2 = {
|
|
37083
|
+
enqueueConfigParseWarnings,
|
|
36929
37084
|
bridgeDirectoryFromCallback,
|
|
36930
37085
|
resolveToolSurface,
|
|
36931
37086
|
handleConfigureWarningsForSession,
|