diff --git a/ariadne/services/hermes_code_repair.py b/ariadne/services/hermes_code_repair.py index 70abb45..418c22e 100644 --- a/ariadne/services/hermes_code_repair.py +++ b/ariadne/services/hermes_code_repair.py @@ -23,6 +23,8 @@ _REPAIR_BRANCH_PREFIX = "hermes-repair/" _OPEN_PULLS_LIMIT = 50 _COMMIT_IDENTITY = {"name": "Hermes Agent", "email": "hermes@bstein.dev"} _COMMIT_OK_STATUSES = {HTTP_OK, HTTP_CREATED} +# The Hermes console reopens a finished run from its id at this route. +RUN_PATH = "/chat?resume=" _BRANCH_RETRY_STATUSES = {HTTP_NOT_FOUND, HTTP_UNPROCESSABLE} _BRANCH_UNSAFE = re.compile(r"[^A-Za-z0-9._-]+") @@ -256,6 +258,19 @@ def _pr_result(response: Any) -> dict[str, Any]: return {"pr_number": number, "url": url, "error": None} +def run_url(ui_url: str, run_id: str) -> str: + """Build the deep link that reopens one Hermes run in its console. + + Inputs: the Hermes UI base url and a run id. Outputs: the resume link, or + "" when either is missing. Kept here so the pull request and the demo + monitor cannot drift into pointing at different pages. + """ + + base = str(ui_url or "").rstrip("/") + run = str(run_id or "").strip() + return f"{base}{RUN_PATH}{run}" if base and run else "" + + def _pr_body(incident_id: str, patch: Any, analysis: str, run_id: str, cfg: dict) -> str: """Render the markdown pull-request body for human review. @@ -275,12 +290,15 @@ def _pr_body(incident_id: str, patch: Any, analysis: str, run_id: str, cfg: dict f"**Rationale:** {patch.rationale}", ] if run_id: - lines.append(f"**Hermes run:** `{run_id}`") ui_url = str(cfg.get("hermes_ui_url") or "").rstrip("/") if ui_url: + lines.append(f"**Hermes run:** [{run_id}]({run_url(ui_url, run_id)})") lines.append( - f"The prompt this run was given and every tool call it made are at {ui_url}." + "That link opens the run itself: the prompt Hermes was given, the evidence " + "bundle it read, the tools it called, and the JSON it returned." ) + else: + lines.append(f"**Hermes run:** `{run_id}`") lines += [ "", "Proposed by Hermes; validated and pushed by Ariadne; " diff --git a/tests/test_hermes_code_repair.py b/tests/test_hermes_code_repair.py index 09e74a7..b304307 100644 --- a/tests/test_hermes_code_repair.py +++ b/tests/test_hermes_code_repair.py @@ -363,9 +363,11 @@ def test_the_pull_request_names_the_hermes_run(monkeypatch) -> None: ) body = calls["requests"][0][2]["json"]["body"] - assert "**Hermes run:** `run_a5af87af`" in body - assert "https://agent.bstein.dev." in body - assert "every tool call it made" in body + assert ( + "**Hermes run:** [run_a5af87af]" + "(https://agent.bstein.dev/chat?resume=run_a5af87af)" + ) in body + assert "the tools it called" in body def test_the_pull_request_omits_the_link_when_no_ui_is_configured(monkeypatch) -> None: @@ -386,3 +388,13 @@ def test_the_pull_request_stays_readable_without_a_run_id(monkeypatch) -> None: body = calls["requests"][0][2]["json"]["body"] assert "Hermes run" not in body assert "requires human review" in body + + +def test_the_run_link_reopens_the_run_in_the_hermes_console() -> None: + """One helper, so the pull request and the demo monitor cannot diverge.""" + + assert module.run_url("https://agent.bstein.dev/", "run_x") == ( + "https://agent.bstein.dev/chat?resume=run_x" + ) + assert module.run_url("", "run_x") == "" + assert module.run_url("https://agent.bstein.dev", " ") == ""