alpiecode 2.0.0__tar.gz → 2.0.2__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.
Files changed (37) hide show
  1. {alpiecode-2.0.0 → alpiecode-2.0.2}/PKG-INFO +1 -1
  2. {alpiecode-2.0.0 → alpiecode-2.0.2}/pyproject.toml +1 -1
  3. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/alpiecode.egg-info/PKG-INFO +1 -1
  4. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/alpiecode.egg-info/SOURCES.txt +1 -0
  5. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/cli.py +48 -2
  6. alpiecode-2.0.2/src/codeagent/doctor.py +208 -0
  7. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/extension/alpiecode.vsix +0 -0
  8. {alpiecode-2.0.0 → alpiecode-2.0.2}/README.md +0 -0
  9. {alpiecode-2.0.0 → alpiecode-2.0.2}/setup.cfg +0 -0
  10. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/alpiecode.egg-info/dependency_links.txt +0 -0
  11. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/alpiecode.egg-info/entry_points.txt +0 -0
  12. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/alpiecode.egg-info/requires.txt +0 -0
  13. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/alpiecode.egg-info/top_level.txt +0 -0
  14. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/__init__.py +0 -0
  15. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/agent.py +0 -0
  16. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/backends/__init__.py +0 -0
  17. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/backends/base.py +0 -0
  18. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/backends/local_backend.py +0 -0
  19. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/backends/openai_backend.py +0 -0
  20. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/cache.py +0 -0
  21. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/client.py +0 -0
  22. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/compaction.py +0 -0
  23. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/config.py +0 -0
  24. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/context.py +0 -0
  25. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/executor.py +0 -0
  26. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/github.py +0 -0
  27. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/guardian.py +0 -0
  28. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/local_model.py +0 -0
  29. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/media.py +0 -0
  30. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/memory.py +0 -0
  31. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/orchestrator.py +0 -0
  32. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/prompt.py +0 -0
  33. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/server.py +0 -0
  34. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/session.py +0 -0
  35. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/tools.py +0 -0
  36. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/updater.py +0 -0
  37. {alpiecode-2.0.0 → alpiecode-2.0.2}/src/codeagent/vscode_installer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alpiecode
3
- Version: 2.0.0
3
+ Version: 2.0.2
4
4
  Summary: AlpieCode — Autonomous AI Coding Agent CLI powered by local 169Pi GGUF VLM
5
5
  Requires-Python: >=3.9
6
6
  Requires-Dist: huggingface_hub>=0.20.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "alpiecode"
7
- version = "2.0.0"
7
+ version = "2.0.2"
8
8
  description = "AlpieCode — Autonomous AI Coding Agent CLI powered by local 169Pi GGUF VLM"
9
9
  requires-python = ">=3.9"
10
10
  dependencies = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alpiecode
3
- Version: 2.0.0
3
+ Version: 2.0.2
4
4
  Summary: AlpieCode — Autonomous AI Coding Agent CLI powered by local 169Pi GGUF VLM
5
5
  Requires-Python: >=3.9
6
6
  Requires-Dist: huggingface_hub>=0.20.0
@@ -14,6 +14,7 @@ src/codeagent/client.py
14
14
  src/codeagent/compaction.py
15
15
  src/codeagent/config.py
16
16
  src/codeagent/context.py
17
+ src/codeagent/doctor.py
17
18
  src/codeagent/executor.py
18
19
  src/codeagent/github.py
19
20
  src/codeagent/guardian.py
@@ -29,7 +29,7 @@ def _show_banner():
29
29
 
30
30
 
31
31
  def _normalize_args():
32
- known_commands = {"init", "serve", "run", "chat", "plan", "diff", "-h", "--help", "--version"}
32
+ known_commands = {"init", "serve", "run", "chat", "plan", "diff", "doctor", "explain", "-h", "--help", "--version"}
33
33
  subcommand = None
34
34
 
35
35
  # Check if a subcommand is present
@@ -42,7 +42,7 @@ def _normalize_args():
42
42
  subcommand = "run"
43
43
  sys.argv.insert(1, "run")
44
44
 
45
- if subcommand in ("run", "plan") and len(sys.argv) > 2:
45
+ if subcommand in ("run", "plan", "explain") and len(sys.argv) > 2:
46
46
  cmd_idx = sys.argv.index(subcommand)
47
47
  sub_args = sys.argv[cmd_idx + 1:]
48
48
 
@@ -107,6 +107,13 @@ def main():
107
107
  # ── diff ──
108
108
  diff_p = sub.add_parser("diff", help="Show changes AlpieCode has made since last checkpoint", parents=[common])
109
109
 
110
+ # ── doctor ──
111
+ sub.add_parser("doctor", help="Run system health checks (CUDA, Python, network, dev tools)")
112
+
113
+ # ── explain ──
114
+ explain_p = sub.add_parser("explain", help="Explain a file, function, or codebase concept", parents=[common])
115
+ explain_p.add_argument("target", help="File path or concept to explain")
116
+
110
117
  args = parser.parse_args()
111
118
 
112
119
  if not args.command:
@@ -117,6 +124,10 @@ def main():
117
124
  interactive_init()
118
125
  return
119
126
 
127
+ if args.command == "doctor":
128
+ from .doctor import run_doctor
129
+ sys.exit(run_doctor())
130
+
120
131
  if args.command == "serve":
121
132
  _show_banner()
122
133
  try:
@@ -181,6 +192,41 @@ def main():
181
192
  github_repo=getattr(args, "github", None),
182
193
  )
183
194
 
195
+ elif args.command == "doctor":
196
+ from .doctor import run_doctor
197
+ sys.exit(run_doctor())
198
+
199
+ elif args.command == "explain":
200
+ _show_banner()
201
+ target = args.target
202
+ target_path = Path(args.workdir) / target if not Path(target).is_absolute() else Path(target)
203
+ if target_path.exists() and target_path.is_file():
204
+ content = target_path.read_text(encoding="utf-8", errors="replace")
205
+ explain_task = (
206
+ f"EXPLANATION ONLY — Do NOT make any file edits or run modifying commands.\n\n"
207
+ f"Please explain the file `{target}` in detail:\n"
208
+ f"1. Overview of its purpose and architecture role\n"
209
+ f"2. Key functions, classes, and internal logic\n"
210
+ f"3. Dependencies and connections to the rest of the project\n"
211
+ f"4. Step-by-step walkthrough of how it operates\n\n"
212
+ f"File content ({target}):\n```\n{content[:16000]}\n```"
213
+ )
214
+ else:
215
+ explain_task = (
216
+ f"EXPLANATION ONLY — Do NOT make any file edits.\n\n"
217
+ f"Explain the following codebase concept, architecture, or question in detail:\n"
218
+ f"Topic: {target}\n\n"
219
+ f"Use read_file, file_search, or list_files if needed to understand the codebase context."
220
+ )
221
+ from .agent import run_agent
222
+ run_agent(
223
+ explain_task, Path(args.workdir), cfg, verbose=True,
224
+ image_path=args.image,
225
+ video_path=getattr(args, "video", None),
226
+ url=getattr(args, "url", None),
227
+ github_repo=getattr(args, "github", None),
228
+ )
229
+
184
230
  elif args.command == "diff":
185
231
  workdir = Path(args.workdir).resolve()
186
232
  # Show git diff since the first checkpoint
@@ -0,0 +1,208 @@
1
+ """
2
+ AlpieCode Doctor — Comprehensive System Diagnostic Tool.
3
+
4
+ Checks Python, CUDA/GPU, compilers, runtime tools, network connectivity,
5
+ local/remote VLM status, and VS Code extension health.
6
+ """
7
+
8
+ import os
9
+ import sys
10
+ import time
11
+ import shutil
12
+ import socket
13
+ import subprocess
14
+ from pathlib import Path
15
+ from typing import Dict, List, Tuple
16
+ from urllib.parse import urlparse
17
+
18
+ from .config import load_config, is_server_reachable, is_internet_available
19
+
20
+
21
+ def _colorize(text: str, color: str) -> str:
22
+ colors = {
23
+ "green": "\033[92m",
24
+ "red": "\033[91m",
25
+ "yellow": "\033[93m",
26
+ "blue": "\033[94m",
27
+ "cyan": "\033[96m",
28
+ "bold": "\033[1m",
29
+ "dim": "\033[2m",
30
+ "reset": "\033[0m",
31
+ }
32
+ return f"{colors.get(color, '')}{text}{colors['reset']}"
33
+
34
+
35
+ def _check_command(cmd: str) -> Tuple[bool, str]:
36
+ """Check if a CLI binary is available and return version if possible."""
37
+ path = shutil.which(cmd)
38
+ if not path:
39
+ return False, "not installed"
40
+ try:
41
+ res = subprocess.run([cmd, "--version"], capture_output=True, text=True, timeout=3)
42
+ out = (res.stdout or res.stderr or "").strip().split("\n")[0]
43
+ return True, out[:60] if out else "installed"
44
+ except Exception:
45
+ return True, "installed"
46
+
47
+
48
+ def _check_gpu() -> Tuple[bool, str]:
49
+ """Check NVIDIA GPU and CUDA support."""
50
+ nvidia_smi = shutil.which("nvidia-smi")
51
+ if not nvidia_smi:
52
+ return False, "No NVIDIA GPU detected (CPU mode)"
53
+ try:
54
+ res = subprocess.run(
55
+ [nvidia_smi, "--query-gpu=name,memory.total", "--format=csv,noheader"],
56
+ capture_output=True,
57
+ text=True,
58
+ timeout=3,
59
+ )
60
+ if res.returncode == 0 and res.stdout.strip():
61
+ gpu_info = res.stdout.strip().split("\n")[0]
62
+ return True, f"NVIDIA GPU: {gpu_info}"
63
+ except Exception:
64
+ pass
65
+ return True, "NVIDIA GPU driver present"
66
+
67
+
68
+ def _check_remote_latency(base_url: str) -> Tuple[bool, str]:
69
+ """Measure roundtrip latency to the remote VLM server."""
70
+ if not base_url:
71
+ return False, "No base_url configured"
72
+ try:
73
+ parsed = urlparse(base_url)
74
+ host = parsed.hostname
75
+ port = parsed.port or (443 if parsed.scheme == "https" else 80)
76
+ if not host:
77
+ return False, "Invalid base_url format"
78
+
79
+ t0 = time.perf_counter()
80
+ with socket.create_connection((host, port), timeout=3.0):
81
+ elapsed_ms = (time.perf_counter() - t0) * 1000.0
82
+ return True, f"Online ({elapsed_ms:.1f}ms latency)"
83
+ except Exception as e:
84
+ return False, f"Unreachable ({e})"
85
+
86
+
87
+ def _check_vscode_extension() -> Tuple[bool, str]:
88
+ """Check if the AlpieCode VS Code extension is installed."""
89
+ code_bin = shutil.which("code") or shutil.which("code.cmd") or shutil.which("code.exe")
90
+ if not code_bin:
91
+ return True, "VS Code CLI not in PATH (extension status unknown)"
92
+ try:
93
+ res = subprocess.run([code_bin, "--list-extensions"], capture_output=True, text=True, timeout=5)
94
+ if "alpiecode" in res.stdout.lower() or "169pi.alpiecode" in res.stdout.lower():
95
+ return True, "AlpieCode extension installed in VS Code"
96
+ return False, "AlpieCode extension not detected in VS Code"
97
+ except Exception:
98
+ return True, "VS Code detected"
99
+
100
+
101
+ def run_doctor() -> int:
102
+ """Run all system diagnostic checks and print a structured report."""
103
+ print()
104
+ print(_colorize(" 🩺 AlpieCode System Health Diagnostic", "bold"))
105
+ print(_colorize(" " + "═" * 50, "dim"))
106
+ print()
107
+
108
+ total_checks = 0
109
+ passed_checks = 0
110
+
111
+ cfg = load_config()
112
+
113
+ # 1. Python Environment
114
+ print(_colorize(" 🐍 Python Environment", "cyan"))
115
+ py_ver = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
116
+ if sys.version_info >= (3, 9):
117
+ print(f" {_colorize('✅', 'green')} Python {py_ver} ({sys.executable})")
118
+ passed_checks += 1
119
+ else:
120
+ print(f" {_colorize('❌', 'red')} Python {py_ver} (Requires Python >= 3.9)")
121
+ total_checks += 1
122
+
123
+ venv_active = "VIRTUAL_ENV" in os.environ or hasattr(sys, "real_prefix") or (hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix)
124
+ if venv_active:
125
+ print(f" {_colorize('✅', 'green')} Virtual Environment active ({os.environ.get('VIRTUAL_ENV', sys.prefix)})")
126
+ passed_checks += 1
127
+ else:
128
+ print(f" {_colorize('⚠️ ', 'yellow')} No virtual environment active (using system Python)")
129
+ total_checks += 1
130
+
131
+ # 2. CUDA / Hardware Acceleration
132
+ print()
133
+ print(_colorize(" 🖥️ Hardware & GPU Acceleration", "cyan"))
134
+ has_gpu, gpu_msg = _check_gpu()
135
+ if has_gpu:
136
+ print(f" {_colorize('✅', 'green')} {gpu_msg}")
137
+ passed_checks += 1
138
+ else:
139
+ print(f" {_colorize('ℹ️ ', 'blue')} {gpu_msg}")
140
+ total_checks += 1
141
+
142
+ # 3. Network & Connectivity
143
+ print()
144
+ print(_colorize(" 🌐 Network & Remote Model API", "cyan"))
145
+ inet_ok = is_internet_available(timeout=2.0)
146
+ if inet_ok:
147
+ print(f" {_colorize('✅', 'green')} General Internet: Connected (DNS 8.8.8.8)")
148
+ passed_checks += 1
149
+ else:
150
+ print(f" {_colorize('❌', 'red')} General Internet: Offline")
151
+ total_checks += 1
152
+
153
+ remote_ok, remote_msg = _check_remote_latency(cfg.base_url)
154
+ if remote_ok:
155
+ print(f" {_colorize('✅', 'green')} Remote VLM Endpoint: {cfg.base_url} — {remote_msg}")
156
+ print(f" {_colorize('✅', 'green')} Model Target: {cfg.model}")
157
+ passed_checks += 2
158
+ else:
159
+ print(f" {_colorize('⚠️ ', 'yellow')} Remote VLM Endpoint: {cfg.base_url} — {remote_msg}")
160
+ print(f" {_colorize('ℹ️ ', 'blue')} Offline fallback ready with: {cfg.model_repo}")
161
+ passed_checks += 1
162
+ total_checks += 2
163
+
164
+ # 4. Development Compilers & Runtimes
165
+ print()
166
+ print(_colorize(" 🧰 Development Tools & Compilers", "cyan"))
167
+ tools_to_check = [
168
+ ("node", "Node.js (JavaScript/TypeScript runtime)"),
169
+ ("npm", "Node Package Manager"),
170
+ ("gcc", "GNU C Compiler"),
171
+ ("g++", "GNU C++ Compiler"),
172
+ ("git", "Git Version Control"),
173
+ ("go", "Go Programming Language (optional)"),
174
+ ("rustc", "Rust Compiler (optional)"),
175
+ ("java", "Java JDK (optional)"),
176
+ ]
177
+ for tool_name, desc in tools_to_check:
178
+ ok, msg = _check_command(tool_name)
179
+ is_optional = "optional" in desc
180
+ if ok:
181
+ print(f" {_colorize('✅', 'green')} {tool_name:8s} : {msg}")
182
+ passed_checks += 1
183
+ elif is_optional:
184
+ print(f" {_colorize('ℹ️ ', 'dim')} {tool_name:8s} : not installed (optional)")
185
+ else:
186
+ print(f" {_colorize('⚠️ ', 'yellow')} {tool_name:8s} : not installed")
187
+ total_checks += 1
188
+
189
+ # 5. VS Code Integration
190
+ print()
191
+ print(_colorize(" 📦 VS Code Extension", "cyan"))
192
+ ext_ok, ext_msg = _check_vscode_extension()
193
+ if ext_ok:
194
+ print(f" {_colorize('✅', 'green')} {ext_msg}")
195
+ passed_checks += 1
196
+ else:
197
+ print(f" {_colorize('⚠️ ', 'yellow')} {ext_msg} (run: alpiecode serve)")
198
+ total_checks += 1
199
+
200
+ # Summary
201
+ print()
202
+ print(_colorize(" " + "═" * 50, "dim"))
203
+ if passed_checks >= total_checks - 3:
204
+ print(f" {_colorize('🎉 System Health Status: EXCELLENT', 'green')} ({passed_checks}/{total_checks} checks passed)\n")
205
+ return 0
206
+ else:
207
+ print(f" {_colorize('⚠️ System Health Status: ATTENTION NEEDED', 'yellow')} ({passed_checks}/{total_checks} checks passed)\n")
208
+ return 1
index 13b805a..c508484 100644
Binary file
File without changes
File without changes