npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pi-distill

v1.7.0

Published

Pi tool-output distillation with file-first configuration

Readme

pi-distill

保留事实,把上下文留给决策。

pi-distill 是一个 Pi 扩展:它不替换工具,也不改变命令的执行方式,只在工具已经返回真实结果之后,帮助 Agent 决定哪些内容值得进入下一轮上下文。

解决什么问题

编码 Agent 通常只需要命令、搜索或文件读取结果中的关键信息。把大段日志、生成文件或搜索结果完整塞入下一轮,会增加上下文消耗,也容易让有效信号被噪声淹没。pi-distill 在不替换 Pi 内置工具的前提下,增加一层结果级提炼。

实际上下文节省效果

构建日志、diff 输出和测试报告经常包含重复状态行、未变化上下文、堆栈噪声,以及下一步决策并不需要的细节。这些内容通常很适合高比例压缩。下面这张真实 Pi 会话截图中,结果从 51,215 个字符压缩到 240 个字符:213.40 倍压缩,输出字符减少 99.5%

pi-distill 上下文节省示例

截图统计的是字符减少比例,不是 tokenizer 得出的精确 token 统计。实际使用时通常会带来同量级的上下文 token 节省,但精确数值取决于语言、内容和模型 tokenizer。对于适合压缩的冗长输出,90% 以上是已经观察到的效果,但不是每个命令的保证;需要完整输出时请使用 RAW

| 场景 | 常见噪声 | 提炼结果保留 | | --- | --- | --- | | 构建 / 编译 | 重复进度、警告和未变化的环境信息 | 成功/失败、首个可行动错误、受影响文件和后续步骤 | | Diff 检查 | 大量未变化 hunk 和格式化噪声 | 变更文件、相关 hunk 和评审所需事实 | | 测试 | 单测逐条输出、snapshot 和框架模板 | 总数、失败用例、关键断言和有效诊断 |

Prompt 语言

提炼 prompt 会严格跟随 /config:language 当前选择的语言。持久化语言发生变化后,下一次工具调用会读取新设置,即使语言命令和 pi-distill 来自不同的包实例也可以同步。PI_EXTENSIONS_LOCALE 仍然是显式的环境变量覆盖项。原始用户消息只作为语言上下文传入,不能覆盖已选择的语言。

工作方式

  • 通过 Pi 原生的 tool_call / tool_result 事件监听 bashreadgrepfind
  • 以工具的 outputRequest 作为是否提炼、如何提炼的依据。
  • 当提示词严格只有 RAW 时,视为明确要求返回原始输出。
  • 默认使用当前会话模型,也可以配置独立的 provider/model
  • 在工具结果 details 中保留状态、字符数、压缩比、耗时和异常等诊断信息。
  • 超长输出不再由 pi-distill 写文件或截断,统一交由 Pi 自身的输出限制机制处理。
  • 当前 Pi 展示中间件可用时显示紧凑审计卡片,否则使用自己的 fallback renderer。展示协议由公共运行库 pi-extensions-tool-display 提供。

它不会注册第二个 bashreadgrepfind 工具。

安装

pi install npm:pi-distill

包清单会把共享依赖 pi-extensions-i18npi-extensions-tool-display 作为扩展入口加载,不需要额外安装这些包。安装 pi-distill 后即可使用 /config:language

安装后重新加载 Pi:

/reload

交互式配置命令:

/config:distill

核心思想

我们不是想让 Agent 少看信息,而是避免它为了找一句结论,被迫把几千行日志一起带进上下文。

工具执行层需要保留完整事实;Agent 消费层需要控制上下文成本。pi-distill 在两者之间增加一个可选的结果处理层:

  • 工具负责执行并返回事实;
  • Agent 通过 outputRequest 表达自己关心什么;
  • 扩展读取真实输出后,再决定是否调用提炼模型;
  • 模型只压缩消费路径,不改变原工具的业务语义;
  • 诊断信息记录这次处理是否真的节省了上下文。

因此,提炼不是“把所有输出都交给模型总结”,而是一份明确的工具契约:需要什么就提取什么,需要完整内容就保留原文。

为什么需要它

构建、测试和 diff 往往会返回大量重复状态、未变化上下文、框架模板和堆栈噪声。Agent 可能只需要失败原因、变更文件或最终状态,却被迫先消费整段输出。

直接截断会丢失关键事实;新增一个总结工具会增加调用链和决策负担;等 Agent 看完再总结又已经消耗了上下文。pi-distill 选择在结果进入后续推理前处理它,同时保留明确的原文模式和失败回退。

实际效果

下面是一段真实 Pi 会话中的输出:原始结果从 51,215 个字符提炼到 240 个字符,压缩 213.40 倍,输出字符减少 99.5%

pi-distill 上下文节省示例

这张图统计的是字符减少比例,不是 tokenizer 得出的精确 token 数。实际 token 节省会受到语言、内容和模型 tokenizer 影响;对于适合压缩的构建日志、diff 和测试输出,90% 甚至更高的节省比例是已经观察到的结果,但不是每个命令的保证。

| 场景 | 原始输出中的典型噪声 | 提炼后优先保留 | | --- | --- | --- | | 构建 / 编译 | 重复进度、环境信息、重复警告 | 成功/失败、首个可行动错误、受影响文件、后续步骤 | | Diff 检查 | 大量未变化 hunk、格式化噪声 | 变更文件、相关 hunk、评审所需事实 | | 测试 | 逐条单测输出、snapshot、框架模板 | 总数、失败用例、关键断言、有效诊断 |

节省比例不是唯一指标。扩展还记录提炼耗时、原始字符数、结果字符数、压缩比和异常;如果总结没有带来真实收益,会暴露 ineffective-compression,而不是静默假装优化成功。

工作原理

一次工具调用的处理链路如下:

Agent 提出处理目标
        ↓ 通过 outputRequest 传给工具
工具执行真实操作,返回 stdout / stderr / 文件内容 / 多媒体结果
        ↓
pi-distill 根据真实结果和配置决定:原样返回,或调用模型提炼
        ↓
Agent 消费更适合当前决策的结果,并获得可审计的处理诊断
  1. 扩展在会话启动时为所有已启用、参数 schema 为 object 的工具增加必填的 outputRequest 参数;editwrite 默认关闭,其他未配置工具默认开启。不写死 bashreadgrepfind
  2. tool_call 事件捕获这个参数,并在交给底层工具前移除它,因此原工具不会收到扩展专用字段。
  3. tool_result 事件拿到真实输出后再做判断,不依赖 Agent 对输出长度的预测。
  4. 每次工具调用都必须包含非空的 outputRequest;严格的 RAW 表示明确要求原文;其他非空 prompt 才允许进入提炼流程。
  5. OpenAI-compatible Completions 提炼请求会通过 response_format: { "type": "json_object" } 启用原生 JSON 模式;OpenAI Responses-compatible 请求使用等价的 text.format。单次提炼超时后按照 timeoutRetryCount 重试,其他模型调用异常按照 errorRetryCount 重试(两者默认都重试 1 次);如果模型已经返回文本,但只是 JSON 语法或响应结构校验失败,扩展会把坏响应和校验错误交给一次 JSON-only 修复 prompt,不会再次发送工具输出,也不会重新总结;修复失败、没有可用模型或结果收益过低时,扩展保留原始事实,并通过 details 和审计卡片暴露状态;模型用 Markdown 的 JSON 代码围栏(如 json … )包裹响应时也会兼容解析。

输出处理契约

| outputRequest | 行为 | 适用场景 | | --- | --- | --- | | 未提供 | 工具调用无效;Pi 会在底层工具执行前拒绝该调用 | 不要省略;未明确要求压缩时使用 RAW | | 严格为 RAW(大小写不敏感) | 不调用提炼模型,保留完整原始文本;超长时由 Pi 自身的输出限制机制处理 | 逐字核对、复制内容、需要完整日志时 | | 任意非空且非 RAW | 输出达到阈值后调用模型,超时与其他异常分别使用独立重试次数,具体保留内容由 prompt 决定 | “只保留错误、警告和最终状态”等场景 | | 包含图片、音频或其他非文本内容 | 原样保留,不发送给提炼模型,不做文本长度截断 | 图片读取、二进制结果、混合文本与图片结果 |

RAW 是确定性的完整输出信号。提炼 prompt 会要求总结模型在用户明确要求“不遗漏地完整提取”时直接返回 RAW,尤其适用于语法、参数、SQL、API 调用或其他需要复制的精确文本。工具调用方可以控制参数时,直接传 RAW 仍然是首选方式。

Prompt 语言

提炼 prompt 完全跟随 /config:language 当前选择的语言:

  • 切换语言后,下一次工具调用读取新的持久化语言设置;
  • 即使 /config:languagepi-distill 来自不同的包实例,也通过共享 locale 设置同步;
  • PI_EXTENSIONS_LOCALE 可以作为显式环境变量覆盖;
  • 原始用户消息只作为任务上下文传入,不会把中文用户消息误判成中文 prompt。

覆盖范围与边界

  • 自动处理所有当前已启用且参数 schema 为 object 的工具;能否注入 outputRequest 由工具 schema 决定,不维护固定工具名单。
  • 不注册替代工具,不改变原工具的执行语义,也不要求额外安装独立的 pi-tool-display 宿主包。
  • 文本提炼是有损操作;完整性要求应使用 RAW
  • 非文本结果是完整性边界:图片、音频、二进制和混合 content 不进入文本提炼链路。
  • 超长输出不再由 pi-distill 写临时文件或截断,统一交由 Pi 自身的输出限制机制处理,避免上下文无限膨胀。
  • 当前会话没有模型时,提炼会失败并保留原始结果,不阻止 Pi 启动。

配置

默认配置路径:

~/.pi/agent/extensions/pi-distill/config.json

可以从 config.example.json 开始:

{
  "enabled": true,
  "model": "",
  "minChars": 200,
  "maxChars": 100000,
  "maxOutputChars": 10000,
  "timeoutSeconds": 10,
  "timeoutRetryCount": 1,
  "errorRetryCount": 1,
  "missedCompressionRatio": 10,
  "summarizeErrors": true,
  "tools": {},
  "render": {
    "enabled": true,
    "showPrompt": true,
    "showResult": true
  }
}

配置文件字段优先于环境变量。未声明的字段依次回退到 PI_DISTILL_*、旧版 PI_BASH_SUMMARY_* 变量和默认值。

| 配置项 | 含义 | | --- | --- | | model | 可选的 provider/model;为空时使用当前 Pi 会话模型。 | | minChars | 达到此输出长度后才请求提炼。 | | maxChars | 提炼结果超过此字符数时写入临时文件。 | | maxOutputChars | 最终返回给 Agent 的文本上限。超出后写入临时文件,只返回文件指针。 | | timeoutSeconds | 每次提炼模型尝试的最长等待时间。 | | timeoutRetryCount | 超时后的额外重试次数。默认 1;设为 0 时不重试超时。 | | errorRetryCount | 非超时异常后的额外重试次数。默认 1;设为 0 时不重试其他异常。 | | missedCompressionRatio | 没有提供摘要 prompt 时,用于长输出诊断的倍数阈值。 | | summarizeErrors | 工具返回错误且达到 minChars 时,是否仍发送给提炼模型。 | | tools.<name>.enabled | 按工具开启或关闭 outputRequest 注入和结果提炼。editwrite 默认关闭,其他未配置工具默认开启,也可以通过 /config:distill 修改。 |

/pi-distill 仍作为兼容别名保留。 | render.* | 控制审计卡片、prompt 预览和结果预览。 |

Session 统计

使用 /distill:stats 查看当前 Pi 会话的提炼统计。统计只保存在内存中,在会话开始时重置,不保存原始工具输出。

统计包括工具结果数量、成功/失败/回退次数、模型尝试次数、原始与摘要字符数、压缩比、估算的原文/摘要 Token(启发式:CJK 字符约每字 1 token,其余文本约 4 字符 1 token)、预计节省 Token、提炼实际消耗的 input/output/cache/total Token 和成本。数量达到 1,000 或 1,000,000 时分别使用 km 紧凑显示;耗时会根据数值显示为 mssmin。原文/摘要 Token 是估算值;provider 未返回 usage 时,提炼消耗 Token 或成本字段显示为不可用。

主要环境变量包括 PI_DISTILL_MODELPI_DISTILL_MIN_CHARSPI_DISTILL_MAX_CHARSPI_DISTILL_MAX_OUTPUT_CHARSPI_DISTILL_TIMEOUT_SECONDSPI_DISTILL_TIMEOUT_RETRY_COUNTPI_DISTILL_ERROR_RETRY_COUNTPI_DISTILL_MISSED_COMPRESSION_RATIOPI_DISTILL_SUMMARIZE_ERRORS

要求

  • Node.js 22 或更高版本。
  • 当前 Pi 会话需要有可用模型,除非 model 指向一个已配置且可用的模型。

许可证

MIT