Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# ReAgent

For a decoupled local progress window with optional worker controls, see the [live monitor guide](docs/live-monitor.md).

[![PyPI](https://img.shields.io/pypi/v/auto-re-agent)](https://pypi.org/project/auto-re-agent/)
[![Python](https://img.shields.io/pypi/pyversions/auto-re-agent)](https://pypi.org/project/auto-re-agent/)
[![CI](https://github.com/Dryxio/reagent/actions/workflows/ci.yml/badge.svg)](https://github.com/Dryxio/reagent/actions/workflows/ci.yml)
Expand Down
44 changes: 44 additions & 0 deletions docs/live-monitor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Live progress monitor

`re-agent monitor` serves a local dashboard independently of the reversal worker. It reads existing session JSON files and logs; it does not import model providers or start work automatically.

```sh
re-agent monitor --work-dir /path/to/project --session-glob re-agent-progress.json --total 500
```

Open the printed `http://127.0.0.1:8765` address. The page refreshes every two seconds and shows saved function results, review passes, failures, rounds, and recent log output. Omit `--total` when the planned count is unknown. A review pass is not a proof of compilation or binary equivalence.

Session patterns are relative to `--work-dir` and can be repeated. For a batch runner:

```sh
re-agent monitor --work-dir /path/to/project --session-glob 'reports/batch-*/progress.json' --log-glob 'reports/batch-*/stderr.log' --total 500
```

The monitor deduplicates function addresses across matching files using their latest result timestamps. Select sessions for the same binary/version; unrelated projects can reuse addresses. Unchanged files are cached, partial JSON writes retain the last readable snapshot, and log output is bounded to the last 7,000 bytes. Counters describe saved final results, not in-flight rounds.

## Optional worker controls

Install the optional process-management dependency:

```sh
pip install 'auto-re-agent[monitor]'
```

Supply an explicit argument array after `--worker`, which must be the last monitor option:

```sh
re-agent monitor --work-dir /path/to/project --session-glob re-agent-progress.json --total 500 --worker re-agent --config re-agent.yaml reverse --manifest targets.json --max-functions 500
```

On Windows, quote paths containing spaces and use an executable such as `python.exe` or `re-agent.exe`, rather than a shell script. Worker arguments are passed directly, without shell interpretation.

- **Start / resume** launches the configured command. Resuming completed work depends on that command's checkpoint behavior. ReAgent uses its configured session and attempt limits; the monitor does not reset them.
- **Stop run** terminates the owned worker process tree. Saved session files remain intact. An interrupted model call may need to be repeated.
- Closing the browser or monitor host leaves the worker running. Restart the monitor with the same work directory, state directory and worker command to reconnect.
- Duplicate starts sharing a state directory are protected by a process lock. Adoption checks the command, working directory record, PID and process creation time, so stale PID records do not attach to unrelated processes.

Control records and worker stdout/stderr live in `reports/monitor` by default; override with `--state-dir`. Treat these as local run artifacts, not source files. `--port` changes the port; zero selects an available port.

## Local access

The server binds only to IPv4 loopback. Host-header checks reject DNS-rebinding requests. Control endpoints require a random per-host token and reject cross-origin requests. HTTP clients cannot supply a different worker command or arbitrary file path. No external scripts, fonts, telemetry or services are used by the dashboard. This is a local tool, not a multi-user network service.
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ dependencies = [
]

[project.optional-dependencies]
monitor = ["psutil>=7.0"]
ghidra-bridge = ["ghidra-ai-bridge>=0.2.0"]
headless = ["ghidra-ai-bridge[headless]>=0.2.0"]
benchmark = ["pefile>=2024.8.26", "unicorn>=2.1"]
dev = ["pytest>=8.0", "pytest-cov>=5.0", "ruff>=0.8", "mypy>=1.13"]
dev = ["pytest>=8.0", "pytest-cov>=5.0", "ruff>=0.8", "mypy>=1.13", "psutil>=7.0"]

[project.scripts]
re-agent = "re_agent.cli.main:main"
Expand Down Expand Up @@ -74,7 +75,7 @@ warn_return_any = true
warn_unused_configs = true

[[tool.mypy.overrides]]
module = ["anthropic.*", "openai.*"]
module = ["anthropic.*", "openai.*", "psutil.*"]
ignore_missing_imports = true

[tool.pytest.ini_options]
Expand Down
22 changes: 22 additions & 0 deletions src/re_agent/cli/cmd_monitor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Serve a local progress dashboard without importing model providers."""
from __future__ import annotations

import argparse
import contextlib
from pathlib import Path


def cmd_monitor(args: argparse.Namespace) -> int:
from re_agent.monitor.server import Monitor, make_server

if not 0 <= args.port <= 65535:
raise ValueError("Port must be between 0 and 65535")
root = Path(args.work_dir).resolve()
monitor = Monitor(root, root / args.state_dir, args.session_glob or ["re-agent-progress.json"],
args.log_glob, args.total, args.worker)
with make_server(monitor, args.port) as server:
print(f"Live monitor: http://127.0.0.1:{server.server_port}", flush=True)
print("Closing the monitor does not stop the worker. Use Stop run to terminate it.", flush=True)
with contextlib.suppress(KeyboardInterrupt):
server.serve_forever()
return 0
14 changes: 14 additions & 0 deletions src/re_agent/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ def build_parser() -> argparse.ArgumentParser:

sub = parser.add_subparsers(dest="command", help="Available commands")

monitor_p = sub.add_parser("monitor", help="Host a local live progress dashboard")
monitor_p.add_argument("--work-dir", default=".", help="Directory containing run sessions")
monitor_p.add_argument("--state-dir", default="reports/monitor", help="Monitor control state and worker logs")
monitor_p.add_argument("--session-glob", action="append", help="Relative session pattern (repeatable)")
monitor_p.add_argument("--log-glob", help="Relative activity-log pattern; shows most recently modified log")
monitor_p.add_argument("--total", type=int, default=0, help="Planned function count; 0 means unknown")
monitor_p.add_argument("--port", type=int, default=8765)
monitor_p.add_argument("--worker", nargs=argparse.REMAINDER, help="Optional worker argv; must be the last option")

doctor_p = sub.add_parser("doctor", help="Check configuration and exported evidence without LLM calls")
doctor_p.add_argument("--address", help="Check evidence for one function")
benchmark_p = sub.add_parser("benchmark", help="Run a differential harness manifest")
Expand Down Expand Up @@ -78,6 +87,11 @@ def _main(argv: list[str] | None = None) -> int:
parser.print_help()
return 0

if args.command == "monitor":
from re_agent.cli.cmd_monitor import cmd_monitor

return cmd_monitor(args)

if args.command == "evidence":
from re_agent.cli.cmd_evidence import cmd_evidence

Expand Down
1 change: 1 addition & 0 deletions src/re_agent/monitor/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Optional local progress dashboard; independent of the reversal worker."""
Loading
Loading