somratpro commited on
Commit
ea9c8a5
·
1 Parent(s): d9dfa01

feat: add Hugging Face backup configuration and support for global app routing

Browse files
Files changed (2) hide show
  1. health-server.js +25 -15
  2. workspace-sync.py +6 -0
health-server.js CHANGED
@@ -13,11 +13,14 @@ const SPACE_HOST = process.env.SPACE_HOST || "";
13
  const TELEGRAM_ENABLED = !!process.env.TELEGRAM_BOT_TOKEN;
14
  const WHATSAPP_ENABLED = /^true$/i.test(process.env.WHATSAPP_ENABLED || "");
15
  const WHATSAPP_STATUS_FILE = "/tmp/huggingclaw-wa-status.json";
 
 
16
  const DASHBOARD_BASE = "/dashboard";
17
  const DASHBOARD_STATUS_PATH = `${DASHBOARD_BASE}/status`;
18
  const DASHBOARD_HEALTH_PATH = `${DASHBOARD_BASE}/health`;
19
  const DASHBOARD_UPTIMEROBOT_PATH = `${DASHBOARD_BASE}/uptimerobot/setup`;
20
  const DASHBOARD_APP_BASE = `${DASHBOARD_BASE}/app`;
 
21
 
22
  function parseRequestUrl(url) {
23
  try {
@@ -36,10 +39,11 @@ function isDashboardScopedPath(pathname, suffix) {
36
  }
37
 
38
  function isDashboardAppRoute(pathname) {
39
- return (
40
- pathname === DASHBOARD_APP_BASE ||
41
- pathname.startsWith(`${DASHBOARD_APP_BASE}/`)
42
- );
 
43
  }
44
 
45
  function isLocalRoute(pathname) {
@@ -59,6 +63,10 @@ function stripDashboardAppPrefix(path) {
59
  if (path.startsWith(`${DASHBOARD_APP_BASE}/`)) {
60
  return path.slice(DASHBOARD_APP_BASE.length) || "/";
61
  }
 
 
 
 
62
  return path;
63
  }
64
 
@@ -89,6 +97,12 @@ function readSyncStatus() {
89
  return JSON.parse(fs.readFileSync("/tmp/sync-status.json", "utf8"));
90
  }
91
  } catch {}
 
 
 
 
 
 
92
  return { status: "unknown", message: "No sync data yet" };
93
  }
94
 
@@ -142,9 +156,7 @@ function renderSyncBadge(syncData) {
142
  }
143
 
144
  function renderDashboard(initialData) {
145
- const controlUiHref = SPACE_HOST
146
- ? `https://${SPACE_HOST}`
147
- : `${DASHBOARD_APP_BASE}/`;
148
  return `
149
  <!DOCTYPE html>
150
  <html lang="en">
@@ -504,11 +516,11 @@ function renderDashboard(initialData) {
504
  </div>
505
  <div class="stat-card">
506
  <span class="stat-label">WhatsApp</span>
507
- <span id="wa-status">${renderChannelBadge(initialData.whatsapp, "Ready to pair")}</span>
508
  </div>
509
  <div class="stat-card">
510
  <span class="stat-label">Telegram</span>
511
- <span id="tg-status">${renderChannelBadge(initialData.telegram, "Configured")}</span>
512
  </div>
513
  <a href="${controlUiHref}" id="control-ui-link" class="stat-btn">Open Control UI</a>
514
  </div>
@@ -692,6 +704,7 @@ function renderDashboard(initialData) {
692
  updateStats();
693
  setInterval(updateStats, 10000);
694
  restoreMonitorUiState();
 
695
  document.getElementById('uptimerobot-btn').addEventListener('click', setupUptimeRobot);
696
  document.getElementById('uptimerobot-toggle').addEventListener('click', toggleMonitorSetup);
697
  </script>
@@ -939,10 +952,7 @@ const server = http.createServer((req, res) => {
939
  return;
940
  }
941
 
942
- if (
943
- pathname === "/uptimerobot/setup" ||
944
- pathname === DASHBOARD_UPTIMEROBOT_PATH
945
- ) {
946
  if (req.method !== "POST") {
947
  res.writeHead(405, { "Content-Type": "application/json" });
948
  res.end(JSON.stringify({ message: "Method not allowed" }));
@@ -1001,7 +1011,7 @@ const server = http.createServer((req, res) => {
1001
  return;
1002
  }
1003
 
1004
- if (isDashboardAppRoute(pathname)) {
1005
  const proxyPath =
1006
  stripDashboardAppPrefix(pathname) + (parsedUrl.search || "");
1007
  proxyHttp(req, res, proxyPath);
@@ -1018,7 +1028,7 @@ server.on("upgrade", (req, socket, head) => {
1018
  return;
1019
  }
1020
 
1021
- if (isDashboardAppRoute(pathname)) {
1022
  const parsedUrl = parseRequestUrl(req.url || "/");
1023
  const proxyPath =
1024
  stripDashboardAppPrefix(pathname) + (parsedUrl.search || "");
 
13
  const TELEGRAM_ENABLED = !!process.env.TELEGRAM_BOT_TOKEN;
14
  const WHATSAPP_ENABLED = /^true$/i.test(process.env.WHATSAPP_ENABLED || "");
15
  const WHATSAPP_STATUS_FILE = "/tmp/huggingclaw-wa-status.json";
16
+ const HF_BACKUP_ENABLED = !!(process.env.HF_USERNAME && process.env.HF_TOKEN);
17
+ const SYNC_INTERVAL = process.env.SYNC_INTERVAL || "600";
18
  const DASHBOARD_BASE = "/dashboard";
19
  const DASHBOARD_STATUS_PATH = `${DASHBOARD_BASE}/status`;
20
  const DASHBOARD_HEALTH_PATH = `${DASHBOARD_BASE}/health`;
21
  const DASHBOARD_UPTIMEROBOT_PATH = `${DASHBOARD_BASE}/uptimerobot/setup`;
22
  const DASHBOARD_APP_BASE = `${DASHBOARD_BASE}/app`;
23
+ const APP_BASE = "/app";
24
 
25
  function parseRequestUrl(url) {
26
  try {
 
39
  }
40
 
41
  function isDashboardAppRoute(pathname) {
42
+ return pathname === DASHBOARD_APP_BASE || pathname.startsWith(`${DASHBOARD_APP_BASE}/`);
43
+ }
44
+
45
+ function isAppRoute(pathname) {
46
+ return pathname === APP_BASE || pathname.startsWith(`${APP_BASE}/`);
47
  }
48
 
49
  function isLocalRoute(pathname) {
 
63
  if (path.startsWith(`${DASHBOARD_APP_BASE}/`)) {
64
  return path.slice(DASHBOARD_APP_BASE.length) || "/";
65
  }
66
+ if (path === APP_BASE) return "/";
67
+ if (path.startsWith(`${APP_BASE}/`)) {
68
+ return path.slice(APP_BASE.length) || "/";
69
+ }
70
  return path;
71
  }
72
 
 
97
  return JSON.parse(fs.readFileSync("/tmp/sync-status.json", "utf8"));
98
  }
99
  } catch {}
100
+ if (HF_BACKUP_ENABLED) {
101
+ return {
102
+ status: "configured",
103
+ message: `Backup is enabled. Waiting for the next sync window (${SYNC_INTERVAL}s).`,
104
+ };
105
+ }
106
  return { status: "unknown", message: "No sync data yet" };
107
  }
108
 
 
156
  }
157
 
158
  function renderDashboard(initialData) {
159
+ const controlUiHref = `${DASHBOARD_APP_BASE}/`;
 
 
160
  return `
161
  <!DOCTYPE html>
162
  <html lang="en">
 
516
  </div>
517
  <div class="stat-card">
518
  <span class="stat-label">WhatsApp</span>
519
+ <span id="wa-status">${renderChannelBadge(initialData.whatsapp, 'Ready to pair')}</span>
520
  </div>
521
  <div class="stat-card">
522
  <span class="stat-label">Telegram</span>
523
+ <span id="tg-status">${renderChannelBadge(initialData.telegram, 'Configured')}</span>
524
  </div>
525
  <a href="${controlUiHref}" id="control-ui-link" class="stat-btn">Open Control UI</a>
526
  </div>
 
704
  updateStats();
705
  setInterval(updateStats, 10000);
706
  restoreMonitorUiState();
707
+ document.getElementById('control-ui-link').setAttribute('href', getDashboardBase() + '/app/');
708
  document.getElementById('uptimerobot-btn').addEventListener('click', setupUptimeRobot);
709
  document.getElementById('uptimerobot-toggle').addEventListener('click', toggleMonitorSetup);
710
  </script>
 
952
  return;
953
  }
954
 
955
+ if (pathname === "/uptimerobot/setup" || pathname === DASHBOARD_UPTIMEROBOT_PATH) {
 
 
 
956
  if (req.method !== "POST") {
957
  res.writeHead(405, { "Content-Type": "application/json" });
958
  res.end(JSON.stringify({ message: "Method not allowed" }));
 
1011
  return;
1012
  }
1013
 
1014
+ if (isDashboardAppRoute(pathname) || isAppRoute(pathname)) {
1015
  const proxyPath =
1016
  stripDashboardAppPrefix(pathname) + (parsedUrl.search || "");
1017
  proxyHttp(req, res, proxyPath);
 
1028
  return;
1029
  }
1030
 
1031
+ if (isDashboardAppRoute(pathname) || isAppRoute(pathname)) {
1032
  const parsedUrl = parseRequestUrl(req.url || "/");
1033
  const proxyPath =
1034
  stripDashboardAppPrefix(pathname) + (parsedUrl.search || "");
workspace-sync.py CHANGED
@@ -195,6 +195,12 @@ def main():
195
  print("📁 Workspace sync: no git repo and no HF credentials, skipping.")
196
  return
197
 
 
 
 
 
 
 
198
  # Give the gateway a short head start before the first sync probe.
199
  time.sleep(INITIAL_DELAY)
200
 
 
195
  print("📁 Workspace sync: no git repo and no HF credentials, skipping.")
196
  return
197
 
198
+ # Give the gateway a short head start before the first sync probe.
199
+ if use_hf_hub:
200
+ write_sync_status("configured", f"Backup enabled. Waiting for next sync in {INTERVAL}s.")
201
+ else:
202
+ write_sync_status("configured", f"Git sync enabled. Waiting for next sync in {INTERVAL}s.")
203
+
204
  # Give the gateway a short head start before the first sync probe.
205
  time.sleep(INITIAL_DELAY)
206