replx-agent 2.0.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.
Potentially problematic release.
This version of replx-agent might be problematic. Click here for more details.
- replx_agent/__init__.py +3 -0
- replx_agent/__main__.py +5 -0
- replx_agent/commands.py +131 -0
- replx_agent/helpers/__init__.py +3 -0
- replx_agent/helpers/scanner.py +308 -0
- replx_agent/pkg/__init__.py +11 -0
- replx_agent/pkg/compiler.py +153 -0
- replx_agent/pkg/registry.py +387 -0
- replx_agent/pkg/service.py +690 -0
- replx_agent/pkg/store.py +83 -0
- replx_agent/protocol/__init__.py +11 -0
- replx_agent/protocol/repl.py +1029 -0
- replx_agent/protocol/storage.py +1018 -0
- replx_agent/rpc/__init__.py +3 -0
- replx_agent/rpc/protocol.py +220 -0
- replx_agent/server/__init__.py +3 -0
- replx_agent/server/__main__.py +4 -0
- replx_agent/server/command_dispatcher.py +49 -0
- replx_agent/server/connection_manager.py +654 -0
- replx_agent/server/core.py +1221 -0
- replx_agent/server/handlers/__init__.py +24 -0
- replx_agent/server/handlers/exec.py +553 -0
- replx_agent/server/handlers/filesystem.py +383 -0
- replx_agent/server/handlers/firmware.py +118 -0
- replx_agent/server/handlers/i2c.py +23 -0
- replx_agent/server/handlers/package.py +182 -0
- replx_agent/server/handlers/repl.py +188 -0
- replx_agent/server/handlers/session.py +205 -0
- replx_agent/server/handlers/spi.py +23 -0
- replx_agent/server/handlers/transfer.py +600 -0
- replx_agent/server/handlers/uart.py +32 -0
- replx_agent/server/session_manager.py +391 -0
- replx_agent/server/tcp.py +207 -0
- replx_agent/terminal.py +566 -0
- replx_agent/transport/__init__.py +32 -0
- replx_agent/transport/serial.py +220 -0
- replx_agent/utils/__init__.py +95 -0
- replx_agent/utils/constants.py +78 -0
- replx_agent/utils/device_info.py +183 -0
- replx_agent/utils/exceptions.py +31 -0
- replx_agent-2.0.0.dist-info/METADATA +74 -0
- replx_agent-2.0.0.dist-info/RECORD +46 -0
- replx_agent-2.0.0.dist-info/WHEEL +5 -0
- replx_agent-2.0.0.dist-info/entry_points.txt +2 -0
- replx_agent-2.0.0.dist-info/licenses/LICENSE +21 -0
- replx_agent-2.0.0.dist-info/top_level.txt +1 -0
replx_agent/pkg/store.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import base64
|
|
4
|
+
import threading
|
|
5
|
+
import urllib.request
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from replx_agent.utils.constants import HTTP_REQUEST_TIMEOUT
|
|
9
|
+
from replx_agent.utils.exceptions import PkgError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class StoreManager:
|
|
13
|
+
HOME_STORE = Path.home() / ".replx"
|
|
14
|
+
HOME_STAGING = HOME_STORE / ".staging"
|
|
15
|
+
META_NAME = "registry.json"
|
|
16
|
+
# Serializes store mutations (meta writes, clean) across agent threads.
|
|
17
|
+
LOCK = threading.RLock()
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def ensure_home_store():
|
|
21
|
+
StoreManager.HOME_STORE.mkdir(parents=True, exist_ok=True)
|
|
22
|
+
(StoreManager.HOME_STORE / "core").mkdir(exist_ok=True)
|
|
23
|
+
(StoreManager.HOME_STORE / "device").mkdir(exist_ok=True)
|
|
24
|
+
StoreManager.HOME_STAGING.mkdir(parents=True, exist_ok=True)
|
|
25
|
+
|
|
26
|
+
@staticmethod
|
|
27
|
+
def pkg_root() -> str:
|
|
28
|
+
StoreManager.ensure_home_store()
|
|
29
|
+
return str(StoreManager.HOME_STORE)
|
|
30
|
+
|
|
31
|
+
@staticmethod
|
|
32
|
+
def local_meta_path() -> str:
|
|
33
|
+
return os.path.join(StoreManager.pkg_root(), StoreManager.META_NAME)
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def gh_headers() -> dict:
|
|
37
|
+
hdrs = {"User-Agent": "replx"}
|
|
38
|
+
tok = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
|
|
39
|
+
if tok:
|
|
40
|
+
hdrs["Authorization"] = f"******"
|
|
41
|
+
return hdrs
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
def load_local_meta() -> dict:
|
|
45
|
+
p = StoreManager.local_meta_path()
|
|
46
|
+
if not os.path.exists(p):
|
|
47
|
+
return {"targets": {}, "items": {}}
|
|
48
|
+
try:
|
|
49
|
+
with open(p, "r", encoding="utf-8") as f:
|
|
50
|
+
return json.load(f)
|
|
51
|
+
except Exception:
|
|
52
|
+
return {"targets": {}, "items": {}}
|
|
53
|
+
|
|
54
|
+
@staticmethod
|
|
55
|
+
def save_local_meta(meta: dict):
|
|
56
|
+
p = StoreManager.local_meta_path()
|
|
57
|
+
tmp = p + ".tmp"
|
|
58
|
+
os.makedirs(os.path.dirname(p), exist_ok=True)
|
|
59
|
+
with open(tmp, "w", encoding="utf-8") as f:
|
|
60
|
+
json.dump(meta, f, ensure_ascii=False, indent=2)
|
|
61
|
+
os.replace(tmp, p)
|
|
62
|
+
|
|
63
|
+
@staticmethod
|
|
64
|
+
def load_remote_meta(owner: str, repo: str, ref_: str) -> dict:
|
|
65
|
+
url = f"https://api.github.com/repos/{owner}/{repo}/contents/{StoreManager.META_NAME}?ref={ref_}"
|
|
66
|
+
req = urllib.request.Request(url, headers=StoreManager.gh_headers())
|
|
67
|
+
with urllib.request.urlopen(req, timeout=HTTP_REQUEST_TIMEOUT) as r:
|
|
68
|
+
data = json.load(r)
|
|
69
|
+
b64 = (data.get("content") or "").replace("\n", "")
|
|
70
|
+
if not b64:
|
|
71
|
+
raise PkgError("Remote meta has no content.")
|
|
72
|
+
txt = base64.b64decode(b64.encode("utf-8")).decode("utf-8")
|
|
73
|
+
return json.loads(txt)
|
|
74
|
+
|
|
75
|
+
@staticmethod
|
|
76
|
+
def refresh_meta_if_online(owner: str, repo: str, ref_: str) -> bool:
|
|
77
|
+
try:
|
|
78
|
+
remote = StoreManager.load_remote_meta(owner, repo, ref_)
|
|
79
|
+
with StoreManager.LOCK:
|
|
80
|
+
StoreManager.save_local_meta(remote)
|
|
81
|
+
return True
|
|
82
|
+
except Exception:
|
|
83
|
+
return False
|