vibecheck-error-assistant-cli 0.1.0__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.
@@ -0,0 +1,70 @@
1
+ Metadata-Version: 2.4
2
+ Name: vibecheck-error-assistant-cli
3
+ Version: 0.1.0
4
+ Summary: Run commands and translate programming errors into beginner-friendly explanations
5
+ Author: VibeCheck
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: openai==2.30.0
9
+ Requires-Dist: rich==14.3.3
10
+ Requires-Dist: python-dotenv==1.2.2
11
+
12
+ # VibeCheck CLI
13
+
14
+ VibeCheck runs your command, catches failures, and translates technical stderr into beginner-friendly guidance.
15
+
16
+ ## Install (MVP)
17
+
18
+ From project root:
19
+
20
+ ```bash
21
+ python3 -m venv .venv
22
+ source .venv/bin/activate
23
+ pip install -e .
24
+ ```
25
+
26
+ After install, you can use the `vibecheck` command directly.
27
+
28
+ ## Configure
29
+
30
+ ```bash
31
+ cp .env.example .env
32
+ # edit .env and set VIBECHECK_GITHUB_TOKEN
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ Single command mode:
38
+
39
+ ```bash
40
+ vibecheck python buggy_sample.py
41
+ ```
42
+
43
+ Interactive mode (tool waits in terminal):
44
+
45
+ ```bash
46
+ vibecheck --shell
47
+ ```
48
+
49
+ Then type commands like:
50
+
51
+ ```bash
52
+ python buggy_sample.py
53
+ node buggy_advanced.js
54
+ ```
55
+
56
+ Exit interactive mode with `exit` or `quit`.
57
+
58
+ ## Useful Flags
59
+
60
+ ```bash
61
+ vibecheck --level beginner python buggy_sample.py
62
+ vibecheck --level advanced node buggy_advanced.js
63
+ vibecheck --print-raw-error python buggy_sample.py
64
+ ```
65
+
66
+ ## Exit Codes
67
+
68
+ - Returns `0` when wrapped command succeeds.
69
+ - Returns wrapped command's non-zero exit code when command fails.
70
+ - Returns `2` on configuration errors.
@@ -0,0 +1,59 @@
1
+ # VibeCheck CLI
2
+
3
+ VibeCheck runs your command, catches failures, and translates technical stderr into beginner-friendly guidance.
4
+
5
+ ## Install (MVP)
6
+
7
+ From project root:
8
+
9
+ ```bash
10
+ python3 -m venv .venv
11
+ source .venv/bin/activate
12
+ pip install -e .
13
+ ```
14
+
15
+ After install, you can use the `vibecheck` command directly.
16
+
17
+ ## Configure
18
+
19
+ ```bash
20
+ cp .env.example .env
21
+ # edit .env and set VIBECHECK_GITHUB_TOKEN
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ Single command mode:
27
+
28
+ ```bash
29
+ vibecheck python buggy_sample.py
30
+ ```
31
+
32
+ Interactive mode (tool waits in terminal):
33
+
34
+ ```bash
35
+ vibecheck --shell
36
+ ```
37
+
38
+ Then type commands like:
39
+
40
+ ```bash
41
+ python buggy_sample.py
42
+ node buggy_advanced.js
43
+ ```
44
+
45
+ Exit interactive mode with `exit` or `quit`.
46
+
47
+ ## Useful Flags
48
+
49
+ ```bash
50
+ vibecheck --level beginner python buggy_sample.py
51
+ vibecheck --level advanced node buggy_advanced.js
52
+ vibecheck --print-raw-error python buggy_sample.py
53
+ ```
54
+
55
+ ## Exit Codes
56
+
57
+ - Returns `0` when wrapped command succeeds.
58
+ - Returns wrapped command's non-zero exit code when command fails.
59
+ - Returns `2` on configuration errors.
@@ -0,0 +1,309 @@
1
+ import argparse
2
+ import os
3
+ import re
4
+ import shlex
5
+ import subprocess
6
+ import sys
7
+ from dataclasses import dataclass
8
+ from typing import Sequence
9
+
10
+ from dotenv import load_dotenv
11
+ from openai import OpenAI, RateLimitError
12
+ from rich.console import Console
13
+ from rich.live import Live
14
+ from rich.markdown import Markdown
15
+ from rich.panel import Panel
16
+ from rich.spinner import Spinner
17
+
18
+
19
+ console = Console()
20
+
21
+
22
+ @dataclass(frozen=True)
23
+ class Settings:
24
+ github_token: str
25
+ endpoint: str
26
+ model_tiers: list[str]
27
+ max_error_chars: int
28
+ ai_timeout_seconds: int
29
+
30
+
31
+ DEFAULT_MODEL_TIERS = [
32
+ "gpt-4o-mini",
33
+ "gpt-4.1-mini",
34
+ "codestral-25.01",
35
+ "meta-llama-3.1-8b-instruct",
36
+ "phi-4",
37
+ "deepseek-r1-0528",
38
+ "o3-mini",
39
+ ]
40
+
41
+
42
+ def load_settings() -> Settings:
43
+ load_dotenv()
44
+ token = os.getenv("VIBECHECK_GITHUB_TOKEN", "").strip()
45
+ endpoint = os.getenv("VIBECHECK_ENDPOINT", "https://models.inference.ai.azure.com").strip()
46
+
47
+ tiers_raw = os.getenv("VIBECHECK_MODELS", "")
48
+ model_tiers = [m.strip() for m in tiers_raw.split(",") if m.strip()] if tiers_raw else DEFAULT_MODEL_TIERS
49
+
50
+ max_error_chars = int(os.getenv("VIBECHECK_MAX_ERROR_CHARS", "5000"))
51
+ ai_timeout_seconds = int(os.getenv("VIBECHECK_AI_TIMEOUT_SECONDS", "45"))
52
+
53
+ return Settings(
54
+ github_token=token,
55
+ endpoint=endpoint,
56
+ model_tiers=model_tiers,
57
+ max_error_chars=max_error_chars,
58
+ ai_timeout_seconds=ai_timeout_seconds,
59
+ )
60
+
61
+
62
+ def parse_args(argv: Sequence[str]) -> argparse.Namespace:
63
+ parser = argparse.ArgumentParser(
64
+ prog="vibecheck",
65
+ description="Run a command and translate failures into beginner-friendly guidance.",
66
+ )
67
+ parser.add_argument(
68
+ "--print-raw-error",
69
+ action="store_true",
70
+ help="Show raw stderr in addition to AI guidance.",
71
+ )
72
+ parser.add_argument(
73
+ "--level",
74
+ choices=["beginner", "intermediate", "advanced"],
75
+ default="beginner",
76
+ help="Explanation depth for the user. Default is beginner.",
77
+ )
78
+ parser.add_argument(
79
+ "--shell",
80
+ action="store_true",
81
+ help="Start interactive mode and run multiple commands in one session.",
82
+ )
83
+ parser.add_argument(
84
+ "command",
85
+ nargs="*",
86
+ help="Command to run. Example: vibecheck python buggy.py",
87
+ )
88
+ args, unknown = parser.parse_known_args(argv)
89
+ args.command = args.command + unknown
90
+ return args
91
+
92
+
93
+ def normalize_command(command: Sequence[str]) -> list[str]:
94
+ normalized = list(command)
95
+ if normalized and normalized[0] == "--":
96
+ normalized = normalized[1:]
97
+ return normalized
98
+
99
+
100
+ def run_target_command(command: Sequence[str]) -> subprocess.CompletedProcess[str]:
101
+ return subprocess.run(command, capture_output=True, text=True)
102
+
103
+
104
+ def extract_line_hint(error_text: str) -> str:
105
+ line_matches = re.findall(r"line\s+(\d+)", error_text, flags=re.IGNORECASE)
106
+ if not line_matches:
107
+ return "No specific line found in traceback."
108
+ return f"Likely line mentioned by runtime: {line_matches[-1]}"
109
+
110
+
111
+ def build_prompt(error_text: str, line_hint: str, level: str) -> str:
112
+ # 1. The Core Identity (The Role)
113
+ base_identity = (
114
+ "You are 'VibeGuard,' an elite coding mentor known for extreme patience and clarity. "
115
+ "Your goal is to turn a frustrating error into a 'lightbulb moment.' "
116
+ "Since your users may not be native English speakers, use 'Global English': "
117
+ "avoid slang, avoid complex metaphors, and use clear, literal instructions.\n\n"
118
+ )
119
+
120
+ level_rules = {
121
+ "beginner": (
122
+ "### ROLE: THE PATIENT EXPLORER\n"
123
+ "1. **Tone**: Warm, encouraging, and highly detailed. Use simple, high-frequency English words.\n"
124
+ "2. **The 'Why'**: Do not just fix the code. Explain the 'Logic of the Universe.' "
125
+ "If it is a TypeError, explain that Python is like a chef who was given a 'shoe' when they asked for an 'onion.'\n"
126
+ "3. **Vocabulary Breakdown**: Identify every technical word in the error (e.g., 'Attribute', 'Iteration', 'Literal') "
127
+ "and define it using a real-world object analogy.\n"
128
+ "4. **Step-by-Step Recovery**: Break the fix into 'Small Steps.' Step 1: Look here. Step 2: Change this. Step 3: Run again.\n"
129
+ "5. **Visual Representation**: Use simple ASCII art or spacing to show where the error is pointing."
130
+ ),
131
+ "intermediate": (
132
+ "### ROLE: THE EFFICIENT COACH\n"
133
+ "1. **Tone**: Professional and direct. Assume they know the basics (loops, variables) but missed a logic connection.\n"
134
+ "2. **Root Cause**: Explain the architectural reason for the error. Did they break a 'contract' of the function?\n"
135
+ "3. **Best Practices**: Briefly mention a 'cleaner' way to write this to avoid the error in the future.\n"
136
+ "4. **The Fix**: Provide the code block clearly."
137
+ ),
138
+ "advanced": (
139
+ "### ROLE: THE SENIOR ARCHITECT\n"
140
+ "1. **Tone**: Minimalist. Use technical shorthand.\n"
141
+ "2. **Insight**: Focus on memory, performance, or library-specific quirks.\n"
142
+ "3. **The Fix**: Provide a 'one-liner' or a diff format fix."
143
+ ),
144
+ }
145
+
146
+ # Constructing the Final Mega-Prompt
147
+ chosen_role = level_rules.get(level, level_rules["beginner"])
148
+
149
+ full_prompt = (
150
+ f"{base_identity}"
151
+ f"{chosen_role}\n\n"
152
+ f"--- THE TASK ---\n"
153
+ f"The user received this error message: '{error_text}'\n"
154
+ f"The error seems to be near: {line_hint}\n\n"
155
+ "Structure your response exactly like this:\n"
156
+ "1. **The Vibe Check**: A 1-sentence supportive opening.\n"
157
+ "2. **The Simple Translation**: Translate the computer-speak into 'Human-speak'.\n"
158
+ "3. **Word Bank**: Define technical terms found in the error.\n"
159
+ "4. **The Deep Dive**: Detailed explanation of the mistake.\n"
160
+ "5. **The Repair**: Clear code fix with comments.\n"
161
+ "6. **Pro-Tip**: How to never see this error again."
162
+ )
163
+
164
+ return full_prompt
165
+
166
+
167
+ def ask_ai_for_explanation(client: OpenAI, settings: Settings, error_text: str, level: str) -> tuple[str, str]:
168
+ line_hint = extract_line_hint(error_text)
169
+ prompt = build_prompt(error_text, line_hint, level)
170
+
171
+ with Live(Spinner("dots", text="[bold yellow]Analyzing failure...[/bold yellow]"), refresh_per_second=12) as live:
172
+ for model_name in settings.model_tiers:
173
+ try:
174
+ live.update(Spinner("dots", text=f"[bold cyan]Trying {model_name}[/bold cyan]"))
175
+ response = client.chat.completions.create(
176
+ model=model_name,
177
+ temperature=0.1,
178
+ timeout=settings.ai_timeout_seconds,
179
+ messages=[
180
+ {
181
+ "role": "system",
182
+ "content": "You explain programming errors clearly for beginners.",
183
+ },
184
+ {"role": "user", "content": prompt},
185
+ ],
186
+ )
187
+ text = response.choices[0].message.content or "No explanation returned by model."
188
+ return text, model_name
189
+ except RateLimitError:
190
+ continue
191
+ except Exception:
192
+ continue
193
+
194
+ return "Unable to get an AI explanation right now. Please retry shortly.", "no-model"
195
+
196
+
197
+ def display_vibe_panel(ai_text: str, model_used: str) -> None:
198
+ panel = Panel(
199
+ Markdown(ai_text),
200
+ title=f"[bold red]VibeCheck Report ({model_used})[/bold red]",
201
+ border_style="bright_magenta",
202
+ padding=(1, 2),
203
+ )
204
+ console.print()
205
+ console.print(panel)
206
+ console.print()
207
+
208
+
209
+ def ensure_token(settings: Settings) -> None:
210
+ if settings.github_token:
211
+ return
212
+
213
+ console.print(
214
+ Panel(
215
+ "Missing VIBECHECK_GITHUB_TOKEN.\n"
216
+ "Create a .env file with:\n\n"
217
+ "VIBECHECK_GITHUB_TOKEN=your_token_here\n"
218
+ "VIBECHECK_ENDPOINT=https://models.inference.ai.azure.com",
219
+ title="Configuration Required",
220
+ border_style="red",
221
+ )
222
+ )
223
+ raise SystemExit(2)
224
+
225
+
226
+ def run_with_vibecheck(command: Sequence[str], settings: Settings, level: str, print_raw_error: bool) -> int:
227
+ console.print(f"[bold green]Running:[/bold green] {' '.join(command)}")
228
+ proc = run_target_command(command)
229
+
230
+ if proc.stdout:
231
+ console.print(Panel(proc.stdout.rstrip(), title="Command stdout", border_style="green"))
232
+
233
+ if proc.returncode == 0:
234
+ console.print("[bold green]Command finished successfully. No errors to explain.[/bold green]")
235
+ return 0
236
+
237
+ error_text = (proc.stderr or "").strip() or f"Command failed with exit code {proc.returncode} and no stderr output."
238
+
239
+ if print_raw_error:
240
+ console.print(Panel(error_text, title="Raw stderr", border_style="yellow"))
241
+
242
+ ensure_token(settings)
243
+
244
+ trimmed_error = error_text[: settings.max_error_chars]
245
+ client = OpenAI(base_url=settings.endpoint, api_key=settings.github_token)
246
+ explanation, model_used = ask_ai_for_explanation(client, settings, trimmed_error, level)
247
+ display_vibe_panel(explanation, model_used)
248
+
249
+ return proc.returncode
250
+
251
+
252
+ def run_interactive_shell(settings: Settings, level: str, print_raw_error: bool) -> int:
253
+ console.print("[bold cyan]VibeCheck shell mode started.[/bold cyan]")
254
+ console.print("Type a command and press Enter. Type 'exit' or 'quit' to stop.")
255
+
256
+ while True:
257
+ try:
258
+ raw = input("vibecheck> ").strip()
259
+ except EOFError:
260
+ console.print()
261
+ break
262
+ except KeyboardInterrupt:
263
+ console.print("\nInterrupted. Type 'exit' to quit cleanly.")
264
+ continue
265
+
266
+ if not raw:
267
+ continue
268
+
269
+ if raw in {"exit", "quit"}:
270
+ break
271
+
272
+ try:
273
+ command = shlex.split(raw)
274
+ except ValueError as exc:
275
+ console.print(f"[red]Invalid command syntax:[/red] {exc}")
276
+ continue
277
+
278
+ run_with_vibecheck(command, settings=settings, level=level, print_raw_error=print_raw_error)
279
+
280
+ console.print("[bold cyan]VibeCheck shell mode ended.[/bold cyan]")
281
+ return 0
282
+
283
+
284
+ def main(argv: Sequence[str]) -> int:
285
+ args = parse_args(argv)
286
+ command = normalize_command(args.command)
287
+ settings = load_settings()
288
+
289
+ if args.shell or not command:
290
+ return run_interactive_shell(
291
+ settings=settings,
292
+ level=args.level,
293
+ print_raw_error=args.print_raw_error,
294
+ )
295
+
296
+ return run_with_vibecheck(
297
+ command,
298
+ settings=settings,
299
+ level=args.level,
300
+ print_raw_error=args.print_raw_error,
301
+ )
302
+
303
+
304
+ def cli() -> None:
305
+ raise SystemExit(main(sys.argv[1:]))
306
+
307
+
308
+ if __name__ == "__main__":
309
+ cli()
@@ -0,0 +1,24 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "vibecheck-error-assistant-cli"
7
+ version = "0.1.0"
8
+ description = "Run commands and translate programming errors into beginner-friendly explanations"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ authors = [
12
+ { name = "VibeCheck" }
13
+ ]
14
+ dependencies = [
15
+ "openai==2.30.0",
16
+ "rich==14.3.3",
17
+ "python-dotenv==1.2.2"
18
+ ]
19
+
20
+ [project.scripts]
21
+ vibecheck = "main:cli"
22
+
23
+ [tool.setuptools]
24
+ py-modules = ["main"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,70 @@
1
+ Metadata-Version: 2.4
2
+ Name: vibecheck-error-assistant-cli
3
+ Version: 0.1.0
4
+ Summary: Run commands and translate programming errors into beginner-friendly explanations
5
+ Author: VibeCheck
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: openai==2.30.0
9
+ Requires-Dist: rich==14.3.3
10
+ Requires-Dist: python-dotenv==1.2.2
11
+
12
+ # VibeCheck CLI
13
+
14
+ VibeCheck runs your command, catches failures, and translates technical stderr into beginner-friendly guidance.
15
+
16
+ ## Install (MVP)
17
+
18
+ From project root:
19
+
20
+ ```bash
21
+ python3 -m venv .venv
22
+ source .venv/bin/activate
23
+ pip install -e .
24
+ ```
25
+
26
+ After install, you can use the `vibecheck` command directly.
27
+
28
+ ## Configure
29
+
30
+ ```bash
31
+ cp .env.example .env
32
+ # edit .env and set VIBECHECK_GITHUB_TOKEN
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ Single command mode:
38
+
39
+ ```bash
40
+ vibecheck python buggy_sample.py
41
+ ```
42
+
43
+ Interactive mode (tool waits in terminal):
44
+
45
+ ```bash
46
+ vibecheck --shell
47
+ ```
48
+
49
+ Then type commands like:
50
+
51
+ ```bash
52
+ python buggy_sample.py
53
+ node buggy_advanced.js
54
+ ```
55
+
56
+ Exit interactive mode with `exit` or `quit`.
57
+
58
+ ## Useful Flags
59
+
60
+ ```bash
61
+ vibecheck --level beginner python buggy_sample.py
62
+ vibecheck --level advanced node buggy_advanced.js
63
+ vibecheck --print-raw-error python buggy_sample.py
64
+ ```
65
+
66
+ ## Exit Codes
67
+
68
+ - Returns `0` when wrapped command succeeds.
69
+ - Returns wrapped command's non-zero exit code when command fails.
70
+ - Returns `2` on configuration errors.
@@ -0,0 +1,9 @@
1
+ README.md
2
+ main.py
3
+ pyproject.toml
4
+ vibecheck_error_assistant_cli.egg-info/PKG-INFO
5
+ vibecheck_error_assistant_cli.egg-info/SOURCES.txt
6
+ vibecheck_error_assistant_cli.egg-info/dependency_links.txt
7
+ vibecheck_error_assistant_cli.egg-info/entry_points.txt
8
+ vibecheck_error_assistant_cli.egg-info/requires.txt
9
+ vibecheck_error_assistant_cli.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ vibecheck = main:cli
@@ -0,0 +1,3 @@
1
+ openai==2.30.0
2
+ rich==14.3.3
3
+ python-dotenv==1.2.2