headroom/sdk/typescript
github-actions[bot] 660fa8cfb6
chore: release main (#1574)
🤖 I have created a release *beep* *boop*
---


<details><summary>0.29.0</summary>

##
[0.29.0](https://github.com/headroomlabs-ai/headroom/compare/v0.28.0...v0.29.0)
(2026-07-03)


### Features

* **proxy:** add --lossless no-CCR mode with format-native compaction
([#1721](https://github.com/headroomlabs-ai/headroom/issues/1721))
([c75ebde](c75ebdee6d))
* **stats:** surface Codex WS compression counters in /stats summary
([#1680](https://github.com/headroomlabs-ai/headroom/issues/1680))
([2fe19c3](2fe19c39e4))
* **transforms:** adaptive Otsu KEEP/DROP threshold (+ land relevance
split on main)
([#1726](https://github.com/headroomlabs-ai/headroom/issues/1726))
([eea667a](eea667a720))


### Bug Fixes

* **bedrock:** fail fast when session-token auth lacks botocore
([#1553](https://github.com/headroomlabs-ai/headroom/issues/1553))
([54cfa36](54cfa361d3))
* **bedrock:** route ARNs via converse, named AWS profiles, and au. re…
([#1456](https://github.com/headroomlabs-ai/headroom/issues/1456))
([7d87aa2](7d87aa2f1c))
* **ccr:** honor workspace dir for sqlite store
([#1564](https://github.com/headroomlabs-ai/headroom/issues/1564))
([96e1dfe](96e1dfe395))
* **claude:** surface Remote Control proxy incompatibility
([#1610](https://github.com/headroomlabs-ai/headroom/issues/1610))
([4bf7f92](4bf7f92417))
* **cli:** stop advertising unwired compression tuning env vars in
banner
([#1634](https://github.com/headroomlabs-ai/headroom/issues/1634))
([d5bf98d](d5bf98df31))
* **codex:** avoid duplicate headroom provider config
([#1431](https://github.com/headroomlabs-ai/headroom/issues/1431))
([ddd4adf](ddd4adf911))
* **compression:** reject lossy unmarked tool output in unit router path
([#1479](https://github.com/headroomlabs-ai/headroom/issues/1479))
([de24cd5](de24cd5fc0))
* **cortex-code:** migrate to current Cortex REST API endpoints + add
e2e benchmarks
([#1474](https://github.com/headroomlabs-ai/headroom/issues/1474))
([f00ace6](f00ace6da5))
* **dashboard:** align token savings headline denominator
([#1653](https://github.com/headroomlabs-ai/headroom/issues/1653))
([646e705](646e705514))
* **dashboard:** derive per-project setup URL from live origin
([#1511](https://github.com/headroomlabs-ai/headroom/issues/1511))
([e035aef](e035aefce2))
* **detection:** contain unidiff panic on orphaned +++ target line
([#1548](https://github.com/headroomlabs-ai/headroom/issues/1548))
([e386c09](e386c097d6))
* **evals:** CJK-aware F1 tokenization + token estimation
([#1527](https://github.com/headroomlabs-ai/headroom/issues/1527))
([99a8540](99a8540e65))
* **install:** close parent log fd in start_detached_agent
([#1576](https://github.com/headroomlabs-ai/headroom/issues/1576))
([816cb85](816cb85fa8))
* **install:** use Windows-safe PID liveness probe in runtime_status
([#1544](https://github.com/headroomlabs-ai/headroom/issues/1544))
([#1560](https://github.com/headroomlabs-ai/headroom/issues/1560))
([6b227b9](6b227b9c90))
* **learn:** aggregate verbosity baselines across projects instead of
overwriting
([#1288](https://github.com/headroomlabs-ai/headroom/issues/1288))
([27a5468](27a5468349))
* **mcp:** show lifetime totals and label rolling session scope in
headroom_stats
([#1428](https://github.com/headroomlabs-ai/headroom/issues/1428))
([1c0e152](1c0e15243e))
* **memory:** cap local embedder CPU thread oversubscription
([#198](https://github.com/headroomlabs-ai/headroom/issues/198))
([#1559](https://github.com/headroomlabs-ai/headroom/issues/1559))
([b84afbf](b84afbfb83))
* **memory:** singleflight LocalBackend init to stop cold-start races
([#1691](https://github.com/headroomlabs-ai/headroom/issues/1691))
([bec47a1](bec47a1898))
* **openclaw:** detect uv-installed headroom binary in ~/.local/bin
([#1459](https://github.com/headroomlabs-ai/headroom/issues/1459))
([adaeb88](adaeb88a4d))
* **opencode:** preserve custom OpenAI gateway paths
([#1596](https://github.com/headroomlabs-ai/headroom/issues/1596))
([c19347c](c19347c310))
* **opencode:** route native providers + load transport plugin, fix
Serena context
([#1573](https://github.com/headroomlabs-ai/headroom/issues/1573))
([ad0034f](ad0034f981))
* preserve anthropic passthrough tool order
([#1427](https://github.com/headroomlabs-ai/headroom/issues/1427))
([a932247](a9322477e3))
* **proxy/auth:** match real Anthropic OAuth token prefix (sk-ant-oat)
([#1672](https://github.com/headroomlabs-ai/headroom/issues/1672))
([8cddf9b](8cddf9b58e))
* **proxy:** expose persistent savings metrics
([#1647](https://github.com/headroomlabs-ai/headroom/issues/1647))
([5fe4e7b](5fe4e7b195))
* **proxy:** fail open when kompress saturation would exhaust
pre-upstream budget
([#1430](https://github.com/headroomlabs-ai/headroom/issues/1430))
([15ac650](15ac650d40))
* **proxy:** handle streaming CCR retrieval
([#1451](https://github.com/headroomlabs-ai/headroom/issues/1451))
([d337e3b](d337e3b828))
* **proxy:** include system/tools/sampling in cache key
([#1473](https://github.com/headroomlabs-ai/headroom/issues/1473))
([312129a](312129a8e7))
* **proxy:** preserve Responses passthrough bytes
([#1598](https://github.com/headroomlabs-ai/headroom/issues/1598))
([2a34a82](2a34a822f2))
* **proxy:** strip Codex lite header on the HTTP /responses path
([#1663](https://github.com/headroomlabs-ai/headroom/issues/1663))
([9fbd47b](9fbd47ba6b))
* **proxy:** wire --compression-max-workers /
HEADROOM_COMPRESSION_MAX_WORKERS
([#1632](https://github.com/headroomlabs-ai/headroom/issues/1632))
([814ffa3](814ffa36a4))
* **savings:** count cache-read tokens in input cost estimate
([#1429](https://github.com/headroomlabs-ai/headroom/issues/1429))
([72ade37](72ade37112))
* skip Magika backend on x86 CPUs without AVX2
([#1162](https://github.com/headroomlabs-ai/headroom/issues/1162))
([64783d8](64783d8824))
* **transforms/content-router:** route grep/log output away from HTML
extractor
([#1719](https://github.com/headroomlabs-ai/headroom/issues/1719))
([0d18ef2](0d18ef26f4))
* **transforms:** bound native content detection with a Windows watchdog
([#575](https://github.com/headroomlabs-ai/headroom/issues/575))
([#1563](https://github.com/headroomlabs-ai/headroom/issues/1563))
([95abca3](95abca3abd))
* Vertex AI support for Claude Code with ANTHROPIC_VERTEX_BASE_URL
([#1393](https://github.com/headroomlabs-ai/headroom/issues/1393))
([cff7247](cff7247efd))
* **wrap:** detach the shared proxy on Windows so it survives an
ungraceful agent close
([#1464](https://github.com/headroomlabs-ai/headroom/issues/1464))
([6cba441](6cba4419d0))
* **wrap:** preserve custom Vertex base URL
([#1477](https://github.com/headroomlabs-ai/headroom/issues/1477))
([75427bb](75427bbd4a))
* **wrap:** remove rtk instructions from Codex AGENTS.md on unwrap
([#1604](https://github.com/headroomlabs-ai/headroom/issues/1604))
([c9d717c](c9d717c13c))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-02 22:54:04 -07:00
..
examples typescript coverage 2026-04-06 21:24:36 +06:00
src feat(telemetry): add headroom_stack and install_mode identity fields 2026-04-17 17:12:38 +02:00
test test(sdk/ts): add HEADROOM_WORKSPACE_DIR precedence tests for derived helpers 2026-04-16 19:59:38 -05:00
.gitignore Add TypeScript SDK (headroom-ai npm package) 2026-03-26 15:41:56 -07:00
package-lock.json fix(deps): remediate dependency CVEs and publish SBOM (#1509) 2026-06-27 15:28:12 -07:00
package.json chore: release main (#1574) 2026-07-02 22:54:04 -07:00
README.md chore: remove committed node_modules + stray/internal markdown (repo hygiene) (#1528) 2026-06-27 23:32:54 -07:00
tsconfig.json Add TypeScript SDK (headroom-ai npm package) 2026-03-26 15:41:56 -07:00
tsup.config.ts typescript coverage 2026-04-06 21:24:36 +06:00
vitest.config.ts Add TypeScript SDK (headroom-ai npm package) 2026-03-26 15:41:56 -07:00

headroom-ai

Compress LLM context. Save tokens. Fit more into every request.

Install

npm install headroom-ai

Quick Start

import { compress } from 'headroom-ai';

const result = await compress(messages, { model: 'gpt-4o' });
console.log(`Saved ${result.tokensSaved} tokens (${((1 - result.compressionRatio) * 100).toFixed(0)}%)`);

// Use compressed messages with any LLM client
const response = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: result.messages,
});

Requires a running Headroom proxy (headroom proxy).

Framework Adapters

Vercel AI SDK

import { withHeadroom } from 'headroom-ai/vercel-ai';
import { openai } from '@ai-sdk/openai';
import { generateText } from 'ai';

const model = withHeadroom(openai('gpt-4o'));
const { text } = await generateText({ model, messages });
Advanced: using middleware directly
import { headroomMiddleware } from 'headroom-ai/vercel-ai';
import { wrapLanguageModel } from 'ai';

const model = wrapLanguageModel({
  model: openai('gpt-4o'),
  middleware: headroomMiddleware({ baseUrl: 'http://localhost:8787' }),
});

OpenAI SDK

import { withHeadroom } from 'headroom-ai/openai';
import OpenAI from 'openai';

const client = withHeadroom(new OpenAI());
const response = await client.chat.completions.create({
  model: 'gpt-4o',
  messages: longConversation,
});

Anthropic SDK

import { withHeadroom } from 'headroom-ai/anthropic';
import Anthropic from '@anthropic-ai/sdk';

const client = withHeadroom(new Anthropic());
const response = await client.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  messages: longConversation,
  max_tokens: 1024,
});

Google Gemini

import { withHeadroom } from 'headroom-ai/gemini';
import { GoogleGenerativeAI } from '@google/generative-ai';

const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);
const model = withHeadroom(genAI.getGenerativeModel({ model: 'gemini-2.0-flash' }));

const result = await model.generateContent({
  contents: longConversation,
});

HeadroomClient

The full client provides direct access to the proxy's OpenAI and Anthropic passthrough endpoints, plus metrics, CCR, and observability.

import { HeadroomClient } from 'headroom-ai';

const client = new HeadroomClient({
  baseUrl: 'http://localhost:8787',
  providerApiKey: process.env.OPENAI_API_KEY,
  config: {
    smartCrusher: { enabled: true, maxItemsAfterCrush: 10 },
    ccr: { enabled: true },
  },
});

Chat Completions (OpenAI-style)

const response = await client.chat.completions.create({
  model: 'gpt-4o',
  messages: longConversation,
  headroomMode: 'optimize',
});

Messages (Anthropic-style)

const response = await client.messages.create({
  model: 'claude-sonnet-4-5-20250929',
  messages: longConversation,
  max_tokens: 1024,
  headroomMode: 'optimize',
});

Direct Compression

const result = await client.compress(messages, { model: 'gpt-4o', tokenBudget: 4000 });

Simulation (Dry Run)

See what compression would do without calling the LLM.

import { simulate } from 'headroom-ai';

const sim = await simulate(messages, { model: 'gpt-4o' });
console.log(`Would save ${sim.tokensSaved} tokens (${sim.estimatedSavings})`);
console.log('Transforms:', sim.transforms);
console.log('Waste signals:', sim.wasteSignals);
console.log('Cache alignment:', sim.cacheAlignmentScore);

Also available on the client:

const sim = await client.chat.completions.simulate({
  model: 'gpt-4o',
  messages,
});

Compression Hooks

Customize compression with pre/post hooks — matching the Python CompressionHooks API.

import { compress, CompressionHooks } from 'headroom-ai';
import type { CompressContext, CompressEvent } from 'headroom-ai';

class MyHooks extends CompressionHooks {
  // Modify messages before compression
  preCompress(messages: any[], ctx: CompressContext) {
    return [{ role: 'system', content: 'Always preserve error details.' }, ...messages];
  }

  // Set per-message importance biases
  computeBiases(messages: any[], ctx: CompressContext) {
    return { 0: 2.0 }; // preserve first message
  }

  // Observe compression results
  postCompress(event: CompressEvent) {
    console.log(`Saved ${event.tokensSaved} tokens via ${event.transformsApplied.join(', ')}`);
  }
}

const result = await compress(messages, { model: 'gpt-4o', hooks: new MyHooks() });

SharedContext (Multi-Agent)

Compressed inter-agent context sharing — matching the Python SharedContext API.

import { SharedContext } from 'headroom-ai';

const ctx = new SharedContext({ model: 'gpt-4o', ttl: 3600, maxEntries: 100 });

// Agent A stores data (automatically compressed)
const entry = await ctx.put('research', bigAgentOutput, { agent: 'researcher' });
console.log(`Compressed: ${entry.savingsPercent.toFixed(0)}% savings`);

// Agent B reads it (~80% smaller)
const summary = ctx.get('research');

// Agent B gets original if needed
const full = ctx.get('research', { full: true });

// Stats
const stats = ctx.stats();
console.log(`${stats.entries} entries, ${stats.totalTokensSaved} tokens saved`);

CCR Retrieve (Compress-Cache-Retrieve)

Retrieve original content when the LLM needs full details.

const result = await client.compress(messages, { model: 'gpt-4o' });

// Later, when the LLM calls headroom_retrieve:
for (const hash of result.ccrHashes) {
  const original = await client.retrieve(hash);
  console.log(`${original.originalTokens} original tokens for ${original.toolName}`);
}

// Search within compressed content
const search = await client.retrieve('abc123', { query: 'error logs' });

// Handle LLM tool calls in an agent loop
const toolResult = await client.handleToolCall({
  toolCall: assistantMessage.tool_calls[0],
  provider: 'openai',
});

Metrics & Observability

// Proxy health
const health = await client.health();
// → { status: 'healthy', version: '0.5.18', config: { optimize: true, ... } }

// Proxy stats
const stats = await client.proxyStats();
// → { requests: { total, cached, failed }, tokens: { saved, savingsPercent }, ... }

// Request metrics
const metrics = await client.getMetrics({ model: 'gpt-4o', limit: 10 });

// Summary
const summary = await client.getSummary();

// Validate setup
const validation = await client.validateSetup();

// Clear cache
await client.clearCache();

// Prometheus metrics
const prom = await client.prometheusMetrics();

Telemetry, Feedback & TOIN

Access the proxy's learning systems.

// Telemetry
const telemetry = await client.telemetry.getStats();
const tools = await client.telemetry.getTools();

// Feedback — per-tool compression hints
const hints = await client.feedback.getHints('list_servers');
// → { hints: { maxItems: 8, skipCompression: false, preserveFields: ['id', 'status'] } }

// TOIN (Tool Output Intelligence Network)
const toinStats = await client.toin.getStats();
const patterns = await client.toin.getPatterns(20);

Configuration Types

Full TypeScript interfaces for every Python config dataclass.

import type { HeadroomConfig, SmartCrusherConfig, CCRConfig } from 'headroom-ai';

const config: HeadroomConfig = {
  defaultMode: 'optimize',
  smartCrusher: {
    enabled: true,
    minItemsToAnalyze: 5,
    maxItemsAfterCrush: 10,
    varianceThreshold: 2.0,
    relevance: { tier: 'hybrid', relevanceThreshold: 0.25 },
    anchor: { anchorBudgetPct: 0.25 },
  },
  ccr: { enabled: true, injectTool: true },
  cacheOptimizer: { enabled: true, autoDetectProvider: true },
  intelligentContext: { enabled: true, useImportanceScoring: true },
};

const client = new HeadroomClient({ config });

Error Handling

Full error hierarchy matching the Python SDK.

import {
  HeadroomError,
  HeadroomConnectionError,
  HeadroomAuthError,
  HeadroomCompressError,
  ConfigurationError,
  ProviderError,
  StorageError,
  TokenizationError,
  CacheError,
  ValidationError,
  TransformError,
} from 'headroom-ai';

try {
  await client.compress(messages);
} catch (err) {
  if (err instanceof HeadroomAuthError) {
    console.error('Auth failed — check HEADROOM_API_KEY');
  } else if (err instanceof HeadroomCompressError) {
    console.error(`Compression error ${err.statusCode}: ${err.errorType}`);
  } else if (err instanceof ConfigurationError) {
    console.error('Bad config:', err.details);
  }
}

Format Detection & Conversion

Auto-detects and converts between OpenAI, Anthropic, Vercel AI SDK, and Gemini formats.

import { detectFormat, toOpenAI, fromOpenAI } from 'headroom-ai';

const format = detectFormat(messages); // 'openai' | 'anthropic' | 'vercel' | 'gemini'
const openaiMessages = toOpenAI(messages);
const back = fromOpenAI(openaiMessages, format);

The compress() function handles this automatically — pass any format and get the same format back.

Configuration

import { compress } from 'headroom-ai';

const result = await compress(messages, {
  model: 'gpt-4o',
  baseUrl: 'http://localhost:8787',  // proxy URL
  apiKey: 'your-api-key',             // optional, for authenticated endpoints
  timeout: 30000,                     // ms
  fallback: true,                     // return uncompressed if proxy is down (default)
  retries: 1,                         // retry on transient failures (default)
  tokenBudget: 4000,                  // compress to fit this limit
  hooks: new MyHooks(),               // pre/post compression hooks
});

Or use environment variables:

  • HEADROOM_BASE_URL — proxy URL
  • HEADROOM_API_KEY — optional API key for authenticated endpoints

Utilities

// Case conversion for proxy communication
import { deepCamelCase, deepSnakeCase } from 'headroom-ai';

const tsObj = deepCamelCase({ tokens_before: 100 }); // { tokensBefore: 100 }
const pyObj = deepSnakeCase({ tokensBefore: 100 });   // { tokens_before: 100 }

// SSE stream parsing
import { parseSSE, collectStream } from 'headroom-ai';

// Hook helpers
import { extractUserQuery, countTurns, extractToolCalls } from 'headroom-ai';

License

Apache-2.0