Download web/src/plugins/sdk.d.ts from SaylorTwift/hermes-agent: direct link, hf CLI and curl.
- Browser
- Download file 8.09 kB
-
https://huggingface.co/SaylorTwift/hermes-agent/resolve/main/web/src/plugins/sdk.d.ts
- Command line
-
hf download hf://SaylorTwift/hermes-agent/web/src/plugins/sdk.d.ts
-
curl -L -o sdk.d.ts https://huggingface.co/SaylorTwift/hermes-agent/resolve/main/web/src/plugins/sdk.d.ts
8.09 kB
| /** | |
| * Hermes Dashboard Plugin SDK — typed contract (SPIKE) | |
| * ==================================================== | |
| * | |
| * This is the public type surface for ``window.__HERMES_PLUGIN_SDK__`` and | |
| * ``window.__HERMES_PLUGINS__``, the globals the dashboard host exposes to | |
| * plugin bundles (see ``web/src/plugins/registry.ts::exposePluginSDK``). | |
| * | |
| * STATUS: spike. This file documents the contract and gives plugin authors | |
| * (in-repo IIFEs and external bundles alike) editor types without bundling | |
| * their own copies of React / the API client. It is intentionally a | |
| * hand-authored ambient declaration rather than ``typeof | |
| * window.__HERMES_PLUGIN_SDK__`` because: | |
| * 1. The runtime object is assembled from many internal modules | |
| * (``@/lib/api``, ``@nous-research/ui``, …). Deriving the type would | |
| * leak those internal import paths into the public contract and couple | |
| * external plugins to the host's internal module layout. | |
| * 2. A hand-authored contract is the *versioned API boundary* — changing | |
| * it is a deliberate act, visible in review, not an accidental | |
| * consequence of refactoring an internal helper. | |
| * | |
| * Versioning: bump ``HermesPluginSDK["sdkVersion"]`` (and the | |
| * ``SDK_CONTRACT_VERSION`` const the host exposes) on any | |
| * backwards-incompatible change to this surface. Additive changes | |
| * (new optional fields, new helpers) don't require a major bump. | |
| * | |
| * OPEN QUESTIONS for productionising this spike (do not block the auth fix): | |
| * - Ship as a published ``@hermes/dashboard-plugin-sdk`` types package, or | |
| * keep in-repo and copy into external plugin repos? | |
| * - Should the host assert at runtime that a plugin's declared | |
| * ``manifest.sdk_version`` is compatible before executing it? | |
| * - The ``components`` map is typed loosely as ``Record<string, | |
| * ComponentType>`` here; do we want exact per-component prop types | |
| * (pulls @nous-research/ui types into the contract) or is the loose | |
| * shape the right boundary for external authors? | |
| */ | |
| import type { ComponentType } from "react"; | |
| // --------------------------------------------------------------------------- | |
| // Auth-relevant helpers (the surface this PR adds/sanctions) | |
| // --------------------------------------------------------------------------- | |
| /** | |
| * JSON ``fetch`` for dashboard ``/api/...`` endpoints. Handles auth in both | |
| * modes (loopback session-token header / gated cookie), throws | |
| * ``Error("<status>: <body>")`` on non-2xx, and triggers the global | |
| * 401 → /login redirect in gated mode. Use for all JSON plugin endpoints. | |
| */ | |
| export type FetchJSON = <T = unknown>( | |
| url: string, | |
| init?: RequestInit, | |
| options?: { allowUnauthorized?: boolean }, | |
| ) => Promise<T>; | |
| /** | |
| * Authenticated ``fetch`` for NON-JSON endpoints (uploads via ``FormData``, | |
| * binary/blob downloads). Same auth handling as ``fetchJSON`` but returns | |
| * the raw ``Response``, does not parse, does not throw on non-2xx, and does | |
| * not run the 401 redirect. Plugins MUST use this (or ``fetchJSON``) instead | |
| * of calling ``fetch`` with a hand-read ``window.__HERMES_SESSION_TOKEN__``. | |
| */ | |
| export type AuthedFetch = (url: string, init?: RequestInit) => Promise<Response>; | |
| /** | |
| * Build an absolute ``ws(s)://`` URL for a dashboard WebSocket endpoint with | |
| * the correct auth query param for the active mode (single-use ``ticket`` in | |
| * gated OAuth mode, ``token`` in loopback). Plugins MUST use this for any | |
| * WebSocket instead of hand-assembling the URL + reading the session token. | |
| */ | |
| export type BuildWsUrl = ( | |
| path: string, | |
| params?: Record<string, string>, | |
| ) => Promise<string>; | |
| /** Lower-level: just the ``[authParamName, authParamValue]`` pair. */ | |
| export type BuildWsAuthParam = () => Promise<[string, string]>; | |
| // --------------------------------------------------------------------------- | |
| // Registry surface (window.__HERMES_PLUGINS__) | |
| // --------------------------------------------------------------------------- | |
| export interface PluginRegistry { | |
| /** Register the plugin's main tab component by manifest name. */ | |
| register(name: string, component: ComponentType<Record<string, never>>): void; | |
| /** Register a component into a named host slot. */ | |
| registerSlot(slot: string, name: string, component: ComponentType): void; | |
| } | |
| // --------------------------------------------------------------------------- | |
| // SDK surface (window.__HERMES_PLUGIN_SDK__) | |
| // --------------------------------------------------------------------------- | |
| export interface HermesPluginSDK { | |
| /** Contract version of this SDK surface (see SDK_CONTRACT_VERSION). */ | |
| readonly sdkVersion: string; | |
| /** React core — use instead of importing/bundling react. */ | |
| React: typeof import("react").default; | |
| hooks: { | |
| useState: typeof import("react").useState; | |
| useEffect: typeof import("react").useEffect; | |
| useCallback: typeof import("react").useCallback; | |
| useMemo: typeof import("react").useMemo; | |
| useRef: typeof import("react").useRef; | |
| useContext: typeof import("react").useContext; | |
| createContext: typeof import("react").createContext; | |
| /** | |
| * Toast feedback. Returns ``{ showToast, toast }`` where ``toast`` is the | |
| * current visible toast (or null) and ``showToast(message, 'success' | 'error')`` | |
| * replaces it. Mount the ``Toast`` component (also on ``components``) somewhere | |
| * in your plugin's tree to render the visible toast. | |
| */ | |
| useToast: () => { | |
| showToast: (message: string, type: "success" | "error") => void; | |
| toast: { message: string; type: "success" | "error" } | null; | |
| }; | |
| /** | |
| * Single-id delete-confirm state machine. Pass ``onDelete(id)`` (an async | |
| * function). Returns ``{ requestDelete, confirm, cancel, isOpen, isDeleting, | |
| * pendingId }``. Pair with the ``ConfirmDialog`` primitive (passed as | |
| * ``open={isOpen}`` etc.) or any custom dialog. | |
| */ | |
| useConfirmDelete: <TId,>(opts: { onDelete: (id: TId) => Promise<void> }) => { | |
| requestDelete: (id: TId) => void; | |
| confirm: () => Promise<void>; | |
| cancel: () => void; | |
| isOpen: boolean; | |
| isDeleting: boolean; | |
| pendingId: TId | null; | |
| }; | |
| }; | |
| /** | |
| * Typed convenience client for core dashboard endpoints. Typed permissively | |
| * at the boundary (methods vary in arity and return type — most return | |
| * ``Promise<T>``, a few return a URL string synchronously); plugins call the | |
| * specific methods they need. See ``web/src/lib/api.ts`` for the concrete shape. | |
| */ | |
| api: Record<string, (...args: never[]) => unknown>; | |
| /** JSON fetch with host auth handling. */ | |
| fetchJSON: FetchJSON; | |
| /** Authenticated raw fetch for uploads / blob downloads. */ | |
| authedFetch: AuthedFetch; | |
| /** Build an auth'd WebSocket URL for the active mode. */ | |
| buildWsUrl: BuildWsUrl; | |
| /** Resolve just the WS auth query-param pair. */ | |
| buildWsAuthParam: BuildWsAuthParam; | |
| /** | |
| * Shared UI primitives (Nous DS / shadcn). Typed permissively at the | |
| * boundary: the host's concrete components (some of which require props like | |
| * ``active``/``value``/``name``) must be assignable here, and external plugin | |
| * authors render them dynamically without the host's internal prop types. | |
| * ``ComponentType<never>`` accepts any component regardless of its prop | |
| * requirements (props are contravariant). | |
| */ | |
| components: Record<string, ComponentType<never>>; | |
| utils: { | |
| cn: (...classes: Array<string | false | null | undefined>) => string; | |
| /** Relative-time formatter. Accepts an epoch-ms number. */ | |
| timeAgo: (ts: number) => string; | |
| /** Relative-time formatter for an ISO-8601 string. */ | |
| isoTimeAgo: (iso: string) => string; | |
| }; | |
| /** | |
| * i18n hook. Returns the host's i18n context value; typed loosely at the | |
| * boundary so the contract doesn't couple to the host's internal | |
| * ``I18nContextValue`` shape. Plugins typically call ``useI18n().t(...)``. | |
| */ | |
| useI18n: () => unknown; | |
| } | |
| declare global { | |
| interface Window { | |
| __HERMES_PLUGIN_SDK__?: HermesPluginSDK; | |
| __HERMES_PLUGINS__?: PluginRegistry; | |
| } | |
| } | |
| export {}; | |