Spaces:
Sleeping
Sleeping
| """ | |
| Level 2 Scenarios — Two-step fixes. | |
| """ | |
| from __future__ import annotations | |
| from typing import List | |
| from scenarios.registry import Scenario | |
| def _success_port_freed(output: str) -> bool: | |
| """Check if the port conflict was resolved.""" | |
| o = output.lower() | |
| return "server running" in o or "running on" in o or "killed" in o or "no process" in o | |
| def _success_env_var_set(output: str) -> bool: | |
| """Check if the DATABASE_URL env var is set and app runs.""" | |
| o = output.lower() | |
| return "connected to database" in o or "success" in o or "postgresql://" in o | |
| def _success_requirements_fixed(output: str) -> bool: | |
| """Check if requirements.txt was fixed and packages installed.""" | |
| o = output.lower() | |
| return "successfully installed" in o or "requirement already satisfied" in o | |
| def get_level2_scenarios() -> List[Scenario]: | |
| """Return all Level 2 (two-step fix) scenarios.""" | |
| return [ | |
| Scenario( | |
| id="port_conflict", | |
| level=2, | |
| description="Flask app fails because port 5000 is already in use.", | |
| initial_state={"files": {}, "env_vars": {}, "processes": []}, | |
| success_condition=_success_port_freed, | |
| hint_commands=["lsof -t -i:5000 | xargs kill -9", "python /app/server.py &"], | |
| error_fingerprint=r"Address already in use|EADDRINUSE", | |
| setup_commands=[ | |
| "pip install flask -q", | |
| "mkdir -p /app", | |
| "cat > /app/server.py << 'PYEOF'\nfrom flask import Flask\napp = Flask(__name__)\n@app.route('/')\ndef hello():\n return 'Hello World'\nif __name__ == '__main__':\n app.run(host='0.0.0.0', port=5000)\nPYEOF", | |
| "python -c \"import socket,time; s=socket.socket(); s.bind(('',5000)); s.listen(); time.sleep(3600)\" &", | |
| ], | |
| initial_error_log=( | |
| "$ python /app/server.py\n" | |
| "Traceback (most recent call last):\n" | |
| " File \"/app/server.py\", line 7, in <module>\n" | |
| " app.run(host='0.0.0.0', port=5000)\n" | |
| "OSError: [Errno 98] Address already in use\n" | |
| ), | |
| verification_command="curl -s http://localhost:5000 || echo 'port freed'", | |
| ), | |
| Scenario( | |
| id="missing_env_var", | |
| level=2, | |
| description="App crashes because DATABASE_URL environment variable is not set.", | |
| initial_state={"files": {}, "env_vars": {}, "processes": []}, | |
| success_condition=_success_env_var_set, | |
| hint_commands=["export DATABASE_URL=postgresql://localhost:5432/mydb", "python /app/db_app.py"], | |
| error_fingerprint=r"KeyError.*DATABASE_URL", | |
| setup_commands=[ | |
| "mkdir -p /app", | |
| "cat > /app/db_app.py << 'PYEOF'\nimport os\ndb_url = os.environ['DATABASE_URL']\nprint(f'Connected to database at: {db_url}')\nprint('Success')\nPYEOF", | |
| ], | |
| initial_error_log=( | |
| "$ python /app/db_app.py\n" | |
| "Traceback (most recent call last):\n" | |
| " File \"/app/db_app.py\", line 2, in <module>\n" | |
| " db_url = os.environ['DATABASE_URL']\n" | |
| "KeyError: 'DATABASE_URL'\n" | |
| ), | |
| verification_command="DATABASE_URL=postgresql://localhost:5432/mydb python /app/db_app.py", | |
| ), | |
| Scenario( | |
| id="broken_requirements", | |
| level=2, | |
| description="requirements.txt has a conflicting version pin.", | |
| initial_state={"files": {}, "env_vars": {}, "processes": []}, | |
| success_condition=_success_requirements_fixed, | |
| hint_commands=["sed -i 's/werkzeug==1.0.0/werkzeug>=2.3.0/' /app/requirements.txt", "pip install -r /app/requirements.txt"], | |
| error_fingerprint=r"version.*conflict|ResolutionImpossible", | |
| setup_commands=[ | |
| "mkdir -p /app", | |
| "cat > /app/requirements.txt << 'PYEOF'\nflask==2.3.0\nwerkzeug==1.0.0\njinja2>=3.0\nPYEOF", | |
| ], | |
| initial_error_log=( | |
| "$ pip install -r /app/requirements.txt\n" | |
| "ERROR: Cannot install flask==2.3.0 and werkzeug==1.0.0\n" | |
| "ERROR: ResolutionImpossible\n" | |
| ), | |
| verification_command="pip install -r /app/requirements.txt", | |
| ), | |
| ] | |