mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 15:03:16 +00:00
* fix: prevent futile retry loop when commit_and_open_pr fails with git/API errors
- Root cause: when git checkout or GitHub PR API fails, the tool returned a generic {"success": false} error with no signal that retrying is futile, causing the agent to loop 9-13+ times until hitting the 1000-step recursion limit
- Change: (1) git_checkout_branch now returns (bool, str) so the actual git error output is surfaced in the tool response; (2) checkout and PR creation failures now include "fatal": true and an explicit "Do not retry" message; (3) prompt.py COMMIT_PR_SECTION adds an explicit instruction to stop on fatal errors
- Verified: 109 unit tests pass, no regressions
* fix: skip PR safety net on fatal commit failures
* style(open_pr): ruff-format fatal retry skip condition
---------
Co-authored-by: LangSmith Forge <forge-agent@langsmith.ai>
Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
48 lines
1.5 KiB
Python
48 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
import shlex
|
|
from types import SimpleNamespace
|
|
|
|
from agent.utils import github
|
|
|
|
|
|
class FakeSandboxBackend:
|
|
def __init__(self) -> None:
|
|
self.commands: list[str] = []
|
|
self.writes: list[tuple[str, str]] = []
|
|
|
|
def execute(self, command: str) -> SimpleNamespace:
|
|
self.commands.append(command)
|
|
return SimpleNamespace(exit_code=0, output="")
|
|
|
|
def write(self, path: str, content: str) -> None:
|
|
self.writes.append((path, content))
|
|
|
|
|
|
def test_git_checkout_existing_branch_quotes_repo_dir_and_branch() -> None:
|
|
sandbox = FakeSandboxBackend()
|
|
repo_dir = "/tmp/repo; curl attacker"
|
|
branch = "main; curl attacker"
|
|
|
|
github.git_checkout_existing_branch(sandbox, repo_dir, branch)
|
|
|
|
assert sandbox.commands == [f"cd {shlex.quote(repo_dir)} && git checkout {shlex.quote(branch)}"]
|
|
|
|
|
|
def test_git_checkout_branch_returns_true_on_success() -> None:
|
|
sandbox = FakeSandboxBackend()
|
|
ok, err = github.git_checkout_branch(sandbox, "/tmp/repo", "my-branch")
|
|
assert ok is True
|
|
assert err == ""
|
|
|
|
|
|
def test_git_checkout_branch_returns_false_with_error_output_on_failure() -> None:
|
|
class FailingSandbox(FakeSandboxBackend):
|
|
def execute(self, command: str) -> SimpleNamespace:
|
|
self.commands.append(command)
|
|
return SimpleNamespace(exit_code=1, output="error: pathspec did not match")
|
|
|
|
sandbox = FailingSandbox()
|
|
ok, err = github.git_checkout_branch(sandbox, "/tmp/repo", "my-branch")
|
|
assert ok is False
|
|
assert "pathspec did not match" in err
|