r2flow-agent 0.3.2__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.
@@ -0,0 +1,14 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .mypy_cache/
7
+ .ruff_cache/
8
+ .pytest_cache/
9
+ .venv/
10
+ venv/
11
+ *.egg
12
+ .env
13
+ agent_err.log
14
+ agent_out.log
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 2kurosss
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,106 @@
1
+ Metadata-Version: 2.5
2
+ Name: r2flow-agent
3
+ Version: 0.3.2
4
+ Summary: R2Flow RPA agent - runs on Windows machines and executes processes dispatched by a r2flow-cloud orchestrator
5
+ Project-URL: Homepage, https://github.com/2kurosss/r2flow
6
+ Project-URL: Repository, https://github.com/2kurosss/r2flow
7
+ Project-URL: Issues, https://github.com/2kurosss/r2flow/issues
8
+ Author: 2kurosss
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Requires-Python: >=3.11
12
+ Requires-Dist: httpx>=0.27.0
13
+ Requires-Dist: rich>=13.0.0
14
+ Provides-Extra: dev
15
+ Requires-Dist: mypy>=1.18; extra == 'dev'
16
+ Requires-Dist: pytest-asyncio>=1.0; extra == 'dev'
17
+ Requires-Dist: pytest>=8; extra == 'dev'
18
+ Requires-Dist: ruff>=0.12; extra == 'dev'
19
+ Provides-Extra: screenshot
20
+ Requires-Dist: mss>=9; extra == 'screenshot'
21
+ Requires-Dist: pillow>=10; extra == 'screenshot'
22
+ Description-Content-Type: text/markdown
23
+
24
+ # r2flow-agent
25
+
26
+ Unattended worker that runs on a Windows machine, registers itself with a
27
+ [r2flow-cloud](https://github.com/2kurosss/r2flow) orchestrator,
28
+ polls it for commands, and executes deployed process bundles (Python code)
29
+ in isolated per-process venvs.
30
+
31
+ ## One-line install (Windows)
32
+
33
+ Regular PowerShell (it self-elevates and installs Python 3.12 via winget if
34
+ missing):
35
+
36
+ ```powershell
37
+ irm https://raw.githubusercontent.com/2kurosss/r2flow/main/packages/agent/install-agent.ps1 | iex
38
+ ```
39
+
40
+ With parameters:
41
+
42
+ ```powershell
43
+ & ([scriptblock]::Create((irm https://raw.githubusercontent.com/2kurosss/r2flow/main/packages/agent/install-agent.ps1))) `
44
+ -Orchestrator https://cloud.example.com -Name prod-1 -JoinToken <TOKEN>
45
+ ```
46
+
47
+ ## Manual install
48
+
49
+ ```bash
50
+ pip install r2flow-agent
51
+ ```
52
+
53
+
54
+ ## Quick start (manual, foreground)
55
+
56
+ ```bash
57
+ pip install r2flow-agent
58
+ r2flow-agent --orchestrator http://orch-host:8000 --name my-agent \
59
+ --url http://this-machine:8001
60
+ ```
61
+
62
+ `--url` must be the address at which the **orchestrator** can reach this
63
+ machine (the orchestrator pushes commands and files to it).
64
+
65
+ ## Unattended installation (recommended)
66
+
67
+ UI automation needs an **interactive desktop**, so the agent runs as a
68
+ scheduled task inside a user's log-on session — not as a session-0 service.
69
+ Use a dedicated local user with auto-logon for production agents.
70
+
71
+ ```bash
72
+ # one command: writes config + creates the scheduled task
73
+ r2flow-agent-service install \
74
+ --orchestrator http://orch-host:8000 \
75
+ --name prod-1 \
76
+ --join-token <AGENT_JOIN_TOKEN> \
77
+ --user "WORKGROUP\\rpa-bot" # optional, default: current user
78
+
79
+ r2flow-agent-service start # launch now
80
+ r2flow-agent-service status # task state
81
+ r2flow-agent-service stop | uninstall
82
+ ```
83
+
84
+ What you get:
85
+
86
+ * task trigger **at log on** of the automation user → agent starts with the
87
+ desktop, no manual steps after reboots;
88
+ * Task Scheduler restart policy (up to 999 retries, 1-minute interval) and,
89
+ belt and braces, a crash-restart loop inside the agent with exponential
90
+ backoff (5 s → 60 s, reset after a stable 5-minute run);
91
+ * config at `%LOCALAPPDATA%\r2flow_agent\config.json`, rolling log at
92
+ `%LOCALAPPDATA%\r2flow_agent\agent.log`.
93
+
94
+ Registration honours `AGENT_JOIN_TOKEN` (pre-shared in the orchestrator
95
+ settings) or an admin JWT — whichever you pass with `--join-token`.
96
+
97
+ ## Privacy note: failure screenshots
98
+
99
+ On a failed run the agent (with the [screenshot] extra installed) captures
100
+ the **entire virtual screen** — all monitors and every visible window, not
101
+ just the automated app — and uploads it to the orchestrator. Keep this in
102
+ mind on shared/multi-user machines: anything on screen at the moment of
103
+ failure (other apps, browser sessions, passwords) ends up in the cloud.
104
+
105
+ Deploy with the plain r2flow-agent package if screenshots are unwanted;
106
+ the agent runs fine without the extra and simply skips capture.
@@ -0,0 +1,83 @@
1
+ # r2flow-agent
2
+
3
+ Unattended worker that runs on a Windows machine, registers itself with a
4
+ [r2flow-cloud](https://github.com/2kurosss/r2flow) orchestrator,
5
+ polls it for commands, and executes deployed process bundles (Python code)
6
+ in isolated per-process venvs.
7
+
8
+ ## One-line install (Windows)
9
+
10
+ Regular PowerShell (it self-elevates and installs Python 3.12 via winget if
11
+ missing):
12
+
13
+ ```powershell
14
+ irm https://raw.githubusercontent.com/2kurosss/r2flow/main/packages/agent/install-agent.ps1 | iex
15
+ ```
16
+
17
+ With parameters:
18
+
19
+ ```powershell
20
+ & ([scriptblock]::Create((irm https://raw.githubusercontent.com/2kurosss/r2flow/main/packages/agent/install-agent.ps1))) `
21
+ -Orchestrator https://cloud.example.com -Name prod-1 -JoinToken <TOKEN>
22
+ ```
23
+
24
+ ## Manual install
25
+
26
+ ```bash
27
+ pip install r2flow-agent
28
+ ```
29
+
30
+
31
+ ## Quick start (manual, foreground)
32
+
33
+ ```bash
34
+ pip install r2flow-agent
35
+ r2flow-agent --orchestrator http://orch-host:8000 --name my-agent \
36
+ --url http://this-machine:8001
37
+ ```
38
+
39
+ `--url` must be the address at which the **orchestrator** can reach this
40
+ machine (the orchestrator pushes commands and files to it).
41
+
42
+ ## Unattended installation (recommended)
43
+
44
+ UI automation needs an **interactive desktop**, so the agent runs as a
45
+ scheduled task inside a user's log-on session — not as a session-0 service.
46
+ Use a dedicated local user with auto-logon for production agents.
47
+
48
+ ```bash
49
+ # one command: writes config + creates the scheduled task
50
+ r2flow-agent-service install \
51
+ --orchestrator http://orch-host:8000 \
52
+ --name prod-1 \
53
+ --join-token <AGENT_JOIN_TOKEN> \
54
+ --user "WORKGROUP\\rpa-bot" # optional, default: current user
55
+
56
+ r2flow-agent-service start # launch now
57
+ r2flow-agent-service status # task state
58
+ r2flow-agent-service stop | uninstall
59
+ ```
60
+
61
+ What you get:
62
+
63
+ * task trigger **at log on** of the automation user → agent starts with the
64
+ desktop, no manual steps after reboots;
65
+ * Task Scheduler restart policy (up to 999 retries, 1-minute interval) and,
66
+ belt and braces, a crash-restart loop inside the agent with exponential
67
+ backoff (5 s → 60 s, reset after a stable 5-minute run);
68
+ * config at `%LOCALAPPDATA%\r2flow_agent\config.json`, rolling log at
69
+ `%LOCALAPPDATA%\r2flow_agent\agent.log`.
70
+
71
+ Registration honours `AGENT_JOIN_TOKEN` (pre-shared in the orchestrator
72
+ settings) or an admin JWT — whichever you pass with `--join-token`.
73
+
74
+ ## Privacy note: failure screenshots
75
+
76
+ On a failed run the agent (with the [screenshot] extra installed) captures
77
+ the **entire virtual screen** — all monitors and every visible window, not
78
+ just the automated app — and uploads it to the orchestrator. Keep this in
79
+ mind on shared/multi-user machines: anything on screen at the moment of
80
+ failure (other apps, browser sessions, passwords) ends up in the cloud.
81
+
82
+ Deploy with the plain r2flow-agent package if screenshots are unwanted;
83
+ the agent runs fine without the extra and simply skips capture.
@@ -0,0 +1,138 @@
1
+ #requires -Version 5.1
2
+ <#
3
+ R2Flow agent one-line installer (Windows).
4
+
5
+ Usage (regular PowerShell, elevated not required - it will self-elevate):
6
+
7
+ irm https://raw.githubusercontent.com/2kurosss/r2flow/main/packages/agent/install-agent.ps1 | iex
8
+
9
+ or with parameters:
10
+
11
+ & ([scriptblock]::Create((irm https://raw.githubusercontent.com/2kurosss/r2flow/main/packages/agent/install-agent.ps1))) `
12
+ -Orchestrator https://cloud.example.com -Name prod-1 -JoinToken <TOKEN>
13
+ #>
14
+ param(
15
+ [string]$Orchestrator = "",
16
+ [string]$Name = "",
17
+ [string]$JoinToken = "",
18
+ [string]$AgentUrl = "",
19
+ [string]$User = "",
20
+ [string]$Python = "",
21
+ # Supply-chain pinning: point this at a release tag instead of master
22
+ # (e.g. https://raw.githubusercontent.com/2kurosss/r2flow/v0.2.1/install-agent.ps1)
23
+ [string]$RepoUrl = "https://raw.githubusercontent.com/2kurosss/r2flow/main/packages/agent/install-agent.ps1"
24
+ )
25
+
26
+ $ErrorActionPreference = "Stop"
27
+ $VenvDir = Join-Path $env:LOCALAPPDATA "r2flow-agent\venv"
28
+
29
+ function Test-Admin {
30
+ $id = [Security.Principal.WindowsIdentity]::GetCurrent()
31
+ (New-Object Security.Principal.WindowsPrincipal($id)).IsInRole(
32
+ [Security.Principal.WindowsBuiltInRole]::Administrator)
33
+ }
34
+
35
+ function Find-Python {
36
+ if ($Python -and (Test-Path $Python)) { return $Python }
37
+ $cmd = Get-Command python -ErrorAction SilentlyContinue
38
+ if ($cmd) {
39
+ $v = & python -c "import sys; print('%d.%d' % sys.version_info[:2])" 2>$null
40
+ if ($v -and [version]$v -ge [version]"3.11") { return $cmd.Source }
41
+ }
42
+ $py = Get-Command py -ErrorAction SilentlyContinue
43
+ if ($py) {
44
+ $v = & py -3 -c "import sys; print('%d.%d' % sys.version_info[:2])" 2>$null
45
+ if ($v -and [version]$v -ge [version]"3.11") { return "py" }
46
+ }
47
+ return ""
48
+ }
49
+
50
+ # ---------------------------------------------------------------- elevate
51
+ if (-not (Test-Admin)) {
52
+ Write-Host "Not running as administrator - relaunching elevated..."
53
+ $tmp = Join-Path $env:TEMP "r2flow-agent-install.ps1"
54
+ if ($MyInvocation.MyCommand.Path -and (Test-Path $MyInvocation.MyCommand.Path)) {
55
+ # Elevated pass must run the exact copy the user inspected - never a
56
+ # fresh (possibly different) download from the network.
57
+ Copy-Item $MyInvocation.MyCommand.Path $tmp -Force
58
+ } else {
59
+ # irm|iex entry: no file on disk - pin to whatever RepoUrl was set to.
60
+ Invoke-WebRequest -UseBasicParsing -Uri $RepoUrl -OutFile $tmp
61
+ }
62
+
63
+ # Rebuild the invocation as an encoded command: values starting with "-"
64
+ # (join tokens are base64-ish) cannot be passed as bare -File arguments.
65
+ function Esc([string]$s) { return "'" + $s.Replace("'", "''") + "'" }
66
+ $inner = "& '$tmp'"
67
+ foreach ($p in @("Orchestrator", "Name", "JoinToken", "AgentUrl", "User", "Python")) {
68
+ $val = Get-Variable -Name $p -ValueOnly
69
+ if ($val) { $inner += " -$p $(Esc $val)" }
70
+ }
71
+ $enc = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($inner))
72
+ $proc = Start-Process powershell -Verb RunAs -Wait -PassThru -ArgumentList @(
73
+ "-NoProfile", "-ExecutionPolicy", "Bypass", "-EncodedCommand", $enc)
74
+ exit $proc.ExitCode
75
+ }
76
+
77
+ Write-Host "=== R2Flow agent installer ==="
78
+
79
+ # ---------------------------------------------------------------- orchestrator
80
+ if (-not $Orchestrator) {
81
+ $Orchestrator = Read-Host "Orchestrator URL (e.g. https://cloud.example.com)"
82
+ }
83
+ $Orchestrator = $Orchestrator.TrimEnd("/")
84
+
85
+ if (-not $Name) {
86
+ $hostLabel = $env:COMPUTERNAME.ToLower() -replace "[^a-z0-9-]", "-"
87
+ $Name = "agent-$hostLabel"
88
+ }
89
+ Write-Host "Orchestrator: $Orchestrator"
90
+ Write-Host "Agent name: $Name"
91
+
92
+ # ---------------------------------------------------------------- python
93
+ $pyExe = Find-Python
94
+ if (-not $pyExe) {
95
+ Write-Host "Python 3.11+ not found - installing via winget..."
96
+ winget install --id Python.Python.3.12 --silent --accept-package-agreements --accept-source-agreements
97
+ if ($LASTEXITCODE -ne 0) { throw "winget failed to install Python; install it manually from https://python.org" }
98
+ # winget adds Python to the machine PATH; pick it up for this session
99
+ $env:PATH = [Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" +
100
+ [Environment]::GetEnvironmentVariable("PATH", "User")
101
+ $pyExe = Find-Python
102
+ if (-not $pyExe) { throw "Python installed but not found - reopen the terminal and retry" }
103
+ }
104
+ Write-Host "Python: $pyExe"
105
+
106
+ # ---------------------------------------------------------------- venv
107
+ New-Item -ItemType Directory -Force -Path (Split-Path $VenvDir) | Out-Null
108
+ if (-not (Test-Path "$VenvDir\Scripts\python.exe")) {
109
+ Write-Host "Creating venv at $VenvDir ..."
110
+ & $pyExe -m venv $VenvDir
111
+ if ($LASTEXITCODE -ne 0) { throw "venv creation failed" }
112
+ }
113
+ Write-Host "Installing r2flow-agent[screenshot] (PyPI)..."
114
+ & "$VenvDir\Scripts\python.exe" -m pip install --upgrade pip --quiet
115
+ & "$VenvDir\Scripts\python.exe" -m pip install --upgrade "r2flow-agent[screenshot]" --quiet
116
+ if ($LASTEXITCODE -ne 0) { throw "pip install r2flow-agent failed" }
117
+
118
+ # ---------------------------------------------------------------- register
119
+ $svc = "$VenvDir\Scripts\r2flow-agent-service.exe"
120
+ if (-not (Test-Path $svc)) { $svc = "$VenvDir\Scripts\r2flow-agent-service.bat" }
121
+
122
+ $installArgs = @("install", "--orchestrator", $Orchestrator, "--name", $Name)
123
+ if ($AgentUrl) { $installArgs += @("--url", $AgentUrl) }
124
+ if ($JoinToken) { $installArgs += "--join-token=$JoinToken" }
125
+ if ($User) { $installArgs += @("--user", $User) }
126
+
127
+ & $svc @installArgs
128
+ if ($LASTEXITCODE -ne 0) { throw "r2flow-agent-service install failed (exit $LASTEXITCODE)" }
129
+
130
+ Write-Host "Starting the agent..."
131
+ & $svc start
132
+
133
+ Write-Host ""
134
+ Write-Host "=== Done ==="
135
+ Write-Host "Agent: $Name"
136
+ Write-Host "Config: $env:LOCALAPPDATA\r2flow_agent\config.json"
137
+ Write-Host "Log: $env:LOCALAPPDATA\r2flow_agent\agent.log"
138
+ Write-Host "It starts automatically at logon. Check it in the orchestrator web UI."
@@ -0,0 +1,60 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "r2flow-agent"
7
+ version = "0.3.2"
8
+ description = "R2Flow RPA agent - runs on Windows machines and executes processes dispatched by a r2flow-cloud orchestrator"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.11"
12
+ authors = [{ name = "2kurosss" }]
13
+ dependencies = [
14
+ "httpx>=0.27.0",
15
+ "rich>=13.0.0",
16
+ ]
17
+
18
+ [project.optional-dependencies]
19
+ screenshot = [
20
+ "mss>=9",
21
+ "Pillow>=10",
22
+ ]
23
+ dev = [
24
+ "pytest>=8",
25
+ "pytest-asyncio>=1.0",
26
+ "ruff>=0.12",
27
+ "mypy>=1.18",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/2kurosss/r2flow"
32
+ Repository = "https://github.com/2kurosss/r2flow"
33
+ Issues = "https://github.com/2kurosss/r2flow/issues"
34
+
35
+ [project.scripts]
36
+ r2flow-agent = "r2flow_agent.main:main"
37
+ r2flow-agent-service = "r2flow_agent.service:main"
38
+
39
+ [tool.hatch.build.targets.wheel]
40
+ packages = ["src/r2flow_agent"]
41
+
42
+ [tool.pytest.ini_options]
43
+ testpaths = ["tests"]
44
+ asyncio_mode = "auto"
45
+
46
+ [tool.ruff]
47
+ line-length = 100
48
+ target-version = "py311"
49
+
50
+ [tool.ruff.lint]
51
+ select = ["E", "F", "I", "N", "UP", "B", "A", "C4", "SIM"]
52
+ # B008 (function call in default) is the idiomatic argparse/click pattern.
53
+ ignore = ["B008"]
54
+
55
+ [tool.mypy]
56
+ python_version = "3.11"
57
+
58
+ [[tool.mypy.overrides]]
59
+ module = ["mss", "mss.*", "PIL", "PIL.*"]
60
+ ignore_missing_imports = true
@@ -0,0 +1,5 @@
1
+ """R2Flow Cloud Agent — runs on each server and communicates with the orchestrator."""
2
+
3
+ from __future__ import annotations
4
+
5
+ __version__ = "0.3.2"