diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 610ac25..6add132 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,15 +39,14 @@ jobs: run: | test_dir="$(mktemp -d)" trap 'rm -rf "$test_dir"' EXIT - mkdir -p "$test_dir/skill/scripts" "$test_dir/fake-path" + mkdir -p "$test_dir/skill/scripts" "$test_dir/skill/bin" "$test_dir/fake-path" cp skills/lexmount-browser/scripts/doctor.sh "$test_dir/skill/scripts/doctor.sh" + printf '#!/bin/sh\nprintf "%%s\\n" "$*"\n' > "$test_dir/skill/bin/browser-cli" + chmod +x "$test_dir/skill/bin/browser-cli" ln -s /usr/bin/true "$test_dir/fake-path/browser-cli" - set +e output="$(PATH="$test_dir/fake-path:/usr/bin:/bin" "$test_dir/skill/scripts/doctor.sh")" - status=$? - set -e - test "$status" -eq 2 - test "$output" = '{"ok":false,"error":"unsupported_platform","message":"This Skill supports macOS arm64 through scripts/doctor.sh and Windows x64 through scripts/doctor.ps1."}' + test "$output" = 'doctor' + grep -Fq 'Linux-x86_64) target="x86_64-unknown-linux-musl"' skills/lexmount-browser/scripts/bootstrap.sh ! grep -q 'command -v browser-cli' skills/lexmount-browser/scripts/doctor.sh ! grep -q 'Get-Command browser-cli' skills/lexmount-browser/scripts/doctor.ps1 - name: Verify runtime packaging contract @@ -85,6 +84,21 @@ jobs: & .\skills\lexmount-browser\scripts\bootstrap.ps1 & (Join-Path $env:LEXMOUNT_BROWSER_CLI_INSTALL_DIR "browser-cli.exe") version + linux-bootstrap: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + - name: Bootstrap static Linux x64 binary from COS + run: | + published_tag="$(git tag --list 'v*' --sort=-version:refname | head -n 1)" + test -n "$published_tag" + export LEXMOUNT_BROWSER_CLI_VERSION="${published_tag#v}" + export LEXMOUNT_BROWSER_CLI_INSTALL_DIR="$RUNNER_TEMP/browser-cli-bootstrap" + ./skills/lexmount-browser/scripts/bootstrap.sh + "$LEXMOUNT_BROWSER_CLI_INSTALL_DIR/browser-cli" version + linux-release: runs-on: ubuntu-22.04 steps: diff --git a/Cargo.lock b/Cargo.lock index 7f23ff6..e7d56c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1208,7 +1208,7 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "lexmount-browser" -version = "1.1.15" +version = "1.1.16" dependencies = [ "base64 0.22.1", "clap", diff --git a/Cargo.toml b/Cargo.toml index d485aa4..9134533 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lexmount-browser" -version = "1.1.15" +version = "1.1.16" edition = "2024" license = "MIT" description = "Native Rust SDK and CLI for Lexmount cloud browsers" diff --git a/README.md b/README.md index 36baa0c..1e15095 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,9 @@ The publishable Skill is in `skills/lexmount-browser`. Build a deterministic ZIP ./scripts/package-skill.sh ``` -The ZIP contains `SKILL.md`, references, and platform bootstrap scripts at its -archive root. Native executables are published separately and are not placed in +The ZIP contains `SKILL.md`, references, and bootstrap scripts for macOS arm64, +Linux x64, and Windows x64 at its archive root. Native executables are published +separately and are not placed in the Skill ZIP. On first use, the matching bootstrap script downloads the pinned release from Tencent Cloud COS and verifies its SHA-256 digest. Set `LEXMOUNT_BROWSER_CLI_VERSION` or `LEXMOUNT_BROWSER_CLI_DOWNLOAD_BASE_URL` only diff --git a/skills/lexmount-browser/SKILL.md b/skills/lexmount-browser/SKILL.md index aa9e797..b8cfa9c 100644 --- a/skills/lexmount-browser/SKILL.md +++ b/skills/lexmount-browser/SKILL.md @@ -17,6 +17,7 @@ Do not infer `` from the working directory. Select the native Rust binary for the current platform: - macOS arm64: run `sh "/scripts/bootstrap.sh"` when `/bin/browser-cli` is missing, then invoke `"/bin/browser-cli"`. +- Linux x64: run `sh "/scripts/bootstrap.sh"` when `/bin/browser-cli` is missing, then invoke `"/bin/browser-cli"`. - Windows x64: run `& "\scripts\bootstrap.ps1"` in PowerShell when `\bin\browser-cli.exe` is missing, then invoke `& "\bin\browser-cli.exe"`. Both bootstrap scripts download the fixed release version from Tencent Cloud COS and verify its SHA-256 digest. @@ -24,12 +25,12 @@ The Agent-specific locator is needed to form the initial absolute command. Once started, the bootstrap and doctor scripts locate the Skill directory from their own file location. -Do not run the binary for the other platform. Both platform binaries emit JSON. The examples below abbreviate the selected absolute path as `browser-cli`; resolve it before running commands and do not assume it is on `PATH`. +Do not run the binary for another platform. All platform binaries emit JSON. The examples below abbreviate the selected absolute path as `browser-cli`; resolve it before running commands and do not assume it is on `PATH`. ## Setup 1. Resolve `` from this `SKILL.md` and select the matching platform paths above. -2. Run the Skill-local bootstrap script if the binary is missing. Then run `sh "/scripts/doctor.sh"` on macOS arm64 or `& "\scripts\doctor.ps1"` in Windows PowerShell. +2. Run the Skill-local bootstrap script if the binary is missing. Then run `sh "/scripts/doctor.sh"` on macOS arm64 or Linux x64, or `& "\scripts\doctor.ps1"` in Windows PowerShell. 3. If credentials are missing, run `browser-cli auth login`. Pass `--client-name ""` when the current Agent has a user-facing name; otherwise the CLI uses `Agent`. Let the user approve in their browser. Never ask them to paste an API key into chat. 4. Run `browser-cli doctor` again. Continue only when `ready_for_browser_actions` is true. diff --git a/skills/lexmount-browser/references/troubleshooting.md b/skills/lexmount-browser/references/troubleshooting.md index 0c6921b..44e965f 100644 --- a/skills/lexmount-browser/references/troubleshooting.md +++ b/skills/lexmount-browser/references/troubleshooting.md @@ -8,6 +8,6 @@ Run `browser-cli doctor` first and use the failed check's message. - `timeout`: inspect session status and network access, then retry with a larger timeout. - `cdp_error`: verify the session is active, inspect `session targets`, and take a snapshot before retrying the action. - Skill root unknown: resolve the directory containing the loaded `SKILL.md` with the current host's locator: Codex supplies its absolute source path in the Skill metadata, Claude Code provides `${CLAUDE_SKILL_DIR}`, and WorkBuddy/CodeBuddy provides `${CODEBUDDY_SKILL_DIR}`. Do not infer it from the working directory or search the user's home directory. -- command not found after bootstrap: invoke `"/bin/browser-cli"` on macOS arm64 or `& "\bin\browser-cli.exe"` in Windows PowerShell; no PATH change or restart is required. +- command not found after bootstrap: invoke `"/bin/browser-cli"` on macOS arm64 or Linux x64, or `& "\bin\browser-cli.exe"` in Windows PowerShell; no PATH change or restart is required. Always close a newly created temporary session when abandoning a failed task. diff --git a/skills/lexmount-browser/scripts/bootstrap.ps1 b/skills/lexmount-browser/scripts/bootstrap.ps1 index d676619..889828c 100644 --- a/skills/lexmount-browser/scripts/bootstrap.ps1 +++ b/skills/lexmount-browser/scripts/bootstrap.ps1 @@ -12,7 +12,7 @@ function Invoke-Tls12Download { } } -$version = if ($env:LEXMOUNT_BROWSER_CLI_VERSION) { $env:LEXMOUNT_BROWSER_CLI_VERSION } else { "1.1.15" } +$version = if ($env:LEXMOUNT_BROWSER_CLI_VERSION) { $env:LEXMOUNT_BROWSER_CLI_VERSION } else { "1.1.16" } $downloadBaseUrl = if ($env:LEXMOUNT_BROWSER_CLI_DOWNLOAD_BASE_URL) { $env:LEXMOUNT_BROWSER_CLI_DOWNLOAD_BASE_URL.TrimEnd('/') } else { "https://cli-bin-1377899528.cos.ap-nanjing.myqcloud.com/releases/browser-cli" } $architecture = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE } if ($architecture -ne "AMD64") { throw "Only Windows x64 is supported" } diff --git a/skills/lexmount-browser/scripts/bootstrap.sh b/skills/lexmount-browser/scripts/bootstrap.sh index fce1662..946ab2a 100755 --- a/skills/lexmount-browser/scripts/bootstrap.sh +++ b/skills/lexmount-browser/scripts/bootstrap.sh @@ -1,12 +1,13 @@ #!/bin/sh set -eu -version="${LEXMOUNT_BROWSER_CLI_VERSION:-1.1.15}" +version="${LEXMOUNT_BROWSER_CLI_VERSION:-1.1.16}" download_base_url="${LEXMOUNT_BROWSER_CLI_DOWNLOAD_BASE_URL:-https://cli-bin-1377899528.cos.ap-nanjing.myqcloud.com/releases/browser-cli}" repo="${download_base_url%/}/v${version}" case "$(uname -s)-$(uname -m)" in Darwin-arm64) target="aarch64-apple-darwin" ;; - *) echo "Unsupported platform: $(uname -s) $(uname -m). This release supports macOS arm64 and Windows x86_64." >&2; exit 2 ;; + Linux-x86_64) target="x86_64-unknown-linux-musl" ;; + *) echo "Unsupported platform: $(uname -s) $(uname -m). This release supports macOS arm64, Linux x64, and Windows x64." >&2; exit 2 ;; esac asset="browser-cli-v${version}-${target}" @@ -16,7 +17,10 @@ curl --proto '=https' --tlsv1.2 -fsSL "$repo/$asset" -o "$tmp_dir/$asset" curl --proto '=https' --tlsv1.2 -fsSL "$repo/SHA256SUMS" -o "$tmp_dir/SHA256SUMS" expected="$(awk -v name="$asset" '$2 == name {print $1}' "$tmp_dir/SHA256SUMS")" [ -n "$expected" ] || { echo "No checksum published for $asset" >&2; exit 3; } -actual="$(openssl dgst -sha256 "$tmp_dir/$asset" | awk '{print $NF}')" +case "$(uname -s)" in + Darwin) actual="$(openssl dgst -sha256 "$tmp_dir/$asset" | awk '{print $NF}')" ;; + Linux) actual="$(sha256sum "$tmp_dir/$asset" | awk '{print $1}')" ;; +esac [ "$expected" = "$actual" ] || { echo "SHA-256 mismatch for $asset" >&2; exit 4; } skill_dir="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)" install_dir="${LEXMOUNT_BROWSER_CLI_INSTALL_DIR:-$skill_dir/bin}" diff --git a/skills/lexmount-browser/scripts/doctor.ps1 b/skills/lexmount-browser/scripts/doctor.ps1 index fc9f34a..303fb08 100644 --- a/skills/lexmount-browser/scripts/doctor.ps1 +++ b/skills/lexmount-browser/scripts/doctor.ps1 @@ -1,7 +1,7 @@ $ErrorActionPreference = "Stop" $architecture = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE } if ($architecture -ne "AMD64") { - Write-Output '{"ok":false,"error":"unsupported_platform","message":"This Skill supports Windows x64 through scripts/doctor.ps1 and macOS arm64 through scripts/doctor.sh."}' + Write-Output '{"ok":false,"error":"unsupported_platform","message":"This Skill supports Windows x64 through scripts/doctor.ps1, and macOS arm64 and Linux x64 through scripts/doctor.sh."}' exit 2 } $skillBinary = Join-Path (Split-Path -Parent $PSScriptRoot) "bin\browser-cli.exe" diff --git a/skills/lexmount-browser/scripts/doctor.sh b/skills/lexmount-browser/scripts/doctor.sh index c0f8882..11dca6c 100755 --- a/skills/lexmount-browser/scripts/doctor.sh +++ b/skills/lexmount-browser/scripts/doctor.sh @@ -1,8 +1,8 @@ #!/bin/sh set -eu case "$(uname -s)-$(uname -m)" in - Darwin-arm64) ;; - *) echo '{"ok":false,"error":"unsupported_platform","message":"This Skill supports macOS arm64 through scripts/doctor.sh and Windows x64 through scripts/doctor.ps1."}'; exit 2 ;; + Darwin-arm64|Linux-x86_64) ;; + *) echo '{"ok":false,"error":"unsupported_platform","message":"This Skill supports macOS arm64 and Linux x64 through scripts/doctor.sh, and Windows x64 through scripts/doctor.ps1."}'; exit 2 ;; esac skill_dir="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)" if [ -x "$skill_dir/bin/browser-cli" ]; then exec "$skill_dir/bin/browser-cli" doctor; fi