weco 0.3.7__py3-none-any.whl → 0.3.9__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.
weco/validation.py ADDED
@@ -0,0 +1,112 @@
1
+ """Input validation for the Weco CLI.
2
+
3
+ Provides early validation of user inputs with helpful, actionable error messages.
4
+ Validation happens before expensive operations (auth, API calls) to fail fast.
5
+ """
6
+
7
+ import pathlib
8
+ from difflib import get_close_matches
9
+
10
+ from rich.console import Console
11
+
12
+
13
+ class ValidationError(Exception):
14
+ """Raised when user input validation fails."""
15
+
16
+ def __init__(self, message: str, suggestion: str | None = None):
17
+ self.message = message
18
+ self.suggestion = suggestion
19
+ super().__init__(message)
20
+
21
+
22
+ def validate_source_file(source: str) -> None:
23
+ """
24
+ Validate that the source file exists and is readable.
25
+
26
+ Args:
27
+ source: Path to the source file.
28
+
29
+ Raises:
30
+ ValidationError: If the file doesn't exist, isn't readable, or isn't a valid text file.
31
+ """
32
+ path = pathlib.Path(source)
33
+
34
+ if not path.exists():
35
+ suggestion = _find_similar_files(path)
36
+ raise ValidationError(f"Source file '{source}' not found.", suggestion=suggestion)
37
+
38
+ if path.is_dir():
39
+ raise ValidationError(
40
+ f"'{source}' is a directory, not a file.", suggestion="Please specify a file path, e.g., 'src/model.py'"
41
+ )
42
+
43
+ # Try reading the file to catch permission and encoding issues early
44
+ try:
45
+ path.read_text(encoding="utf-8")
46
+ except PermissionError:
47
+ raise ValidationError(f"Cannot read '{source}' — permission denied.")
48
+ except UnicodeDecodeError:
49
+ raise ValidationError(
50
+ f"'{source}' doesn't appear to be a valid text file.",
51
+ suggestion="Weco optimizes source code files (e.g., .py, .cu, .rs)",
52
+ )
53
+ except OSError as e:
54
+ raise ValidationError(f"Cannot read '{source}': {e}")
55
+
56
+
57
+ def validate_log_directory(log_dir: str) -> None:
58
+ """
59
+ Validate that the log directory is writable.
60
+
61
+ Args:
62
+ log_dir: Path to the log directory.
63
+
64
+ Raises:
65
+ ValidationError: If the directory can't be created or isn't writable.
66
+ """
67
+ path = pathlib.Path(log_dir)
68
+
69
+ try:
70
+ # Attempt to create the directory (no-op if exists)
71
+ path.mkdir(parents=True, exist_ok=True)
72
+ except PermissionError:
73
+ raise ValidationError(f"Cannot create log directory '{log_dir}' — permission denied.")
74
+ except OSError as e:
75
+ raise ValidationError(f"Cannot create log directory '{log_dir}': {e}")
76
+
77
+ # Check if writable by attempting to create a temp file
78
+ test_file = path / ".weco_write_test"
79
+ try:
80
+ test_file.touch()
81
+ test_file.unlink()
82
+ except PermissionError:
83
+ raise ValidationError(f"Log directory '{log_dir}' is not writable.")
84
+ except OSError:
85
+ pass # Directory exists and is likely fine
86
+
87
+
88
+ def _find_similar_files(path: pathlib.Path) -> str | None:
89
+ """Find similar filenames in the same directory to suggest as alternatives."""
90
+ parent = path.parent if path.parent.exists() else pathlib.Path(".")
91
+
92
+ try:
93
+ # Get files with the same extension, or all files if no extension
94
+ if path.suffix:
95
+ candidates = [f.name for f in parent.iterdir() if f.is_file() and f.suffix == path.suffix]
96
+ else:
97
+ candidates = [f.name for f in parent.iterdir() if f.is_file()]
98
+
99
+ matches = get_close_matches(path.name, candidates, n=3, cutoff=0.4)
100
+ if matches:
101
+ return f"Did you mean: {', '.join(matches)}?"
102
+ except OSError:
103
+ pass
104
+
105
+ return None
106
+
107
+
108
+ def print_validation_error(error: ValidationError, console: Console) -> None:
109
+ """Print a validation error in a user-friendly format."""
110
+ console.print(f"[bold red]Error:[/] {error.message}")
111
+ if error.suggestion:
112
+ console.print(f"[dim]{error.suggestion}[/]")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: weco
3
- Version: 0.3.7
3
+ Version: 0.3.9
4
4
  Summary: Documentation for `weco`, a CLI for using Weco AI's code optimizer.
5
5
  Author-email: Weco AI Team <contact@weco.ai>
6
6
  License:
@@ -336,7 +336,25 @@ For more advanced examples, including [Triton](/examples/triton/README.md), [CUD
336
336
  |---------|-------------|-------------|
337
337
  | `weco run [options]` | Direct optimization execution | **For advanced users** - When you know exactly what to optimize and how |
338
338
  | `weco resume <run-id>` | Resume an interrupted run | Continue from the last completed step |
339
+ | `weco login` | Authenticate with Weco | First-time setup or switching accounts |
339
340
  | `weco logout` | Clear authentication credentials | To switch accounts or troubleshoot authentication issues |
341
+ | `weco credits balance` | Check your current credit balance | Monitor usage |
342
+ | `weco credits topup [amount]` | Purchase additional credits | When you need more credits (default: 10) |
343
+ | `weco credits autotopup` | Configure automatic top-up | Set up automatic credit replenishment |
344
+
345
+ ### Setup Commands (Experimental)
346
+
347
+ | Command | Description |
348
+ |---------|-------------|
349
+ | `weco setup claude-code` | Set up Weco skill for Claude Code |
350
+
351
+ The `setup` command installs Weco skills for AI coding assistants. Currently supports Claude Code:
352
+
353
+ ```bash
354
+ weco setup claude-code
355
+ ```
356
+
357
+ This clones the Weco skill to `~/.claude/skills/weco/` and optionally updates your `~/.claude/CLAUDE.md` to enable automatic skill discovery.
340
358
 
341
359
  ### Model Selection
342
360
 
@@ -357,7 +375,7 @@ weco run --model gpt-5 --source optimize.py [other options...]
357
375
  - `claude-opus-4-5`, `claude-opus-4-1`, `claude-opus-4`, `claude-sonnet-4-5`, `claude-sonnet-4`, `claude-haiku-4-5`
358
376
 
359
377
  **Google Gemini:**
360
- - `gemini-3-pro-preview`, `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.5-flash-lite`
378
+ - `gemini-3-pro-preview`, `gemini-3-flash-preview`, `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.5-flash-lite`
361
379
 
362
380
  All models are available through Weco. If no model is specified, Weco automatically selects the best model for your optimization task.
363
381
 
@@ -0,0 +1,19 @@
1
+ weco/__init__.py,sha256=ClO0uT6GKOA0iSptvP0xbtdycf0VpoPTq37jHtvlhtw,303
2
+ weco/api.py,sha256=hy0D01x-AJ26DURtKEywQAS7nQgo38A-wAJfPKHGGqM,17395
3
+ weco/auth.py,sha256=O31Hoj-Loi8DWJJG2LfeWgUMuNqAUeGDpd2ZGjA9Ah0,9997
4
+ weco/browser.py,sha256=nsqQtLqbNOe9Zhu9Zogc8rMmBMyuDxuHzKZQL_w10Ps,923
5
+ weco/cli.py,sha256=zPWQa2UU19ClzTtIvsXuYmo7E9xm50wUzY2fU8iwcro,13921
6
+ weco/constants.py,sha256=rxL6yrpIzK8zvPTmPqOYl7LUMZ01vUJ9zUqfZD2n-0U,519
7
+ weco/credits.py,sha256=C08x-TRcLg3ccfKqMGNRY7zBn7t3r7LZ119bxgfztaI,7629
8
+ weco/optimizer.py,sha256=l9TrAsie5yPbhq71kStW5jfdz9jfIXuN6Azdn6hUMZo,25224
9
+ weco/panels.py,sha256=POHt0MdRKDykwUJYXcry92O41lpB9gxna55wFI9abWU,16272
10
+ weco/setup.py,sha256=UWlJNfNvxmET3ZrhaJxQFrtZCMSyjp4HC8d6h1ndaC4,7078
11
+ weco/ui.py,sha256=Y7ASIQydwuYFdSYrvme5aGvkplFMi-cjhsnCj5Ebgoc,15092
12
+ weco/utils.py,sha256=v_rvgw-ktRoXrpPA2copngI8QDCB8UXmbiN-wAiYvEE,9450
13
+ weco/validation.py,sha256=n5aDuF3BFgwVb4eZ9PuU48nogrseXYNI8S3ePqWZCoc,3736
14
+ weco-0.3.9.dist-info/licenses/LICENSE,sha256=9LUfoGHjLPtak2zps2kL2tm65HAZIICx_FbLaRuS4KU,11337
15
+ weco-0.3.9.dist-info/METADATA,sha256=dry9z1fIVdbnCdRy8i-0Xu3SClyAZNPBCdl-hDyL6MM,30660
16
+ weco-0.3.9.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
17
+ weco-0.3.9.dist-info/entry_points.txt,sha256=ixJ2uClALbCpBvnIR6BXMNck8SHAab8eVkM9pIUowcs,39
18
+ weco-0.3.9.dist-info/top_level.txt,sha256=F0N7v6e2zBSlsorFv-arAq2yDxQbzX3KVO8GxYhPUeE,5
19
+ weco-0.3.9.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,15 +0,0 @@
1
- weco/__init__.py,sha256=ClO0uT6GKOA0iSptvP0xbtdycf0VpoPTq37jHtvlhtw,303
2
- weco/api.py,sha256=xVVRk1pj9jpjTphaInkkAhjqhgFP2-6zHT_V-5Du1Fc,13629
3
- weco/auth.py,sha256=O31Hoj-Loi8DWJJG2LfeWgUMuNqAUeGDpd2ZGjA9Ah0,9997
4
- weco/cli.py,sha256=Mtkv3rE1rQLdeoVydn30EUi1ki3Cyu45Q3cONnQH4QY,11210
5
- weco/constants.py,sha256=rxL6yrpIzK8zvPTmPqOYl7LUMZ01vUJ9zUqfZD2n-0U,519
6
- weco/credits.py,sha256=C08x-TRcLg3ccfKqMGNRY7zBn7t3r7LZ119bxgfztaI,7629
7
- weco/optimizer.py,sha256=2qYweESOAer26gjjhu4dg01XmuhtA2nMrJuijaxizzE,45492
8
- weco/panels.py,sha256=POHt0MdRKDykwUJYXcry92O41lpB9gxna55wFI9abWU,16272
9
- weco/utils.py,sha256=v_rvgw-ktRoXrpPA2copngI8QDCB8UXmbiN-wAiYvEE,9450
10
- weco-0.3.7.dist-info/licenses/LICENSE,sha256=9LUfoGHjLPtak2zps2kL2tm65HAZIICx_FbLaRuS4KU,11337
11
- weco-0.3.7.dist-info/METADATA,sha256=rWJKSr-quLFBWSfmmAuTkaR3nP7G8DPjBZTVib9fvN8,29835
12
- weco-0.3.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
- weco-0.3.7.dist-info/entry_points.txt,sha256=ixJ2uClALbCpBvnIR6BXMNck8SHAab8eVkM9pIUowcs,39
14
- weco-0.3.7.dist-info/top_level.txt,sha256=F0N7v6e2zBSlsorFv-arAq2yDxQbzX3KVO8GxYhPUeE,5
15
- weco-0.3.7.dist-info/RECORD,,