
不只会配 Claude Codefast-jev-compaction 的 NPM 形态如何接入你自己的 Agent 管道【免费下载链接】fast-jev-compactionClaude Code plugin that replaces the compaction summary with Jev decisions: every tool call and result is scored in one fast request, stale ones are dropped or truncated, everything kept stays verbatim.项目地址: https://gitcode.com/gh_mirrors/fa/fast-jev-compaction2026 年 9 月中旬TypeSafe AI 发布了一个不生成文本的决策模型 Jev它不写总结、不编代码只对给定的问题输出结构化的概率判断却在 Hacker News 上一天冲到 1863 分、引来近 500 条评论。社区随即涌出一批 Jev 驱动项目其中被讨论最多、也最工程化的就是本文的主角 fast-jev-compaction——一个把 LLM 有损摘要替换成 Jev 逐条决策的上下文压缩组件。但外界对它的认知大多停留在Claude Code 插件这一层。事实上这个仓库天生就是双形态hooks/目录里的插件适配层只是它的第一种消费方式而src/目录编译出的fast-jev-compactionNPM 包是面向任意自建 Agent 的独立库。本文基于仓库源码拆开 NPM 形态的 API 设计、最小接入范式、密钥与 token 预算的配合逻辑以及生产环境必须处理的并发、分批与失败降级问题。一、NPM 形态的 API 设计输入输出与调用范式先看包的入口声明package.json纯 ESMtype: module、Node 18、exports只暴露.一个入口类型声明与运行时实现一并发布。src/index.ts把六个模块全部 re-export所以调用方拿到的是一套完整且分层的 API。输入模型是整个设计的关键。库的核心类型Message定义在 src/types.tsinterface Message { role: user | assistant; text: string; toolUses: ToolUse[]; toolResults?: ToolResult[]; }注释里写明这是 Claude CodeSessionMessage的子集。也就是说任何把会话建模为role 文本 工具调用 工具结果的 Agent 框架其 transcript 都可以原样传入不需要任何适配转换。ToolUse与ToolResult之间通过tool_use_id配对——这正是压缩算法运转的最小单元。调用范式分两层由浅入深compactMessages(messages, options)一行调用内部自动构造一个JevClient负责鉴权、HTTP 请求与响应解析src/messages.ts。适合大多数接入场景。compact(messages, asker, options)把怎么问 Jev抽象成JevAsker接口——只有一个ask(state, questions): PromiseJevResponse方法src/types.ts。你可以传入自己封装的传输层、代理、缓存或测试桩。再往下一层src/request.ts 导出buildJevRequest与parseJevResponse前者把(apiKey, model, state, questions)组装成一个标准POST请求默认打到https://api.typesafe.ai/v1/systemone后者做响应校验。这意味着整个请求构造与响应解析过程是可审计、可替换的纯函数——如果你想自己控制签名、加日志或改走内部网关不用碰压缩逻辑本身。输出侧同样分层compact返回CompactResult包含三个部分——messages压缩后的 transcript、decisions每个候选调用的判定明细、stats压缩前后的消息/字符数、按原因归类的决策计数、state 估算 token 数、拟合阶段、请求数、耗时毫秒。配套的reductionRatio(result)直接给出字符缩减率方便调用方做值不值得的判断。这套分层最直观的价值是压缩引擎与 Jev 的通信方式完全解耦。单元测试就是这么做的——tests/fast-jev-compaction.test.ts 里塞了一个返回固定概率的 fakeJevAsker整条压缩流水线配对、拟合、分批、决策、重建在零网络、零密钥的情况下全部可测。二、最小集成示例把压缩接进自建 Agent 的会话循环仓库自带的 examples/demo.ts 演示了一个完整场景一个修复 parser 测试的长会话包含Glob、Read、Bash、Edit等多次工具调用然后调用compactMessages并打印逐条决策与统计。下面是把它抽象成自建 Agent 会话循环的最小范式import { compactMessages, reductionRatio, type Message } from fast-jev-compaction; // 你的 Agent 维护的会话历史结构上与 SessionMessage 同构 let transcript: Message[] [/* 初始消息与工具调用 … */]; // 在每轮 turn 结束、或上下文占用达到预算时触发 async function maybeCompact(usagePercent: number): Promisevoid { if (usagePercent 60) return; // 未到预算线跳过 const result await compactMessages(transcript, { preserveRecentMessages: 6, // 最近 6 条永不触碰 keepThreshold: 0.5, // 保留概率阈值 }); // 收益不足默认 0.25 缩减率时保留原 transcript if (reductionRatio(result) 0.25) return; transcript result.messages; console.log(result.stats); // requests / stateTokens / kept / resultsDropped … }几点语义值得注意它们来自 src/compact.ts 的compact()实现压缩只发生在有候选时。collectToolCalls先按tool_use_id把调用与结果配对再剔除钉住项如果没有非钉住候选整个流程零 Jev 请求stats.requests 0消息原样返回。短会话或纯文本对话不会白白产生网络开销。未触碰的消息是原对象。applyDecisions对没被删改的消息直接 push 原引用——这与插件层哪些消息还保留着引擎句柄的语义一致也意味着在你自己的管道里未变消息的引用相等性可以安全依赖。文本永不重写。被判定过时的只有工具调用与其结果要么整组删除drop_call要么保留调用、把结果截断成头部truncateHeadChars字符 一行说明drop_result。用户与助手的原文、顺序、完整性全部保持不变——这是整个方案与 LLM 摘要最本质的分野。如果你的传输层不是标准fetch换成compact JevAsker即可其余参数完全一致import { compact, buildJevRequest, parseJevResponse, type JevAsker } from fast-jev-compaction; const asker: JevAsker { async ask(state, questions) { const req buildJevRequest({ apiKey: myKey, model: jev-latest }, state, questions); const res await myCustomTransport(req.url, { method: req.method, headers: req.headers, body: req.body }); return parseJevResponse(res.status, res.ok, await res.text()); }, }; const result await compact(messages, asker, { maxStateTokens: 25_000 });三、密钥、token 预算与状态拟合的配合密钥解析链。库层默认从process.env.TYPESAFE_API_KEY读取密钥src/client.tsJevClient构造时可用apiKey覆盖两者皆缺时ask()直接抛TYPESAFE_API_KEY is not configured。插件层hooks/fast-jev.ts的解析链更长插件配置apiKey→$.env.get(TYPESAFE_API_KEY)→settings里的环境变量。对自建管道的启示很直接把密钥放在环境变量或密钥管理系统里永远不要写进源码——库的设计就是为此服务的。token 预算没有 tokenizer 的估算器。Jev 单请求上限约 32k token而库的默认maxStateTokens是 25k、maxRequestTokens是 30k都在限制之内。但如何在不引入 tokenizer 依赖的前提下估算src/state.ts 的estimateTokens给出一个精心校准的启发式英文单词按每 6 个字母 1 token 计、数字每 2 位 0.5 token、其余符号每个 0.9 token。注释里说明了校准依据对真实 transcript 它会略高于Jev 上报的用量 2–18%而朴素的字符数 ÷ 常数估算在 JSON 密集的 state 上会低估最多 40%。换言之这套估算刻意宁高勿低避免请求悄悄越限。状态拟合分级裁剪链。每次压缩Jev 看到的state是整段对话从旧到新其中每个工具结果被替换成一行摘要注记如ok, 4213 chars (omitted)工具输入与文本原文则原样携带src/state.ts 的fitState。装不下maxStateTokens时按固定顺序逐级收缩每级只在前一级不够时才生效工具输入从 1000 字符截到 200、再到 60长文本按头 400 尾 150缩写最旧优先、钉住消息最后旧的非钉住消息折叠成[… N chars omitted …]注记旧工具调用压缩成单行t12 Read file_pathsrc/a.ts → ok 480ch无调用的旧消息直接剔除连续的纯调用消息合并为一条。全部用尽仍超限才抛错history too large for Jev。这个分级设计让调用方从stats.stateStage一眼看出 state 处于哪一档方便定位为什么这次压缩的信息量下降。goal 字段。state 里除了context与history还有一个goal默认取最近 3 条用户消息src/state.ts 的goalFromMessages也可以通过选项显式传入。Jev 在回答这条调用还要不要留时能看到当前任务的描述——这是让决策与任务意图对齐的关键输入自建管道里务必检查默认值是否符合你的场景。四、生产注意点并发、分批与失败降级分批与并发。每个候选调用对应两个noul问题这个调用还要不要留这个结果原文还要不要留src/compact.ts 的batchCalls按maxRequestTokens - stateTokens - 20的预算把问题切批每批请求都重发完整的 state然后用Promise.all并发发出、合并答案。两点成本特征要在设计管道时想清楚stats.requests就是批次数量。当历史接近 state 上限时一批只能容纳少量问题请求数会随调用数线性增长——一请求一问是可能出现的极端形态好在所有请求共享同一份 state并发度高、延迟基本由最慢一批决定整体仍是毫秒级。失败即抛错降级归调用方。compact/compactMessages的失败面很明确密钥缺失、HTTP 非 2xx、响应畸形、答案缺失或非有限数、历史装不进 state——全部以异常形式抛出由调用方决定回退策略。这比静默降级更可控。插件层hooks/fast-jev.ts给出了一个值得抄的降级范式压缩收益低于minReductionRatio默认 0.25时放弃本次替换回退到 Claude Code 内置摘要任何异常同样回退并在 toast/日志中写明原因turn.complete钩子在上下文占用达到compactAtPercent默认 60%时触发压缩并用一个compacting布尔做重入保护防止并发压缩互相踩踏。对应到自建管道就是三件事先算reductionRatio再决定是否替换、catch 所有异常并保留原 transcript、用标志位或互斥锁防止同一份 transcript 被并发压缩。阈值调参。行为旋钮集中在keepThreshold保留概率门槛默认 0.5、preserveRecentMessages钉住最近消息数默认 6、truncateHeadChars被截结果的保留头部字符数默认 300。判定逻辑decideCall是严格的三段式结果概率达阈则整组保留否则调用概率达阈则留调用、截结果再否则整组删除。注意 README.md 的告诫概率不是删除安全性的证明——被删内容若后续还需要助手永远可以重跑工具或重读文件这是该方案在工程上的兜底语义。边界与取舍。库只以工具调用/结果为候选用户与助手文本在输出中永远不删不改它们只在 Jev 看到的 state 里被缩写token 数是字符级的估算而非精确分词state 重复发送带来成本。这些限制都写在了 README.md 的 Limitations 一节接入前值得对照评估。收束插件只是入口库才是通用件从架构上看Claude Code 插件层hooks/fast-jev.ts总共只做了四件事读配置、找密钥、把session.compact的 transcript 喂给src/的库、把结果映射回会话消息并处理降级。真正承载配对、拟合、分批、决策、重建全部算法的是 NPM 包本身。这意味着无论你的 Agent 跑在哪种框架里——只要会话能被建模为Message[]你就能用同一套逐条决策、只删不改、概率阈值的压缩语义替代掉那些有损的 LLM 摘要。Jev 的价值在于把压缩从重新表述变成选择与删除而 fast-jev-compaction 的价值在于让这种语义变成一行compactMessages()就能接进任何管道的能力。【免费下载链接】fast-jev-compactionClaude Code plugin that replaces the compaction summary with Jev decisions: every tool call and result is scored in one fast request, stale ones are dropped or truncated, everything kept stays verbatim.项目地址: https://gitcode.com/gh_mirrors/fa/fast-jev-compaction创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考