5.4 KiB
pi-aps:Pi Agent 访问 APS Gateway 的 PoC 包
本目录实现 方向 A(外向接入):Pi CLI 作为外部
客户端智能体,通过新增的 /api/agent/* 适配层调用 APS 业务能力,不在 Pi 侧另开
排产执行通道。
当前状态:这是 P0/P1 只读接入扩展包。服务端
/api/agent/intents与/api/agent/invoke由 Gateway 侧实现并另行验收;本扩展不包含任何模拟 APS 数据。
包结构
poc/pi-aps/
├── package.json # pi-package manifest,本地路径安装
├── extensions/aps.ts # Pi ExtensionAPI:健康/摘要/调用 + 动态意图工具
├── skills/pi-aps/SKILL.md # 面向 Pi 的 skill
├── README.md
└── e2e/
├── mock-llm.mjs # OpenAI-compatible 剧本 LLM(只用于真实 Pi E2E)
├── e2e.mjs # 真实 Pi CLI 端到端包装
└── pi-home/ # PI_CODING_AGENT_DIR 隔离配置(运行时生成)
安装(本地路径,不发布 npm)
$env:APS_BASE_URL = "http://127.0.0.1:8000"
$env:APS_AGENT_TOKEN = "" # 正式态填 Agent Token;开发态 APS_AUTH_ENABLED=0 可留空
$repo = (Resolve-Path ".").Path
$env:PI_CODING_AGENT_DIR = Join-Path $repo "poc\pi-aps\e2e\pi-home" # 隔离配置,不改全局 ~/.pi/agent
$piCli = Join-Path $repo "poc\pi-fallback\runtime\node_modules\@mariozechner\pi-coding-agent\dist\cli.js"
node $piCli install (Join-Path $repo "poc\pi-aps")
只临时试一次、不写全局/项目配置:
node $piCli `
--mode json --no-session --model "<provider>/<model>" `
-e (Join-Path $repo "poc\pi-aps\extensions\aps.ts") `
-p "查询订单池"
<provider>/<model> 替换为真实 LLM provider(或在隔离配置目录中写好 mock provider)。
真实用法需要把 PI_CODING_AGENT_DIR 指向包含 models.json 的配置目录:
$env:PI_CODING_AGENT_DIR = Join-Path $repo "poc\pi-aps\e2e\pi-home"
# 把 baseUrl/apiKey/models 写到 $env:PI_CODING_AGENT_DIR\models.json
node "...\pi-coding-agent\dist\cli.js" --mode json --no-session --model <provider>/<model> `
--extension "...\extensions\aps.ts" -p "查询订单池"
持久化配置
可以改用持久化配置文件(计划落点 ~/.pi/aps.json;若设置
PI_CODING_AGENT_DIR,则读取 <PI_CODING_AGENT_DIR>/aps.json;
APS_CONFIG_FILE 可显式覆盖路径):
{
"aps": {
"baseUrl": "http://127.0.0.1:8000",
"token": "replace-with-issued-agent-token",
"requestTimeoutMs": 30000,
"catalogTimeoutMs": 8000
}
}
环境变量优先级最高:APS_BASE_URL、APS_AGENT_TOKEN、
APS_REQUEST_TIMEOUT_MS、APS_CATALOG_TIMEOUT_MS 会覆盖 JSON 同名字段。
配置文件缺失或损坏时扩展回退环境变量/默认值,并可在 /aps-status 看到
配置加载错误,不会伪装成成功请求。
工具与意图目录
扩展固定注册:
| 工具 | 调用 | 说明 |
|---|---|---|
aps_health |
GET /api/health |
APS 健康/接口版本 |
aps_summary |
GET /api/world/summary |
世界/KPI 摘要 |
aps_invoke |
POST /api/agent/invoke |
按 intent 名调用 |
session_start 时扩展请求 GET /api/agent/intents,把目录中每个意图注册为
aps_ + 下划线形式的动态工具(例如 order.pool → aps_order_pool)。目录不可用
不影响上述三个基础工具。
命令 /aps-status 显示 baseUrl、token 是否已配置(只掩码后四位,绝不打印原文)、
已注册工具数和最近错误。
只读边界与预期错误
当前阶段只把只读目录暴露给 Pi。P0 只读意图应直通执行;P1/P2/P3 写类意图由 Gateway 返回以下错误之一,Pi 工具会作为失败事件抛给模型,而不是包装成成功:
CONFIRM_REQUIREDPOWER_DENIEDINTENT_NOT_REGISTEREDUPSTREAM_FAILED
E2E 验证
e2e.mjs 不伪造 APS 数据:它先探测真实 APS /api/health,再启动本地
OpenAI-compatible 剧本 LLM,最后拉起真实 Pi CLI 和本扩展。
$env:APS_BASE_URL = "http://127.0.0.1:8000"
node (Join-Path $repo "poc\pi-aps\e2e\e2e.mjs")
要专门验证配置文件读取,可把 token/URL 只放配置文件,不让环境变量进入 Pi 子进程:
$env:APS_CONFIG_FILE = Join-Path $repo "poc\pi-aps\e2e\pi-home\aps.json"
$env:APS_E2E_CONFIG_FILE_ONLY = "1"
node (Join-Path $repo "poc\pi-aps\e2e\e2e.mjs")
e2e.mjs 会临时生成该文件并在结束时删除(仅限 pi-home 内生成的配置)。
输出与产物:
last-events.jsonl:Pi 原始 JSONL 事件,供人工复查last-summary.json:断言结果摘要- 若
/api/agent/intents可用且含order.pool,走aps_order_pool动态工具; 否则回退aps_health只验证基础 HTTP 接入
Pi headless 的进程退出码恒为 0,判成败必须以 JSONL 中的
tool_execution_end.isError 和最后 assistant 消息 stopReason=stop 为准。
已知边界
- 服务端
/api/agent/*三件套与 Agent Token 签发是 Gateway 侧交付,本目录只做 Pi 侧客户端;未看到服务端路由前,/api/agent/intents返回 404 属预期。 - P2 确认卡(写操作审批)尚未在本扩展内实现交互;当前写意图应失败显式。
- Pi 自身无沙箱;安全边界靠扩展只发 APS HTTP + 现场 token 管理实现。