首页
/ Headroom TypeScript SDK 实战:headroom-ai 在 Node.js 中压缩 LLM 上下文,跨 OpenAI / Anthropic / Vercel AI / Gemini 的接入方式

Headroom TypeScript SDK 实战:headroom-ai 在 Node.js 中压缩 LLM 上下文,跨 OpenAI / Anthropic / Vercel AI / Gemini 的接入方式

2026-09-04 17:28:37作者:吴年前Myrtle

本文以 sdk/typescript 目录下的 TypeScript SDK(npm 包 headroom-ai)为主线,完整讲解它的安装与快速上手、compress() 的格式自动检测与七步压缩管线、四大框架适配器(OpenAI / Anthropic / Vercel AI SDK / Gemini)的拦截实现、HeadroomClient 的透传与 CCR 检索、dry-run 模拟、压缩 Hooks、多智能体 SharedContext、可观测性与配置类型。读完后,你可以在不改动业务调用逻辑的前提下,让任何 JavaScript/TypeScript LLM 应用在请求发出前先经过 Headroom 代理压缩上下文,并通过源码路径追踪每个行为的实际实现。

一、定位与架构:客户端只做转换与路由,压缩在代理侧完成

Headroom 项目的核心能力是“在工具输出、日志、文件、RAG 分块到达 LLM 之前压缩它们”,提供 Library、Proxy、MCP Server 三种形态。TypeScript SDK 是其中的客户端库:它本身不做压缩算法,而是把消息转换为 OpenAI 格式后发给本地运行的 Headroom 代理(默认 http://localhost:8787,由 headroom proxy 启动),再拿回同格式的压缩结果。

从源码结构看,整个 SDK 的职责划分非常清晰(见 入口导出):

  • compress() / HeadroomClient / simulate():核心压缩 API(compress.tsclient.tssimulate.ts);
  • adapters/:四个框架适配器的 withHeadroom 包装(openai.tsanthropic.tsvercel-ai.tsgemini.ts);
  • utils/format.ts:四种消息格式的结构化检测与互转;
  • utils/case.ts / utils/stream.ts:snake_case ↔ camelCase 深度转换、SSE 流解析;
  • hooks.ts / shared-context.ts / errors.ts:压缩钩子、多智能体共享上下文、错误层级。

package.jsonexports 字段定义了五个子路径:根入口 headroom-ai,以及 headroom-ai/vercel-aiheadroom-ai/openaiheadroom-ai/anthropicheadroom-ai/gemini 四个适配器入口,同时声明 node >= 18,并对 openai@anthropic-ai/sdkai@ai-sdk/provider 使用 optional peerDependencies——即只需要安装你实际用到的 SDK。

安装

npm install headroom-ai

前提条件:需要一个正在运行的 Headroom 代理进程(headroom proxy)。SDK 所有压缩能力都依赖该代理;若代理不可达,默认会触发 fallback 行为(见第四节)。

快速开始

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,
});

CompressResult 的完整字段在 types.ts 中定义:messages(与输入同格式的压缩后消息)、tokensBeforetokensAftertokensSavedcompressionRatiotransformsApplied(实际应用的变换列表)、ccrHashes(CCR 存储句柄)、compressed(是否真正发生压缩)。

compress() 的七步管线

compress() 接受任意格式消息,其完整流程在 compress.ts 中一目了然,值得逐步拆解,因为它决定了 SDK “同格式进、同格式出”的语义:

  1. preCompress 钩子:若传入了 hooks,先调用 hooks.preCompress(messages, ctx),允许在压缩前改写消息。钩子上下文 CompressContext 自动携带 modeluserQuery(最后一条 user 消息文本)、turnNumber(user 消息计数)、toolCalls(从 tool_callstool_usetool-call 三种结构中抽取的工具名),见 hooks.ts 与三个抽取函数;
  2. 格式检测detectFormat() 基于结构化标记识别输入是 OpenAI / Anthropic / Vercel / Gemini 哪种格式(第十一节详述);
  3. 统一转 OpenAI 格式:OpenAI 格式是代理的“通用语”,toOpenAI() 对四种格式分别处理;
  4. 计算 biaseshooks.computeBiases() 可返回“消息下标 → 保留偏置”的映射(大于 1 表示更多保留,小于 1 表示更激进压缩);
  5. 代理压缩:复用或新建 HeadroomClient 调用 POST /v1/compress
  6. 转回原格式fromOpenAI(result.messages, inputFormat) 把压缩结果还原为输入格式;
  7. postCompress 钩子:只读事件通知,携带 token 统计与变换列表,不能修改结果。

这个管线保证了:你传入 Anthropic 消息数组,拿回的 result.messages 仍是 Anthropic 格式,可以直接喂给 @anthropic-ai/sdk;传入 Vercel AI SDK 的 ModelMessage[],拿回的仍是 Vercel 格式。

二、框架适配器:withHeadroom 一行接入四种 SDK

四个适配器共同的设计模式是:用 ES Proxy 只拦截产生 LLM 请求的那一个方法,其余方法原样透传。例如 OpenAI 适配器只拦截 client.chat.completions.create,embeddings、images、audio 等全部不受影响(openai.ts)。

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 });

withHeadroom(model)wrapLanguageModel + headroomMiddleware 的便捷封装:运行时动态 require("ai") 包,未安装会抛出提示安装 ai 的明确错误(vercel-ai.ts)。若需要更细粒度的控制,可以直接使用中间件:

import { headroomMiddleware } from 'headroom-ai/vercel-ai';
import { wrapLanguageModel } from 'ai';

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

headroomMiddleware 返回的 transformParams 会在每次调用前把 Vercel prompt 转成 OpenAI 格式压缩、再转回 Vercel 格式;未压缩成功时原样放行。它对 AI SDK v6 与更早版本都有兼容处理(input/argsoutput/result 字段差异),见 format.ts 中的 vercelToOpenAI

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,
});

Anthropic 适配器的格式转换细节最有代表性(anthropic.ts):user 消息中的 tool_result 块被拆成独立的 OpenAI tool 消息(tool_use_idtool_call_id);assistant 消息中的 tool_use 块转成 OpenAI tool_callsinput 序列化进 function.arguments);反向转换时,OpenAI tool 消息再变回 Anthropic 的 user 消息 + tool_result 块。若压缩未发生(result.compressed === false,例如代理下线走了 fallback),则直接发送原始消息,保证格式零损耗。

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,
});

Gemini 适配器同时拦截 generateContentgenerateContentStreamgemini.ts)。Gemini 的 parts/functionCall/functionResponserole: "model" 标记是格式检测的独有特征(见第十一节)。

适配器共有的行为

每个适配器在调用 compress() 时都会附带一个 stack 标识(如 adapter_ts_openaiadapter_ts_anthropicadapter_ts_vercel_aiadapter_ts_gemini),该值作为 X-Headroom-Stack 头随每个请求发出(client.ts),用于在代理侧按集成来源归因统计。所有适配器也完整继承 CompressOptionsbaseUrlapiKeytimeoutfallbackretriestokenBudgethooksstack,定义于 types.ts)。

仓库 sdk/typescript/examples/ 目录提供了对应示例:with-headroom-vercel.tsopenai-anthropic-adapters.tstool-calling-agent.ts 等,可直接参照。

三、HeadroomClient:直连代理的完整 HTTP 客户端

HeadroomClient 提供对代理 OpenAI / Anthropic 透传端点以及 metrics、CCR、可观测性端点的直接访问:

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 },
  },
});

客户端默认值在 client.ts 中定义:baseUrl 缺省 http://localhost:8787(也读 HEADROOM_BASE_URL),timeout 30 秒,retries 1,fallback true。

透传式调用:Chat Completions(OpenAI 风格)

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

从源码看(client.ts),headroomModeheadroom* 参数会被从请求体中剥离,headroomMode 通过 x-headroom-mode 请求头传递(取值为 audit / optimize / simulate 之一,见 types/config.ts);providerApiKey 则以 Authorization: Bearer 头携带,缺省时回退读 OPENAI_API_KEY 环境变量。请求打到代理的 POST /v1/chat/completions,代理完成压缩后再转发到真实上游。stream: true 时返回值是 parseSSE 解析后的异步流。此外还支持 headroomCachePrefixTokensheadroomOutputBufferTokensheadroomKeepTurnsheadroomToolProfiles 四个细粒度参数(HeadroomParams)。

透传式调用:Messages(Anthropic 风格)

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

对应 POST /v1/messages,自动附加 anthropic-version: 2023-06-01 头;providerApiKeyx-api-key 头,缺省回退 ANTHROPIC_API_KEY;未显式给 max_tokens 时默认 1024(client.ts)。client.messages.stream(...)client.chat.completions.simulate(...) 也已内置。

直接压缩

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

compress()POST /v1/compress。重试语义在源码中有明确定义(client.ts):

  • 401 认证错误不重试,直接抛 HeadroomAuthError
  • 状态码小于 500 的压缩错误视为客户端错误,不重试;
  • 其余(连接失败、5xx)按 retries 次数重试;
  • 全部失败后,若 fallback: true(默认),返回 compressed: false 的原始消息结果——代理宕机时业务请求不会中断,只是不省 token;若 fallback: false,则抛出对应错误。

tokenBudget 会以 token_budget 字段发给代理,用于“压缩到适配该 token 上限”的场景(上下文压缩/compaction)。

四、Simulation:不花一次 LLM 调用的 dry-run

在决定是否开启压缩、或调整配置前,可以先看“如果压缩会发生什么”:

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);

实现上,simulate()simulate.ts)并不是单独的端点,而是给 POST /v1/compress 注入 config: { default_mode: "simulate", generate_diff_artifact: true }——即以 simulate 模式执行整条压缩管线并生成 diff 工件,但不转发任何 LLM 请求。client.chat.completions.simulate({ model, messages })client.messages.simulate(...) 是等价的客户端方法。返回的 SimulationResult(含 wasteSignals 浪费信号、transformscachePrefixMetrics 等,定义见 types/models.ts)可以直接用于上线前的收益评估与回归对比。

五、Compression Hooks:与 Python 版对齐的压缩定制点

Hooks 用于在压缩前后注入自定义逻辑,与 Python SDK 的 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() });

hooks.ts 的基类实现看,三个方法都提供了安全的默认实现(preCompress 原样返回、computeBiases 返回空对象、postCompress 空操作),因此你可以只覆盖关心的一个方法。两个接口的语义边界值得注意:

  • CompressEvent(压缩后事件,hooks.ts)携带 tokensBefore/AftertokensSavedcompressionRatiotransformsAppliedccrHashesmodeluserQueryprovider,是只读观测点
  • CompressContext(压缩前上下文)携带 modeluserQueryturnNumbertoolCallsprovider,其中 userQuery/turnNumber/toolCalls 由 SDK 自动从任意格式的消息中抽取,方便你在 computeBiases 里按轮次或工具调用写策略。

配套的 Hook 助手函数 extractUserQuery(取最后一条 user 文本)、countTurns(user 消息计数)、extractToolCalls(跨三种格式抽取工具名)也都从包根导出,可独立使用。完整示例见 hooks-custom-compression.ts,行为验证见 hooks.test.ts

六、SharedContext:多智能体间的压缩式上下文共享

在多 Agent 系统中,Agent A 的长输出常常要交给 Agent B。SharedContext 提供“存入即压缩、读取即省 token”的本地缓存,与 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
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`);

shared-context.ts 的实现看,几个默认值和容错策略值得了解:

  • 构造函数参数 model 缺省 claude-sonnet-4-5-20250929ttl 缺省 3600 秒,maxEntries 缺省 100(shared-context.ts);
  • put() 把内容包成单条 user 消息调代理压缩,条目中同时保留 originalcompressedoriginalTokens/compressedTokens、所用变换列表与 savingsPercent代理不可用时降级为存原文(token 数按 length/4 粗估),不会让 Agent 流程失败;
  • 过期策略双重保障:每次 get/keys/stats 都会触发 evictExpired(),且 put 前若已满 maxEntries 会淘汰最老条目(Map 插入序,shared-context.ts);
  • 除 README 示例外,还有 getEntry()(取完整元数据)与 clear() 方法,stats() 返回 entriestotalOriginalTokenstotalCompressedTokenstotalTokensSavedsavingsPercent

多 Agent 场景示例见 shared-context-multi-agent.ts

七、CCR Retrieve:压缩后按需取回原文

CCR(Compress-Cache-Retrieve)是 Headroom 的关键机制:大块内容被压缩进上下文的同时,原文被存入代理侧的 CCR 存储并返回哈希句柄;当 LLM 需要细节时,通过 headroom_retrieve 工具调用取回原文。SDK 端对应的代码:

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',
});

client.ts 看,三条对应链路是:

  • retrieve(hash, { query })POST /v1/retrieve,带 query 时变为在原文内容中搜索;
  • handleToolCall({ toolCall, provider })POST /v1/retrieve/tool_call,接收 OpenAI 或 Anthropic 两种工具调用结构(发送前自动 deepSnakeCase 转换),供 Agent 循环里解析模型发起的 headroom_retrieve 调用;
  • getCCRStats()GET /v1/retrieve/stats,查看 CCR 存储规模。

HeadroomConfig 中的 ccr 配置块(enabledstoreMaxEntriesstoreTtlSecondsinjectRetrievalMarkerinjectToolinjectSystemInstructionsmarkerTemplate 等,types/config.ts)控制代理侧的标记注入与存储策略。端到端示例见 ccr-retrieve.ts

八、Metrics、Telemetry、Feedback 与 TOIN

SDK 把代理的运维与学习系统也暴露成了方法。Metrics 部分:

// Proxy health
const health = await client.health();
// → { status: 'healthy', version: '...', 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();

实现映射(client.ts):health()validateSetup() 都读 GET /health(后者把 status === "healthy" 映射为 valid 并携带代理配置快照);proxyStats()GET /statsgetMetrics() 实际取 /statsrecent_requests 后在客户端按 model/mode/limit 过滤;clearCache()POST /cache/clearprometheusMetrics()GET /metrics 返回原始 Prometheus 文本。此外还有 statsHistory()memoryUsage()GET /debug/memory)两个 README 未展开的方法。

代理学习系统的访问入口:

// 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);

对应端点:telemetry 组提供 getStats / export / import / getTools / getTool(signatureHash)/v1/telemetry*);feedback.getHints(toolName) 返回按工具名学习的压缩提示(maxItemsskipCompressionpreserveFields 等),这正是 SmartCrusherConfig.useFeedbackHints 在代理侧消费的数据;toin 组提供 getStats / getPatterns(limit) / getPattern(hashPrefix)/v1/toin/*),返回工具输出智能网络的统计与已学习模式。所有返回值都经过 deepCamelCase 转换,代理的 snake_case 字段在 TS 侧统一呈现为 camelCase。

九、配置类型、环境变量与错误层级

配置类型

HeadroomConfig 是 Python headroom.config 各 dataclass 的 TypeScript 全量镜像(types/config.ts),字段全部可选,省略时由代理用默认值:

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 });

顶层除 defaultModeaudit / optimize / simulate)与 modelContextLimits 外,还有若干 README 示例未展示的配置块:toolCrusher(按 token 阈值压缩工具输出的数组/字符串/深度,含 preserveKeys 与按工具配置的 toolProfiles)、cacheAligner(动态内容检测:regex/NER/semantic 分级、熵阈值、空白归一化等)、rollingWindowprefixFreeze(前缀冻结的缓存保护)、readLifecycle(陈旧/被取代读文件的压缩)、contentRouterEnabledgenerateDiffArtifactSmartCrusherConfigrelevance.tier 支持 bm25 / embedding / hybrid 三档相关性评分,anchor 子配置控制保留槽位与前后权重。完整的 HeadroomModeRelevanceTierContentType(json/code/logs/text/html/diff/search/unknown)、BlockKind 等类型也都从包根导出。

config 传入 HeadroomClient 后,compress() 调用时会以 deepSnakeCase(this.config) 放入请求体的 config 字段(client.ts),simulate() 则将其与 default_mode: "simulate" 合并——即每次压缩都可以携带独立配置覆盖代理默认值

运行配置与环境变量

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
});

等价的环境变量(client.ts 中可见解析优先级:显式参数 > 环境变量 > 默认值):

环境变量 作用
HEADROOM_BASE_URL 代理地址,缺省 http://localhost:8787
HEADROOM_API_KEY 访问代理自身的可选 API key(Authorization: Bearer
OPENAI_API_KEY / ANTHROPIC_API_KEY 透传端点的 provider key 回退来源(providerApiKey 未显式给出时)

注意区分两类密钥:apiKey 用于访问 Headroom 代理本身,providerApiKey 用于代理转发到 OpenAI/Anthropic 时的上游鉴权。

错误层级

SDK 提供与 Python SDK 对齐的完整错误层级(errors.ts):

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);
  }
}

映射规则由 mapProxyError() 决定:HTTP 401 → HeadroomAuthError;代理错误体中的 error.typeconfiguration_error / provider_error / storage_error / tokenization_error / cache_error / validation_error / transform_error 时分别实例化对应类;其余情况包装为携带 statusCodeerrorTypeHeadroomCompressError。网络层失败(fetch 异常、超时)则抛 HeadroomConnectionError

十、格式检测与转换:detectFormat / toOpenAI / fromOpenAI

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

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

compress() 会自动完成这一步——传任意格式、回同格式。检测逻辑(format.ts)不是模糊猜测,而是基于每种格式的独有结构标记:

格式 判定标记
Gemini 消息用 parts 而非 content;或 role === "model"
OpenAI assistant 消息带 tool_calls;或 role: "tool" 且带 tool_call_id
Vercel AI SDK content 部件类型用连字符:tool-call / tool-result
Anthropic content 块类型用下划线:tool_use / tool_result;或 image 块带 source.type
默认 无法识别时按 OpenAI 处理({role, content: string} 本身就是合法 OpenAI)

互转层的几个易错点都做了显式处理:Anthropic tool_result ↔ OpenAI tool 消息(format.ts);Vercel 图片 URL 对象 ↔ image_url;Gemini functionCall/functionResponsetool_call_idgemini_ 前缀占位(format.ts)。测试覆盖见 detect-format.test.tsformat.test.tsformat-integration.test.ts

十一、实用工具函数

// 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';
  • deepCamelCase / deepSnakeCasecase.ts):递归转换嵌套对象与数组的键名,跳过 Date 实例。这是 SDK 与代理之间 snake_case(Python 侧)/ camelCase(TS 侧)边界的统一实现——所有客户端方法返回前都调用 deepCamelCase,所有复杂请求体发出前都调用 deepSnakeCase
  • parseSSE / collectStreamstream.ts):解析代理透传的 SSE 流,client.chat.completions.create({ stream: true })client.messages.stream(...) 的返回即由它产生;
  • Hook 助手三件套:extractUserQuery(任意格式中取最后一条 user 文本,兼容 string 与 content 数组)、countTurns(user 消息计数)、extractToolCalls(同时识别 tool_callstool_usetool-call 三种工具调用形态)。

十二、测试与验证

SDK 自带完整测试套件(vitest),可对照阅读以验证本文各行为结论:client.test.tsclient-expanded.test.ts(客户端与透传端点)、compress.test.ts(compress 管线与格式往返)、simulate.test.ts(dry-run)、hooks.test.tsshared-context.test.tserrors.test.tsconfig.test.tsparity.test.ts(与 Python 版的行为对齐校验),以及四个适配器的 adapters/ 测试目录(含 vercel-ai-e2e.test.ts 端到端用例)。构建与检查脚本定义在 package.jsonnpm run build(tsup 双产物 ESM/CJS)、npm testnpm run typecheck

十三、选型速查

场景 推荐 API
已有 OpenAI / Anthropic / Gemini 客户端,零侵入接入 withHeadroom(client) / withHeadroom(model)(对应子路径导出)
Vercel AI SDK(generateText/streamText 等) withHeadroom(openai(...))wrapLanguageModel + headroomMiddleware
只需要压缩消息数组,不用代理透传 compress(messages, options)
上线前评估压缩收益 / 做回归 simulate(messages, { model })
压缩策略定制(注入系统提示、按消息保留、观测统计) 继承 CompressionHooks
多 Agent 共享长输出 SharedContext
LLM 需要取回被压缩原文 client.retrieve / client.handleToolCall(CCR)
监控与学习系统对接 health / proxyStats / prometheusMetrics / telemetry / feedback / toin

适用前提小结:所有能力都要求 headroom proxyHEADROOM_BASE_URL(默认 http://localhost:8787)可达;Node.js ≥ 18;透传调用需要有效的上游 provider key;在 fallback: true(默认)下,代理故障会被静默降级为不压缩,生产环境建议结合 client.health()validateSetup() 做可用性探测,并留意 result.compressed 标志判断本次请求是否真的被压缩。SDK 源码与示例均在 sdk/typescript 目录,可按上文各节给出的文件路径逐行核对实现细节。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384