@linxiraos/pi-utils 1.0.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/CHANGELOG.md +449 -0
- package/README.md +36 -0
- package/dist/types/abortable.d.ts +32 -0
- package/dist/types/acp/connection.d.ts +118 -0
- package/dist/types/acp/protocol.d.ts +526 -0
- package/dist/types/acp/schema.d.ts +41 -0
- package/dist/types/acp/stream.d.ts +8 -0
- package/dist/types/acp/transport.d.ts +81 -0
- package/dist/types/acp.d.ts +6 -0
- package/dist/types/async.d.ts +20 -0
- package/dist/types/binary.d.ts +17 -0
- package/dist/types/browsers.d.ts +68 -0
- package/dist/types/chalk.d.ts +125 -0
- package/dist/types/cli.d.ts +134 -0
- package/dist/types/color.d.ts +102 -0
- package/dist/types/dates.d.ts +7 -0
- package/dist/types/dirs.d.ts +282 -0
- package/dist/types/docx/converter.d.ts +46 -0
- package/dist/types/docx/xml.d.ts +26 -0
- package/dist/types/docx/zip.d.ts +6 -0
- package/dist/types/docx.d.ts +11 -0
- package/dist/types/dom/core.d.ts +431 -0
- package/dist/types/dom/parser.d.ts +7 -0
- package/dist/types/dom/selector.d.ts +5 -0
- package/dist/types/dom.d.ts +5 -0
- package/dist/types/env.d.ts +124 -0
- package/dist/types/fetch-retry.d.ts +96 -0
- package/dist/types/file-lock.d.ts +23 -0
- package/dist/types/format.d.ts +37 -0
- package/dist/types/frontmatter.d.ts +46 -0
- package/dist/types/fs-error.d.ts +31 -0
- package/dist/types/glob.d.ts +28 -0
- package/dist/types/headers.d.ts +34 -0
- package/dist/types/index.d.ts +39 -0
- package/dist/types/json-parse.d.ts +74 -0
- package/dist/types/json.d.ts +14 -0
- package/dist/types/logger/rotating-file.d.ts +18 -0
- package/dist/types/logger.d.ts +96 -0
- package/dist/types/loop-phase.d.ts +10 -0
- package/dist/types/lru.d.ts +46 -0
- package/dist/types/marked/core.d.ts +445 -0
- package/dist/types/marked.d.ts +2 -0
- package/dist/types/mermaid-ascii.d.ts +11 -0
- package/dist/types/mime.d.ts +29 -0
- package/dist/types/module-timer.d.ts +1 -0
- package/dist/types/path-tree.d.ts +76 -0
- package/dist/types/path.d.ts +2 -0
- package/dist/types/peek-file.d.ts +29 -0
- package/dist/types/postmortem.d.ts +104 -0
- package/dist/types/process-name.d.ts +7 -0
- package/dist/types/procmgr.d.ts +74 -0
- package/dist/types/prompt.d.ts +18 -0
- package/dist/types/ptree.d.ts +110 -0
- package/dist/types/readability/readability.d.ts +9 -0
- package/dist/types/readability/readerable.d.ts +10 -0
- package/dist/types/readability/types.d.ts +70 -0
- package/dist/types/readability.d.ts +4 -0
- package/dist/types/ring.d.ts +93 -0
- package/dist/types/runtime-install.d.ts +78 -0
- package/dist/types/sanitize-text.d.ts +29 -0
- package/dist/types/snowflake.d.ts +25 -0
- package/dist/types/stderr-guard.d.ts +22 -0
- package/dist/types/stream.d.ts +67 -0
- package/dist/types/tab-spacing.d.ts +24 -0
- package/dist/types/temp.d.ts +17 -0
- package/dist/types/template.d.ts +62 -0
- package/dist/types/timing-buffer.d.ts +22 -0
- package/dist/types/tls-fetch.d.ts +37 -0
- package/dist/types/turndown/gfm.d.ts +11 -0
- package/dist/types/turndown/html.d.ts +5 -0
- package/dist/types/turndown/service.d.ts +21 -0
- package/dist/types/turndown/types.d.ts +70 -0
- package/dist/types/turndown.d.ts +4 -0
- package/dist/types/type-guards.d.ts +5 -0
- package/dist/types/vendor/mermaid-ascii/ascii/ansi.d.ts +41 -0
- package/dist/types/vendor/mermaid-ascii/ascii/canvas.d.ts +89 -0
- package/dist/types/vendor/mermaid-ascii/ascii/class-diagram.d.ts +7 -0
- package/dist/types/vendor/mermaid-ascii/ascii/converter.d.ts +12 -0
- package/dist/types/vendor/mermaid-ascii/ascii/draw.d.ts +66 -0
- package/dist/types/vendor/mermaid-ascii/ascii/edge-bundling.d.ts +48 -0
- package/dist/types/vendor/mermaid-ascii/ascii/edge-routing.d.ts +43 -0
- package/dist/types/vendor/mermaid-ascii/ascii/er-diagram.d.ts +7 -0
- package/dist/types/vendor/mermaid-ascii/ascii/grid.d.ts +56 -0
- package/dist/types/vendor/mermaid-ascii/ascii/index.d.ts +65 -0
- package/dist/types/vendor/mermaid-ascii/ascii/multiline-utils.d.ts +27 -0
- package/dist/types/vendor/mermaid-ascii/ascii/pathfinder.d.ts +17 -0
- package/dist/types/vendor/mermaid-ascii/ascii/sequence.d.ts +7 -0
- package/dist/types/vendor/mermaid-ascii/ascii/shapes/circle.d.ts +11 -0
- package/dist/types/vendor/mermaid-ascii/ascii/shapes/corners.d.ts +34 -0
- package/dist/types/vendor/mermaid-ascii/ascii/shapes/diamond.d.ts +11 -0
- package/dist/types/vendor/mermaid-ascii/ascii/shapes/hexagon.d.ts +11 -0
- package/dist/types/vendor/mermaid-ascii/ascii/shapes/index.d.ts +26 -0
- package/dist/types/vendor/mermaid-ascii/ascii/shapes/rectangle.d.ts +31 -0
- package/dist/types/vendor/mermaid-ascii/ascii/shapes/rounded.d.ts +11 -0
- package/dist/types/vendor/mermaid-ascii/ascii/shapes/special.d.ts +59 -0
- package/dist/types/vendor/mermaid-ascii/ascii/shapes/stadium.d.ts +17 -0
- package/dist/types/vendor/mermaid-ascii/ascii/shapes/state.d.ts +30 -0
- package/dist/types/vendor/mermaid-ascii/ascii/shapes/types.d.ts +55 -0
- package/dist/types/vendor/mermaid-ascii/ascii/types.d.ts +206 -0
- package/dist/types/vendor/mermaid-ascii/ascii/validate.d.ts +51 -0
- package/dist/types/vendor/mermaid-ascii/ascii/xychart.d.ts +2 -0
- package/dist/types/vendor/mermaid-ascii/class/parser.d.ts +6 -0
- package/dist/types/vendor/mermaid-ascii/class/types.d.ts +102 -0
- package/dist/types/vendor/mermaid-ascii/er/parser.d.ts +6 -0
- package/dist/types/vendor/mermaid-ascii/er/types.d.ts +76 -0
- package/dist/types/vendor/mermaid-ascii/index.d.ts +1 -0
- package/dist/types/vendor/mermaid-ascii/multiline-utils.d.ts +9 -0
- package/dist/types/vendor/mermaid-ascii/parser.d.ts +7 -0
- package/dist/types/vendor/mermaid-ascii/sequence/parser.d.ts +6 -0
- package/dist/types/vendor/mermaid-ascii/sequence/types.d.ts +130 -0
- package/dist/types/vendor/mermaid-ascii/text-metrics.d.ts +21 -0
- package/dist/types/vendor/mermaid-ascii/types.d.ts +114 -0
- package/dist/types/vendor/mermaid-ascii/xychart/colors.d.ts +25 -0
- package/dist/types/vendor/mermaid-ascii/xychart/parser.d.ts +6 -0
- package/dist/types/vendor/mermaid-ascii/xychart/types.d.ts +145 -0
- package/dist/types/version.d.ts +18 -0
- package/dist/types/vterm/buffer.d.ts +99 -0
- package/dist/types/vterm/terminal.d.ts +44 -0
- package/dist/types/vterm.d.ts +8 -0
- package/dist/types/which.d.ts +37 -0
- package/dist/types/worker-host.d.ts +51 -0
- package/dist/types/xml.d.ts +31 -0
- package/package.json +59 -0
- package/src/abortable.ts +109 -0
- package/src/acp/connection.ts +344 -0
- package/src/acp/protocol.ts +466 -0
- package/src/acp/schema.ts +160 -0
- package/src/acp/stream.ts +82 -0
- package/src/acp/transport.ts +213 -0
- package/src/acp.ts +6 -0
- package/src/async.ts +91 -0
- package/src/binary.ts +50 -0
- package/src/browsers.ts +501 -0
- package/src/chalk.ts +312 -0
- package/src/cli.ts +529 -0
- package/src/color.ts +302 -0
- package/src/dates.ts +194 -0
- package/src/dirs.ts +1026 -0
- package/src/docx/converter.ts +681 -0
- package/src/docx/xml.ts +166 -0
- package/src/docx/zip.ts +87 -0
- package/src/docx.ts +20 -0
- package/src/dom/core.ts +1254 -0
- package/src/dom/parser.ts +370 -0
- package/src/dom/selector.ts +290 -0
- package/src/dom.ts +33 -0
- package/src/env.ts +400 -0
- package/src/fetch-retry.ts +379 -0
- package/src/file-lock.ts +69 -0
- package/src/format.ts +113 -0
- package/src/frontmatter.ts +205 -0
- package/src/fs-error.ts +56 -0
- package/src/glob.ts +189 -0
- package/src/headers.ts +167 -0
- package/src/index.ts +59 -0
- package/src/json-parse.ts +821 -0
- package/src/json.ts +23 -0
- package/src/logger/rotating-file.ts +149 -0
- package/src/logger.ts +798 -0
- package/src/loop-phase.ts +49 -0
- package/src/lru.ts +185 -0
- package/src/marked/core.ts +1576 -0
- package/src/marked.ts +2 -0
- package/src/mermaid-ascii.ts +31 -0
- package/src/mime.ts +159 -0
- package/src/module-timer.ts +148 -0
- package/src/path-tree.ts +147 -0
- package/src/path.ts +28 -0
- package/src/peek-file.ts +188 -0
- package/src/postmortem.ts +433 -0
- package/src/process-name.ts +57 -0
- package/src/procmgr.ts +247 -0
- package/src/prompt.ts +545 -0
- package/src/ptree.ts +412 -0
- package/src/readability/readability.ts +533 -0
- package/src/readability/readerable.ts +51 -0
- package/src/readability/types.ts +72 -0
- package/src/readability.ts +11 -0
- package/src/ring.ts +169 -0
- package/src/runtime-install.ts +393 -0
- package/src/sanitize-text.ts +96 -0
- package/src/snowflake.ts +121 -0
- package/src/stderr-guard.ts +155 -0
- package/src/stream.ts +454 -0
- package/src/tab-spacing.ts +336 -0
- package/src/temp.ts +134 -0
- package/src/template.ts +586 -0
- package/src/timing-buffer.ts +47 -0
- package/src/tls-fetch.ts +178 -0
- package/src/turndown/gfm.ts +106 -0
- package/src/turndown/html.ts +257 -0
- package/src/turndown/service.ts +334 -0
- package/src/turndown/types.ts +81 -0
- package/src/turndown.ts +5 -0
- package/src/type-guards.ts +17 -0
- package/src/vendor/mermaid-ascii/NOTICE +33 -0
- package/src/vendor/mermaid-ascii/ascii/ansi.ts +409 -0
- package/src/vendor/mermaid-ascii/ascii/canvas.ts +476 -0
- package/src/vendor/mermaid-ascii/ascii/class-diagram.ts +699 -0
- package/src/vendor/mermaid-ascii/ascii/converter.ts +271 -0
- package/src/vendor/mermaid-ascii/ascii/draw.ts +1382 -0
- package/src/vendor/mermaid-ascii/ascii/edge-bundling.ts +328 -0
- package/src/vendor/mermaid-ascii/ascii/edge-routing.ts +297 -0
- package/src/vendor/mermaid-ascii/ascii/er-diagram.ts +441 -0
- package/src/vendor/mermaid-ascii/ascii/grid.ts +578 -0
- package/src/vendor/mermaid-ascii/ascii/index.ts +187 -0
- package/src/vendor/mermaid-ascii/ascii/multiline-utils.ts +78 -0
- package/src/vendor/mermaid-ascii/ascii/pathfinder.ts +277 -0
- package/src/vendor/mermaid-ascii/ascii/sequence.ts +460 -0
- package/src/vendor/mermaid-ascii/ascii/shapes/circle.ts +27 -0
- package/src/vendor/mermaid-ascii/ascii/shapes/corners.ts +127 -0
- package/src/vendor/mermaid-ascii/ascii/shapes/diamond.ts +27 -0
- package/src/vendor/mermaid-ascii/ascii/shapes/hexagon.ts +27 -0
- package/src/vendor/mermaid-ascii/ascii/shapes/index.ts +101 -0
- package/src/vendor/mermaid-ascii/ascii/shapes/rectangle.ts +175 -0
- package/src/vendor/mermaid-ascii/ascii/shapes/rounded.ts +27 -0
- package/src/vendor/mermaid-ascii/ascii/shapes/special.ts +296 -0
- package/src/vendor/mermaid-ascii/ascii/shapes/stadium.ts +114 -0
- package/src/vendor/mermaid-ascii/ascii/shapes/state.ts +192 -0
- package/src/vendor/mermaid-ascii/ascii/shapes/types.ts +73 -0
- package/src/vendor/mermaid-ascii/ascii/types.ts +273 -0
- package/src/vendor/mermaid-ascii/ascii/validate.ts +120 -0
- package/src/vendor/mermaid-ascii/ascii/xychart.ts +875 -0
- package/src/vendor/mermaid-ascii/class/parser.ts +290 -0
- package/src/vendor/mermaid-ascii/class/types.ts +121 -0
- package/src/vendor/mermaid-ascii/er/parser.ts +181 -0
- package/src/vendor/mermaid-ascii/er/types.ts +91 -0
- package/src/vendor/mermaid-ascii/index.ts +14 -0
- package/src/vendor/mermaid-ascii/multiline-utils.ts +30 -0
- package/src/vendor/mermaid-ascii/parser.ts +645 -0
- package/src/vendor/mermaid-ascii/sequence/parser.ts +207 -0
- package/src/vendor/mermaid-ascii/sequence/types.ts +146 -0
- package/src/vendor/mermaid-ascii/text-metrics.ts +71 -0
- package/src/vendor/mermaid-ascii/types.ts +164 -0
- package/src/vendor/mermaid-ascii/xychart/colors.ts +140 -0
- package/src/vendor/mermaid-ascii/xychart/parser.ts +115 -0
- package/src/vendor/mermaid-ascii/xychart/types.ts +150 -0
- package/src/version.ts +99 -0
- package/src/vterm/buffer.ts +218 -0
- package/src/vterm/terminal.ts +773 -0
- package/src/vterm.ts +8 -0
- package/src/which.ts +234 -0
- package/src/worker-host.ts +100 -0
- package/src/xml.ts +313 -0
package/src/procmgr.ts
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { Process, ProcessStatus } from "@linxiraos/pi-natives";
|
|
4
|
+
import type { Subprocess } from "bun";
|
|
5
|
+
import { getAgentDir, MAIN_CONFIG_FILENAMES } from "./dirs";
|
|
6
|
+
import { $env, filterChildShellEnv } from "./env";
|
|
7
|
+
import { $which } from "./which";
|
|
8
|
+
|
|
9
|
+
export interface ShellConfig {
|
|
10
|
+
shell: string;
|
|
11
|
+
args: string[];
|
|
12
|
+
env: Record<string, string>;
|
|
13
|
+
prefix: string | undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Identifies the settings source users should edit when shell resolution fails. */
|
|
17
|
+
export interface ShellConfigOptions {
|
|
18
|
+
/** File path or runtime layer that supplied the active shell setting. */
|
|
19
|
+
configSource?: string;
|
|
20
|
+
}
|
|
21
|
+
let cachedShellConfig: ShellConfig | null = null;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Check if a shell binary is executable.
|
|
25
|
+
*/
|
|
26
|
+
export function isExecutable(path: string): boolean {
|
|
27
|
+
try {
|
|
28
|
+
fs.accessSync(path, fs.constants.X_OK);
|
|
29
|
+
return true;
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Build the spawn environment (cached).
|
|
37
|
+
*/
|
|
38
|
+
function buildSpawnEnv(shell: string): Record<string, string> {
|
|
39
|
+
const noCI = $env.PI_BASH_NO_CI || $env.CLAUDE_BASH_NO_CI;
|
|
40
|
+
return {
|
|
41
|
+
...filterChildShellEnv(Bun.env),
|
|
42
|
+
SHELL: shell,
|
|
43
|
+
GIT_EDITOR: "true",
|
|
44
|
+
GPG_TTY: "not a tty",
|
|
45
|
+
OMPCODE: "1",
|
|
46
|
+
CLAUDECODE: "1",
|
|
47
|
+
...(noCI ? {} : { CI: "true" }),
|
|
48
|
+
} as Record<string, string>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get shell args for the resolved shell.
|
|
53
|
+
* cmd.exe takes `/c`; PowerShell (powershell.exe / pwsh) takes
|
|
54
|
+
* `-NoLogo -Command`, with `-NoProfile` when PI_BASH_NO_LOGIN /
|
|
55
|
+
* CLAUDE_BASH_NO_LOGIN is set (profile scripts are PowerShell's login-shell
|
|
56
|
+
* analog); POSIX shells take `-c`, with `-l` unless the same env is set.
|
|
57
|
+
*
|
|
58
|
+
* Exported for tests; `env` overrides the process env gate.
|
|
59
|
+
*/
|
|
60
|
+
export function getShellArgs(shell: string, env: Record<string, string | undefined> = $env): string[] {
|
|
61
|
+
if (isCmdShell(shell)) return ["/c"];
|
|
62
|
+
const noLogin = env.PI_BASH_NO_LOGIN || env.CLAUDE_BASH_NO_LOGIN;
|
|
63
|
+
if (isPowerShell(shell)) {
|
|
64
|
+
return noLogin ? ["-NoLogo", "-NoProfile", "-Command"] : ["-NoLogo", "-Command"];
|
|
65
|
+
}
|
|
66
|
+
return noLogin ? ["-c"] : ["-l", "-c"];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Whether the shell is Windows cmd.exe (spawn paths must use `/c`, not `-c`). */
|
|
70
|
+
export function isCmdShell(shell: string): boolean {
|
|
71
|
+
const basename = shell.replace(/\\/g, "/").split("/").pop()?.toLowerCase();
|
|
72
|
+
return basename === "cmd.exe" || basename === "cmd";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Whether the shell is Windows PowerShell or PowerShell Core (pwsh). Spawn
|
|
77
|
+
* paths must use `-Command`: passing the POSIX `-l -c` pair makes PowerShell
|
|
78
|
+
* parse `-l` as the command and fail with `The term '-l' is not recognized`.
|
|
79
|
+
*/
|
|
80
|
+
export function isPowerShell(shell: string): boolean {
|
|
81
|
+
const basename = shell.replace(/\\/g, "/").split("/").pop()?.toLowerCase();
|
|
82
|
+
return basename === "powershell.exe" || basename === "powershell" || basename === "pwsh.exe" || basename === "pwsh";
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get shell prefix for wrapping commands (profilers, strace, etc.).
|
|
87
|
+
*/
|
|
88
|
+
function getShellPrefix(): string | undefined {
|
|
89
|
+
return $env.PI_SHELL_PREFIX || $env.CLAUDE_CODE_SHELL_PREFIX;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Build full shell config from a shell path.
|
|
94
|
+
*/
|
|
95
|
+
function buildConfig(shell: string): ShellConfig {
|
|
96
|
+
return {
|
|
97
|
+
shell,
|
|
98
|
+
args: getShellArgs(shell),
|
|
99
|
+
env: buildSpawnEnv(shell),
|
|
100
|
+
prefix: getShellPrefix(),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Resolve a basic shell (bash or sh) as fallback.
|
|
106
|
+
*/
|
|
107
|
+
export function resolveBasicShell(): string | undefined {
|
|
108
|
+
for (const name of ["bash", "bash.exe", "sh", "sh.exe"]) {
|
|
109
|
+
const resolved = $which(name);
|
|
110
|
+
if (resolved) return resolved;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (process.platform !== "win32") {
|
|
114
|
+
const searchPaths = ["/bin", "/usr/bin", "/usr/local/bin", "/opt/homebrew/bin"];
|
|
115
|
+
const candidates = ["bash", "sh"];
|
|
116
|
+
|
|
117
|
+
for (const name of candidates) {
|
|
118
|
+
for (const dir of searchPaths) {
|
|
119
|
+
const fullPath = path.join(dir, name);
|
|
120
|
+
if (fs.existsSync(fullPath)) return fullPath;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Resolve the external shell to advertise on Windows.
|
|
130
|
+
*
|
|
131
|
+
* A host bash is OPTIONAL: bash tool commands always execute in the embedded
|
|
132
|
+
* brush-core shell. The resolved binary only serves the spawn-a-shell paths
|
|
133
|
+
* (interactive PTY sessions, ACP client terminals, SHELL env), so this
|
|
134
|
+
* prefers a real Git Bash when one exists and otherwise falls back to
|
|
135
|
+
* cmd.exe — it never fails.
|
|
136
|
+
*
|
|
137
|
+
* Search order:
|
|
138
|
+
* 1. Git for Windows install roots (machine + per-user installers)
|
|
139
|
+
* 2. scoop installs — scoop's git manifest sets GIT_INSTALL_ROOT and shims
|
|
140
|
+
* sh.exe/git.exe but never bash.exe, so PATH lookup alone misses it
|
|
141
|
+
* 3. bash.exe on PATH (Cygwin, MSYS2, ...)
|
|
142
|
+
* 4. sh.exe on PATH (Git for Windows' sh.exe is bash; prefer a sibling
|
|
143
|
+
* bash.exe when present)
|
|
144
|
+
* 5. cmd.exe from ComSpec
|
|
145
|
+
*
|
|
146
|
+
* Exported for tests; `env` overrides Bun.env-based discovery.
|
|
147
|
+
*/
|
|
148
|
+
export function resolveWindowsShell(env: Record<string, string | undefined> = Bun.env): string {
|
|
149
|
+
const gitRoots = [
|
|
150
|
+
env.ProgramFiles && path.join(env.ProgramFiles, "Git"),
|
|
151
|
+
env["ProgramFiles(x86)"] && path.join(env["ProgramFiles(x86)"], "Git"),
|
|
152
|
+
env.LOCALAPPDATA && path.join(env.LOCALAPPDATA, "Programs", "Git"),
|
|
153
|
+
env.GIT_INSTALL_ROOT,
|
|
154
|
+
env.SCOOP && path.join(env.SCOOP, "apps", "git", "current"),
|
|
155
|
+
env.USERPROFILE && path.join(env.USERPROFILE, "scoop", "apps", "git", "current"),
|
|
156
|
+
];
|
|
157
|
+
for (const root of gitRoots) {
|
|
158
|
+
if (!root) continue;
|
|
159
|
+
const candidate = path.join(root, "bin", "bash.exe");
|
|
160
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const bashOnPath = $which("bash.exe");
|
|
164
|
+
if (bashOnPath) return bashOnPath;
|
|
165
|
+
|
|
166
|
+
const shOnPath = $which("sh.exe");
|
|
167
|
+
if (shOnPath) {
|
|
168
|
+
const siblingBash = path.join(path.dirname(shOnPath), "bash.exe");
|
|
169
|
+
return fs.existsSync(siblingBash) ? siblingBash : shOnPath;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return env.ComSpec || env.COMSPEC || "C:\\Windows\\System32\\cmd.exe";
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Get shell configuration based on platform.
|
|
177
|
+
* Resolution order:
|
|
178
|
+
* 1. User-specified shellPath from the active settings source
|
|
179
|
+
* 2. On Windows: Git Bash / bash / sh discovery, then cmd.exe (see
|
|
180
|
+
* {@link resolveWindowsShell}) — never fails
|
|
181
|
+
* 3. On Unix: $SHELL if bash/zsh, then fallback paths
|
|
182
|
+
* 4. Fallback: sh
|
|
183
|
+
*/
|
|
184
|
+
export function getShellConfig(customShellPath?: string, options: ShellConfigOptions = {}): ShellConfig {
|
|
185
|
+
const configSource = options.configSource ?? path.join(getAgentDir(), MAIN_CONFIG_FILENAMES[0]);
|
|
186
|
+
// 1. Check user-specified shell path. Validated even on the cached path so a
|
|
187
|
+
// broken shellPath surfaces its guidance error instead of being masked by an
|
|
188
|
+
// earlier successful resolution in the same process.
|
|
189
|
+
if (customShellPath) {
|
|
190
|
+
if (!fs.existsSync(customShellPath)) {
|
|
191
|
+
throw new Error(`Custom shell path not found: ${customShellPath}\nPlease update shellPath in ${configSource}`);
|
|
192
|
+
}
|
|
193
|
+
if (cachedShellConfig?.shell !== customShellPath) {
|
|
194
|
+
cachedShellConfig = buildConfig(customShellPath);
|
|
195
|
+
}
|
|
196
|
+
return cachedShellConfig;
|
|
197
|
+
}
|
|
198
|
+
if (cachedShellConfig) {
|
|
199
|
+
return cachedShellConfig;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (process.platform === "win32") {
|
|
203
|
+
cachedShellConfig = buildConfig(resolveWindowsShell());
|
|
204
|
+
return cachedShellConfig;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Unix: prefer user's shell from $SHELL if it's bash/zsh and executable
|
|
208
|
+
const userShell = Bun.env.SHELL;
|
|
209
|
+
const isValidShell = userShell && (userShell.includes("bash") || userShell.includes("zsh"));
|
|
210
|
+
if (isValidShell && isExecutable(userShell)) {
|
|
211
|
+
cachedShellConfig = buildConfig(userShell);
|
|
212
|
+
return cachedShellConfig;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// 4. Fallback: use basic shell
|
|
216
|
+
const basicShell = resolveBasicShell();
|
|
217
|
+
if (basicShell) {
|
|
218
|
+
cachedShellConfig = buildConfig(basicShell);
|
|
219
|
+
return cachedShellConfig;
|
|
220
|
+
}
|
|
221
|
+
cachedShellConfig = buildConfig("sh");
|
|
222
|
+
return cachedShellConfig;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Check if a process is running.
|
|
227
|
+
*/
|
|
228
|
+
export function isPidRunning(pid: number | Subprocess): boolean {
|
|
229
|
+
if (typeof pid !== "number") {
|
|
230
|
+
if (pid.killed) return false;
|
|
231
|
+
if (pid.exitCode !== null) return false;
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return Process.fromPid(pid)?.status() === ProcessStatus.Running;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export async function onProcessExit(proc: Subprocess | number, abortSignal?: AbortSignal): Promise<boolean> {
|
|
239
|
+
if (typeof proc !== "number") {
|
|
240
|
+
return proc.exited.then(
|
|
241
|
+
() => true,
|
|
242
|
+
() => true,
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return (await Process.fromPid(proc)?.waitForExit({ signal: abortSignal })) ?? true;
|
|
247
|
+
}
|