aicodinggym-cli 0.4.0__tar.gz → 0.5.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/PKG-INFO +1 -1
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/aicodinggym_cli.egg-info/PKG-INFO +1 -1
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/api.py +12 -8
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/cli.py +85 -0
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/git_ops.py +6 -2
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/pyproject.toml +1 -1
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/README.md +0 -0
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/__init__.py +0 -0
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/aicodinggym_cli.egg-info/SOURCES.txt +0 -0
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/aicodinggym_cli.egg-info/dependency_links.txt +0 -0
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/aicodinggym_cli.egg-info/entry_points.txt +0 -0
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/aicodinggym_cli.egg-info/requires.txt +0 -0
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/aicodinggym_cli.egg-info/top_level.txt +0 -0
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/config.py +0 -0
- {aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/setup.cfg +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"""HTTP API client for the AI Coding Gym backend at aicodinggym.com."""
|
|
2
2
|
|
|
3
|
+
import gzip
|
|
3
4
|
import os
|
|
5
|
+
from pathlib import Path
|
|
4
6
|
|
|
5
7
|
import requests
|
|
6
8
|
|
|
@@ -123,15 +125,17 @@ def mlebench_download_file(url: str, dest_path: str, timeout: int = 300) -> None
|
|
|
123
125
|
def mlebench_submit_csv(user_id: str, competition_id: str, csv_path: str) -> dict:
|
|
124
126
|
"""Upload a prediction CSV for an MLE-bench competition."""
|
|
125
127
|
try:
|
|
128
|
+
csv_name = Path(csv_path).name
|
|
126
129
|
with open(csv_path, "rb") as f:
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
130
|
+
compressed = gzip.compress(f.read())
|
|
131
|
+
resp = requests.post(
|
|
132
|
+
f"{API_BASE}/competitions/{competition_id}/submit",
|
|
133
|
+
data={"user_id": user_id, "competition_id": competition_id},
|
|
134
|
+
files={"file": (csv_name + ".gz", compressed, "application/gzip")},
|
|
135
|
+
timeout=120,
|
|
136
|
+
)
|
|
137
|
+
resp.raise_for_status()
|
|
138
|
+
return resp.json()
|
|
135
139
|
except requests.ConnectionError:
|
|
136
140
|
raise APIError(
|
|
137
141
|
f"Cannot connect to {API_BASE}.\n"
|
|
@@ -22,11 +22,13 @@ CODE REVIEW WORKFLOW:
|
|
|
22
22
|
aicodinggym cr submit sentry-0001 -f review.md
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
+
import json
|
|
25
26
|
import os
|
|
26
27
|
import platform
|
|
27
28
|
import re
|
|
28
29
|
import subprocess
|
|
29
30
|
import sys
|
|
31
|
+
import urllib.request
|
|
30
32
|
from datetime import datetime
|
|
31
33
|
from pathlib import Path
|
|
32
34
|
|
|
@@ -78,6 +80,81 @@ def _warn(msg: str) -> None:
|
|
|
78
80
|
click.echo(f"Warning: {msg}", err=True)
|
|
79
81
|
|
|
80
82
|
|
|
83
|
+
_GYM_ENV_API = "https://api.github.com/repos/AICodingGym/gym-environment/contents"
|
|
84
|
+
_GYM_ENV_SKIP = {"README.md"}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _install_gym_environment(dest: Path) -> None:
|
|
88
|
+
"""Download gym-environment files into dest and add them to .gitignore."""
|
|
89
|
+
try:
|
|
90
|
+
req = urllib.request.Request(_GYM_ENV_API, headers={"Accept": "application/vnd.github.v3+json"})
|
|
91
|
+
with urllib.request.urlopen(req, timeout=15) as resp:
|
|
92
|
+
entries = json.loads(resp.read())
|
|
93
|
+
except Exception as e:
|
|
94
|
+
_warn(f"Could not fetch gym-environment file list: {e}")
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
downloaded: list[str] = []
|
|
98
|
+
|
|
99
|
+
for entry in entries:
|
|
100
|
+
name = entry.get("name", "")
|
|
101
|
+
if name in _GYM_ENV_SKIP:
|
|
102
|
+
continue
|
|
103
|
+
etype = entry.get("type")
|
|
104
|
+
|
|
105
|
+
if etype == "file":
|
|
106
|
+
url = entry.get("download_url")
|
|
107
|
+
if not url:
|
|
108
|
+
continue
|
|
109
|
+
try:
|
|
110
|
+
with urllib.request.urlopen(url, timeout=15) as r:
|
|
111
|
+
(dest / name).write_bytes(r.read())
|
|
112
|
+
downloaded.append(name)
|
|
113
|
+
except Exception as e:
|
|
114
|
+
_warn(f"Failed to download {name}: {e}")
|
|
115
|
+
|
|
116
|
+
elif etype == "dir":
|
|
117
|
+
# Fetch subdirectory contents recursively (one level deep)
|
|
118
|
+
try:
|
|
119
|
+
sub_req = urllib.request.Request(
|
|
120
|
+
f"{_GYM_ENV_API}/{name}",
|
|
121
|
+
headers={"Accept": "application/vnd.github.v3+json"},
|
|
122
|
+
)
|
|
123
|
+
with urllib.request.urlopen(sub_req, timeout=15) as r:
|
|
124
|
+
sub_entries = json.loads(r.read())
|
|
125
|
+
except Exception as e:
|
|
126
|
+
_warn(f"Failed to list directory {name}: {e}")
|
|
127
|
+
continue
|
|
128
|
+
|
|
129
|
+
sub_dir = dest / name
|
|
130
|
+
sub_dir.mkdir(parents=True, exist_ok=True)
|
|
131
|
+
for sub in sub_entries:
|
|
132
|
+
sub_name = sub.get("name", "")
|
|
133
|
+
sub_url = sub.get("download_url")
|
|
134
|
+
if sub.get("type") != "file" or not sub_url:
|
|
135
|
+
continue
|
|
136
|
+
try:
|
|
137
|
+
with urllib.request.urlopen(sub_url, timeout=15) as r:
|
|
138
|
+
(sub_dir / sub_name).write_bytes(r.read())
|
|
139
|
+
except Exception as e:
|
|
140
|
+
_warn(f"Failed to download {name}/{sub_name}: {e}")
|
|
141
|
+
downloaded.append(name)
|
|
142
|
+
|
|
143
|
+
if not downloaded:
|
|
144
|
+
return
|
|
145
|
+
|
|
146
|
+
# Append to .gitignore
|
|
147
|
+
gitignore = dest / ".gitignore"
|
|
148
|
+
existing = gitignore.read_text(encoding="utf-8") if gitignore.exists() else ""
|
|
149
|
+
existing_lines = set(existing.splitlines())
|
|
150
|
+
new_entries = [f for f in downloaded if f not in existing_lines and f"/{f}" not in existing_lines]
|
|
151
|
+
if new_entries:
|
|
152
|
+
block = "\n# gym-environment\n" + "\n".join(new_entries) + "\n"
|
|
153
|
+
with open(gitignore, "a", encoding="utf-8", newline="\n") as fh:
|
|
154
|
+
fh.write(block)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
81
158
|
def _resolve_user_id(config: dict, user_id: str | None) -> str:
|
|
82
159
|
"""Resolve user_id from argument or config, with helpful error."""
|
|
83
160
|
if user_id:
|
|
@@ -334,6 +411,8 @@ def configure(user_id: str, workspace_dir: str | None):
|
|
|
334
411
|
}
|
|
335
412
|
save_config(config)
|
|
336
413
|
|
|
414
|
+
_install_gym_environment(Path(resolved_workspace))
|
|
415
|
+
|
|
337
416
|
click.echo(
|
|
338
417
|
f"\nConfiguration saved successfully!\n"
|
|
339
418
|
f"\n"
|
|
@@ -449,6 +528,8 @@ def swe_fetch(problem_id: str, user_id: str | None, workspace_dir: str | None):
|
|
|
449
528
|
if not success:
|
|
450
529
|
_error(msg)
|
|
451
530
|
|
|
531
|
+
_install_gym_environment(workspace / problem_id)
|
|
532
|
+
|
|
452
533
|
click.echo(
|
|
453
534
|
f"\nSuccessfully fetched problem: {problem_id}\n"
|
|
454
535
|
f"\n"
|
|
@@ -940,6 +1021,8 @@ def cr_fetch(problem_id: str, user_id: str | None, workspace_dir: str | None):
|
|
|
940
1021
|
if not success:
|
|
941
1022
|
_error(msg)
|
|
942
1023
|
|
|
1024
|
+
_install_gym_environment(workspace / problem_id)
|
|
1025
|
+
|
|
943
1026
|
problem_dir = workspace / problem_id
|
|
944
1027
|
|
|
945
1028
|
# Generate diff.patch
|
|
@@ -1099,6 +1182,8 @@ def mle_download(competition_id: str, user_id: str | None, workspace_dir: str |
|
|
|
1099
1182
|
except APIError as e:
|
|
1100
1183
|
_error(str(e))
|
|
1101
1184
|
|
|
1185
|
+
_install_gym_environment(workspace / competition_id)
|
|
1186
|
+
|
|
1102
1187
|
click.echo(
|
|
1103
1188
|
f"\nDataset downloaded to: {dest_path}\n"
|
|
1104
1189
|
f"\nNext step: train your model and submit predictions with:\n"
|
|
@@ -236,8 +236,12 @@ def add_commit_push(problem_dir: str, branch: str, key_path: Path,
|
|
|
236
236
|
"""
|
|
237
237
|
pdir = Path(problem_dir)
|
|
238
238
|
|
|
239
|
-
# Stage all changes except
|
|
240
|
-
result = run_git_command([
|
|
239
|
+
# Stage all changes except dotfiles/dotdirs and markdown files
|
|
240
|
+
result = run_git_command([
|
|
241
|
+
"git", "add", "-A", "--", ".",
|
|
242
|
+
":(exclude).*",
|
|
243
|
+
":(exclude)*.md",
|
|
244
|
+
], str(pdir))
|
|
241
245
|
if result.returncode != 0:
|
|
242
246
|
return False, f"Git add failed:\n{result.stderr}", ""
|
|
243
247
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aicodinggym_cli-0.4.0 → aicodinggym_cli-0.5.1}/aicodinggym_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|