@frank/hermes-client (0.1.0)
Installation
@frank:registry=npm install @frank/hermes-client@0.1.0"@frank/hermes-client": "0.1.0"About this package
@frank/hermes-client
Typed server-side client for the two contracted Hermes surfaces (gateway
API Server and rich hermes serve), plus event normalization, the
append-only redacted event projection, and the Hermes redaction layer.
Ported from apps/window/hermes_adapter/ and merged with the server.py
inline client (W113, W114): behaviour, allowlists, timeouts, size caps,
fail-closed gates and redaction rules are unchanged.
Public API
RestSurface,ENDPOINT_SPECS,resolvePath,encodeQuery,RestErrorGatewayClient(runs, sessions, chat stream),ServeClient+serveStatusGateAdDbClient,adDbQuery,adDbPublicPayload,mediaRequest,gatewayBaseUrlnormalize,derivedLabel,SequenceTracker(event envelope)EventProjection(caps, receipts, compaction, TTL prune)redactText,redactUrl,redactValue,REDACTEDconfigFromEnv()- the only process.env reader; everything else is parameters
Config
The caller passes URLs and runtime secret resolvers (apiKey: () => string).
configFromEnv() reads HERMES_ENDPOINT/HERMES_API_URL, HERMES_API_KEY,
HERMES_PROFILE, HERMES_SERVE_URL, HERMES_SERVE_TOKEN and
FRANK_PRIVATE_BRIDGE_HOSTS. Base URLs must be loopback, bridge, or https.
Example
import { configFromEnv, GatewayClient } from "@frank/hermes-client";
const env = configFromEnv();
const gw = new GatewayClient({
baseUrl: env.gatewayUrl,
apiKey: () => env.gatewayKey,
profile: env.profile,
bridgeHosts: env.bridgeHosts,
});
const { body } = await gw.submitRun({ input: "hello", idempotency_key: "ops:..." });
for await (const frame of await gw.runEventsStream(String(body.run_id))) {
// frame: { event, data, id }
}
Errors: every call throws RestError. chatStream throws on an upstream error instead of emitting SSE error/done frames like the Flask stream did; the route that relays it to the browser re-emits those frames.
Dependencies
Development dependencies
| ID | Version |
|---|---|
| @types/node | ^22.20.4 |