website-agent-server 0.1.2__tar.gz → 0.1.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.
- {website_agent_server-0.1.2/website_agent_server.egg-info → website_agent_server-0.1.4}/PKG-INFO +2 -1
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/README.md +2 -1
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/pyproject.toml +1 -1
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/__init__.py +1 -1
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/__main__.py +66 -26
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/browser.py +510 -219
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/config.py +2 -1
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/main.py +94 -7
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/static/app.js +182 -2
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/static/index.html +29 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/static/styles.css +67 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4/website_agent_server.egg-info}/PKG-INFO +2 -1
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/LICENSE +0 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/setup.cfg +0 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/auth.py +0 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/static/auth.css +0 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/static/auth.html +0 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/static/auth.js +0 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server/url_policy.py +0 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server.egg-info/SOURCES.txt +0 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server.egg-info/dependency_links.txt +0 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server.egg-info/entry_points.txt +0 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server.egg-info/requires.txt +0 -0
- {website_agent_server-0.1.2 → website_agent_server-0.1.4}/website_agent_server.egg-info/top_level.txt +0 -0
{website_agent_server-0.1.2/website_agent_server.egg-info → website_agent_server-0.1.4}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: website-agent-server
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: A server-side browser proxy that lets clients operate websites without direct remote connections.
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -80,6 +80,7 @@ venv\Scripts\python.exe -m website_agent_server --pin 123456
|
|
|
80
80
|
| `--accept-language` | `zh-CN,zh;q=0.9,en;q=0.8` | `Accept-Language` header sent by browser contexts. |
|
|
81
81
|
| `--user-agent` | auto | Desktop browser User-Agent. By default the server derives a normal Chrome UA from the bundled Chromium version instead of exposing `HeadlessChrome`. |
|
|
82
82
|
| `--session-ttl-seconds` | `600` | Disconnected client session and client browser context lifetime. A client can reconnect to its cached browser session during this window. |
|
|
83
|
+
| `--shutdown-timeout-seconds` | `3.0` | Maximum graceful shutdown wait for active HTTP/WebSocket connections after Ctrl+C. |
|
|
83
84
|
| `--navigation-timeout-ms` | `30000` | Navigation timeout. |
|
|
84
85
|
| `--frame-interval-seconds` | `0.18` | Screenshot streaming interval. |
|
|
85
86
|
| `--screenshot-quality` | `95` | Frame quality from 1 to 100. Values below 100 use JPEG; 100 uses PNG. |
|
|
@@ -67,7 +67,8 @@ venv\Scripts\python.exe -m website_agent_server --pin 123456
|
|
|
67
67
|
| `--accept-language` | `zh-CN,zh;q=0.9,en;q=0.8` | `Accept-Language` header sent by browser contexts. |
|
|
68
68
|
| `--user-agent` | auto | Desktop browser User-Agent. By default the server derives a normal Chrome UA from the bundled Chromium version instead of exposing `HeadlessChrome`. |
|
|
69
69
|
| `--session-ttl-seconds` | `600` | Disconnected client session and client browser context lifetime. A client can reconnect to its cached browser session during this window. |
|
|
70
|
-
| `--
|
|
70
|
+
| `--shutdown-timeout-seconds` | `3.0` | Maximum graceful shutdown wait for active HTTP/WebSocket connections after Ctrl+C. |
|
|
71
|
+
| `--navigation-timeout-ms` | `30000` | Navigation timeout. |
|
|
71
72
|
| `--frame-interval-seconds` | `0.18` | Screenshot streaming interval. |
|
|
72
73
|
| `--screenshot-quality` | `95` | Frame quality from 1 to 100. Values below 100 use JPEG; 100 uses PNG. |
|
|
73
74
|
| `--media-frame-interval-seconds` | `0.35` | Screenshot streaming interval while remote media is playing. |
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "website-agent-server"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.4"
|
|
8
8
|
description = "A server-side browser proxy that lets clients operate websites without direct remote connections."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -1,13 +1,41 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import argparse
|
|
4
|
-
import asyncio
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
from
|
|
10
|
-
from .
|
|
3
|
+
import argparse
|
|
4
|
+
import asyncio
|
|
5
|
+
import contextlib
|
|
6
|
+
import signal
|
|
7
|
+
import threading
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from types import FrameType
|
|
10
|
+
from collections.abc import Callable, Generator
|
|
11
|
+
|
|
12
|
+
import uvicorn
|
|
13
|
+
from uvicorn.server import HANDLED_SIGNALS
|
|
14
|
+
|
|
15
|
+
from .config import settings
|
|
16
|
+
from .url_policy import HostAccessPolicy
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class WebsiteAgentServer(uvicorn.Server):
|
|
20
|
+
def __init__(self, config: uvicorn.Config, request_stop: Callable[[], None]) -> None:
|
|
21
|
+
super().__init__(config)
|
|
22
|
+
self._request_stop = request_stop
|
|
23
|
+
|
|
24
|
+
def handle_exit(self, sig: int, frame: FrameType | None) -> None:
|
|
25
|
+
self._request_stop()
|
|
26
|
+
super().handle_exit(sig, frame)
|
|
27
|
+
|
|
28
|
+
@contextlib.contextmanager
|
|
29
|
+
def capture_signals(self) -> Generator[None]:
|
|
30
|
+
if threading.current_thread() is not threading.main_thread():
|
|
31
|
+
yield
|
|
32
|
+
return
|
|
33
|
+
original_handlers = {sig: signal.signal(sig, self.handle_exit) for sig in HANDLED_SIGNALS}
|
|
34
|
+
try:
|
|
35
|
+
yield
|
|
36
|
+
finally:
|
|
37
|
+
for sig, handler in original_handlers.items():
|
|
38
|
+
signal.signal(sig, handler)
|
|
11
39
|
|
|
12
40
|
|
|
13
41
|
def build_parser() -> argparse.ArgumentParser:
|
|
@@ -60,11 +88,17 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
60
88
|
"--session-ttl-seconds",
|
|
61
89
|
type=int,
|
|
62
90
|
default=settings.session_ttl_seconds,
|
|
63
|
-
help="Idle session lifetime in seconds.",
|
|
64
|
-
)
|
|
65
|
-
parser.add_argument(
|
|
66
|
-
"--
|
|
67
|
-
type=
|
|
91
|
+
help="Idle session lifetime in seconds.",
|
|
92
|
+
)
|
|
93
|
+
parser.add_argument(
|
|
94
|
+
"--shutdown-timeout-seconds",
|
|
95
|
+
type=float,
|
|
96
|
+
default=settings.shutdown_timeout_seconds,
|
|
97
|
+
help="Maximum graceful shutdown wait for active HTTP/WebSocket connections.",
|
|
98
|
+
)
|
|
99
|
+
parser.add_argument(
|
|
100
|
+
"--navigation-timeout-ms",
|
|
101
|
+
type=int,
|
|
68
102
|
default=settings.navigation_timeout_ms,
|
|
69
103
|
help="Navigation timeout in milliseconds.",
|
|
70
104
|
)
|
|
@@ -146,7 +180,8 @@ async def apply_args(args: argparse.Namespace) -> None:
|
|
|
146
180
|
settings.accept_language = args.accept_language
|
|
147
181
|
settings.user_agent = args.user_agent
|
|
148
182
|
settings.session_ttl_seconds = args.session_ttl_seconds
|
|
149
|
-
settings.
|
|
183
|
+
settings.shutdown_timeout_seconds = max(0.1, args.shutdown_timeout_seconds)
|
|
184
|
+
settings.navigation_timeout_ms = args.navigation_timeout_ms
|
|
150
185
|
settings.frame_interval_seconds = args.frame_interval_seconds
|
|
151
186
|
settings.screenshot_quality = max(1, min(100, args.screenshot_quality))
|
|
152
187
|
settings.media_frame_interval_seconds = max(0.05, args.media_frame_interval_seconds)
|
|
@@ -167,20 +202,25 @@ async def apply_args(args: argparse.Namespace) -> None:
|
|
|
167
202
|
settings.lock_url = None
|
|
168
203
|
|
|
169
204
|
|
|
170
|
-
def main() -> None:
|
|
171
|
-
parser = build_parser()
|
|
172
|
-
args = parser.parse_args()
|
|
205
|
+
def main() -> None:
|
|
206
|
+
parser = build_parser()
|
|
207
|
+
args = parser.parse_args()
|
|
173
208
|
try:
|
|
174
209
|
asyncio.run(apply_args(args))
|
|
175
|
-
except ValueError as exc:
|
|
176
|
-
parser.error(str(exc))
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
210
|
+
except ValueError as exc:
|
|
211
|
+
parser.error(str(exc))
|
|
212
|
+
from .main import app, manager
|
|
213
|
+
|
|
214
|
+
config = uvicorn.Config(
|
|
215
|
+
app,
|
|
216
|
+
host=settings.host,
|
|
217
|
+
port=settings.port,
|
|
218
|
+
reload=False,
|
|
219
|
+
ws_ping_interval=None,
|
|
220
|
+
timeout_graceful_shutdown=settings.shutdown_timeout_seconds,
|
|
221
|
+
)
|
|
222
|
+
server = WebsiteAgentServer(config, manager.request_stop)
|
|
223
|
+
server.run()
|
|
184
224
|
|
|
185
225
|
|
|
186
226
|
if __name__ == "__main__":
|