pzero-operator 0.1.6 → 0.1.8

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.
@@ -2,17 +2,15 @@ import { existsSync } from "node:fs";
2
2
  import { delimiter } from "node:path";
3
3
  import { spawn, spawnSync } from "child_process";
4
4
  import { getBinDir } from "../config.js";
5
- /**
6
- * Find bash executable on PATH (cross-platform)
7
- */
8
- function findBashOnPath() {
9
- if (process.platform === "win32") {
10
- // Windows: Use 'where' and verify file exists (where can return non-existent paths)
5
+ function findExecutableOnPath(candidates) {
6
+ const commands = Array.isArray(candidates) ? candidates : [candidates];
7
+ const lookupCommand = process.platform === "win32" ? "where" : "which";
8
+ for (const candidate of commands) {
11
9
  try {
12
- const result = spawnSync("where", ["bash.exe"], { encoding: "utf-8", timeout: 5000 });
10
+ const result = spawnSync(lookupCommand, [candidate], { encoding: "utf-8", timeout: 5000 });
13
11
  if (result.status === 0 && result.stdout) {
14
12
  const firstMatch = result.stdout.trim().split(/\r?\n/)[0];
15
- if (firstMatch && existsSync(firstMatch)) {
13
+ if (firstMatch && (process.platform !== "win32" || existsSync(firstMatch))) {
16
14
  return firstMatch;
17
15
  }
18
16
  }
@@ -20,74 +18,107 @@ function findBashOnPath() {
20
18
  catch {
21
19
  // Ignore errors
22
20
  }
23
- return null;
24
21
  }
25
- // Unix: Use 'which' and trust its output (handles Termux and special filesystems)
26
- try {
27
- const result = spawnSync("which", ["bash"], { encoding: "utf-8", timeout: 5000 });
28
- if (result.status === 0 && result.stdout) {
29
- const firstMatch = result.stdout.trim().split(/\r?\n/)[0];
30
- if (firstMatch) {
31
- return firstMatch;
32
- }
22
+ return null;
23
+ }
24
+ function getShellConfigForExecutable(shellPath) {
25
+ const normalized = shellPath.toLowerCase();
26
+ if (process.platform === "win32") {
27
+ if (normalized.endsWith("pwsh.exe") || normalized.endsWith("\\pwsh")) {
28
+ return {
29
+ shell: shellPath,
30
+ args: ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command"],
31
+ kind: "powershell",
32
+ displayName: "PowerShell",
33
+ };
34
+ }
35
+ if (normalized.endsWith("powershell.exe") || normalized.endsWith("\\powershell")) {
36
+ return {
37
+ shell: shellPath,
38
+ args: ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command"],
39
+ kind: "powershell",
40
+ displayName: "Windows PowerShell",
41
+ };
33
42
  }
34
43
  }
35
- catch {
36
- // Ignore errors
37
- }
38
- return null;
44
+ return {
45
+ shell: shellPath,
46
+ args: ["-c"],
47
+ kind: "bash",
48
+ displayName: process.platform === "win32" ? "Bash" : "Shell",
49
+ };
50
+ }
51
+ /**
52
+ * Find bash executable on PATH (cross-platform)
53
+ */
54
+ function findBashOnPath() {
55
+ return process.platform === "win32" ? findExecutableOnPath("bash.exe") : findExecutableOnPath("bash");
39
56
  }
40
57
  /**
41
58
  * Resolve shell configuration based on platform and an optional explicit shell path.
42
59
  * Resolution order:
43
60
  * 1. User-specified shellPath
44
- * 2. On Windows: Git Bash in known locations, then bash on PATH
61
+ * 2. On Windows: PowerShell Core, Windows PowerShell, Git Bash, then bash on PATH
45
62
  * 3. On Unix: /bin/bash, then bash on PATH, then fallback to sh
46
63
  */
47
64
  export function getShellConfig(customShellPath) {
48
65
  // 1. Check user-specified shell path
49
66
  if (customShellPath) {
50
67
  if (existsSync(customShellPath)) {
51
- return { shell: customShellPath, args: ["-c"] };
68
+ return getShellConfigForExecutable(customShellPath);
52
69
  }
53
70
  throw new Error(`Custom shell path not found: ${customShellPath}`);
54
71
  }
55
72
  if (process.platform === "win32") {
56
- // 2. Try Git Bash in known locations
57
- const paths = [];
73
+ // 2. Prefer native PowerShell shells on Windows.
74
+ const pwshOnPath = findExecutableOnPath(["pwsh.exe", "pwsh"]);
75
+ if (pwshOnPath) {
76
+ return getShellConfigForExecutable(pwshOnPath);
77
+ }
78
+ const powershellPaths = [];
58
79
  const programFiles = process.env.ProgramFiles;
59
80
  if (programFiles) {
60
- paths.push(`${programFiles}\\Git\\bin\\bash.exe`);
81
+ powershellPaths.push(`${programFiles}\\PowerShell\\7\\pwsh.exe`);
82
+ powershellPaths.push(`${programFiles}\\Git\\bin\\bash.exe`);
61
83
  }
62
84
  const programFilesX86 = process.env["ProgramFiles(x86)"];
63
85
  if (programFilesX86) {
64
- paths.push(`${programFilesX86}\\Git\\bin\\bash.exe`);
86
+ powershellPaths.push(`${programFilesX86}\\Git\\bin\\bash.exe`);
65
87
  }
66
- for (const path of paths) {
88
+ const systemRoot = process.env.SystemRoot;
89
+ if (systemRoot) {
90
+ powershellPaths.push(`${systemRoot}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`);
91
+ }
92
+ for (const path of powershellPaths) {
67
93
  if (existsSync(path)) {
68
- return { shell: path, args: ["-c"] };
94
+ return getShellConfigForExecutable(path);
69
95
  }
70
96
  }
97
+ const powershellOnPath = findExecutableOnPath(["powershell.exe", "powershell"]);
98
+ if (powershellOnPath) {
99
+ return getShellConfigForExecutable(powershellOnPath);
100
+ }
71
101
  // 3. Fallback: search bash.exe on PATH (Cygwin, MSYS2, WSL, etc.)
72
102
  const bashOnPath = findBashOnPath();
73
103
  if (bashOnPath) {
74
- return { shell: bashOnPath, args: ["-c"] };
104
+ return getShellConfigForExecutable(bashOnPath);
75
105
  }
76
- throw new Error(`No bash shell found. Options:\n` +
77
- ` 1. Install Git for Windows: https://git-scm.com/download/win\n` +
78
- ` 2. Add your bash to PATH (Cygwin, MSYS2, etc.)\n` +
79
- " 3. Set shellPath in settings.json\n\n" +
80
- `Searched Git Bash in:\n${paths.map((p) => ` ${p}`).join("\n")}`);
106
+ throw new Error(`No supported shell found on Windows. Options:\n` +
107
+ ` 1. Install PowerShell 7: https://github.com/PowerShell/PowerShell\n` +
108
+ ` 2. Use built-in Windows PowerShell\n` +
109
+ ` 3. Install Git for Windows: https://git-scm.com/download/win\n` +
110
+ " 4. Set shellPath in settings.json\n\n" +
111
+ `Searched common paths:\n${powershellPaths.map((p) => ` ${p}`).join("\n")}`);
81
112
  }
82
113
  // Unix: try /bin/bash, then bash on PATH, then fallback to sh
83
114
  if (existsSync("/bin/bash")) {
84
- return { shell: "/bin/bash", args: ["-c"] };
115
+ return getShellConfigForExecutable("/bin/bash");
85
116
  }
86
117
  const bashOnPath = findBashOnPath();
87
118
  if (bashOnPath) {
88
- return { shell: bashOnPath, args: ["-c"] };
119
+ return getShellConfigForExecutable(bashOnPath);
89
120
  }
90
- return { shell: "sh", args: ["-c"] };
121
+ return { shell: "sh", args: ["-c"], kind: "sh", displayName: "Shell" };
91
122
  }
92
123
  export function getShellEnv() {
93
124
  const binDir = getBinDir();
@@ -187,4 +218,4 @@ export function killProcessTree(pid) {
187
218
  }
188
219
  }
189
220
  }
190
- //# sourceMappingURL=shell.js.map
221
+ //# sourceMappingURL=shell.js.map
@@ -396,6 +396,11 @@ function buildParams(model, context, options, compat = getCompat(model), cacheRe
396
396
  else if (options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) {
397
397
  // OpenAI-style reasoning_effort
398
398
  params.reasoning_effort = mapReasoningEffort(options.reasoningEffort, compat.reasoningEffortMap);
399
+ // LiteLLM proxies may reject OpenAI-only params unless they are explicitly allow-listed.
400
+ // Alem AI Plus sits behind LiteLLM and returns UnsupportedParamsError without this field.
401
+ if (model.baseUrl.includes("llm.alem.ai")) {
402
+ params.allowed_openai_params = ["reasoning_effort"];
403
+ }
399
404
  }
400
405
  // OpenRouter provider routing preferences
401
406
  if (model.baseUrl.includes("openrouter.ai") && model.compat?.openRouterRouting) {
@@ -851,4 +856,4 @@ function getCompat(model) {
851
856
  sendSessionAffinityHeaders: model.compat.sendSessionAffinityHeaders ?? detected.sendSessionAffinityHeaders,
852
857
  };
853
858
  }
854
- //# sourceMappingURL=openai-completions.js.map
859
+ //# sourceMappingURL=openai-completions.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pzero-operator",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Operator is a coding-first terminal AI agent from ProjectZero for software development, shell execution, local project workflows, and broader device-level operator control.",