browser-agent-server 1.0.2__tar.gz → 1.0.4__tar.gz
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.
- browser_agent_server-1.0.4/.github/ISSUE_TEMPLATE/bug_report.yml +33 -0
- browser_agent_server-1.0.4/.github/ISSUE_TEMPLATE/config.yml +8 -0
- browser_agent_server-1.0.4/.github/ISSUE_TEMPLATE/feature_request.yml +15 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/.github/workflows/ci.yml +3 -0
- browser_agent_server-1.0.4/.github/workflows/deploy-ssh.yml +47 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/.github/workflows/release.yml +9 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/CHANGELOG.md +27 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/PKG-INFO +7 -1
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/README.md +6 -0
- browser_agent_server-1.0.4/docs/multi-project-cd.md +99 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/docs/publishing.md +20 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/pyproject.toml +1 -1
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/uv.lock +1 -1
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/.gitignore +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/AGENTS.md +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/LICENSE +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/docs/api.md +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/docs/architecture.md +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/docs/deployment.md +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/docs/security.md +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/docs/troubleshooting.md +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/src/browser_agent/__init__.py +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/src/browser_agent/chrome.py +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/src/browser_agent/cli.py +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/src/browser_agent/data/browser-agent.service +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/src/browser_agent/server.py +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/src/browser_agent/vision_agent.py +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/src/browser_agent/x11_input.py +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/tests/test_bezier.py +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/tests/test_chrome_state_dir.py +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/tests/test_cli.py +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/tests/test_client.py +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/tests/test_cloudflare.py +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/tests/test_http_api.py +0 -0
- {browser_agent_server-1.0.2 → browser_agent_server-1.0.4}/tests/test_ws_frames.py +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something in browser-agent-server or the browser-agent CLI misbehaves
|
|
3
|
+
title: "[bug]: "
|
|
4
|
+
labels: [bug]
|
|
5
|
+
body:
|
|
6
|
+
- type: input
|
|
7
|
+
id: version
|
|
8
|
+
attributes:
|
|
9
|
+
label: Daemon version
|
|
10
|
+
description: Output of `browser-agent --version`
|
|
11
|
+
placeholder: browser-agent 1.0.2
|
|
12
|
+
validations:
|
|
13
|
+
required: true
|
|
14
|
+
- type: input
|
|
15
|
+
id: environment
|
|
16
|
+
attributes:
|
|
17
|
+
label: OS / how it runs
|
|
18
|
+
placeholder: Ubuntu 24.04, systemd unit, installed via `uv tool install`
|
|
19
|
+
validations:
|
|
20
|
+
required: true
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: what
|
|
23
|
+
attributes:
|
|
24
|
+
label: What happened vs what you expected
|
|
25
|
+
description: Include the exact command or HTTP request, and steps to reproduce if you have them
|
|
26
|
+
validations:
|
|
27
|
+
required: true
|
|
28
|
+
- type: textarea
|
|
29
|
+
id: logs
|
|
30
|
+
attributes:
|
|
31
|
+
label: Logs
|
|
32
|
+
description: "`journalctl -u browser-agent -n 50 --no-pager` or the terminal output"
|
|
33
|
+
render: shell
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: true
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Companion project — @vernikr/browser-agent-mcp
|
|
4
|
+
url: https://github.com/vernikr/browser-agent-mcp
|
|
5
|
+
about: Issue with the MCP bridge or an MCP client, not the daemon itself? File it there.
|
|
6
|
+
- name: Docs
|
|
7
|
+
url: https://github.com/vernikr/browser-agent/tree/main/docs
|
|
8
|
+
about: Installation, systemd, API and troubleshooting guides
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest an idea for the daemon, CLI, or API
|
|
3
|
+
title: "[feat]: "
|
|
4
|
+
labels: [enhancement]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: problem
|
|
8
|
+
attributes:
|
|
9
|
+
label: What problem does this solve for you?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: solution
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed solution / API sketch
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: deploy-ssh (reusable)
|
|
2
|
+
|
|
3
|
+
# Push-style continuous deployment to self-hosted servers.
|
|
4
|
+
# Caller passes the app name; the server-side dispatcher /usr/local/bin/deploy-tools
|
|
5
|
+
# resolves it via /etc/deploy-tools.d/<app>.conf (install exact version → restart →
|
|
6
|
+
# healthcheck → auto-rollback). See docs/multi-project-cd.md.
|
|
7
|
+
#
|
|
8
|
+
# Caller:
|
|
9
|
+
# deploy:
|
|
10
|
+
# needs: pypi # or your publish job — deploy only what is published
|
|
11
|
+
# uses: vernikr/browser-agent/.github/workflows/deploy-ssh.yml@main
|
|
12
|
+
# with: { app: my-app, tag: ${{ github.ref_name }} }
|
|
13
|
+
# secrets: inherit # DEPLOY_SSH_KEY / DEPLOY_HOST / DEPLOY_USER
|
|
14
|
+
|
|
15
|
+
on:
|
|
16
|
+
workflow_call:
|
|
17
|
+
inputs:
|
|
18
|
+
app:
|
|
19
|
+
required: true
|
|
20
|
+
type: string
|
|
21
|
+
description: App name — must match /etc/deploy-tools.d/<app>.conf on the host
|
|
22
|
+
tag:
|
|
23
|
+
required: true
|
|
24
|
+
type: string
|
|
25
|
+
description: Git tag that triggered the release, e.g. v1.2.3
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
deploy:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
environment:
|
|
31
|
+
name: prod
|
|
32
|
+
steps:
|
|
33
|
+
# Plain ssh (no third-party action): this key is trusted to drive the prod host.
|
|
34
|
+
# Server side it is pinned to the dispatcher via authorized_keys forced command:
|
|
35
|
+
# command="/usr/local/bin/deploy-tools",no-pty,no-port-forwarding,no-agent-forwarding,no-X11-forwarding
|
|
36
|
+
- name: Deploy exact version to production
|
|
37
|
+
env:
|
|
38
|
+
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
39
|
+
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
|
40
|
+
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
|
41
|
+
run: |
|
|
42
|
+
mkdir -p ~/.ssh && chmod 700 ~/.ssh
|
|
43
|
+
printf '%s\n' "$DEPLOY_SSH_KEY" > ~/.ssh/ci_deploy_key
|
|
44
|
+
chmod 600 ~/.ssh/ci_deploy_key
|
|
45
|
+
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts 2>/dev/null
|
|
46
|
+
VER="${{ inputs.tag }}"; VER="${VER#v}"
|
|
47
|
+
ssh -i ~/.ssh/ci_deploy_key "$DEPLOY_USER@$DEPLOY_HOST" "deploy ${{ inputs.app }} $VER"
|
|
@@ -49,6 +49,15 @@ jobs:
|
|
|
49
49
|
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
50
50
|
if: steps.exists.outputs.exists == 'false'
|
|
51
51
|
|
|
52
|
+
|
|
53
|
+
deploy:
|
|
54
|
+
needs: pypi
|
|
55
|
+
uses: ./.github/workflows/deploy-ssh.yml
|
|
56
|
+
with:
|
|
57
|
+
app: browser-agent
|
|
58
|
+
tag: ${{ github.ref_name }}
|
|
59
|
+
secrets: inherit
|
|
60
|
+
|
|
52
61
|
github-release:
|
|
53
62
|
needs: build
|
|
54
63
|
runs-on: ubuntu-latest
|
|
@@ -5,6 +5,33 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [1.0.4] - 2026-10-10
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- CD generalized for multi-project use: the deploy job now calls the reusable
|
|
13
|
+
workflow `.github/workflows/deploy-ssh.yml`, and the server-side forced
|
|
14
|
+
command became a dispatcher (`deploy <app> <semver>`) driven by
|
|
15
|
+
`/etc/deploy-tools.d/*.conf` — playbook in docs/multi-project-cd.md.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- docs/multi-project-cd.md — how to wire any project on the same server for
|
|
20
|
+
push-style CD in ~20 minutes (checklist + agent prompt).
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## [1.0.3] - 2026-10-10
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- Continuous deployment: after a successful PyPI publish, `release.yml` deploys
|
|
28
|
+
the exact version to the production host over SSH. The CI key is pinned to a
|
|
29
|
+
single forced command (`deploy-browser-agent` on the server): it installs the
|
|
30
|
+
exact pinned version from PyPI via `uv tool`, restarts the unit and
|
|
31
|
+
health-checks `/status`, rolling back to the previous version on failure
|
|
32
|
+
(see docs/publishing.md → Continuous deployment).
|
|
33
|
+
|
|
34
|
+
|
|
8
35
|
## [1.0.2] - 2026-10-10
|
|
9
36
|
|
|
10
37
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: browser-agent-server
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: Real headful Chrome on Xvfb with a hardware-level X11 mouse, Cloudflare Turnstile auto-solve and zero-leak CDP. Localhost HTTP API + CLI + Python SDK.
|
|
5
5
|
Project-URL: Homepage, https://github.com/vernikr/browser-agent
|
|
6
6
|
Project-URL: Repository, https://github.com/vernikr/browser-agent
|
|
@@ -23,6 +23,12 @@ Description-Content-Type: text/markdown
|
|
|
23
23
|
|
|
24
24
|
# browser-agent
|
|
25
25
|
|
|
26
|
+
[](https://pypi.org/project/browser-agent-server/)
|
|
27
|
+
[](https://github.com/vernikr/browser-agent/actions/workflows/ci.yml)
|
|
28
|
+
[](https://github.com/vernikr/browser-agent/releases)
|
|
29
|
+
[](https://pypi.org/project/browser-agent-server/)
|
|
30
|
+
[](LICENSE)
|
|
31
|
+
|
|
26
32
|
> 🔗 **Companion project:** [`@vernikr/browser-agent-mcp`](https://github.com/vernikr/browser-agent-mcp) — the MCP server that exposes this daemon to LLM agents (Claude Code, Cursor, Freebuff…). The two projects are developed together and speak the HTTP contract in [`docs/api.md`](docs/api.md).
|
|
27
33
|
|
|
28
34
|
**Real headful Chrome on Xvfb with a hardware-level X11 mouse.** One localhost daemon gives any project, script, or AI agent on a Linux box a genuine desktop browser: steered over real XTEST input events on randomized Bézier paths, with zero-leak CDP (no `Runtime.enable`), Cloudflare Turnstile auto-solve, and RAM discipline for tiny VPSes (auto-hibernates to ~12 MB idle).
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# browser-agent
|
|
2
2
|
|
|
3
|
+
[](https://pypi.org/project/browser-agent-server/)
|
|
4
|
+
[](https://github.com/vernikr/browser-agent/actions/workflows/ci.yml)
|
|
5
|
+
[](https://github.com/vernikr/browser-agent/releases)
|
|
6
|
+
[](https://pypi.org/project/browser-agent-server/)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
3
9
|
> 🔗 **Companion project:** [`@vernikr/browser-agent-mcp`](https://github.com/vernikr/browser-agent-mcp) — the MCP server that exposes this daemon to LLM agents (Claude Code, Cursor, Freebuff…). The two projects are developed together and speak the HTTP contract in [`docs/api.md`](docs/api.md).
|
|
4
10
|
|
|
5
11
|
**Real headful Chrome on Xvfb with a hardware-level X11 mouse.** One localhost daemon gives any project, script, or AI agent on a Linux box a genuine desktop browser: steered over real XTEST input events on randomized Bézier paths, with zero-leak CDP (no `Runtime.enable`), Cloudflare Turnstile auto-solve, and RAM discipline for tiny VPSes (auto-hibernates to ~12 MB idle).
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Multi-project CD: push every release to production from CI
|
|
2
|
+
|
|
3
|
+
The deploy used for `browser-agent` generalizes to any number of projects on the same
|
|
4
|
+
server. This page is the one-stop playbook — give it (or the prompt at the bottom) to any
|
|
5
|
+
agent to wire up a new project in ~20 minutes.
|
|
6
|
+
|
|
7
|
+
## Architecture (once per server)
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
GitHub release.yml (tag push)
|
|
11
|
+
build → publish (OIDC, no tokens)
|
|
12
|
+
→ deploy job → reusable workflow deploy-ssh.yml
|
|
13
|
+
└─ ssh <ci-key>@host "deploy <app> <ver>"
|
|
14
|
+
└─ authorized_keys forced command → /usr/local/bin/deploy-tools
|
|
15
|
+
└─ /etc/deploy-tools.d/<app>.conf
|
|
16
|
+
└─ install exact version → restart unit → healthcheck → rollback
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- **One CI key serves all projects.** The key is pinned by a forced command to the
|
|
20
|
+
dispatcher; it cannot open a shell, forward ports, or run anything else.
|
|
21
|
+
- **The whitelist of deployable apps is the server itself**: an app exists iff a
|
|
22
|
+
root-owned `/etc/deploy-tools.d/<app>.conf` exists. Unknown names are rejected.
|
|
23
|
+
- **No public endpoint, no firewall changes** — push arrives over the SSH port that is
|
|
24
|
+
already open for admin access.
|
|
25
|
+
|
|
26
|
+
Server-side artifacts (already installed on 38.244.152.2; copy to a new host as-is):
|
|
27
|
+
|
|
28
|
+
- `/usr/local/bin/deploy-tools` — the generic dispatcher (protocol: `deploy <app> <semver>`;
|
|
29
|
+
legacy `deploy <semver>` works while exactly one app is configured).
|
|
30
|
+
- `/etc/deploy-tools.d/browser-agent.conf` — the reference app config.
|
|
31
|
+
- backups under `/root/bak/`.
|
|
32
|
+
|
|
33
|
+
## Per-project checklist (~20 min)
|
|
34
|
+
|
|
35
|
+
Prerequisites: the project is a package published from CI to a registry with OIDC
|
|
36
|
+
trusted publishing (same one-time registry setup as in `docs/publishing.md`), and it runs
|
|
37
|
+
on the server as a systemd unit with some health signal.
|
|
38
|
+
|
|
39
|
+
1. **Systemd unit** — the service must come up healthy after `systemctl restart`. Health
|
|
40
|
+
signal: either a JSON endpoint answering `"version": "X.Y.Z"` or a CLI
|
|
41
|
+
`myapp --version`. No JSON endpoint? Put `HEALTH_CMD=...` in the config.
|
|
42
|
+
2. **Server config** — create `/etc/deploy-tools.d/<app>.conf` (app name: `[a-z0-9-]+`):
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
INSTALLER=uv # uv (Python) | npm-global (Node)
|
|
46
|
+
PKG=<registry package name> # e.g. my-tool-server / @scope/my-tool
|
|
47
|
+
BIN=<executable name> # for uv tools (for --version); optional otherwise
|
|
48
|
+
UNIT=<systemd unit name>
|
|
49
|
+
STATUS_URL=http://127.0.0.1:PORT/status # OR: HEALTH_CMD='...'
|
|
50
|
+
HEALTH_FIELD=version
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Test on the host:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
SSH_ORIGINAL_COMMAND="deploy <app> <current-version>" /usr/local/bin/deploy-tools
|
|
57
|
+
# expect: "already on <ver> and healthy — nothing to do"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
3. **Registry/CI side already solved**: publish from `release.yml` exactly like this repo
|
|
61
|
+
(`pypi`/`npm` job first, so deploy only installs what already exists in the registry).
|
|
62
|
+
4. **Deploy job** in the project's `release.yml`:
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
deploy:
|
|
66
|
+
needs: <publish-job>
|
|
67
|
+
uses: vernikr/browser-agent/.github/workflows/deploy-ssh.yml@main
|
|
68
|
+
with:
|
|
69
|
+
app: <app>
|
|
70
|
+
tag: ${{ github.ref_name }}
|
|
71
|
+
secrets: inherit
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
5. **Repo secrets** (Settings → Secrets and variables → Actions): `DEPLOY_SSH_KEY`,
|
|
75
|
+
`DEPLOY_HOST`, `DEPLOY_USER` — the same values as in this repo (reusing the same
|
|
76
|
+
single-purpose key across repos is fine and simplifies rotation; rotate by replacing
|
|
77
|
+
the one `authorized_keys` line + the secret values).
|
|
78
|
+
6. **Smoke-release**: tag `vX.Y.Z+1`, watch the Actions tab — deploy should be green and
|
|
79
|
+
the unit should report the new version on its health endpoint.
|
|
80
|
+
|
|
81
|
+
Failure semantics: unreadable registry → retries; bad health → automatic reinstall of the
|
|
82
|
+
previous version, restart, re-check, and the CI job turns red. Everything is logged in the
|
|
83
|
+
GitHub job — no `journalctl` digging needed for routine failures.
|
|
84
|
+
|
|
85
|
+
## Agent prompt (copy-paste to configure a new project)
|
|
86
|
+
|
|
87
|
+
> Wire the `<PROJECT>` repo for push-style CD to our production server, following
|
|
88
|
+
> `vernikr/browser-agent/docs/multi-project-cd.md`: (1) on the server create
|
|
89
|
+
> `/etc/deploy-tools.d/<app>.conf` for unit `<UNIT>`, package `<PKG>` (`INSTALLER=uv|npm-global`),
|
|
90
|
+
> health via `STATUS_URL=<...>` or `HEALTH_CMD`, then smoke-test with
|
|
91
|
+
> `SSH_ORIGINAL_COMMAND="deploy <app> <current-version>" /usr/local/bin/deploy-tools`;
|
|
92
|
+
> (2) add a `deploy` job to `<PROJECT>`'s `release.yml` that `needs:` the publish job and
|
|
93
|
+
> calls `vernikr/browser-agent/.github/workflows/deploy-ssh.yml@main` with
|
|
94
|
+
> `with: { app: <app>, tag: github.ref_name }` and `secrets: inherit`;
|
|
95
|
+
> (3) add the repo secrets `DEPLOY_SSH_KEY` / `DEPLOY_HOST` / `DEPLOY_USER` (same values as
|
|
96
|
+
> in `vernikr/browser-agent`); (4) ship a patch release and confirm the deploy job is green
|
|
97
|
+
> and the unit reports the new version. Do not touch other services, firewall, or VPN units
|
|
98
|
+
> on the server; before modifying `authorized_keys` or the dispatcher, back the file up to
|
|
99
|
+
> `/root/bak/`.
|
|
@@ -30,3 +30,23 @@ Then still tag, so the GitHub Release and CHANGELOG stay in sync: `git tag vX.Y.
|
|
|
30
30
|
- Verify: https://pypi.org/pypi/browser-agent-server/json (`info.version`)
|
|
31
31
|
- Bump CHANGELOG under `[Unreleased]` for the next cycle.
|
|
32
32
|
- Revoke the manual token once trusted publishing is proven (pypi.org → Account settings → API tokens).
|
|
33
|
+
|
|
34
|
+
## Continuous deployment (release → production)
|
|
35
|
+
|
|
36
|
+
After the PyPI job succeeds, `release.yml` also runs a `deploy` job that ships the exact
|
|
37
|
+
tag version to the production host — no human SSH needed. Design:
|
|
38
|
+
|
|
39
|
+
- The repo holds three secrets: `DEPLOY_SSH_KEY` (dedicated ed25519 keypair), `DEPLOY_HOST`,
|
|
40
|
+
`DEPLOY_USER`. The key is **not** the admin key; on the server it is pinned in
|
|
41
|
+
`authorized_keys` to a single forced command:
|
|
42
|
+
`command="/usr/local/bin/deploy-browser-agent",no-pty,no-port-forwarding,no-agent-forwarding,no-X11-forwarding`.
|
|
43
|
+
Even if the GitHub secret leaks, it can only redeploy this one daemon.
|
|
44
|
+
- The server-side script accepts only `deploy <semver>` (anything else is rejected), installs
|
|
45
|
+
`browser-agent-server==<ver>` from PyPI (`uv tool install --force --refresh`, with retries
|
|
46
|
+
for registry propagation), restarts the systemd unit and waits for `/status` to report the
|
|
47
|
+
target version. On healthcheck failure it reinstalls the previous version and restarts again.
|
|
48
|
+
- Idempotent: redeploying the version already running is a no-op success.
|
|
49
|
+
|
|
50
|
+
Scaling to more projects on the same server: the forced command now points at a generic
|
|
51
|
+
dispatcher — the full playbook (per-project checklist + an agent prompt) is
|
|
52
|
+
[docs/multi-project-cd.md](multi-project-cd.md).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "browser-agent-server"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.4"
|
|
4
4
|
description = "Real headful Chrome on Xvfb with a hardware-level X11 mouse, Cloudflare Turnstile auto-solve and zero-leak CDP. Localhost HTTP API + CLI + Python SDK."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|