wafer-cli 0.2.18__tar.gz → 0.2.20__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.18 → wafer_cli-0.2.20}/PKG-INFO +1 -1
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/pyproject.toml +1 -1
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_cli_coverage.py +14 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_wevin_cli.py +86 -7
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/cli.py +15 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/wevin_cli.py +6 -1
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer_cli.egg-info/PKG-INFO +1 -1
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/README.md +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/setup.cfg +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_analytics.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_auth.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_billing.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_cli_parity_integration.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_config_integration.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_file_operations_integration.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_kernel_scope_cli.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_nsys_analyze.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_nsys_profile.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_output.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_rocprof_compute_integration.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_skill_commands.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_ssh_integration.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_targets_ops.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/tests/test_workflow_integration.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/GUIDE.md +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/__init__.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/analytics.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/api_client.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/auth.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/autotuner.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/billing.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/config.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/corpus.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/evaluate.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/global_config.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/gpu_run.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/inference.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/kernel_scope.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/ncu_analyze.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/nsys_analyze.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/nsys_profile.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/output.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/problems.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/rocprof_compute.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/rocprof_sdk.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/rocprof_systems.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/skills/wafer-guide/SKILL.md +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/ssh_keys.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/target_lock.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/targets.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/targets_ops.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/templates/__init__.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/templates/ask_docs.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/templates/optimize_kernel.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/templates/optimize_kernelbench.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/templates/trace_analyze.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/tracelens.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer/workspaces.py +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer_cli.egg-info/SOURCES.txt +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer_cli.egg-info/dependency_links.txt +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer_cli.egg-info/entry_points.txt +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer_cli.egg-info/requires.txt +0 -0
- {wafer_cli-0.2.18 → wafer_cli-0.2.20}/wafer_cli.egg-info/top_level.txt +0 -0
|
@@ -719,3 +719,17 @@ class TestWorkspacesExecFlagPassthrough:
|
|
|
719
719
|
"workspaces", "exec", "test-ws", "--", "cmd", "--output=/tmp/out"
|
|
720
720
|
])
|
|
721
721
|
assert "no such option" not in result.output.lower()
|
|
722
|
+
|
|
723
|
+
|
|
724
|
+
class TestAgentNoSandboxOption:
|
|
725
|
+
"""Test --no-sandbox option in wafer agent command."""
|
|
726
|
+
|
|
727
|
+
def test_agent_no_sandbox_option_exists(self) -> None:
|
|
728
|
+
"""Test that --no-sandbox option is accepted by wafer agent command."""
|
|
729
|
+
result = runner.invoke(app, ["agent", "--help"])
|
|
730
|
+
assert result.exit_code == 0
|
|
731
|
+
# Strip ANSI escape codes before checking (help output may contain color codes)
|
|
732
|
+
ansi_escape = re.compile(r'\x1b\[[0-9;]*m')
|
|
733
|
+
clean_output = ansi_escape.sub('', result.stdout)
|
|
734
|
+
assert "--no-sandbox" in clean_output
|
|
735
|
+
assert "liability" in clean_output.lower() # Warning text should be in help
|
|
@@ -634,35 +634,114 @@ def test_streaming_frontend_session_start_state_without_session_id():
|
|
|
634
634
|
|
|
635
635
|
def test_streaming_frontend_session_start_resumed_then_new():
|
|
636
636
|
"""Test session_start emission when resuming but states have different session_id.
|
|
637
|
-
|
|
637
|
+
|
|
638
638
|
Edge case: --resume used but states return different session_id (should use states one).
|
|
639
639
|
"""
|
|
640
640
|
import trio
|
|
641
641
|
|
|
642
642
|
from wafer.wevin_cli import StreamingChunkFrontend
|
|
643
|
-
|
|
643
|
+
|
|
644
644
|
async def run_test() -> None:
|
|
645
645
|
# Start with resumed session_id
|
|
646
646
|
frontend = StreamingChunkFrontend(
|
|
647
647
|
session_id="resumed-session-123",
|
|
648
648
|
model="claude-sonnet-4.5"
|
|
649
649
|
)
|
|
650
|
-
|
|
650
|
+
|
|
651
651
|
emitted_events = []
|
|
652
652
|
|
|
653
653
|
def mock_emit(obj) -> None:
|
|
654
654
|
emitted_events.append(obj)
|
|
655
|
-
|
|
655
|
+
|
|
656
656
|
frontend._emit = mock_emit
|
|
657
|
-
|
|
657
|
+
|
|
658
658
|
# start() emits session_start for resumed session
|
|
659
659
|
await frontend.start()
|
|
660
660
|
assert len(emitted_events) == 1
|
|
661
661
|
assert emitted_events[0]["session_id"] == "resumed-session-123"
|
|
662
|
-
|
|
662
|
+
|
|
663
663
|
# If states have different session_id (shouldn't happen, but handle gracefully)
|
|
664
664
|
# The logic in main() checks `if first_session_id and not session_id`
|
|
665
665
|
# So if session_id was set, it won't emit again
|
|
666
666
|
# This is correct behavior - use the one from --resume
|
|
667
|
-
|
|
667
|
+
|
|
668
668
|
trio.run(run_test)
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
# =============================================================================
|
|
672
|
+
# --no-sandbox flag tests
|
|
673
|
+
# =============================================================================
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def test_no_sandbox_parameter_accepted():
|
|
677
|
+
"""Test that no_sandbox parameter exists in wevin_main signature."""
|
|
678
|
+
import inspect
|
|
679
|
+
|
|
680
|
+
from wafer.wevin_cli import main as wevin_main
|
|
681
|
+
|
|
682
|
+
sig = inspect.signature(wevin_main)
|
|
683
|
+
params = sig.parameters
|
|
684
|
+
|
|
685
|
+
# Verify parameter exists
|
|
686
|
+
assert 'no_sandbox' in params
|
|
687
|
+
|
|
688
|
+
# Verify type and default
|
|
689
|
+
assert str(params['no_sandbox'].annotation) in ('bool', "<class 'bool'>")
|
|
690
|
+
assert params['no_sandbox'].default is False
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
def test_build_environment_accepts_no_sandbox():
|
|
694
|
+
"""Test that _build_environment accepts no_sandbox parameter."""
|
|
695
|
+
import inspect
|
|
696
|
+
|
|
697
|
+
from wafer.wevin_cli import _build_environment
|
|
698
|
+
|
|
699
|
+
sig = inspect.signature(_build_environment)
|
|
700
|
+
params = sig.parameters
|
|
701
|
+
|
|
702
|
+
assert 'no_sandbox' in params
|
|
703
|
+
assert params['no_sandbox'].default is False
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
def test_build_environment_with_no_sandbox_false():
|
|
707
|
+
"""Test _build_environment creates env with sandbox ENABLED when no_sandbox=False."""
|
|
708
|
+
from wafer_core.rollouts.templates import TemplateConfig
|
|
709
|
+
from wafer_core.sandbox import SandboxMode
|
|
710
|
+
|
|
711
|
+
from wafer.wevin_cli import _build_environment
|
|
712
|
+
|
|
713
|
+
tpl = TemplateConfig(
|
|
714
|
+
name="test",
|
|
715
|
+
description="Test template",
|
|
716
|
+
system_prompt="Test",
|
|
717
|
+
tools=["read"],
|
|
718
|
+
)
|
|
719
|
+
|
|
720
|
+
# This will raise RuntimeError if sandbox is unavailable on this system
|
|
721
|
+
# That's expected - we're testing that sandbox is ENABLED by default
|
|
722
|
+
try:
|
|
723
|
+
env = _build_environment(tpl, None, None, no_sandbox=False)
|
|
724
|
+
# If we get here, sandbox is available - verify it's enabled
|
|
725
|
+
assert env.sandbox_mode == SandboxMode.ENABLED
|
|
726
|
+
except RuntimeError as e:
|
|
727
|
+
# Sandbox unavailable - that's OK, the error proves ENABLED is set
|
|
728
|
+
assert "sandboxing is not available" in str(e)
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
def test_build_environment_with_no_sandbox_true():
|
|
732
|
+
"""Test _build_environment creates env with sandbox DISABLED when no_sandbox=True."""
|
|
733
|
+
from wafer_core.rollouts.templates import TemplateConfig
|
|
734
|
+
from wafer_core.sandbox import SandboxMode
|
|
735
|
+
|
|
736
|
+
from wafer.wevin_cli import _build_environment
|
|
737
|
+
|
|
738
|
+
tpl = TemplateConfig(
|
|
739
|
+
name="test",
|
|
740
|
+
description="Test template",
|
|
741
|
+
system_prompt="Test",
|
|
742
|
+
tools=["read"],
|
|
743
|
+
)
|
|
744
|
+
|
|
745
|
+
# This should NOT raise - sandbox is disabled
|
|
746
|
+
env = _build_environment(tpl, None, None, no_sandbox=True)
|
|
747
|
+
assert env.sandbox_mode == SandboxMode.DISABLED
|
|
@@ -1327,6 +1327,11 @@ def agent( # noqa: PLR0913
|
|
|
1327
1327
|
"-c",
|
|
1328
1328
|
help="Documentation corpus to use (cuda, cutlass, hip, amd). Must be downloaded first.",
|
|
1329
1329
|
),
|
|
1330
|
+
no_sandbox: bool = typer.Option(
|
|
1331
|
+
False,
|
|
1332
|
+
"--no-sandbox",
|
|
1333
|
+
help="Disable OS-level sandboxing (YOU accept liability for any damage caused by the agent)",
|
|
1334
|
+
),
|
|
1330
1335
|
) -> None:
|
|
1331
1336
|
"""AI assistant for GPU kernel development.
|
|
1332
1337
|
|
|
@@ -1408,6 +1413,13 @@ def agent( # noqa: PLR0913
|
|
|
1408
1413
|
raise typer.Exit(1) from None
|
|
1409
1414
|
corpus_path = str(path)
|
|
1410
1415
|
|
|
1416
|
+
# Warn user about sandbox disabled
|
|
1417
|
+
if no_sandbox:
|
|
1418
|
+
print(
|
|
1419
|
+
"Warning: Sandbox disabled. You accept liability for any damage caused by the agent.",
|
|
1420
|
+
file=sys.stderr,
|
|
1421
|
+
)
|
|
1422
|
+
|
|
1411
1423
|
wevin_main(
|
|
1412
1424
|
prompt=actual_prompt,
|
|
1413
1425
|
interactive=use_tui,
|
|
@@ -1425,6 +1437,7 @@ def agent( # noqa: PLR0913
|
|
|
1425
1437
|
template=template,
|
|
1426
1438
|
template_args=parsed_template_args,
|
|
1427
1439
|
corpus_path=corpus_path,
|
|
1440
|
+
no_sandbox=no_sandbox,
|
|
1428
1441
|
)
|
|
1429
1442
|
|
|
1430
1443
|
|
|
@@ -1455,6 +1468,7 @@ def _make_agent_alias(name: str, doc: str) -> None:
|
|
|
1455
1468
|
template: str | None = typer.Option(None, "--template", "-t"),
|
|
1456
1469
|
template_args: list[str] | None = typer.Option(None, "--args"),
|
|
1457
1470
|
corpus: str | None = typer.Option(None, "--corpus"),
|
|
1471
|
+
no_sandbox: bool = typer.Option(False, "--no-sandbox"),
|
|
1458
1472
|
) -> None:
|
|
1459
1473
|
agent(
|
|
1460
1474
|
prompt=prompt,
|
|
@@ -1474,6 +1488,7 @@ def _make_agent_alias(name: str, doc: str) -> None:
|
|
|
1474
1488
|
template=template,
|
|
1475
1489
|
template_args=template_args,
|
|
1476
1490
|
corpus=corpus,
|
|
1491
|
+
no_sandbox=no_sandbox,
|
|
1477
1492
|
)
|
|
1478
1493
|
|
|
1479
1494
|
alias_cmd.__doc__ = doc
|
|
@@ -266,18 +266,22 @@ def _build_environment(
|
|
|
266
266
|
tpl: TemplateConfig,
|
|
267
267
|
tools_override: list[str] | None,
|
|
268
268
|
corpus_path: str | None,
|
|
269
|
+
no_sandbox: bool = False,
|
|
269
270
|
) -> Environment:
|
|
270
271
|
"""Build a CodingEnvironment from template config."""
|
|
271
272
|
from wafer_core.environments.coding import CodingEnvironment
|
|
272
273
|
from wafer_core.rollouts.templates import DANGEROUS_BASH_COMMANDS
|
|
274
|
+
from wafer_core.sandbox import SandboxMode
|
|
273
275
|
|
|
274
276
|
working_dir = Path(corpus_path) if corpus_path else Path.cwd()
|
|
275
277
|
resolved_tools = tools_override or tpl.tools
|
|
278
|
+
sandbox_mode = SandboxMode.DISABLED if no_sandbox else SandboxMode.ENABLED
|
|
276
279
|
env: Environment = CodingEnvironment(
|
|
277
280
|
working_dir=working_dir,
|
|
278
281
|
enabled_tools=resolved_tools,
|
|
279
282
|
bash_allowlist=tpl.bash_allowlist,
|
|
280
283
|
bash_denylist=DANGEROUS_BASH_COMMANDS,
|
|
284
|
+
sandbox_mode=sandbox_mode,
|
|
281
285
|
) # type: ignore[assignment]
|
|
282
286
|
return env
|
|
283
287
|
|
|
@@ -362,6 +366,7 @@ def main( # noqa: PLR0913, PLR0915
|
|
|
362
366
|
list_sessions: bool = False,
|
|
363
367
|
get_session: str | None = None,
|
|
364
368
|
json_output: bool = False,
|
|
369
|
+
no_sandbox: bool = False,
|
|
365
370
|
) -> None:
|
|
366
371
|
"""Run wevin agent in-process via rollouts."""
|
|
367
372
|
from dataclasses import asdict
|
|
@@ -505,7 +510,7 @@ def main( # noqa: PLR0913, PLR0915
|
|
|
505
510
|
|
|
506
511
|
# Build endpoint and environment
|
|
507
512
|
endpoint = _build_endpoint(tpl, model, api_base, api_key)
|
|
508
|
-
environment = _build_environment(tpl, tools, corpus_path)
|
|
513
|
+
environment = _build_environment(tpl, tools, corpus_path, no_sandbox)
|
|
509
514
|
|
|
510
515
|
# Session store
|
|
511
516
|
session_store = FileSessionStore()
|
|
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
|