browser4-cli 0.1.14 → 0.1.16

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.
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "browser4-cli",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "Browser automation CLI for AI agents",
5
5
  "type": "module",
6
6
  "files": [
@@ -67,9 +67,17 @@ $ErrorActionPreference = "Stop"
67
67
  # OS detection (compatible with PS 5.1+)
68
68
  # ──────────────────────────────────────────────
69
69
 
70
- $script:IsWin = [System.Environment]::OSVersion.Platform -eq "Win32NT"
71
- $script:IsMac = [System.Environment]::OSVersion.Platform -eq "Unix" -and (uname -s 2>$null) -eq "Darwin"
72
- $script:IsLinux = [System.Environment]::OSVersion.Platform -eq "Unix" -and (uname -s 2>$null) -ne "Darwin"
70
+ # Avoid assigning to $IsLinux / $IsWindows / $IsMacOS directly —
71
+ # they are read-only automatic variables in PowerShell 7+.
72
+ if ($PSVersionTable.PSVersion.Major -ge 6) {
73
+ $script:OSWin = $IsWindows
74
+ $script:OSLinux = $IsLinux
75
+ $script:OSMac = $IsMacOS
76
+ } else {
77
+ $script:OSWin = [System.Environment]::OSVersion.Platform -eq "Win32NT"
78
+ $script:OSMac = $false
79
+ $script:OSLinux = $false
80
+ }
73
81
 
74
82
  # ──────────────────────────────────────────────
75
83
  # Helpers
@@ -102,13 +110,13 @@ function Write-WarnMsg {
102
110
  function Get-PlatformKey {
103
111
  $arch = if ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture -eq [System.Runtime.InteropServices.Architecture]::Arm64) { "arm64" } else { "x64" }
104
112
 
105
- if ($script:IsWin) {
113
+ if ($script:OSWin) {
106
114
  return "win32-$arch"
107
115
  }
108
- elseif ($script:IsMac) {
116
+ elseif ($script:OSMac) {
109
117
  return "darwin-$arch"
110
118
  }
111
- elseif ($script:IsLinux) {
119
+ elseif ($script:OSLinux) {
112
120
  # Detect musl
113
121
  $isMusl = $false
114
122
  try {
@@ -133,10 +141,10 @@ function Get-BinaryName {
133
141
  }
134
142
 
135
143
  function Get-DefaultInstallDir {
136
- if ($script:IsWin) {
144
+ if ($script:OSWin) {
137
145
  return Join-Path $env:LOCALAPPDATA "Programs\browser4-cli"
138
146
  }
139
- elseif ($script:IsLinux -or $script:IsMac) {
147
+ elseif ($script:OSLinux -or $script:OSMac) {
140
148
  # Prefer ~/.local/bin for user installs
141
149
  if (Test-Path "$env:HOME/.local/bin") {
142
150
  return "$env:HOME/.local/bin"
@@ -233,7 +241,7 @@ function New-PlatformLink {
233
241
  }
234
242
 
235
243
  # Try hard link (Windows, same volume)
236
- if ($script:IsWin) {
244
+ if ($script:OSWin) {
237
245
  try {
238
246
  $targetPath = Join-Path (Split-Path $LinkPath -Parent) $TargetName
239
247
  New-Item -ItemType HardLink -Path $LinkPath -Target $targetPath -Force -ErrorAction Stop | Out-Null
@@ -292,7 +300,7 @@ function New-Symlinks {
292
300
  }
293
301
 
294
302
  # Also check b4.cmd if on Windows (wrapper fallback)
295
- if ($script:IsWin) {
303
+ if ($script:OSWin) {
296
304
  $shortCmdPath = Join-Path $InstallDir "b4.cmd"
297
305
  if (Test-Path $shortCmdPath) {
298
306
  Write-WarnMsg "Skipping short link '$shortName': 'b4.cmd' already exists in $InstallDir"
@@ -415,7 +423,7 @@ Please check:
415
423
  }
416
424
 
417
425
  # On Unix, ensure executable bit
418
- if (-not $script:IsWin) {
426
+ if (-not $script:OSWin) {
419
427
  if (-not $DryRun) {
420
428
  try { chmod +x $binaryPath 2>$null } catch { }
421
429
  }
@@ -426,10 +434,10 @@ Please check:
426
434
  New-Symlinks -BinaryName $binaryName -InstallDir $installDir -PlatformKey $platformKey
427
435
 
428
436
  # Add to PATH
429
- if ($AddToPath -and $script:IsWin) {
437
+ if ($AddToPath -and $script:OSWin) {
430
438
  Write-Summary ""
431
439
  Add-DirectoryToUserPath -Dir $installDir
432
- } elseif ($AddToPath -and -not $script:IsWin) {
440
+ } elseif ($AddToPath -and -not $script:OSWin) {
433
441
  Write-Summary ""
434
442
  $shellRc = if (Test-Path "$env:HOME/.zshrc") { "$env:HOME/.zshrc" } elseif (Test-Path "$env:HOME/.bashrc") { "$env:HOME/.bashrc" } elseif (Test-Path "$env:HOME/.bash_profile") { "$env:HOME/.bash_profile" } else { "$env:HOME/.profile" }
435
443
  $pathLine = "export PATH=""$installDir`:`$PATH"""
@@ -465,7 +473,7 @@ Please check:
465
473
  Write-Summary ""
466
474
  Write-Summary "Run 'browser4-cli --help' to get started." -Color Cyan
467
475
 
468
- if ($script:IsWin) {
476
+ if ($script:OSWin) {
469
477
  Write-Summary "If the command isn't found, restart your terminal or run:"
470
478
  Write-Summary " `$env:Path = [System.Environment]::GetEnvironmentVariable('Path','User') + ';' + [System.Environment]::GetEnvironmentVariable('Path','Machine')"
471
479
  }
@@ -140,14 +140,34 @@ detect_libc() {
140
140
  return
141
141
  fi
142
142
 
143
- # Check for musl
144
- if ldd --version 2>&1 | grep -qi musl; then
145
- echo "musl"
146
- elif [[ -f /lib/ld-musl-x86_64.so.1 ]] || [[ -f /lib/ld-musl-aarch64.so.1 ]]; then
147
- echo "musl"
148
- else
149
- echo ""
143
+ # Check for musl via ldd --version (guarded against missing ldd)
144
+ if command -v ldd >/dev/null 2>&1; then
145
+ if ldd --version 2>&1 | grep -qi musl; then
146
+ echo "musl"
147
+ return
148
+ fi
150
149
  fi
150
+
151
+ # Check for musl loader — covers common architectures
152
+ # x86_64, aarch64, armhf (32-bit ARM), i386, riscv64, s390x, ppc64le, mips64
153
+ local musl_loader
154
+ for musl_loader in \
155
+ /lib/ld-musl-x86_64.so.1 \
156
+ /lib/ld-musl-aarch64.so.1 \
157
+ /lib/ld-musl-armhf.so.1 \
158
+ /lib/ld-musl-i386.so.1 \
159
+ /lib/ld-musl-riscv64.so.1 \
160
+ /lib/ld-musl-s390x.so.1 \
161
+ /lib/ld-musl-ppc64le.so.1 \
162
+ /lib/ld-musl-mips64.so.1 \
163
+ /lib/ld-musl-mipsel.so.1; do
164
+ if [[ -f "$musl_loader" ]]; then
165
+ echo "musl"
166
+ return
167
+ fi
168
+ done
169
+
170
+ echo ""
151
171
  }
152
172
 
153
173
  get_platform_key() {
@@ -196,8 +216,14 @@ get_default_install_dir() {
196
216
  # ──────────────────────────────────────────────
197
217
 
198
218
  check_commands() {
199
- if ! command -v curl >/dev/null 2>&1; then
200
- die "'curl' is required but not found. Install curl and retry."
219
+ local missing=()
220
+ for cmd in curl mktemp stat awk grep ln mkdir chmod; do
221
+ if ! command -v "$cmd" >/dev/null 2>&1; then
222
+ missing+=("$cmd")
223
+ fi
224
+ done
225
+ if [[ ${#missing[@]} -gt 0 ]]; then
226
+ die "Required command(s) not found: ${missing[*]}. Install them and retry."
201
227
  fi
202
228
  }
203
229
 
@@ -240,10 +266,27 @@ download_file() {
240
266
  return 0
241
267
  fi
242
268
 
243
- local http_code
269
+ local curl_stderr
270
+ curl_stderr=$(mktemp)
271
+ local http_code curl_exit
272
+
244
273
  http_code=$(curl -sSfL -w "%{http_code}" -o "$dest" \
245
274
  ${GITHUB_TOKEN:+-H "Authorization: Bearer $GITHUB_TOKEN"} \
246
- "$url" 2>/dev/null) || true
275
+ "$url" 2>"$curl_stderr")
276
+ curl_exit=$?
277
+
278
+ if [[ $curl_exit -ne 0 ]]; then
279
+ local stderr_msg
280
+ stderr_msg=$(<"$curl_stderr")
281
+ rm -f "$curl_stderr" "$dest"
282
+ if [[ -n "$stderr_msg" ]]; then
283
+ warn "curl error (exit ${curl_exit}): ${stderr_msg}"
284
+ else
285
+ warn "curl failed with exit code ${curl_exit} (no stderr output)"
286
+ fi
287
+ return 1
288
+ fi
289
+ rm -f "$curl_stderr"
247
290
 
248
291
  if [[ "$http_code" == "200" ]] || [[ "$http_code" == "302" ]]; then
249
292
  local size
@@ -297,12 +340,38 @@ add_to_shell_rc() {
297
340
  return
298
341
  fi
299
342
 
343
+ # Ensure the file ends with a newline before appending, so the new
344
+ # content isn't glued to the last existing line.
345
+ if [[ -s "$rc_file" ]]; then
346
+ local last_byte
347
+ last_byte=$(tail -c1 "$rc_file" 2>/dev/null || true)
348
+ if [[ -n "$last_byte" ]]; then
349
+ echo "" >> "$rc_file"
350
+ fi
351
+ fi
352
+
353
+ # Use a lock file to prevent concurrent append races (best-effort).
354
+ local lock_file="${rc_file}.browser4-install.lock"
355
+ local lock_fd=9
356
+ # Wait up to 10 seconds for another install process to release the lock.
357
+ local waited=0
358
+ while ! (umask 0002 && command -v flock >/dev/null 2>&1 && flock -n 9 2>/dev/null); do
359
+ if [[ $waited -ge 10 ]]; then
360
+ warn "Could not acquire lock on ${rc_file} after 10s; appending anyway"
361
+ break
362
+ fi
363
+ sleep 0.5
364
+ waited=$((waited + 1))
365
+ done 9>"$lock_file"
366
+
300
367
  {
301
- echo ""
302
368
  echo "# browser4-cli"
303
369
  echo "export PATH=\"$dir:\$PATH\""
304
370
  } >> "$rc_file"
305
371
 
372
+ # Clean up (flock auto-releases when fd 9 is closed)
373
+ rm -f "$lock_file" 2>/dev/null || true
374
+
306
375
  ok "Added to PATH in $rc_file"
307
376
  say " Reload with: source $rc_file"
308
377
  }