reasonix 0.43.0 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -11
- package/README.zh-CN.md +35 -7
- package/dashboard/app.css +225 -4
- package/dashboard/dist/app.js +6441 -6080
- package/dashboard/dist/app.js.map +1 -1
- package/data/deepseek-tokenizer.json.gz +0 -0
- package/dist/cli/{acp-DAGPCVFZ.js → acp-TYZ2CTDL.js} +28 -30
- package/dist/cli/acp-TYZ2CTDL.js.map +1 -0
- package/dist/cli/chat-TH7VNNCJ.js +51 -0
- package/dist/cli/chunk-2425HK6U.js +0 -0
- package/dist/cli/chunk-25T6CVUP.js +0 -0
- package/dist/cli/chunk-2UQP6H6T.js +0 -0
- package/dist/cli/{chunk-3Z6IBU3D.js → chunk-2V6EAEUW.js} +95 -31
- package/dist/cli/chunk-2V6EAEUW.js.map +1 -0
- package/dist/cli/{chunk-XCGGEJTI.js → chunk-4CTDEJUF.js} +2 -2
- package/dist/cli/chunk-4QUNBQQ2.js +0 -0
- package/dist/cli/{chunk-74EX7SUH.js → chunk-5QCB62C4.js} +33 -7
- package/dist/cli/{chunk-74EX7SUH.js.map → chunk-5QCB62C4.js.map} +1 -1
- package/dist/cli/chunk-6OWJV3YW.js +390 -0
- package/dist/cli/chunk-6OWJV3YW.js.map +1 -0
- package/dist/cli/chunk-6PBZN4VI.js +0 -0
- package/dist/cli/{chunk-7O5ALB4C.js → chunk-7CIGMZT3.js} +2 -2
- package/dist/cli/{chunk-H6PS7IUE.js → chunk-7UCMM425.js} +7 -3
- package/dist/cli/chunk-7UCMM425.js.map +1 -0
- package/dist/cli/{chunk-TJX6BFZZ.js → chunk-AB2RED3C.js} +3 -3
- package/dist/cli/{chunk-XPDVG52A.js → chunk-AVFXO2EZ.js} +361 -13
- package/dist/cli/chunk-AVFXO2EZ.js.map +1 -0
- package/dist/cli/{chunk-FHOGSSCH.js → chunk-C53JQES5.js} +3 -3
- package/dist/cli/{chunk-RE4RAVFF.js → chunk-CGDR2ELH.js} +92 -30
- package/dist/cli/chunk-CGDR2ELH.js.map +1 -0
- package/dist/cli/{chunk-OSZC7C6F.js → chunk-CWZKQ5FE.js} +7 -4
- package/dist/cli/chunk-CWZKQ5FE.js.map +1 -0
- package/dist/cli/{devtools-YECO25QO.js → chunk-FEZK652I.js} +10 -85
- package/dist/cli/chunk-FEZK652I.js.map +1 -0
- package/dist/cli/{chunk-45U62RI3.js → chunk-HNXDZGC6.js} +104 -2
- package/dist/cli/chunk-HNXDZGC6.js.map +1 -0
- package/dist/cli/chunk-J5XJHLWM.js +0 -0
- package/dist/cli/chunk-JMBMLOBP.js +0 -0
- package/dist/cli/{chunk-5JJRUIPA.js → chunk-JNAQYELD.js} +16 -8
- package/dist/cli/{chunk-5JJRUIPA.js.map → chunk-JNAQYELD.js.map} +1 -1
- package/dist/cli/{chunk-YFGF5NKA.js → chunk-KGBG6M2X.js} +19 -15
- package/dist/cli/chunk-KGBG6M2X.js.map +1 -0
- package/dist/cli/{chunk-3BXRZFWS.js → chunk-KLQTAZIY.js} +12 -4
- package/dist/cli/chunk-KLQTAZIY.js.map +1 -0
- package/dist/cli/{chunk-VK5HG73G.js → chunk-KM465GST.js} +9 -9
- package/dist/cli/{chunk-DOYHN4KB.js → chunk-LIR2HBQH.js} +2 -2
- package/dist/cli/{chunk-YYQAUTTN.js → chunk-MJ6W5UN3.js} +2 -2
- package/dist/cli/{chunk-6PZ3CXBP.js → chunk-MRHHQJAQ.js} +5 -4
- package/dist/cli/chunk-MRHHQJAQ.js.map +1 -0
- package/dist/cli/{chunk-PQXPXJBJ.js → chunk-NVURFF27.js} +16 -5
- package/dist/cli/chunk-NVURFF27.js.map +1 -0
- package/dist/cli/{chunk-2R4QCDOZ.js → chunk-OPFUUYHL.js} +540 -287
- package/dist/cli/chunk-OPFUUYHL.js.map +1 -0
- package/dist/cli/chunk-PLHAZOLZ.js +0 -0
- package/dist/cli/{chunk-HFEAY5DT.js → chunk-R3CTO2HM.js} +2 -2
- package/dist/cli/{chunk-O52OLQL3.js → chunk-RDRC3XDT.js} +136 -38
- package/dist/cli/chunk-RDRC3XDT.js.map +1 -0
- package/dist/cli/chunk-S4XVGLRW.js +0 -0
- package/dist/cli/chunk-SZ5XES2N.js +0 -0
- package/dist/cli/{chunk-2K65GZBT.js → chunk-TEUDEGX2.js} +64 -19
- package/dist/cli/chunk-TEUDEGX2.js.map +1 -0
- package/dist/cli/{chunk-2Z35JOA4.js → chunk-TKVXTQ3T.js} +4 -4
- package/dist/cli/{chunk-2Z35JOA4.js.map → chunk-TKVXTQ3T.js.map} +1 -1
- package/dist/cli/chunk-TUK7OWJA.js +0 -0
- package/dist/cli/{chunk-32TIKD5U.js → chunk-TXJMRPIL.js} +3 -3
- package/dist/cli/{chunk-2KDUS647.js → chunk-V26WPN3J.js} +7 -4
- package/dist/cli/chunk-V26WPN3J.js.map +1 -0
- package/dist/cli/{chunk-F3PXYSNN.js → chunk-WK3UFQY3.js} +2 -2
- package/dist/cli/{chunk-6G3CUUFG.js → chunk-X53B3JIX.js} +3 -3
- package/dist/cli/{chunk-6G3CUUFG.js.map → chunk-X53B3JIX.js.map} +1 -1
- package/dist/cli/chunk-XJXDHAES.js +0 -0
- package/dist/cli/{chunk-6AK4EY3D.js → chunk-XSU4QVFW.js} +1 -81
- package/dist/cli/chunk-XSU4QVFW.js.map +1 -0
- package/dist/cli/chunk-XXC2BYTV.js +0 -0
- package/dist/cli/{chunk-P7EKE5ZQ.js → chunk-Z4S7EYXG.js} +4482 -1310
- package/dist/cli/chunk-Z4S7EYXG.js.map +1 -0
- package/dist/cli/chunk-ZZM6QJ4W.js +0 -0
- package/dist/cli/{chunk-YQ6NTIIE.js → chunk-ZZYBBX5N.js} +13 -5
- package/dist/cli/chunk-ZZYBBX5N.js.map +1 -0
- package/dist/cli/{code-SMKEW6CD.js → code-PSVJ3KEN.js} +48 -36
- package/dist/cli/code-PSVJ3KEN.js.map +1 -0
- package/dist/cli/{commands-FVVB5FZF.js → commands-OCU42XG4.js} +4 -4
- package/dist/cli/{commit-HE4VSPZ7.js → commit-XCQIQCYG.js} +3 -3
- package/dist/cli/{desktop-Q7NDXCON.js → desktop-KWGR4BNE.js} +210 -69
- package/dist/cli/desktop-KWGR4BNE.js.map +1 -0
- package/dist/cli/devtools-HW3WDT3Q.js +91 -0
- package/dist/cli/devtools-HW3WDT3Q.js.map +1 -0
- package/dist/cli/{diff-435UTPC5.js → diff-NHANTNC3.js} +9 -9
- package/dist/cli/{doctor-OT7KH75K.js → doctor-CC5CLOGG.js} +10 -10
- package/dist/cli/events-XEFAD5VX.js +0 -0
- package/dist/cli/index.js +132 -94
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-WUL2WO75.js → mcp-MPVGBBJF.js} +2 -2
- package/dist/cli/{mcp-browse-RR7R4XET.js → mcp-browse-4XOTC3FJ.js} +3 -3
- package/dist/cli/{mcp-inspect-REGLYBWT.js → mcp-inspect-CEMGKKAH.js} +14 -9
- package/dist/cli/mcp-inspect-CEMGKKAH.js.map +1 -0
- package/dist/cli/{prompt-UW6EFLVR.js → prompt-2D7ID24X.js} +4 -4
- package/dist/cli/prune-sessions-3RWUBYRS.js +0 -0
- package/dist/cli/{replay-YOURXV4C.js → replay-SR44E6RS.js} +10 -10
- package/dist/cli/{run-Q6BUXV66.js → run-MDGL27WL.js} +35 -36
- package/dist/cli/run-MDGL27WL.js.map +1 -0
- package/dist/cli/{server-XGDBRWMB.js → server-27ARQXIZ.js} +67 -24
- package/dist/cli/server-27ARQXIZ.js.map +1 -0
- package/dist/cli/{sessions-FH7QVYSY.js → sessions-CKQXCYGP.js} +18 -18
- package/dist/cli/sessions-CKQXCYGP.js.map +1 -0
- package/dist/cli/{setup-VDS6SVEP.js → setup-TPAGSVXO.js} +6 -6
- package/dist/cli/{stats-MQVI2XQH.js → stats-DPUBZNVX.js} +6 -4
- package/dist/cli/update-6ITLPRDV.js +0 -0
- package/dist/cli/{version-DAHGZY5N.js → version-2X3BHVVK.js} +15 -15
- package/dist/index.d.ts +181 -53
- package/dist/index.js +1322 -533
- package/dist/index.js.map +1 -1
- package/package.json +21 -8
- package/dist/cli/.-3G6VX5S7.js +0 -327
- package/dist/cli/.-6YRPB2C7.js +0 -329
- package/dist/cli/.-EYSVINK3.js +0 -317
- package/dist/cli/acp-DAGPCVFZ.js.map +0 -1
- package/dist/cli/chat-7ES4IBNH.js +0 -50
- package/dist/cli/chunk-2K65GZBT.js.map +0 -1
- package/dist/cli/chunk-2KDUS647.js.map +0 -1
- package/dist/cli/chunk-2R4QCDOZ.js.map +0 -1
- package/dist/cli/chunk-3BXRZFWS.js.map +0 -1
- package/dist/cli/chunk-3Z6IBU3D.js.map +0 -1
- package/dist/cli/chunk-45U62RI3.js.map +0 -1
- package/dist/cli/chunk-6AK4EY3D.js.map +0 -1
- package/dist/cli/chunk-6PZ3CXBP.js.map +0 -1
- package/dist/cli/chunk-H6PS7IUE.js.map +0 -1
- package/dist/cli/chunk-O52OLQL3.js.map +0 -1
- package/dist/cli/chunk-OSZC7C6F.js.map +0 -1
- package/dist/cli/chunk-P7EKE5ZQ.js.map +0 -1
- package/dist/cli/chunk-PQXPXJBJ.js.map +0 -1
- package/dist/cli/chunk-PV55UMTO.js +0 -200
- package/dist/cli/chunk-PV55UMTO.js.map +0 -1
- package/dist/cli/chunk-RE4RAVFF.js.map +0 -1
- package/dist/cli/chunk-XPDVG52A.js.map +0 -1
- package/dist/cli/chunk-YFGF5NKA.js.map +0 -1
- package/dist/cli/chunk-YQ6NTIIE.js.map +0 -1
- package/dist/cli/code-SMKEW6CD.js.map +0 -1
- package/dist/cli/desktop-Q7NDXCON.js.map +0 -1
- package/dist/cli/devtools-YECO25QO.js.map +0 -1
- package/dist/cli/doctor-OT7KH75K.js.map +0 -1
- package/dist/cli/mcp-inspect-REGLYBWT.js.map +0 -1
- package/dist/cli/prompt-UW6EFLVR.js.map +0 -1
- package/dist/cli/run-Q6BUXV66.js.map +0 -1
- package/dist/cli/server-XGDBRWMB.js.map +0 -1
- package/dist/cli/sessions-FH7QVYSY.js.map +0 -1
- package/dist/cli/stats-MQVI2XQH.js.map +0 -1
- /package/dist/cli/{.-3G6VX5S7.js.map → chat-TH7VNNCJ.js.map} +0 -0
- /package/dist/cli/{chunk-XCGGEJTI.js.map → chunk-4CTDEJUF.js.map} +0 -0
- /package/dist/cli/{chunk-7O5ALB4C.js.map → chunk-7CIGMZT3.js.map} +0 -0
- /package/dist/cli/{chunk-TJX6BFZZ.js.map → chunk-AB2RED3C.js.map} +0 -0
- /package/dist/cli/{chunk-FHOGSSCH.js.map → chunk-C53JQES5.js.map} +0 -0
- /package/dist/cli/{chunk-VK5HG73G.js.map → chunk-KM465GST.js.map} +0 -0
- /package/dist/cli/{chunk-DOYHN4KB.js.map → chunk-LIR2HBQH.js.map} +0 -0
- /package/dist/cli/{chunk-YYQAUTTN.js.map → chunk-MJ6W5UN3.js.map} +0 -0
- /package/dist/cli/{chunk-HFEAY5DT.js.map → chunk-R3CTO2HM.js.map} +0 -0
- /package/dist/cli/{chunk-32TIKD5U.js.map → chunk-TXJMRPIL.js.map} +0 -0
- /package/dist/cli/{chunk-F3PXYSNN.js.map → chunk-WK3UFQY3.js.map} +0 -0
- /package/dist/cli/{commands-FVVB5FZF.js.map → commands-OCU42XG4.js.map} +0 -0
- /package/dist/cli/{commit-HE4VSPZ7.js.map → commit-XCQIQCYG.js.map} +0 -0
- /package/dist/cli/{diff-435UTPC5.js.map → diff-NHANTNC3.js.map} +0 -0
- /package/dist/cli/{.-6YRPB2C7.js.map → doctor-CC5CLOGG.js.map} +0 -0
- /package/dist/cli/{mcp-WUL2WO75.js.map → mcp-MPVGBBJF.js.map} +0 -0
- /package/dist/cli/{mcp-browse-RR7R4XET.js.map → mcp-browse-4XOTC3FJ.js.map} +0 -0
- /package/dist/cli/{.-EYSVINK3.js.map → prompt-2D7ID24X.js.map} +0 -0
- /package/dist/cli/{replay-YOURXV4C.js.map → replay-SR44E6RS.js.map} +0 -0
- /package/dist/cli/{setup-VDS6SVEP.js.map → setup-TPAGSVXO.js.map} +0 -0
- /package/dist/cli/{chat-7ES4IBNH.js.map → stats-DPUBZNVX.js.map} +0 -0
- /package/dist/cli/{version-DAHGZY5N.js.map → version-2X3BHVVK.js.map} +0 -0
|
File without changes
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
cacheSavingsUsd,
|
|
5
5
|
claudeEquivalentCost,
|
|
6
6
|
costUsd
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZZYBBX5N.js";
|
|
8
8
|
|
|
9
9
|
// src/telemetry/usage.ts
|
|
10
10
|
import {
|
|
@@ -229,4 +229,4 @@ export {
|
|
|
229
229
|
aggregateUsage,
|
|
230
230
|
formatLogSize
|
|
231
231
|
};
|
|
232
|
-
//# sourceMappingURL=chunk-
|
|
232
|
+
//# sourceMappingURL=chunk-R3CTO2HM.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
|
|
3
3
|
import {
|
|
4
4
|
addProjectShellAllowed
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AVFXO2EZ.js";
|
|
6
6
|
|
|
7
7
|
// src/core/pause-gate.ts
|
|
8
8
|
var PauseGate = class {
|
|
@@ -19,10 +19,10 @@ var PauseGate = class {
|
|
|
19
19
|
`${kind}: no confirmation listener registered \u2014 cannot prompt the user. This tool can only be used inside an interactive Reasonix session.`
|
|
20
20
|
);
|
|
21
21
|
}
|
|
22
|
-
return new Promise((
|
|
22
|
+
return new Promise((resolve5) => {
|
|
23
23
|
const id = this._nextId++;
|
|
24
24
|
const request = { id, kind, payload };
|
|
25
|
-
this._pending.set(id, { resolve:
|
|
25
|
+
this._pending.set(id, { resolve: resolve5, request });
|
|
26
26
|
for (const fn of this._listeners) {
|
|
27
27
|
try {
|
|
28
28
|
fn(request);
|
|
@@ -130,15 +130,15 @@ var pauseGate = new PauseGate();
|
|
|
130
130
|
|
|
131
131
|
// src/tools/jobs.ts
|
|
132
132
|
import { spawn as spawn3 } from "child_process";
|
|
133
|
-
import * as
|
|
133
|
+
import * as pathMod5 from "path";
|
|
134
134
|
|
|
135
135
|
// src/tools/shell.ts
|
|
136
|
-
import * as
|
|
136
|
+
import * as pathMod4 from "path";
|
|
137
137
|
|
|
138
138
|
// src/tools/shell/exec.ts
|
|
139
139
|
import { spawn as spawn2, spawnSync } from "child_process";
|
|
140
140
|
import { existsSync, statSync } from "fs";
|
|
141
|
-
import * as
|
|
141
|
+
import * as pathMod3 from "path";
|
|
142
142
|
|
|
143
143
|
// src/tools/shell-chain.ts
|
|
144
144
|
import { spawn } from "child_process";
|
|
@@ -471,6 +471,10 @@ async function runPipeGroup(segments, opts) {
|
|
|
471
471
|
cwd: opts.cwd,
|
|
472
472
|
shell: false,
|
|
473
473
|
windowsHide: true,
|
|
474
|
+
// POSIX: detach so the child becomes its own process-group leader,
|
|
475
|
+
// allowing killProcessTree's neg-pid kill to terminate the whole
|
|
476
|
+
// pipe chain subtree instead of just the direct child.
|
|
477
|
+
detached: process.platform !== "win32",
|
|
474
478
|
env,
|
|
475
479
|
stdio: [stdinSpec, stdoutSpec, stderrSpec],
|
|
476
480
|
...spawnOverrides
|
|
@@ -521,9 +525,9 @@ async function runPipeGroup(segments, opts) {
|
|
|
521
525
|
}
|
|
522
526
|
const exits = await Promise.all(
|
|
523
527
|
children.map(
|
|
524
|
-
(c) => new Promise((
|
|
525
|
-
c.once("error", () =>
|
|
526
|
-
c.once("close", (code) =>
|
|
528
|
+
(c) => new Promise((resolve5) => {
|
|
529
|
+
c.once("error", () => resolve5(null));
|
|
530
|
+
c.once("close", (code) => resolve5(code));
|
|
527
531
|
})
|
|
528
532
|
)
|
|
529
533
|
);
|
|
@@ -567,6 +571,8 @@ var OutputBuffer = class {
|
|
|
567
571
|
};
|
|
568
572
|
|
|
569
573
|
// src/tools/shell/parse.ts
|
|
574
|
+
import { homedir } from "os";
|
|
575
|
+
import * as pathMod2 from "path";
|
|
570
576
|
var BUILTIN_ALLOWLIST = [
|
|
571
577
|
// Repo inspection
|
|
572
578
|
"git status",
|
|
@@ -743,7 +749,65 @@ function tailHasRisky(tail, risky) {
|
|
|
743
749
|
}
|
|
744
750
|
return false;
|
|
745
751
|
}
|
|
746
|
-
|
|
752
|
+
var DEFAULT_SENSITIVE_PREFIXES = [
|
|
753
|
+
"~/.ssh",
|
|
754
|
+
"~/.aws",
|
|
755
|
+
"~/.gnupg",
|
|
756
|
+
"~/.kube",
|
|
757
|
+
"/etc/shadow",
|
|
758
|
+
"/etc/sudoers"
|
|
759
|
+
];
|
|
760
|
+
var DEFAULT_SENSITIVE_PATTERNS = [
|
|
761
|
+
"*.env",
|
|
762
|
+
"*.env.*",
|
|
763
|
+
"*.key",
|
|
764
|
+
"*.pem",
|
|
765
|
+
"id_rsa*",
|
|
766
|
+
"id_ed25519*",
|
|
767
|
+
"*credentials*",
|
|
768
|
+
"*secret*"
|
|
769
|
+
];
|
|
770
|
+
function resolveSensitivePath(token, projectRoot) {
|
|
771
|
+
if (!token || token.startsWith("-") || token.includes("://") || token.startsWith("$"))
|
|
772
|
+
return null;
|
|
773
|
+
let expanded = token;
|
|
774
|
+
if (expanded.startsWith("~")) {
|
|
775
|
+
expanded = pathMod2.join(homedir(), expanded.slice(1));
|
|
776
|
+
}
|
|
777
|
+
return pathMod2.resolve(projectRoot, expanded);
|
|
778
|
+
}
|
|
779
|
+
function expandPrefix(prefix) {
|
|
780
|
+
if (prefix.startsWith("~")) return pathMod2.join(homedir(), prefix.slice(1));
|
|
781
|
+
return pathMod2.resolve(prefix);
|
|
782
|
+
}
|
|
783
|
+
function pathStartsWithPrefix(normalized, prefix) {
|
|
784
|
+
return normalized === prefix || normalized.startsWith(`${prefix}${pathMod2.sep}`);
|
|
785
|
+
}
|
|
786
|
+
function matchesGlob(name, pattern) {
|
|
787
|
+
const regex = new RegExp(
|
|
788
|
+
`^${pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".")}$`,
|
|
789
|
+
"i"
|
|
790
|
+
);
|
|
791
|
+
return regex.test(name);
|
|
792
|
+
}
|
|
793
|
+
function hasSensitivePathArgs(argv, projectRoot, extraPrefixes = [], extraPatterns = []) {
|
|
794
|
+
const prefixes = [...DEFAULT_SENSITIVE_PREFIXES, ...extraPrefixes].map(expandPrefix);
|
|
795
|
+
const patterns = [...DEFAULT_SENSITIVE_PATTERNS, ...extraPatterns];
|
|
796
|
+
for (const token of argv) {
|
|
797
|
+
const resolved = resolveSensitivePath(token, projectRoot);
|
|
798
|
+
if (!resolved) continue;
|
|
799
|
+
const normalized = pathMod2.normalize(resolved);
|
|
800
|
+
for (const pfx of prefixes) {
|
|
801
|
+
if (pathStartsWithPrefix(normalized, pfx)) return true;
|
|
802
|
+
}
|
|
803
|
+
const base = pathMod2.basename(normalized);
|
|
804
|
+
for (const pat of patterns) {
|
|
805
|
+
if (matchesGlob(base, pat)) return true;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
return false;
|
|
809
|
+
}
|
|
810
|
+
function isAllowed(cmd, extra = [], projectRoot, sensitivePathConfig) {
|
|
747
811
|
let argv;
|
|
748
812
|
try {
|
|
749
813
|
argv = tokenizeCommand(cmd);
|
|
@@ -765,19 +829,26 @@ function isAllowed(cmd, extra = []) {
|
|
|
765
829
|
if (!match) continue;
|
|
766
830
|
const risky = RISKY_ARGS[prefix];
|
|
767
831
|
if (risky && tailHasRisky(argv.slice(prefixTokens.length), risky)) return false;
|
|
832
|
+
if (projectRoot && hasSensitivePathArgs(
|
|
833
|
+
argv,
|
|
834
|
+
projectRoot,
|
|
835
|
+
sensitivePathConfig?.prefixes,
|
|
836
|
+
sensitivePathConfig?.patterns
|
|
837
|
+
))
|
|
838
|
+
return false;
|
|
768
839
|
return true;
|
|
769
840
|
}
|
|
770
841
|
return false;
|
|
771
842
|
}
|
|
772
|
-
function isCommandAllowed(cmd, extra = []) {
|
|
843
|
+
function isCommandAllowed(cmd, extra = [], projectRoot, sensitivePathConfig) {
|
|
773
844
|
let chain;
|
|
774
845
|
try {
|
|
775
846
|
chain = parseCommandChain(cmd);
|
|
776
847
|
} catch {
|
|
777
848
|
return false;
|
|
778
849
|
}
|
|
779
|
-
if (chain === null) return isAllowed(cmd, extra);
|
|
780
|
-
return chainAllowed(chain, (seg) => isAllowed(seg, extra));
|
|
850
|
+
if (chain === null) return isAllowed(cmd, extra, projectRoot, sensitivePathConfig);
|
|
851
|
+
return chainAllowed(chain, (seg) => isAllowed(seg, extra, projectRoot, sensitivePathConfig));
|
|
781
852
|
}
|
|
782
853
|
|
|
783
854
|
// src/tools/shell/exec.ts
|
|
@@ -824,8 +895,15 @@ async function runCommand(cmd, opts) {
|
|
|
824
895
|
const spawnOpts = {
|
|
825
896
|
cwd: opts.cwd,
|
|
826
897
|
shell: false,
|
|
827
|
-
// no shell-expansion — see header comment
|
|
828
898
|
windowsHide: true,
|
|
899
|
+
// POSIX: detach so the child becomes its own process-group leader.
|
|
900
|
+
// Required for `process.kill(-pid, …)` in killProcessTree to
|
|
901
|
+
// terminate the whole subtree (child + grandchildren) instead of
|
|
902
|
+
// only the leader — without this grandchildren like npm→node→esbuild
|
|
903
|
+
// become orphaned.
|
|
904
|
+
// Windows: detached would spawn a new console window; leave the
|
|
905
|
+
// default and use taskkill /T for tree termination (see killProcessTree).
|
|
906
|
+
detached: process.platform !== "win32",
|
|
829
907
|
// PYTHONIOENCODING + PYTHONUTF8 force any spawned Python child
|
|
830
908
|
// (run_command running `python script.py`, etc.) to emit UTF-8
|
|
831
909
|
// on stdout/stderr. Without this, Chinese-Windows defaults
|
|
@@ -838,7 +916,7 @@ async function runCommand(cmd, opts) {
|
|
|
838
916
|
};
|
|
839
917
|
const { bin, args, spawnOverrides } = prepareSpawn(argv, { env: normalizedEnv });
|
|
840
918
|
const effectiveSpawnOpts = { ...spawnOpts, ...spawnOverrides };
|
|
841
|
-
return await new Promise((
|
|
919
|
+
return await new Promise((resolve5, reject) => {
|
|
842
920
|
let child;
|
|
843
921
|
try {
|
|
844
922
|
child = spawn2(bin, args, effectiveSpawnOpts);
|
|
@@ -892,7 +970,7 @@ async function runCommand(cmd, opts) {
|
|
|
892
970
|
const output = buf.length > maxChars ? `${buf.slice(0, maxChars)}
|
|
893
971
|
|
|
894
972
|
[\u2026 truncated ${buf.length - maxChars} chars \u2026]` : buf;
|
|
895
|
-
|
|
973
|
+
resolve5({ exitCode: code, output, timedOut });
|
|
896
974
|
});
|
|
897
975
|
});
|
|
898
976
|
}
|
|
@@ -914,16 +992,16 @@ function resolveExecutable(cmd, opts = {}) {
|
|
|
914
992
|
const platform = opts.platform ?? process.platform;
|
|
915
993
|
if (platform !== "win32") return cmd;
|
|
916
994
|
if (!cmd) return cmd;
|
|
917
|
-
if (cmd.includes("/") || cmd.includes("\\") ||
|
|
918
|
-
if (
|
|
995
|
+
if (cmd.includes("/") || cmd.includes("\\") || pathMod3.isAbsolute(cmd)) return cmd;
|
|
996
|
+
if (pathMod3.extname(cmd)) return cmd;
|
|
919
997
|
const env = opts.env ?? process.env;
|
|
920
998
|
const pathExt = (getEnvCaseInsensitive(env, "PATHEXT") ?? ".COM;.EXE;.BAT;.CMD").split(";").map((e) => e.trim()).filter(Boolean);
|
|
921
|
-
const delimiter2 = opts.pathDelimiter ?? (platform === "win32" ? ";" :
|
|
999
|
+
const delimiter2 = opts.pathDelimiter ?? (platform === "win32" ? ";" : pathMod3.delimiter);
|
|
922
1000
|
const pathDirs = (getEnvCaseInsensitive(env, "PATH") ?? "").split(delimiter2).filter(Boolean);
|
|
923
1001
|
const isFile = opts.isFile ?? defaultIsFile;
|
|
924
1002
|
for (const dir of pathDirs) {
|
|
925
1003
|
for (const ext of pathExt) {
|
|
926
|
-
const full =
|
|
1004
|
+
const full = pathMod3.win32.join(dir, cmd + ext);
|
|
927
1005
|
if (isFile(full)) return full;
|
|
928
1006
|
}
|
|
929
1007
|
}
|
|
@@ -1039,8 +1117,8 @@ function withUtf8Codepage(cmdline) {
|
|
|
1039
1117
|
function isBareWindowsName(s) {
|
|
1040
1118
|
if (!s) return false;
|
|
1041
1119
|
if (s.includes("/") || s.includes("\\")) return false;
|
|
1042
|
-
if (
|
|
1043
|
-
if (
|
|
1120
|
+
if (pathMod3.isAbsolute(s)) return false;
|
|
1121
|
+
if (pathMod3.extname(s)) return false;
|
|
1044
1122
|
return true;
|
|
1045
1123
|
}
|
|
1046
1124
|
function quoteForCmdExe(arg) {
|
|
@@ -1051,7 +1129,7 @@ function quoteForCmdExe(arg) {
|
|
|
1051
1129
|
|
|
1052
1130
|
// src/tools/shell.ts
|
|
1053
1131
|
function registerShellTools(registry, opts) {
|
|
1054
|
-
const rootDir =
|
|
1132
|
+
const rootDir = pathMod4.resolve(opts.rootDir);
|
|
1055
1133
|
const timeoutSec = opts.timeoutSec ?? DEFAULT_TIMEOUT_SEC;
|
|
1056
1134
|
const maxOutputChars = opts.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;
|
|
1057
1135
|
const jobs = opts.jobs ?? new JobRegistry();
|
|
@@ -1071,7 +1149,7 @@ function registerShellTools(registry, opts) {
|
|
|
1071
1149
|
if (isAllowAll()) return true;
|
|
1072
1150
|
const cmd = typeof args?.command === "string" ? args.command.trim() : "";
|
|
1073
1151
|
if (!cmd) return false;
|
|
1074
|
-
return isCommandAllowed(cmd, getExtraAllowed());
|
|
1152
|
+
return isCommandAllowed(cmd, getExtraAllowed(), rootDir, opts.sensitivePaths);
|
|
1075
1153
|
},
|
|
1076
1154
|
parameters: {
|
|
1077
1155
|
type: "object",
|
|
@@ -1091,7 +1169,7 @@ function registerShellTools(registry, opts) {
|
|
|
1091
1169
|
const cmd = args.command.trim();
|
|
1092
1170
|
if (!cmd) throw new Error("run_command: empty command");
|
|
1093
1171
|
const effectiveTimeout = Math.max(1, Math.min(600, args.timeoutSec ?? timeoutSec));
|
|
1094
|
-
if (!isAllowAll() && !isCommandAllowed(cmd, getExtraAllowed())) {
|
|
1172
|
+
if (!isAllowAll() && !isCommandAllowed(cmd, getExtraAllowed(), rootDir, opts.sensitivePaths)) {
|
|
1095
1173
|
const gate = ctx?.confirmationGate ?? pauseGate;
|
|
1096
1174
|
const choice = await gate.ask({
|
|
1097
1175
|
kind: "run_command",
|
|
@@ -1117,7 +1195,7 @@ function registerShellTools(registry, opts) {
|
|
|
1117
1195
|
});
|
|
1118
1196
|
registry.register({
|
|
1119
1197
|
name: "run_background",
|
|
1120
|
-
description: "Spawn a long-running process and detach. Waits up to `waitSec` for startup or a readiness signal ('Local:', 'listening on', 'compiled successfully'), then returns the job id + startup preview. Tail logs with `job_output`, block on completion with `wait_for_job`, kill with `stop_job`, list with `list_jobs`.\n\nSingle process only \u2014 chains / redirects
|
|
1198
|
+
description: "Spawn a long-running process and detach. Waits up to `waitSec` for startup or a readiness signal ('Local:', 'listening on', 'compiled successfully'), then returns the job id + startup preview. Tail logs with `job_output`, block on completion with `wait_for_job`, kill with `stop_job`, list with `list_jobs`.\n\nSingle process only \u2014 no chains / redirects. For subdirectories use the `cwd` parameter (workspace-relative or absolute, must stay inside the workspace root); do NOT write `cd X && cmd`, that gets rejected.\n\nUSE THIS \u2014 not run_command \u2014 for:\n- Dev servers / watchers: npm/yarn/pnpm dev, uvicorn / flask run, cargo watch, tsc --watch, webpack serve, anything with dev/serve/watch in the name.\n- One-shot long jobs: curl / wget large downloads, `huggingface-cli download`, multi-GB `pip install` / `npm install`, big `cargo build` / `docker build`. Start with `run_background`, then call `wait_for_job` once (default `waitFor: 'exit'`, timeoutMs up to 300_000) \u2014 the harness blocks server-side so a 5-minute download costs ONE tool call, not 30 polls.",
|
|
1121
1199
|
parameters: {
|
|
1122
1200
|
type: "object",
|
|
1123
1201
|
properties: {
|
|
@@ -1125,6 +1203,10 @@ function registerShellTools(registry, opts) {
|
|
|
1125
1203
|
type: "string",
|
|
1126
1204
|
description: "Full command line. Same quoting rules as run_command (no pipes / redirects / chaining)."
|
|
1127
1205
|
},
|
|
1206
|
+
cwd: {
|
|
1207
|
+
type: "string",
|
|
1208
|
+
description: "Working directory for the spawn. Workspace-relative or absolute. Defaults to the workspace root. Must resolve inside the workspace \u2014 paths escaping the root are rejected."
|
|
1209
|
+
},
|
|
1128
1210
|
waitSec: {
|
|
1129
1211
|
type: "integer",
|
|
1130
1212
|
description: "Max seconds to wait for startup before returning. 0..30, default 3. A ready-signal match short-circuits this."
|
|
@@ -1135,11 +1217,12 @@ function registerShellTools(registry, opts) {
|
|
|
1135
1217
|
fn: async (args, ctx) => {
|
|
1136
1218
|
const cmd = args.command.trim();
|
|
1137
1219
|
if (!cmd) throw new Error("run_background: empty command");
|
|
1138
|
-
|
|
1220
|
+
const cwd = resolveCwdInsideRoot(rootDir, args.cwd);
|
|
1221
|
+
if (!isAllowAll() && !isCommandAllowed(cmd, getExtraAllowed(), rootDir, opts.sensitivePaths)) {
|
|
1139
1222
|
const gate = ctx?.confirmationGate ?? pauseGate;
|
|
1140
1223
|
const choice = await gate.ask({
|
|
1141
1224
|
kind: "run_background",
|
|
1142
|
-
payload: { command: cmd, cwd
|
|
1225
|
+
payload: { command: cmd, cwd, waitSec: args.waitSec }
|
|
1143
1226
|
});
|
|
1144
1227
|
if (choice.type === "deny") {
|
|
1145
1228
|
throw new Error(
|
|
@@ -1151,10 +1234,11 @@ function registerShellTools(registry, opts) {
|
|
|
1151
1234
|
}
|
|
1152
1235
|
}
|
|
1153
1236
|
const result = await jobs.start(cmd, {
|
|
1154
|
-
cwd
|
|
1237
|
+
cwd,
|
|
1155
1238
|
waitSec: args.waitSec,
|
|
1156
1239
|
signal: ctx?.signal
|
|
1157
1240
|
});
|
|
1241
|
+
opts.onJobsChanged?.();
|
|
1158
1242
|
return formatJobStart(result);
|
|
1159
1243
|
}
|
|
1160
1244
|
});
|
|
@@ -1216,6 +1300,7 @@ function registerShellTools(registry, opts) {
|
|
|
1216
1300
|
waitFor: args.waitFor
|
|
1217
1301
|
});
|
|
1218
1302
|
if (!out) return `job ${args.jobId}: not found (use list_jobs)`;
|
|
1303
|
+
if (out.exited) opts.onJobsChanged?.();
|
|
1219
1304
|
return {
|
|
1220
1305
|
jobId: args.jobId,
|
|
1221
1306
|
exited: out.exited,
|
|
@@ -1236,6 +1321,7 @@ function registerShellTools(registry, opts) {
|
|
|
1236
1321
|
},
|
|
1237
1322
|
fn: async (args) => {
|
|
1238
1323
|
const rec = await jobs.stop(args.jobId);
|
|
1324
|
+
opts.onJobsChanged?.();
|
|
1239
1325
|
if (!rec) return `job ${args.jobId}: not found`;
|
|
1240
1326
|
return formatJobStop(rec);
|
|
1241
1327
|
}
|
|
@@ -1255,6 +1341,18 @@ function registerShellTools(registry, opts) {
|
|
|
1255
1341
|
});
|
|
1256
1342
|
return registry;
|
|
1257
1343
|
}
|
|
1344
|
+
function resolveCwdInsideRoot(rootDir, raw) {
|
|
1345
|
+
const root = pathMod4.resolve(rootDir);
|
|
1346
|
+
if (!raw || !raw.trim()) return root;
|
|
1347
|
+
const resolved = pathMod4.resolve(root, raw);
|
|
1348
|
+
const rel = pathMod4.relative(root, resolved);
|
|
1349
|
+
if (rel.startsWith("..") || pathMod4.isAbsolute(rel)) {
|
|
1350
|
+
throw new Error(
|
|
1351
|
+
`run_background: cwd "${raw}" resolves outside the workspace root (${root}). Pass a workspace-relative path.`
|
|
1352
|
+
);
|
|
1353
|
+
}
|
|
1354
|
+
return resolved;
|
|
1355
|
+
}
|
|
1258
1356
|
function formatJobStart(r) {
|
|
1259
1357
|
const header = r.stillRunning ? `[job ${r.jobId} started \xB7 pid ${r.pid ?? "?"} \xB7 ${r.readyMatched ? "READY signal matched" : "running (no ready signal yet)"}]` : r.exitCode !== null ? `[job ${r.jobId} exited during startup \xB7 exit ${r.exitCode}]` : `[job ${r.jobId} failed to start]`;
|
|
1260
1358
|
return r.preview ? `${header}
|
|
@@ -1355,7 +1453,7 @@ var JobRegistry = class {
|
|
|
1355
1453
|
const maxBytes = opts.maxBufferBytes ?? DEFAULT_OUTPUT_CAP_BYTES;
|
|
1356
1454
|
const { bin, args, spawnOverrides } = prepareSpawn(argv);
|
|
1357
1455
|
const spawnOpts = {
|
|
1358
|
-
cwd:
|
|
1456
|
+
cwd: pathMod5.resolve(opts.cwd),
|
|
1359
1457
|
shell: false,
|
|
1360
1458
|
windowsHide: true,
|
|
1361
1459
|
env: process.env,
|
|
@@ -1540,16 +1638,16 @@ ${job.output.slice(start)}`;
|
|
|
1540
1638
|
let wakeOutput = null;
|
|
1541
1639
|
if (waitFor === "output-or-exit") {
|
|
1542
1640
|
racers.push(
|
|
1543
|
-
new Promise((
|
|
1544
|
-
wakeOutput =
|
|
1545
|
-
job.outputWaiters.add(
|
|
1641
|
+
new Promise((resolve5) => {
|
|
1642
|
+
wakeOutput = resolve5;
|
|
1643
|
+
job.outputWaiters.add(resolve5);
|
|
1546
1644
|
})
|
|
1547
1645
|
);
|
|
1548
1646
|
}
|
|
1549
1647
|
let timer = null;
|
|
1550
1648
|
racers.push(
|
|
1551
|
-
new Promise((
|
|
1552
|
-
timer = setTimeout(
|
|
1649
|
+
new Promise((resolve5) => {
|
|
1650
|
+
timer = setTimeout(resolve5, timeoutMs);
|
|
1553
1651
|
})
|
|
1554
1652
|
);
|
|
1555
1653
|
await Promise.race(racers);
|
|
@@ -1658,9 +1756,9 @@ function latestOutputSince(before, after) {
|
|
|
1658
1756
|
|
|
1659
1757
|
// src/tools/fs/edit.ts
|
|
1660
1758
|
import { promises as fs } from "fs";
|
|
1661
|
-
import * as
|
|
1759
|
+
import * as pathMod6 from "path";
|
|
1662
1760
|
function displayRel(rootDir, full) {
|
|
1663
|
-
return
|
|
1761
|
+
return pathMod6.relative(rootDir, full).replaceAll("\\", "/");
|
|
1664
1762
|
}
|
|
1665
1763
|
async function applyEdit(rootDir, abs, args) {
|
|
1666
1764
|
if (args.search.length === 0) {
|
|
@@ -1823,4 +1921,4 @@ export {
|
|
|
1823
1921
|
registerShellTools,
|
|
1824
1922
|
formatCommandResult
|
|
1825
1923
|
};
|
|
1826
|
-
//# sourceMappingURL=chunk-
|
|
1924
|
+
//# sourceMappingURL=chunk-RDRC3XDT.js.map
|