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.
- package/dist/core/agent-session.js +3 -3
- package/dist/core/keybindings.js +1 -0
- package/dist/core/sdk.js +3 -3
- package/dist/core/system-prompt.js +5 -1
- package/dist/core/tools/bash.js +28 -3
- package/dist/core/tools/index.js +12 -2
- package/dist/core/tools/web-search.js +162 -0
- package/dist/migrations.js +36 -2
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +5 -6
- package/dist/modes/interactive/interactive-mode.js +353 -74
- package/dist/utils/shell.js +70 -39
- package/node_modules/@operator/ai/dist/providers/openai-completions.js +6 -1
- package/package.json +1 -1
package/dist/utils/shell.js
CHANGED
|
@@ -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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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(
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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:
|
|
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
|
|
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.
|
|
57
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
86
|
+
powershellPaths.push(`${programFilesX86}\\Git\\bin\\bash.exe`);
|
|
65
87
|
}
|
|
66
|
-
|
|
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
|
|
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
|
|
104
|
+
return getShellConfigForExecutable(bashOnPath);
|
|
75
105
|
}
|
|
76
|
-
throw new Error(`No
|
|
77
|
-
` 1. Install
|
|
78
|
-
` 2.
|
|
79
|
-
|
|
80
|
-
|
|
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
|
|
115
|
+
return getShellConfigForExecutable("/bin/bash");
|
|
85
116
|
}
|
|
86
117
|
const bashOnPath = findBashOnPath();
|
|
87
118
|
if (bashOnPath) {
|
|
88
|
-
return
|
|
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.
|
|
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.",
|