@enigmax/dashboard 0.1.114 → 0.1.115
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/assets/index.html +198 -45
- package/package.json +1 -1
package/assets/index.html
CHANGED
|
@@ -467,6 +467,15 @@
|
|
|
467
467
|
.pg-textarea { min-height: 92px; resize: vertical; line-height: 1.5; }
|
|
468
468
|
.pg-check { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--text); padding-top: 4px; }
|
|
469
469
|
.pg-check label { color: var(--muted); }
|
|
470
|
+
.ad-pool { display: flex; flex-wrap: wrap; gap: 8px 16px; }
|
|
471
|
+
.ad-pool label { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text); cursor: pointer; min-width: 0; max-width: 100%; }
|
|
472
|
+
.ad-pool label > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
473
|
+
.ad-pool input { accent-color: var(--good); }
|
|
474
|
+
.ad-pool .aicon { color: var(--muted); }
|
|
475
|
+
.ad-pool.off { opacity: .5; }
|
|
476
|
+
.ad-fixed.off { opacity: .5; }
|
|
477
|
+
.ad-err { color: var(--bad); font-size: 11px; }
|
|
478
|
+
.ad-err:empty { display: none; }
|
|
470
479
|
.pg-out { background: var(--surface2); border: 1px solid var(--border); border-radius: 8px; padding: 12px 14px; font-size: 12px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; white-space: pre-wrap; word-break: break-word; overflow-x: auto; max-height: 360px; overflow-y: auto; margin: 0; }
|
|
471
480
|
/* Claude-style usage window gauges (current session / weekly all / weekly Sonnet). */
|
|
472
481
|
.wgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; margin-bottom: 18px; }
|
|
@@ -836,7 +845,7 @@
|
|
|
836
845
|
</a>
|
|
837
846
|
<a href="#/playground" data-view="playground" class="tab">
|
|
838
847
|
<svg class="tab-ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m4 17 6-6-6-6"/><path d="M12 19h8"/></svg>
|
|
839
|
-
<span>
|
|
848
|
+
<span>Local API</span>
|
|
840
849
|
</a>
|
|
841
850
|
</div>
|
|
842
851
|
<div class="nav-group" role="group" aria-labelledby="ng-code">
|
|
@@ -1427,9 +1436,44 @@
|
|
|
1427
1436
|
|
|
1428
1437
|
<section id="view-playground" style="display:none">
|
|
1429
1438
|
<div class="page-head">
|
|
1430
|
-
<h1>API
|
|
1431
|
-
<p>
|
|
1439
|
+
<h1>Local API</h1>
|
|
1440
|
+
<p>Set which account answers <code>enigma api</code> requests, then try it below.</p>
|
|
1432
1441
|
</div>
|
|
1442
|
+
<div class="panel" id="adPanel">
|
|
1443
|
+
<div class="set-cat-h">Server defaults</div>
|
|
1444
|
+
<div class="set-cat-b">What <code>enigma api</code> starts with. A command-line flag overrides them for one run; changes apply the next time the server starts.</div>
|
|
1445
|
+
<div class="pg-grid">
|
|
1446
|
+
<label class="pg-field"><span>Account rotation</span>
|
|
1447
|
+
<select id="adRotation"></select>
|
|
1448
|
+
</label>
|
|
1449
|
+
<label class="pg-field ad-fixed"><span>Default account</span>
|
|
1450
|
+
<select id="adAccount"><option value="">(active account)</option></select>
|
|
1451
|
+
</label>
|
|
1452
|
+
<label class="pg-field ad-fixed"><span>Default profile</span>
|
|
1453
|
+
<select id="adProfile"><option value="">(none)</option></select>
|
|
1454
|
+
</label>
|
|
1455
|
+
<label class="pg-field ad-fixed"><span>Default pack</span>
|
|
1456
|
+
<select id="adPack"><option value="">(none)</option></select>
|
|
1457
|
+
</label>
|
|
1458
|
+
<label class="pg-field"><span>Port</span>
|
|
1459
|
+
<input id="adPort" class="linput" type="number" min="1" max="65535" step="1" inputmode="numeric" aria-describedby="adPortErr">
|
|
1460
|
+
<small id="adPortErr" class="ad-err" role="alert"></small>
|
|
1461
|
+
</label>
|
|
1462
|
+
<div class="pg-field"><span>Callers choose the account</span>
|
|
1463
|
+
<button id="adClient" type="button" class="toggle on" data-kind="bool" role="switch" aria-checked="true" aria-label="Let requests pick their own account, profile or pack">On</button>
|
|
1464
|
+
</div>
|
|
1465
|
+
</div>
|
|
1466
|
+
<div id="adRotationHint" class="set-hint"></div>
|
|
1467
|
+
<div class="pg-field" id="adPoolWrap"><span>Accounts in the rotation <small>(none checked = every account; fill-first uses them in the order you check them)</small></span>
|
|
1468
|
+
<div id="adPool" class="ad-pool"></div>
|
|
1469
|
+
</div>
|
|
1470
|
+
<div class="ladd" style="gap:8px;align-items:center">
|
|
1471
|
+
<button id="adSave" type="button" class="toggle on" disabled>Save defaults</button>
|
|
1472
|
+
<button id="adDiscard" type="button" class="laddb" style="display:none">Discard changes</button>
|
|
1473
|
+
<span id="adNote" class="set-hint"></span>
|
|
1474
|
+
</div>
|
|
1475
|
+
</div>
|
|
1476
|
+
<div class="set-cat-h" style="margin:18px 0 8px">Playground</div>
|
|
1433
1477
|
<div class="panel">
|
|
1434
1478
|
<div class="pg-grid">
|
|
1435
1479
|
<label class="pg-field"><span>Run</span>
|
|
@@ -1454,13 +1498,13 @@
|
|
|
1454
1498
|
<input id="pgKey" class="linput" type="password" placeholder="Bearer token / ENIGMA_API_KEY">
|
|
1455
1499
|
</label>
|
|
1456
1500
|
<label class="pg-field"><span>Account <small>(optional)</small></span>
|
|
1457
|
-
<select id="pgAccount"><option value="">(
|
|
1501
|
+
<select id="pgAccount"><option value="">(server default)</option></select>
|
|
1458
1502
|
</label>
|
|
1459
1503
|
<label class="pg-field"><span>Profile <small>(optional)</small></span>
|
|
1460
|
-
<select id="pgProfile"><option value="">(
|
|
1504
|
+
<select id="pgProfile"><option value="">(server default)</option></select>
|
|
1461
1505
|
</label>
|
|
1462
1506
|
<label class="pg-field"><span>Pack <small>(optional)</small></span>
|
|
1463
|
-
<select id="pgPack"><option value="">(
|
|
1507
|
+
<select id="pgPack"><option value="">(server default)</option></select>
|
|
1464
1508
|
</label>
|
|
1465
1509
|
<div class="pg-field pg-tools"><span>Agent tools <small>(Read/Write/Bash...)</small></span>
|
|
1466
1510
|
<button id="pgTools" type="button" class="toggle on" data-kind="bool" role="switch" aria-checked="true" aria-label="Enable agent tools">On</button>
|
|
@@ -1469,10 +1513,6 @@
|
|
|
1469
1513
|
<input id="pgImage" type="file" accept="image/*" class="linput">
|
|
1470
1514
|
</label>
|
|
1471
1515
|
</div>
|
|
1472
|
-
<div class="ladd" style="gap:8px;align-items:center">
|
|
1473
|
-
<button id="pgSaveDefault" type="button" class="laddb">Save context as <code>enigma api</code> default</button>
|
|
1474
|
-
<span id="pgDefaultNote" class="set-hint"></span>
|
|
1475
|
-
</div>
|
|
1476
1516
|
<label class="pg-field"><span>System prompt <small>(optional)</small></span>
|
|
1477
1517
|
<input id="pgSystem" class="linput" placeholder="e.g. You are a terse assistant.">
|
|
1478
1518
|
</label>
|
|
@@ -3660,8 +3700,9 @@ export {
|
|
|
3660
3700
|
|
|
3661
3701
|
function renderSettings(cats) {
|
|
3662
3702
|
const el = $("settingsBody");
|
|
3663
|
-
// Skill-related settings live in the Skills tab
|
|
3664
|
-
|
|
3703
|
+
// Skill-related settings live in the Skills tab and the API server's in the Local API tab;
|
|
3704
|
+
// drop them here so they aren't shown twice.
|
|
3705
|
+
cats = (cats || []).map((c) => ({ ...c, settings: (c.settings || []).filter((s) => SKILL_SETTING_KEYS.indexOf(s.key) === -1 && !/^api-/.test(s.key)) })).filter((c) => c.settings.length);
|
|
3665
3706
|
if (!cats.length) { el.innerHTML = '<div class="empty" style="padding:24px 0">No settings available.</div>'; return; }
|
|
3666
3707
|
// One panel per category; settings laid out in a responsive 2-column grid so a
|
|
3667
3708
|
// long config list stays scannable on a wide screen.
|
|
@@ -4059,7 +4100,7 @@ export {
|
|
|
4059
4100
|
// config stores `opencode` and `rovodev`, the reader sees OpenCode and Rovo Dev.
|
|
4060
4101
|
const AGENT_LABELS = {
|
|
4061
4102
|
auto: "Auto", claude: "Claude Code", codex: "Codex",
|
|
4062
|
-
opencode: "OpenCode", rovodev: "Rovo Dev", pi: "Pi"
|
|
4103
|
+
opencode: "OpenCode", kimi: "Kimi Code", rovodev: "Rovo Dev", pi: "Pi"
|
|
4063
4104
|
};
|
|
4064
4105
|
// App label -> internal name. Normalized so every label variant maps to an icon:
|
|
4065
4106
|
// "Claude Code", "Codex"/"OpenAI Codex", "opencode"/"OpenCode", "Rovo Dev", "Pi".
|
|
@@ -5090,7 +5131,7 @@ export {
|
|
|
5090
5131
|
|
|
5091
5132
|
/**
|
|
5092
5133
|
* The palette's engine, from @enigmax/primitives: subsequence ranking (so "qgate"
|
|
5093
|
-
* finds "Quality gate" and "
|
|
5134
|
+
* finds "Quality gate" and "lapi" finds "Local API"), the debounce and the
|
|
5094
5135
|
* cancellation. The scorer this replaced is the one the package now ships, so the
|
|
5095
5136
|
* dashboard and every other consumer rank the same way.
|
|
5096
5137
|
*/
|
|
@@ -6342,30 +6383,149 @@ export {
|
|
|
6342
6383
|
if (!opts.length) opts.push('<option value="claude" data-icon="claude">Claude Code (default)</option>');
|
|
6343
6384
|
sel.innerHTML = opts.join("");
|
|
6344
6385
|
syncDD(sel);
|
|
6345
|
-
// Context selectors: account (labeled by tool), profile, pack.
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
const
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
acc.value = def.account || ""; syncDD(acc);
|
|
6359
|
-
prof.value = def.profile || ""; syncDD(prof);
|
|
6360
|
-
pk.value = def.pack || ""; syncDD(pk);
|
|
6361
|
-
renderPgDefault(def);
|
|
6362
|
-
$("pgBase").placeholder = "http://127.0.0.1:" + (info.apiPort || 8000);
|
|
6386
|
+
// Context selectors: account (labeled by tool), profile, pack. Blank = whatever the
|
|
6387
|
+
// server defaults below pick (the rotation included), so a test matches `enigma api`.
|
|
6388
|
+
fillContextSelect($("pgAccount"), "(server default)", accountOptions(info.accounts));
|
|
6389
|
+
fillContextSelect($("pgProfile"), "(server default)", (info.profiles || []).map((n) => ({ value: n, label: n })));
|
|
6390
|
+
fillContextSelect($("pgPack"), "(server default)", packOptions(info.packs));
|
|
6391
|
+
fillContextSelect($("adAccount"), "(active account)", accountOptions(info.accounts));
|
|
6392
|
+
fillContextSelect($("adProfile"), "(none)", (info.profiles || []).map((n) => ({ value: n, label: n })));
|
|
6393
|
+
fillContextSelect($("adPack"), "(none)", packOptions(info.packs));
|
|
6394
|
+
const rot = $("adRotation");
|
|
6395
|
+
rot.innerHTML = (info.rotations || ["off"]).map((r) => '<option value="' + esc(r) + '">' + esc(prettyChoice(r)) + "</option>").join("");
|
|
6396
|
+
adInfo = info;
|
|
6397
|
+
adApply(info.defaults);
|
|
6398
|
+
$("pgBase").placeholder = "http://127.0.0.1:" + ((info.defaults && info.defaults.port) || info.apiPort || 8000);
|
|
6363
6399
|
pgSyncMode();
|
|
6364
6400
|
}
|
|
6365
|
-
function
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6401
|
+
function fillContextSelect(sel, blank, items) {
|
|
6402
|
+
sel.innerHTML = '<option value="">' + esc(blank) + "</option>" + items.map((o) =>
|
|
6403
|
+
'<option value="' + esc(o.value) + '"' + (o.icon ? ' data-icon="' + esc(o.icon) + '"' : "") + ">" + esc(o.label) + "</option>").join("");
|
|
6404
|
+
syncDD(sel);
|
|
6405
|
+
}
|
|
6406
|
+
function accountOptions(accounts) {
|
|
6407
|
+
return (accounts || []).map((a) => ({ value: a.name, label: a.name + " (" + agentLabel(a.tool) + ")", icon: agentName(a.tool) }));
|
|
6408
|
+
}
|
|
6409
|
+
function packOptions(packs) {
|
|
6410
|
+
return (packs || []).map((p) => ({ value: p.id, label: p.label + (p.installed ? "" : " - not installed") }));
|
|
6411
|
+
}
|
|
6412
|
+
|
|
6413
|
+
// --- Server defaults for `enigma api` (account, rotation, pool, caller choice, port) ---
|
|
6414
|
+
let adInfo = null;
|
|
6415
|
+
let adSaved = null;
|
|
6416
|
+
let adPicked = [];
|
|
6417
|
+
const AD_ROTATION_HINT = {
|
|
6418
|
+
"off": "Requests that name no account use the default account, profile or pack below.",
|
|
6419
|
+
"round-robin": "Requests that name no account take turns across the accounts below. One that hits a usage limit is retried on the next.",
|
|
6420
|
+
"least-used": "Requests that name no account go to the one with the least use in its current 5-hour window. One that hits a usage limit is retried on the next.",
|
|
6421
|
+
"fill-first": "Requests use the first account below until it hits a usage limit, then the next one.",
|
|
6422
|
+
"random": "Requests that name no account go to a random account below. One that hits a usage limit is retried on the next.",
|
|
6423
|
+
};
|
|
6424
|
+
// Unique account names (the pool is by name; the same name can exist for several agents), saved pool order first.
|
|
6425
|
+
function adPoolNames(pool) {
|
|
6426
|
+
const all = [];
|
|
6427
|
+
((adInfo && adInfo.accounts) || []).forEach((a) => { if (all.indexOf(a.name) === -1) all.push(a.name); });
|
|
6428
|
+
return (pool || []).filter((n) => all.indexOf(n) !== -1).concat(all.filter((n) => (pool || []).indexOf(n) === -1));
|
|
6429
|
+
}
|
|
6430
|
+
function adRenderPool(pool) {
|
|
6431
|
+
const el = $("adPool");
|
|
6432
|
+
const names = adPoolNames(pool);
|
|
6433
|
+
if (!names.length) { el.innerHTML = '<span class="lnone">No accounts yet - add one in Accounts.</span>'; return; }
|
|
6434
|
+
el.innerHTML = names.map((n) => {
|
|
6435
|
+
const tools = ((adInfo && adInfo.accounts) || []).filter((a) => a.name === n).map((a) => a.tool);
|
|
6436
|
+
const icon = tools.length === 1 ? '<span class="aicon" aria-hidden="true">' + (agentSvg(agentName(tools[0])) || "") + "</span>" : "";
|
|
6437
|
+
return '<label title="' + esc(n + " (" + tools.map(agentLabel).join(", ") + ")") + '"><input type="checkbox" data-pool="' + esc(n) + '"'
|
|
6438
|
+
+ ((pool || []).indexOf(n) !== -1 ? " checked" : "") + ">" + icon + "<span>" + esc(n) + "</span></label>";
|
|
6439
|
+
}).join("");
|
|
6440
|
+
}
|
|
6441
|
+
function adApply(def) {
|
|
6442
|
+
def = def || { account: "", profile: "", pack: "", rotation: "off", pool: [], clientContext: true, port: 8000 };
|
|
6443
|
+
adSaved = { account: def.account || "", profile: def.profile || "", pack: def.pack || "", rotation: def.rotation || "off", pool: (def.pool || []).slice(), clientContext: def.clientContext !== false, port: def.port || 8000 };
|
|
6444
|
+
$("adAccount").value = adSaved.account; syncDD($("adAccount"));
|
|
6445
|
+
$("adProfile").value = adSaved.profile; syncDD($("adProfile"));
|
|
6446
|
+
$("adPack").value = adSaved.pack; syncDD($("adPack"));
|
|
6447
|
+
$("adRotation").value = adSaved.rotation; syncDD($("adRotation"));
|
|
6448
|
+
$("adPort").value = String(adSaved.port);
|
|
6449
|
+
paintSwitch($("adClient"), adSaved.clientContext, "On", "Off");
|
|
6450
|
+
adPicked = adSaved.pool.slice();
|
|
6451
|
+
adRenderPool(adSaved.pool);
|
|
6452
|
+
adSync();
|
|
6453
|
+
}
|
|
6454
|
+
function adRead() {
|
|
6455
|
+
const checked = [...$("adPool").querySelectorAll("input[data-pool]:checked")].map((i) => i.dataset.pool);
|
|
6456
|
+
// Pool order is the order accounts were checked in (fill-first walks it), saved ones first.
|
|
6457
|
+
const pool = adPicked.filter((n) => checked.indexOf(n) !== -1).concat(checked.filter((n) => adPicked.indexOf(n) === -1));
|
|
6458
|
+
return {
|
|
6459
|
+
account: $("adAccount").value, profile: $("adProfile").value, pack: $("adPack").value,
|
|
6460
|
+
rotation: $("adRotation").value, pool,
|
|
6461
|
+
clientContext: $("adClient").getAttribute("aria-checked") === "true",
|
|
6462
|
+
port: $("adPort").value.trim(),
|
|
6463
|
+
};
|
|
6464
|
+
}
|
|
6465
|
+
function adPortError(v) {
|
|
6466
|
+
if (v === "") return "Enter a port.";
|
|
6467
|
+
const n = Number(v);
|
|
6468
|
+
return Number.isInteger(n) && n >= 1 && n <= 65535 ? "" : "Use a whole number from 1 to 65535.";
|
|
6469
|
+
}
|
|
6470
|
+
// Dirty = the form differs from what was loaded, so a value changed and put back leaves Save off.
|
|
6471
|
+
function adDirty(cur) {
|
|
6472
|
+
if (!adSaved) return false;
|
|
6473
|
+
return cur.account !== adSaved.account || cur.profile !== adSaved.profile || cur.pack !== adSaved.pack
|
|
6474
|
+
|| cur.rotation !== adSaved.rotation || cur.clientContext !== adSaved.clientContext
|
|
6475
|
+
|| Number(cur.port) !== adSaved.port || cur.pool.join("\n") !== adSaved.pool.join("\n");
|
|
6476
|
+
}
|
|
6477
|
+
function adSync() {
|
|
6478
|
+
const cur = adRead();
|
|
6479
|
+
const rotating = cur.rotation !== "off";
|
|
6480
|
+
$("adRotationHint").textContent = AD_ROTATION_HINT[cur.rotation] || "";
|
|
6481
|
+
$("adPool").classList.toggle("off", !rotating);
|
|
6482
|
+
$("adPoolWrap").style.display = rotating ? "" : "none";
|
|
6483
|
+
document.querySelectorAll("#adPanel .ad-fixed").forEach((el) => el.classList.toggle("off", rotating));
|
|
6484
|
+
const portErr = adPortError(cur.port);
|
|
6485
|
+
$("adPortErr").textContent = portErr;
|
|
6486
|
+
$("adPort").setAttribute("aria-invalid", portErr ? "true" : "false");
|
|
6487
|
+
const dirty = adDirty(cur);
|
|
6488
|
+
$("adSave").disabled = !dirty || !!portErr;
|
|
6489
|
+
$("adSave").title = portErr ? portErr : (dirty ? "" : "Nothing changed");
|
|
6490
|
+
$("adDiscard").style.display = dirty ? "" : "none";
|
|
6491
|
+
}
|
|
6492
|
+
async function adSave() {
|
|
6493
|
+
const cur = adRead();
|
|
6494
|
+
if (adPortError(cur.port) || !adDirty(cur)) return;
|
|
6495
|
+
const btn = $("adSave");
|
|
6496
|
+
btn.disabled = true;
|
|
6497
|
+
setNote("adNote", "Saving defaults...");
|
|
6498
|
+
try {
|
|
6499
|
+
const out = await apiJson("/api/playground", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ op: "set-defaults", ...cur, port: Number(cur.port) }) });
|
|
6500
|
+
if (!out.ok) {
|
|
6501
|
+
setNote("adNote", "Could not save: " + (out.error || "error"), "err");
|
|
6502
|
+
const focus = { account: "adAccount", profile: "adProfile", pack: "adPack", rotation: "adRotation", port: "adPort", clientContext: "adClient" }[out.field];
|
|
6503
|
+
if (focus && $(focus)) $(focus).focus();
|
|
6504
|
+
adSync();
|
|
6505
|
+
return;
|
|
6506
|
+
}
|
|
6507
|
+
adApply(out.defaults);
|
|
6508
|
+
setNote("adNote", "Saved. Restart 'enigma api' to use them.", "ok");
|
|
6509
|
+
} catch (e) {
|
|
6510
|
+
setNote("adNote", "Could not save: " + e.message, "err");
|
|
6511
|
+
adSync();
|
|
6512
|
+
}
|
|
6513
|
+
}
|
|
6514
|
+
function wireApiDefaults() {
|
|
6515
|
+
["adAccount", "adProfile", "adPack", "adRotation"].forEach((id) => $(id).addEventListener("change", adSync));
|
|
6516
|
+
$("adPort").addEventListener("input", adSync);
|
|
6517
|
+
$("adPool").addEventListener("change", (e) => {
|
|
6518
|
+
const box = e.target.closest("input[data-pool]");
|
|
6519
|
+
if (box) {
|
|
6520
|
+
adPicked = adPicked.filter((n) => n !== box.dataset.pool);
|
|
6521
|
+
if (box.checked) adPicked.push(box.dataset.pool);
|
|
6522
|
+
}
|
|
6523
|
+
adSync();
|
|
6524
|
+
});
|
|
6525
|
+
const cl = $("adClient");
|
|
6526
|
+
cl.addEventListener("click", () => { paintSwitch(cl, cl.getAttribute("aria-checked") !== "true", "On", "Off"); adSync(); });
|
|
6527
|
+
$("adSave").addEventListener("click", adSave);
|
|
6528
|
+
$("adDiscard").addEventListener("click", () => adApply(adSaved));
|
|
6369
6529
|
}
|
|
6370
6530
|
function pgSyncMode() {
|
|
6371
6531
|
const http = $("pgMode").value === "http";
|
|
@@ -6417,6 +6577,7 @@ export {
|
|
|
6417
6577
|
const meta = [];
|
|
6418
6578
|
if (out.format) meta.push(out.format === "anthropic" ? "Anthropic" : "OpenAI");
|
|
6419
6579
|
if (out.tool) meta.push(out.tool);
|
|
6580
|
+
if (out.account) meta.push("account " + out.account);
|
|
6420
6581
|
if (typeof out.status === "number") meta.push("HTTP " + out.status);
|
|
6421
6582
|
if (out.usage) meta.push(out.usage.input + " in / " + out.usage.output + " out");
|
|
6422
6583
|
$("pgMeta").textContent = meta.join(" · ");
|
|
@@ -6424,17 +6585,9 @@ export {
|
|
|
6424
6585
|
$("pgRaw").textContent = out.response ? (typeof out.response === "string" ? out.response : JSON.stringify(out.response, null, 2)) : "";
|
|
6425
6586
|
$("pgCurl").textContent = out.curl || "";
|
|
6426
6587
|
}
|
|
6427
|
-
async function pgSaveDefault() {
|
|
6428
|
-
const payload = { op: "set-defaults", account: $("pgAccount").value || "", profile: $("pgProfile").value || "", pack: $("pgPack").value || "" };
|
|
6429
|
-
try {
|
|
6430
|
-
const out = await (await fetch("/api/playground", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) })).json();
|
|
6431
|
-
if (out.ok) { renderPgDefault(out.defaults); toast.success("Saved as the enigma api default"); }
|
|
6432
|
-
else toast.error(out.error || "Could not save the default");
|
|
6433
|
-
} catch { toast.error("Could not reach the dashboard server."); }
|
|
6434
|
-
}
|
|
6435
6588
|
function wirePlayground() {
|
|
6589
|
+
wireApiDefaults();
|
|
6436
6590
|
$("pgSend").addEventListener("click", pgSend);
|
|
6437
|
-
$("pgSaveDefault").addEventListener("click", pgSaveDefault);
|
|
6438
6591
|
const tog = $("pgTools");
|
|
6439
6592
|
tog.addEventListener("click", () => paintSwitch(tog, tog.getAttribute("aria-checked") !== "true", "On", "Off"));
|
|
6440
6593
|
$("pgMode").addEventListener("change", pgSyncMode);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enigmax/dashboard",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.115",
|
|
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": [
|