Documentation
¶
Overview ¶
Device pairing for the OpenClaw provider.
The OpenClaw gateway's connect handler strips a session's scopes to the empty set whenever the client (a) isn't openclaw-control-ui, (b) isn't gateway-client+backend on a loopback connection, and (c) hasn't completed Ed25519 device pairing — see connect-policy.ts:88-106 in openclaw/openclaw. For Tailscale / remote-host gateway access, only path (c) works.
This file implements the client side of pairing:
- Generate an Ed25519 keypair on first connect, persist the raw 32-byte keys + derived deviceId to disk.
- After the gateway emits its connect.challenge nonce, build the V3 canonical signed payload (pipe-joined UTF-8 string of [v3, deviceId, clientId, clientMode, role, scopes, signedAt, token, nonce, platform, deviceFamily]; see src/gateway/device-auth.ts:21-52) and sign it with the private key. Send the {id, publicKey, signature, signedAt, nonce} block on connect.params.device.
- Server responds with NOT_PAIRED + details.requestId on the first connect; the user runs `openclaw devices approve <requestId>` on the gateway host to grant the requested scopes.
- Next connect with the same signed payload returns hello-ok containing auth.deviceToken (an opaque base64url 32-byte string). We persist it and include it in the canonical signed payload on subsequent connects so the signature binds to the token.
Package openclaw implements the OpenClaw self-hosted gateway dashboard provider (openclaw/openclaw on GitHub).
OpenClaw is a self-hostable AI-gateway product that bridges chat channels (WhatsApp, Slack, Discord, …) to LLM-backed agents and tracks per-provider/per-model token + cost usage. The gateway listens on ws://127.0.0.1:18789 by default; users typically run it on their dev box or a Tailscale node, so the base URL is user-configurable in the PI per provider with per-button override.
Auth: a shared "operator" gateway token, same scope the dashboard frontend uses. Pasted in PI / OPENCLAW_GATEWAY_TOKEN env. The gateway protocol is WebSocket JSON-RPC — no REST surface for these metrics. Fresh WS per Fetch() (typical poll interval is 15 min; connect overhead is negligible).
Method called: usage.cost with { days: N } for the {1, 7, 30}-day windows we expose. Response shape is CostUsageSummary, with totals {input, output, cacheRead, cacheWrite, totalTokens, totalCost}.
Source pointers (commit-pinned, openclaw/openclaw):
src/gateway/server-methods/usage.ts:391-433 — usage.cost handler src/infra/session-cost-usage.types.ts:37-62 — CostUsageTotals src/gateway/protocol/client-info.ts:3-19 — GATEWAY_CLIENT_IDS ui/src/ui/gateway.ts:298-340 — WS protocol ui/src/ui/gateway.ts:416-435 — connect params docs/gateway/protocol.md — protocol overview
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CostUsageSummary ¶
type CostUsageSummary struct {
UpdatedAt int64 `json:"updatedAt"`
Days int `json:"days"`
Totals CostUsageTotals `json:"totals"`
}
CostUsageSummary is the usage.cost response payload — see src/infra/session-cost-usage.types.ts:56-62.
type CostUsageTotals ¶
type CostUsageTotals struct {
Input float64 `json:"input"`
Output float64 `json:"output"`
CacheRead float64 `json:"cacheRead"`
CacheWrite float64 `json:"cacheWrite"`
TotalTokens float64 `json:"totalTokens"`
TotalCost float64 `json:"totalCost"`
InputCost float64 `json:"inputCost"`
OutputCost float64 `json:"outputCost"`
CacheReadCost float64 `json:"cacheReadCost"`
CacheWriteCost float64 `json:"cacheWriteCost"`
}
CostUsageTotals mirrors the server's response shape — see src/infra/session-cost-usage.types.ts:37-50.
type Provider ¶
type Provider struct{}
Provider fetches OpenClaw gateway usage data.
func (Provider) BrandBg ¶
BrandBg returns a deep-red complement. Tuned warmer than the previous near-black so the empty-meter state reads as "OpenClaw red" instead of generic brown.
func (Provider) BrandColor ¶
BrandColor returns the meter-fill accent. Matches the lobster's brighter gradient stop in OpenClaw's favicon (ui/public/favicon.svg, #ff4d4d) — vibrant brand red.