wafer-cli 0.2.3__py3-none-any.whl → 0.2.5__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.
- wafer/cli.py +862 -104
- wafer/evaluate.py +1423 -158
- wafer/gpu_run.py +5 -1
- wafer/problems.py +357 -0
- wafer/target_lock.py +198 -0
- wafer/targets.py +158 -0
- wafer/wevin_cli.py +22 -2
- {wafer_cli-0.2.3.dist-info → wafer_cli-0.2.5.dist-info}/METADATA +1 -1
- {wafer_cli-0.2.3.dist-info → wafer_cli-0.2.5.dist-info}/RECORD +12 -10
- {wafer_cli-0.2.3.dist-info → wafer_cli-0.2.5.dist-info}/WHEEL +1 -1
- {wafer_cli-0.2.3.dist-info → wafer_cli-0.2.5.dist-info}/entry_points.txt +0 -0
- {wafer_cli-0.2.3.dist-info → wafer_cli-0.2.5.dist-info}/top_level.txt +0 -0
wafer/targets.py
CHANGED
|
@@ -257,6 +257,164 @@ def get_default_target() -> str | None:
|
|
|
257
257
|
return data.get("default_target")
|
|
258
258
|
|
|
259
259
|
|
|
260
|
+
# ── Pool Management ─────────────────────────────────────────────────────────
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def get_pool(name: str) -> list[str]:
|
|
264
|
+
"""Get list of targets in a named pool.
|
|
265
|
+
|
|
266
|
+
Pools are defined in ~/.wafer/config.toml:
|
|
267
|
+
[pools.my-pool]
|
|
268
|
+
targets = ["target-1", "target-2", "target-3"]
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
name: Pool name
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
List of target names in the pool
|
|
275
|
+
|
|
276
|
+
Raises:
|
|
277
|
+
FileNotFoundError: If pool doesn't exist
|
|
278
|
+
"""
|
|
279
|
+
if not CONFIG_FILE.exists():
|
|
280
|
+
raise FileNotFoundError(f"Pool not found: {name} (no config file)")
|
|
281
|
+
|
|
282
|
+
with open(CONFIG_FILE, "rb") as f:
|
|
283
|
+
data = tomllib.load(f)
|
|
284
|
+
|
|
285
|
+
pools = data.get("pools", {})
|
|
286
|
+
if name not in pools:
|
|
287
|
+
raise FileNotFoundError(
|
|
288
|
+
f"Pool not found: {name}\n"
|
|
289
|
+
f" Define pools in ~/.wafer/config.toml:\n"
|
|
290
|
+
f" [pools.{name}]\n"
|
|
291
|
+
f' targets = ["target-1", "target-2"]'
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
pool_config = pools[name]
|
|
295
|
+
targets = pool_config.get("targets", [])
|
|
296
|
+
|
|
297
|
+
if not targets:
|
|
298
|
+
raise ValueError(f"Pool '{name}' has no targets defined")
|
|
299
|
+
|
|
300
|
+
return targets
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def list_pools() -> list[str]:
|
|
304
|
+
"""List all configured pool names.
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
Sorted list of pool names
|
|
308
|
+
"""
|
|
309
|
+
if not CONFIG_FILE.exists():
|
|
310
|
+
return []
|
|
311
|
+
|
|
312
|
+
with open(CONFIG_FILE, "rb") as f:
|
|
313
|
+
data = tomllib.load(f)
|
|
314
|
+
|
|
315
|
+
return sorted(data.get("pools", {}).keys())
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def save_pool(name: str, targets: list[str]) -> None:
|
|
319
|
+
"""Save or update a pool configuration.
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
name: Pool name
|
|
323
|
+
targets: List of target names (must all exist)
|
|
324
|
+
|
|
325
|
+
Raises:
|
|
326
|
+
FileNotFoundError: If any target doesn't exist
|
|
327
|
+
"""
|
|
328
|
+
# Verify all targets exist
|
|
329
|
+
existing_targets = list_targets()
|
|
330
|
+
missing = [t for t in targets if t not in existing_targets]
|
|
331
|
+
if missing:
|
|
332
|
+
raise FileNotFoundError(f"Targets not found: {', '.join(missing)}")
|
|
333
|
+
|
|
334
|
+
_ensure_dirs()
|
|
335
|
+
|
|
336
|
+
# Load existing config
|
|
337
|
+
if CONFIG_FILE.exists():
|
|
338
|
+
with open(CONFIG_FILE, "rb") as f:
|
|
339
|
+
data = tomllib.load(f)
|
|
340
|
+
else:
|
|
341
|
+
data = {}
|
|
342
|
+
|
|
343
|
+
# Update pools section
|
|
344
|
+
if "pools" not in data:
|
|
345
|
+
data["pools"] = {}
|
|
346
|
+
|
|
347
|
+
data["pools"][name] = {"targets": targets}
|
|
348
|
+
|
|
349
|
+
# Write back - need custom handling for nested structure
|
|
350
|
+
_write_config_with_pools(data)
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
def _write_config_with_pools(data: dict) -> None:
|
|
354
|
+
"""Write config file with pools support.
|
|
355
|
+
|
|
356
|
+
Handles the nested [pools.name] TOML structure and preserves
|
|
357
|
+
existing nested sections like [default], [api], [environments.*].
|
|
358
|
+
"""
|
|
359
|
+
lines = []
|
|
360
|
+
|
|
361
|
+
# Collect nested sections to write after top-level keys
|
|
362
|
+
nested_sections: dict[str, dict] = {}
|
|
363
|
+
|
|
364
|
+
# Write top-level keys first (except pools and nested dicts)
|
|
365
|
+
for key, value in data.items():
|
|
366
|
+
if key == "pools":
|
|
367
|
+
continue
|
|
368
|
+
if value is None:
|
|
369
|
+
continue
|
|
370
|
+
if isinstance(value, dict):
|
|
371
|
+
# Save nested sections for later
|
|
372
|
+
nested_sections[key] = value
|
|
373
|
+
elif isinstance(value, str):
|
|
374
|
+
lines.append(f'{key} = "{value}"')
|
|
375
|
+
elif isinstance(value, bool):
|
|
376
|
+
lines.append(f"{key} = {str(value).lower()}")
|
|
377
|
+
elif isinstance(value, int | float):
|
|
378
|
+
lines.append(f"{key} = {value}")
|
|
379
|
+
elif isinstance(value, list):
|
|
380
|
+
if all(isinstance(v, int) for v in value):
|
|
381
|
+
lines.append(f"{key} = {value}")
|
|
382
|
+
else:
|
|
383
|
+
formatted = ", ".join(f'"{v}"' if isinstance(v, str) else str(v) for v in value)
|
|
384
|
+
lines.append(f"{key} = [{formatted}]")
|
|
385
|
+
|
|
386
|
+
# Write nested sections (e.g., [default], [api], [environments.foo])
|
|
387
|
+
for section_name, section_data in nested_sections.items():
|
|
388
|
+
lines.append("")
|
|
389
|
+
lines.append(f"[{section_name}]")
|
|
390
|
+
for key, value in section_data.items():
|
|
391
|
+
if value is None:
|
|
392
|
+
continue
|
|
393
|
+
if isinstance(value, str):
|
|
394
|
+
lines.append(f'{key} = "{value}"')
|
|
395
|
+
elif isinstance(value, bool):
|
|
396
|
+
lines.append(f"{key} = {str(value).lower()}")
|
|
397
|
+
elif isinstance(value, int | float):
|
|
398
|
+
lines.append(f"{key} = {value}")
|
|
399
|
+
elif isinstance(value, list):
|
|
400
|
+
if all(isinstance(v, int) for v in value):
|
|
401
|
+
lines.append(f"{key} = {value}")
|
|
402
|
+
else:
|
|
403
|
+
formatted = ", ".join(f'"{v}"' if isinstance(v, str) else str(v) for v in value)
|
|
404
|
+
lines.append(f"{key} = [{formatted}]")
|
|
405
|
+
|
|
406
|
+
# Write pools
|
|
407
|
+
pools = data.get("pools", {})
|
|
408
|
+
for pool_name, pool_config in pools.items():
|
|
409
|
+
lines.append("")
|
|
410
|
+
lines.append(f"[pools.{pool_name}]")
|
|
411
|
+
targets = pool_config.get("targets", [])
|
|
412
|
+
formatted = ", ".join(f'"{t}"' for t in targets)
|
|
413
|
+
lines.append(f"targets = [{formatted}]")
|
|
414
|
+
|
|
415
|
+
CONFIG_FILE.write_text("\n".join(lines) + "\n")
|
|
416
|
+
|
|
417
|
+
|
|
260
418
|
def set_default_target(name: str) -> None:
|
|
261
419
|
"""Set default target.
|
|
262
420
|
|
wafer/wevin_cli.py
CHANGED
|
@@ -86,8 +86,21 @@ class StreamingChunkFrontend:
|
|
|
86
86
|
})
|
|
87
87
|
|
|
88
88
|
elif isinstance(event, ToolResultReceived):
|
|
89
|
-
# Emit tool_result event
|
|
90
|
-
|
|
89
|
+
# Emit tool_result event with error details
|
|
90
|
+
result_event = {"type": "tool_result", "is_error": event.is_error}
|
|
91
|
+
# Include error message and content if available
|
|
92
|
+
if event.error:
|
|
93
|
+
result_event["error"] = event.error
|
|
94
|
+
if event.content:
|
|
95
|
+
# Convert content to string if it's a list
|
|
96
|
+
if isinstance(event.content, list):
|
|
97
|
+
result_event["content"] = "\n".join(
|
|
98
|
+
str(item) if not isinstance(item, dict) else item.get("text", str(item))
|
|
99
|
+
for item in event.content
|
|
100
|
+
)
|
|
101
|
+
else:
|
|
102
|
+
result_event["content"] = str(event.content)
|
|
103
|
+
self._emit(result_event)
|
|
91
104
|
|
|
92
105
|
elif isinstance(event, StreamDone):
|
|
93
106
|
# Will be handled by stop()
|
|
@@ -240,6 +253,7 @@ def _build_environment(
|
|
|
240
253
|
) -> Environment:
|
|
241
254
|
"""Build a CodingEnvironment from template config."""
|
|
242
255
|
from wafer_core.environments.coding import CodingEnvironment
|
|
256
|
+
from wafer_core.rollouts.templates import DANGEROUS_BASH_COMMANDS
|
|
243
257
|
|
|
244
258
|
working_dir = Path(corpus_path) if corpus_path else Path.cwd()
|
|
245
259
|
resolved_tools = tools_override or tpl.tools
|
|
@@ -247,6 +261,7 @@ def _build_environment(
|
|
|
247
261
|
working_dir=working_dir,
|
|
248
262
|
enabled_tools=resolved_tools,
|
|
249
263
|
bash_allowlist=tpl.bash_allowlist,
|
|
264
|
+
bash_denylist=DANGEROUS_BASH_COMMANDS,
|
|
250
265
|
) # type: ignore[assignment]
|
|
251
266
|
return env
|
|
252
267
|
|
|
@@ -347,6 +362,11 @@ def main( # noqa: PLR0913, PLR0915
|
|
|
347
362
|
print(f" {s.session_id} {preview}")
|
|
348
363
|
return
|
|
349
364
|
|
|
365
|
+
# Emit early event for JSON mode before heavy imports
|
|
366
|
+
# This gives immediate feedback that the CLI started correctly
|
|
367
|
+
if json_output:
|
|
368
|
+
print(json.dumps({"type": "initializing"}), flush=True)
|
|
369
|
+
|
|
350
370
|
import trio
|
|
351
371
|
from wafer_core.rollouts import FileSessionStore, Message, Trajectory
|
|
352
372
|
from wafer_core.rollouts.frontends import NoneFrontend, RunnerConfig, run_interactive
|
|
@@ -5,29 +5,31 @@ wafer/api_client.py,sha256=cPULiTxqOAYYSfDTNJgd-6Pqrt3IM4Gm9903U7yGIwY,6163
|
|
|
5
5
|
wafer/auth.py,sha256=ZLsXZ73GDLD8GL7Rij1ELtuLqyJ5EU_uPBUMPVKwExA,10703
|
|
6
6
|
wafer/autotuner.py,sha256=6gH0Ho7T58EFerMQcHQxshWe3DF4qU7fb5xthAh5SPM,44364
|
|
7
7
|
wafer/billing.py,sha256=jbLB2lI4_9f2KD8uEFDi_ixLlowe5hasC0TIZJyIXRg,7163
|
|
8
|
-
wafer/cli.py,sha256=
|
|
8
|
+
wafer/cli.py,sha256=rdR84w5ubXO1W2xnrURTrX3AtXy3VeUFVekeGw0djyA,211114
|
|
9
9
|
wafer/config.py,sha256=h5Eo9_yfWqWGoPNdVQikI9GoZVUeysunSYiixf1mKcw,3411
|
|
10
10
|
wafer/corpus.py,sha256=yTF3UA5bOa8BII2fmcXf-3WsIsM5DX4etysv0AzVknE,8912
|
|
11
|
-
wafer/evaluate.py,sha256=
|
|
11
|
+
wafer/evaluate.py,sha256=D_0WqIw1HysH7XXiyjxRpv6BUuOoPljN9-1vjPt4xFo,166765
|
|
12
12
|
wafer/global_config.py,sha256=fhaR_RU3ufMksDmOohH1OLeQ0JT0SDW1hEip_zaP75k,11345
|
|
13
|
-
wafer/gpu_run.py,sha256=
|
|
13
|
+
wafer/gpu_run.py,sha256=TwqXy72T7f2I7e6n5WWod3xgxCPnDhU0BgLsB4CUoQY,9716
|
|
14
14
|
wafer/inference.py,sha256=tZCO5i05FKY27ewis3CSBHFBeFbXY3xwj0DSjdoMY9s,4314
|
|
15
15
|
wafer/ncu_analyze.py,sha256=rAWzKQRZEY6E_CL3gAWUaW3uZ4kvQVZskVCPDpsFJuE,24633
|
|
16
16
|
wafer/nsys_analyze.py,sha256=dRsYNYp1IqzGSPrQuEMW5vRbIxr-VrQwQbotLSrPvlY,6795
|
|
17
|
+
wafer/problems.py,sha256=ce2sy10A1nnNUG3VGsseTS8jL7LZsku4dE8zVf9JHQ4,11296
|
|
17
18
|
wafer/rocprof_compute.py,sha256=Tu16Vb05b2grvheFWi1XLGlAr6m48NEDeZoDyw_4Uzw,19885
|
|
18
19
|
wafer/rocprof_sdk.py,sha256=fAYCxpfJa5BZTTkIMBOXg4KsYK4i_wNOKrJJn1ZfypM,10086
|
|
19
20
|
wafer/rocprof_systems.py,sha256=4IWbMcbYk1x_8iS7P3FC_u5sgH6EXADCtR2lV9id80M,18629
|
|
20
|
-
wafer/
|
|
21
|
+
wafer/target_lock.py,sha256=QW0NMlu9Paa28O5iSAvGtN11j3kU2di0lADBrfwr2js,5160
|
|
22
|
+
wafer/targets.py,sha256=JlLvi18IHtOkgtBdkv_nUrzBweVmFoOQH-9tQW5s1yQ,15250
|
|
21
23
|
wafer/tracelens.py,sha256=g9ZIeFyNojZn4uTd3skPqIrRiL7aMJOz_-GOd3aiyy4,7998
|
|
22
|
-
wafer/wevin_cli.py,sha256=
|
|
24
|
+
wafer/wevin_cli.py,sha256=1_o2P47namZmPkbt47TnyYDmwhEzQYbSg5zjHffu2JQ,16802
|
|
23
25
|
wafer/workspaces.py,sha256=92LG1mtkzNz-ap3XzcqY6KnQ9SUCFG8VBIOUj1Who64,25757
|
|
24
26
|
wafer/skills/wafer-guide/SKILL.md,sha256=UfBeIe5GKFzOYcbPmcs8U2nrjbfr-jSMRwg0jQDBfb0,3058
|
|
25
27
|
wafer/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
28
|
wafer/templates/ask_docs.py,sha256=Lxs-faz9v5m4Qa4NjF2X_lE8KwM9ES9MNJkxo7ep56o,2256
|
|
27
29
|
wafer/templates/optimize_kernel.py,sha256=u6AL7Q3uttqlnBLzcoFdsiPq5lV2TV3bgqwCYYlK9gk,2357
|
|
28
30
|
wafer/templates/trace_analyze.py,sha256=XE1VqzVkIUsZbXF8EzQdDYgg-AZEYAOFpr6B_vnRELc,2880
|
|
29
|
-
wafer_cli-0.2.
|
|
30
|
-
wafer_cli-0.2.
|
|
31
|
-
wafer_cli-0.2.
|
|
32
|
-
wafer_cli-0.2.
|
|
33
|
-
wafer_cli-0.2.
|
|
31
|
+
wafer_cli-0.2.5.dist-info/METADATA,sha256=O1JyAJtPtr5j4sz5jKiDfyB4d14Mb3tSSDEnQftyzwE,559
|
|
32
|
+
wafer_cli-0.2.5.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
33
|
+
wafer_cli-0.2.5.dist-info/entry_points.txt,sha256=WqB7hB__WhtPY8y1cO2sZiUz7fCq6Ik-usAigpeFvWE,41
|
|
34
|
+
wafer_cli-0.2.5.dist-info/top_level.txt,sha256=2MK1IVMWfpLL8BZCQ3E9aG6L6L666gSA_teYlwan4fs,6
|
|
35
|
+
wafer_cli-0.2.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|