@javierfrancoleal/dsh-supervisor 1.0.49 → 1.0.50
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.
- package/dashboard.html +1 -1
- package/package.json +1 -1
- package/server.js +2 -1
package/dashboard.html
CHANGED
|
@@ -898,7 +898,7 @@ $("saveDecisions").onclick=async()=>{await api("/api/decisions",{content:$("deci
|
|
|
898
898
|
document.querySelectorAll(".tabs button, .bnav button").forEach(b=>b.onclick=()=>{document.querySelectorAll(".tabs button, .bnav button").forEach(x=>x.classList.remove("active"));b.classList.add("active");["overview","field","rules","sector","studio"].forEach(x=>$("tab-"+x).classList.add("hidden"));$("tab-"+b.dataset.tab).classList.remove("hidden");});
|
|
899
899
|
$("reportBtn").onclick=async()=>{const r=await api("/api/report",{text:$("reportText").value});if(r.error){showMsg("Error: "+r.error);return;}$("reportText").value="";showMsg(t("reportSent"));};
|
|
900
900
|
$("empFbBtn").onclick=async()=>{const r=await api("/api/feedback",{worker:me.name,role:me.role,category:$("empFbCat").value,text:$("empFbText").value});if(r.error){showMsg("Error: "+r.error);return;}$("empFbText").value="";showMsg(t("feedbackSent"));};
|
|
901
|
-
(async()=>{const dm=(/[?&]demo=([a-z]+)/.exec(location.search)||[])[1];if(dm){const r=await api("/api/demo-login",{role:dm});if(r&&r.token){token=r.token;me={name:r.name,role:r.role,label:r.label||r.name};sessionStorage.setItem("dsh-sup-token",token);sessionStorage.setItem("dsh-sup-me",JSON.stringify(me));enter();return;}}})();
|
|
901
|
+
(async()=>{const dm=(/[?&]demo=([a-z]+)/.exec(location.search)||[])[1];if(dm){const r=await api("/api/demo-login",{role:dm});if(r&&r.token){token=r.token;me={name:r.name,role:r.role,label:r.label||r.name};sessionStorage.setItem("dsh-sup-token",token);sessionStorage.setItem("dsh-sup-me",JSON.stringify(me));enter();if(/[?&]alert=1/.test(location.search)){await api("/api/demo/alert");setTimeout(pollAlerts,400);}return;}}})();
|
|
902
902
|
api("/api/setup-status").then((st)=>{if(st&&st.users===0){$("setupSection").classList.remove("hidden");$("loginUser").parentNode.style.display="none";$("loginBtn").style.display="none";$("loginPass").closest(".passwrap").style.display="none";$("loginTitle").textContent=t("setupTitle");}}).catch(()=>{});
|
|
903
903
|
const st=sessionStorage.getItem("dsh-sup-token");
|
|
904
904
|
if(st){token=st;me=JSON.parse(sessionStorage.getItem("dsh-sup-me")||"null");(async()=>{const r=await api("/api/me");if(!r||!r.name){logout();return;}enter();})();}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@javierfrancoleal/dsh-supervisor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.50",
|
|
4
4
|
"description": "The Veilleux central control plane of the J.Franco agentic workflow suite: user accounts, the live conversation flow (listen → per-person summary → confirm → orders), telemetry, and the universal sector dashboard with 10 languages. Created by J.Franco.",
|
|
5
5
|
"author": "J.Franco",
|
|
6
6
|
"license": "MIT",
|
package/server.js
CHANGED
|
@@ -59,7 +59,7 @@ const SECTOR_CLOSE = [
|
|
|
59
59
|
{ id: "close_clean", label: "Nettoyage et rangement des postes" },
|
|
60
60
|
{ id: "close_lights", label: "Lumières, chauffage et alarme" }
|
|
61
61
|
];
|
|
62
|
-
const VERSION = "1.0.
|
|
62
|
+
const VERSION = "1.0.50";
|
|
63
63
|
// Homeostasis: the daily token budget (metabolic limit). The brain rests
|
|
64
64
|
// when the budget is spent — no runaway costs.
|
|
65
65
|
const DAILY_BUDGET_USD = Number(process.env.DSH_DAILY_BUDGET_USD || 0); // 0 = unlimited: consumption is the business
|
|
@@ -420,6 +420,7 @@ async function api(req, res, pathname) {
|
|
|
420
420
|
if (pathname === "/api/studio" && req.method === "GET") { if (!auth(req)) return send(res, 401, { error: "unauthorized" }); const tk = tasksRead(); return send(res, 200, { tasks: tk.tasks.slice(-20).reverse() }); }
|
|
421
421
|
if (pathname === "/api/studio" && req.method === "POST") { const u = auth(req); if (!u) return send(res, 401, { error: "unauthorized" }); const b = await json(req); const tk = tasksRead(); const id = "t" + Date.now(); tk.tasks.push({ id, type: String(b.type || "other"), text: String(b.text || ""), by: u.name, ts: ts(), status: "pending", result: null }); tasksWrite(tk); const l = liveRead(); l.inbox = l.inbox || []; l.inbox.push({ from: u.name, kind: "studio", id, text: String(b.text || "") }); liveWrite(l); return send(res, 200, { ok: true, id }); }
|
|
422
422
|
if (pathname === "/api/studio/result" && req.method === "POST") { if (!auth(req)) return send(res, 401, { error: "unauthorized" }); const b = await json(req); const tk = tasksRead(); const it = tk.tasks.find((x) => x.id === b.id); if (!it) return send(res, 200, { ok: false }); it.result = String(b.result || ""); it.status = "done"; it.doneAt = ts(); tasksWrite(tk); return send(res, 200, { ok: true }); }
|
|
423
|
+
if (pathname === "/api/demo/alert" && req.method === "POST") { if (process.env.DSH_DEMO_MODE !== "1") return send(res, 403, { error: "demo mode disabled" }); const a = alertsRead(); a.items.push({ id: "a" + Date.now(), key: "demo-" + Date.now(), kind: "rain", pct: 85, inHour: 1, ts: ts(), status: "active", decision: null, source: "demo" }); alertsWrite(a); return send(res, 200, { ok: true }); }
|
|
423
424
|
if (pathname === "/api/demo-login" && req.method === "POST") { if (process.env.DSH_DEMO_MODE !== "1") return send(res, 403, { error: "demo mode disabled" }); const b = await json(req); const u = loadUsers(); const name = Object.keys(u).find((n) => u[n].role === String(b.role || "owner")); if (!name) return send(res, 404, { error: "no demo user for that role" }); const token = issue(name, u[name].role, u[name].label || name); return send(res, 200, { token, name, role: u[name].role, label: u[name].label || name }, true); }
|
|
424
425
|
if (pathname === "/api/alerts" && req.method === "GET") { if (!auth(req)) return send(res, 401, { error: "unauthorized" }); const a = alertsRead(); const active = a.items.find((x) => x.status === "active"); return send(res, 200, { active: active || null, last: a.items.slice(-3).reverse() }); }
|
|
425
426
|
if (pathname === "/api/alerts/decide" && req.method === "POST") { const u = auth(req); if (!u) return send(res, 401, { error: "unauthorized" }); const b = await json(req); const a = alertsRead(); const it = a.items.find((x) => x.id === b.id); if (!it || it.status !== "active") return send(res, 200, { ok: false }); it.status = "done"; it.decision = b.decision === "yes" ? "yes" : "no"; it.decidedBy = u.name; it.decidedAt = ts(); alertsWrite(a); if (b.decision === "yes") { const l = liveRead(); l.notices = l.notices || []; l.notices.push({ ts: ts(), from: u.name, text: "Pluie probable (~" + it.pct + "%) dans ~" + it.inHour + " h — préparez-vous." }); liveWrite(l); } return send(res, 200, { ok: true }); }
|