# pi-aps:Pi Agent 访问 APS Gateway 的 PoC 包 本目录实现 **方向 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 "/" ` -e (Join-Path $repo "poc\pi-aps\extensions\aps.ts") ` -p "查询订单池" ``` `/` 替换为真实 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 / ` --extension "...\extensions\aps.ts" -p "查询订单池" ``` ### 持久化配置 可以改用持久化配置文件(计划落点 `~/.pi/aps.json`;若设置 `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 管理实现。