/** * Headroom OpenClaw Plugin — register ContextEngine + CCR retrieval tool. * * Usage: * openclaw plugins install headroom-ai/openclaw * * Configuration (in ~/.openclaw/config.json or ~/.clawdbot/clawdbot.json): * { * "plugins": { * "slots": { "contextEngine": "headroom" }, * "entries": { "headroom": { "enabled": true } } * } * } */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { HeadroomContextEngine } from "../engine.js"; import { applyGatewayProviderBaseUrlsInPlace, resolveGatewayProviderIds, } from "../gateway-config.js"; import { normalizeAndValidateProxyUrl } from "../proxy-manager.js"; import { createHeadroomRetrieveTool } from "../tools/headroom-retrieve.js"; export default function headroomPlugin(api: any) { const config = api.config?.plugins?.entries?.headroom?.config ?? {}; const logger = api.logger ?? console; const rawProxyUrl = config.proxyUrl; const proxyUrl = typeof rawProxyUrl === "string" && rawProxyUrl.trim().length > 0 ? normalizeAndValidateProxyUrl(rawProxyUrl) : undefined; const engine = new HeadroomContextEngine({ ...config, proxyUrl }, { info: (m: string) => logger.info(m), warn: (m: string) => logger.warn(m), error: (m: string) => logger.error(m), debug: (m: string) => logger.debug?.(m), }); const gatewayProviderIds = resolveGatewayProviderIds(config); const applyGatewayRouting = async (activeProxyUrl: string) => { if (gatewayProviderIds.length === 0) { return; } try { const changed = applyGatewayProviderBaseUrlsInPlace(api.config, activeProxyUrl, gatewayProviderIds); if (changed) { logger.info( `[headroom] Routed ${gatewayProviderIds.join(", ")} through Headroom proxy in memory at ${activeProxyUrl}`, ); } else { logger.info( `[headroom] Upstream gateway already routed in memory for ${gatewayProviderIds.join(", ")} at ${activeProxyUrl}`, ); } } catch (error) { logger.warn(`[headroom] Failed to configure upstream gateway routing: ${error}`); } }; const ensureGatewayRouting = async () => { const activeProxyUrl = engine.getProxyUrl(); if (!activeProxyUrl) { logger.debug?.("[headroom] Deferring upstream gateway routing until proxy is available"); engine.ensureProxyStarted(); return; } await applyGatewayRouting(activeProxyUrl); }; engine.onProxyReady(async (activeProxyUrl) => { await applyGatewayRouting(activeProxyUrl); }); // Register as context engine api.registerContextEngine("headroom", () => engine); // Register CCR retrieval tool (active once proxy is running) api.registerTool((ctx: any) => { const activeProxyUrl = engine.getProxyUrl() ?? proxyUrl; if (!activeProxyUrl) return null; return createHeadroomRetrieveTool({ proxyUrl: activeProxyUrl }); }); api.on("gateway_start", async () => { await ensureGatewayRouting(); }); void ensureGatewayRouting(); logger.info("[headroom] Plugin registered"); }