(function () {
"use strict";
// hermes-achievements dashboard plugin
// Originally authored by @PCinkusz — https://github.com/PCinkusz/hermes-achievements (MIT).
// Bundled into hermes-agent. Upstream repo remains the staging ground for new
// badges and UI iteration; the in-progress scan banner below is a small addition
// layered on top of the original dist bundle.
const SDK = window.__HERMES_PLUGIN_SDK__;
if (!SDK || !window.__HERMES_PLUGINS__) return;
const React = SDK.React;
const hooks = SDK.hooks;
const C = SDK.components;
const cn = SDK.utils.cn;
const LUCIDE = {"flame":"","avalanche":"\n ","nodes":"\n \n \n \n ","rocket":"\n \n \n ","branch":"\n \n \n ","daemon":"\n ","clock":"\n ","warning":"\n \n ","wine":"\n \n \n ","scroll":"\n \n \n ","plug":"\n \n \n \n \n ","lock":"\n \n ","package_skull":"\n \n \n \n ","restart":"\n \n \n ","key":"\n ","colon":"\n ","container":"\n \n \n \n ","melting_clock":"\n \n ","pencil":"\n ","blueprint":"\n \n \n \n ","pixel":"\n \n \n \n ","ship":"\n \n \n \n ","spark_cursor":"\n \n \n \n ","needle":"","hammer_scroll":"\n \n ","anvil":"\n \n \n \n ","crystal":"\n \n ","palace":"\n \n \n \n \n ","dragon":"","antenna":"\n \n \n \n \n \n ","puzzle":"","rewind":"\n ","spiral":"\n \n \n \n ","quote":"\n ","compass":"\n ","browser":"\n \n ","terminal":"\n ","wand":"\n \n \n \n \n \n \n ","folder":"\n \n ","eye":"\n ","wave":"","swap":"\n \n \n ","router":"\n \n \n \n \n ","codex":"\n \n ","prism":"\n \n ","marathon":"\n \n ","calendar":"\n \n \n \n \n \n \n \n \n ","moon":"","cache":"\n \n ","secret":"\n \n "};
const tierClass = function (tier) {
return tier ? "ha-tier-" + tier.toLowerCase() : "ha-tier-pending";
};
async function api(path, options) {
const url = "/api/plugins/hermes-achievements" + path;
const res = await fetch(url, options || {});
if (!res.ok) {
const text = await res.text().catch(function () { return res.statusText; });
throw new Error(res.status + ": " + text);
}
const text = await res.text();
try {
return JSON.parse(text);
} catch (_) {
return null;
}
}
function AchievementIcon({ icon }) {
const svg = LUCIDE[icon] || LUCIDE.secret;
const ref = React.useRef(null);
React.useEffect(function () {
if (!ref.current) return;
const el = ref.current;
while (el.firstChild) el.removeChild(el.firstChild);
try {
const doc = new DOMParser().parseFromString(
"",
"image/svg+xml"
);
if (!doc.querySelector("parsererror")) {
Array.from(doc.documentElement.childNodes).forEach(function (n) {
el.appendChild(document.importNode(n, true));
});
}
} catch (_) {}
}, [svg]);
return React.createElement("svg", {
ref: ref,
className: "ha-lucide",
viewBox: "0 0 24 24",
fill: "none",
stroke: "currentColor",
strokeWidth: 2,
strokeLinecap: "round",
strokeLinejoin: "round",
"aria-hidden": "true",
});
}
const TIER_HEX = {
"Copper": "#b87333",
"Silver": "#c0c7d2",
"Gold": "#f2c94c",
"Diamond": "#67e8f9",
"Olympian": "#c084fc",
};
function tierHex(tier) {
return TIER_HEX[tier] || "#67e8f9";
}
// Render a LUCIDE icon path fragment into a standalone SVG string with an
// explicit stroke color so it can be rasterized onto a