rnow 0.2.4__py3-none-any.whl
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.
- rnow/__init__.py +5 -0
- rnow/__main__.py +7 -0
- rnow/cli/__init__.py +6 -0
- rnow/cli/auth.py +67 -0
- rnow/cli/blob.py +98 -0
- rnow/cli/commands.py +2311 -0
- rnow/cli/common.py +28 -0
- rnow/cli/cube.py +255 -0
- rnow/cli/main.py +49 -0
- rnow/cli/test.py +728 -0
- rnow/cli/token_count.py +295 -0
- rnow/core/__init__.py +33 -0
- rnow/core/reward.py +333 -0
- rnow/core/tool.py +494 -0
- rnow/models.py +295 -0
- rnow/templates/deepseek-aha/config.yml +26 -0
- rnow/templates/deepseek-aha/rewards.py +36 -0
- rnow/templates/deepseek-aha/train.jsonl +1000 -0
- rnow/templates/mcp-tavily/config.yml +29 -0
- rnow/templates/mcp-tavily/requirements.txt +1 -0
- rnow/templates/mcp-tavily/rewards.py +25 -0
- rnow/templates/mcp-tavily/train.jsonl +500 -0
- rnow/templates/new/config.yml +26 -0
- rnow/templates/new/requirements.txt +1 -0
- rnow/templates/new/rewards.py +0 -0
- rnow/templates/new/train.jsonl +0 -0
- rnow/templates/rl-nextjs/config.yml +27 -0
- rnow/templates/rl-nextjs/requirements.txt +2 -0
- rnow/templates/rl-nextjs/rewards.py +446 -0
- rnow/templates/rl-nextjs/train.jsonl +1000 -0
- rnow/templates/rl-single/config.yml +27 -0
- rnow/templates/rl-single/requirements.txt +1 -0
- rnow/templates/rl-single/rewards.py +14 -0
- rnow/templates/rl-single/train.jsonl +1000 -0
- rnow/templates/rl-tools/config.yml +27 -0
- rnow/templates/rl-tools/env.py +38 -0
- rnow/templates/rl-tools/requirements.txt +3 -0
- rnow/templates/rl-tools/rewards.py +25 -0
- rnow/templates/rl-tools/train.jsonl +500 -0
- rnow/templates/sft/config.yml +20 -0
- rnow/templates/sft/train.jsonl +100 -0
- rnow/templates/tutorial-reward/config.yml +27 -0
- rnow/templates/tutorial-reward/requirements.txt +1 -0
- rnow/templates/tutorial-reward/rewards.py +15 -0
- rnow/templates/tutorial-reward/train.jsonl +1000 -0
- rnow/templates/tutorial-tool/config.yml +27 -0
- rnow/templates/tutorial-tool/env.py +7 -0
- rnow/templates/tutorial-tool/requirements.txt +3 -0
- rnow/templates/tutorial-tool/rewards.py +7 -0
- rnow/templates/tutorial-tool/train.jsonl +1266 -0
- rnow-0.2.4.dist-info/METADATA +135 -0
- rnow-0.2.4.dist-info/RECORD +56 -0
- rnow-0.2.4.dist-info/WHEEL +5 -0
- rnow-0.2.4.dist-info/entry_points.txt +2 -0
- rnow-0.2.4.dist-info/licenses/LICENSE +21 -0
- rnow-0.2.4.dist-info/top_level.txt +1 -0
rnow/__init__.py
ADDED
rnow/__main__.py
ADDED
rnow/cli/__init__.py
ADDED
rnow/cli/auth.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# reinforcenow/cli/auth.py
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
# Simple home directory paths
|
|
9
|
+
DATA_DIR = Path.home() / ".reinforcenow"
|
|
10
|
+
CREDS_FILE = DATA_DIR / "credentials.json"
|
|
11
|
+
CONFIG_FILE = DATA_DIR / "config.json"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def is_authenticated() -> bool:
|
|
15
|
+
"""Check if authenticated."""
|
|
16
|
+
try:
|
|
17
|
+
with open(CREDS_FILE) as f:
|
|
18
|
+
return "api_key" in json.load(f)
|
|
19
|
+
except (FileNotFoundError, json.JSONDecodeError, KeyError):
|
|
20
|
+
return False
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_auth_headers() -> dict[str, str]:
|
|
24
|
+
"""Get auth headers."""
|
|
25
|
+
try:
|
|
26
|
+
with open(CREDS_FILE) as f:
|
|
27
|
+
creds = json.load(f)
|
|
28
|
+
return {
|
|
29
|
+
"Content-Type": "application/json",
|
|
30
|
+
"Authorization": f"Bearer {creds['api_key']}",
|
|
31
|
+
}
|
|
32
|
+
except (FileNotFoundError, json.JSONDecodeError, KeyError):
|
|
33
|
+
raise click.ClickException("Not authenticated. Run 'reinforcenow login'")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_active_org_from_config() -> str | None:
|
|
37
|
+
"""Get active organization."""
|
|
38
|
+
try:
|
|
39
|
+
with open(CONFIG_FILE) as f:
|
|
40
|
+
return json.load(f).get("active_organization_id")
|
|
41
|
+
except (FileNotFoundError, json.JSONDecodeError):
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def set_active_organization(org_id: str) -> None:
|
|
46
|
+
"""Set active organization."""
|
|
47
|
+
DATA_DIR.mkdir(parents=True, exist_ok=True)
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
with open(CONFIG_FILE) as f:
|
|
51
|
+
config = json.load(f)
|
|
52
|
+
except (FileNotFoundError, json.JSONDecodeError):
|
|
53
|
+
config = {}
|
|
54
|
+
|
|
55
|
+
config["active_organization_id"] = org_id
|
|
56
|
+
|
|
57
|
+
with open(CONFIG_FILE, "w") as f:
|
|
58
|
+
json.dump(config, f, indent=2)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def logout() -> None:
|
|
62
|
+
"""Remove credentials."""
|
|
63
|
+
if CREDS_FILE.exists():
|
|
64
|
+
CREDS_FILE.unlink()
|
|
65
|
+
click.echo("✓ Logged out")
|
|
66
|
+
else:
|
|
67
|
+
click.echo("Not logged in")
|
rnow/cli/blob.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# reinforcenow/cli/blob.py
|
|
2
|
+
"""Vercel Blob upload support for large files."""
|
|
3
|
+
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import requests
|
|
7
|
+
|
|
8
|
+
from rnow.cli import auth
|
|
9
|
+
|
|
10
|
+
# Size threshold for blob uploads (4MB to stay under 4.5MB limit)
|
|
11
|
+
MAX_INLINE_BYTES = 4 * 1024 * 1024
|
|
12
|
+
|
|
13
|
+
BLOB_API_URL = "https://blob.vercel-storage.com"
|
|
14
|
+
BLOB_API_VERSION = "7"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def request_blob_client_token(base_url: str, pathname: str) -> str:
|
|
18
|
+
"""
|
|
19
|
+
Request a client upload token from the backend.
|
|
20
|
+
This token allows direct upload to Vercel Blob.
|
|
21
|
+
"""
|
|
22
|
+
headers = auth.get_auth_headers()
|
|
23
|
+
headers["Content-Type"] = "application/json"
|
|
24
|
+
|
|
25
|
+
payload = {
|
|
26
|
+
"type": "blob.generate-client-token",
|
|
27
|
+
"payload": {
|
|
28
|
+
"pathname": pathname,
|
|
29
|
+
"callbackUrl": f"{base_url}/dataset/upload",
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
resp = requests.post(
|
|
34
|
+
f"{base_url}/dataset/upload",
|
|
35
|
+
headers=headers,
|
|
36
|
+
json=payload,
|
|
37
|
+
timeout=30,
|
|
38
|
+
)
|
|
39
|
+
resp.raise_for_status()
|
|
40
|
+
data = resp.json()
|
|
41
|
+
|
|
42
|
+
if data.get("type") != "blob.generate-client-token":
|
|
43
|
+
raise RuntimeError(f"Unexpected response from blob token endpoint: {data}")
|
|
44
|
+
|
|
45
|
+
client_token = data.get("clientToken")
|
|
46
|
+
if not client_token:
|
|
47
|
+
raise RuntimeError("No clientToken returned from blob token endpoint")
|
|
48
|
+
|
|
49
|
+
return client_token
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def upload_file_to_blob(base_url: str, local_path: Path, blob_pathname: str) -> dict:
|
|
53
|
+
"""
|
|
54
|
+
Upload a file directly to Vercel Blob using a client token.
|
|
55
|
+
Returns the blob JSON (contains url, pathname, etc).
|
|
56
|
+
"""
|
|
57
|
+
client_token = request_blob_client_token(base_url, blob_pathname)
|
|
58
|
+
|
|
59
|
+
url = f"{BLOB_API_URL}/{blob_pathname.lstrip('/')}"
|
|
60
|
+
headers = {
|
|
61
|
+
"Authorization": f"Bearer {client_token}",
|
|
62
|
+
"x-api-version": BLOB_API_VERSION,
|
|
63
|
+
"x-content-type": "application/jsonl",
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
with open(local_path, "rb") as f:
|
|
67
|
+
resp = requests.put(url, headers=headers, data=f, timeout=300)
|
|
68
|
+
|
|
69
|
+
resp.raise_for_status()
|
|
70
|
+
return resp.json()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def maybe_upload_to_blob(
|
|
74
|
+
base_url: str,
|
|
75
|
+
file_path: Path,
|
|
76
|
+
dataset_id: str,
|
|
77
|
+
) -> tuple[str | None, dict | None]:
|
|
78
|
+
"""
|
|
79
|
+
Check if file needs blob upload and handle it.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
(inline_contents, blob_info)
|
|
83
|
+
- If small: inline_contents is file content, blob_info is None
|
|
84
|
+
- If large: inline_contents is None, blob_info has url/pathname
|
|
85
|
+
"""
|
|
86
|
+
size = file_path.stat().st_size
|
|
87
|
+
|
|
88
|
+
if size <= MAX_INLINE_BYTES:
|
|
89
|
+
# Small file - return contents for inline upload
|
|
90
|
+
return None, None
|
|
91
|
+
|
|
92
|
+
# Large file - upload to blob
|
|
93
|
+
import uuid
|
|
94
|
+
|
|
95
|
+
blob_pathname = f"datasets/{dataset_id}/{uuid.uuid4().hex[:8]}-{file_path.name}"
|
|
96
|
+
|
|
97
|
+
blob = upload_file_to_blob(base_url, file_path, blob_pathname)
|
|
98
|
+
return None, blob
|