Files
wehub-resource-sync 0d3cb498a3
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Waiting to run
Test and Publish Multi-arch Docker Image / test (push) Waiting to run
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Blocked by required conditions
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Blocked by required conditions
Validate Renovate Config / Validate Renovate Configuration (push) Waiting to run
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:24:08 +08:00

137 lines
4.8 KiB
Python

# swe_runner.py (e2b-only skeleton)
import os
import shutil
import subprocess
import tempfile
from textwrap import dedent
from e2b_code_interpreter import Sandbox
# Optional: use OpenAI if available for real patch generation
try:
from openai import OpenAI # pip install openai
except Exception:
OpenAI = None
def model_call_patch(fail_log: str, relevant_files: dict) -> str:
"""
Minimal working example:
- If OPENAI_API_KEY is set and the OpenAI SDK is available, ask the model for a unified diff.
- Otherwise, return a tiny, valid unified diff against the first relevant file (demo fallback).
"""
# 1) Try LLM-backed patch generation (only if configured)
if OpenAI and os.getenv("OPENAI_API_KEY"):
client = OpenAI()
model = os.getenv("PATCH_MODEL", "gpt-4o-mini")
sys_msg = (
"You are a code repair assistant. Output ONLY a unified diff patch that "
"can be applied with `git apply -p0`. Do NOT include any explanations."
)
files_blob = "\n\n".join(
f"{path}:\n{content}" for path, content in relevant_files.items()
)
user_msg = (
"Given the failing test log and the repository files, produce a minimal fix:\n\n"
f"Failing test log:\n{fail_log}\n\n"
f"Relevant files (path => content):\n{files_blob}\n"
)
resp = client.chat.completions.create(
model=model,
temperature=0,
messages=[
{"role": "system", "content": sys_msg},
{"role": "user", "content": user_msg},
],
)
if not resp.choices or resp.choices[0].message is None:
raise ValueError("LLM returned empty or filtered response")
patch = resp.choices[0].message.content.strip()
return patch
# 2) Fallback: return a harmless, valid unified diff so the example runs without any API keys
if not relevant_files:
demo_path = "README.md"
old = ""
else:
demo_path = next(iter(relevant_files.keys()))
old = relevant_files[demo_path]
# Minimal unified diff; uses -p0 friendly paths (a/ and b/)
fallback_patch = dedent(f"""\
--- a/{demo_path}
+++ b/{demo_path}
@@
{old or ""}
+# patched-by-demo
""")
return fallback_patch
def run_task_local(
repo_url: str, failing_test_cmd: str, relevant_paths: list, attempts=3
):
tmp = tempfile.mkdtemp()
try:
subprocess.check_call(["git", "clone", repo_url, tmp])
cwd = os.getcwd()
os.chdir(tmp)
# capture failing test
p = subprocess.run(failing_test_cmd, shell=True, capture_output=True, text=True)
fail_log = p.stdout + "\n" + p.stderr
relevant_files = {}
for path in relevant_paths:
try:
with open(os.path.join(tmp, path), "r") as f:
relevant_files[path] = f.read()
except Exception:
relevant_files[path] = ""
success = False
for attempt in range(attempts):
try:
patch = model_call_patch(fail_log, relevant_files)
except Exception as e:
print("Model call failed:", e)
break
# apply patch locally
proc = subprocess.run(
["git", "apply", "-"], input=patch, text=True, capture_output=True
)
if proc.returncode != 0:
print("Patch apply failed:", proc.stderr)
continue
# run tests inside e2b sandbox (safe)
with Sandbox.create() as sbx:
test_script = f"import subprocess; print(subprocess.run('{failing_test_cmd}', shell=True, capture_output=True).returncode)"
res = sbx.run_code(
code=test_script,
language="python",
limits={"cputime": 10, "wall_time": 30, "memory": 512},
allow_network=False,
)
rc = None
try:
if getattr(res, "results", None):
r0 = res.results[0]
val = r0.get("stdout") or r0.get("output") or r0.get("text") or ""
if isinstance(val, list):
val = "".join(map(str, val))
rc = int(str(val).strip())
elif getattr(res, "text", None):
rc = int(str(res.text).strip())
except Exception:
rc = None
if rc == 0:
success = True
print("Patch fixed tests on attempt", attempt + 1)
break
else:
print("Patch did not fix tests; rc:", rc)
os.chdir(cwd)
return {"success": success}
finally:
shutil.rmtree(tmp, ignore_errors=True)