alpiecode 0.6.0__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.
codeagent/updater.py ADDED
@@ -0,0 +1,126 @@
1
+ """
2
+ Auto-updater module for AlpieCode.
3
+
4
+ Checks GitHub repo (https://api.github.com/repos/169Pi/AlpieCode/commits/main)
5
+ and automatically updates AlpieCode in the background if a newer commit exists.
6
+
7
+ Updates are installed silently via background thread so CLI startup is instant.
8
+ The updated code takes effect on the NEXT run.
9
+ """
10
+
11
+ import json
12
+ import os
13
+ import subprocess
14
+ import sys
15
+ import time
16
+ import urllib.request
17
+ from pathlib import Path
18
+
19
+ import threading
20
+
21
+ CACHE_FILE = Path.home() / ".alpiecode" / "update_cache.json"
22
+ CHECK_INTERVAL_SECONDS = 1800 # Check every 30 minutes
23
+
24
+
25
+ def _get_cache() -> dict:
26
+ """Read update cache data."""
27
+ if CACHE_FILE.exists():
28
+ try:
29
+ return json.loads(CACHE_FILE.read_text())
30
+ except Exception:
31
+ pass
32
+ return {}
33
+
34
+
35
+ def _save_cache(sha: str, updated: bool = False) -> None:
36
+ """Save last checked commit SHA and timestamp."""
37
+ try:
38
+ CACHE_FILE.parent.mkdir(parents=True, exist_ok=True)
39
+ CACHE_FILE.write_text(json.dumps({
40
+ "sha": sha,
41
+ "timestamp": time.time(),
42
+ "updated": updated,
43
+ }))
44
+ except Exception:
45
+ pass
46
+
47
+
48
+ def _check_pending_update_notice() -> None:
49
+ """Print a notice if an update was installed in a previous run."""
50
+ cache = _get_cache()
51
+ if cache.get("updated"):
52
+ short_sha = cache.get("sha", "")[:7]
53
+ print(f" ✅ AlpieCode auto-updated to latest ({short_sha})")
54
+ # Clear the flag so we don't show it again
55
+ _save_cache(cache.get("sha", ""), updated=False)
56
+
57
+
58
+
59
+ def _bg_update_worker(quiet: bool = False) -> None:
60
+ """Background worker: check GitHub for new commits and auto-upgrade."""
61
+ try:
62
+ url = "https://api.github.com/repos/169Pi/AlpieCode/commits/main"
63
+ req = urllib.request.Request(url, headers={"User-Agent": "AlpieCode-Updater"})
64
+ with urllib.request.urlopen(req, timeout=3.0) as resp:
65
+ data = json.loads(resp.read().decode("utf-8"))
66
+ latest_sha = data.get("sha", "")
67
+ except Exception:
68
+ return
69
+
70
+ cache = _get_cache()
71
+ current_sha = cache.get("sha", "")
72
+
73
+ if latest_sha and latest_sha != current_sha:
74
+ repo_url = f"git+https://github.com/169Pi/AlpieCode.git@main"
75
+
76
+ # Try uv first (faster), fall back to pip
77
+ cmd = ["uv", "pip", "install", "--upgrade", "--no-cache", "--quiet", repo_url]
78
+ try:
79
+ res = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
80
+ if res.returncode != 0:
81
+ cmd = [sys.executable, "-m", "pip", "install", "--upgrade",
82
+ "--no-cache-dir", "--quiet", repo_url]
83
+ subprocess.run(cmd, capture_output=True, text=True, timeout=120)
84
+ except Exception:
85
+ pass
86
+
87
+ # Also ensure llama-cpp-python is installed (pre-compiled wheel)
88
+ try:
89
+ import llama_cpp # noqa: F401
90
+ except ImportError:
91
+ try:
92
+ from .local_model import _ensure_llama_cpp
93
+ _ensure_llama_cpp()
94
+ except Exception:
95
+ pass
96
+
97
+ _save_cache(latest_sha, updated=True)
98
+ else:
99
+ # No update needed, just refresh timestamp
100
+ _save_cache(latest_sha or current_sha, updated=False)
101
+
102
+
103
+ def auto_update(quiet: bool = False) -> bool:
104
+ """
105
+ Spawns a non-blocking background thread to check and update AlpieCode.
106
+ Adds zero latency to CLI startup (< 10ms).
107
+
108
+ Also prints a one-time notice if a previous update was installed.
109
+ """
110
+ if os.environ.get("ALPIECODE_NO_UPDATE") == "1":
111
+ return False
112
+
113
+ # Show notice if last run installed an update
114
+ if not quiet:
115
+ _check_pending_update_notice()
116
+
117
+ # Check cache interval — don't spam GitHub API
118
+ cache = _get_cache()
119
+ last_check = cache.get("timestamp", 0)
120
+ if time.time() - last_check < CHECK_INTERVAL_SECONDS:
121
+ return False
122
+
123
+ # Launch background thread so startup is INSTANT
124
+ thread = threading.Thread(target=_bg_update_worker, args=(quiet,), daemon=True)
125
+ thread.start()
126
+ return True