@livx.cc/agentx 0.99.77 → 0.99.79
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/{Agent-BBlKI8uD.d.ts → Agent-BK-heHrw.d.ts} +4 -0
- package/dist/cli.d.ts +24 -2
- package/dist/cli.js +690 -248
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +27 -2
- package/dist/index.js +300 -50
- package/dist/index.js.map +1 -1
- package/dist/mcp.client.js +59 -2
- package/dist/mcp.client.js.map +1 -1
- package/dist/tools.shell.d.ts +23 -1
- package/dist/tools.shell.js +157 -19
- package/dist/tools.shell.js.map +1 -1
- package/package.json +4 -4
package/dist/tools.shell.js
CHANGED
|
@@ -28,6 +28,19 @@ function redactSecrets(text) {
|
|
|
28
28
|
return text.replace(SECRET_PAIR, (_m, head, quote, _val) => `${head}${quote}${REDACTED}`).replace(SECRET_TOKEN, REDACTED);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// src/hostPath.ts
|
|
32
|
+
var currentPlatform = () => typeof process !== "undefined" && process.platform || "browser";
|
|
33
|
+
var isWinPaths = (platform = currentPlatform()) => platform === "win32";
|
|
34
|
+
function toVfsPath(p, platform = currentPlatform()) {
|
|
35
|
+
if (!isWinPaths(platform) || typeof p !== "string") return p;
|
|
36
|
+
let s = p.replace(/\\/g, "/");
|
|
37
|
+
s = s.replace(/^\/\/\?\/UNC\//i, "//").replace(/^\/\/\?\//, "");
|
|
38
|
+
const drive = /^([A-Za-z]):(?=\/|$)/.exec(s);
|
|
39
|
+
if (drive) return `/${drive[1].toLowerCase()}${s.slice(2) || "/"}`.replace(/\/+$/, "") || "/";
|
|
40
|
+
if (/^\/\/[^/]/.test(s)) return `/unc/${s.slice(2)}`;
|
|
41
|
+
return s;
|
|
42
|
+
}
|
|
43
|
+
|
|
31
44
|
// src/tools.structured.ts
|
|
32
45
|
function ckAbort(signal) {
|
|
33
46
|
if (signal?.aborted) throw new Error("aborted");
|
|
@@ -72,7 +85,7 @@ async function walkFiles(fs, dir, signal, out = [], st, depth = 0) {
|
|
|
72
85
|
}
|
|
73
86
|
function scanRoots(fs, path, opts) {
|
|
74
87
|
const asked = path == null ? [] : (Array.isArray(path) ? path : [path]).map((p) => String(p)).filter(Boolean);
|
|
75
|
-
const roots = (asked.length ? asked : opts?.roots?.length ? opts.roots : [fsCwd(fs)]).map((r) => r.length > 1 && r.endsWith("/") ? r.slice(0, -1) : r);
|
|
88
|
+
const roots = (asked.length ? asked : opts?.roots?.length ? opts.roots : [fsCwd(fs)]).map((r) => toVfsPath(r)).map((r) => r.length > 1 && r.endsWith("/") ? r.slice(0, -1) : r);
|
|
76
89
|
return [...new Set(roots)].filter((r, _i, all) => !all.some((other) => other !== r && r.startsWith(`${other}/`)));
|
|
77
90
|
}
|
|
78
91
|
function scanNote(states) {
|
|
@@ -866,21 +879,130 @@ var JobRegistry = class {
|
|
|
866
879
|
}
|
|
867
880
|
};
|
|
868
881
|
|
|
869
|
-
// src/
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
882
|
+
// src/platform.ts
|
|
883
|
+
import { spawnSync, execFile } from "child_process";
|
|
884
|
+
import { statSync as statSync3 } from "fs";
|
|
885
|
+
import * as np from "path";
|
|
886
|
+
var IS_WIN = process.platform === "win32";
|
|
887
|
+
var POSIX_SH = { bin: "/bin/sh", args: (c) => ["-c", c], label: "/bin/sh", kind: "sh" };
|
|
888
|
+
function specFor(bin) {
|
|
889
|
+
const name = np.basename(bin).toLowerCase().replace(/\.exe$/, "");
|
|
890
|
+
if (name === "powershell" || name === "pwsh") {
|
|
891
|
+
const pre = "$ProgressPreference='SilentlyContinue';[Console]::OutputEncoding=[Text.Encoding]::UTF8;$OutputEncoding=[Text.Encoding]::UTF8;";
|
|
892
|
+
return {
|
|
893
|
+
bin,
|
|
894
|
+
kind: "powershell",
|
|
895
|
+
label: name === "pwsh" ? "PowerShell (pwsh)" : "Windows PowerShell",
|
|
896
|
+
args: (c) => ["-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-EncodedCommand", Buffer.from(pre + c, "utf16le").toString("base64")]
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
if (name === "cmd") return { bin, kind: "cmd", label: "cmd.exe", args: (c) => ["/d", "/s", "/c", `"${c}"`], spawnOptions: { windowsVerbatimArguments: true } };
|
|
900
|
+
return { bin, kind: "sh", label: /bash/.test(name) && /git/i.test(bin) ? "Git Bash" : name, args: (c) => ["-c", c] };
|
|
901
|
+
}
|
|
902
|
+
var isFile = (p) => {
|
|
875
903
|
try {
|
|
876
|
-
|
|
877
|
-
return true;
|
|
904
|
+
return statSync3(p).isFile();
|
|
878
905
|
} catch {
|
|
879
906
|
return false;
|
|
880
907
|
}
|
|
908
|
+
};
|
|
909
|
+
function findGitBash(env = process.env) {
|
|
910
|
+
const roots = [];
|
|
911
|
+
const git = findOnPath("git", env);
|
|
912
|
+
if (git) {
|
|
913
|
+
const dir = np.dirname(git);
|
|
914
|
+
const up = (p, n) => {
|
|
915
|
+
for (let i = 0; i < n; i++) p = np.dirname(p);
|
|
916
|
+
return p;
|
|
917
|
+
};
|
|
918
|
+
roots.push(/[\\/](mingw(32|64)|ucrt64|clang(32|64|arm64))[\\/]bin$/i.test(dir) ? up(dir, 2) : up(dir, 1));
|
|
919
|
+
}
|
|
920
|
+
for (const base of [env.ProgramFiles, env["ProgramFiles(x86)"], env.ProgramW6432, env.LOCALAPPDATA && np.join(env.LOCALAPPDATA, "Programs")])
|
|
921
|
+
if (base) roots.push(np.join(base, "Git"));
|
|
922
|
+
for (const r of roots) {
|
|
923
|
+
const b = np.join(r, "bin", "bash.exe");
|
|
924
|
+
if (isFile(b)) return b;
|
|
925
|
+
}
|
|
926
|
+
return void 0;
|
|
881
927
|
}
|
|
928
|
+
var _shell;
|
|
929
|
+
function defaultShell() {
|
|
930
|
+
if (!IS_WIN) return POSIX_SH;
|
|
931
|
+
if (_shell) return _shell;
|
|
932
|
+
const override = process.env.AGENTX_SHELL;
|
|
933
|
+
if (override && (isFile(override) || findOnPath(override))) return _shell = specFor(isFile(override) ? override : findOnPath(override));
|
|
934
|
+
const bash = findGitBash();
|
|
935
|
+
if (bash) return _shell = specFor(bash);
|
|
936
|
+
const sysRoot = process.env.SystemRoot || "C:\\Windows";
|
|
937
|
+
const ps = np.join(sysRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
|
|
938
|
+
if (isFile(ps)) return _shell = specFor(ps);
|
|
939
|
+
return _shell = specFor(process.env.ComSpec || "cmd.exe");
|
|
940
|
+
}
|
|
941
|
+
function shellFor(shell) {
|
|
942
|
+
if (!IS_WIN) return shell ? { ...POSIX_SH, bin: shell } : POSIX_SH;
|
|
943
|
+
return shell && isFile(shell) ? specFor(shell) : defaultShell();
|
|
944
|
+
}
|
|
945
|
+
var DETACH_OPTIONS = IS_WIN ? { windowsHide: true } : { detached: true };
|
|
946
|
+
function killTree(pid, signal) {
|
|
947
|
+
if (!pid) return false;
|
|
948
|
+
if (!IS_WIN) {
|
|
949
|
+
try {
|
|
950
|
+
process.kill(-pid, signal);
|
|
951
|
+
return true;
|
|
952
|
+
} catch {
|
|
953
|
+
return false;
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
try {
|
|
957
|
+
const r = spawnSync("taskkill", ["/PID", String(pid), "/T", "/F"], { windowsHide: true, stdio: "ignore", timeout: 1e4 });
|
|
958
|
+
return r.status === 0;
|
|
959
|
+
} catch {
|
|
960
|
+
return false;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
async function winTreeCpuSeconds(root) {
|
|
964
|
+
const script = 'Get-CimInstance Win32_Process | ForEach-Object { "$($_.ProcessId) $($_.ParentProcessId) $([uint64]$_.UserModeTime + [uint64]$_.KernelModeTime)" }';
|
|
965
|
+
const out = await new Promise((res, rej) => execFile(
|
|
966
|
+
"powershell.exe",
|
|
967
|
+
["-NoProfile", "-NonInteractive", "-Command", script],
|
|
968
|
+
{ timeout: 15e3, windowsHide: true },
|
|
969
|
+
(e, so) => e ? rej(e) : res(String(so))
|
|
970
|
+
));
|
|
971
|
+
const rows = out.split(/\r?\n/).map((l) => l.trim().split(/\s+/)).filter((r) => r.length === 3).map(([pid, ppid, ticks]) => ({ pid: Number(pid), ppid: Number(ppid), sec: Number(ticks) / 1e7 }));
|
|
972
|
+
const inTree = new Set(rows.filter((r) => r.pid === root).map((r) => r.pid));
|
|
973
|
+
for (let grew = true; grew; ) {
|
|
974
|
+
grew = false;
|
|
975
|
+
for (const r of rows) if (!inTree.has(r.pid) && inTree.has(r.ppid) && r.pid !== r.ppid) {
|
|
976
|
+
inTree.add(r.pid);
|
|
977
|
+
grew = true;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
let total;
|
|
981
|
+
for (const r of rows) if (inTree.has(r.pid) && Number.isFinite(r.sec)) total = (total ?? 0) + r.sec;
|
|
982
|
+
return total;
|
|
983
|
+
}
|
|
984
|
+
function findOnPath(cmd, env = process.env) {
|
|
985
|
+
const exts = IS_WIN && !/\.[^\\/.]+$/.test(cmd) ? (env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean) : [""];
|
|
986
|
+
const cands = (base) => exts.map((e) => base + e);
|
|
987
|
+
if (/[\\/]/.test(cmd)) return cands(cmd).find(isFile);
|
|
988
|
+
const PATH = env.PATH ?? env.Path ?? "";
|
|
989
|
+
for (const dir of PATH.split(np.delimiter)) {
|
|
990
|
+
if (!dir) continue;
|
|
991
|
+
for (const p of cands(np.join(dir, cmd))) if (isFile(p)) return p;
|
|
992
|
+
}
|
|
993
|
+
return void 0;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
// src/tools.shell.ts
|
|
997
|
+
var log7 = forComponent("shell");
|
|
998
|
+
var clean = (s) => truncateOutput(redactSecrets(s.replace(/\n+$/, "")));
|
|
999
|
+
var DETACHED = { stdio: ["ignore", "pipe", "pipe"], ...DETACH_OPTIONS };
|
|
1000
|
+
function killGroup(proc, signal) {
|
|
1001
|
+
return killTree(proc?.pid, signal);
|
|
1002
|
+
}
|
|
1003
|
+
var shellArgv = (sh, command) => ({ bin: sh.bin, args: sh.args(command), ...sh.spawnOptions ? { spawnOptions: sh.spawnOptions } : {} });
|
|
882
1004
|
async function spawnArgvFor(command, cwd, osSandbox) {
|
|
883
|
-
if (!osSandbox) return
|
|
1005
|
+
if (!osSandbox) return shellArgv(defaultShell(), command);
|
|
884
1006
|
const opts = osSandbox === true ? {} : osSandbox;
|
|
885
1007
|
const wrapper = await findSandboxWrapper();
|
|
886
1008
|
const wrapped = wrapper ? sandboxArgv(command, cwd, opts, process.platform, process.env.TMPDIR) : null;
|
|
@@ -910,9 +1032,17 @@ function parsePsTime(t) {
|
|
|
910
1032
|
return Number(m[1] ?? 0) * 86400 + Number(m[2] ?? 0) * 3600 + Number(m[3]) * 60 + Number(m[4]);
|
|
911
1033
|
}
|
|
912
1034
|
async function psGroupCpuSeconds(pgid) {
|
|
1035
|
+
if (IS_WIN) {
|
|
1036
|
+
try {
|
|
1037
|
+
return await winTreeCpuSeconds(pgid);
|
|
1038
|
+
} catch (e) {
|
|
1039
|
+
log7.debug(`cpu probe failed for ${pgid}: ${e}`);
|
|
1040
|
+
return void 0;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
913
1043
|
try {
|
|
914
|
-
const { execFile } = await import("child_process");
|
|
915
|
-
const out = await new Promise((res, rej) =>
|
|
1044
|
+
const { execFile: execFile2 } = await import("child_process");
|
|
1045
|
+
const out = await new Promise((res, rej) => execFile2("ps", ["-A", "-o", "pid=,ppid=,pgid=,time="], { timeout: 5e3, env: { ...process.env, LC_ALL: "C" } }, (e, so) => e ? rej(e) : res(String(so))));
|
|
916
1046
|
return sumTreeCpu(out, pgid);
|
|
917
1047
|
} catch (e) {
|
|
918
1048
|
log7.debug(`ps cpu probe failed for group ${pgid}: ${e}`);
|
|
@@ -946,8 +1076,8 @@ var ShellJobRegistry = class {
|
|
|
946
1076
|
const h = this.track(command, { idleMs: 0 });
|
|
947
1077
|
try {
|
|
948
1078
|
const spawn = this.cfg.spawn ?? await nodeSpawn();
|
|
949
|
-
const argv = this.cfg.osSandbox ? await spawnArgvFor(command, this.cfg.cwd, this.cfg.osSandbox) :
|
|
950
|
-
this.attach(h, spawn(argv.bin, argv.args, { cwd: this.cfg.cwd, env: childEnv(this.cfg), ...DETACHED }));
|
|
1079
|
+
const argv = this.cfg.osSandbox ? await spawnArgvFor(command, this.cfg.cwd, this.cfg.osSandbox) : shellArgv(defaultShell(), command);
|
|
1080
|
+
this.attach(h, spawn(argv.bin, argv.args, { cwd: this.cfg.cwd, env: childEnv(this.cfg), ...DETACHED, ...argv.spawnOptions }));
|
|
951
1081
|
} catch (e) {
|
|
952
1082
|
h.chunk(`failed to spawn: ${e?.message ?? e}`);
|
|
953
1083
|
h.finish("error", void 0, e?.message ?? String(e));
|
|
@@ -1101,7 +1231,7 @@ function makeRealShellTool(options) {
|
|
|
1101
1231
|
return { ...this, description: rebound.description, run: rebound.run, withCwd: rebound.withCwd };
|
|
1102
1232
|
},
|
|
1103
1233
|
get description() {
|
|
1104
|
-
return
|
|
1234
|
+
return `Run a shell command via ${shellFor(options.shell).label} in the working directory. ` + windowsShellNote(shellFor(options.shell)) + "Executes any installed binary \u2014 ls, cat, grep, git, bun, node, curl, scripts, etc. Returns combined stdout+stderr; non-zero exits are prefixed `[exit N]`. Runs non-interactively with no terminal (stdin is /dev/null): commands that prompt for input fail fast rather than hang \u2014 for privileged actions use a non-interactive flag (e.g. `sudo -n`), or ask the user to run the command themselves. " + (options.registry?.adopt ? `A command still running after ${defaultTimeoutMs}ms is NOT killed \u2014 it is handed to a background job and you get its id, so you can keep checking on it (\`[still running]\`). Pass \`timeoutMs\` (max ${maxTimeoutMs}) to wait longer in the foreground, and always bound network commands yourself (e.g. \`curl -m 10\`). ` : `Each command is killed after ${defaultTimeoutMs}ms (result \`[exit 124]\` with whatever output it produced) \u2014 pass \`timeoutMs\` (max ${maxTimeoutMs}) for a legitimately slower command, and always bound network commands yourself (e.g. \`curl -m 10\`). `) + backgroundDoc();
|
|
1105
1235
|
},
|
|
1106
1236
|
// Declared so transports above the agent loop can size their own deadline with headroom (see AgentTool.maxDurationMs).
|
|
1107
1237
|
maxDurationMs: maxTimeoutMs,
|
|
@@ -1125,7 +1255,7 @@ function makeRealShellTool(options) {
|
|
|
1125
1255
|
return `Started background job ${id}. Poll output with ShellOutput({id:"${id}"}), check ShellStatus({id:"${id}"}), stop with ShellKill({id:"${id}"}).`;
|
|
1126
1256
|
}
|
|
1127
1257
|
const spawn = options.spawn ?? await nodeSpawn();
|
|
1128
|
-
let argv =
|
|
1258
|
+
let argv = shellArgv(shellFor(options.shell), cmd);
|
|
1129
1259
|
if (options.osSandbox) {
|
|
1130
1260
|
try {
|
|
1131
1261
|
argv = await spawnArgvFor(cmd, options.cwd, options.osSandbox);
|
|
@@ -1170,12 +1300,13 @@ function makeRealShellTool(options) {
|
|
|
1170
1300
|
};
|
|
1171
1301
|
let proc;
|
|
1172
1302
|
try {
|
|
1173
|
-
|
|
1303
|
+
if (IS_WIN) ctl.signal.addEventListener("abort", () => killGroup(proc, "SIGKILL"), { once: true });
|
|
1304
|
+
proc = spawn(argv.bin, argv.args, { cwd: options.cwd, env: childEnv(options), signal: ctl.signal, ...DETACHED, ...argv.spawnOptions });
|
|
1174
1305
|
} catch (e) {
|
|
1175
1306
|
return finish(`[exit 1] failed to spawn shell: ${e?.message ?? e}`);
|
|
1176
1307
|
}
|
|
1177
1308
|
if (ctl.signal.aborted) killGroup(proc, "SIGKILL");
|
|
1178
|
-
else ctl.signal.addEventListener("abort", () => killGroup(proc, "SIGKILL"), { once: true });
|
|
1309
|
+
else if (!IS_WIN) ctl.signal.addEventListener("abort", () => killGroup(proc, "SIGKILL"), { once: true });
|
|
1179
1310
|
const registry = options.registry;
|
|
1180
1311
|
if (registry?.adopt) {
|
|
1181
1312
|
onDeadline = () => {
|
|
@@ -1220,6 +1351,12 @@ function makeRealShellTool(options) {
|
|
|
1220
1351
|
}
|
|
1221
1352
|
};
|
|
1222
1353
|
}
|
|
1354
|
+
function windowsShellNote(sh) {
|
|
1355
|
+
if (!IS_WIN) return "";
|
|
1356
|
+
if (sh.kind === "sh") return "This is Windows: the shell is bash (POSIX syntax); drive paths are written /c/Users/\u2026 or C:/Users/\u2026, and Windows programs (.exe/.cmd) run directly. ";
|
|
1357
|
+
if (sh.kind === "powershell") return "This is Windows and the shell is PowerShell \u2014 use PowerShell syntax (`;` not `&&`, `$env:VAR`, Get-ChildItem/Select-String), not bash. ";
|
|
1358
|
+
return "This is Windows and the shell is cmd.exe \u2014 use cmd syntax (`&&`, `%VAR%`, dir/type/findstr), not bash. ";
|
|
1359
|
+
}
|
|
1223
1360
|
function handoffFor(timeoutMs, id, body, notifies) {
|
|
1224
1361
|
const head = `[still running] exceeded ${timeoutMs}ms, so it was handed to background job ${id} \u2014 NOT killed, it is still going (it is only stopped if it goes silent with no CPU activity for a long time, and then you are told why). Check on it with ShellOutput({id:"${id}"}) / ShellStatus({id:"${id}"}), stop it with ShellKill({id:"${id}"}). ` + (notifies ? "Its completion will be reported to you, so you may continue with other work meanwhile." : "Nothing will tell you when it finishes \u2014 poll it yourself before you rely on its result.");
|
|
1225
1362
|
return body ? `${head}
|
|
@@ -1282,6 +1419,7 @@ export {
|
|
|
1282
1419
|
makeShellJobTools,
|
|
1283
1420
|
parsePsTime,
|
|
1284
1421
|
psGroupCpuSeconds,
|
|
1285
|
-
sumTreeCpu
|
|
1422
|
+
sumTreeCpu,
|
|
1423
|
+
windowsShellNote
|
|
1286
1424
|
};
|
|
1287
1425
|
//# sourceMappingURL=tools.shell.js.map
|