Instructions to use Wellz1000/hermes-2 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- HERMES
How to use Wellz1000/hermes-2 with HERMES:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
Download web/src/plugins/usePlugins.ts from Wellz1000/hermes-2: direct link, hf CLI and curl.
- Browser
- Download file 4.75 kB
-
https://huggingface.co/Wellz1000/hermes-2/resolve/main/web/src/plugins/usePlugins.ts
- Command line
-
hf download hf://Wellz1000/hermes-2/web/src/plugins/usePlugins.ts
-
curl -L -o usePlugins.ts https://huggingface.co/Wellz1000/hermes-2/resolve/main/web/src/plugins/usePlugins.ts
4.75 kB
| /** | |
| * usePlugins hook — discovers and loads dashboard plugins. | |
| * | |
| * 1. Fetches plugin manifests from GET /api/dashboard/plugins | |
| * 2. Injects CSS <link> tags for plugins that declare css | |
| * 3. Loads plugin JS bundles via <script> tags | |
| * 4. Waits for plugins to call register() and resolves them | |
| */ | |
| import { useState, useEffect, useRef } from "react"; | |
| import { api, HERMES_BASE_PATH } from "@/lib/api"; | |
| import type { PluginManifest, RegisteredPlugin } from "./types"; | |
| import { | |
| getPluginComponent, | |
| onPluginRegistered, | |
| notifyPluginRegistry, | |
| setPluginLoadError, | |
| } from "./registry"; | |
| export function usePlugins() { | |
| const [manifests, setManifests] = useState<PluginManifest[]>([]); | |
| const [plugins, setPlugins] = useState<RegisteredPlugin[]>([]); | |
| const [loading, setLoading] = useState(true); | |
| const loadedScripts = useRef<Set<string>>(new Set()); | |
| // Fetch manifests on mount. | |
| useEffect(() => { | |
| api | |
| .getPlugins() | |
| .then((list) => { | |
| setManifests(list); | |
| if (list.length === 0) setLoading(false); | |
| }) | |
| .catch(() => setLoading(false)); | |
| }, []); | |
| // Load plugin assets when manifests arrive. | |
| useEffect(() => { | |
| if (manifests.length === 0) return; | |
| const injectedScripts: HTMLScriptElement[] = []; | |
| for (const manifest of manifests) { | |
| // Inject CSS if specified. | |
| if (manifest.css) { | |
| const cssUrl = `${HERMES_BASE_PATH}/dashboard-plugins/${manifest.name}/${manifest.css}`; | |
| if (!document.querySelector(`link[href="${cssUrl}"]`)) { | |
| const link = document.createElement("link"); | |
| link.rel = "stylesheet"; | |
| link.href = cssUrl; | |
| document.head.appendChild(link); | |
| } | |
| } | |
| // Load JS bundle. In dev, cache-bust so Vite HMR can clear the | |
| // in-memory registry while the browser would otherwise never | |
| // re-execute a previously cached <script> URL. | |
| const baseUrl = `${HERMES_BASE_PATH}/dashboard-plugins/${manifest.name}/${manifest.entry}`; | |
| const scriptSrc = import.meta.env.DEV | |
| ? `${baseUrl}?hermes_dv=${Date.now()}` | |
| : baseUrl; | |
| if (!import.meta.env.DEV) { | |
| if (loadedScripts.current.has(baseUrl)) continue; | |
| loadedScripts.current.add(baseUrl); | |
| } | |
| const script = document.createElement("script"); | |
| script.setAttribute("data-hermes-plugin", manifest.name); | |
| script.src = scriptSrc; | |
| script.async = true; | |
| // SRI integrity verification — defense against compromised plugin | |
| // delivery. Plugin manifests can declare an integrity hash | |
| // (e.g. "sha384-...") which the browser verifies before executing. | |
| // Without this, a man-in-the-middle or compromised plugin server | |
| // can substitute the JS bundle silently. Opt-in: when no integrity | |
| // is declared in the manifest, behavior is unchanged. | |
| if (manifest.integrity && typeof manifest.integrity === "string") { | |
| script.integrity = manifest.integrity; | |
| script.crossOrigin = "anonymous"; | |
| } | |
| script.onerror = () => { | |
| setPluginLoadError(manifest.name, "LOAD_FAILED"); | |
| console.warn( | |
| `[plugins] Failed to load ${manifest.name} from ${scriptSrc} (open Network tab)`, | |
| ); | |
| }; | |
| script.onload = () => { | |
| notifyPluginRegistry(); | |
| queueMicrotask(() => { | |
| if (getPluginComponent(manifest.name)) return; | |
| setPluginLoadError(manifest.name, "NO_REGISTER"); | |
| }); | |
| }; | |
| document.body.appendChild(script); | |
| injectedScripts.push(script); | |
| } | |
| // Give plugins a moment to load and register, then stop loading state. | |
| const timeout = setTimeout(() => setLoading(false), 2000); | |
| return () => { | |
| clearTimeout(timeout); | |
| if (import.meta.env.DEV) { | |
| for (const el of injectedScripts) { | |
| el.remove(); | |
| } | |
| } | |
| }; | |
| }, [manifests]); | |
| // Listen for plugin registrations and resolve them against manifests. | |
| useEffect(() => { | |
| function resolvePlugins() { | |
| const resolved: RegisteredPlugin[] = []; | |
| for (const manifest of manifests) { | |
| const component = getPluginComponent(manifest.name); | |
| if (component) { | |
| resolved.push({ manifest, component }); | |
| } | |
| } | |
| setPlugins(resolved); | |
| // If all plugins registered, stop loading early. | |
| if (resolved.length === manifests.length && manifests.length > 0) { | |
| setLoading(false); | |
| } | |
| } | |
| resolvePlugins(); | |
| const unsub = onPluginRegistered(resolvePlugins); | |
| return unsub; | |
| }, [manifests]); | |
| return { plugins, manifests, loading }; | |
| } | |