Pi HTTP开发
给Pi Coding Agent提供结构化HTTP(S)请求能力。每次Tool Call只表示一次请求,不解析Shell或curl语法。
项目:https://github.com/evalexp/pi-http
相关笔记:Pi Extension
当前状态
当前准备发布0.2.0。这是0.1接口到新结构化接口的Breaking Change,但本轮后续修改都只是0.2.0发布前的Bug Fix,不再改版本号。
发布前最后一次验证结果:
npm run typecheck通过;npm test共45个测试通过;npm audit为0个漏洞;npm pack后的生产依赖安装通过;- 使用Pi官方Extension Loader实际加载和执行通过;
- 自签名HTTPS默认返回
HTTP_TLS_FAILED,设置tls.insecure=true后可正常请求; - 临时调试日志已经全部移除;
- Tool描述、Schema描述、Prompt Guidelines和重试提示已经改成精简中文。
先记住的结论
- 这个Extension只适配Pi Coding Agent,不再考虑Bun兼容。
- Pi实际运行时是Node.js,最低版本跟随Pi要求:
>=22.19.0。 - 直接依赖
undici@8.9.0,不要检测Bun,也不要使用Bun.*。 - 不依赖Pi安装过的全局Fetch Dispatcher;每次Tool调用建立独立的Undici Dispatcher,确保代理和TLS参数真的生效。
- 模型能看到的是Tool Result的
content,不能假设它能看到details。 - 完整结果超过Pi输出预算时不截断,原子落盘,只把绝对路径和字节数告诉模型。
- HTTP 4xx/5xx是正常协议结果;只有参数、本地文件和传输错误才抛Tool Error。
- Extension本身不暗中重试。Prompt告诉Agent如何改参数以及何时安全重试。
设计目标
- 请求参数只有一种规范表达,不兼容0.1别名;
- 字符串都按JSON字面值使用,不展开环境变量、反斜线、Glob或命令替换;
- Body字节和Multipart结构尽量可控;
- 上传、下载采用流式处理;
- Redirect、Cookie、Proxy、TLS、Timeout都有明确状态;
- 无法忠实实现的功能明确拒绝,不能静默忽略;
- 输出同时适合模型阅读和Pi UI保留结构化信息;
- 错误可诊断,而且重试不会默认制造副作用;
index.ts保持薄,HTTP Core不依赖Pi Context。
Pi运行时适配
为什么不再判断Bun
之前误以为Pi Extension可能直接运行在Bun中,因此TLS代码出现过运行时分支,最终在Pi里触发了:
Bun is not defined实际适配目标就是Pi Coding Agent。Pi以Node.js加载TypeScript Extension,并且当前包本身声明:
{
"engines": {
"node": ">=22.19.0"
},
"dependencies": {
"undici": "8.9.0"
}
}因此维护时不要重新加入:
Bun全局变量;typeof Bun运行时探测;- Bun专用TLS Option;
- Node/Bun双分支;
- 为兼容Bun而绕开Pi的真实执行模型。
为什么不直接依赖全局fetch
Pi会为自身网络请求配置全局Undici Dispatcher。若Extension直接依赖全局fetch的隐式Dispatcher,逐请求代理、CA、自签名证书和mTLS设置可能被宿主配置干扰或根本不生效。
现在的结构是:
flowchart LR A[Pi调用http Tool] --> B[解析并校验参数] B --> C[为本次调用建立Undici Agent或ProxyAgent] C --> D[fetch或undici.request] D --> E[读取响应/下载] E --> F[销毁本次Dispatcher]
关键点:
- Dispatcher属于一次Tool Call,不共享可变状态;
- 显式代理使用
ProxyAgent; - 直连使用
Agent; - TLS参数传给本次连接;
- 清理失败不能覆盖原始请求错误;
transfer.decompress=false走undici.request,用于保留压缩响应字节;- 204、205、304等无Body状态在Raw路径也必须正确处理。
代码结构
| 文件 | 职责 |
|---|---|
index.ts | Pi Adapter、TypeBox Schema、注册Tool、把结果放入模型可见content |
agent-guidance.ts | 中文Prompt Guidelines和按错误码分类的参数重试建议 |
request.ts | 参数校验、请求编排、Redirect、Timeout、错误分类和Timing |
request-types.ts | 输入、结果、状态、错误等共享Contract |
request-body.ts | 各类Body与精确Multipart构造 |
file-stream.ts | 本地文件校验和流式上传 |
pi-transport.ts | Pi专用Undici Agent/ProxyAgent、Fetch/Raw传输与清理 |
response-body.ts | Response Header、内联捕获、Hash和原子下载 |
cookie-store.ts | 单次调用Cookie Jar、Netscape Cookie文件与原子写回 |
model-output.ts | 完整JSON内联或超限后原子落盘 |
test-server.ts | 测试用HTTP、HTTPS、代理Server |
request.test.ts | HTTP Core集成测试 |
contract-size.test.ts | Schema、Prompt和模型输出预算回归测试 |
依赖方向尽量保持:
flowchart TD A[index.ts / Pi Adapter] --> B[request.ts] A --> C[model-output.ts] A --> D[agent-guidance.ts] B --> E[request-body.ts] B --> F[pi-transport.ts] B --> G[response-body.ts] B --> H[cookie-store.ts] E --> I[file-stream.ts] C --> J[Node文件系统]
不要把Pi的ctx一路传进HTTP Core。目前只在Adapter取ctx.cwd和Pi的DEFAULT_MAX_BYTES。
Tool输入
唯一必填参数是:
{ "url": "https://example.com/status" }Method默认规则:
| 条件 | 默认Method |
|---|---|
| 无Body | GET |
| 有Body | POST |
GET和HEAD Body会直接拒绝,不尝试依赖运行时的模糊行为。
完整输入按职责分组:
| 分组 | 用途 |
|---|---|
url、method、headers、query | 基础请求 |
body | text/base64/json/form/file/multipart六选一 |
auth | Basic或Bearer |
cookies | 显式Cookie、Cookie文件、Jar写回 |
delayMs、timeoutMs | 网络前延迟和请求总超时 |
redirect | 模式、次数、协议、方法和敏感Header策略 |
connection | 显式代理、noProxy、连接超时和HTTP版本偏好 |
tls | CA、客户端证书和证书校验 |
transfer | 自动解压与Range |
response | 模式、捕获上限、Header选择和详情级别 |
download | 流式文件下载 |
Header和Query
统一使用有序数组:
{
"headers": [
{ "name": "X-Trace", "value": "abc" }
],
"query": [
{ "name": "tag", "value": "one" },
{ "name": "tag", "value": "two" }
]
}Query、Form和Multipart Part Header可以重复。顶层请求Header如果重复,Fetch语义会合并,无法保持原始重复项,因此当前直接返回HTTP_UNSUPPORTED_CAPABILITY,不能让模型误以为字节被保留。
requestTarget和pathAsIs=true也属于当前Undici层不能忠实表达的功能,传入即拒绝。
Body
Body是Discriminated Union,只允许一种type。
文本:
{ "body": { "type": "text", "value": "literal $HOME\\n" } }Base64原始字节:
{ "body": { "type": "base64", "value": "AAEC/w==" } }JSON:
{ "body": { "type": "json", "value": { "name": "Pi" } } }重复Form字段:
{
"body": {
"type": "form",
"entries": [
{ "name": "role", "value": "a" },
{ "name": "role", "value": "b" }
]
}
}流式文件Body:
{ "body": { "type": "file", "path": "./archive.bin" } }所有相对路径都基于Pi调用时的ctx.cwd。整个字符串就是路径,@没有特殊含义。
Multipart
0.2不再使用FormData + Blob + readFile()。Multipart由自己构造并流式读取文件,因此可以控制:
- Part顺序和重复字段;
- Boundary;
- CRLF或LF;
- 是否写结束Boundary;
filename原值;filename编码方式;- 结构化Header顺序;
- 原始Header行;
- text/base64/file三种Part内容。
{
"url": "https://example.com/upload",
"body": {
"type": "multipart",
"boundary": "chosen-boundary",
"lineEnding": "crlf",
"closeBoundary": true,
"parts": [
{
"name": "note",
"content": { "type": "text", "value": "hello" }
},
{
"name": "file",
"filename": "../../report 文本.txt",
"filenameEncoding": "both",
"contentType": "text/plain",
"content": { "type": "file", "path": "./report.txt" }
}
]
}
}filename故意不做basename或Unicode改写,因为调用者可能正在复现具体报文。
headers和rawHeaderLines互斥。若需要控制整个Preamble、分隔符、任意二进制内容或Epilogue,应直接用body.type=base64构造完整Body,并显式设置顶层Content-Type。
这里的“精确”只指Body字节。请求行、顶层Header编码、Framing、连接复用和协议协商仍由Undici控制;它不是Raw TCP Client。
Auth、Cookie和Redirect
Auth
支持:
- Basic:用户名、密码按UTF-8编码后再Base64;
- Bearer:直接形成Authorization Header。
URL中携带Credential会拒绝,避免出现两个认证来源。显式Authorization和auth冲突也会在发送前报告。
Cookie
{
"cookies": {
"value": "theme=dark",
"file": "./cookies.txt",
"jarPath": "./cookies-after.txt"
}
}Cookie文件使用Netscape格式。Jar仅存在于当前Tool Call及其Redirect Chain,不跨调用偷偷维持Session。写回使用临时文件再Rename。
即使后续Redirect请求失败,前一跳已经收到的Cookie仍应按当前状态写回。
Redirect
Redirect由request.ts逐跳处理,不交给Fetch自动跟随,这样才能准确控制:
follow、manual、error;- 最大20跳;
- 只允许HTTP/HTTPS中的指定协议;
- Loop检测;
- 301/302/303的方法改写或显式保留;
- 307/308正常保留Method和Body;
- 跨Origin敏感Header处理;
- 每一跳重新判断
noProxy; - 每一跳记录诊断信息。
跨Origin默认移除:
Authorization;Proxy-Authorization;Cookie。
只有明确设置redirect.trusted=true才允许转发。这个开关不能默认开启。
Proxy和TLS
Proxy
代理必须显式传入:
{
"connection": {
"proxy": "http://proxy.example:8080",
"proxyHeaders": [
{ "name": "Proxy-Authorization", "value": "Bearer value" }
],
"noProxy": ["localhost", ".internal.example:8443"]
}
}设计边界:
- 不继承
HTTP_PROXY、HTTPS_PROXY、NO_PROXY等环境变量; proxyHeaders只传给ProxyAgent,不能泄漏给目标站点;noProxy支持*、精确Host、点开头域名后缀和可选Port;- Redirect每一跳重新选择直连或代理;
- 仅有
proxyHeaders或noProxy但没有proxy时直接报参数错误; - HTTPS经HTTP代理使用CONNECT,并已经用本地代理测试真实TLS握手。
TLS
{
"tls": {
"caFile": "./private-ca.pem",
"clientCert": "./client-cert.pem",
"clientKey": "./client-key.pem",
"clientKeyPassphrase": "secret",
"insecure": false
}
}注意:
caFile是本次请求的Node CA输入,不是简单追加系统CA的抽象;clientCert和clientKey必须成对;insecure=true只关闭服务端证书校验;- TLS设置应用到本次Agent或Proxy CONNECT后的目标连接;
- 不再存在Bun TLS分支。
当前明确不支持
以下字段保留在Schema中是为了明确返回不支持,而不是静默忽略:
| 参数 | 原因 |
|---|---|
connection.resolve | 当前传输层不能提供可靠的逐请求DNS覆盖 |
connection.connectTo | 不能忠实覆盖连接目标同时保留目标语义 |
connection.ipVersion=4/6 | 当前仅支持auto |
requestTarget | Undici不提供独立Raw Request Target |
pathAsIs=true | URL规范化无法关闭 |
这些情况统一用HTTP_UNSUPPORTED_CAPABILITY提醒Agent删掉字段或改用别的表达。
Timeout、取消和请求状态
delayMs发生在任何网络I/O之前,而且不计入timeoutMs。
flowchart LR A[Tool开始] --> B[delayMs] B --> C[启动timeoutMs] C --> D[连接/上传/等待Header/读Body] D --> E[完成或取消]
Pi传入的AbortSignal在Delay和网络阶段都有效。调用开始前Signal已经Abort时,必须保持not_sent,不能创建一次看似发生过的网络事务。
requestState.outcome是重试判断的核心:
| outcome | 含义 |
|---|---|
not_sent | 没有发出网络事务,可在修正参数后重试 |
sent_no_response | 已发送,但没有拿到响应Header |
response_received | 已收到Header,可能在读Body或下载阶段失败 |
同时记录:
networkTransactions;initialRequestStarted;uploadedBytes;responseHeadersReceived。
这样Agent不需要仅凭错误文案猜请求是否可能已经产生副作用。
Response
详情级别
response.details | 返回内容 |
|---|---|
compact | Status、最终URL、请求状态、选中的Header和Body |
standard | 再加Timing、传输统计、Hash和Redirect次数 |
diagnostic | 再加规范化请求、每跳Redirect、Proxy/TLS摘要和连接字段 |
默认compact,需要排查连接或完整请求语义时才用diagnostic,避免长期浪费Context。
Body模式
response.mode | 行为 |
|---|---|
auto | 根据Content-Type决定UTF-8或Base64 |
text | 按UTF-8返回 |
base64 | 保留为Base64 |
discard | 读取并丢弃,不把内容放进结果 |
Body只出现一次:
body.content不再同时生成一份自然语言Summary和一份结构化Body,避免重复占Token。
Header
response.headers可以是:
all;none;- Header名称数组,大小写不敏感。
结果继续使用{name,value}[]。重复Set-Cookie必须逐条保留;其它重复Header受Fetch/Undici规范化影响,可能显示为逗号合并值。
可观测性边界
诊断结果中的这些字段目前可能是null:
- HTTP Version;
- Remote/Local Address和Port;
- IP Version;
- TLS Protocol和Cipher;
- Wire Bytes。
原因是当前Undici层没有可靠暴露它们。宁可返回null,不能用推测值冒充实际观测。
完整报文与模型输出
这是0.2里最重要的修复之一。
Pi Tool返回:
return {
content: [{ type: "text", text: modelOutput.text }],
details: result.details,
};模型实际依赖content。details主要供UI和程序化消费,不能认为模型一定可以看到它。
所以正常情况下,content直接放一份完整、合法、符合所选详情级别的JSON。不能只放Summary,否则用户要求完整报文时,Agent仍只看得到摘要。
两个完全不同的大小限制
Response捕获限制
response.maxBytes限制从Response Body捕获到结果中的原始字节,默认和上限都是Pi的DEFAULT_MAX_BYTES,当前为50 KiB。
达到上限时:
body.captureTruncated=true;- Hash只覆盖捕获字节,
hashScope=captured; - 这是网络读取/模型上下文层面的主动限制。
如果Body本身很大且确实要完整内容,应使用download.path,而不是增大模型内联结果。
Tool模型输出限制
完整JSON即使Body不大,也可能因为Diagnostic、Header或Base64膨胀超过Pi预算。
此时model-output.ts不会截断JSON:
flowchart TD A[序列化完整结果] --> B{不超过Pi输出预算?} B -->|是| C[直接写入content] B -->|否| D[写同目录临时文件] D --> E[Rename到.pi-http-results] E --> F[content只返回绝对路径和字节数]
首选目录:
<ctx.cwd>/.pi-http-results/http-result-<timestamp>-<uuid>.json如果当前工作目录不可写,回退到:
<os.tmpdir>/pi-http-results/权限:目录0700,文件0600。写入先使用.tmp,完成后Rename,失败清理临时文件。
这里的结果是“落盘而不是截断”,所以body.outputTruncated保持false。模型得到路径后应读取文件继续分析。
注意.pi-http-results可能包含Header、Cookie、Token和Body等敏感数据,使用后按需清理。
下载
大文件或二进制文件使用:
{
"url": "https://example.com/archive.zip",
"download": {
"path": "./downloads/archive.zip",
"overwrite": false,
"maxBytes": 104857600
}
}下载行为:
- Response Stream直接写文件;
- 自动创建父目录;
- 默认不覆盖;
- 写同目录临时文件,完整结束后Rename;
- 允许覆盖时也不会先破坏原文件;
- Timeout、Abort、Body错误或超过
download.maxBytes都会清理Partial File; - 返回绝对路径、实际字节数和SHA-256;
- HTTP 404/500正文也可能被成功下载,必须另外检查Status。
两个并发请求写同一路径且都设置overwrite=true时仍是Last Writer Wins。当前没有按路径加Mutation Queue。
错误模型
所有本地/传输错误都是HttpToolError,包含:
interface HttpToolErrorDetails {
code: string;
phase: "delay" | "prepare" | "resolve" | "connect" | "proxy" |
"tls" | "upload" | "headers" | "body" | "download";
message: string;
elapsedMs: number;
requestState: RequestState;
issues?: HttpIssue[];
causeCode?: string;
}参数预检会集中返回issues[],尽量让Agent一次修完,不要修一个再暴露下一个。底层Undici错误通过causeCode保留稳定原因,例如证书或DNS错误。
HTTP 4xx/5xx不进入这里:
flowchart TD A[请求结果] --> B{是否收到有效HTTP Response?} B -->|是| C[无论2xx/4xx/5xx都返回HttpResult] B -->|否| D[按阶段和原因生成HttpToolError]
重试为什么写在Prompt里
每个错误结果里重复塞完整重试说明会浪费Token,而且重试策略本来就是Tool使用规范。现在统一写在promptGuidelines,错误只返回状态、Cause和必要Issue。
通用规则:
outcome=not_sent:修正所有问题后可以重试;HTTP_ABORTED:不得自动重试;- 已发送请求:只有安全/幂等Method最多自动重试一次;
- 禁止自动重放可能有副作用的POST/PATCH等请求;
- Extension自身不隐藏Retry,是否重试由Agent显式决定。
参数可修正错误都有对应建议:
| 错误 | 建议方向 |
|---|---|
HTTP_INVALID_BODY | 按issues修正Body,只留一个body.type |
HTTP_INVALID_HEADERS | 修正Header、长度或冲突 |
HTTP_INVALID_URL | 修正URL、Query、Target或Redirect |
HTTP_INVALID_AUTH | 修正Auth或Authorization冲突 |
HTTP_INVALID_COOKIES | 修正Cookie值、文件或Jar路径 |
HTTP_INVALID_CONNECTION | 修正连接、代理或证书密钥配对 |
HTTP_INVALID_DOWNLOAD | 修正Download与Response字段冲突 |
HTTP_FILE_ERROR | 修正不可读的上传路径 |
HTTP_UPLOAD_FAILED | 修正上传源,再判断能否安全重放 |
HTTP_TIMEOUT | 调整timeoutMs或connectTimeoutMs |
HTTP_DNS_FAILED | 修正Host或Proxy |
HTTP_CONNECT_FAILED | 修正Host、Port、Proxy或noProxy |
HTTP_PROXY_FAILED | 修正代理URL、凭据、Header或noProxy |
HTTP_TLS_FAILED | 修正CA/客户端证书,或按条件关闭校验 |
HTTP_REQUEST_FAILED | 检查Cause和请求/连接参数 |
HTTP_RESPONSE_FAILED | 解码问题可尝试decompress=false |
HTTP_REDIRECT_LIMIT | 确认必要后增加最大跳转数 |
HTTP_REDIRECT_DISALLOWED | 允许时改follow或manual |
HTTP_REDIRECT_PROTOCOL | 改manual或修正目标协议 |
HTTP_REDIRECT_LOOP | 改manual或修正循环 |
HTTP_RESPONSE_TOO_LARGE | 调整或移除下载大小限制 |
HTTP_DOWNLOAD_FAILED | 修正下载路径和覆盖策略 |
HTTP_UNSUPPORTED_CAPABILITY | 删除字段或换成可支持的表达 |
TLS失败的特殊建议
只在下面条件同时成立时,Agent才应自动尝试一次:
- 错误是
HTTP_TLS_FAILED; - 使用的是默认服务端证书校验;
- 用户并未要求严格证书验证;
- 请求满足重放安全规则。
重试参数:
{ "tls": { "insecure": true } }如果用户明确要求验证CA、Hostname或mTLS,不能用insecure=true掩盖问题。
Prompt和Schema预算
Tool Prompt已经改为中文,并压缩成五条共享规则。原因不是面向用户显示,而是每轮Agent都可能携带这些内容,冗长英文会持续消耗Context。
当前要守住的预算回归:
- 生成后的Tool Schema约7413 Bytes;
- Prompt Guidelines约2251 Bytes;
- Typical Compact Result有单独测试;
- Oversized Result落盘和不可写CWD回退都有测试。
以后加参数时不要只看实现复杂度,也要检查Schema和Prompt的常驻Token成本。参数重试建议集中在agent-guidance.ts,不要复制进每个错误JSON。
测试
测试不Mock Fetch,使用本地真实Server、Socket、TLS和Proxy,更接近HTTP Core Contract Test。
当前45个测试主要覆盖:
- 六类Body、重复Form字段和大文件流式上传;
- 精确Multipart、Filename和Header;
- 多问题预检、旧0.1参数拒绝、重复顶层Header拒绝;
- HTTP 4xx/5xx正常返回;
- 301/302/303/307/308、Loop、Limit和跨Origin凭据;
- Cookie规则、Cookie文件、Jar持久化;
- Delay、连接/Body阶段Timeout和不同阶段Abort;
- 二进制、Hash、捕获限制、Header筛选和Discard;
- Raw Undici解压控制与无Body状态;
- 原子下载、拒绝覆盖和超限Partial清理;
- 自签名TLS、CA参数和CONNECT Proxy TLS;
- 独立Dispatcher,不受Pi全局Fetch Dispatcher影响;
- 显式代理、Proxy Header、逐跳noProxy和环境变量隔离;
- DNS、连接、代理错误分类;
- 不支持能力明确拒绝;
- 模型实际看到完整JSON,超限结果落盘;
- CWD不可写时回退系统临时目录;
- Schema、Prompt和典型结果大小预算。
测试命令:
npm run typecheck
npm test
npm audit
npm pack --dry-run本地加载:
pi -e .发布前不能只运行源码测试,还要解包tarball、只装Production Dependency,再用Pi官方Loader实际加载一次。这样才能发现files白名单漏文件、Peer Dependency或运行时导入问题。
Package
| 配置 | 当前值 |
|---|---|
| Name | @evalexp/pi-http |
| Version | 0.2.0 |
| Module | ESM |
| Node | >=22.19.0 |
| Runtime Dependency | undici@8.9.0 |
| Peer Dependency | Pi Coding Agent、TypeBox |
| Tests | Vitest |
| Type Check | TypeScript tsc --noEmit |
| Publish Access | Public |
Package直接发布TypeScript,由Pi负责加载。files白名单必须包含全部运行时代码:
index.ts
request.ts
request-body.ts
request-types.ts
agent-guidance.ts
model-output.ts
cookie-store.ts
file-stream.ts
pi-transport.ts
response-body.ts
README.md
CHANGELOG.md
LICENSE测试Server、测试代码和TLS Fixture不进入npm包。
安全边界
这个Tool同时拥有Pi进程的网络和文件权限:
- 能访问localhost、内网和宿主可访问的服务,天然具有SSRF式能力;
- 上传文件可以读取Pi进程有权限读取的本地内容;
- 下载可以创建文件,
overwrite=true可以替换目标; - Cookie、Authorization、代理凭据和完整响应可能进入Tool Result或
.pi-http-results; tls.insecure=true会放弃服务端身份校验;- 远端响应本身可能包含Prompt Injection。
安全默认值继续保持:
- 不自动读取代理环境变量;
- 不默认跨Origin转发敏感Header;
- 不默认覆盖下载文件;
- 不自动关闭TLS校验;
- 不自动重试已发送的副作用请求;
- 不在失败后保留Partial Download。
当前边界
- 不是Raw TCP/HTTP客户端;
- 顶层重复Request Header不能字节精确保留;
- 文本统一按UTF-8,没有完整Charset转换;
auto模式依赖Content-Type判断文本或二进制;- 某些连接和TLS细节无法由Undici可靠观测;
- 单次调用有Cookie Jar,但没有跨调用Session;
- 不在Extension内部做自动Retry;
- 同路径并发覆盖仍是Last Writer Wins;
- 完整模型结果可落盘,但内联Body捕获本身仍有50 KiB限制;真正的大响应必须下载。
维护检查表
以后修改至少确认:
- 没有引入
Bun或运行时探测; - 代码在Pi实际Node运行时和官方Loader中可用;
- 每次调用仍使用独立Undici Dispatcher;
- Proxy、TLS和noProxy在每个Redirect Hop正确生效;
- Dispatcher清理错误不覆盖Primary Error;
-
index.ts只做Pi Adapter; - 0.1旧参数仍明确拒绝;
- 无法实现的功能不静默忽略;
- 非2xx仍作为正常HTTP结果;
- Abort、Timeout、DNS、Connect、Proxy、TLS错误仍可区分;
-
requestState.outcome和实际发送状态一致; - Agent能从
content看到结果,不能只依赖details; - 输出超限时完整落盘,不截断JSON;
- 上传和下载保持流式;
- 下载仍然临时写入、原子Rename、失败清理;
- Cookie Jar写回保持原子性;
- Prompt与参数说明保持精简中文;
- 所有可改参数修复的错误都有重试建议;
- 已发送副作用请求不会被自动重放;
- Schema、Prompt和典型输出没有明显膨胀;
-
package.json files覆盖所有运行时文件; - 没有遗留调试日志或固定
/tmp调试路径; - Bug Fix不要再改0.2.0版本号;
- Type Check、45项测试、Audit、Pack和Pi实际加载全部通过。
问题快速定位
| 问题 | 先看 |
|---|---|
Pi加载失败、Bun is not defined一类问题 | package.json、pi-transport.ts及所有运行时Import |
| Agent没有选择http Tool | index.ts的Description、agent-guidance.ts |
| Schema不对或Token增长 | index.ts、contract-size.test.ts |
| 参数未一次报全 | request.ts的预检逻辑 |
| Body或Multipart字节不对 | request-body.ts |
| 文件上传失败或内存增长 | file-stream.ts、request-body.ts |
| TLS、Proxy、CONNECT不生效 | pi-transport.ts |
| Redirect方法或凭据异常 | request.ts的逐跳逻辑 |
| Cookie丢失或Jar异常 | cookie-store.ts |
| Timeout/Abort状态不对 | request.ts和RequestState |
| Response编码、Hash、Header异常 | response-body.ts |
| 用户要求完整报文但模型只见Summary | index.ts、model-output.ts |
| 输出被截断或落盘失败 | model-output.ts、contract-size.test.ts |
| 下载覆盖或残留Partial File | response-body.ts |
| Agent没有按错误调整参数 | agent-guidance.ts |
| npm包运行时缺文件 | package.json files和解包后的Pi Loader测试 |