aps-agent/poc/pi-aps/README.md

141 lines
5.4 KiB
Markdown
Raw Normal View History

# pi-aps:Pi Agent 访问 APS Gateway 的 PoC 包
本目录对应 `Pi-Agent接入详细计划.md` 的**方向 A(外向接入)**:Pi CLI 作为外部
客户端智能体,通过新增的 `/api/agent/*` 适配层调用 APS 业务能力,不在 Pi 侧另开
排产执行通道。
> 当前状态:这是 **P0/P1 只读接入扩展包**。服务端 `/api/agent/intents` 与
> `/api/agent/invoke` 由 Gateway 侧实现并另行验收;本扩展不包含任何模拟 APS 数据。
## 包结构
```text
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)
```powershell
$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")
```
只临时试一次、不写全局/项目配置:
```powershell
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` 的配置目录:
```powershell
$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` 可显式覆盖路径):
```json
{
"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_REQUIRED`
- `POWER_DENIED`
- `INTENT_NOT_REGISTERED`
- `UPSTREAM_FAILED`
## E2E 验证
`e2e.mjs` 不伪造 APS 数据:它先探测真实 APS `/api/health`,再启动本地
OpenAI-compatible 剧本 LLM,最后拉起真实 Pi CLI 和本扩展。
```powershell
$env:APS_BASE_URL = "http://127.0.0.1:8000"
node (Join-Path $repo "poc\pi-aps\e2e\e2e.mjs")
```
要专门验证配置文件读取,可把 token/URL 只放配置文件,不让环境变量进入
Pi 子进程:
```powershell
$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 管理实现。