@enigmax/dashboard 0.1.25 → 0.1.27

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.
Files changed (2) hide show
  1. package/assets/index.html +33 -10
  2. package/package.json +1 -1
package/assets/index.html CHANGED
@@ -215,11 +215,16 @@
215
215
  .btn-danger.icon { display: inline-flex; align-items: center; justify-content: center; padding: 6px 9px; }
216
216
  .btn-danger.icon:hover { color: var(--bad); border-color: var(--bad); }
217
217
  .btn-danger svg { width: 15px; height: 15px; display: block; }
218
- /* Per-agent skill toggles: one pill per app (Claude Code, Codex, OpenCode), green when the skill is on for it. */
218
+ /* Per-agent skill toggles: one pill per app (the app's icon), green when the skill is on for it; the app name is the tooltip. */
219
219
  .set-agents { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
220
- .achip { font-family: var(--mono); font-size: 11px; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--border); background: var(--surface2); color: var(--muted); cursor: pointer; text-decoration: none; transition: color .15s, background .15s, border-color .15s; }
220
+ .achip { display: inline-flex; align-items: center; justify-content: center; padding: 5px 8px; border-radius: 999px; border: 1px solid var(--border); background: var(--surface2); color: var(--muted); cursor: pointer; text-decoration: none; transition: color .15s, background .15s, border-color .15s; }
221
221
  .achip:hover { border-color: #2f3744; color: var(--text); }
222
- .achip.on { background: var(--good); color: #06210f; border-color: var(--good); font-weight: 600; }
222
+ .achip.on { background: var(--good); color: #06210f; border-color: var(--good); }
223
+ .achip svg { width: 14px; height: 14px; display: block; }
224
+ /* Inline app icons in the "where deployed" tag (static, name in tooltip). */
225
+ .aicons { display: inline-flex; gap: 5px; align-items: center; vertical-align: middle; }
226
+ .aicon { display: inline-flex; align-items: center; color: var(--muted); }
227
+ .aicon svg { width: 14px; height: 14px; display: block; }
223
228
  /* List settings (guard block/allow globs, custom secret patterns): chips + add input. A list row spans the full grid width. */
224
229
  .set-row.list { grid-column: 1 / -1; align-items: stretch; flex-direction: column; }
225
230
  .lchips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
@@ -359,7 +364,7 @@
359
364
  <div class="panel-head">
360
365
  <h2>Enigma Systems <small>what's active - configuration, not savings</small></h2>
361
366
  <div class="ctrls">
362
- <button id="refreshBtn" type="button" class="toggle">Refresh</button>
367
+ <button id="refreshBtn" type="button" class="iconbtn" title="Refresh" aria-label="Refresh"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M23 4v6h-6"/><path d="M1 20v-6h6"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg></button>
363
368
  <button id="fixPathBtn" type="button" class="toggle">Fix tool paths</button>
364
369
  <button id="updateBtn" type="button" class="toggle on">Check &amp; update</button>
365
370
  </div>
@@ -449,7 +454,7 @@
449
454
  </div>
450
455
  <div class="panel" id="usagePanel" style="display:none">
451
456
  <h2 style="margin:0 0 4px">Usage limits <small>same windows Claude Code shows</small></h2>
452
- <div class="sub" style="margin-bottom:12px">Cards marked <span class="tag meas">live</span> show the <b>real % and reset</b> Anthropic reports (the same as Claude's own UI), captured by the local proxy from your <code>enigma claude</code> traffic - no plan limit needed. Until the proxy has seen a request, the card falls back to tokens used, or a % against a plan limit you set (on the card, or <code>enigma config plan-weekly-limit &lt;tokens&gt;</code>). Per-model live data appears only when Anthropic sends it.</div>
457
+ <div class="sub" style="margin-bottom:12px">Cards marked <span class="tag meas">live</span> show the <b>real % and reset</b> Anthropic reports (the same as Claude's own UI). Turn on <code>enigma config usage-api on</code> to fetch them with your local Claude Code login - no proxy or plan limit needed. (The proxy also captures them from <code>enigma claude</code> traffic.) Until live data lands, the card falls back to tokens used, or a % against a plan limit you set (on the card, or <code>enigma config plan-weekly-limit &lt;tokens&gt;</code>). Per-model live data appears only when Anthropic sends it.</div>
453
458
  <div id="uWindows"></div>
454
459
  <div class="grid" style="margin-bottom:16px">
455
460
  <div class="card"><div class="label">Est. Cost</div><div id="uCost" class="value accent">-</div><div class="foot">All sessions, per-model pricing</div></div>
@@ -1772,7 +1777,8 @@ export {
1772
1777
  $("uBlockBar").style.width = pct + "%";
1773
1778
  $("uBlockState").textContent = b.active ? "active" : "window elapsed";
1774
1779
  const remMin = Math.max(0, Math.round((b.endsAt - now) / 60000));
1775
- $("uBlockTime").textContent = b.active ? (remMin + " min left") : "ended";
1780
+ const remLabel = remMin >= 60 ? Math.floor(remMin / 60) + "h " + (remMin % 60) + "m left" : remMin + "m left";
1781
+ $("uBlockTime").textContent = b.active ? remLabel : "ended";
1776
1782
  $("uBlockTokens").textContent = fmt(b.tokens || 0);
1777
1783
  $("uBlockCost").textContent = fmtUsd(b.cost || 0);
1778
1784
  $("uBlockBurn").textContent = fmt(Math.round(b.burnRatePerMin || 0)) + " tok/min";
@@ -2328,9 +2334,26 @@ export {
2328
2334
  function refreshAll(force) { poll(force); if (onSavings()) loadSystems(force); }
2329
2335
 
2330
2336
  // --- skills subpage (lists enigma + external skills over /api/skills) ---
2337
+ // App logos (Claude, OpenAI/Codex, OpenCode), recoloured to currentColor so a chip's
2338
+ // on/off colour applies and they always contrast. The app name is shown as the tooltip.
2339
+ const AGENT_ICONS = {
2340
+ claude: '<svg viewBox="0 0 100 100" fill="currentColor" aria-hidden="true"><path d="m19.6 66.5 19.7-11 .3-1-.3-.5h-1l-3.3-.2-11.2-.3L14 53l-9.5-.5-2.4-.5L0 49l.2-1.5 2-1.3 2.9.2 6.3.5 9.5.6 6.9.4L38 49.1h1.6l.2-.7-.5-.4-.4-.4L29 41l-10.6-7-5.6-4.1-3-2-1.5-2-.6-4.2 2.7-3 3.7.3.9.2 3.7 2.9 8 6.1L37 36l1.5 1.2.6-.4.1-.3-.7-1.1L33 25l-6-10.4-2.7-4.3-.7-2.6c-.3-1-.4-2-.4-3l3-4.2L28 0l4.2.6L33.8 2l2.6 6 4.1 9.3L47 29.9l2 3.8 1 3.4.3 1h.7v-.5l.5-7.2 1-8.7 1-11.2.3-3.2 1.6-3.8 3-2L61 2.6l2 2.9-.3 1.8-1.1 7.7L59 27.1l-1.5 8.2h.9l1-1.1 4.1-5.4 6.9-8.6 3-3.5L77 13l2.3-1.8h4.3l3.1 4.7-1.4 4.9-4.4 5.6-3.7 4.7-5.3 7.1-3.2 5.7.3.4h.7l12-2.6 6.4-1.1 7.6-1.3 3.5 1.6.4 1.6-1.4 3.4-8.2 2-9.6 2-14.3 3.3-.2.1.2.3 6.4.6 2.8.2h6.8l12.6 1 3.3 2 1.9 2.7-.3 2-5.1 2.6-6.8-1.6-16-3.8-5.4-1.3h-.8v.4l4.6 4.5 8.3 7.5L89 80.1l.5 2.4-1.3 2-1.4-.2-9.2-7-3.6-3-8-6.8h-.5v.7l1.8 2.7 9.8 14.7.5 4.5-.7 1.4-2.6 1-2.7-.6-5.8-8-6-9-4.7-8.2-.5.4-2.9 30.2-1.3 1.5-3 1.2-2.5-2-1.4-3 1.4-6.2 1.6-8 1.3-6.4 1.2-7.9.7-2.6v-.2H49L43 72l-9 12.3-7.2 7.6-1.7.7-3-1.5.3-2.8L24 86l10-12.8 6-7.9 4-4.6-.1-.5h-.3L17.2 77.4l-4.7.6-2-2 .2-3 1-1 8-5.5Z"/></svg>',
2341
+ codex: '<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"/></svg>',
2342
+ opencode: '<svg viewBox="0 0 240 300" fill="currentColor" aria-hidden="true"><path d="M180 240H60V120H180V240Z" opacity=".55"/><path fill-rule="evenodd" d="M180 60H60V240H180V60ZM240 300H0V0H240V300Z"/></svg>',
2343
+ };
2344
+ // App label -> internal name, so the "where deployed" tag (which carries labels) maps to icons.
2345
+ const AGENT_NAME_BY_LABEL = { "Claude Code": "claude", "OpenAI Codex": "codex", "OpenCode": "opencode" };
2346
+ const agentSvg = (name) => AGENT_ICONS[name] || "";
2347
+
2331
2348
  function skillRow(s) {
2332
2349
  const ver = s.version ? '<span class="tag">v' + esc(s.version) + "</span>" : "";
2333
- const where = s.agents && s.agents.length ? '<span class="tag">' + s.agents.map(esc).join(", ") + "</span>"
2350
+ // Show one app icon per agent that holds the skill (name in the tooltip), not the names.
2351
+ const where = s.agents && s.agents.length
2352
+ ? '<span class="aicons">' + s.agents.map((l) => {
2353
+ const ic = agentSvg(AGENT_NAME_BY_LABEL[l]);
2354
+ return ic ? '<span class="aicon" title="' + esc(l) + '" aria-label="' + esc(l) + '">' + ic + "</span>"
2355
+ : '<span class="tag">' + esc(l) + "</span>";
2356
+ }).join("") + "</span>"
2334
2357
  : (s.discarded ? '<span class="tag">disabled</span>' : '<span class="tag">not deployed</span>');
2335
2358
  const ext = s.source === "external" ? '<span class="tag ext">external</span>' : "";
2336
2359
  const upd = s.source !== "enigma" ? ""
@@ -2349,9 +2372,9 @@ export {
2349
2372
  const agentChips = (s.source === "enigma" && !s.discarded && s.agentStates && s.agentStates.length)
2350
2373
  ? '<div class="set-agents">' + s.agentStates.map((a) =>
2351
2374
  '<button type="button" class="achip' + (a.deployed ? " on" : "") + '" data-action="agent-toggle" data-name="' + esc(s.name)
2352
- + '" data-agent="' + esc(a.name) + '" data-off="' + (a.deployed ? 1 : 0) + '" title="'
2353
- + (a.deployed ? "On for " + esc(a.label) + " - click to disable" : "Off for " + esc(a.label) + " - click to enable")
2354
- + '">' + esc(a.label) + (a.deployed ? " on" : " off") + "</button>").join("") + "</div>"
2375
+ + '" data-agent="' + esc(a.name) + '" data-off="' + (a.deployed ? 1 : 0) + '" aria-label="' + esc(a.label) + '" title="'
2376
+ + (a.deployed ? esc(a.label) + " - on, click to disable" : esc(a.label) + " - off, click to enable")
2377
+ + '">' + (agentSvg(a.name) || esc(a.label)) + "</button>").join("") + "</div>"
2355
2378
  : "";
2356
2379
  return '<div class="set-row"><div class="set-meta"><div class="set-name">' + esc(s.name) + ext + ver + upd + where + "</div>"
2357
2380
  + '<div class="set-hint">' + esc(s.description || "") + "</div>" + agentChips + '</div><div class="set-ctl" style="display:flex;gap:8px">' + edit + main + "</div></div>";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enigmax/dashboard",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "Local browser dashboard UI for enigma: the static page and chart assets enigma serves on its loopback dashboard (savings, real tool usage, in-browser settings). Installed on demand by enigma-cli; not a runtime dependency.",
5
5
  "type": "module",
6
6
  "files": [