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-auto-goal

v0.7.0

Published

Pi stop guard: judges premature agent stops with a second model and continues the task

Readme

pi-auto-goal

Pi 的停止守卫:agent 停下来时,用第二个模型判断这次停止是否属于「擅自早停」,命中就用 system 提示把 agent 赶回去继续干活。

English

它做什么

一个多步任务只做了一半,agent 却改完一个文件、汇报了进度就结束——这在 Pi 里很常见。pi-auto-goal 监听 agent_settled(Pi 确定不会自己继续的时刻),然后用第二个模型只回答一个问题:此刻停下算合理,还是还有活没干完?

当结论是「还有活没干完」且置信度足够高时,扩展会注入一条 system 继续指令,点明缺口并要求 agent 继续(不会伪装成你自己发的一条用户消息)。否则保持安静,本轮正常结束。

安装与使用

pi install npm:pi-auto-goal

安装后执行 /reload;用 /config:auto-goal 改的配置立即生效,手动改配置文件才需要 /reload。

除非 enabled 为 false,每次完全停止都会判定一次,所以一句普通问答也会多花一次判定调用。判定输入包括:

  • 用户请求:当前分支上最后一条真实用户输入。本扩展注入的催促是 custom 角色的消息,不是用户输入,因此连续干预时判定的始终是你最初的请求。
  • 用户回答:agent 用 ask_user_question 问过你时,你当时的回答(会话里存成工具结果而不是用户消息)。它是本轮的用户输入,判定提示词规定它优先于原始请求:你借回答缩小范围、选定方案或要求先停下时,agent 停下来属于正常结束。单条回答按 maxUserAnswerChars(默认 2000)截断。
  • 最后输出:agent 本轮最后一段文本输出。
  • 工具轨迹(可选,默认关闭:includeToolTrace):该用户输入之后发生的工具调用,每条压缩成一行;默认不发,判定只看上面几段文本。

判定模型看不到你其它的会话分支。

安全边界

  • 干预次数有上限:maxAutoContinues(默认 2)限制同一条用户请求的自动干预次数;你自己发新消息会重置计数。到达上限只提示一次,之后不再干预。
  • 不打断你的输入:判定期间如果你开了新一轮、有排队消息,或会话分支已经变化,判定结果直接丢弃。
  • 要求落地的改动指令不能只复述:用户请求是「去掉 X」「统一用 Y」「A 应该是 B」这类改动指令(祈使句或目标状态描述)时,agent 只复述规则、列出改动后的样子、回一句「明白了」而没有落地迹象,判定为提前停止;只有请求本身是提问、讨论或征求意见时才按「答完就能停」处理。
  • 在等后台任务时判为正常等待:agent 的最后输出说明它在等后台任务结果(例如刚启动 subagent、subagent_resume 或 workflow,并说明结果会自动送回来)时,判定提示词要求判「可以停止」——后台任务跑完会自己唤醒会话,此时催促只会多打一轮;这一条优先于其它判定条目。判断依据就是 agent 的最后输出,不依赖工具轨迹。
  • 失败必须报告:判定、鉴权、超时和发送失败都会在 UI 里报错,判定失败绝不会被当成「可以停止」。
  • 只在持续会话中生效:TUI 与 RPC 模式下才会判定;print/json 模式在 agent 停止后就收尾,催促不可能执行,因此直接跳过。

配置

文件:<pi-agent-dir>/extensions/pi-auto-goal/config.json,遵守 PI_CODING_AGENT_DIR。可从 config.example.json 开始。

{
  "enabled": true,
  "model": "",
  "maxAutoContinues": 2,
  "confidenceThreshold": 0.6,
  "timeoutSeconds": 30,
  "includeToolTrace": false,
  "maxUserRequestChars": 2000,
  "maxFinalOutputChars": 4000,
  "maxToolTraceEntries": 20,
  "maxUserAnswerChars": 2000,
  "notifyOnStopDecision": false,
  "showVerdictNotice": true,
  "judgeMaxTokens": 2000,
  "continueMessageTemplate": "",
  "forcedDecision": "auto"
}

| 字段 | 默认值 | 含义 | | --- | --- | --- | | enabled | true | 总开关;关闭后不产生任何判定调用。 | | model | "" | 判定模型,格式 provider/modelId;留空则复用当前会话模型。可直接在 /config:auto-goal 菜单里选,或用 /config:auto-goal model <provider/modelId> 指定。 | | maxAutoContinues | 2 | 同一条用户请求允许的自动干预次数;0 表示不限制。 | | confidenceThreshold | 0.6 | 触发干预所需的最低置信度。 | | timeoutSeconds | 30 | 判定请求超时;超时只报告,不当成可以停止。 | | includeToolTrace | false | 是否把本轮工具调用轨迹交给判定模型。默认关闭:判定应当基于用户请求与 agent 的最后输出。 | | maxUserRequestChars | 2000 | 用户请求截断长度。 | | maxFinalOutputChars | 4000 | agent 最后输出截断长度。 | | maxToolTraceEntries | 20 | 工具轨迹最大条数。 | | maxUserAnswerChars | 2000 | 单条用户回答(ask_user_question 的答案)截断长度。 | | notifyOnStopDecision | false | 已废弃:每轮只发一条结论块,这个开关不再起作用(保留字段以免旧配置报错)。 | | showVerdictNotice | true | 把最近一次判定结论写进会话区(落在消息下方,带底色的消息块;细节按 Ctrl+O 展开)。 | | judgeMaxTokens | 2000 | 单次判定调用的输出 token 上限,同时会被收敛到模型自身的输出上限。 | | continueMessageTemplate | "" | 覆盖内置催促文案(作为 system 指令注入),支持 {reason} 占位。 | | forcedDecision | "auto" | 受控实验开关:auto(正常判定)、continue(强制判定为提前停止)、stop(强制判定为可停止)。 |

未知字段与非法值会明确报错,不会被静默忽略。

怎么知道它到底有没有触发

每轮结束后,会话区里(消息下方)会出现一条带底色的 [auto-goal] 消息块,内容是判定结论(由 showVerdictNotice 控制,默认开):

| 结论行 | 颜色 | 含义 | | --- | --- | --- | | ⚖️ 判定可停止 · 置信度 92% | 绿 | 判定为正常结束,没有干预;理由收在展开里(Ctrl+O,全屏模式下直接点这条提示)。 | | ⚖️ 判定该继续 · 已催促 1/2 | 黄 | 判定为提前停止,已自动注入 system 催促(1/2 = 已催 1 次,上限 2 次)。 | | ⚖️ 催促次数用尽(2/2)· 不再干预 | 灰 | 本轮干预次数用尽,不再干预。 | | ⚖️ 已打断 · 未判定 | 灰 | 你按 Esc 打断了这一轮,判定主动让路。 | | ⚖️ 本轮未正常结束 · 未判定 | 灰 | 这一轮以失败或残缺结束(不是 agent 自己停下)。 | | ⚖️ 判定失败 | 红 | 判定调用失败。 |

正文只占一行;判定理由、已注入的催促文本、失败原因、结束原因等细节收在展开里:按 Ctrl+O 展开工具输出时会一起展开,全屏模式下也可以直接点这条提示块切换展开,平时不占地方。

判定结论不进 LLM 上下文,也不会写到页脚状态栏;它是本包写进会话的一条本地条目,重新打开会话时仍会照原样显示。

什么轮次会被判定

只判定「正常跑完」的轮次:最后一条 assistant 消息的结束原因是 stop(agent 自己结束本轮)或 length(输出被长度上限截断)。

用户按 Esc 打断时,结束原因是 aborted 或 error、内容为空——这是你的决定,不是 agent 的停止决定。以前这种轮次也会被当成「提前停止」去催,结果是刚按完 Esc 就被自动复活,看起来像 Esc 失效;现在这类轮次直接不判定,只写一行「已打断 · 未判定」。

如果你看到的是旧行为(按 Esc 后又被催),先确认当前会话的进程开在修复之后:本包在运行中的进程里不会热更新,需要 /reload 或重开会话。

两件事同时成立时才算「这一轮没有判定」:页脚还停在上一轮的结论,且没有任何新提示。常见原因是当前不是 tui/rpc 模式、你已经在打字,或上面这两种不判定的轮次。

同一轮的结论只发一条消息块(正文一行 + Ctrl+O 展开的细节),不再另外弹提示;notifyOnStopDecision 已废弃(保留字段以免旧配置报错,但不再起作用)。颜色只在 TUI 下添加,其他模式不会出现 ANSI 乱码。

判定调用为什么不会“空响应”

判定只需要一个 JSON 结论,但推理型模型会先把输出预算花在思考上。历史上 judgeMaxTokens 固定为 400,一旦思考把预算吃光,响应里就只剩思考块、没有任何文本,用户看到的是含糊的「无法解析的响应:(空响应)」。现在:

  • 判定调用固定使用最低思考强度(Pi 会收敛到模型支持的最低档,不支持关闭思考的模型也不报错);
  • 输出上限默认 2000,并可用 judgeMaxTokens 调整;
  • 若仍然被截断且没有文本,自动用翻倍预算重试一次;
  • 仍失败时,错误文案带上 stopReason 与内容块摘要(如 结束原因=length,内容块=thinking:400),不再只说「空响应」。

命令

  • /config:auto-goal — 打开 TUI 配置面板(别名:/auto-goal、/pi-auto-goal-config);面板是设置列表:左边字段名、右边当前值,选中项下面给说明,回车改一项并立即存盘生效,包含启用判定、判定模型、干预上限、置信度阈值、判定输出上限、判定结论写入会话区。字段的完整清单用 status 看。
  • /config:auto-goal enable|disable|status|reset — 非交互式写法;status 显示生效配置与本会话已干预次数。配置命令改完立即生效。
  • /config:auto-goal model 看当前判定模型;/config:auto-goal model provider/modelId 指定判定模型;/config:auto-goal model default 改回复用当前会话模型。

开发

cd packages/pi-auto-goal
npm run typecheck
npm test
npm run check

测试是确定性的:判定调用可以注入替身,不需要 API key 或真实模型。