@javierfrancoleal/dsh-supervisor 1.0.24 → 1.0.26

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 CHANGED
@@ -7,8 +7,8 @@
7
7
  <title>Le Veilleux — Dashboard</title>
8
8
  <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='16' fill='%234D6BFE'/%3E%3Cpath d='M32 16 C 15 16, 8.5 25.5, 8.5 32 C 8.5 38.5, 15 48, 32 48 C 49 48, 55.5 38.5, 55.5 32 C 55.5 25.5, 49 16, 32 16 Z' fill='none' stroke='%23fff' stroke-width='4.5'/%3E%3Cpath d='M32 23.5 C 36.6 28.2, 38.6 31.4, 38.6 34.8 A 6.6 6.6 0 1 1 25.4 34.8 C 25.4 31.4, 27.4 28.2, 32 23.5 Z' fill='%23FACC15'/%3E%3C/svg%3E">
9
9
  <style>
10
- :root{--blue:#4D6BFE;--green:#22c55e;--amber:#facc15;--red:#ef4444;--ink:#101828;--muted:#667085;--bg:#f6f7fb;--card:#fff;--card2:var(--card2);--line:var(--line);--line2:var(--line2)}
11
- body.dark{--ink:#e6ecf7;--muted:#94a3b8;--bg:#0b1220;--card:#141f31;--card2:#18253a;--line:#26334d;--line2:#26334d}
10
+ :root{--blue:#4D6BFE;--violet:#7c5cff;--green:#22c55e;--amber:#facc15;--red:#ef4444;--ink:#101828;--muted:#667085;--bg:#eef2ff;--card:rgba(255,255,255,.78);--card2:rgba(255,255,255,.62);--line:rgba(15,23,42,.10);--line2:rgba(15,23,42,.06)}
11
+ body.dark{background:linear-gradient(165deg,#0b1220 0%,#141f31 50%,#1e1b4b 100%);background-attachment:fixed;--ink:#e6ecf7;--muted:#94a3b8;--bg:#0b1220;--card:rgba(20,31,49,.8);--card2:rgba(24,37,58,.62);--line:rgba(148,163,184,.16);--line2:rgba(148,163,184,.10)}
12
12
  .anim{animation:slidein .28s ease}
13
13
  @keyframes slidein{from{opacity:0;transform:translateX(26px)}to{opacity:1;transform:none}}
14
14
  .empty{text-align:center;padding:26px 12px;color:var(--muted);font-size:14px;border:1px dashed var(--line);border-radius:14px}
@@ -52,22 +52,22 @@ body.dark #loginView{background:rgba(20,31,49,.93)}
52
52
  input:focus,select:focus,textarea:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(77,107,254,.18)}
53
53
  @media(max-width:560px){.bnav{display:flex}.tabs{display:none}body{padding-bottom:70px}button,.btn,.pill,.confirmBtn{min-height:44px}}
54
54
  *{box-sizing:border-box}
55
- body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;background:var(--bg);color:var(--ink);-webkit-tap-highlight-color:transparent}
56
- header{background:var(--blue);color:#fff;padding:12px 16px;display:flex;justify-content:space-between;align-items:center;gap:8px;flex-wrap:wrap}
55
+ body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;background:linear-gradient(165deg,#e8edff 0%,#f6f7fb 45%,#fdf1f8 100%);background-attachment:fixed;color:var(--ink);-webkit-tap-highlight-color:transparent}
56
+ header{background:linear-gradient(135deg,#4D6BFE,#7c5cff);box-shadow:0 4px 18px rgba(77,107,254,.28);color:#fff;padding:12px 16px;display:flex;justify-content:space-between;align-items:center;gap:8px;flex-wrap:wrap}
57
57
  header h1{margin:0;font-size:18px}
58
58
  header .who{font-size:13px;opacity:.9}
59
59
  button{font-family:inherit;cursor:pointer}
60
- .btn{border:none;border-radius:12px;padding:12px 16px;font-size:15px;font-weight:600;color:#fff;background:var(--blue)}
60
+ .btn{border:none;border-radius:12px;padding:12px 16px;font-size:15px;font-weight:600;color:#fff;background:linear-gradient(135deg,#4D6BFE,#7c5cff);box-shadow:0 4px 12px rgba(77,107,254,.22)}
61
61
  .btn.gray{background:var(--line2);color:var(--ink)}
62
62
  .btn.small{padding:8px 12px;font-size:13px}
63
63
  main{max-width:960px;margin:0 auto;padding:14px}
64
- .card{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:16px;margin:12px 0}
64
+ .card{background:var(--card);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid var(--line);border-radius:20px;box-shadow:0 8px 24px rgba(15,23,42,.06);padding:16px;margin:12px 0}
65
65
  .card h2{margin:0 0 10px;font-size:16px}
66
66
  input,select,textarea{width:100%;border:1px solid var(--line);border-radius:12px;padding:12px;font-size:16px;margin-bottom:8px;font-family:inherit;background:var(--card)}
67
67
  textarea{resize:vertical;min-height:80px}
68
68
  pre{background:#0f172a;color:#d7e3f4;border-radius:12px;padding:12px;font-size:12.5px;overflow:auto;max-height:320px;white-space:pre-wrap;margin:0}
69
69
  .metrics{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:10px}
70
- .metric{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:12px;text-align:center}
70
+ .metric{background:var(--card);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid var(--line);border-radius:16px;box-shadow:0 4px 14px rgba(15,23,42,.05);padding:12px;text-align:center}
71
71
  .metric .v{font-size:26px;font-weight:700;color:var(--blue)}
72
72
  .metric .l{font-size:12px;color:var(--muted);margin-top:2px}
73
73
  .tabs{display:flex;gap:8px;flex-wrap:wrap;margin:12px 0}
@@ -142,7 +142,7 @@ td,th{border-bottom:1px solid var(--line);padding:9px 6px;text-align:left}
142
142
  button{transition:transform .12s ease}
143
143
  button:active{transform:scale(.97)}
144
144
  button:focus-visible,.pill:focus-visible,input:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
145
- body.wall{background:#0b1220}
145
+ body.wall{background:linear-gradient(165deg,#0b1220 0%,#131c30 60%,#1e1b4b 100%);background-attachment:fixed}
146
146
  body.wall pre{max-height:40vh}
147
147
  @media (max-width:560px){header h1{font-size:15px}.listen{font-size:24px;padding:26px 12px}input,select,textarea,button{font-size:16px}}
148
148
  </style>
@@ -350,7 +350,7 @@ body.wall pre{max-height:40vh}
350
350
  <div id="toast" class="toast"></div>
351
351
  <div id="msg" class="note" style="text-align:center"></div>
352
352
  </main>
353
- <footer class="foot"><div class="langs" id="footLangs"></div><div class="copyr">Suite J.Franco · open source (MIT) · autor J.Franco</div></footer>
353
+ <footer class="foot"><div class="langs" id="footLangs"></div><div class="copyr">Le Veilleux · open source (MIT) · autor J.Franco</div><div class="copyr" id="verBadge" style="opacity:.75;margin-top:2px"></div></footer>
354
354
  <script>
355
355
  "use strict";
356
356
  const LANG={es:"ES",en:"EN",fr:"FR",de:"DE",it:"IT",pt:"PT",zh:"中文",ja:"日本語",ko:"한국어",ar:"العربية"};
@@ -436,6 +436,7 @@ async function loadRegister(){
436
436
  renderRegSales(r);
437
437
  }
438
438
  if(me&&me.role==="employee"){$("regCount").textContent=(r.sales||[]).length+" "+t("salesToday");}
439
+ try{api("/api/health").then(hp=>{if(hp&&hp.version)$("verBadge").textContent="supervisor v"+hp.version+" · app 0.1.0 · dsh "+((hp.workers!==undefined)?"":"")+"runtime";});}catch(e){}
439
440
  }
440
441
  function renderRegSales(r){
441
442
  const q=($("regSearch").value||"").toLowerCase();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@javierfrancoleal/dsh-supervisor",
3
- "version": "1.0.24",
3
+ "version": "1.0.26",
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
@@ -44,6 +44,7 @@ const LIVE_FILE = path.join(DATA_DIR, "live.json");
44
44
  const SECTOR_FILE = path.join(DATA_DIR, "sector.json");
45
45
  const REG_FILE = path.join(DATA_DIR, "register.json");
46
46
  const PRICE_PER_MILLION = Number(process.env.DSH_PRICE_PER_MILLION || 0.28);
47
+ const VERSION = "1.0.25";
47
48
  // Homeostasis: the daily token budget (metabolic limit). The brain rests
48
49
  // when the budget is spent — no runaway costs.
49
50
  const DAILY_BUDGET_USD = Number(process.env.DSH_DAILY_BUDGET_USD || 0); // 0 = unlimited: consumption is the business
@@ -384,7 +385,7 @@ async function api(req, res, pathname) {
384
385
  }
385
386
  if (pathname === "/api/health" && req.method === "GET") {
386
387
  const m = metrics();
387
- return send(res, 200, { ok: true, uptime: Math.round(process.uptime()), workers: m.workers, reports: m.reports, budgetUsd: DAILY_BUDGET_USD, spentTodayUsd: todayCostUsd(), budgetPct: DAILY_BUDGET_USD > 0 ? Math.round((todayCostUsd() / DAILY_BUDGET_USD) * 100) : 0 }, true);
388
+ return send(res, 200, { ok: true, version: VERSION, uptime: Math.round(process.uptime()), workers: m.workers, reports: m.reports, budgetUsd: DAILY_BUDGET_USD, spentTodayUsd: todayCostUsd(), budgetPct: DAILY_BUDGET_USD > 0 ? Math.round((todayCostUsd() / DAILY_BUDGET_USD) * 100) : 0 }, true);
388
389
  }
389
390
  if (pathname === "/api/sector" && req.method === "GET") {
390
391
  try { return send(res, 200, JSON.parse(fs.readFileSync(SECTOR_FILE, "utf8"))); }