pi-web-ui 0.19.1 → 0.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.
@@ -103,16 +103,50 @@ export async function saveCommandsFile(workspaceRoot, commands) {
103
103
  }
104
104
  }
105
105
  const isWindows = process.platform === "win32";
106
+ /** `-i` makes bash interactive; cmd.exe / powershell.exe are interactive on their own. */
107
+ function bashArgs(shell) {
108
+ return /[\\/]bash(\.exe)?$/i.test(shell) ? ["-i"] : [];
109
+ }
106
110
  /**
107
- * Interactive shell for PTYs. Windows has no $SHELL: use Git Bash if the user
108
- * has it, otherwise the console host from $COMSPEC (always set → cmd.exe).
109
- * POSIX uses the user's login shell, falling back to bash.
111
+ * Interactive shell for PTYs.
112
+ * - Windows: prefer bash — it matches the SDK's bash tool, so the agent and
113
+ * the terminal speak the same shell language (no more PowerShell/bash
114
+ * 混用 that leaves heredocs / `&&` / `<<` hanging or erroring). Order:
115
+ * 1. PI_WEB_SHELL (explicit override)
116
+ * 2. $SHELL when it exists on disk (user launched from a Git Bash session)
117
+ * 3. Git Bash install paths (ProgramFiles / ProgramFiles(x86))
118
+ * 4. busybox-w32 fallback in <home>/.pi-web/bin/bash.exe (ensure-bash.ts
119
+ * downloads it automatically when 2–3 are absent)
120
+ * 5. $COMSPEC (cmd.exe — always set)
121
+ * 6. powershell.exe (last resort)
122
+ * - POSIX: the user's login shell, falling back to bash.
123
+ * Resolved per terminal spawn (not at module load) so a busybox download that
124
+ * finishes after startup is picked up by the next terminal.
110
125
  */
111
- const SHELL = isWindows
112
- ? process.env.SHELL || process.env.COMSPEC || "powershell.exe"
113
- : process.env.SHELL || "bash";
114
- /** `-i` is POSIX-only; cmd.exe / powershell.exe start interactively on their own. */
115
- const SHELL_ARGS = isWindows ? [] : ["-i"];
126
+ function resolveShell() {
127
+ if (isWindows) {
128
+ const explicit = process.env.PI_WEB_SHELL;
129
+ if (explicit)
130
+ return { shell: explicit, args: bashArgs(explicit) };
131
+ const she = process.env.SHELL;
132
+ if (she && existsSync(she))
133
+ return { shell: she, args: bashArgs(she) };
134
+ const pf = process.env.ProgramFiles;
135
+ const pf86 = process.env["ProgramFiles(x86)"];
136
+ for (const cand of [
137
+ pf ? join(pf, "Git", "bin", "bash.exe") : "",
138
+ pf86 ? join(pf86, "Git", "bin", "bash.exe") : "",
139
+ ]) {
140
+ if (cand && existsSync(cand))
141
+ return { shell: cand, args: ["-i"] };
142
+ }
143
+ const busybox = join(homedir(), ".pi-web", "bin", "bash.exe");
144
+ if (existsSync(busybox))
145
+ return { shell: busybox, args: ["-i"] };
146
+ return { shell: process.env.COMSPEC || "powershell.exe", args: [] };
147
+ }
148
+ return { shell: process.env.SHELL || "bash", args: ["-i"] };
149
+ }
116
150
  /**
117
151
  * Environment for spawned shells. System services (launchd/systemd) run with
118
152
  * no locale variables, which puts the shell in the C locale: its line editor
@@ -302,7 +336,8 @@ export class TerminalManager {
302
336
  repairSpawnHelperPermissions();
303
337
  let pty;
304
338
  try {
305
- pty = spawn(SHELL, SHELL_ARGS, {
339
+ const { shell, args } = resolveShell();
340
+ pty = spawn(shell, args, {
306
341
  name: "xterm-256color",
307
342
  cols: Math.max(2, Math.floor(cols) || 80),
308
343
  rows: Math.max(2, Math.floor(rows) || 24),
package/package.json CHANGED
@@ -1,87 +1,87 @@
1
- {
2
- "name": "pi-web-ui",
3
- "version": "0.19.1",
4
- "description": "Web chat interface for the pi coding agent, powered by the pi SDK (@earendil-works/pi-coding-agent) — one-command run, Docker/systemd/launchd deployable",
5
- "license": "MIT",
6
- "type": "module",
7
- "bin": {
8
- "pi-web-ui": "bin/pi-web-ui.mjs"
9
- },
10
- "main": "dist/server/index.js",
11
- "files": [
12
- "bin/",
13
- "dist/",
14
- "web/dist/",
15
- "web/public/",
16
- "deploy/",
17
- "extensions/",
18
- "README.md",
19
- "LICENSE"
20
- ],
21
- "keywords": [
22
- "pi",
23
- "pi-package",
24
- "coding-agent",
25
- "ai",
26
- "chat",
27
- "web-ui",
28
- "terminal",
29
- "llm"
30
- ],
31
- "repository": {
32
- "type": "git",
33
- "url": "git+https://github.com/xing-shuyin/pi-web-ui.git"
34
- },
35
- "pi": {
36
- "extensions": [
37
- "./extensions"
38
- ]
39
- },
40
- "engines": {
41
- "node": ">=22.19.0"
42
- },
43
- "scripts": {
44
- "prepublishOnly": "npm run build",
45
- "dev": "concurrently -k -n server,web -c blue,green \"npm:dev:server\" \"npm:dev:web\"",
46
- "dev:server": "node --watch --import tsx server/index.ts",
47
- "dev:web": "vite --config web/vite.config.ts",
48
- "build": "npm run build:web && npm run build:server",
49
- "build:web": "vite build --config web/vite.config.ts",
50
- "build:server": "tsc -p tsconfig.server.json",
51
- "typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit",
52
- "test:freeze": "node freeze-test.mjs",
53
- "start": "node dist/server/index.js"
54
- },
55
- "dependencies": {
56
- "@earendil-works/pi-coding-agent": "^0.83.0",
57
- "@xterm/addon-fit": "^0.11.0",
58
- "@xterm/xterm": "^6.0.0",
59
- "express": "^4.21.2",
60
- "highlight.js": "^11.10.0",
61
- "node-pty": "^1.1.0",
62
- "react": "^18.3.1",
63
- "react-dom": "^18.3.1",
64
- "react-icons": "^5.7.0",
65
- "react-markdown": "^9.0.1",
66
- "rehype-highlight": "^7.0.1",
67
- "remark-gfm": "^4.0.0",
68
- "typebox": "^1.3.14",
69
- "ws": "^8.18.0"
70
- },
71
- "devDependencies": {
72
- "@types/express": "^4.17.21",
73
- "@types/node": "^22.10.0",
74
- "@types/react": "^18.3.12",
75
- "@types/react-dom": "^18.3.1",
76
- "@types/ws": "^8.5.13",
77
- "@vitejs/plugin-react": "^4.3.4",
78
- "concurrently": "^9.1.0",
79
- "playwright-core": "^1.62.1",
80
- "tsx": "^4.19.2",
81
- "typescript": "^5.7.2",
82
- "vite": "^6.0.3"
83
- },
84
- "allowScripts": {
85
- "node-pty@1.1.0": true
86
- }
87
- }
1
+ {
2
+ "name": "pi-web-ui",
3
+ "version": "0.20.0",
4
+ "description": "Web chat interface for the pi coding agent, powered by the pi SDK (@earendil-works/pi-coding-agent) — one-command run, Docker/systemd/launchd deployable",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "pi-web-ui": "bin/pi-web-ui.mjs"
9
+ },
10
+ "main": "dist/server/index.js",
11
+ "files": [
12
+ "bin/",
13
+ "dist/",
14
+ "web/dist/",
15
+ "web/public/",
16
+ "deploy/",
17
+ "extensions/",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "keywords": [
22
+ "pi",
23
+ "pi-package",
24
+ "coding-agent",
25
+ "ai",
26
+ "chat",
27
+ "web-ui",
28
+ "terminal",
29
+ "llm"
30
+ ],
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/xing-shuyin/pi-web-ui.git"
34
+ },
35
+ "pi": {
36
+ "extensions": [
37
+ "./extensions"
38
+ ]
39
+ },
40
+ "engines": {
41
+ "node": ">=22.19.0"
42
+ },
43
+ "scripts": {
44
+ "prepublishOnly": "npm run build",
45
+ "dev": "concurrently -k -n server,web -c blue,green \"npm:dev:server\" \"npm:dev:web\"",
46
+ "dev:server": "node --watch --import tsx server/index.ts",
47
+ "dev:web": "vite --config web/vite.config.ts",
48
+ "build": "npm run build:web && npm run build:server",
49
+ "build:web": "vite build --config web/vite.config.ts",
50
+ "build:server": "tsc -p tsconfig.server.json",
51
+ "typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit",
52
+ "test:freeze": "node freeze-test.mjs",
53
+ "start": "node dist/server/index.js"
54
+ },
55
+ "dependencies": {
56
+ "@earendil-works/pi-coding-agent": "^0.83.0",
57
+ "@xterm/addon-fit": "^0.11.0",
58
+ "@xterm/xterm": "^6.0.0",
59
+ "express": "^4.21.2",
60
+ "highlight.js": "^11.10.0",
61
+ "node-pty": "^1.1.0",
62
+ "react": "^18.3.1",
63
+ "react-dom": "^18.3.1",
64
+ "react-icons": "^5.7.0",
65
+ "react-markdown": "^9.0.1",
66
+ "rehype-highlight": "^7.0.1",
67
+ "remark-gfm": "^4.0.0",
68
+ "typebox": "^1.3.14",
69
+ "ws": "^8.18.0"
70
+ },
71
+ "devDependencies": {
72
+ "@types/express": "^4.17.21",
73
+ "@types/node": "^22.10.0",
74
+ "@types/react": "^18.3.12",
75
+ "@types/react-dom": "^18.3.1",
76
+ "@types/ws": "^8.5.13",
77
+ "@vitejs/plugin-react": "^4.3.4",
78
+ "concurrently": "^9.1.0",
79
+ "playwright-core": "^1.62.1",
80
+ "tsx": "^4.19.2",
81
+ "typescript": "^5.7.2",
82
+ "vite": "^6.0.3"
83
+ },
84
+ "allowScripts": {
85
+ "node-pty@1.1.0": true
86
+ }
87
+ }