feat: deploy Codeg multi-agent workspace, Gitea hot/cold storage hub, and grill-me skill
This commit is contained in:
1 parent
c4f54203a4
commit
01a4681f98
18 files changed
+1238
-252
No files matched your search
+122
-1
@@ -268,24 +268,134 @@ def get_network_and_edge_stats() -> dict:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _codeg_call(endpoint: str, payload=None) -> object:
|
||||||
|
try:
|
||||||
|
req = urllib.request.Request(
|
||||||
|
f"http://127.0.0.1:3080/api/{endpoint}",
|
||||||
|
data=json.dumps(payload or {}).encode("utf-8"),
|
||||||
|
headers={
|
||||||
|
"Authorization": "Bearer homelab2026",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
method="POST",
|
||||||
|
)
|
||||||
|
with urllib.request.urlopen(req, timeout=2.0) as r:
|
||||||
|
return json.loads(r.read().decode("utf-8"))
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_agents_and_git_overview() -> dict:
|
||||||
|
codeg_ok, codeg_ms = check_tcp("127.0.0.1", 3080)
|
||||||
|
gitea_ok, gitea_ms = check_tcp("127.0.0.1", 3005)
|
||||||
|
|
||||||
|
assistants = _codeg_call("assistant_list") if codeg_ok else []
|
||||||
|
folders = _codeg_call("list_folders") if codeg_ok else []
|
||||||
|
conversations = _codeg_call("list_conversations") if codeg_ok else []
|
||||||
|
stats = _codeg_call("get_stats") if codeg_ok else {}
|
||||||
|
|
||||||
|
# Query local Gitea repositories
|
||||||
|
repos = []
|
||||||
|
if gitea_ok:
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen("http://127.0.0.1:3005/api/v1/repos/search?limit=10", timeout=2.0) as r:
|
||||||
|
rdata = json.loads(r.read().decode("utf-8"))
|
||||||
|
for item in rdata.get("data", []):
|
||||||
|
repos.append(
|
||||||
|
{
|
||||||
|
"name": item.get("full_name"),
|
||||||
|
"description": item.get("description", ""),
|
||||||
|
"default_branch": item.get("default_branch", "main"),
|
||||||
|
"updated_at": item.get("updated_at", ""),
|
||||||
|
"size_kb": item.get("size", 0),
|
||||||
|
"html_url": item.get("html_url", ""),
|
||||||
|
"clone_url": item.get("clone_url", ""),
|
||||||
|
"ssh_url": item.get("ssh_url", ""),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Query active tmux windows in 'agy' session
|
||||||
|
tmux_windows = []
|
||||||
|
try:
|
||||||
|
out = run_cmd("/opt/homebrew/bin/tmux list-windows -t agy -F '#{window_index}|#{window_name}|#{window_active}|#{pane_current_command}'", timeout=1.5)
|
||||||
|
for line in out.splitlines():
|
||||||
|
parts = line.split("|")
|
||||||
|
if len(parts) >= 4:
|
||||||
|
tmux_windows.append(
|
||||||
|
{
|
||||||
|
"index": parts[0],
|
||||||
|
"name": parts[1],
|
||||||
|
"active": parts[2] == "1",
|
||||||
|
"command": parts[3],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Check ZSpace NAS Git Cold Storage bundles
|
||||||
|
cold_dir = Path("/Users/ixvii0iv/nas/个人空间/Git_Cold_Storage/bundles")
|
||||||
|
cold_bundles = []
|
||||||
|
try:
|
||||||
|
if cold_dir.exists():
|
||||||
|
for f in sorted(cold_dir.glob("*.bundle")):
|
||||||
|
st = f.stat()
|
||||||
|
cold_bundles.append(
|
||||||
|
{
|
||||||
|
"name": f.name,
|
||||||
|
"size_mb": round(st.st_size / (1024 * 1024), 2),
|
||||||
|
"mtime": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(st.st_mtime)),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return {
|
||||||
|
"codeg": {
|
||||||
|
"online": codeg_ok,
|
||||||
|
"latency_ms": codeg_ms,
|
||||||
|
"version": "0.42.0",
|
||||||
|
"assistants": assistants if isinstance(assistants, list) else [],
|
||||||
|
"folders": folders if isinstance(folders, list) else [],
|
||||||
|
"conversations": conversations if isinstance(conversations, list) else [],
|
||||||
|
"stats": stats if isinstance(stats, dict) else {},
|
||||||
|
},
|
||||||
|
"gitea": {
|
||||||
|
"online": gitea_ok,
|
||||||
|
"latency_ms": gitea_ms,
|
||||||
|
"version": "28.3.0",
|
||||||
|
"hot_path": "/Users/ixvii0iv/homelab/stacks/git/data",
|
||||||
|
"cold_path": "/Users/ixvii0iv/nas/个人空间/Git_Cold_Storage",
|
||||||
|
"repos": repos,
|
||||||
|
"cold_bundles": cold_bundles,
|
||||||
|
},
|
||||||
|
"tmux_windows": tmux_windows,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def collect_telemetry() -> dict:
|
def collect_telemetry() -> dict:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
with _cache_lock:
|
with _cache_lock:
|
||||||
if _cache["data"] and (now - _cache["ts"] < 2.0):
|
if _cache["data"] and (now - _cache["ts"] < 2.0):
|
||||||
return _cache["data"]
|
return _cache["data"]
|
||||||
|
|
||||||
with ThreadPoolExecutor(max_workers=4) as pool:
|
with ThreadPoolExecutor(max_workers=6) as pool:
|
||||||
f_mini = pool.submit(get_mac_mini_stats)
|
f_mini = pool.submit(get_mac_mini_stats)
|
||||||
f_nas = pool.submit(get_nas_stats)
|
f_nas = pool.submit(get_nas_stats)
|
||||||
f_net = pool.submit(get_network_and_edge_stats)
|
f_net = pool.submit(get_network_and_edge_stats)
|
||||||
f_agy = pool.submit(check_tcp, "127.0.0.1", 7681)
|
f_agy = pool.submit(check_tcp, "127.0.0.1", 7681)
|
||||||
f_vw = pool.submit(check_tcp, "127.0.0.1", 8222)
|
f_vw = pool.submit(check_tcp, "127.0.0.1", 8222)
|
||||||
|
f_codeg = pool.submit(check_tcp, "127.0.0.1", 3080)
|
||||||
|
f_gitea = pool.submit(check_tcp, "127.0.0.1", 3005)
|
||||||
|
|
||||||
mini = f_mini.result()
|
mini = f_mini.result()
|
||||||
nas = f_nas.result()
|
nas = f_nas.result()
|
||||||
net = f_net.result()
|
net = f_net.result()
|
||||||
agy_ok, _ = f_agy.result()
|
agy_ok, _ = f_agy.result()
|
||||||
vw_ok, _ = f_vw.result()
|
vw_ok, _ = f_vw.result()
|
||||||
|
codeg_ok, _ = f_codeg.result()
|
||||||
|
gitea_ok, _ = f_gitea.result()
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
|
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
@@ -294,6 +404,8 @@ def collect_telemetry() -> dict:
|
|||||||
"network": net,
|
"network": net,
|
||||||
"services": {
|
"services": {
|
||||||
"agy": agy_ok,
|
"agy": agy_ok,
|
||||||
|
"codeg": codeg_ok,
|
||||||
|
"gitea": gitea_ok,
|
||||||
"vaultwarden": vw_ok,
|
"vaultwarden": vw_ok,
|
||||||
"nas": nas["online"],
|
"nas": nas["online"],
|
||||||
"clash": net["router_online"],
|
"clash": net["router_online"],
|
||||||
@@ -394,6 +506,11 @@ class PortalHandler(BaseHTTPRequestHandler):
|
|||||||
self._send_json(clawbot_mgr.get_public_status())
|
self._send_json(clawbot_mgr.get_public_status())
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# 3c. Agent Orchestrator & Gitea Cold/Hot Storage overview (/api/agents/overview)
|
||||||
|
if self.path.startswith("/api/agents/overview"):
|
||||||
|
self._send_json(get_agents_and_git_overview())
|
||||||
|
return
|
||||||
|
|
||||||
# 4. Serve static assets from Vite build output (dist/) if available
|
# 4. Serve static assets from Vite build output (dist/) if available
|
||||||
clean_path = self.path.split("?", 1)[0].lstrip("/")
|
clean_path = self.path.split("?", 1)[0].lstrip("/")
|
||||||
if clean_path and DIST_DIR.exists():
|
if clean_path and DIST_DIR.exists():
|
||||||
@@ -506,6 +623,10 @@ class PortalHandler(BaseHTTPRequestHandler):
|
|||||||
_cache["ts"] = 0.0
|
_cache["ts"] = 0.0
|
||||||
self._send_json({"ok": True, "message": out or "Cloudflare DDNS 已刷新"})
|
self._send_json({"ok": True, "message": out or "Cloudflare DDNS 已刷新"})
|
||||||
return
|
return
|
||||||
|
if self.path == "/api/action/sync_git_nas":
|
||||||
|
out = run_cmd("/Users/ixvii0iv/homelab/scripts/sync-git-to-nas.sh", timeout=20.0)
|
||||||
|
self._send_json({"ok": True, "message": out or "Git 热层与极空间 20TB 冷备归档已同步"})
|
||||||
|
return
|
||||||
self._send_json({"ok": False, "message": "Unknown action"}, status=404)
|
self._send_json({"ok": False, "message": "Unknown action"}, status=404)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user