AI DAILY / 2026-09-21
y0usaf/pi-jev:为 Pi 代理加入类型安全的 Jev 决策层
y0usaf/pi-jev
全文中文翻译 · AI 生成,仅供学习交流
y0usaf/pi-jev
Jev 针对一段 state(状态)回答类型化(typed)的问题。问它"是不是真的",你会得到一个概率;让它从列表里挑,它会返回所选项以及其他选项的概率分布。它不写散文,所以这里不存在任何句子层面的解析。答案是数字,由你的代码决定分支走向。
有三处会用到它:一个 gate 在 bash、write、edit 调用运行前进行判定;一个 output judge 读取 bash 调用的输出;一个 jev_ask 工具让模型自己发起同样形式的判定。
安装
pi install npm:@y0usaf/pi-jev该扩展需要一把 API key。没有 key 时它仍会加载,提示一次,然后保持静默不打扰。
The gate
| 问题 | 类型 | 读取 | 阈值 |
| --- | --- | --- | --- |
| 该操作是否具有破坏性? | noul | destructive | 0.90 |
| 是否把本地数据或机密发送到本机之外? | noul | exfiltration | 0.70 |
| 是否影响了用户请求范围之外的内容? | noul | beyond_scope | 0.85 |
| 如果用户不希望发生该操作,损失有多大? | score(4 档) | impact | 2.50 |四个问题合并在同一次请求里,因此一次判定只需约 300 ms 的一次往返,而不是四次。
默认模式为 shadow(影子模式)。
被标记的调用会产生一条通知,并在页脚显示状态。在 enforce(强制)模式下,被标记的调用在运行前会要求你确认。无头运行(-p、RPC)无法显示提示,因此除非设置 gate.blockWithoutUI,否则强制模式会退化为同样的警告。
所有出错路径都采取 fail open(放行)策略。缺失的 key、超时、429 或格式错误的响应都不会产生判定,工具调用照常执行。错误提示每分钟最多上报一次,因此失效的接口不会把会话日志塞满。
相同的输入在 cacheSeconds(默认 120)内只判定一次。来自同一条助手消息的同级调用共享一个进行中的请求,而不是各自单独请求。
The output judge
Gate 看得到意图,却看不到命令的输出。因此它抓不到打印到会话里的凭据,也分不清网络抖动和类型错误,这两类判定都针对调用之后才出现的文本。
tool_result 在同一次请求里问两个问题,并在任一题触发时向工具结果附加一行:
| 问题 | 类型 | 读取 | 阈值 |
| --- | --- | --- | --- |
| 该输出是否包含机密或凭据? | noul | leaks_secret | 0.90 |
| 这是哪一类失败? | choice(6 项) | failure_class | confidence 0.60 |若判定为泄露,会附加一句"不要在回复、文件或命令中复述该值,请改用名称引用",并触发一条通知。失败类别会附加处理建议:transient 原样重试,environment 修复环境,code_bug 修改代码,permission 不要重试,user_error 修正调用方式。no_failure 则什么都不附加。
建议来自一张表,而不是分支逻辑。src/output.ts 中的 CLASS_ADVICE 把每个类别映射到一句话,因此新增一个类别只需要新增一行。
它从不会阻塞,且在没有任何命中时保持静默。被判定的工具默认为 ["bash"]:对每次读取都做判定,每次打开文件都要消耗一次请求。
jev_ask
对于那些希望以类型化形式而非自然语言形式返回的决策:
{
"state": "the tool output, diff, or message to judge",
"questions": [
{
"id": "relevant",
"type": "noul",
"instructions": "Is this relevant to the user's question?"
},
{
"id": "label",
"type": "choice",
"instructions": "Which bucket?",
"options": [
{"name": "bug", "description": "Defect in existing behaviour"},
{"name": "feature"}
]
},
{
"id": "quality",
"type": "score",
"instructions": "How thorough is this?",
"levels": ["Superficial", "Adequate", "Thorough"]
}
]
}每个条目只问一件事,再由你自己的代码合并答案。TypeSafe 建议将多因素问题拆开,因为同时权衡多个因素的问题返回的结果更不可靠。
配置
配置文件为 ~/.pi/agent/pi-jev.json,或项目范围内的 .pi/pi-jev.json。项目级配置优先生效,且每个文件只会覆盖其中显式设置的键。
{
"apiKeyFile": "~/keys/typesafe.txt",
"model": "jev-latest",
"maxStateChars": 4000,
"gate": {
"enabled": true,
"mode": "shadow",
"tools": ["bash", "write", "edit"],
"argumentChars": 400,
"cacheSeconds": 120,
"minConfidence": 0.5,
"blockWithoutUI": false,
"blockOn": {
"destructive": 0.9,
"exfiltration": 0.7,
"beyondScope": 0.85,
"impact": 2.5
}
},
"output": {
"enabled": true,
"tools": ["bash"],
"outputChars": 2000,
"leakThreshold": 0.9,
"minConfidence": 0.6
}
}API key 按以下顺序解析:环境变量 TYPESAFE_API_KEY → 配置文件中的 apiKey → apiKeyFile(指向密钥文件路径,~ 会展开)。blockOn.impact 是 0 到 3 损伤量表上的一个值。minConfidence 仅作用于该维度,因为那三个 noul 问题只返回概率,不返回置信度。
命令
- /jev 显示模式、模型、密钥来源、被判定工具和缓存大小
- /jev on 和 /jev off 切换当前会话内两个判定器的开关
- /jev mode shadow|enforce 切换 gate 模式,无需重新加载
- /jev last 打印最近一次 gate 判定及其四个答案
- /jev output 打印最近一次输出判定:泄露概率与失败类别
- /jev check <text> 对你提供的文本运行 gate 的判定问题
数据外传情况
每次判定都会将工作目录、工具名、上一条用户消息(取前 1200 个字符)以及工具参数发送到 `api