headroom-openclaw 0.37.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/README.md +2 -2
- package/dist/index.d.ts +34 -27
- package/dist/index.js +17 -21
- package/dist/index.js.map +1 -1
- package/dist/package.json +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -215,8 +215,8 @@ Compression is lossless via CCR (Compress-Cache-Retrieve): originals are stored
|
|
|
215
215
|
|
|
216
216
|
| | lossless-claw | headroom |
|
|
217
217
|
|---|---|---|
|
|
218
|
-
| Compaction method | LLM summarization (DAG) |
|
|
219
|
-
| Cost of compaction | Tokens (LLM calls) |
|
|
218
|
+
| Compaction method | LLM summarization (DAG) | OpenClaw native compaction (delegated) |
|
|
219
|
+
| Cost of compaction | Tokens (LLM calls) | OpenClaw configuration-dependent |
|
|
220
220
|
| Best for | Long conversations | Tool-heavy agents with large outputs |
|
|
221
221
|
| Retrieval | `lcm_grep`, `lcm_expand` | `headroom_retrieve` (instant) |
|
|
222
222
|
|
package/dist/README.md
CHANGED
|
@@ -215,8 +215,8 @@ Compression is lossless via CCR (Compress-Cache-Retrieve): originals are stored
|
|
|
215
215
|
|
|
216
216
|
| | lossless-claw | headroom |
|
|
217
217
|
|---|---|---|
|
|
218
|
-
| Compaction method | LLM summarization (DAG) |
|
|
219
|
-
| Cost of compaction | Tokens (LLM calls) |
|
|
218
|
+
| Compaction method | LLM summarization (DAG) | OpenClaw native compaction (delegated) |
|
|
219
|
+
| Cost of compaction | Tokens (LLM calls) | OpenClaw configuration-dependent |
|
|
220
220
|
| Best for | Long conversations | Tool-heavy agents with large outputs |
|
|
221
221
|
| Retrieval | `lcm_grep`, `lcm_expand` | `headroom_retrieve` (instant) |
|
|
222
222
|
|
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
/**
|
|
16
16
|
* OpenClaw 2026.x plugin API requires a `{ register(api) }` object export.
|
|
17
17
|
* The previous bare-function default export was silently skipped by the loader.
|
|
18
|
-
* See: https://github.com/
|
|
18
|
+
* See: https://github.com/headroomlabs-ai/headroom/issues/XXX
|
|
19
19
|
*/
|
|
20
20
|
declare const _default: {
|
|
21
21
|
register: typeof registerHeadroomPlugin;
|
|
@@ -77,6 +77,37 @@ declare function isLocalProxyUrl(proxyUrl: string): boolean;
|
|
|
77
77
|
*/
|
|
78
78
|
declare function probeHeadroomProxy(proxyUrl: string): Promise<ProxyProbeResult>;
|
|
79
79
|
|
|
80
|
+
interface OpenClawCompactParams {
|
|
81
|
+
sessionId: string;
|
|
82
|
+
sessionKey?: string;
|
|
83
|
+
agentId?: string;
|
|
84
|
+
sessionTarget?: unknown;
|
|
85
|
+
sessionFile?: string;
|
|
86
|
+
tokenBudget?: number;
|
|
87
|
+
force?: boolean;
|
|
88
|
+
currentTokenCount?: number;
|
|
89
|
+
compactionTarget?: "budget" | "threshold";
|
|
90
|
+
customInstructions?: string;
|
|
91
|
+
runtimeSettings?: unknown;
|
|
92
|
+
runtimeContext?: unknown;
|
|
93
|
+
abortSignal?: AbortSignal;
|
|
94
|
+
}
|
|
95
|
+
interface OpenClawCompactResult {
|
|
96
|
+
ok: boolean;
|
|
97
|
+
compacted: boolean;
|
|
98
|
+
reason?: string;
|
|
99
|
+
result?: {
|
|
100
|
+
summary?: string;
|
|
101
|
+
firstKeptEntryId?: string;
|
|
102
|
+
tokensBefore: number;
|
|
103
|
+
tokensAfter?: number;
|
|
104
|
+
details?: unknown;
|
|
105
|
+
sessionId?: string;
|
|
106
|
+
sessionTarget?: unknown;
|
|
107
|
+
sessionFile?: string;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
80
111
|
/**
|
|
81
112
|
* HeadroomContextEngine — ContextEngine implementation for OpenClaw.
|
|
82
113
|
*
|
|
@@ -145,32 +176,8 @@ declare class HeadroomContextEngine {
|
|
|
145
176
|
estimatedTokens: number;
|
|
146
177
|
systemPromptAddition?: string;
|
|
147
178
|
}>;
|
|
148
|
-
/**
|
|
149
|
-
|
|
150
|
-
*
|
|
151
|
-
* Calls compress() with the token budget, which triggers:
|
|
152
|
-
* - SmartCrusher: aggressive JSON compression (70-90% on tool outputs)
|
|
153
|
-
* - Kompress: ModernBERT text compression (40-60% on assistant text)
|
|
154
|
-
* - RollingWindow: drops oldest messages if still over budget
|
|
155
|
-
* - CCR: stores originals for retrieval via headroom_retrieve tool
|
|
156
|
-
*
|
|
157
|
-
* Zero LLM calls. All algorithmic.
|
|
158
|
-
*/
|
|
159
|
-
compact(params: {
|
|
160
|
-
sessionId: string;
|
|
161
|
-
sessionFile: string;
|
|
162
|
-
tokenBudget?: number;
|
|
163
|
-
force?: boolean;
|
|
164
|
-
runtimeContext?: any;
|
|
165
|
-
}): Promise<{
|
|
166
|
-
ok: boolean;
|
|
167
|
-
compacted: boolean;
|
|
168
|
-
reason?: string;
|
|
169
|
-
result?: {
|
|
170
|
-
tokensBefore: number;
|
|
171
|
-
tokensAfter?: number;
|
|
172
|
-
};
|
|
173
|
-
}>;
|
|
179
|
+
/** Delegate persistent compaction to OpenClaw's built-in runtime. */
|
|
180
|
+
compact(params: OpenClawCompactParams): Promise<OpenClawCompactResult>;
|
|
174
181
|
afterTurn?(params: {
|
|
175
182
|
sessionId: string;
|
|
176
183
|
messages: any[];
|
package/dist/index.js
CHANGED
|
@@ -668,6 +668,16 @@ function isRecord(value) {
|
|
|
668
668
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
669
669
|
}
|
|
670
670
|
|
|
671
|
+
// src/openclaw-compaction.ts
|
|
672
|
+
var OPENCLAW_PLUGIN_SDK_CORE = "openclaw/plugin-sdk/core";
|
|
673
|
+
async function delegateCompactionToRuntime(params) {
|
|
674
|
+
const pluginSdk = await import(OPENCLAW_PLUGIN_SDK_CORE);
|
|
675
|
+
if (!pluginSdk.delegateCompactionToRuntime) {
|
|
676
|
+
throw new Error("OpenClaw runtime does not expose delegateCompactionToRuntime");
|
|
677
|
+
}
|
|
678
|
+
return pluginSdk.delegateCompactionToRuntime(params);
|
|
679
|
+
}
|
|
680
|
+
|
|
671
681
|
// src/engine.ts
|
|
672
682
|
function withTimeout(promise, ms) {
|
|
673
683
|
let timerId;
|
|
@@ -683,7 +693,7 @@ var HeadroomContextEngine = class {
|
|
|
683
693
|
id: "headroom",
|
|
684
694
|
name: "Headroom Context Compression",
|
|
685
695
|
version: "0.1.0",
|
|
686
|
-
ownsCompaction:
|
|
696
|
+
ownsCompaction: false
|
|
687
697
|
};
|
|
688
698
|
proxyManager;
|
|
689
699
|
proxyUrl = null;
|
|
@@ -769,30 +779,16 @@ var HeadroomContextEngine = class {
|
|
|
769
779
|
return { messages: normalizeAgentMessages(params.messages), estimatedTokens: 0 };
|
|
770
780
|
}
|
|
771
781
|
}
|
|
772
|
-
/**
|
|
773
|
-
* Compact context — zero-cost alternative to LLM summarization.
|
|
774
|
-
*
|
|
775
|
-
* Calls compress() with the token budget, which triggers:
|
|
776
|
-
* - SmartCrusher: aggressive JSON compression (70-90% on tool outputs)
|
|
777
|
-
* - Kompress: ModernBERT text compression (40-60% on assistant text)
|
|
778
|
-
* - RollingWindow: drops oldest messages if still over budget
|
|
779
|
-
* - CCR: stores originals for retrieval via headroom_retrieve tool
|
|
780
|
-
*
|
|
781
|
-
* Zero LLM calls. All algorithmic.
|
|
782
|
-
*/
|
|
782
|
+
/** Delegate persistent compaction to OpenClaw's built-in runtime. */
|
|
783
783
|
async compact(params) {
|
|
784
|
-
|
|
785
|
-
|
|
784
|
+
const result = await delegateCompactionToRuntime(params);
|
|
785
|
+
if (result.compacted) {
|
|
786
|
+
this.stats.compactions++;
|
|
786
787
|
}
|
|
787
|
-
this.stats.compactions++;
|
|
788
788
|
this.logger.info(
|
|
789
|
-
`
|
|
789
|
+
`Compaction ${result.compacted ? "completed" : "skipped"} (budget: ${params.tokenBudget ?? "none"}, force: ${params.force ?? false})`
|
|
790
790
|
);
|
|
791
|
-
return
|
|
792
|
-
ok: true,
|
|
793
|
-
compacted: true,
|
|
794
|
-
reason: "Headroom applies SmartCrusher + Kompress + RollingWindow on next assemble()"
|
|
795
|
-
};
|
|
791
|
+
return result;
|
|
796
792
|
}
|
|
797
793
|
async afterTurn(params) {
|
|
798
794
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/engine.ts","../src/proxy-manager.ts","../src/convert.ts","../src/gateway-config.ts","../src/tools/headroom-retrieve.ts","../src/plugin/index.ts"],"sourcesContent":["/**\n * HeadroomContextEngine — ContextEngine implementation for OpenClaw.\n *\n * Compresses tool outputs and conversation context using the Headroom proxy.\n * Zero LLM calls — all compression is algorithmic (SmartCrusher, ContentRouter, etc.)\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { compress } from \"headroom-ai\";\nimport { ProxyManager, defaultLogger, type ProxyManagerConfig, type ProxyManagerLogger } from \"./proxy-manager.js\";\nimport { agentToOpenAI, normalizeAgentMessages, openAIToAgent } from \"./convert.js\";\n\n/** Race a promise against a timeout and always release the timer. */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n let timerId: ReturnType<typeof setTimeout> | undefined;\n const timer = new Promise<never>((_, reject) => {\n timerId = setTimeout(() => reject(new Error(`headroom compress() timed out after ${ms}ms`)), ms);\n });\n return Promise.race([promise, timer]).finally(() => {\n if (timerId !== undefined) clearTimeout(timerId);\n });\n}\n\nexport interface HeadroomEngineConfig extends ProxyManagerConfig {\n enabled?: boolean;\n requestTimeoutMs?: number;\n circuitBreakerThreshold?: number;\n circuitBreakerCooldownMs?: number;\n}\n\nexport class HeadroomContextEngine {\n readonly info = {\n id: \"headroom\",\n name: \"Headroom Context Compression\",\n version: \"0.1.0\",\n ownsCompaction: true,\n };\n\n private proxyManager: ProxyManager;\n private proxyUrl: string | null = null;\n private config: HeadroomEngineConfig;\n private logger: ProxyManagerLogger;\n private proxyReadyListeners = new Set<(proxyUrl: string) => void | Promise<void>>();\n private proxyStartupPromise: Promise<string> | null = null;\n private proxyStartupError: unknown = null;\n private stats = {\n totalCompressions: 0,\n totalTokensSaved: 0,\n totalTokensBefore: 0,\n compactions: 0,\n };\n private circuit = { errors: 0, openUntilMs: 0 };\n\n constructor(config: HeadroomEngineConfig = {}, logger?: ProxyManagerLogger) {\n this.config = config;\n this.logger = logger ?? defaultLogger;\n this.proxyManager = new ProxyManager(config, this.logger);\n }\n\n // === ContextEngine Lifecycle ===\n\n async bootstrap(params: {\n sessionId: string;\n sessionKey?: string;\n sessionFile: string;\n }): Promise<{ bootstrapped: boolean; reason?: string }> {\n if (this.config.enabled === false) {\n return { bootstrapped: false, reason: \"disabled\" };\n }\n\n this.ensureProxyStarted();\n return { bootstrapped: true, reason: \"proxy startup scheduled\" };\n }\n\n async ingest(params: {\n sessionId: string;\n message: any;\n isHeartbeat?: boolean;\n }): Promise<{ ingested: boolean }> {\n // No-op: OpenClaw's runtime stores messages. We don't need a separate store.\n return { ingested: true };\n }\n\n async ingestBatch?(params: {\n sessionId: string;\n messages: any[];\n isHeartbeat?: boolean;\n }): Promise<{ ingestedCount: number }> {\n return { ingestedCount: params.messages.length };\n }\n\n /**\n * Assemble context for the model — THE CORE HOOK.\n *\n * Converts AgentMessage[] → OpenAI format → compress() → AgentMessage[]\n */\n async assemble(params: {\n sessionId: string;\n messages: any[];\n tokenBudget?: number;\n model?: string;\n prompt?: string;\n }): Promise<{\n messages: any[];\n estimatedTokens: number;\n systemPromptAddition?: string;\n }> {\n if (!this.proxyUrl || this.config.enabled === false) {\n this.ensureProxyStarted();\n // Fallback: return messages unchanged\n return { messages: normalizeAgentMessages(params.messages), estimatedTokens: 0 };\n }\n\n if (this.isCircuitOpen()) {\n this.logger.warn(\"[headroom] Circuit open — using uncompressed messages\");\n return { messages: normalizeAgentMessages(params.messages), estimatedTokens: 0 };\n }\n\n try {\n // Convert AgentMessage → OpenAI format\n const openaiMessages = agentToOpenAI(params.messages);\n\n // Compress via proxy — pass tokenBudget so RollingWindow enforces it\n const result = await withTimeout(\n compress(openaiMessages, {\n model: params.model ?? \"claude-sonnet-4-5\",\n baseUrl: this.proxyUrl,\n fallback: true,\n tokenBudget: params.tokenBudget,\n } as any),\n this.config.requestTimeoutMs ?? 30_000,\n );\n\n if (!result.compressed || result.tokensSaved === 0) {\n this.resetCircuit();\n return {\n messages: normalizeAgentMessages(params.messages),\n estimatedTokens: result.tokensBefore,\n };\n }\n\n // Convert back to AgentMessage format\n const compressedAgentMessages = openAIToAgent(result.messages);\n this.resetCircuit();\n\n // Track stats\n this.stats.totalCompressions++;\n this.stats.totalTokensSaved += result.tokensSaved;\n this.stats.totalTokensBefore += result.tokensBefore;\n\n this.logger.debug(\n `Assembled: ${result.tokensBefore} → ${result.tokensAfter} tokens (saved ${result.tokensSaved})`,\n );\n\n return {\n messages: compressedAgentMessages,\n estimatedTokens: result.tokensAfter,\n systemPromptAddition:\n result.tokensSaved > 100\n ? `[Context compressed by Headroom: ${result.tokensSaved} tokens saved. Use headroom_retrieve with the hash to get full details.]`\n : undefined,\n };\n } catch (error) {\n this.logger.error(`Assemble failed: ${error}`);\n this.tripCircuit(error);\n // Graceful fallback: return original messages\n return { messages: normalizeAgentMessages(params.messages), estimatedTokens: 0 };\n }\n }\n\n /**\n * Compact context — zero-cost alternative to LLM summarization.\n *\n * Calls compress() with the token budget, which triggers:\n * - SmartCrusher: aggressive JSON compression (70-90% on tool outputs)\n * - Kompress: ModernBERT text compression (40-60% on assistant text)\n * - RollingWindow: drops oldest messages if still over budget\n * - CCR: stores originals for retrieval via headroom_retrieve tool\n *\n * Zero LLM calls. All algorithmic.\n */\n async compact(params: {\n sessionId: string;\n sessionFile: string;\n tokenBudget?: number;\n force?: boolean;\n runtimeContext?: any;\n }): Promise<{\n ok: boolean;\n compacted: boolean;\n reason?: string;\n result?: {\n tokensBefore: number;\n tokensAfter?: number;\n };\n }> {\n if (!this.proxyUrl) {\n return { ok: false, compacted: false, reason: \"Proxy not available\" };\n }\n\n // Read current messages from session file if available\n // For now, compact() works in tandem with assemble() — the next assemble()\n // call will compress with the token budget. When compact() is called\n // independently, we report success since our pipeline handles it.\n //\n // TODO: Read session file, extract messages, call compress() with tokenBudget,\n // write back compacted messages.\n\n this.stats.compactions++;\n this.logger.info(\n `Compact called (budget: ${params.tokenBudget ?? \"none\"}, force: ${params.force ?? false})`,\n );\n\n return {\n ok: true,\n compacted: true,\n reason: \"Headroom applies SmartCrusher + Kompress + RollingWindow on next assemble()\",\n };\n }\n\n async afterTurn?(params: {\n sessionId: string;\n messages: any[];\n prePromptMessageCount: number;\n isHeartbeat?: boolean;\n }): Promise<void> {\n // Optional: could log stats or trigger learning\n }\n\n async prepareSubagentSpawn?(params: {\n parentSessionKey: string;\n childSessionKey: string;\n ttlMs?: number;\n }): Promise<{ rollback: () => Promise<void> } | undefined> {\n // Subagent context is compressed naturally via assemble()\n return undefined;\n }\n\n async onSubagentEnded?(params: {\n childSessionKey: string;\n reason: string;\n }): Promise<void> {\n // No-op\n }\n\n async dispose(): Promise<void> {\n await this.proxyManager.stop();\n this.logger.info(\n `Engine disposed. Stats: ${this.stats.totalCompressions} compressions, ` +\n `${this.stats.totalTokensSaved} tokens saved`,\n );\n }\n\n // --- Public API ---\n\n getStats() {\n return { ...this.stats };\n }\n\n getProxyUrl(): string | null {\n return this.proxyUrl;\n }\n\n getProxyStartupError(): unknown {\n return this.proxyStartupError;\n }\n\n private isCircuitOpen(): boolean {\n const threshold = this.config.circuitBreakerThreshold ?? 3;\n if (this.circuit.errors < threshold) return false;\n if (Date.now() < this.circuit.openUntilMs) return true;\n this.circuit = { errors: 0, openUntilMs: 0 };\n return false;\n }\n\n private tripCircuit(error: unknown): void {\n this.circuit.errors += 1;\n const threshold = this.config.circuitBreakerThreshold ?? 3;\n if (this.circuit.errors < threshold) return;\n const cooldownMs = this.config.circuitBreakerCooldownMs ?? 60_000;\n this.circuit.openUntilMs = Date.now() + cooldownMs;\n this.logger.warn(\n `[headroom] Circuit breaker opened after ${this.circuit.errors} errors ` +\n `(last: ${String(error)}); bypassing compression for ${cooldownMs}ms`,\n );\n }\n\n private resetCircuit(): void {\n this.circuit = { errors: 0, openUntilMs: 0 };\n }\n\n ensureProxyStarted(): void {\n if (this.config.enabled === false || this.proxyUrl || this.proxyStartupPromise) {\n return;\n }\n\n this.proxyStartupError = null;\n this.proxyStartupPromise = this.proxyManager\n .start()\n .then(async (proxyUrl) => {\n this.proxyUrl = proxyUrl;\n this.proxyStartupError = null;\n await this.notifyProxyReady(proxyUrl);\n this.logger.info(`Headroom proxy ready at ${proxyUrl}`);\n return proxyUrl;\n })\n .catch((error) => {\n this.proxyStartupError = error;\n this.logger.warn(`Headroom proxy unavailable: ${error}`);\n throw error;\n })\n .finally(() => {\n this.proxyStartupPromise = null;\n });\n\n // Fire-and-forget lifecycle callers intentionally do not await this promise.\n // Keep the promise rejectable for ensureProxyUrl(), but mark it observed so\n // a missing proxy cannot become a process-level unhandled rejection.\n void this.proxyStartupPromise.catch(() => {});\n }\n\n onProxyReady(listener: (proxyUrl: string) => void | Promise<void>): () => void {\n this.proxyReadyListeners.add(listener);\n return () => {\n this.proxyReadyListeners.delete(listener);\n };\n }\n\n async ensureProxyUrl(): Promise<string> {\n if (this.proxyUrl) {\n return this.proxyUrl;\n }\n\n this.ensureProxyStarted();\n if (!this.proxyStartupPromise) {\n throw new Error(\"Headroom proxy startup is disabled\");\n }\n return this.proxyStartupPromise;\n }\n\n private async notifyProxyReady(proxyUrl: string): Promise<void> {\n for (const listener of this.proxyReadyListeners) {\n try {\n await listener(proxyUrl);\n } catch (error) {\n this.logger.warn(`Headroom proxy ready listener failed: ${error}`);\n }\n }\n }\n}\n","/**\n * Manages connectivity to a Headroom proxy (local or remote).\n *\n * Security model:\n * - Local proxies (127.0.0.1 / localhost) can be auto-started via subprocess\n * - Remote proxies are connect-only: probe and use, never launch\n * - No environment variable access\n */\nimport { spawn } from \"node:child_process\";\nimport { spawnSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport os from \"os\";\n\nexport interface ProxyManagerConfig {\n proxyUrl?: string;\n proxyPort?: number;\n pythonPath?: string;\n autoStart?: boolean;\n startupTimeoutMs?: number;\n retryMaxAttempts?: number;\n connectTimeoutSeconds?: number;\n}\n\nexport interface ProxyManagerLogger {\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n debug(message: string): void;\n}\n\n/** Default logger that prefixes all messages with `[headroom]`. */\nexport const defaultLogger: ProxyManagerLogger = {\n info: (m) => console.log(`[headroom] ${m}`),\n warn: (m) => console.warn(`[headroom] ${m}`),\n error: (m) => console.error(`[headroom] ${m}`),\n debug: () => {},\n};\n\nexport interface ProxyProbeResult {\n reachable: boolean;\n isHeadroom: boolean;\n reason?: string;\n}\n\ninterface LaunchSpec {\n label: string;\n command: string;\n args: string[];\n checkCommand: string;\n checkArgs: string[];\n useShell?: boolean;\n checkUseShell?: boolean;\n}\n\nconst HEADROOM_MODULE_DISCOVERY_SNIPPET =\n \"import importlib.util, sys; sys.exit(0 if importlib.util.find_spec('headroom') else 1)\";\n\nexport class ProxyManager {\n private config: ProxyManagerConfig;\n private logger: ProxyManagerLogger;\n private proxyUrl: string | null = null;\n\n constructor(config: ProxyManagerConfig = {}, logger?: ProxyManagerLogger) {\n this.config = config;\n this.logger = logger ?? defaultLogger;\n }\n\n /**\n * Ensure a proxy is available. Returns the normalized URL origin.\n */\n async start(): Promise<string> {\n const port = this.getProxyPort();\n const rawExplicitUrl =\n typeof this.config.proxyUrl === \"string\" && this.config.proxyUrl.trim().length > 0\n ? normalizeAndValidateProxyUrl(this.config.proxyUrl)\n : null;\n // Only apply proxyPort default to local URLs — remote URLs use their protocol default\n const explicitUrl = rawExplicitUrl\n ? isLocalProxyUrl(rawExplicitUrl) ? withDefaultPort(rawExplicitUrl, port) : rawExplicitUrl\n : null;\n const defaultCandidates = this.getDefaultProxyCandidates(port);\n const candidateUrls = explicitUrl ? [explicitUrl] : [...defaultCandidates];\n const probeByUrl = new Map<string, ProxyProbeResult>();\n\n for (const url of candidateUrls) {\n const probe = await probeHeadroomProxy(url);\n probeByUrl.set(url, probe);\n if (probe.reachable && probe.isHeadroom) {\n this.proxyUrl = url;\n this.logger.info(`Headroom proxy already running at ${url}`);\n return url;\n }\n }\n\n if (explicitUrl) {\n const explicitProbe = probeByUrl.get(explicitUrl);\n if (explicitProbe?.reachable && !explicitProbe.isHeadroom) {\n throw new Error(\n `Service reachable at ${explicitUrl}, but it does not appear to be a Headroom proxy (${explicitProbe.reason ?? \"unknown service\"}).`,\n );\n }\n }\n\n // Remote URLs are connect-only — never auto-start a subprocess for them\n if (explicitUrl && !isLocalProxyUrl(explicitUrl)) {\n throw new Error(\n `Remote Headroom proxy not reachable at ${explicitUrl}. Ensure the proxy is running at that address.`,\n );\n }\n\n // Auto-start is only available for local proxies\n if (this.config.autoStart === true) {\n const startupUrl = explicitUrl ?? defaultCandidates[0];\n const startupProbe = probeByUrl.get(startupUrl);\n if (startupProbe?.reachable && !startupProbe.isHeadroom) {\n throw new Error(\n `Cannot auto-start Headroom at ${startupUrl}: port is in use by a non-Headroom service (${startupProbe.reason ?? \"unknown service\"}).`,\n );\n }\n\n this.logger.info(\n `No Headroom proxy detected${explicitUrl ? ` at ${startupUrl}` : \" on default local endpoints\"}; attempting to auto-start...`,\n );\n await this.startHeadroomProxy(startupUrl, port);\n\n const startedProbe = await waitForHeadroomProxy(\n startupUrl,\n this.config.startupTimeoutMs ?? 20_000,\n );\n if (startedProbe.reachable && startedProbe.isHeadroom) {\n this.proxyUrl = startupUrl;\n this.logger.info(`Headroom proxy started and reachable at ${startupUrl}`);\n return startupUrl;\n }\n throw new Error(\n `Attempted to start Headroom proxy, but it was not reachable at ${startupUrl} (${startedProbe.reason ?? \"unknown\"}).`,\n );\n }\n\n if (explicitUrl) {\n throw new Error(\n `Headroom proxy not reachable at ${explicitUrl}. Ensure the proxy is running first.`,\n );\n }\n\n throw new Error(\n `Headroom proxy not detected on default endpoints (${defaultCandidates.join(\", \")}). ` +\n \"Set proxyUrl explicitly or enable autoStart.\",\n );\n }\n\n private getProxyPort(): number {\n const rawPort = this.config.proxyPort;\n if (!Number.isInteger(rawPort) || rawPort === undefined) return 8787;\n if (rawPort < 1 || rawPort > 65535) {\n throw new Error(\"proxyPort must be an integer between 1 and 65535\");\n }\n return rawPort;\n }\n\n private getDefaultProxyCandidates(port: number): string[] {\n return [`http://127.0.0.1:${port}`, `http://localhost:${port}`];\n }\n\n /**\n * Stop manager state. Spawned proxy processes are detached and externally managed.\n */\n async stop(): Promise<void> {\n this.proxyUrl = null;\n }\n\n getUrl(): string | null {\n return this.proxyUrl;\n }\n\n // --- Internal ---\n\n private async startHeadroomProxy(proxyUrl: string, defaultPort: number): Promise<void> {\n const parsed = new URL(proxyUrl);\n const host = parsed.hostname;\n const port = parsed.port || String(defaultPort);\n const specs = this.buildLaunchSpecs(host, port);\n const errors: string[] = [];\n\n for (const spec of specs) {\n if (!this.canExecute(spec.checkCommand, spec.checkArgs, spec.checkUseShell ?? spec.useShell)) {\n this.logger.debug(`Launcher unavailable: ${spec.label}`);\n continue;\n }\n\n try {\n const child = spawn(spec.command, spec.args, {\n detached: true,\n shell: spec.useShell === true,\n stdio: \"ignore\",\n });\n child.unref();\n this.logger.info(`Auto-start launcher selected: ${spec.label}`);\n return;\n } catch (error) {\n errors.push(`${spec.label}: ${String(error)}`);\n }\n }\n\n throw new Error(\n \"No usable Headroom launcher found. Tried PATH, local npm, global npm, and Python. \" +\n \"Install headroom-ai (npm or pip) and ensure one launcher is available.\\n\" +\n (errors.length > 0 ? `Launch errors: ${errors.join(\"; \")}` : \"\"),\n );\n }\n\n private buildLaunchSpecs(host: string, port: string): LaunchSpec[] {\n const commonArgs = [\"proxy\", \"--host\", host, \"--port\", port];\n const retryMaxAttempts = this.config.retryMaxAttempts;\n if (Number.isInteger(retryMaxAttempts)) {\n commonArgs.push(\"--retry-max-attempts\", String(retryMaxAttempts));\n }\n\n const connectTimeoutSeconds = this.config.connectTimeoutSeconds;\n if (Number.isInteger(connectTimeoutSeconds)) {\n commonArgs.push(\"--connect-timeout-seconds\", String(connectTimeoutSeconds));\n }\n\n const specs: LaunchSpec[] = [];\n\n const configuredPython = this.getConfiguredPythonCommand();\n if (configuredPython) {\n specs.push({\n label: `Configured Python: ${configuredPython} -m headroom.cli`,\n command: configuredPython,\n args: [\"-m\", \"headroom.cli\", ...commonArgs],\n checkCommand: configuredPython,\n checkArgs: [\"-c\", HEADROOM_MODULE_DISCOVERY_SNIPPET],\n });\n }\n\n // 2) Windows pyenv: resolve the real executable so we avoid shim .bat wrappers.\n if (process.platform === \"win32\") {\n const pyenvHeadroom = this.getPyenvResolvedHeadroom();\n if (pyenvHeadroom) {\n specs.push({\n label: `pyenv: ${pyenvHeadroom}`,\n command: pyenvHeadroom,\n args: commonArgs,\n checkCommand: pyenvHeadroom,\n checkArgs: [\"--version\"],\n useShell: false,\n });\n }\n }\n\n // 3) PATH\n specs.push({\n label: \"PATH: headroom\",\n command: \"headroom\",\n args: commonArgs,\n checkCommand: process.platform === \"win32\" ? \"where.exe\" : \"sh\",\n checkArgs: process.platform === \"win32\"\n ? [\"headroom\"]\n : [\"-c\", \"command -v headroom >/dev/null 2>&1\"],\n useShell: process.platform === \"win32\",\n checkUseShell: false,\n });\n\n // 4) uv tool install path (~/.local/bin/headroom)\n const uvBin = join(\n os.homedir(),\n \".local\", \"bin\", \"headroom\"\n );\n if (existsSync(uvBin)) {\n specs.push({\n label: `uv tool: ${uvBin}`,\n command: uvBin,\n args: commonArgs,\n checkCommand: uvBin,\n checkArgs: [\"--version\"],\n });\n }\n\n // 5) Local npm install (inside plugin install path)\n const moduleDir = dirname(fileURLToPath(import.meta.url)); // .../dist\n const packageRoot = dirname(moduleDir);\n const localBinDir = join(packageRoot, \"node_modules\", \".bin\");\n const localBins = process.platform === \"win32\"\n ? [join(localBinDir, \"headroom.cmd\"), join(localBinDir, \"headroom\")]\n : [join(localBinDir, \"headroom\")];\n for (const localBin of localBins) {\n if (!existsSync(localBin)) continue;\n specs.push({\n label: `Local npm: ${localBin}`,\n command: localBin,\n args: commonArgs,\n checkCommand: localBin,\n checkArgs: [\"--version\"],\n useShell: process.platform === \"win32\",\n });\n }\n\n // 5) Global npm install\n const npmPrefix = this.getNpmGlobalPrefix();\n if (npmPrefix) {\n const globalBins = process.platform === \"win32\"\n ? [join(npmPrefix, \"headroom.cmd\"), join(npmPrefix, \"headroom\")]\n : [join(npmPrefix, \"bin\", \"headroom\"), join(npmPrefix, \"headroom\")];\n\n for (const globalBin of globalBins) {\n if (!existsSync(globalBin)) continue;\n specs.push({\n label: `Global npm: ${globalBin}`,\n command: globalBin,\n args: commonArgs,\n checkCommand: globalBin,\n checkArgs: [\"--version\"],\n useShell: process.platform === \"win32\",\n });\n }\n }\n\n // 6) Python module fallback\n const pythonCommands = this.getPythonCommands();\n for (const pyCmd of pythonCommands) {\n if (configuredPython && pyCmd === configuredPython) continue;\n specs.push({\n label: `Python: ${pyCmd} -m headroom.cli`,\n command: pyCmd,\n args: [\"-m\", \"headroom.cli\", ...commonArgs],\n checkCommand: pyCmd,\n checkArgs: [\"-c\", HEADROOM_MODULE_DISCOVERY_SNIPPET],\n });\n }\n\n return specs;\n }\n\n private getConfiguredPythonCommand(): string | null {\n const configured = typeof this.config.pythonPath === \"string\"\n ? this.config.pythonPath.trim()\n : \"\";\n return configured.length > 0 ? configured : null;\n }\n\n private getPyenvResolvedHeadroom(): string | null {\n if (process.platform !== \"win32\") return null;\n\n try {\n const result = spawnSync(\"pyenv\", [\"which\", \"headroom\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 5000,\n });\n if (result.error || result.status !== 0) return null;\n const resolved = (result.stdout ?? \"\").trim().split(/\\r?\\n/, 1)[0];\n if (!resolved || !existsSync(resolved)) return null;\n return resolved;\n } catch {\n return null;\n }\n }\n\n private getPythonCommands(): string[] {\n const commands: string[] = [];\n const configured = this.getConfiguredPythonCommand() ?? \"\";\n if (configured.length > 0) {\n commands.push(configured);\n }\n for (const fallback of [\"python\", \"python3\", \"py\"]) {\n if (!commands.includes(fallback)) commands.push(fallback);\n }\n return commands;\n }\n\n private canExecute(command: string, args: string[], useShell = false): boolean {\n try {\n const result = spawnSync(command, args, {\n shell: useShell,\n stdio: \"ignore\",\n timeout: 5000,\n });\n if (result.error) return false;\n return result.status === 0;\n } catch {\n return false;\n }\n }\n\n private getNpmGlobalPrefix(): string | null {\n try {\n const result = spawnSync(\"npm\", [\"prefix\", \"-g\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 5000,\n });\n if (result.error || result.status !== 0) return null;\n const prefix = (result.stdout ?? \"\").trim();\n return prefix.length > 0 ? prefix : null;\n } catch {\n return null;\n }\n }\n}\n\n/** Parse a URL, returning the parsed object or throwing a descriptive error. */\nfunction parseProxyUrl(proxyUrl: string): URL {\n try {\n return new URL(proxyUrl);\n } catch {\n throw new Error(`Invalid proxyUrl: \"${proxyUrl}\"`);\n }\n}\n\nexport function normalizeAndValidateProxyUrl(proxyUrl: string): string {\n const parsed = parseProxyUrl(proxyUrl);\n\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new Error(\"proxyUrl must use http:// or https://\");\n }\n\n if (parsed.pathname !== \"/\" || parsed.search || parsed.hash) {\n throw new Error(\"proxyUrl must not include a path, query, or hash\");\n }\n\n return parsed.origin;\n}\n\n/** Returns true if the URL points to a local address (localhost or 127.0.0.1). */\nexport function isLocalProxyUrl(proxyUrl: string): boolean {\n try {\n const parsed = new URL(proxyUrl);\n return parsed.hostname === \"127.0.0.1\" || parsed.hostname === \"localhost\";\n } catch {\n return false;\n }\n}\n\nfunction withDefaultPort(proxyUrl: string, defaultPort: number): string {\n const parsed = parseProxyUrl(proxyUrl);\n if (!parsed.port) {\n parsed.port = String(defaultPort);\n }\n return parsed.origin;\n}\n\n/**\n * Probe a configured URL and verify whether it is a running Headroom proxy.\n */\nexport async function probeHeadroomProxy(proxyUrl: string): Promise<ProxyProbeResult> {\n const origin = normalizeAndValidateProxyUrl(proxyUrl);\n const probeEndpoint = async (\n path: string,\n options: { readBody?: boolean } = {},\n ): Promise<{ reachable: boolean; ok: boolean; status?: number; body?: string }> => {\n try {\n const response = await fetch(`${origin}${path}`, {\n signal: AbortSignal.timeout(3_000),\n });\n const body =\n response.ok && options.readBody\n ? await response.text().catch(() => undefined)\n : undefined;\n return { reachable: true, ok: response.ok, status: response.status, body };\n } catch {\n return { reachable: false, ok: false };\n }\n };\n\n const ready = await probeEndpoint(\"/readyz\");\n const retrieveStats = await probeEndpoint(\"/v1/retrieve/stats\", { readBody: true });\n if (retrieveStats.ok && hasHeadroomStatsShape(retrieveStats.body)) {\n return { reachable: true, isHeadroom: true };\n }\n\n const stats = await probeEndpoint(\"/stats\", { readBody: true });\n if (stats.ok && hasHeadroomStatsShape(stats.body)) {\n return { reachable: true, isHeadroom: true };\n }\n\n const health = await probeEndpoint(\"/health\");\n const anyReachable = ready.reachable || retrieveStats.reachable || stats.reachable || health.reachable;\n if (!anyReachable) {\n return { reachable: false, isHeadroom: false, reason: \"proxy probe failed\" };\n }\n\n const reasons = [\n ready.reachable ? `readyz HTTP ${ready.status}` : \"readyz unavailable\",\n retrieveStats.reachable\n ? `retrieve stats HTTP ${retrieveStats.status}`\n : \"retrieve stats endpoint unavailable\",\n stats.reachable ? `stats HTTP ${stats.status}` : \"stats endpoint unavailable\",\n health.reachable ? `health HTTP ${health.status}` : \"health check failed\",\n ];\n return { reachable: true, isHeadroom: false, reason: reasons.join(\"; \") };\n}\n\nfunction hasHeadroomStatsShape(body: string | undefined): boolean {\n if (!body) {\n return false;\n }\n\n try {\n const parsed = JSON.parse(body) as Record<string, unknown>;\n return (\n parsed !== null &&\n typeof parsed === \"object\" &&\n (Object.hasOwn(parsed, \"proxy_inbound\") ||\n Object.hasOwn(parsed, \"api_requests\") ||\n Object.hasOwn(parsed, \"provider_tokens\") ||\n Object.hasOwn(parsed, \"proxy_compression_saved\") ||\n Object.hasOwn(parsed, \"store\") ||\n Object.hasOwn(parsed, \"recent_retrievals\"))\n );\n } catch {\n return false;\n }\n}\n\nasync function waitForHeadroomProxy(proxyUrl: string, timeoutMs: number): Promise<ProxyProbeResult> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n const result = await probeHeadroomProxy(proxyUrl);\n if (result.reachable && result.isHeadroom) {\n return result;\n }\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n return probeHeadroomProxy(proxyUrl);\n}\n","/**\n * Convert between OpenClaw's AgentMessage format and OpenAI message format.\n *\n * AgentMessage uses:\n * role: \"user\" | \"assistant\" | \"toolResult\"\n * content: string | ContentBlock[]\n *\n * OpenAI uses:\n * role: \"user\" | \"assistant\" | \"system\" | \"tool\"\n * content: string\n * tool_calls?: ToolCall[]\n * tool_call_id?: string\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport interface OpenAIMessage {\n role: string;\n content: string | null;\n tool_calls?: any[];\n tool_call_id?: string;\n name?: string;\n _headroomMeta?: Record<string, unknown>;\n}\n\n/**\n * Convert AgentMessage[] to OpenAI message format for compression.\n */\nexport function agentToOpenAI(messages: any[]): OpenAIMessage[] {\n const result: OpenAIMessage[] = [];\n\n for (const msg of messages) {\n const normalized = normalizeAgentMessage(msg);\n const role = normalized.role;\n\n const buildMeta = (): Record<string, unknown> => {\n const meta = { ...normalized } as Record<string, unknown>;\n delete meta.role;\n delete meta.content;\n return meta;\n };\n\n if (role === \"system\") {\n result.push({\n role: \"system\",\n content:\n typeof normalized.content === \"string\"\n ? normalized.content\n : extractText(normalized.content),\n _headroomMeta: buildMeta(),\n });\n continue;\n }\n\n if (role === \"user\") {\n result.push({\n role: \"user\",\n content:\n typeof normalized.content === \"string\"\n ? normalized.content\n : extractText(normalized.content),\n _headroomMeta: buildMeta(),\n });\n continue;\n }\n\n if (role === \"assistant\") {\n const content = normalized.content;\n if (typeof content === \"string\") {\n result.push({ role: \"assistant\", content, _headroomMeta: buildMeta() });\n continue;\n }\n\n // Content blocks: extract text and tool call blocks.\n // OpenClaw uses `toolCall`; some adapters still emit legacy `tool_use`.\n if (Array.isArray(content)) {\n const textParts: string[] = [];\n const toolCalls: any[] = [];\n\n for (const block of content) {\n if (typeof block === \"string\") {\n textParts.push(block);\n } else if (block.type === \"text\") {\n textParts.push(block.text);\n } else if (block.type === \"tool_use\" || block.type === \"toolCall\") {\n const args =\n block.type === \"toolCall\"\n ? block.arguments\n : block.input;\n toolCalls.push({\n id: block.id,\n type: \"function\",\n function: {\n name: block.name,\n arguments:\n typeof args === \"string\"\n ? args\n : JSON.stringify(args ?? {}),\n },\n });\n }\n }\n\n const openaiMsg: OpenAIMessage = {\n role: \"assistant\",\n content: textParts.length > 0 ? textParts.join(\"\") : null,\n _headroomMeta: buildMeta(),\n };\n if (toolCalls.length > 0) {\n openaiMsg.tool_calls = toolCalls;\n }\n result.push(openaiMsg);\n }\n continue;\n }\n\n if (role === \"toolResult\" || role === \"tool_result\") {\n const content =\n typeof normalized.content === \"string\"\n ? normalized.content\n : Array.isArray(normalized.content)\n ? extractText(normalized.content)\n : JSON.stringify(normalized.content);\n\n result.push({\n role: \"tool\",\n content,\n tool_call_id:\n normalized.toolCallId ??\n normalized.tool_use_id ??\n normalized.id ??\n \"unknown\",\n _headroomMeta: buildMeta(),\n });\n continue;\n }\n\n // Fallback: pass through as user message\n result.push({\n role: \"user\",\n content:\n typeof normalized.content === \"string\"\n ? normalized.content\n : JSON.stringify(normalized.content),\n _headroomMeta: buildMeta(),\n });\n }\n\n return result;\n}\n\n/**\n * Convert compressed OpenAI messages back to AgentMessage format.\n */\nexport function openAIToAgent(messages: OpenAIMessage[]): any[] {\n const result: any[] = [];\n\n for (const msg of messages) {\n const meta = (msg._headroomMeta ?? {}) as Record<string, unknown>;\n const timestamp =\n typeof meta.timestamp === \"number\" ? meta.timestamp : Date.now();\n\n if (msg.role === \"system\") {\n result.push({\n role: \"system\",\n content: msg.content ?? \"\",\n timestamp,\n });\n continue;\n }\n\n if (msg.role === \"user\") {\n result.push({\n role: \"user\",\n content: msg.content ?? \"\",\n timestamp,\n });\n continue;\n }\n\n if (msg.role === \"assistant\") {\n const blocks: any[] = [];\n if (msg.content) {\n blocks.push({ type: \"text\", text: msg.content });\n }\n if (msg.tool_calls) {\n for (const tc of msg.tool_calls) {\n let input: any;\n try {\n input = JSON.parse(tc.function.arguments);\n } catch {\n input = tc.function.arguments ?? {};\n }\n // Emit OpenClaw-native block shape so downstream transports keep call linkage.\n blocks.push({\n type: \"toolCall\",\n id: tc.id,\n name: tc.function.name,\n arguments: input,\n });\n }\n }\n // OpenClaw's Pi agent expects content to always be an array for assistant messages\n // (it calls .flatMap() on it). Never flatten to a string.\n result.push({\n ...(meta as object),\n role: \"assistant\",\n content: blocks,\n api: typeof meta.api === \"string\" ? meta.api : \"headroom\",\n provider: typeof meta.provider === \"string\" ? meta.provider : \"headroom\",\n model: typeof meta.model === \"string\" ? meta.model : \"headroom\",\n usage:\n isRecord(meta.usage)\n ? meta.usage\n : {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n },\n stopReason:\n typeof meta.stopReason === \"string\" ? meta.stopReason : \"stop\",\n timestamp,\n });\n continue;\n }\n\n if (msg.role === \"tool\") {\n const textContent =\n typeof msg.content === \"string\"\n ? msg.content\n : msg.content == null\n ? \"\"\n : JSON.stringify(msg.content);\n const toolCallId = msg.tool_call_id ?? \"unknown\";\n result.push({\n ...(meta as object),\n role: \"toolResult\",\n // OpenClaw transport layers expect toolResult content blocks, not a raw string.\n content: [{ type: \"text\", text: textContent }],\n toolCallId:\n typeof meta.toolCallId === \"string\" ? meta.toolCallId : toolCallId,\n tool_use_id:\n typeof meta.tool_use_id === \"string\" ? meta.tool_use_id : toolCallId,\n toolName:\n typeof meta.toolName === \"string\" ? meta.toolName : \"headroom\",\n isError: typeof meta.isError === \"boolean\" ? meta.isError : false,\n timestamp,\n });\n continue;\n }\n }\n\n return result;\n}\n\nexport function normalizeAgentMessages(messages: any[]): any[] {\n return messages.map((message) => normalizeAgentMessage(message));\n}\n\n/**\n * Extract text from content blocks.\n */\nfunction extractText(content: any): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return JSON.stringify(content);\n\n return content\n .map((block: any) => {\n if (typeof block === \"string\") return block;\n if (block.type === \"text\") return block.text;\n if (block.type === \"tool_result\") {\n return typeof block.content === \"string\" ? block.content : JSON.stringify(block.content);\n }\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction normalizeAgentMessage(message: any): any {\n if (!isRecord(message)) return message;\n\n if (message.role === \"assistant\") {\n return normalizeAssistantMessage(message);\n }\n\n if (message.role === \"toolResult\" || message.role === \"tool_result\") {\n return normalizeToolResultMessage(message);\n }\n\n return message;\n}\n\nfunction normalizeAssistantMessage(message: Record<string, any>): Record<string, any> {\n const normalizedContent = normalizeAssistantContent(message.content);\n\n return {\n ...message,\n content: normalizedContent,\n api: typeof message.api === \"string\" ? message.api : \"headroom\",\n provider: typeof message.provider === \"string\" ? message.provider : \"headroom\",\n model: typeof message.model === \"string\" ? message.model : \"headroom\",\n usage: isRecord(message.usage)\n ? message.usage\n : {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n },\n stopReason: typeof message.stopReason === \"string\" ? message.stopReason : \"stop\",\n timestamp: typeof message.timestamp === \"number\" ? message.timestamp : Date.now(),\n };\n}\n\nfunction normalizeToolResultMessage(message: Record<string, any>): Record<string, any> {\n const normalizedContent = normalizeToolResultContent(message.content);\n const toolCallId =\n typeof message.toolCallId === \"string\"\n ? message.toolCallId\n : typeof message.tool_use_id === \"string\"\n ? message.tool_use_id\n : typeof message.id === \"string\"\n ? message.id\n : \"unknown\";\n\n return {\n ...message,\n role: \"toolResult\",\n content: normalizedContent,\n toolCallId,\n tool_use_id:\n typeof message.tool_use_id === \"string\" ? message.tool_use_id : toolCallId,\n toolName: typeof message.toolName === \"string\" ? message.toolName : \"headroom\",\n isError: typeof message.isError === \"boolean\" ? message.isError : false,\n timestamp: typeof message.timestamp === \"number\" ? message.timestamp : Date.now(),\n };\n}\n\nfunction normalizeAssistantContent(content: unknown): any[] {\n if (Array.isArray(content)) {\n return content.flatMap((block) => {\n if (typeof block === \"string\") return [{ type: \"text\", text: block }];\n if (!isRecord(block) || typeof block.type !== \"string\") return [];\n if (block.type === \"text\" && typeof block.text === \"string\") return [block];\n if (block.type === \"thinking\" && typeof block.thinking === \"string\") return [block];\n if (\n (block.type === \"toolCall\" || block.type === \"tool_use\") &&\n typeof block.name === \"string\"\n ) {\n return [\n {\n type: \"toolCall\",\n id: typeof block.id === \"string\" ? block.id : \"unknown\",\n name: block.name,\n arguments:\n \"arguments\" in block\n ? block.arguments\n : \"input\" in block\n ? block.input\n : {},\n },\n ];\n }\n return [];\n });\n }\n\n if (typeof content === \"string\" && content.length > 0) {\n return [{ type: \"text\", text: content }];\n }\n\n if (content == null) {\n return [];\n }\n\n return [{ type: \"text\", text: JSON.stringify(content) }];\n}\n\nfunction normalizeToolResultContent(content: unknown): any[] {\n if (Array.isArray(content)) {\n return content.flatMap((block) => {\n if (typeof block === \"string\") return [{ type: \"text\", text: block }];\n if (!isRecord(block) || typeof block.type !== \"string\") return [];\n if (block.type === \"text\" && typeof block.text === \"string\") return [block];\n if (\n block.type === \"image\" &&\n typeof block.data === \"string\" &&\n typeof block.mimeType === \"string\"\n ) {\n return [block];\n }\n if (block.type === \"tool_result\" && \"content\" in block) {\n return normalizeToolResultContent(block.content);\n }\n return [];\n });\n }\n\n if (typeof content === \"string\" && content.length > 0) {\n return [{ type: \"text\", text: content }];\n }\n\n if (content == null) {\n return [];\n }\n\n return [{ type: \"text\", text: JSON.stringify(content) }];\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport const DEFAULT_GATEWAY_PROVIDER_IDS = [\"openai-codex\"] as const;\n\nconst DEFAULT_PROVIDER_BASE_URLS: Readonly<Record<string, string>> = {\n \"openai-codex\": \"https://chatgpt.com/backend-api\",\n};\n\nconst GATEWAY_PROVIDER_ID_ALIASES: Readonly<Record<string, string>> = {\n codex: \"openai-codex\",\n claude: \"anthropic\",\n copilot: \"github-copilot\",\n gemini: \"google\",\n};\n\nconst EXPLICIT_BASE_URL_REQUIRED_PROVIDER_IDS = new Set<string>([\"github-copilot\"]);\n\nexport function resolveGatewayProviderIds(config: Record<string, unknown> | undefined): string[] {\n const configuredProviderIds = normalizeGatewayProviderIds(config?.gatewayProviderIds);\n if (configuredProviderIds.length > 0) {\n return configuredProviderIds;\n }\n\n if (config?.routeCodexViaProxy === false) {\n return [];\n }\n\n return [...DEFAULT_GATEWAY_PROVIDER_IDS];\n}\n\nfunction normalizeGatewayProviderIds(value: unknown): string[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const seen = new Set<string>();\n const normalized: string[] = [];\n\n for (const entry of value) {\n if (typeof entry !== \"string\") {\n continue;\n }\n\n const rawProviderId = entry.trim();\n const providerId = GATEWAY_PROVIDER_ID_ALIASES[rawProviderId.toLowerCase()] ?? rawProviderId;\n if (!providerId || seen.has(providerId)) {\n continue;\n }\n\n seen.add(providerId);\n normalized.push(providerId);\n }\n\n return normalized;\n}\n\nexport function applyGatewayProviderBaseUrls<T>(\n cfg: T,\n proxyUrl: string,\n providerIds: readonly string[],\n): { changed: boolean; config: T } {\n const next = structuredClone((cfg ?? {}) as any);\n const changed = applyGatewayProviderBaseUrlsInPlace(next, proxyUrl, providerIds);\n return { changed, config: next as T };\n}\n\nexport function applyGatewayProviderBaseUrlsInPlace(\n cfg: any,\n proxyUrl: string,\n providerIds: readonly string[],\n): boolean {\n if (!cfg || typeof cfg !== \"object\" || providerIds.length === 0) {\n return false;\n }\n\n const models = (cfg.models ??= {});\n const providers = (models.providers ??= {});\n let changed = false;\n\n for (const providerId of providerIds) {\n const currentValue = providers[providerId];\n const currentConfig =\n currentValue && typeof currentValue === \"object\" && !Array.isArray(currentValue)\n ? currentValue\n : {};\n const nextConfig = { ...currentConfig };\n const currentBaseUrl =\n typeof nextConfig.baseUrl === \"string\" && nextConfig.baseUrl.trim().length > 0\n ? nextConfig.baseUrl\n : undefined;\n const defaultBaseUrl = DEFAULT_PROVIDER_BASE_URLS[providerId];\n if (\n !currentBaseUrl &&\n !defaultBaseUrl &&\n EXPLICIT_BASE_URL_REQUIRED_PROVIDER_IDS.has(providerId)\n ) {\n continue;\n }\n const nextBaseUrl = routeBaseUrlThroughProxy({\n providerId,\n proxyUrl,\n currentBaseUrl,\n });\n\n if (!Array.isArray(nextConfig.models)) {\n nextConfig.models = [];\n changed = true;\n }\n\n if (nextConfig.baseUrl === nextBaseUrl) {\n providers[providerId] = nextConfig;\n continue;\n }\n\n nextConfig.baseUrl = nextBaseUrl;\n providers[providerId] = nextConfig;\n changed = true;\n }\n\n return changed;\n}\n\nfunction routeBaseUrlThroughProxy(params: {\n providerId: string;\n proxyUrl: string;\n currentBaseUrl?: string;\n}): string {\n const upstreamBaseUrl = params.currentBaseUrl ?? DEFAULT_PROVIDER_BASE_URLS[params.providerId];\n if (!upstreamBaseUrl) {\n return params.proxyUrl;\n }\n\n try {\n const proxy = new URL(params.proxyUrl);\n const upstream = new URL(upstreamBaseUrl);\n proxy.pathname = upstream.pathname;\n proxy.search = upstream.search;\n proxy.hash = \"\";\n return proxy.toString().replace(/\\/$/, \"\");\n } catch {\n return params.proxyUrl;\n }\n}\n","/**\n * CCR (Compress-Cache-Retrieve) tool for OpenClaw.\n *\n * Allows the agent to retrieve original uncompressed content\n * from the Headroom proxy's compression store.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { normalizeAndValidateProxyUrl } from \"../proxy-manager.js\";\n\nexport interface RetrieveToolConfig {\n proxyUrl: string;\n}\n\nexport function createHeadroomRetrieveTool(config: RetrieveToolConfig) {\n const proxyOrigin = normalizeAndValidateProxyUrl(config.proxyUrl);\n\n return {\n name: \"headroom_retrieve\",\n description:\n \"Retrieve original uncompressed content from Headroom's compression store. \" +\n \"Use when compressed context mentions a hash and you need the full details. \" +\n \"Pass the hash from the compression marker (24 hex characters). \" +\n \"Retrieval is by hash and always returns the full original content.\",\n parameters: {\n type: \"object\" as const,\n properties: {\n hash: {\n type: \"string\",\n description: \"The 24-character hex hash from the compression marker\",\n },\n },\n required: [\"hash\"],\n },\n execute: async (args: { hash: string }): Promise<string> => {\n const { hash } = args;\n\n // Validate hash format\n if (!/^[a-f0-9]{24}$/i.test(hash)) {\n return JSON.stringify({\n error: \"Invalid hash format. Expected 24 hex characters.\",\n });\n }\n\n try {\n const url = `${proxyOrigin}/v1/retrieve/${hash}`;\n\n const resp = await fetch(url, {\n signal: AbortSignal.timeout(10_000),\n });\n\n if (!resp.ok) {\n const body = await resp.text().catch(() => \"\");\n return JSON.stringify({\n error: `Retrieval failed: HTTP ${resp.status}`,\n details: body,\n });\n }\n\n const data = await resp.json();\n return typeof data === \"string\" ? data : JSON.stringify(data);\n } catch (error) {\n return JSON.stringify({\n error: `Retrieval failed: ${error}`,\n hint: \"The compressed content may have expired (default TTL: 30 minutes)\",\n });\n }\n },\n };\n}\n","/**\n * Headroom OpenClaw Plugin — register ContextEngine + CCR retrieval tool.\n *\n * Usage:\n * openclaw plugins install headroom-ai/openclaw\n *\n * Configuration (in ~/.openclaw/config.json or ~/.clawdbot/clawdbot.json):\n * {\n * \"plugins\": {\n * \"slots\": { \"contextEngine\": \"headroom\" },\n * \"entries\": { \"headroom\": { \"enabled\": true } }\n * }\n * }\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { HeadroomContextEngine } from \"../engine.js\";\nimport {\n applyGatewayProviderBaseUrlsInPlace,\n resolveGatewayProviderIds,\n} from \"../gateway-config.js\";\nimport { normalizeAndValidateProxyUrl, probeHeadroomProxy } from \"../proxy-manager.js\";\nimport { createHeadroomRetrieveTool } from \"../tools/headroom-retrieve.js\";\n\n/**\n * OpenClaw 2026.x plugin API requires a `{ register(api) }` object export.\n * The previous bare-function default export was silently skipped by the loader.\n * See: https://github.com/chopratejas/headroom/issues/XXX\n */\nexport default {\n register: registerHeadroomPlugin,\n};\n\nexport function registerHeadroomPlugin(api: any) {\n const config = api.config?.plugins?.entries?.headroom?.config ?? {};\n const logger = api.logger ?? console;\n const rawProxyUrl = config.proxyUrl;\n const proxyUrl =\n typeof rawProxyUrl === \"string\" && rawProxyUrl.trim().length > 0\n ? normalizeAndValidateProxyUrl(rawProxyUrl)\n : undefined;\n\n const engine = new HeadroomContextEngine({ ...config, proxyUrl }, {\n info: (m: string) => logger.info(m),\n warn: (m: string) => logger.warn(m),\n error: (m: string) => logger.error(m),\n debug: (m: string) => logger.debug?.(m),\n });\n const gatewayProviderIds = resolveGatewayProviderIds(config);\n let validatedConfiguredProxyUrl: string | null = null;\n let configuredProxyProbePromise: Promise<string | null> | null = null;\n\n const applyGatewayRouting = async (activeProxyUrl: string) => {\n if (gatewayProviderIds.length === 0) {\n return;\n }\n\n try {\n const changed = applyGatewayProviderBaseUrlsInPlace(api.config, activeProxyUrl, gatewayProviderIds);\n\n if (changed) {\n logger.info(\n `[headroom] Routed ${gatewayProviderIds.join(\", \")} through Headroom proxy in memory at ${activeProxyUrl}`,\n );\n } else {\n logger.info(\n `[headroom] Upstream gateway already routed in memory for ${gatewayProviderIds.join(\", \")} at ${activeProxyUrl}`,\n );\n }\n } catch (error) {\n logger.warn(`[headroom] Failed to configure upstream gateway routing: ${error}`);\n }\n };\n\n const getConfiguredRoutingProxyUrl = async (): Promise<string | null> => {\n if (!proxyUrl) {\n return null;\n }\n if (validatedConfiguredProxyUrl === proxyUrl) {\n return validatedConfiguredProxyUrl;\n }\n if (!configuredProxyProbePromise) {\n configuredProxyProbePromise = probeHeadroomProxy(proxyUrl)\n .then((probe) => {\n if (probe.reachable && probe.isHeadroom) {\n validatedConfiguredProxyUrl = proxyUrl;\n return proxyUrl;\n }\n logger.warn(\n `[headroom] Skipping upstream gateway routing: configured proxyUrl is not a ready Headroom proxy at ${proxyUrl}` +\n (probe.reason ? ` (${probe.reason})` : \"\"),\n );\n return null;\n })\n .catch((error) => {\n logger.warn(\n `[headroom] Skipping upstream gateway routing: failed to probe configured proxyUrl ${proxyUrl}: ${error}`,\n );\n return null;\n })\n .finally(() => {\n configuredProxyProbePromise = null;\n });\n }\n return configuredProxyProbePromise;\n };\n\n const ensureGatewayRouting = async () => {\n if (gatewayProviderIds.length === 0) {\n return;\n }\n const activeProxyUrl = engine.getProxyUrl() ?? (await getConfiguredRoutingProxyUrl());\n if (!activeProxyUrl) {\n logger.debug?.(\"[headroom] Deferring upstream gateway routing until proxy is available\");\n return;\n }\n await applyGatewayRouting(activeProxyUrl);\n };\n\n engine.onProxyReady(async (activeProxyUrl) => {\n await applyGatewayRouting(activeProxyUrl);\n });\n\n // Register as context engine\n api.registerContextEngine(\"headroom\", () => engine);\n\n // Register CCR retrieval tool (active once proxy is running)\n api.registerTool((ctx: any) => {\n const activeProxyUrl = engine.getProxyUrl() ?? proxyUrl;\n if (!activeProxyUrl) return null;\n return createHeadroomRetrieveTool({ proxyUrl: activeProxyUrl });\n }, { names: [\"headroom_retrieve\"] });\n\n api.on(\"gateway_start\", async () => {\n await ensureGatewayRouting();\n });\n\n void ensureGatewayRouting();\n\n logger.info(\"[headroom] Plugin registered\");\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/engine.ts","../src/proxy-manager.ts","../src/convert.ts","../src/openclaw-compaction.ts","../src/gateway-config.ts","../src/tools/headroom-retrieve.ts","../src/plugin/index.ts"],"sourcesContent":["/**\n * HeadroomContextEngine — ContextEngine implementation for OpenClaw.\n *\n * Compresses tool outputs and conversation context using the Headroom proxy.\n * Zero LLM calls — all compression is algorithmic (SmartCrusher, ContentRouter, etc.)\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { compress } from \"headroom-ai\";\nimport { ProxyManager, defaultLogger, type ProxyManagerConfig, type ProxyManagerLogger } from \"./proxy-manager.js\";\nimport { agentToOpenAI, normalizeAgentMessages, openAIToAgent } from \"./convert.js\";\nimport {\n delegateCompactionToRuntime,\n type OpenClawCompactParams,\n type OpenClawCompactResult,\n} from \"./openclaw-compaction.js\";\n\n/** Race a promise against a timeout and always release the timer. */\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n let timerId: ReturnType<typeof setTimeout> | undefined;\n const timer = new Promise<never>((_, reject) => {\n timerId = setTimeout(() => reject(new Error(`headroom compress() timed out after ${ms}ms`)), ms);\n });\n return Promise.race([promise, timer]).finally(() => {\n if (timerId !== undefined) clearTimeout(timerId);\n });\n}\n\nexport interface HeadroomEngineConfig extends ProxyManagerConfig {\n enabled?: boolean;\n requestTimeoutMs?: number;\n circuitBreakerThreshold?: number;\n circuitBreakerCooldownMs?: number;\n}\n\nexport class HeadroomContextEngine {\n readonly info = {\n id: \"headroom\",\n name: \"Headroom Context Compression\",\n version: \"0.1.0\",\n ownsCompaction: false,\n };\n\n private proxyManager: ProxyManager;\n private proxyUrl: string | null = null;\n private config: HeadroomEngineConfig;\n private logger: ProxyManagerLogger;\n private proxyReadyListeners = new Set<(proxyUrl: string) => void | Promise<void>>();\n private proxyStartupPromise: Promise<string> | null = null;\n private proxyStartupError: unknown = null;\n private stats = {\n totalCompressions: 0,\n totalTokensSaved: 0,\n totalTokensBefore: 0,\n compactions: 0,\n };\n private circuit = { errors: 0, openUntilMs: 0 };\n\n constructor(config: HeadroomEngineConfig = {}, logger?: ProxyManagerLogger) {\n this.config = config;\n this.logger = logger ?? defaultLogger;\n this.proxyManager = new ProxyManager(config, this.logger);\n }\n\n // === ContextEngine Lifecycle ===\n\n async bootstrap(params: {\n sessionId: string;\n sessionKey?: string;\n sessionFile: string;\n }): Promise<{ bootstrapped: boolean; reason?: string }> {\n if (this.config.enabled === false) {\n return { bootstrapped: false, reason: \"disabled\" };\n }\n\n this.ensureProxyStarted();\n return { bootstrapped: true, reason: \"proxy startup scheduled\" };\n }\n\n async ingest(params: {\n sessionId: string;\n message: any;\n isHeartbeat?: boolean;\n }): Promise<{ ingested: boolean }> {\n // No-op: OpenClaw's runtime stores messages. We don't need a separate store.\n return { ingested: true };\n }\n\n async ingestBatch?(params: {\n sessionId: string;\n messages: any[];\n isHeartbeat?: boolean;\n }): Promise<{ ingestedCount: number }> {\n return { ingestedCount: params.messages.length };\n }\n\n /**\n * Assemble context for the model — THE CORE HOOK.\n *\n * Converts AgentMessage[] → OpenAI format → compress() → AgentMessage[]\n */\n async assemble(params: {\n sessionId: string;\n messages: any[];\n tokenBudget?: number;\n model?: string;\n prompt?: string;\n }): Promise<{\n messages: any[];\n estimatedTokens: number;\n systemPromptAddition?: string;\n }> {\n if (!this.proxyUrl || this.config.enabled === false) {\n this.ensureProxyStarted();\n // Fallback: return messages unchanged\n return { messages: normalizeAgentMessages(params.messages), estimatedTokens: 0 };\n }\n\n if (this.isCircuitOpen()) {\n this.logger.warn(\"[headroom] Circuit open — using uncompressed messages\");\n return { messages: normalizeAgentMessages(params.messages), estimatedTokens: 0 };\n }\n\n try {\n // Convert AgentMessage → OpenAI format\n const openaiMessages = agentToOpenAI(params.messages);\n\n // Compress via proxy — pass tokenBudget so RollingWindow enforces it\n const result = await withTimeout(\n compress(openaiMessages, {\n model: params.model ?? \"claude-sonnet-4-5\",\n baseUrl: this.proxyUrl,\n fallback: true,\n tokenBudget: params.tokenBudget,\n } as any),\n this.config.requestTimeoutMs ?? 30_000,\n );\n\n if (!result.compressed || result.tokensSaved === 0) {\n this.resetCircuit();\n return {\n messages: normalizeAgentMessages(params.messages),\n estimatedTokens: result.tokensBefore,\n };\n }\n\n // Convert back to AgentMessage format\n const compressedAgentMessages = openAIToAgent(result.messages);\n this.resetCircuit();\n\n // Track stats\n this.stats.totalCompressions++;\n this.stats.totalTokensSaved += result.tokensSaved;\n this.stats.totalTokensBefore += result.tokensBefore;\n\n this.logger.debug(\n `Assembled: ${result.tokensBefore} → ${result.tokensAfter} tokens (saved ${result.tokensSaved})`,\n );\n\n return {\n messages: compressedAgentMessages,\n estimatedTokens: result.tokensAfter,\n systemPromptAddition:\n result.tokensSaved > 100\n ? `[Context compressed by Headroom: ${result.tokensSaved} tokens saved. Use headroom_retrieve with the hash to get full details.]`\n : undefined,\n };\n } catch (error) {\n this.logger.error(`Assemble failed: ${error}`);\n this.tripCircuit(error);\n // Graceful fallback: return original messages\n return { messages: normalizeAgentMessages(params.messages), estimatedTokens: 0 };\n }\n }\n\n /** Delegate persistent compaction to OpenClaw's built-in runtime. */\n async compact(params: OpenClawCompactParams): Promise<OpenClawCompactResult> {\n const result = await delegateCompactionToRuntime(params);\n\n if (result.compacted) {\n this.stats.compactions++;\n }\n this.logger.info(\n `Compaction ${result.compacted ? \"completed\" : \"skipped\"} ` +\n `(budget: ${params.tokenBudget ?? \"none\"}, force: ${params.force ?? false})`,\n );\n\n return result;\n }\n\n async afterTurn?(params: {\n sessionId: string;\n messages: any[];\n prePromptMessageCount: number;\n isHeartbeat?: boolean;\n }): Promise<void> {\n // Optional: could log stats or trigger learning\n }\n\n async prepareSubagentSpawn?(params: {\n parentSessionKey: string;\n childSessionKey: string;\n ttlMs?: number;\n }): Promise<{ rollback: () => Promise<void> } | undefined> {\n // Subagent context is compressed naturally via assemble()\n return undefined;\n }\n\n async onSubagentEnded?(params: {\n childSessionKey: string;\n reason: string;\n }): Promise<void> {\n // No-op\n }\n\n async dispose(): Promise<void> {\n await this.proxyManager.stop();\n this.logger.info(\n `Engine disposed. Stats: ${this.stats.totalCompressions} compressions, ` +\n `${this.stats.totalTokensSaved} tokens saved`,\n );\n }\n\n // --- Public API ---\n\n getStats() {\n return { ...this.stats };\n }\n\n getProxyUrl(): string | null {\n return this.proxyUrl;\n }\n\n getProxyStartupError(): unknown {\n return this.proxyStartupError;\n }\n\n private isCircuitOpen(): boolean {\n const threshold = this.config.circuitBreakerThreshold ?? 3;\n if (this.circuit.errors < threshold) return false;\n if (Date.now() < this.circuit.openUntilMs) return true;\n this.circuit = { errors: 0, openUntilMs: 0 };\n return false;\n }\n\n private tripCircuit(error: unknown): void {\n this.circuit.errors += 1;\n const threshold = this.config.circuitBreakerThreshold ?? 3;\n if (this.circuit.errors < threshold) return;\n const cooldownMs = this.config.circuitBreakerCooldownMs ?? 60_000;\n this.circuit.openUntilMs = Date.now() + cooldownMs;\n this.logger.warn(\n `[headroom] Circuit breaker opened after ${this.circuit.errors} errors ` +\n `(last: ${String(error)}); bypassing compression for ${cooldownMs}ms`,\n );\n }\n\n private resetCircuit(): void {\n this.circuit = { errors: 0, openUntilMs: 0 };\n }\n\n ensureProxyStarted(): void {\n if (this.config.enabled === false || this.proxyUrl || this.proxyStartupPromise) {\n return;\n }\n\n this.proxyStartupError = null;\n this.proxyStartupPromise = this.proxyManager\n .start()\n .then(async (proxyUrl) => {\n this.proxyUrl = proxyUrl;\n this.proxyStartupError = null;\n await this.notifyProxyReady(proxyUrl);\n this.logger.info(`Headroom proxy ready at ${proxyUrl}`);\n return proxyUrl;\n })\n .catch((error) => {\n this.proxyStartupError = error;\n this.logger.warn(`Headroom proxy unavailable: ${error}`);\n throw error;\n })\n .finally(() => {\n this.proxyStartupPromise = null;\n });\n\n // Fire-and-forget lifecycle callers intentionally do not await this promise.\n // Keep the promise rejectable for ensureProxyUrl(), but mark it observed so\n // a missing proxy cannot become a process-level unhandled rejection.\n void this.proxyStartupPromise.catch(() => {});\n }\n\n onProxyReady(listener: (proxyUrl: string) => void | Promise<void>): () => void {\n this.proxyReadyListeners.add(listener);\n return () => {\n this.proxyReadyListeners.delete(listener);\n };\n }\n\n async ensureProxyUrl(): Promise<string> {\n if (this.proxyUrl) {\n return this.proxyUrl;\n }\n\n this.ensureProxyStarted();\n if (!this.proxyStartupPromise) {\n throw new Error(\"Headroom proxy startup is disabled\");\n }\n return this.proxyStartupPromise;\n }\n\n private async notifyProxyReady(proxyUrl: string): Promise<void> {\n for (const listener of this.proxyReadyListeners) {\n try {\n await listener(proxyUrl);\n } catch (error) {\n this.logger.warn(`Headroom proxy ready listener failed: ${error}`);\n }\n }\n }\n}\n","/**\n * Manages connectivity to a Headroom proxy (local or remote).\n *\n * Security model:\n * - Local proxies (127.0.0.1 / localhost) can be auto-started via subprocess\n * - Remote proxies are connect-only: probe and use, never launch\n * - No environment variable access\n */\nimport { spawn } from \"node:child_process\";\nimport { spawnSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport os from \"os\";\n\nexport interface ProxyManagerConfig {\n proxyUrl?: string;\n proxyPort?: number;\n pythonPath?: string;\n autoStart?: boolean;\n startupTimeoutMs?: number;\n retryMaxAttempts?: number;\n connectTimeoutSeconds?: number;\n}\n\nexport interface ProxyManagerLogger {\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n debug(message: string): void;\n}\n\n/** Default logger that prefixes all messages with `[headroom]`. */\nexport const defaultLogger: ProxyManagerLogger = {\n info: (m) => console.log(`[headroom] ${m}`),\n warn: (m) => console.warn(`[headroom] ${m}`),\n error: (m) => console.error(`[headroom] ${m}`),\n debug: () => {},\n};\n\nexport interface ProxyProbeResult {\n reachable: boolean;\n isHeadroom: boolean;\n reason?: string;\n}\n\ninterface LaunchSpec {\n label: string;\n command: string;\n args: string[];\n checkCommand: string;\n checkArgs: string[];\n useShell?: boolean;\n checkUseShell?: boolean;\n}\n\nconst HEADROOM_MODULE_DISCOVERY_SNIPPET =\n \"import importlib.util, sys; sys.exit(0 if importlib.util.find_spec('headroom') else 1)\";\n\nexport class ProxyManager {\n private config: ProxyManagerConfig;\n private logger: ProxyManagerLogger;\n private proxyUrl: string | null = null;\n\n constructor(config: ProxyManagerConfig = {}, logger?: ProxyManagerLogger) {\n this.config = config;\n this.logger = logger ?? defaultLogger;\n }\n\n /**\n * Ensure a proxy is available. Returns the normalized URL origin.\n */\n async start(): Promise<string> {\n const port = this.getProxyPort();\n const rawExplicitUrl =\n typeof this.config.proxyUrl === \"string\" && this.config.proxyUrl.trim().length > 0\n ? normalizeAndValidateProxyUrl(this.config.proxyUrl)\n : null;\n // Only apply proxyPort default to local URLs — remote URLs use their protocol default\n const explicitUrl = rawExplicitUrl\n ? isLocalProxyUrl(rawExplicitUrl) ? withDefaultPort(rawExplicitUrl, port) : rawExplicitUrl\n : null;\n const defaultCandidates = this.getDefaultProxyCandidates(port);\n const candidateUrls = explicitUrl ? [explicitUrl] : [...defaultCandidates];\n const probeByUrl = new Map<string, ProxyProbeResult>();\n\n for (const url of candidateUrls) {\n const probe = await probeHeadroomProxy(url);\n probeByUrl.set(url, probe);\n if (probe.reachable && probe.isHeadroom) {\n this.proxyUrl = url;\n this.logger.info(`Headroom proxy already running at ${url}`);\n return url;\n }\n }\n\n if (explicitUrl) {\n const explicitProbe = probeByUrl.get(explicitUrl);\n if (explicitProbe?.reachable && !explicitProbe.isHeadroom) {\n throw new Error(\n `Service reachable at ${explicitUrl}, but it does not appear to be a Headroom proxy (${explicitProbe.reason ?? \"unknown service\"}).`,\n );\n }\n }\n\n // Remote URLs are connect-only — never auto-start a subprocess for them\n if (explicitUrl && !isLocalProxyUrl(explicitUrl)) {\n throw new Error(\n `Remote Headroom proxy not reachable at ${explicitUrl}. Ensure the proxy is running at that address.`,\n );\n }\n\n // Auto-start is only available for local proxies\n if (this.config.autoStart === true) {\n const startupUrl = explicitUrl ?? defaultCandidates[0];\n const startupProbe = probeByUrl.get(startupUrl);\n if (startupProbe?.reachable && !startupProbe.isHeadroom) {\n throw new Error(\n `Cannot auto-start Headroom at ${startupUrl}: port is in use by a non-Headroom service (${startupProbe.reason ?? \"unknown service\"}).`,\n );\n }\n\n this.logger.info(\n `No Headroom proxy detected${explicitUrl ? ` at ${startupUrl}` : \" on default local endpoints\"}; attempting to auto-start...`,\n );\n await this.startHeadroomProxy(startupUrl, port);\n\n const startedProbe = await waitForHeadroomProxy(\n startupUrl,\n this.config.startupTimeoutMs ?? 20_000,\n );\n if (startedProbe.reachable && startedProbe.isHeadroom) {\n this.proxyUrl = startupUrl;\n this.logger.info(`Headroom proxy started and reachable at ${startupUrl}`);\n return startupUrl;\n }\n throw new Error(\n `Attempted to start Headroom proxy, but it was not reachable at ${startupUrl} (${startedProbe.reason ?? \"unknown\"}).`,\n );\n }\n\n if (explicitUrl) {\n throw new Error(\n `Headroom proxy not reachable at ${explicitUrl}. Ensure the proxy is running first.`,\n );\n }\n\n throw new Error(\n `Headroom proxy not detected on default endpoints (${defaultCandidates.join(\", \")}). ` +\n \"Set proxyUrl explicitly or enable autoStart.\",\n );\n }\n\n private getProxyPort(): number {\n const rawPort = this.config.proxyPort;\n if (!Number.isInteger(rawPort) || rawPort === undefined) return 8787;\n if (rawPort < 1 || rawPort > 65535) {\n throw new Error(\"proxyPort must be an integer between 1 and 65535\");\n }\n return rawPort;\n }\n\n private getDefaultProxyCandidates(port: number): string[] {\n return [`http://127.0.0.1:${port}`, `http://localhost:${port}`];\n }\n\n /**\n * Stop manager state. Spawned proxy processes are detached and externally managed.\n */\n async stop(): Promise<void> {\n this.proxyUrl = null;\n }\n\n getUrl(): string | null {\n return this.proxyUrl;\n }\n\n // --- Internal ---\n\n private async startHeadroomProxy(proxyUrl: string, defaultPort: number): Promise<void> {\n const parsed = new URL(proxyUrl);\n const host = parsed.hostname;\n const port = parsed.port || String(defaultPort);\n const specs = this.buildLaunchSpecs(host, port);\n const errors: string[] = [];\n\n for (const spec of specs) {\n if (!this.canExecute(spec.checkCommand, spec.checkArgs, spec.checkUseShell ?? spec.useShell)) {\n this.logger.debug(`Launcher unavailable: ${spec.label}`);\n continue;\n }\n\n try {\n const child = spawn(spec.command, spec.args, {\n detached: true,\n shell: spec.useShell === true,\n stdio: \"ignore\",\n });\n child.unref();\n this.logger.info(`Auto-start launcher selected: ${spec.label}`);\n return;\n } catch (error) {\n errors.push(`${spec.label}: ${String(error)}`);\n }\n }\n\n throw new Error(\n \"No usable Headroom launcher found. Tried PATH, local npm, global npm, and Python. \" +\n \"Install headroom-ai (npm or pip) and ensure one launcher is available.\\n\" +\n (errors.length > 0 ? `Launch errors: ${errors.join(\"; \")}` : \"\"),\n );\n }\n\n private buildLaunchSpecs(host: string, port: string): LaunchSpec[] {\n const commonArgs = [\"proxy\", \"--host\", host, \"--port\", port];\n const retryMaxAttempts = this.config.retryMaxAttempts;\n if (Number.isInteger(retryMaxAttempts)) {\n commonArgs.push(\"--retry-max-attempts\", String(retryMaxAttempts));\n }\n\n const connectTimeoutSeconds = this.config.connectTimeoutSeconds;\n if (Number.isInteger(connectTimeoutSeconds)) {\n commonArgs.push(\"--connect-timeout-seconds\", String(connectTimeoutSeconds));\n }\n\n const specs: LaunchSpec[] = [];\n\n const configuredPython = this.getConfiguredPythonCommand();\n if (configuredPython) {\n specs.push({\n label: `Configured Python: ${configuredPython} -m headroom.cli`,\n command: configuredPython,\n args: [\"-m\", \"headroom.cli\", ...commonArgs],\n checkCommand: configuredPython,\n checkArgs: [\"-c\", HEADROOM_MODULE_DISCOVERY_SNIPPET],\n });\n }\n\n // 2) Windows pyenv: resolve the real executable so we avoid shim .bat wrappers.\n if (process.platform === \"win32\") {\n const pyenvHeadroom = this.getPyenvResolvedHeadroom();\n if (pyenvHeadroom) {\n specs.push({\n label: `pyenv: ${pyenvHeadroom}`,\n command: pyenvHeadroom,\n args: commonArgs,\n checkCommand: pyenvHeadroom,\n checkArgs: [\"--version\"],\n useShell: false,\n });\n }\n }\n\n // 3) PATH\n specs.push({\n label: \"PATH: headroom\",\n command: \"headroom\",\n args: commonArgs,\n checkCommand: process.platform === \"win32\" ? \"where.exe\" : \"sh\",\n checkArgs: process.platform === \"win32\"\n ? [\"headroom\"]\n : [\"-c\", \"command -v headroom >/dev/null 2>&1\"],\n useShell: process.platform === \"win32\",\n checkUseShell: false,\n });\n\n // 4) uv tool install path (~/.local/bin/headroom)\n const uvBin = join(\n os.homedir(),\n \".local\", \"bin\", \"headroom\"\n );\n if (existsSync(uvBin)) {\n specs.push({\n label: `uv tool: ${uvBin}`,\n command: uvBin,\n args: commonArgs,\n checkCommand: uvBin,\n checkArgs: [\"--version\"],\n });\n }\n\n // 5) Local npm install (inside plugin install path)\n const moduleDir = dirname(fileURLToPath(import.meta.url)); // .../dist\n const packageRoot = dirname(moduleDir);\n const localBinDir = join(packageRoot, \"node_modules\", \".bin\");\n const localBins = process.platform === \"win32\"\n ? [join(localBinDir, \"headroom.cmd\"), join(localBinDir, \"headroom\")]\n : [join(localBinDir, \"headroom\")];\n for (const localBin of localBins) {\n if (!existsSync(localBin)) continue;\n specs.push({\n label: `Local npm: ${localBin}`,\n command: localBin,\n args: commonArgs,\n checkCommand: localBin,\n checkArgs: [\"--version\"],\n useShell: process.platform === \"win32\",\n });\n }\n\n // 5) Global npm install\n const npmPrefix = this.getNpmGlobalPrefix();\n if (npmPrefix) {\n const globalBins = process.platform === \"win32\"\n ? [join(npmPrefix, \"headroom.cmd\"), join(npmPrefix, \"headroom\")]\n : [join(npmPrefix, \"bin\", \"headroom\"), join(npmPrefix, \"headroom\")];\n\n for (const globalBin of globalBins) {\n if (!existsSync(globalBin)) continue;\n specs.push({\n label: `Global npm: ${globalBin}`,\n command: globalBin,\n args: commonArgs,\n checkCommand: globalBin,\n checkArgs: [\"--version\"],\n useShell: process.platform === \"win32\",\n });\n }\n }\n\n // 6) Python module fallback\n const pythonCommands = this.getPythonCommands();\n for (const pyCmd of pythonCommands) {\n if (configuredPython && pyCmd === configuredPython) continue;\n specs.push({\n label: `Python: ${pyCmd} -m headroom.cli`,\n command: pyCmd,\n args: [\"-m\", \"headroom.cli\", ...commonArgs],\n checkCommand: pyCmd,\n checkArgs: [\"-c\", HEADROOM_MODULE_DISCOVERY_SNIPPET],\n });\n }\n\n return specs;\n }\n\n private getConfiguredPythonCommand(): string | null {\n const configured = typeof this.config.pythonPath === \"string\"\n ? this.config.pythonPath.trim()\n : \"\";\n return configured.length > 0 ? configured : null;\n }\n\n private getPyenvResolvedHeadroom(): string | null {\n if (process.platform !== \"win32\") return null;\n\n try {\n const result = spawnSync(\"pyenv\", [\"which\", \"headroom\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 5000,\n });\n if (result.error || result.status !== 0) return null;\n const resolved = (result.stdout ?? \"\").trim().split(/\\r?\\n/, 1)[0];\n if (!resolved || !existsSync(resolved)) return null;\n return resolved;\n } catch {\n return null;\n }\n }\n\n private getPythonCommands(): string[] {\n const commands: string[] = [];\n const configured = this.getConfiguredPythonCommand() ?? \"\";\n if (configured.length > 0) {\n commands.push(configured);\n }\n for (const fallback of [\"python\", \"python3\", \"py\"]) {\n if (!commands.includes(fallback)) commands.push(fallback);\n }\n return commands;\n }\n\n private canExecute(command: string, args: string[], useShell = false): boolean {\n try {\n const result = spawnSync(command, args, {\n shell: useShell,\n stdio: \"ignore\",\n timeout: 5000,\n });\n if (result.error) return false;\n return result.status === 0;\n } catch {\n return false;\n }\n }\n\n private getNpmGlobalPrefix(): string | null {\n try {\n const result = spawnSync(\"npm\", [\"prefix\", \"-g\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 5000,\n });\n if (result.error || result.status !== 0) return null;\n const prefix = (result.stdout ?? \"\").trim();\n return prefix.length > 0 ? prefix : null;\n } catch {\n return null;\n }\n }\n}\n\n/** Parse a URL, returning the parsed object or throwing a descriptive error. */\nfunction parseProxyUrl(proxyUrl: string): URL {\n try {\n return new URL(proxyUrl);\n } catch {\n throw new Error(`Invalid proxyUrl: \"${proxyUrl}\"`);\n }\n}\n\nexport function normalizeAndValidateProxyUrl(proxyUrl: string): string {\n const parsed = parseProxyUrl(proxyUrl);\n\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new Error(\"proxyUrl must use http:// or https://\");\n }\n\n if (parsed.pathname !== \"/\" || parsed.search || parsed.hash) {\n throw new Error(\"proxyUrl must not include a path, query, or hash\");\n }\n\n return parsed.origin;\n}\n\n/** Returns true if the URL points to a local address (localhost or 127.0.0.1). */\nexport function isLocalProxyUrl(proxyUrl: string): boolean {\n try {\n const parsed = new URL(proxyUrl);\n return parsed.hostname === \"127.0.0.1\" || parsed.hostname === \"localhost\";\n } catch {\n return false;\n }\n}\n\nfunction withDefaultPort(proxyUrl: string, defaultPort: number): string {\n const parsed = parseProxyUrl(proxyUrl);\n if (!parsed.port) {\n parsed.port = String(defaultPort);\n }\n return parsed.origin;\n}\n\n/**\n * Probe a configured URL and verify whether it is a running Headroom proxy.\n */\nexport async function probeHeadroomProxy(proxyUrl: string): Promise<ProxyProbeResult> {\n const origin = normalizeAndValidateProxyUrl(proxyUrl);\n const probeEndpoint = async (\n path: string,\n options: { readBody?: boolean } = {},\n ): Promise<{ reachable: boolean; ok: boolean; status?: number; body?: string }> => {\n try {\n const response = await fetch(`${origin}${path}`, {\n signal: AbortSignal.timeout(3_000),\n });\n const body =\n response.ok && options.readBody\n ? await response.text().catch(() => undefined)\n : undefined;\n return { reachable: true, ok: response.ok, status: response.status, body };\n } catch {\n return { reachable: false, ok: false };\n }\n };\n\n const ready = await probeEndpoint(\"/readyz\");\n const retrieveStats = await probeEndpoint(\"/v1/retrieve/stats\", { readBody: true });\n if (retrieveStats.ok && hasHeadroomStatsShape(retrieveStats.body)) {\n return { reachable: true, isHeadroom: true };\n }\n\n const stats = await probeEndpoint(\"/stats\", { readBody: true });\n if (stats.ok && hasHeadroomStatsShape(stats.body)) {\n return { reachable: true, isHeadroom: true };\n }\n\n const health = await probeEndpoint(\"/health\");\n const anyReachable = ready.reachable || retrieveStats.reachable || stats.reachable || health.reachable;\n if (!anyReachable) {\n return { reachable: false, isHeadroom: false, reason: \"proxy probe failed\" };\n }\n\n const reasons = [\n ready.reachable ? `readyz HTTP ${ready.status}` : \"readyz unavailable\",\n retrieveStats.reachable\n ? `retrieve stats HTTP ${retrieveStats.status}`\n : \"retrieve stats endpoint unavailable\",\n stats.reachable ? `stats HTTP ${stats.status}` : \"stats endpoint unavailable\",\n health.reachable ? `health HTTP ${health.status}` : \"health check failed\",\n ];\n return { reachable: true, isHeadroom: false, reason: reasons.join(\"; \") };\n}\n\nfunction hasHeadroomStatsShape(body: string | undefined): boolean {\n if (!body) {\n return false;\n }\n\n try {\n const parsed = JSON.parse(body) as Record<string, unknown>;\n return (\n parsed !== null &&\n typeof parsed === \"object\" &&\n (Object.hasOwn(parsed, \"proxy_inbound\") ||\n Object.hasOwn(parsed, \"api_requests\") ||\n Object.hasOwn(parsed, \"provider_tokens\") ||\n Object.hasOwn(parsed, \"proxy_compression_saved\") ||\n Object.hasOwn(parsed, \"store\") ||\n Object.hasOwn(parsed, \"recent_retrievals\"))\n );\n } catch {\n return false;\n }\n}\n\nasync function waitForHeadroomProxy(proxyUrl: string, timeoutMs: number): Promise<ProxyProbeResult> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n const result = await probeHeadroomProxy(proxyUrl);\n if (result.reachable && result.isHeadroom) {\n return result;\n }\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n return probeHeadroomProxy(proxyUrl);\n}\n","/**\n * Convert between OpenClaw's AgentMessage format and OpenAI message format.\n *\n * AgentMessage uses:\n * role: \"user\" | \"assistant\" | \"toolResult\"\n * content: string | ContentBlock[]\n *\n * OpenAI uses:\n * role: \"user\" | \"assistant\" | \"system\" | \"tool\"\n * content: string\n * tool_calls?: ToolCall[]\n * tool_call_id?: string\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport interface OpenAIMessage {\n role: string;\n content: string | null;\n tool_calls?: any[];\n tool_call_id?: string;\n name?: string;\n _headroomMeta?: Record<string, unknown>;\n}\n\n/**\n * Convert AgentMessage[] to OpenAI message format for compression.\n */\nexport function agentToOpenAI(messages: any[]): OpenAIMessage[] {\n const result: OpenAIMessage[] = [];\n\n for (const msg of messages) {\n const normalized = normalizeAgentMessage(msg);\n const role = normalized.role;\n\n const buildMeta = (): Record<string, unknown> => {\n const meta = { ...normalized } as Record<string, unknown>;\n delete meta.role;\n delete meta.content;\n return meta;\n };\n\n if (role === \"system\") {\n result.push({\n role: \"system\",\n content:\n typeof normalized.content === \"string\"\n ? normalized.content\n : extractText(normalized.content),\n _headroomMeta: buildMeta(),\n });\n continue;\n }\n\n if (role === \"user\") {\n result.push({\n role: \"user\",\n content:\n typeof normalized.content === \"string\"\n ? normalized.content\n : extractText(normalized.content),\n _headroomMeta: buildMeta(),\n });\n continue;\n }\n\n if (role === \"assistant\") {\n const content = normalized.content;\n if (typeof content === \"string\") {\n result.push({ role: \"assistant\", content, _headroomMeta: buildMeta() });\n continue;\n }\n\n // Content blocks: extract text and tool call blocks.\n // OpenClaw uses `toolCall`; some adapters still emit legacy `tool_use`.\n if (Array.isArray(content)) {\n const textParts: string[] = [];\n const toolCalls: any[] = [];\n\n for (const block of content) {\n if (typeof block === \"string\") {\n textParts.push(block);\n } else if (block.type === \"text\") {\n textParts.push(block.text);\n } else if (block.type === \"tool_use\" || block.type === \"toolCall\") {\n const args =\n block.type === \"toolCall\"\n ? block.arguments\n : block.input;\n toolCalls.push({\n id: block.id,\n type: \"function\",\n function: {\n name: block.name,\n arguments:\n typeof args === \"string\"\n ? args\n : JSON.stringify(args ?? {}),\n },\n });\n }\n }\n\n const openaiMsg: OpenAIMessage = {\n role: \"assistant\",\n content: textParts.length > 0 ? textParts.join(\"\") : null,\n _headroomMeta: buildMeta(),\n };\n if (toolCalls.length > 0) {\n openaiMsg.tool_calls = toolCalls;\n }\n result.push(openaiMsg);\n }\n continue;\n }\n\n if (role === \"toolResult\" || role === \"tool_result\") {\n const content =\n typeof normalized.content === \"string\"\n ? normalized.content\n : Array.isArray(normalized.content)\n ? extractText(normalized.content)\n : JSON.stringify(normalized.content);\n\n result.push({\n role: \"tool\",\n content,\n tool_call_id:\n normalized.toolCallId ??\n normalized.tool_use_id ??\n normalized.id ??\n \"unknown\",\n _headroomMeta: buildMeta(),\n });\n continue;\n }\n\n // Fallback: pass through as user message\n result.push({\n role: \"user\",\n content:\n typeof normalized.content === \"string\"\n ? normalized.content\n : JSON.stringify(normalized.content),\n _headroomMeta: buildMeta(),\n });\n }\n\n return result;\n}\n\n/**\n * Convert compressed OpenAI messages back to AgentMessage format.\n */\nexport function openAIToAgent(messages: OpenAIMessage[]): any[] {\n const result: any[] = [];\n\n for (const msg of messages) {\n const meta = (msg._headroomMeta ?? {}) as Record<string, unknown>;\n const timestamp =\n typeof meta.timestamp === \"number\" ? meta.timestamp : Date.now();\n\n if (msg.role === \"system\") {\n result.push({\n role: \"system\",\n content: msg.content ?? \"\",\n timestamp,\n });\n continue;\n }\n\n if (msg.role === \"user\") {\n result.push({\n role: \"user\",\n content: msg.content ?? \"\",\n timestamp,\n });\n continue;\n }\n\n if (msg.role === \"assistant\") {\n const blocks: any[] = [];\n if (msg.content) {\n blocks.push({ type: \"text\", text: msg.content });\n }\n if (msg.tool_calls) {\n for (const tc of msg.tool_calls) {\n let input: any;\n try {\n input = JSON.parse(tc.function.arguments);\n } catch {\n input = tc.function.arguments ?? {};\n }\n // Emit OpenClaw-native block shape so downstream transports keep call linkage.\n blocks.push({\n type: \"toolCall\",\n id: tc.id,\n name: tc.function.name,\n arguments: input,\n });\n }\n }\n // OpenClaw's Pi agent expects content to always be an array for assistant messages\n // (it calls .flatMap() on it). Never flatten to a string.\n result.push({\n ...(meta as object),\n role: \"assistant\",\n content: blocks,\n api: typeof meta.api === \"string\" ? meta.api : \"headroom\",\n provider: typeof meta.provider === \"string\" ? meta.provider : \"headroom\",\n model: typeof meta.model === \"string\" ? meta.model : \"headroom\",\n usage:\n isRecord(meta.usage)\n ? meta.usage\n : {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n },\n stopReason:\n typeof meta.stopReason === \"string\" ? meta.stopReason : \"stop\",\n timestamp,\n });\n continue;\n }\n\n if (msg.role === \"tool\") {\n const textContent =\n typeof msg.content === \"string\"\n ? msg.content\n : msg.content == null\n ? \"\"\n : JSON.stringify(msg.content);\n const toolCallId = msg.tool_call_id ?? \"unknown\";\n result.push({\n ...(meta as object),\n role: \"toolResult\",\n // OpenClaw transport layers expect toolResult content blocks, not a raw string.\n content: [{ type: \"text\", text: textContent }],\n toolCallId:\n typeof meta.toolCallId === \"string\" ? meta.toolCallId : toolCallId,\n tool_use_id:\n typeof meta.tool_use_id === \"string\" ? meta.tool_use_id : toolCallId,\n toolName:\n typeof meta.toolName === \"string\" ? meta.toolName : \"headroom\",\n isError: typeof meta.isError === \"boolean\" ? meta.isError : false,\n timestamp,\n });\n continue;\n }\n }\n\n return result;\n}\n\nexport function normalizeAgentMessages(messages: any[]): any[] {\n return messages.map((message) => normalizeAgentMessage(message));\n}\n\n/**\n * Extract text from content blocks.\n */\nfunction extractText(content: any): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return JSON.stringify(content);\n\n return content\n .map((block: any) => {\n if (typeof block === \"string\") return block;\n if (block.type === \"text\") return block.text;\n if (block.type === \"tool_result\") {\n return typeof block.content === \"string\" ? block.content : JSON.stringify(block.content);\n }\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction normalizeAgentMessage(message: any): any {\n if (!isRecord(message)) return message;\n\n if (message.role === \"assistant\") {\n return normalizeAssistantMessage(message);\n }\n\n if (message.role === \"toolResult\" || message.role === \"tool_result\") {\n return normalizeToolResultMessage(message);\n }\n\n return message;\n}\n\nfunction normalizeAssistantMessage(message: Record<string, any>): Record<string, any> {\n const normalizedContent = normalizeAssistantContent(message.content);\n\n return {\n ...message,\n content: normalizedContent,\n api: typeof message.api === \"string\" ? message.api : \"headroom\",\n provider: typeof message.provider === \"string\" ? message.provider : \"headroom\",\n model: typeof message.model === \"string\" ? message.model : \"headroom\",\n usage: isRecord(message.usage)\n ? message.usage\n : {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n },\n stopReason: typeof message.stopReason === \"string\" ? message.stopReason : \"stop\",\n timestamp: typeof message.timestamp === \"number\" ? message.timestamp : Date.now(),\n };\n}\n\nfunction normalizeToolResultMessage(message: Record<string, any>): Record<string, any> {\n const normalizedContent = normalizeToolResultContent(message.content);\n const toolCallId =\n typeof message.toolCallId === \"string\"\n ? message.toolCallId\n : typeof message.tool_use_id === \"string\"\n ? message.tool_use_id\n : typeof message.id === \"string\"\n ? message.id\n : \"unknown\";\n\n return {\n ...message,\n role: \"toolResult\",\n content: normalizedContent,\n toolCallId,\n tool_use_id:\n typeof message.tool_use_id === \"string\" ? message.tool_use_id : toolCallId,\n toolName: typeof message.toolName === \"string\" ? message.toolName : \"headroom\",\n isError: typeof message.isError === \"boolean\" ? message.isError : false,\n timestamp: typeof message.timestamp === \"number\" ? message.timestamp : Date.now(),\n };\n}\n\nfunction normalizeAssistantContent(content: unknown): any[] {\n if (Array.isArray(content)) {\n return content.flatMap((block) => {\n if (typeof block === \"string\") return [{ type: \"text\", text: block }];\n if (!isRecord(block) || typeof block.type !== \"string\") return [];\n if (block.type === \"text\" && typeof block.text === \"string\") return [block];\n if (block.type === \"thinking\" && typeof block.thinking === \"string\") return [block];\n if (\n (block.type === \"toolCall\" || block.type === \"tool_use\") &&\n typeof block.name === \"string\"\n ) {\n return [\n {\n type: \"toolCall\",\n id: typeof block.id === \"string\" ? block.id : \"unknown\",\n name: block.name,\n arguments:\n \"arguments\" in block\n ? block.arguments\n : \"input\" in block\n ? block.input\n : {},\n },\n ];\n }\n return [];\n });\n }\n\n if (typeof content === \"string\" && content.length > 0) {\n return [{ type: \"text\", text: content }];\n }\n\n if (content == null) {\n return [];\n }\n\n return [{ type: \"text\", text: JSON.stringify(content) }];\n}\n\nfunction normalizeToolResultContent(content: unknown): any[] {\n if (Array.isArray(content)) {\n return content.flatMap((block) => {\n if (typeof block === \"string\") return [{ type: \"text\", text: block }];\n if (!isRecord(block) || typeof block.type !== \"string\") return [];\n if (block.type === \"text\" && typeof block.text === \"string\") return [block];\n if (\n block.type === \"image\" &&\n typeof block.data === \"string\" &&\n typeof block.mimeType === \"string\"\n ) {\n return [block];\n }\n if (block.type === \"tool_result\" && \"content\" in block) {\n return normalizeToolResultContent(block.content);\n }\n return [];\n });\n }\n\n if (typeof content === \"string\" && content.length > 0) {\n return [{ type: \"text\", text: content }];\n }\n\n if (content == null) {\n return [];\n }\n\n return [{ type: \"text\", text: JSON.stringify(content) }];\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","export interface OpenClawCompactParams {\n sessionId: string;\n sessionKey?: string;\n agentId?: string;\n sessionTarget?: unknown;\n sessionFile?: string;\n tokenBudget?: number;\n force?: boolean;\n currentTokenCount?: number;\n compactionTarget?: \"budget\" | \"threshold\";\n customInstructions?: string;\n runtimeSettings?: unknown;\n runtimeContext?: unknown;\n abortSignal?: AbortSignal;\n}\n\nexport interface OpenClawCompactResult {\n ok: boolean;\n compacted: boolean;\n reason?: string;\n result?: {\n summary?: string;\n firstKeptEntryId?: string;\n tokensBefore: number;\n tokensAfter?: number;\n details?: unknown;\n sessionId?: string;\n sessionTarget?: unknown;\n sessionFile?: string;\n };\n}\n\nconst OPENCLAW_PLUGIN_SDK_CORE = \"openclaw/plugin-sdk/core\";\n\n/** Delegate compaction without bundling the optional OpenClaw peer dependency. */\nexport async function delegateCompactionToRuntime(\n params: OpenClawCompactParams,\n): Promise<OpenClawCompactResult> {\n const pluginSdk = (await import(OPENCLAW_PLUGIN_SDK_CORE)) as {\n delegateCompactionToRuntime?: (\n compactParams: OpenClawCompactParams,\n ) => Promise<OpenClawCompactResult>;\n };\n\n if (!pluginSdk.delegateCompactionToRuntime) {\n throw new Error(\"OpenClaw runtime does not expose delegateCompactionToRuntime\");\n }\n\n return pluginSdk.delegateCompactionToRuntime(params);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport const DEFAULT_GATEWAY_PROVIDER_IDS = [\"openai-codex\"] as const;\n\nconst DEFAULT_PROVIDER_BASE_URLS: Readonly<Record<string, string>> = {\n \"openai-codex\": \"https://chatgpt.com/backend-api\",\n};\n\nconst GATEWAY_PROVIDER_ID_ALIASES: Readonly<Record<string, string>> = {\n codex: \"openai-codex\",\n claude: \"anthropic\",\n copilot: \"github-copilot\",\n gemini: \"google\",\n};\n\nconst EXPLICIT_BASE_URL_REQUIRED_PROVIDER_IDS = new Set<string>([\"github-copilot\"]);\n\nexport function resolveGatewayProviderIds(config: Record<string, unknown> | undefined): string[] {\n const configuredProviderIds = normalizeGatewayProviderIds(config?.gatewayProviderIds);\n if (configuredProviderIds.length > 0) {\n return configuredProviderIds;\n }\n\n if (config?.routeCodexViaProxy === false) {\n return [];\n }\n\n return [...DEFAULT_GATEWAY_PROVIDER_IDS];\n}\n\nfunction normalizeGatewayProviderIds(value: unknown): string[] {\n if (!Array.isArray(value)) {\n return [];\n }\n\n const seen = new Set<string>();\n const normalized: string[] = [];\n\n for (const entry of value) {\n if (typeof entry !== \"string\") {\n continue;\n }\n\n const rawProviderId = entry.trim();\n const providerId = GATEWAY_PROVIDER_ID_ALIASES[rawProviderId.toLowerCase()] ?? rawProviderId;\n if (!providerId || seen.has(providerId)) {\n continue;\n }\n\n seen.add(providerId);\n normalized.push(providerId);\n }\n\n return normalized;\n}\n\nexport function applyGatewayProviderBaseUrls<T>(\n cfg: T,\n proxyUrl: string,\n providerIds: readonly string[],\n): { changed: boolean; config: T } {\n const next = structuredClone((cfg ?? {}) as any);\n const changed = applyGatewayProviderBaseUrlsInPlace(next, proxyUrl, providerIds);\n return { changed, config: next as T };\n}\n\nexport function applyGatewayProviderBaseUrlsInPlace(\n cfg: any,\n proxyUrl: string,\n providerIds: readonly string[],\n): boolean {\n if (!cfg || typeof cfg !== \"object\" || providerIds.length === 0) {\n return false;\n }\n\n const models = (cfg.models ??= {});\n const providers = (models.providers ??= {});\n let changed = false;\n\n for (const providerId of providerIds) {\n const currentValue = providers[providerId];\n const currentConfig =\n currentValue && typeof currentValue === \"object\" && !Array.isArray(currentValue)\n ? currentValue\n : {};\n const nextConfig = { ...currentConfig };\n const currentBaseUrl =\n typeof nextConfig.baseUrl === \"string\" && nextConfig.baseUrl.trim().length > 0\n ? nextConfig.baseUrl\n : undefined;\n const defaultBaseUrl = DEFAULT_PROVIDER_BASE_URLS[providerId];\n if (\n !currentBaseUrl &&\n !defaultBaseUrl &&\n EXPLICIT_BASE_URL_REQUIRED_PROVIDER_IDS.has(providerId)\n ) {\n continue;\n }\n const nextBaseUrl = routeBaseUrlThroughProxy({\n providerId,\n proxyUrl,\n currentBaseUrl,\n });\n\n if (!Array.isArray(nextConfig.models)) {\n nextConfig.models = [];\n changed = true;\n }\n\n if (nextConfig.baseUrl === nextBaseUrl) {\n providers[providerId] = nextConfig;\n continue;\n }\n\n nextConfig.baseUrl = nextBaseUrl;\n providers[providerId] = nextConfig;\n changed = true;\n }\n\n return changed;\n}\n\nfunction routeBaseUrlThroughProxy(params: {\n providerId: string;\n proxyUrl: string;\n currentBaseUrl?: string;\n}): string {\n const upstreamBaseUrl = params.currentBaseUrl ?? DEFAULT_PROVIDER_BASE_URLS[params.providerId];\n if (!upstreamBaseUrl) {\n return params.proxyUrl;\n }\n\n try {\n const proxy = new URL(params.proxyUrl);\n const upstream = new URL(upstreamBaseUrl);\n proxy.pathname = upstream.pathname;\n proxy.search = upstream.search;\n proxy.hash = \"\";\n return proxy.toString().replace(/\\/$/, \"\");\n } catch {\n return params.proxyUrl;\n }\n}\n","/**\n * CCR (Compress-Cache-Retrieve) tool for OpenClaw.\n *\n * Allows the agent to retrieve original uncompressed content\n * from the Headroom proxy's compression store.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { normalizeAndValidateProxyUrl } from \"../proxy-manager.js\";\n\nexport interface RetrieveToolConfig {\n proxyUrl: string;\n}\n\nexport function createHeadroomRetrieveTool(config: RetrieveToolConfig) {\n const proxyOrigin = normalizeAndValidateProxyUrl(config.proxyUrl);\n\n return {\n name: \"headroom_retrieve\",\n description:\n \"Retrieve original uncompressed content from Headroom's compression store. \" +\n \"Use when compressed context mentions a hash and you need the full details. \" +\n \"Pass the hash from the compression marker (24 hex characters). \" +\n \"Retrieval is by hash and always returns the full original content.\",\n parameters: {\n type: \"object\" as const,\n properties: {\n hash: {\n type: \"string\",\n description: \"The 24-character hex hash from the compression marker\",\n },\n },\n required: [\"hash\"],\n },\n execute: async (args: { hash: string }): Promise<string> => {\n const { hash } = args;\n\n // Validate hash format\n if (!/^[a-f0-9]{24}$/i.test(hash)) {\n return JSON.stringify({\n error: \"Invalid hash format. Expected 24 hex characters.\",\n });\n }\n\n try {\n const url = `${proxyOrigin}/v1/retrieve/${hash}`;\n\n const resp = await fetch(url, {\n signal: AbortSignal.timeout(10_000),\n });\n\n if (!resp.ok) {\n const body = await resp.text().catch(() => \"\");\n return JSON.stringify({\n error: `Retrieval failed: HTTP ${resp.status}`,\n details: body,\n });\n }\n\n const data = await resp.json();\n return typeof data === \"string\" ? data : JSON.stringify(data);\n } catch (error) {\n return JSON.stringify({\n error: `Retrieval failed: ${error}`,\n hint: \"The compressed content may have expired (default TTL: 30 minutes)\",\n });\n }\n },\n };\n}\n","/**\n * Headroom OpenClaw Plugin — register ContextEngine + CCR retrieval tool.\n *\n * Usage:\n * openclaw plugins install headroom-ai/openclaw\n *\n * Configuration (in ~/.openclaw/config.json or ~/.clawdbot/clawdbot.json):\n * {\n * \"plugins\": {\n * \"slots\": { \"contextEngine\": \"headroom\" },\n * \"entries\": { \"headroom\": { \"enabled\": true } }\n * }\n * }\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { HeadroomContextEngine } from \"../engine.js\";\nimport {\n applyGatewayProviderBaseUrlsInPlace,\n resolveGatewayProviderIds,\n} from \"../gateway-config.js\";\nimport { normalizeAndValidateProxyUrl, probeHeadroomProxy } from \"../proxy-manager.js\";\nimport { createHeadroomRetrieveTool } from \"../tools/headroom-retrieve.js\";\n\n/**\n * OpenClaw 2026.x plugin API requires a `{ register(api) }` object export.\n * The previous bare-function default export was silently skipped by the loader.\n * See: https://github.com/headroomlabs-ai/headroom/issues/XXX\n */\nexport default {\n register: registerHeadroomPlugin,\n};\n\nexport function registerHeadroomPlugin(api: any) {\n const config = api.config?.plugins?.entries?.headroom?.config ?? {};\n const logger = api.logger ?? console;\n const rawProxyUrl = config.proxyUrl;\n const proxyUrl =\n typeof rawProxyUrl === \"string\" && rawProxyUrl.trim().length > 0\n ? normalizeAndValidateProxyUrl(rawProxyUrl)\n : undefined;\n\n const engine = new HeadroomContextEngine({ ...config, proxyUrl }, {\n info: (m: string) => logger.info(m),\n warn: (m: string) => logger.warn(m),\n error: (m: string) => logger.error(m),\n debug: (m: string) => logger.debug?.(m),\n });\n const gatewayProviderIds = resolveGatewayProviderIds(config);\n let validatedConfiguredProxyUrl: string | null = null;\n let configuredProxyProbePromise: Promise<string | null> | null = null;\n\n const applyGatewayRouting = async (activeProxyUrl: string) => {\n if (gatewayProviderIds.length === 0) {\n return;\n }\n\n try {\n const changed = applyGatewayProviderBaseUrlsInPlace(api.config, activeProxyUrl, gatewayProviderIds);\n\n if (changed) {\n logger.info(\n `[headroom] Routed ${gatewayProviderIds.join(\", \")} through Headroom proxy in memory at ${activeProxyUrl}`,\n );\n } else {\n logger.info(\n `[headroom] Upstream gateway already routed in memory for ${gatewayProviderIds.join(\", \")} at ${activeProxyUrl}`,\n );\n }\n } catch (error) {\n logger.warn(`[headroom] Failed to configure upstream gateway routing: ${error}`);\n }\n };\n\n const getConfiguredRoutingProxyUrl = async (): Promise<string | null> => {\n if (!proxyUrl) {\n return null;\n }\n if (validatedConfiguredProxyUrl === proxyUrl) {\n return validatedConfiguredProxyUrl;\n }\n if (!configuredProxyProbePromise) {\n configuredProxyProbePromise = probeHeadroomProxy(proxyUrl)\n .then((probe) => {\n if (probe.reachable && probe.isHeadroom) {\n validatedConfiguredProxyUrl = proxyUrl;\n return proxyUrl;\n }\n logger.warn(\n `[headroom] Skipping upstream gateway routing: configured proxyUrl is not a ready Headroom proxy at ${proxyUrl}` +\n (probe.reason ? ` (${probe.reason})` : \"\"),\n );\n return null;\n })\n .catch((error) => {\n logger.warn(\n `[headroom] Skipping upstream gateway routing: failed to probe configured proxyUrl ${proxyUrl}: ${error}`,\n );\n return null;\n })\n .finally(() => {\n configuredProxyProbePromise = null;\n });\n }\n return configuredProxyProbePromise;\n };\n\n const ensureGatewayRouting = async () => {\n if (gatewayProviderIds.length === 0) {\n return;\n }\n const activeProxyUrl = engine.getProxyUrl() ?? (await getConfiguredRoutingProxyUrl());\n if (!activeProxyUrl) {\n logger.debug?.(\"[headroom] Deferring upstream gateway routing until proxy is available\");\n return;\n }\n await applyGatewayRouting(activeProxyUrl);\n };\n\n engine.onProxyReady(async (activeProxyUrl) => {\n await applyGatewayRouting(activeProxyUrl);\n });\n\n // Register as context engine\n api.registerContextEngine(\"headroom\", () => engine);\n\n // Register CCR retrieval tool (active once proxy is running)\n api.registerTool((ctx: any) => {\n const activeProxyUrl = engine.getProxyUrl() ?? proxyUrl;\n if (!activeProxyUrl) return null;\n return createHeadroomRetrieveTool({ proxyUrl: activeProxyUrl });\n }, { names: [\"headroom_retrieve\"] });\n\n api.on(\"gateway_start\", async () => {\n await ensureGatewayRouting();\n });\n\n void ensureGatewayRouting();\n\n logger.info(\"[headroom] Plugin registered\");\n}\n"],"mappings":"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","names":[]}
|
package/dist/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "headroom-openclaw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "Headroom context compression plugin for OpenClaw — 70-90% token savings with zero LLM calls",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
7
7
|
"types": "./index.d.ts",
|
|
8
8
|
"license": "Apache-2.0",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"headroom-ai": "^0.
|
|
10
|
+
"headroom-ai": "^0.38.0"
|
|
11
11
|
},
|
|
12
12
|
"peerDependencies": {
|
|
13
13
|
"openclaw": "*"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "headroom-openclaw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "Headroom context compression plugin for OpenClaw — 70-90% token savings with zero LLM calls",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"typecheck": "node node_modules/@typescript/native/bin/tsc --noEmit"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"headroom-ai": "^0.
|
|
21
|
+
"headroom-ai": "^0.38.0"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"openclaw": "*"
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@types/node": "^26.1.1",
|
|
34
34
|
"tsup": "^8.0.0",
|
|
35
35
|
"typescript": "^6.0.3",
|
|
36
|
-
"vitest": "^
|
|
36
|
+
"vitest": "^5.0.0"
|
|
37
37
|
},
|
|
38
38
|
"overrides": {
|
|
39
39
|
"esbuild": "^0.28.1"
|