benchmax 0.1.2.dev19__tar.gz → 0.1.2.dev21__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.
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/PKG-INFO +1 -1
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/pyproject.toml +1 -1
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/bundle/bundler.py +43 -2
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/bundle/loader.py +14 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/bundle/payload.py +29 -1
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/bundle/validator.py +20 -6
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax.egg-info/PKG-INFO +1 -1
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/LICENSE +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/README.md +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/setup.cfg +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/adapters/__init__.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/adapters/benchmax_wrapper.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/adapters/skyrl/benchmax_data_process.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/adapters/skyrl/skyrl_adapter.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/bundle/__init__.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/bundle/errors.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/__init__.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/base_env.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/crm/crm_env.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/crm/workdir/reward_fn.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/crm/workdir/salesforce_mcp.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/excel/data_utils.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/excel/excel_env.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/excel/workdir/__init__.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/excel/workdir/excel_code_runner_mcp.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/excel/workdir/excel_utils.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/excel/workdir/reward_fn.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/math/math_env.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/math/workdir/reward_fn.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/__init__.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/example_workdir/demo_mcp_server.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/example_workdir/reward_fn.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/parallel_mcp_env.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/provisioners/__init__.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/provisioners/base_provisioner.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/provisioners/local_provisioner.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/provisioners/manual_provisioner.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/provisioners/skypilot_provisioner.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/provisioners/utils.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/proxy_server.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/server_pool.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/utils.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/tracking.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/types.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/wikipedia/utils.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/wikipedia/wiki_env.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/prompts/__init__.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/prompts/tools.py +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax.egg-info/SOURCES.txt +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax.egg-info/dependency_links.txt +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax.egg-info/requires.txt +0 -0
- {benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax.egg-info/top_level.txt +0 -0
|
@@ -70,9 +70,18 @@ def bundle_env(
|
|
|
70
70
|
f"{mod.__name__}"
|
|
71
71
|
)
|
|
72
72
|
|
|
73
|
-
# --- Serialize the class ---
|
|
73
|
+
# --- Serialize the class AND constructor_args while modules are registered ---
|
|
74
|
+
pickled_constructor_args: bytes | None = None
|
|
74
75
|
try:
|
|
75
76
|
pickled_class = cloudpickle.dumps(env_class)
|
|
77
|
+
# Pickle constructor_args now (while local_modules are registered)
|
|
78
|
+
# so non-JSON-serializable objects get pickled by value.
|
|
79
|
+
if constructor_args is not None:
|
|
80
|
+
try:
|
|
81
|
+
import json
|
|
82
|
+
json.dumps(constructor_args)
|
|
83
|
+
except TypeError:
|
|
84
|
+
pickled_constructor_args = cloudpickle.dumps(constructor_args)
|
|
76
85
|
except Exception as e:
|
|
77
86
|
raise BundlingError(
|
|
78
87
|
f"Failed to serialize {env_class.__name__} with cloudpickle: {e}"
|
|
@@ -99,8 +108,13 @@ def bundle_env(
|
|
|
99
108
|
python_version=python_version,
|
|
100
109
|
benchmax_version=benchmax_version,
|
|
101
110
|
constructor_args=constructor_args,
|
|
111
|
+
constructor_args_pickled=pickled_constructor_args is not None,
|
|
112
|
+
)
|
|
113
|
+
payload = BundledEnv(
|
|
114
|
+
pickled_class=pickled_class,
|
|
115
|
+
metadata=metadata,
|
|
116
|
+
pickled_constructor_args=pickled_constructor_args,
|
|
102
117
|
)
|
|
103
|
-
payload = BundledEnv(pickled_class=pickled_class, metadata=metadata)
|
|
104
118
|
|
|
105
119
|
size_kb = len(pickled_class) / 1024
|
|
106
120
|
logger.info(
|
|
@@ -136,10 +150,37 @@ def write_bundle_files(
|
|
|
136
150
|
pickle_path.write_bytes(bundle.pickled_class)
|
|
137
151
|
metadata_path.write_bytes(bundle.metadata.to_json_bytes())
|
|
138
152
|
|
|
153
|
+
# Write pre-pickled constructor_args (pickled during bundling while
|
|
154
|
+
# local_modules were registered, so module code is inline).
|
|
155
|
+
if bundle.pickled_constructor_args is not None:
|
|
156
|
+
args_path = pickle_path.with_suffix(".args.pkl")
|
|
157
|
+
args_path.write_bytes(bundle.pickled_constructor_args)
|
|
158
|
+
logger.info("[bundling] Wrote pickled constructor_args to %s", args_path)
|
|
159
|
+
|
|
139
160
|
|
|
140
161
|
def read_bundle_files(pickle_path: Path, metadata_path: Path) -> BundledEnv:
|
|
141
162
|
pickle_path = Path(pickle_path)
|
|
142
163
|
metadata_path = Path(metadata_path)
|
|
143
164
|
pickled_class = pickle_path.read_bytes()
|
|
144
165
|
metadata = BundleMetadata.from_json_bytes(metadata_path.read_bytes())
|
|
166
|
+
|
|
167
|
+
# Load pickled constructor_args if they were serialized separately.
|
|
168
|
+
if metadata.constructor_args_pickled:
|
|
169
|
+
args_pickle_path = pickle_path.with_suffix(".args.pkl")
|
|
170
|
+
if args_pickle_path.exists():
|
|
171
|
+
constructor_args = cloudpickle.loads(args_pickle_path.read_bytes())
|
|
172
|
+
metadata = BundleMetadata(
|
|
173
|
+
pip_dependencies=metadata.pip_dependencies,
|
|
174
|
+
python_version=metadata.python_version,
|
|
175
|
+
benchmax_version=metadata.benchmax_version,
|
|
176
|
+
constructor_args=constructor_args,
|
|
177
|
+
format_version=metadata.format_version,
|
|
178
|
+
)
|
|
179
|
+
logger.info("[bundling] Loaded pickled constructor_args from %s", args_pickle_path)
|
|
180
|
+
else:
|
|
181
|
+
logger.warning(
|
|
182
|
+
"[bundling] Metadata indicates pickled constructor_args but %s not found",
|
|
183
|
+
args_pickle_path,
|
|
184
|
+
)
|
|
185
|
+
|
|
145
186
|
return BundledEnv(pickled_class=pickled_class, metadata=metadata)
|
|
@@ -150,6 +150,20 @@ def load_env_from_files(
|
|
|
150
150
|
metadata_path = Path(metadata_path)
|
|
151
151
|
pickled_class = pickle_path.read_bytes()
|
|
152
152
|
metadata = BundleMetadata.from_json_bytes(metadata_path.read_bytes())
|
|
153
|
+
|
|
154
|
+
# If constructor_args were pickled separately, load them.
|
|
155
|
+
if constructor_args is None and metadata.constructor_args_pickled:
|
|
156
|
+
args_pickle_path = pickle_path.with_suffix(".args.pkl")
|
|
157
|
+
if args_pickle_path.exists():
|
|
158
|
+
import cloudpickle
|
|
159
|
+
constructor_args = cloudpickle.loads(args_pickle_path.read_bytes())
|
|
160
|
+
logger.info("[bundling] Loaded pickled constructor_args from %s", args_pickle_path)
|
|
161
|
+
else:
|
|
162
|
+
logger.warning(
|
|
163
|
+
"[bundling] Metadata indicates pickled constructor_args but %s not found",
|
|
164
|
+
args_pickle_path,
|
|
165
|
+
)
|
|
166
|
+
|
|
153
167
|
return load_env(
|
|
154
168
|
pickled_class,
|
|
155
169
|
metadata,
|
|
@@ -13,6 +13,7 @@ class BundleMetadata:
|
|
|
13
13
|
python_version: str
|
|
14
14
|
benchmax_version: str
|
|
15
15
|
constructor_args: Optional[Dict[str, Any]] = None
|
|
16
|
+
constructor_args_pickled: bool = False
|
|
16
17
|
format_version: int = FORMAT_VERSION
|
|
17
18
|
|
|
18
19
|
def to_dict(self) -> Dict[str, Any]:
|
|
@@ -21,11 +22,36 @@ class BundleMetadata:
|
|
|
21
22
|
"python_version": self.python_version,
|
|
22
23
|
"benchmax_version": self.benchmax_version,
|
|
23
24
|
"constructor_args": self.constructor_args,
|
|
25
|
+
"constructor_args_pickled": self.constructor_args_pickled,
|
|
24
26
|
"format_version": self.format_version,
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
def to_json_bytes(self) -> bytes:
|
|
28
|
-
|
|
30
|
+
data = self.to_dict()
|
|
31
|
+
# constructor_args may contain non-JSON-serializable objects
|
|
32
|
+
# (e.g. SearchClient instances). Null them out and set the flag
|
|
33
|
+
# so the loader knows to look for the separate pickled args file.
|
|
34
|
+
if self.has_pickled_constructor_args():
|
|
35
|
+
data["constructor_args"] = None
|
|
36
|
+
data["constructor_args_pickled"] = True
|
|
37
|
+
return json.dumps(data).encode("utf-8")
|
|
38
|
+
|
|
39
|
+
def has_pickled_constructor_args(self) -> bool:
|
|
40
|
+
"""True if constructor_args need separate pickle serialization."""
|
|
41
|
+
if self.constructor_args is None:
|
|
42
|
+
return False
|
|
43
|
+
try:
|
|
44
|
+
json.dumps(self.constructor_args)
|
|
45
|
+
return False
|
|
46
|
+
except TypeError:
|
|
47
|
+
return True
|
|
48
|
+
|
|
49
|
+
def pickled_constructor_args_bytes(self) -> bytes | None:
|
|
50
|
+
"""Pickle constructor_args if they aren't JSON-serializable."""
|
|
51
|
+
if not self.has_pickled_constructor_args():
|
|
52
|
+
return None
|
|
53
|
+
import cloudpickle
|
|
54
|
+
return cloudpickle.dumps(self.constructor_args)
|
|
29
55
|
|
|
30
56
|
@classmethod
|
|
31
57
|
def from_dict(cls, data: Dict[str, Any]) -> "BundleMetadata":
|
|
@@ -34,6 +60,7 @@ class BundleMetadata:
|
|
|
34
60
|
python_version=data.get("python_version", "unknown"),
|
|
35
61
|
benchmax_version=data.get("benchmax_version", "unknown"),
|
|
36
62
|
constructor_args=data.get("constructor_args"),
|
|
63
|
+
constructor_args_pickled=bool(data.get("constructor_args_pickled", False)),
|
|
37
64
|
format_version=int(data.get("format_version", FORMAT_VERSION)),
|
|
38
65
|
)
|
|
39
66
|
|
|
@@ -48,3 +75,4 @@ class BundledEnv:
|
|
|
48
75
|
|
|
49
76
|
pickled_class: bytes
|
|
50
77
|
metadata: BundleMetadata
|
|
78
|
+
pickled_constructor_args: Optional[bytes] = None
|
|
@@ -35,7 +35,8 @@ def validate_bundle(
|
|
|
35
35
|
if constructor_args is None:
|
|
36
36
|
constructor_args = bundle.metadata.constructor_args
|
|
37
37
|
return _run_isolated_validation(
|
|
38
|
-
bundle.pickled_class, bundle.metadata, constructor_args
|
|
38
|
+
bundle.pickled_class, bundle.metadata, constructor_args,
|
|
39
|
+
pickled_constructor_args=bundle.pickled_constructor_args,
|
|
39
40
|
)
|
|
40
41
|
|
|
41
42
|
|
|
@@ -110,6 +111,7 @@ def _run_isolated_validation(
|
|
|
110
111
|
pickled_class: bytes,
|
|
111
112
|
metadata: BundleMetadata,
|
|
112
113
|
constructor_args: Optional[Dict[str, Any]],
|
|
114
|
+
pickled_constructor_args: Optional[bytes] = None,
|
|
113
115
|
) -> List[str]:
|
|
114
116
|
"""Create a temp venv, install deps, unpickle the bundle, and smoke test.
|
|
115
117
|
|
|
@@ -192,18 +194,30 @@ def _run_isolated_validation(
|
|
|
192
194
|
with open(pickle_path, "wb") as f:
|
|
193
195
|
f.write(pickled_class)
|
|
194
196
|
|
|
195
|
-
# 5. Write
|
|
196
|
-
|
|
197
|
+
# 5. Write constructor args as pickle (handles non-JSON-serializable objects)
|
|
198
|
+
args_pickle_path = os.path.join(venv_dir, "constructor_args.pkl")
|
|
199
|
+
if pickled_constructor_args is not None:
|
|
200
|
+
# Use pre-pickled args (pickled during bundling with modules registered)
|
|
201
|
+
with open(args_pickle_path, "wb") as f:
|
|
202
|
+
f.write(pickled_constructor_args)
|
|
203
|
+
elif constructor_args is not None:
|
|
204
|
+
import cloudpickle as _cp
|
|
205
|
+
with open(args_pickle_path, "wb") as f:
|
|
206
|
+
_cp.dump(constructor_args, f)
|
|
207
|
+
|
|
208
|
+
# 6. Write and run smoke test script using cloudpickle directly
|
|
197
209
|
smoke_script = textwrap.dedent(f"""\
|
|
198
|
-
import
|
|
210
|
+
import os
|
|
199
211
|
import asyncio
|
|
200
212
|
import cloudpickle
|
|
201
213
|
|
|
202
214
|
with open({pickle_path!r}, "rb") as f:
|
|
203
215
|
env_class = cloudpickle.load(f)
|
|
204
216
|
|
|
205
|
-
|
|
206
|
-
if
|
|
217
|
+
args_path = {args_pickle_path!r}
|
|
218
|
+
if os.path.exists(args_path):
|
|
219
|
+
with open(args_path, "rb") as f:
|
|
220
|
+
constructor_args = cloudpickle.load(f)
|
|
207
221
|
instance = env_class(**constructor_args)
|
|
208
222
|
tools = asyncio.run(instance.list_tools())
|
|
209
223
|
asyncio.run(instance.shutdown())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/adapters/skyrl/benchmax_data_process.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/crm/workdir/salesforce_mcp.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/excel/workdir/excel_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/example_workdir/reward_fn.py
RENAMED
|
File without changes
|
|
File without changes
|
{benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/provisioners/__init__.py
RENAMED
|
File without changes
|
{benchmax-0.1.2.dev19 → benchmax-0.1.2.dev21}/src/benchmax/envs/mcp/provisioners/base_provisioner.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|