wafer-cli 0.2.38__tar.gz → 0.2.40__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.
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/PKG-INFO +1 -1
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/pyproject.toml +1 -1
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/agent_defaults.py +48 -1
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/cli.py +84 -27
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/wevin_cli.py +36 -3
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/workspaces.py +8 -2
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer_cli.egg-info/PKG-INFO +1 -1
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/README.md +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/setup.cfg +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_analytics.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_auth.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_billing.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_cli_coverage.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_cli_parity_integration.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_config_integration.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_file_operations_integration.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_kernel_scope_cli.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_nsys_analyze.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_nsys_profile.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_output.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_rocprof_compute_integration.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_skill_commands.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_ssh_integration.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_targets_ops.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_wevin_cli.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/tests/test_workflow_integration.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/GUIDE.md +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/__init__.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/analytics.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/api_client.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/auth.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/autotuner.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/baseline.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/billing.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/cli_instructions.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/config.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/corpus.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/evaluate.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/global_config.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/gpu_run.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/inference.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/kernel_scope.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/ncu_analyze.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/nsys_analyze.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/nsys_profile.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/output.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/problems.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/rocprof_compute.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/rocprof_sdk.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/rocprof_systems.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/skills/wafer-guide/SKILL.md +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/specs_cli.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/ssh_keys.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/target_lock.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/targets.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/targets_cli.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/targets_ops.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/templates/__init__.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/templates/aiter_optimize.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/templates/ask_docs.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/templates/optimize_kernel.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/templates/optimize_kernelbench.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/templates/optimize_vllm.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/templates/trace_analyze.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/tests/test_eval_cli_parity.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/trace_compare.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer/tracelens.py +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer_cli.egg-info/SOURCES.txt +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer_cli.egg-info/dependency_links.txt +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer_cli.egg-info/entry_points.txt +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer_cli.egg-info/requires.txt +0 -0
- {wafer_cli-0.2.38 → wafer_cli-0.2.40}/wafer_cli.egg-info/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Shared agent defaults for kernel
|
|
1
|
+
"""Shared agent defaults for kernel tasks.
|
|
2
2
|
|
|
3
3
|
Single source of truth for bash allowlists and enabled tools used by both:
|
|
4
4
|
- CLI templates (apps/wafer-cli/wafer/templates/*.py)
|
|
@@ -195,3 +195,50 @@ VLLM_BASH_ALLOWLIST: list[str] = [
|
|
|
195
195
|
"cd",
|
|
196
196
|
"git",
|
|
197
197
|
]
|
|
198
|
+
|
|
199
|
+
# Tools available to audit agents (read-only + bash for compilation/profiling)
|
|
200
|
+
AUDIT_ENABLED_TOOLS: list[str] = ["read", "glob", "grep", "bash"]
|
|
201
|
+
|
|
202
|
+
# Bash commands allowed for kernel audit agents.
|
|
203
|
+
AUDIT_BASH_ALLOWLIST: list[str] = [
|
|
204
|
+
# Read-only
|
|
205
|
+
"ls",
|
|
206
|
+
"cat",
|
|
207
|
+
"head",
|
|
208
|
+
"tail",
|
|
209
|
+
"wc",
|
|
210
|
+
"find",
|
|
211
|
+
"grep",
|
|
212
|
+
"rg",
|
|
213
|
+
"pwd",
|
|
214
|
+
"tree",
|
|
215
|
+
"which",
|
|
216
|
+
"diff",
|
|
217
|
+
"sort",
|
|
218
|
+
# Filesystem
|
|
219
|
+
"mkdir",
|
|
220
|
+
# Compilation
|
|
221
|
+
"make",
|
|
222
|
+
"cmake",
|
|
223
|
+
"nvcc",
|
|
224
|
+
"hipcc",
|
|
225
|
+
"g++",
|
|
226
|
+
"gcc",
|
|
227
|
+
"clang",
|
|
228
|
+
"python",
|
|
229
|
+
"python3",
|
|
230
|
+
# Execution — allows running compiled binaries via ./path.
|
|
231
|
+
# Security note: the agent can already compile arbitrary code via hipcc/gcc/etc,
|
|
232
|
+
# so blocking ./ execution doesn't add meaningful protection.
|
|
233
|
+
"./",
|
|
234
|
+
# Profiling
|
|
235
|
+
"wafer evaluate",
|
|
236
|
+
"wafer nvidia ncu",
|
|
237
|
+
"wafer nvidia nsys",
|
|
238
|
+
"wafer amd rocprof-compute",
|
|
239
|
+
"wafer amd rocprof-sdk",
|
|
240
|
+
"wafer amd rocprof-systems",
|
|
241
|
+
"wafer compiler-analyze",
|
|
242
|
+
# Misc
|
|
243
|
+
"timeout",
|
|
244
|
+
]
|
|
@@ -220,16 +220,22 @@ workspaces_app = typer.Typer(
|
|
|
220
220
|
|
|
221
221
|
Workspaces are on-demand cloud GPU environments. Requires authentication (wafer login).
|
|
222
222
|
|
|
223
|
+
Environment Types:
|
|
224
|
+
modal Serverless GPU execution (fast startup, no SSH)
|
|
225
|
+
baremetal Dedicated GPU server (SSH access, hardware counters)
|
|
226
|
+
|
|
223
227
|
Available GPUs:
|
|
224
|
-
MI300X AMD Instinct MI300X (192GB HBM3, ROCm)
|
|
228
|
+
MI300X AMD Instinct MI300X (192GB HBM3, ROCm) - baremetal only
|
|
225
229
|
B200 NVIDIA Blackwell B200 (180GB HBM3e, CUDA)
|
|
230
|
+
H100 NVIDIA Hopper H100 (80GB HBM3, CUDA)
|
|
226
231
|
|
|
227
232
|
Commands:
|
|
228
|
-
wafer workspaces create dev
|
|
229
|
-
wafer workspaces
|
|
230
|
-
wafer workspaces
|
|
231
|
-
wafer workspaces
|
|
232
|
-
wafer workspaces
|
|
233
|
+
wafer workspaces create dev -g B200 -e modal # Create Modal workspace
|
|
234
|
+
wafer workspaces create dev -g B200 -e baremetal # Create baremetal workspace
|
|
235
|
+
wafer workspaces exec dev -- python x.py # Run commands
|
|
236
|
+
wafer workspaces ssh dev # Interactive SSH (baremetal only)
|
|
237
|
+
wafer workspaces sync dev ./project # Sync files
|
|
238
|
+
wafer workspaces delete dev # Clean up"""
|
|
233
239
|
)
|
|
234
240
|
app.add_typer(workspaces_app, name="workspaces")
|
|
235
241
|
|
|
@@ -1862,6 +1868,12 @@ def kernelbench_evaluate( # noqa: PLR0913, PLR0915
|
|
|
1862
1868
|
help="Sync files and generate eval script but don't run. "
|
|
1863
1869
|
"Prints the command to run manually (useful for wrapping with rocprof, etc.)",
|
|
1864
1870
|
),
|
|
1871
|
+
pool_timeout: int = typer.Option(
|
|
1872
|
+
600,
|
|
1873
|
+
"--pool-timeout",
|
|
1874
|
+
help="Seconds to wait for a target from the pool before failing (default: 600). "
|
|
1875
|
+
"Set to 0 for immediate failure if all targets are busy.",
|
|
1876
|
+
),
|
|
1865
1877
|
json_output: bool = typer.Option(
|
|
1866
1878
|
False, "--json", help="Output as single JSON object (machine-readable)"
|
|
1867
1879
|
),
|
|
@@ -1953,14 +1965,24 @@ def kernelbench_evaluate( # noqa: PLR0913, PLR0915
|
|
|
1953
1965
|
collector.finalize()
|
|
1954
1966
|
raise typer.Exit(1) from None
|
|
1955
1967
|
|
|
1956
|
-
|
|
1957
|
-
|
|
1968
|
+
effective_timeout = pool_timeout if pool_timeout > 0 else None
|
|
1969
|
+
collector.emit("pool_acquire", pool=pool, count=len(usable_targets), timeout=pool_timeout)
|
|
1970
|
+
pool_lock_context = acquire_from_pool(usable_targets, timeout=effective_timeout)
|
|
1958
1971
|
acquired_target = pool_lock_context.__enter__()
|
|
1959
1972
|
|
|
1960
1973
|
if acquired_target is None:
|
|
1961
1974
|
# Exit context manager before raising to avoid resource leak
|
|
1962
1975
|
pool_lock_context.__exit__(None, None, None)
|
|
1963
|
-
|
|
1976
|
+
if pool_timeout > 0:
|
|
1977
|
+
collector.set_error(
|
|
1978
|
+
"pool",
|
|
1979
|
+
"AllTargetsBusy",
|
|
1980
|
+
pool=pool,
|
|
1981
|
+
targets=usable_targets,
|
|
1982
|
+
message=f"All targets busy after waiting {pool_timeout}s",
|
|
1983
|
+
)
|
|
1984
|
+
else:
|
|
1985
|
+
collector.set_error("pool", "AllTargetsBusy", pool=pool, targets=usable_targets)
|
|
1964
1986
|
collector.finalize()
|
|
1965
1987
|
raise typer.Exit(1)
|
|
1966
1988
|
|
|
@@ -2315,6 +2337,12 @@ def gpumode_evaluate( # noqa: PLR0913, PLR0915
|
|
|
2315
2337
|
True, "--sync-artifacts/--no-sync-artifacts", help="Download artifacts"
|
|
2316
2338
|
),
|
|
2317
2339
|
gpu_id: int | None = typer.Option(None, "--gpu-id", help="Override GPU ID"),
|
|
2340
|
+
pool_timeout: int = typer.Option(
|
|
2341
|
+
600,
|
|
2342
|
+
"--pool-timeout",
|
|
2343
|
+
help="Seconds to wait for a target from the pool before failing (default: 600). "
|
|
2344
|
+
"Set to 0 for immediate failure if all targets are busy.",
|
|
2345
|
+
),
|
|
2318
2346
|
) -> None:
|
|
2319
2347
|
"""Run kernel evaluation in GPUMode format (functional).
|
|
2320
2348
|
|
|
@@ -2394,14 +2422,21 @@ def gpumode_evaluate( # noqa: PLR0913, PLR0915
|
|
|
2394
2422
|
typer.echo(" Run 'wafer auth status' to see which providers need setup.", err=True)
|
|
2395
2423
|
raise typer.Exit(1) from None
|
|
2396
2424
|
|
|
2425
|
+
effective_timeout = pool_timeout if pool_timeout > 0 else None
|
|
2397
2426
|
typer.echo(f"Acquiring target from pool '{pool}' ({len(usable_targets)} targets)...")
|
|
2398
|
-
pool_lock_context = acquire_from_pool(usable_targets)
|
|
2427
|
+
pool_lock_context = acquire_from_pool(usable_targets, timeout=effective_timeout)
|
|
2399
2428
|
acquired_target = pool_lock_context.__enter__()
|
|
2400
2429
|
|
|
2401
2430
|
if acquired_target is None:
|
|
2402
2431
|
# Exit context manager before raising to avoid resource leak
|
|
2403
2432
|
pool_lock_context.__exit__(None, None, None)
|
|
2404
|
-
|
|
2433
|
+
if pool_timeout > 0:
|
|
2434
|
+
typer.echo(
|
|
2435
|
+
f"Error: All targets in pool '{pool}' are busy (waited {pool_timeout}s)",
|
|
2436
|
+
err=True,
|
|
2437
|
+
)
|
|
2438
|
+
else:
|
|
2439
|
+
typer.echo(f"Error: All targets in pool '{pool}' are busy", err=True)
|
|
2405
2440
|
typer.echo(f" Targets: {', '.join(usable_targets)}", err=True)
|
|
2406
2441
|
raise typer.Exit(1)
|
|
2407
2442
|
|
|
@@ -3243,7 +3278,7 @@ def demo_eval(
|
|
|
3243
3278
|
# Step 1: Create workspace
|
|
3244
3279
|
typer.echo(f"\n[1/4] Creating workspace '{workspace_name}'...")
|
|
3245
3280
|
result = subprocess.run(
|
|
3246
|
-
["wafer", "workspaces", "create", workspace_name, "--gpu", "B200", "--json"],
|
|
3281
|
+
["wafer", "workspaces", "create", workspace_name, "--gpu", "B200", "--environment", "modal", "--json"],
|
|
3247
3282
|
capture_output=True,
|
|
3248
3283
|
text=True,
|
|
3249
3284
|
check=True,
|
|
@@ -3330,7 +3365,7 @@ print(f"Performance: {(t1-t0)/100*1e6:.1f} us/iter")
|
|
|
3330
3365
|
typer.echo("\n✓ Demo complete! To evaluate your own kernels:")
|
|
3331
3366
|
typer.echo("")
|
|
3332
3367
|
typer.echo(" # Using workspaces (no setup required):")
|
|
3333
|
-
typer.echo(" wafer workspaces create dev --gpu B200")
|
|
3368
|
+
typer.echo(" wafer workspaces create dev --gpu B200 --environment modal")
|
|
3334
3369
|
typer.echo(" wafer workspaces exec --sync ./my-kernel dev -- python my_test.py")
|
|
3335
3370
|
typer.echo("")
|
|
3336
3371
|
typer.echo(" # Or using wafer evaluate with a configured target:")
|
|
@@ -4787,7 +4822,10 @@ def workspaces_list(
|
|
|
4787
4822
|
def workspaces_create(
|
|
4788
4823
|
name: str = typer.Argument(..., help="Workspace name"),
|
|
4789
4824
|
gpu_type: str = typer.Option(
|
|
4790
|
-
|
|
4825
|
+
..., "--gpu", "-g", help="GPU type: MI300X (AMD) or B200/H100 (NVIDIA)"
|
|
4826
|
+
),
|
|
4827
|
+
environment: str = typer.Option(
|
|
4828
|
+
..., "--environment", "-e", help="Environment type: modal or baremetal"
|
|
4791
4829
|
),
|
|
4792
4830
|
image: str | None = typer.Option(None, "--image", "-i", help="Docker image (optional)"),
|
|
4793
4831
|
wait: bool = typer.Option(
|
|
@@ -4797,16 +4835,22 @@ def workspaces_create(
|
|
|
4797
4835
|
) -> None:
|
|
4798
4836
|
"""Create a new workspace.
|
|
4799
4837
|
|
|
4838
|
+
Per-vendor architecture: each workspace has a single environment type.
|
|
4839
|
+
|
|
4840
|
+
Environment Types:
|
|
4841
|
+
modal Serverless GPU execution (fast startup, no SSH)
|
|
4842
|
+
baremetal Dedicated GPU server (SSH access, hardware counters)
|
|
4843
|
+
|
|
4800
4844
|
Available GPUs:
|
|
4801
|
-
MI300X
|
|
4802
|
-
B200
|
|
4845
|
+
MI300X AMD Instinct MI300X (192GB HBM3, ROCm) - baremetal only
|
|
4846
|
+
B200 NVIDIA Blackwell B200 (180GB HBM3e, CUDA)
|
|
4847
|
+
H100 NVIDIA Hopper H100 (80GB HBM3, CUDA)
|
|
4803
4848
|
|
|
4804
4849
|
Example:
|
|
4805
|
-
wafer workspaces create my-kernel
|
|
4806
|
-
wafer workspaces create my-kernel --gpu MI300X
|
|
4807
|
-
wafer workspaces create my-kernel
|
|
4808
|
-
wafer workspaces create my-kernel
|
|
4809
|
-
wafer workspaces create my-kernel --wait
|
|
4850
|
+
wafer workspaces create my-kernel --gpu B200 --environment modal
|
|
4851
|
+
wafer workspaces create my-kernel --gpu MI300X --environment baremetal
|
|
4852
|
+
wafer workspaces create my-kernel -g B200 -e baremetal # SSH + ncu profiling
|
|
4853
|
+
wafer workspaces create my-kernel -g B200 -e modal --wait
|
|
4810
4854
|
"""
|
|
4811
4855
|
from .workspaces import create_workspace
|
|
4812
4856
|
|
|
@@ -4814,6 +4858,7 @@ def workspaces_create(
|
|
|
4814
4858
|
result = create_workspace(
|
|
4815
4859
|
name,
|
|
4816
4860
|
gpu_type=gpu_type,
|
|
4861
|
+
environment_type=environment,
|
|
4817
4862
|
image=image,
|
|
4818
4863
|
wait=wait,
|
|
4819
4864
|
json_output=json_output,
|
|
@@ -7751,16 +7796,24 @@ def compare_analyze(
|
|
|
7751
7796
|
"-f",
|
|
7752
7797
|
help="Output format: text, text-layers, csv, csv-layers, json",
|
|
7753
7798
|
),
|
|
7754
|
-
output: Path | None = typer.Option(
|
|
7799
|
+
output: Path | None = typer.Option(
|
|
7800
|
+
None, "--output", "-o", help="Output file (default: stdout)"
|
|
7801
|
+
),
|
|
7755
7802
|
phase: str = typer.Option(
|
|
7756
7803
|
"all",
|
|
7757
7804
|
"--phase",
|
|
7758
7805
|
help="Filter by phase: all, prefill, decode",
|
|
7759
7806
|
),
|
|
7760
7807
|
layers: bool = typer.Option(False, "--layers", help="Show layer-wise performance breakdown"),
|
|
7761
|
-
all: bool = typer.Option(
|
|
7762
|
-
|
|
7763
|
-
|
|
7808
|
+
all: bool = typer.Option(
|
|
7809
|
+
False, "--all", help="Show all items (no truncation for layers, operations, kernels)"
|
|
7810
|
+
),
|
|
7811
|
+
stack_traces: bool = typer.Option(
|
|
7812
|
+
False, "--stack-traces", help="Show Python stack traces for operations"
|
|
7813
|
+
),
|
|
7814
|
+
json: bool = typer.Option(
|
|
7815
|
+
False, "--json", hidden=True, help="Ignored (for compatibility with cliExecutor)"
|
|
7816
|
+
),
|
|
7764
7817
|
) -> None:
|
|
7765
7818
|
"""Compare GPU traces from two platforms platforms.
|
|
7766
7819
|
|
|
@@ -7824,13 +7877,17 @@ def compare_fusion_cmd(
|
|
|
7824
7877
|
"-f",
|
|
7825
7878
|
help="Output format: text, csv, json",
|
|
7826
7879
|
),
|
|
7827
|
-
output: Path | None = typer.Option(
|
|
7880
|
+
output: Path | None = typer.Option(
|
|
7881
|
+
None, "--output", "-o", help="Output file (default: stdout)"
|
|
7882
|
+
),
|
|
7828
7883
|
min_group_size: int = typer.Option(
|
|
7829
7884
|
50,
|
|
7830
7885
|
"--min-group-size",
|
|
7831
7886
|
help="Minimum correlation group size to analyze",
|
|
7832
7887
|
),
|
|
7833
|
-
json: bool = typer.Option(
|
|
7888
|
+
json: bool = typer.Option(
|
|
7889
|
+
False, "--json", hidden=True, help="Ignored (for compatibility with cliExecutor)"
|
|
7890
|
+
),
|
|
7834
7891
|
) -> None:
|
|
7835
7892
|
"""Analyze kernel fusion differences between AMD and NVIDIA traces.
|
|
7836
7893
|
|
|
@@ -326,13 +326,28 @@ def _build_environment(
|
|
|
326
326
|
tools_override: list[str] | None,
|
|
327
327
|
corpus_path: str | None,
|
|
328
328
|
no_sandbox: bool = False,
|
|
329
|
+
has_target: bool = False,
|
|
330
|
+
template_args: dict[str, str] | None = None,
|
|
329
331
|
) -> Environment:
|
|
330
|
-
"""Build a CodingEnvironment from template config.
|
|
332
|
+
"""Build a CodingEnvironment from template config.
|
|
333
|
+
|
|
334
|
+
Working directory priority:
|
|
335
|
+
1. Template arg "dir" (--args dir=./my_project) — scopes agent to a directory
|
|
336
|
+
2. corpus_path (--corpus cuda) — for doc-browsing templates
|
|
337
|
+
3. Current working directory
|
|
338
|
+
"""
|
|
331
339
|
from wafer_core.environments.coding import CodingEnvironment
|
|
332
340
|
from wafer_core.rollouts.templates import DANGEROUS_BASH_COMMANDS
|
|
333
341
|
from wafer_core.sandbox import SandboxMode
|
|
334
342
|
|
|
335
|
-
|
|
343
|
+
# Template arg "dir" takes priority over corpus_path
|
|
344
|
+
dir_arg = (template_args or {}).get("dir")
|
|
345
|
+
if dir_arg:
|
|
346
|
+
working_dir = Path(dir_arg).resolve()
|
|
347
|
+
elif corpus_path:
|
|
348
|
+
working_dir = Path(corpus_path)
|
|
349
|
+
else:
|
|
350
|
+
working_dir = Path.cwd()
|
|
336
351
|
resolved_tools = list(tools_override or tpl.tools)
|
|
337
352
|
|
|
338
353
|
# Add skill tool if skills are enabled
|
|
@@ -340,12 +355,18 @@ def _build_environment(
|
|
|
340
355
|
resolved_tools.append("skill")
|
|
341
356
|
|
|
342
357
|
sandbox_mode = SandboxMode.DISABLED if no_sandbox else SandboxMode.ENABLED
|
|
358
|
+
|
|
359
|
+
# Enable network when a target is configured — the agent needs to reach
|
|
360
|
+
# remote GPUs via SSH/HTTPS. Filesystem sandbox stays enforced.
|
|
361
|
+
allow_network = has_target
|
|
362
|
+
|
|
343
363
|
env: Environment = CodingEnvironment(
|
|
344
364
|
working_dir=working_dir,
|
|
345
365
|
enabled_tools=resolved_tools,
|
|
346
366
|
bash_allowlist=tpl.bash_allowlist,
|
|
347
367
|
bash_denylist=DANGEROUS_BASH_COMMANDS,
|
|
348
368
|
sandbox_mode=sandbox_mode,
|
|
369
|
+
allow_network=allow_network,
|
|
349
370
|
) # type: ignore[assignment]
|
|
350
371
|
return env
|
|
351
372
|
|
|
@@ -589,9 +610,21 @@ def main( # noqa: PLR0913, PLR0915
|
|
|
589
610
|
# CLI args override template values
|
|
590
611
|
resolved_single_turn = single_turn if single_turn is not None else tpl.single_turn
|
|
591
612
|
|
|
613
|
+
# Check if a default target is configured — if so, enable network access
|
|
614
|
+
# so the agent can reach remote GPUs via SSH/HTTPS.
|
|
615
|
+
has_target = False
|
|
616
|
+
try:
|
|
617
|
+
from wafer.targets import get_default_target
|
|
618
|
+
|
|
619
|
+
has_target = get_default_target() is not None
|
|
620
|
+
except Exception:
|
|
621
|
+
pass # No target configured — network stays disabled
|
|
622
|
+
|
|
592
623
|
# Build endpoint and environment
|
|
593
624
|
endpoint = _build_endpoint(tpl, model, api_base, api_key, api_key_refresh)
|
|
594
|
-
environment = _build_environment(
|
|
625
|
+
environment = _build_environment(
|
|
626
|
+
tpl, tools, corpus_path, no_sandbox, has_target=has_target, template_args=template_args
|
|
627
|
+
)
|
|
595
628
|
|
|
596
629
|
# Session store
|
|
597
630
|
session_store = FileSessionStore()
|
|
@@ -249,16 +249,20 @@ def list_workspaces(json_output: bool = False) -> str:
|
|
|
249
249
|
|
|
250
250
|
def create_workspace(
|
|
251
251
|
name: str,
|
|
252
|
-
gpu_type: str
|
|
252
|
+
gpu_type: str,
|
|
253
|
+
environment_type: str,
|
|
253
254
|
image: str | None = None,
|
|
254
255
|
wait: bool = False,
|
|
255
256
|
json_output: bool = False,
|
|
256
257
|
) -> str:
|
|
257
258
|
"""Create a new workspace.
|
|
258
259
|
|
|
260
|
+
Per-vendor architecture: each workspace has a single environment type.
|
|
261
|
+
|
|
259
262
|
Args:
|
|
260
263
|
name: Workspace name (must be unique)
|
|
261
|
-
gpu_type: GPU type (
|
|
264
|
+
gpu_type: GPU type (required: B200, H100, MI300X)
|
|
265
|
+
environment_type: Environment type (required: modal, baremetal)
|
|
262
266
|
image: Docker image (optional, uses default if not specified)
|
|
263
267
|
wait: If True, stream provisioning progress and return SSH credentials
|
|
264
268
|
json_output: If True, return raw JSON; otherwise return formatted text
|
|
@@ -272,6 +276,7 @@ def create_workspace(
|
|
|
272
276
|
# Validate inputs
|
|
273
277
|
assert name, "Workspace name must be non-empty"
|
|
274
278
|
assert gpu_type, "GPU type must be non-empty"
|
|
279
|
+
assert environment_type, "Environment type must be non-empty"
|
|
275
280
|
|
|
276
281
|
api_url, headers = _get_client()
|
|
277
282
|
|
|
@@ -296,6 +301,7 @@ def create_workspace(
|
|
|
296
301
|
request_body: dict = {
|
|
297
302
|
"name": name,
|
|
298
303
|
"gpu_type": gpu_type,
|
|
304
|
+
"environment_type": environment_type,
|
|
299
305
|
}
|
|
300
306
|
if image:
|
|
301
307
|
request_body["image"] = image
|
|
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
|
|
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
|
|
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
|
|
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
|