zelari-code 1.19.0 → 1.20.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/dist/cli/budget/tokenBudget.js +7 -3
- package/dist/cli/budget/tokenBudget.js.map +1 -1
- package/dist/cli/hooks/useChatTurn.js +5 -3
- package/dist/cli/hooks/useChatTurn.js.map +1 -1
- package/dist/cli/main.bundled.js +306 -27
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +36 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/runHeadless.js +1 -1
- package/dist/cli/utils/doctor.js +44 -0
- package/dist/cli/utils/doctor.js.map +1 -1
- package/dist/cli/utils/fixBudget.js +106 -0
- package/dist/cli/utils/fixBudget.js.map +1 -0
- package/dist/cli/utils/prereqChecks.js +134 -29
- package/dist/cli/utils/prereqChecks.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -16596,12 +16596,20 @@ function isWslBashPath(p3) {
|
|
|
16596
16596
|
return true;
|
|
16597
16597
|
return false;
|
|
16598
16598
|
}
|
|
16599
|
+
function isPowerShellPath(p3) {
|
|
16600
|
+
if (!p3 || typeof p3 !== "string")
|
|
16601
|
+
return false;
|
|
16602
|
+
const lower = p3.toLowerCase().trim();
|
|
16603
|
+
return POWERSHELL_EXES.some((exe) => lower.endsWith(exe));
|
|
16604
|
+
}
|
|
16599
16605
|
function acceptBashPath(p3) {
|
|
16600
16606
|
if (!p3 || p3.trim().length === 0)
|
|
16601
16607
|
return null;
|
|
16602
16608
|
const trimmed = p3.trim();
|
|
16603
16609
|
if (isWslBashPath(trimmed))
|
|
16604
16610
|
return null;
|
|
16611
|
+
if (isPowerShellPath(trimmed))
|
|
16612
|
+
return null;
|
|
16605
16613
|
if (!existsSyncSafe(trimmed))
|
|
16606
16614
|
return null;
|
|
16607
16615
|
return trimmed;
|
|
@@ -16610,19 +16618,24 @@ function resolveShell(forceReResolve = false) {
|
|
|
16610
16618
|
if (memoized && !forceReResolve)
|
|
16611
16619
|
return memoized;
|
|
16612
16620
|
if (process.platform !== "win32") {
|
|
16613
|
-
memoized = { shell: true, via: "/bin/sh", isBash: false };
|
|
16621
|
+
memoized = { shell: true, via: "/bin/sh", isBash: false, isPowerShell: false };
|
|
16614
16622
|
return memoized;
|
|
16615
16623
|
}
|
|
16616
|
-
const
|
|
16617
|
-
if (
|
|
16618
|
-
memoized = { shell:
|
|
16624
|
+
const bashFound = resolveBashWindows();
|
|
16625
|
+
if (bashFound) {
|
|
16626
|
+
memoized = { shell: bashFound, via: `bash (${bashFound})`, isBash: true, isPowerShell: false };
|
|
16627
|
+
return memoized;
|
|
16628
|
+
}
|
|
16629
|
+
const psFound = resolvePowerShellWindows();
|
|
16630
|
+
if (psFound) {
|
|
16631
|
+
memoized = { shell: psFound, via: `powershell (${psFound})`, isBash: false, isPowerShell: true };
|
|
16619
16632
|
return memoized;
|
|
16620
16633
|
}
|
|
16621
16634
|
if (!warnedFallback) {
|
|
16622
16635
|
warnedFallback = true;
|
|
16623
16636
|
console.error("[zelari-code] bash tool: Git Bash not found \u2014 falling back to cmd.exe. POSIX commands (ls, which, $VAR, &&) may fail. Install Git for Windows or set ZELARI_SHELL to your bash binary for proper POSIX support.");
|
|
16624
16637
|
}
|
|
16625
|
-
memoized = { shell: true, via: "cmd.exe", isBash: false };
|
|
16638
|
+
memoized = { shell: true, via: "cmd.exe", isBash: false, isPowerShell: false };
|
|
16626
16639
|
return memoized;
|
|
16627
16640
|
}
|
|
16628
16641
|
function resolveBashWindows() {
|
|
@@ -16650,6 +16663,42 @@ function resolveBashWindows() {
|
|
|
16650
16663
|
}
|
|
16651
16664
|
return null;
|
|
16652
16665
|
}
|
|
16666
|
+
function acceptPowerShellPath(p3) {
|
|
16667
|
+
if (!p3 || p3.trim().length === 0)
|
|
16668
|
+
return null;
|
|
16669
|
+
const trimmed = p3.trim();
|
|
16670
|
+
if (isWslBashPath(trimmed))
|
|
16671
|
+
return null;
|
|
16672
|
+
if (!isPowerShellPath(trimmed))
|
|
16673
|
+
return null;
|
|
16674
|
+
if (!existsSyncSafe(trimmed))
|
|
16675
|
+
return null;
|
|
16676
|
+
return trimmed;
|
|
16677
|
+
}
|
|
16678
|
+
function resolvePowerShellWindows() {
|
|
16679
|
+
const fromEnv = acceptPowerShellPath(process.env.ZELARI_SHELL);
|
|
16680
|
+
if (fromEnv)
|
|
16681
|
+
return fromEnv;
|
|
16682
|
+
for (const p3 of STANDARD_POWERSHELL_PATHS) {
|
|
16683
|
+
const accepted = acceptPowerShellPath(p3);
|
|
16684
|
+
if (accepted)
|
|
16685
|
+
return accepted;
|
|
16686
|
+
}
|
|
16687
|
+
try {
|
|
16688
|
+
for (const name of POWERSHELL_EXES) {
|
|
16689
|
+
const result = spawnSync("where", [name], { encoding: "utf-8", windowsHide: true });
|
|
16690
|
+
if (result.status === 0 && result.stdout) {
|
|
16691
|
+
for (const line of result.stdout.split(/\r?\n/)) {
|
|
16692
|
+
const accepted = acceptPowerShellPath(line);
|
|
16693
|
+
if (accepted)
|
|
16694
|
+
return accepted;
|
|
16695
|
+
}
|
|
16696
|
+
}
|
|
16697
|
+
}
|
|
16698
|
+
} catch {
|
|
16699
|
+
}
|
|
16700
|
+
return null;
|
|
16701
|
+
}
|
|
16653
16702
|
function existsSyncSafe(p3) {
|
|
16654
16703
|
try {
|
|
16655
16704
|
return existsSync4(p3);
|
|
@@ -16657,7 +16706,7 @@ function existsSyncSafe(p3) {
|
|
|
16657
16706
|
return false;
|
|
16658
16707
|
}
|
|
16659
16708
|
}
|
|
16660
|
-
var STANDARD_BASH_PATHS, memoized, warnedFallback;
|
|
16709
|
+
var STANDARD_BASH_PATHS, POWERSHELL_EXES, STANDARD_POWERSHELL_PATHS, memoized, warnedFallback;
|
|
16661
16710
|
var init_shellResolver = __esm({
|
|
16662
16711
|
"packages/core/dist/core/tools/builtin/shellResolver.js"() {
|
|
16663
16712
|
"use strict";
|
|
@@ -16667,6 +16716,13 @@ var init_shellResolver = __esm({
|
|
|
16667
16716
|
"C:\\Program Files (x86)\\Git\\bin\\bash.exe",
|
|
16668
16717
|
"C:\\Program Files (x86)\\Git\\usr\\bin\\bash.exe"
|
|
16669
16718
|
];
|
|
16719
|
+
POWERSHELL_EXES = ["pwsh.exe", "powershell.exe"];
|
|
16720
|
+
STANDARD_POWERSHELL_PATHS = [
|
|
16721
|
+
"C:\\Program Files\\PowerShell\\7\\pwsh.exe",
|
|
16722
|
+
"C:\\Program Files\\PowerShell\\7\\powershell.exe",
|
|
16723
|
+
"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
|
|
16724
|
+
"C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe"
|
|
16725
|
+
];
|
|
16670
16726
|
memoized = null;
|
|
16671
16727
|
warnedFallback = false;
|
|
16672
16728
|
}
|
|
@@ -16731,6 +16787,14 @@ var init_shell = __esm({
|
|
|
16731
16787
|
env,
|
|
16732
16788
|
stdio: ["ignore", "pipe", "pipe"]
|
|
16733
16789
|
});
|
|
16790
|
+
} else if (resolved.isPowerShell) {
|
|
16791
|
+
child = spawn(resolved.shell, ["-Command", args.command], {
|
|
16792
|
+
cwd,
|
|
16793
|
+
signal: ctx.signal,
|
|
16794
|
+
shell: false,
|
|
16795
|
+
env: baseEnv,
|
|
16796
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
16797
|
+
});
|
|
16734
16798
|
} else {
|
|
16735
16799
|
child = spawn(args.command, {
|
|
16736
16800
|
shell: resolved.shell,
|
|
@@ -19551,7 +19615,7 @@ var init_AgentHarness = __esm({
|
|
|
19551
19615
|
this.eventBus = config2.eventBus;
|
|
19552
19616
|
this.sessionId = config2.sessionId ?? crypto.randomUUID();
|
|
19553
19617
|
this.maxQueuedIterations = config2.maxQueuedIterations ?? 3;
|
|
19554
|
-
this.maxToolLoopIterations = config2.maxToolLoopIterations ??
|
|
19618
|
+
this.maxToolLoopIterations = config2.maxToolLoopIterations ?? 60;
|
|
19555
19619
|
const soft = this.maxToolLoopIterations;
|
|
19556
19620
|
const hardCfg = config2.maxToolLoopHardCap;
|
|
19557
19621
|
this.maxToolLoopHardCap = typeof hardCfg === "number" && hardCfg > 0 ? Math.max(soft, hardCfg) : Math.max(soft * 3, soft + 60);
|
|
@@ -32759,6 +32823,7 @@ __export(prereqChecks_exports, {
|
|
|
32759
32823
|
checkAgentGit: () => checkAgentGit,
|
|
32760
32824
|
checkAgentNode: () => checkAgentNode,
|
|
32761
32825
|
checkMainNode: () => checkMainNode,
|
|
32826
|
+
isPowerShellPath: () => isPowerShellPath2,
|
|
32762
32827
|
isWslBashPath: () => isWslBashPath2,
|
|
32763
32828
|
runPrereqChecks: () => runPrereqChecks
|
|
32764
32829
|
});
|
|
@@ -32773,33 +32838,72 @@ function isWslBashPath2(p3) {
|
|
|
32773
32838
|
if (n.includes("\\windowsapps\\bash.exe")) return true;
|
|
32774
32839
|
return false;
|
|
32775
32840
|
}
|
|
32841
|
+
function isPowerShellPath2(p3) {
|
|
32842
|
+
if (!p3 || typeof p3 !== "string") return false;
|
|
32843
|
+
const lower = p3.toLowerCase().trim();
|
|
32844
|
+
return POWERSHELL_EXES2.some((exe) => lower.endsWith(exe));
|
|
32845
|
+
}
|
|
32776
32846
|
function acceptBashPath2(p3) {
|
|
32777
32847
|
if (!p3 || p3.trim().length === 0) return null;
|
|
32778
32848
|
const trimmed = p3.trim();
|
|
32779
32849
|
if (isWslBashPath2(trimmed)) return null;
|
|
32850
|
+
if (isPowerShellPath2(trimmed)) return null;
|
|
32780
32851
|
if (!existsSyncSafe2(trimmed)) return null;
|
|
32781
32852
|
return trimmed;
|
|
32782
32853
|
}
|
|
32854
|
+
function acceptPowerShellPath2(p3) {
|
|
32855
|
+
if (!p3 || p3.trim().length === 0) return null;
|
|
32856
|
+
const trimmed = p3.trim();
|
|
32857
|
+
if (isWslBashPath2(trimmed)) return null;
|
|
32858
|
+
if (!isPowerShellPath2(trimmed)) return null;
|
|
32859
|
+
if (!existsSyncSafe2(trimmed)) return null;
|
|
32860
|
+
return trimmed;
|
|
32861
|
+
}
|
|
32862
|
+
function resolvePowerShellWindowsSync() {
|
|
32863
|
+
const fromEnv = acceptPowerShellPath2(process.env.ZELARI_SHELL);
|
|
32864
|
+
if (fromEnv) return fromEnv;
|
|
32865
|
+
for (const p3 of STANDARD_POWERSHELL_PATHS2) {
|
|
32866
|
+
const accepted = acceptPowerShellPath2(p3);
|
|
32867
|
+
if (accepted) return accepted;
|
|
32868
|
+
}
|
|
32869
|
+
try {
|
|
32870
|
+
for (const name of POWERSHELL_EXES2) {
|
|
32871
|
+
const result = spawnSync2("where", [name], {
|
|
32872
|
+
encoding: "utf8",
|
|
32873
|
+
windowsHide: true
|
|
32874
|
+
});
|
|
32875
|
+
if (result.status === 0 && result.stdout) {
|
|
32876
|
+
for (const line of result.stdout.split(/\r?\n/)) {
|
|
32877
|
+
const accepted = acceptPowerShellPath2(line);
|
|
32878
|
+
if (accepted) return accepted;
|
|
32879
|
+
}
|
|
32880
|
+
}
|
|
32881
|
+
}
|
|
32882
|
+
} catch {
|
|
32883
|
+
}
|
|
32884
|
+
return null;
|
|
32885
|
+
}
|
|
32783
32886
|
function resolveAgentShellSync() {
|
|
32784
32887
|
if (process.platform !== "win32") {
|
|
32785
|
-
return { bashPath: null, isBash: true, via: "/bin/sh" };
|
|
32888
|
+
return { bashPath: null, isBash: true, isPowerShell: false, via: "/bin/sh" };
|
|
32786
32889
|
}
|
|
32787
32890
|
const fromEnv = acceptBashPath2(process.env.ZELARI_SHELL);
|
|
32788
32891
|
if (fromEnv) {
|
|
32789
|
-
return { bashPath: fromEnv, isBash: true, via: `bash (${fromEnv})` };
|
|
32892
|
+
return { bashPath: fromEnv, isBash: true, isPowerShell: false, via: `bash (${fromEnv})` };
|
|
32790
32893
|
}
|
|
32791
32894
|
const fromSession = acceptBashPath2(process.env.SHELL);
|
|
32792
32895
|
if (fromSession) {
|
|
32793
32896
|
return {
|
|
32794
32897
|
bashPath: fromSession,
|
|
32795
32898
|
isBash: true,
|
|
32899
|
+
isPowerShell: false,
|
|
32796
32900
|
via: `bash (${fromSession})`
|
|
32797
32901
|
};
|
|
32798
32902
|
}
|
|
32799
32903
|
for (const p3 of STANDARD_BASH_PATHS2) {
|
|
32800
32904
|
const accepted = acceptBashPath2(p3);
|
|
32801
32905
|
if (accepted) {
|
|
32802
|
-
return { bashPath: accepted, isBash: true, via: `bash (${accepted})` };
|
|
32906
|
+
return { bashPath: accepted, isBash: true, isPowerShell: false, via: `bash (${accepted})` };
|
|
32803
32907
|
}
|
|
32804
32908
|
}
|
|
32805
32909
|
try {
|
|
@@ -32814,6 +32918,7 @@ function resolveAgentShellSync() {
|
|
|
32814
32918
|
return {
|
|
32815
32919
|
bashPath: accepted,
|
|
32816
32920
|
isBash: true,
|
|
32921
|
+
isPowerShell: false,
|
|
32817
32922
|
via: `bash (${accepted})`
|
|
32818
32923
|
};
|
|
32819
32924
|
}
|
|
@@ -32821,7 +32926,11 @@ function resolveAgentShellSync() {
|
|
|
32821
32926
|
}
|
|
32822
32927
|
} catch {
|
|
32823
32928
|
}
|
|
32824
|
-
|
|
32929
|
+
const psFound = resolvePowerShellWindowsSync();
|
|
32930
|
+
if (psFound) {
|
|
32931
|
+
return { bashPath: psFound, isBash: false, isPowerShell: true, via: `powershell (${psFound})` };
|
|
32932
|
+
}
|
|
32933
|
+
return { bashPath: null, isBash: false, isPowerShell: false, via: "cmd.exe" };
|
|
32825
32934
|
}
|
|
32826
32935
|
function agentProbeEnv() {
|
|
32827
32936
|
const env = { ...process.env };
|
|
@@ -32853,15 +32962,28 @@ function probeTool(tool) {
|
|
|
32853
32962
|
let stdout = "";
|
|
32854
32963
|
const env = agentProbeEnv();
|
|
32855
32964
|
if (shell.bashPath) {
|
|
32856
|
-
|
|
32857
|
-
|
|
32858
|
-
|
|
32859
|
-
|
|
32860
|
-
|
|
32861
|
-
|
|
32862
|
-
|
|
32863
|
-
|
|
32864
|
-
|
|
32965
|
+
if (shell.isPowerShell) {
|
|
32966
|
+
try {
|
|
32967
|
+
const r = spawnSync2(shell.bashPath, ["-Command", `${tool} --version`], {
|
|
32968
|
+
encoding: "utf8",
|
|
32969
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
32970
|
+
windowsHide: true,
|
|
32971
|
+
env
|
|
32972
|
+
});
|
|
32973
|
+
if (r.status === 0) stdout = (r.stdout || "").trim();
|
|
32974
|
+
} catch {
|
|
32975
|
+
}
|
|
32976
|
+
} else {
|
|
32977
|
+
try {
|
|
32978
|
+
const r = spawnSync2(shell.bashPath, ["-c", `${tool} --version`], {
|
|
32979
|
+
encoding: "utf8",
|
|
32980
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
32981
|
+
windowsHide: true,
|
|
32982
|
+
env
|
|
32983
|
+
});
|
|
32984
|
+
if (r.status === 0) stdout = (r.stdout || "").trim();
|
|
32985
|
+
} catch {
|
|
32986
|
+
}
|
|
32865
32987
|
}
|
|
32866
32988
|
} else if (process.platform === "win32") {
|
|
32867
32989
|
try {
|
|
@@ -32982,11 +33104,19 @@ function checkAgentBash() {
|
|
|
32982
33104
|
message: `real bash available (${shell.via})`
|
|
32983
33105
|
};
|
|
32984
33106
|
}
|
|
33107
|
+
if (shell.isPowerShell) {
|
|
33108
|
+
return {
|
|
33109
|
+
ok: true,
|
|
33110
|
+
severity: "warn",
|
|
33111
|
+
tool: "bash",
|
|
33112
|
+
message: `PowerShell available (${shell.via}) \u2014 works as bash replacement`
|
|
33113
|
+
};
|
|
33114
|
+
}
|
|
32985
33115
|
return {
|
|
32986
33116
|
ok: false,
|
|
32987
33117
|
severity: "warn",
|
|
32988
33118
|
tool: "bash",
|
|
32989
|
-
message: "no Git Bash \u2014 bash tool uses cmd.exe (install Git for Windows or set ZELARI_SHELL). Details: zelari-code --doctor"
|
|
33119
|
+
message: "no Git Bash or PowerShell \u2014 bash tool uses cmd.exe (install Git for Windows, or set ZELARI_SHELL). Details: zelari-code --doctor"
|
|
32990
33120
|
};
|
|
32991
33121
|
}
|
|
32992
33122
|
function checkMainNode() {
|
|
@@ -33047,7 +33177,7 @@ function runPrereqChecks(opts = { mode: "preflight" }) {
|
|
|
33047
33177
|
void opts.mode;
|
|
33048
33178
|
return { results, hasCriticalFail, warnings };
|
|
33049
33179
|
}
|
|
33050
|
-
var MIN_NODE_MAJOR, STANDARD_BASH_PATHS2;
|
|
33180
|
+
var MIN_NODE_MAJOR, STANDARD_BASH_PATHS2, POWERSHELL_EXES2, STANDARD_POWERSHELL_PATHS2;
|
|
33051
33181
|
var init_prereqChecks = __esm({
|
|
33052
33182
|
"src/cli/utils/prereqChecks.ts"() {
|
|
33053
33183
|
"use strict";
|
|
@@ -33058,6 +33188,13 @@ var init_prereqChecks = __esm({
|
|
|
33058
33188
|
"C:\\Program Files (x86)\\Git\\bin\\bash.exe",
|
|
33059
33189
|
"C:\\Program Files (x86)\\Git\\usr\\bin\\bash.exe"
|
|
33060
33190
|
];
|
|
33191
|
+
POWERSHELL_EXES2 = ["pwsh.exe", "powershell.exe"];
|
|
33192
|
+
STANDARD_POWERSHELL_PATHS2 = [
|
|
33193
|
+
"C:\\Program Files\\PowerShell\\7\\pwsh.exe",
|
|
33194
|
+
"C:\\Program Files\\PowerShell\\7\\powershell.exe",
|
|
33195
|
+
"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
|
|
33196
|
+
"C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe"
|
|
33197
|
+
];
|
|
33061
33198
|
}
|
|
33062
33199
|
});
|
|
33063
33200
|
|
|
@@ -33464,6 +33601,43 @@ function checkPath() {
|
|
|
33464
33601
|
` + (process.platform === "win32" ? winHint : posixHint)
|
|
33465
33602
|
);
|
|
33466
33603
|
}
|
|
33604
|
+
function checkBudget() {
|
|
33605
|
+
const expected = {
|
|
33606
|
+
ZELARI_MAX_TOOL_LOOP_HARD: "180",
|
|
33607
|
+
ZELARI_MAX_TOOL_LOOP_ITERATIONS: "60",
|
|
33608
|
+
ZELARI_CONTEXT_LIMIT: "400000"
|
|
33609
|
+
};
|
|
33610
|
+
const missing = [];
|
|
33611
|
+
const wrong = [];
|
|
33612
|
+
for (const [name, target] of Object.entries(expected)) {
|
|
33613
|
+
const current = process.env[name];
|
|
33614
|
+
if (current === void 0 || current === "") missing.push(name);
|
|
33615
|
+
else if (current !== target) wrong.push(`${name}=${current} (recommended ${target})`);
|
|
33616
|
+
}
|
|
33617
|
+
if (missing.length === 0 && wrong.length === 0) {
|
|
33618
|
+
return OK(`budget at recommended values (hard=180, soft=60, ctx=400k)`);
|
|
33619
|
+
}
|
|
33620
|
+
const lines = [];
|
|
33621
|
+
if (missing.length > 0) {
|
|
33622
|
+
lines.push(
|
|
33623
|
+
`missing: ${missing.join(", ")} \u2014 agent uses tighter in-code defaults`
|
|
33624
|
+
);
|
|
33625
|
+
}
|
|
33626
|
+
if (wrong.length > 0) {
|
|
33627
|
+
lines.push(`override: ${wrong.join("; ")}`);
|
|
33628
|
+
}
|
|
33629
|
+
const winHint = ` fix: zelari-code --fix-budget (sets all three at User scope)
|
|
33630
|
+
then open a NEW terminal for the changes to take effect`;
|
|
33631
|
+
const posixHint = ` fix: export ZELARI_MAX_TOOL_LOOP_HARD=180
|
|
33632
|
+
export ZELARI_MAX_TOOL_LOOP_ITERATIONS=60
|
|
33633
|
+
export ZELARI_CONTEXT_LIMIT=400000
|
|
33634
|
+
(add to ~/.bashrc or ~/.zshrc to persist)`;
|
|
33635
|
+
return WARN(
|
|
33636
|
+
`${lines.join("\n")}
|
|
33637
|
+
symptom: agent stops mid-task without completing (not rate limit)
|
|
33638
|
+
` + (process.platform === "win32" ? winHint : posixHint)
|
|
33639
|
+
);
|
|
33640
|
+
}
|
|
33467
33641
|
function prereqToCheckResult(r) {
|
|
33468
33642
|
if (r.ok) return OK(r.message);
|
|
33469
33643
|
return r.severity === "critical" ? FAIL(r.message, "critical") : WARN(r.message);
|
|
@@ -33513,6 +33687,10 @@ async function runDoctor() {
|
|
|
33513
33687
|
{ name: "node (agent shell)", run: () => prereqToCheckResult(checkAgentNode()) },
|
|
33514
33688
|
{ name: "git (agent shell)", run: () => prereqToCheckResult(checkAgentGit()) },
|
|
33515
33689
|
{ name: "bash", run: () => prereqToCheckResult(checkAgentBash()) },
|
|
33690
|
+
// --- tool-budget sanity (v1.20.0) ---
|
|
33691
|
+
// WARNS when the recommended ZELARI_* caps are unset/overridden, so users
|
|
33692
|
+
// learn why the agent stops mid-task without completing. Points to --fix-budget.
|
|
33693
|
+
{ name: "budget", run: () => checkBudget() },
|
|
33516
33694
|
// --- optional tool plugins (v1.5.0) ---
|
|
33517
33695
|
// Playwright / eslint / ruff / LSP servers. WARN-only (never critical):
|
|
33518
33696
|
// these power edge features that degrade silently when absent. Surfaced
|
|
@@ -33663,6 +33841,85 @@ var init_fixPath = __esm({
|
|
|
33663
33841
|
}
|
|
33664
33842
|
});
|
|
33665
33843
|
|
|
33844
|
+
// src/cli/utils/fixBudget.ts
|
|
33845
|
+
var fixBudget_exports = {};
|
|
33846
|
+
__export(fixBudget_exports, {
|
|
33847
|
+
RECOMMENDED_BUDGET: () => RECOMMENDED_BUDGET,
|
|
33848
|
+
repairWindowsBudget: () => repairWindowsBudget
|
|
33849
|
+
});
|
|
33850
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
33851
|
+
function powershell2(script) {
|
|
33852
|
+
try {
|
|
33853
|
+
const res = spawnSync4(
|
|
33854
|
+
"powershell.exe",
|
|
33855
|
+
["-NoProfile", "-NonInteractive", "-Command", script],
|
|
33856
|
+
{ encoding: "utf8" }
|
|
33857
|
+
);
|
|
33858
|
+
if (res.status === 0) return (res.stdout || "").trim();
|
|
33859
|
+
return "";
|
|
33860
|
+
} catch {
|
|
33861
|
+
return "";
|
|
33862
|
+
}
|
|
33863
|
+
}
|
|
33864
|
+
function repairWindowsBudget() {
|
|
33865
|
+
if (process.platform !== "win32") {
|
|
33866
|
+
const lines = Object.entries(RECOMMENDED_BUDGET).map(
|
|
33867
|
+
([k, v]) => ` export ${k}=${v}`
|
|
33868
|
+
);
|
|
33869
|
+
return {
|
|
33870
|
+
ok: false,
|
|
33871
|
+
error: `--fix-budget is Windows-only. On ${process.platform}, add to your shell profile (~/.bashrc or ~/.zshrc):
|
|
33872
|
+
${lines.join("\n")}`
|
|
33873
|
+
};
|
|
33874
|
+
}
|
|
33875
|
+
const applied = [];
|
|
33876
|
+
const skipped = [];
|
|
33877
|
+
let writeFailed = false;
|
|
33878
|
+
for (const [name, target] of Object.entries(RECOMMENDED_BUDGET)) {
|
|
33879
|
+
const current = powershell2(
|
|
33880
|
+
`[Environment]::GetEnvironmentVariable('${name}','User')`
|
|
33881
|
+
);
|
|
33882
|
+
if (current === target) {
|
|
33883
|
+
skipped.push(name);
|
|
33884
|
+
continue;
|
|
33885
|
+
}
|
|
33886
|
+
powershell2(
|
|
33887
|
+
`[Environment]::SetEnvironmentVariable('${name}', ${JSON.stringify(target)}, 'User')`
|
|
33888
|
+
);
|
|
33889
|
+
const reread = powershell2(
|
|
33890
|
+
`[Environment]::GetEnvironmentVariable('${name}','User')`
|
|
33891
|
+
);
|
|
33892
|
+
if (reread === target) {
|
|
33893
|
+
applied.push(name);
|
|
33894
|
+
} else {
|
|
33895
|
+
writeFailed = true;
|
|
33896
|
+
}
|
|
33897
|
+
}
|
|
33898
|
+
if (writeFailed) {
|
|
33899
|
+
return {
|
|
33900
|
+
ok: false,
|
|
33901
|
+
error: "PowerShell write did not take effect for at least one variable (permission denied? run as the same user that owns the install)"
|
|
33902
|
+
};
|
|
33903
|
+
}
|
|
33904
|
+
return {
|
|
33905
|
+
ok: true,
|
|
33906
|
+
alreadyOk: applied.length === 0,
|
|
33907
|
+
applied,
|
|
33908
|
+
skipped
|
|
33909
|
+
};
|
|
33910
|
+
}
|
|
33911
|
+
var RECOMMENDED_BUDGET;
|
|
33912
|
+
var init_fixBudget = __esm({
|
|
33913
|
+
"src/cli/utils/fixBudget.ts"() {
|
|
33914
|
+
"use strict";
|
|
33915
|
+
RECOMMENDED_BUDGET = {
|
|
33916
|
+
ZELARI_MAX_TOOL_LOOP_HARD: "180",
|
|
33917
|
+
ZELARI_MAX_TOOL_LOOP_ITERATIONS: "60",
|
|
33918
|
+
ZELARI_CONTEXT_LIMIT: "400000"
|
|
33919
|
+
};
|
|
33920
|
+
}
|
|
33921
|
+
});
|
|
33922
|
+
|
|
33666
33923
|
// src/cli/main.ts
|
|
33667
33924
|
import React15 from "react";
|
|
33668
33925
|
import { render } from "ink";
|
|
@@ -37544,7 +37801,7 @@ function estimateHistoryTokens(messages) {
|
|
|
37544
37801
|
}
|
|
37545
37802
|
function resolveContextLimit() {
|
|
37546
37803
|
return envNumber(process.env.ZELARI_CONTEXT_LIMIT, {
|
|
37547
|
-
default:
|
|
37804
|
+
default: 4e5,
|
|
37548
37805
|
min: 4e3,
|
|
37549
37806
|
max: 2e6
|
|
37550
37807
|
});
|
|
@@ -37553,7 +37810,7 @@ function applyBudgetPolicy(history2, phase2, opts) {
|
|
|
37553
37810
|
const contextLimit = resolveContextLimit();
|
|
37554
37811
|
const warnings = [];
|
|
37555
37812
|
let historyTurns = phase2 === "plan" ? envNumber(process.env.ZELARI_HISTORY_TURNS, { default: 8, min: 0 }) : envNumber(process.env.ZELARI_HISTORY_TURNS, { default: 6, min: 0 });
|
|
37556
|
-
let maxToolLoopIterations = phase2 === "plan" ? envNumber(process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS, { default:
|
|
37813
|
+
let maxToolLoopIterations = phase2 === "plan" ? envNumber(process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS, { default: 60, min: 1 }) : envNumber(process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS, { default: 120, min: 1 });
|
|
37557
37814
|
let hist = history2;
|
|
37558
37815
|
let estimated = estimateHistoryTokens(hist);
|
|
37559
37816
|
const sessionExtra = opts?.sessionTokens ?? 0;
|
|
@@ -37773,7 +38030,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
|
|
|
37773
38030
|
const toolList = openAiTools.map((t) => `- ${t.function.name}: ${t.function.description}`).join("\n");
|
|
37774
38031
|
const resolvedShell = resolveShell();
|
|
37775
38032
|
const isWindows = process.platform === "win32";
|
|
37776
|
-
const shellGuidance = resolvedShell.isBash ? `The bash tool runs commands via Git Bash / MSYS2 (${resolvedShell.shell}). Write POSIX commands: ls, grep, $VAR, &&, /c/Users/... all work.` : isWindows ? `The bash tool runs commands via cmd.exe (Git Bash not found). Write Windows-native commands: use dir (not ls), %VAR% (not $VAR), avoid POSIX-only syntax.` : `The bash tool runs commands via /bin/sh.`;
|
|
38033
|
+
const shellGuidance = resolvedShell.isBash ? `The bash tool runs commands via Git Bash / MSYS2 (${resolvedShell.shell}). Write POSIX commands: ls, grep, $VAR, &&, /c/Users/... all work.` : resolvedShell.isPowerShell ? `The bash tool runs commands via PowerShell (${resolvedShell.shell}). Write PowerShell syntax: ls/cat/pwd aliases work, use \`\${env:VAR}\` (not %VAR%), pipe with |, && works in PS7+.` : isWindows ? `The bash tool runs commands via cmd.exe (Git Bash not found). Write Windows-native commands: use dir (not ls), %VAR% (not $VAR), avoid POSIX-only syntax.` : `The bash tool runs commands via /bin/sh.`;
|
|
37777
38034
|
const nonInteractiveGuidance = "The shell is NON-INTERACTIVE (stdin closed): commands that prompt for input fail immediately. Always pass non-interactive flags (--yes, -y, --template, --force). If a scaffolder still insists on prompting (e.g. `npm create vite` in a non-empty directory), do NOT retry it \u2014 scaffold into a fresh empty subdirectory and move the files, or write package.json/configs/sources yourself with write_file, then run `npm install`.";
|
|
37778
38035
|
const planPhaseBlock = workPhase === "plan" ? [
|
|
37779
38036
|
"# Work Phase: PLAN",
|
|
@@ -43141,7 +43398,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
|
|
|
43141
43398
|
workspaceContext: composed.workspaceContext,
|
|
43142
43399
|
...composed.ragContext ? { ragContext: composed.ragContext } : {},
|
|
43143
43400
|
maxToolLoopIterations: envNumber(process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS, {
|
|
43144
|
-
default:
|
|
43401
|
+
default: 60,
|
|
43145
43402
|
min: 1
|
|
43146
43403
|
}),
|
|
43147
43404
|
...(() => {
|
|
@@ -44036,9 +44293,31 @@ function pickRootComponent() {
|
|
|
44036
44293
|
}
|
|
44037
44294
|
process.exit(1);
|
|
44038
44295
|
}
|
|
44296
|
+
if (argv.includes("--fix-budget") || argv.includes("fix-budget")) {
|
|
44297
|
+
const { repairWindowsBudget: repairWindowsBudget2 } = (init_fixBudget(), __toCommonJS(fixBudget_exports));
|
|
44298
|
+
const result = repairWindowsBudget2();
|
|
44299
|
+
const green = "\x1B[32m";
|
|
44300
|
+
const red = "\x1B[31m";
|
|
44301
|
+
const dim = "\x1B[2m";
|
|
44302
|
+
const reset = "\x1B[0m";
|
|
44303
|
+
if (result.ok) {
|
|
44304
|
+
if (result.alreadyOk) {
|
|
44305
|
+
console.log(`${green}\u2714${reset} budget variables already at recommended values (${result.skipped.join(", ")})`);
|
|
44306
|
+
} else {
|
|
44307
|
+
console.log(`${green}\u2714${reset} applied budget variables: ${result.applied.join(", ")}`);
|
|
44308
|
+
if (result.skipped.length > 0) {
|
|
44309
|
+
console.log(`${dim}already set: ${result.skipped.join(", ")}${reset}`);
|
|
44310
|
+
}
|
|
44311
|
+
console.log(`${dim}open a NEW terminal for the changes to take effect${reset}`);
|
|
44312
|
+
}
|
|
44313
|
+
process.exit(0);
|
|
44314
|
+
}
|
|
44315
|
+
console.error(`${red}\u2717${reset} ${result.error}`);
|
|
44316
|
+
process.exit(1);
|
|
44317
|
+
}
|
|
44039
44318
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
44040
44319
|
console.log(
|
|
44041
|
-
"zelari-code \u2014 AI Council coding agent CLI.\n\nUsage: zelari-code [options]\n\nOptions:\n --version, -v Print version and exit\n --help, -h Print this help and exit\n --doctor Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\n --fix-path Add the npm global prefix to the user PATH\n (Windows only; fixes 'command not found' after install)\n --skip-checks Skip the boot-time prerequisite check\n (alias for ZELARI_SKIP_PREFLIGHT=1)\n --no-wizard Skip the first-run wizard\n --reset-config Re-run the wizard (clears provider.json on commit)\n --headless Run a single task without mounting the TUI\n --task <text> Task prompt (required in headless mode)\n --output json|plain Output format (default: json)\n --mode agent|council|zelari Dispatch mode (default: agent)\n --council Alias for --mode council\n --phase plan|build Work phase (default: build)\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n --print-config Print provider/model config as JSON (no secrets)\n --plugins-status JSON status of optional plugins (Playwright, eslint, \u2026)\n --plugins-install <id> Install plugin (playwright also fetches Chromium)\n --cwd <path> Workspace for -D installs (default: process.cwd())\n --set-config Persist provider/model/endpoint\n --provider <id> Set active provider\n --model <id> Set model for that provider\n --endpoint <url> Custom OpenAI-compatible base URL\n --endpoint-clear Remove custom endpoint override\n --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\n --discover-models Refresh model list for a provider\n --provider <id> Provider (default: active)\n --print-mcp Print MCP server config (user + project)\n --cwd <path> Project root for .zelari/mcp.json\n --set-mcp Add/update an MCP server entry\n --name <id> Server name (required)\n --command <bin> Executable (required)\n --args <json> JSON array of args (optional)\n --scope user|project Default: user\n --enabled true|false Default: true\n --cwd <path> Required when scope=project\n --set-mcp-preset Install a named MCP preset (e.g. cua)\n --preset cua Cua Driver desktop computer-use (MCP)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-mcp Remove an MCP server entry\n --name <id> --scope user|project [--cwd <path>]\n --print-ssh-targets Print SSH deploy/monitor targets\n --set-ssh-target Upsert target (--json '{...}' or flags)\n --remove-ssh-target --id <id>\n --test-ssh-target --id <id> (BatchMode ssh true)\n --print-ssh-pubkey --path <private-or-.pub> (display public key)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ZELARI_SKIP_PREFLIGHT=1 Skip the boot prerequisite check\n ZELARI_NO_PLUGIN_PROMPT=1 Skip the boot plugin-install prompt\n ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
44320
|
+
"zelari-code \u2014 AI Council coding agent CLI.\n\nUsage: zelari-code [options]\n\nOptions:\n --version, -v Print version and exit\n --help, -h Print this help and exit\n --doctor Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\n --fix-path Add the npm global prefix to the user PATH\n (Windows only; fixes 'command not found' after install)\n --fix-budget Set recommended ZELARI_MAX_TOOL_LOOP_HARD=180,\n ZELARI_MAX_TOOL_LOOP_ITERATIONS=60, ZELARI_CONTEXT_LIMIT=400000\n at User scope (prevents the agent stopping mid-task)\n --skip-checks Skip the boot-time prerequisite check\n (alias for ZELARI_SKIP_PREFLIGHT=1)\n --no-wizard Skip the first-run wizard\n --reset-config Re-run the wizard (clears provider.json on commit)\n --headless Run a single task without mounting the TUI\n --task <text> Task prompt (required in headless mode)\n --output json|plain Output format (default: json)\n --mode agent|council|zelari Dispatch mode (default: agent)\n --council Alias for --mode council\n --phase plan|build Work phase (default: build)\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n --print-config Print provider/model config as JSON (no secrets)\n --plugins-status JSON status of optional plugins (Playwright, eslint, \u2026)\n --plugins-install <id> Install plugin (playwright also fetches Chromium)\n --cwd <path> Workspace for -D installs (default: process.cwd())\n --set-config Persist provider/model/endpoint\n --provider <id> Set active provider\n --model <id> Set model for that provider\n --endpoint <url> Custom OpenAI-compatible base URL\n --endpoint-clear Remove custom endpoint override\n --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\n --discover-models Refresh model list for a provider\n --provider <id> Provider (default: active)\n --print-mcp Print MCP server config (user + project)\n --cwd <path> Project root for .zelari/mcp.json\n --set-mcp Add/update an MCP server entry\n --name <id> Server name (required)\n --command <bin> Executable (required)\n --args <json> JSON array of args (optional)\n --scope user|project Default: user\n --enabled true|false Default: true\n --cwd <path> Required when scope=project\n --set-mcp-preset Install a named MCP preset (e.g. cua)\n --preset cua Cua Driver desktop computer-use (MCP)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-mcp Remove an MCP server entry\n --name <id> --scope user|project [--cwd <path>]\n --print-ssh-targets Print SSH deploy/monitor targets\n --set-ssh-target Upsert target (--json '{...}' or flags)\n --remove-ssh-target --id <id>\n --test-ssh-target --id <id> (BatchMode ssh true)\n --print-ssh-pubkey --path <private-or-.pub> (display public key)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ZELARI_SKIP_PREFLIGHT=1 Skip the boot prerequisite check\n ZELARI_NO_PLUGIN_PROMPT=1 Skip the boot plugin-install prompt\n ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
44042
44321
|
);
|
|
44043
44322
|
process.exit(0);
|
|
44044
44323
|
}
|