Files
pikasTech-HWLAB/docs/reference/code-agent-chat-readiness.md
T
2026-05-25 20:55:33 +08:00

193 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Code Agent Chat Readiness Runbook
本文定义 Cloud Workbench `POST /v1/agent/chat` 的 readiness 判定。它只处理
Code Agent 回复链路是否具备复测条件,不修复、不读取、不打印、不创建也不修改任何
Secret 或 token。
## 运行边界
- DEV Cloud Web 入口是 `http://74.48.78.17:16666/`,同源代理到
`/v1/agent/chat`
- DEV API/edge 入口是 `http://74.48.78.17:16667/`;它不能替代 Workbench
同源聊天入口的真实回复证据。
- `internal/cloud/code-agent-chat.mjs``/v1/agent/chat` 的后端处理入口。
- `scripts/code-agent-chat-smoke.mjs` 是 Code Agent chat schema 与 readiness
合同检查。
- `scripts/dev-cloud-workbench-smoke.mjs --static` 只验证 Workbench 源码合同和
`/v1/agent/chat` 前端接线;它不是 DEV-LIVE 回复证明。
## Provider 前置条件
当前 DEV 部署合同中 `hwlab-cloud-api` 的 Code Agent provider 是
`HWLAB_CODE_AGENT_PROVIDER=codex-stdio`。运行时必须具备 repo-owned Codex app-server
stdio session supervisor,并证明 `/workspace/hwlab` 可读写、`CODEX_HOME=/codex-home`
可写、`/app/node_modules/.bin/codex --version` 可执行、`codex app-server --listen stdio://`
可创建和复用同一个 Codex thread/session。
Codex token boundary 仍由授权路径把 `OPENAI_API_KEY` 注入到 DEV runtime。DEV Pod
必须使用 `HWLAB_CODE_AGENT_OPENAI_BASE_URL` 指向受控 DEV egress/proxy 路径
`http://172.26.26.227:17680/v1/responses`,不能直接指向 public `api.openai.com`
Runner 不得尝试修补、读取、回显或替换该 Secret。若 DEV runtime 缺少该授权凭证注入,
`provider_unavailable``error.missingEnv` 包含 `OPENAI_API_KEY` 必须判为
`BLOCKED/credential`
部署前和部署后的自动化只允许证明 env 名称、`secretKeyRef` 的 Secret 名和 key 名、以及
DEV egress/base-url 合同是否声明和保留;不得读取 Secret data,也不得把 Secret 值写入
report、issue、PR 或截图。
## 判定标准
| 观测结果 | readiness |
| --- | --- |
| `status: "failed"``error.code: "provider_unavailable"`,且 `error.missingEnv` 包含 `OPENAI_API_KEY` | `BLOCKED/credential`;provider 凭证缺失,不能标真实回复通过。 |
| `provider: "codex-readonly-runner"``sessionMode: "controlled-readonly-session-registry"` | 历史只读状态,只能作为 `BLOCKED/not-codex-stdio` 诊断;不能满足当前自然语言单一路由或 DEV-LIVE reply pass。 |
| `codexStdioFeasibility.status: "blocked"`,或 blocker 包含 `codex_cli_binary_missing``codex_cli_not_executable``codex_cli_native_dependency_missing``runner_lifecycle_missing``stdio_protocol_not_wired``workspace_mount_missing``workspace_write_boundary_blocked``codex_home_missing``codex_home_write_blocked``provider_token_boundary` | 真实 Codex stdio / 等价 long-lived runner 未具备;必须按 blocker 处理,不能表述为完整 Codex session。 |
| `status: "completed"`,但来自 mock、fixture、本地 stub、source-only smoke、浏览器本地回显或人工拼接 | 不是 DEV-LIVE reply pass。 |
| 真实 DEV `POST /v1/agent/chat` 返回 `status: "completed"`,且 `reply.content` 是非空 assistant 回复 | 可标 DEV-LIVE reply pass。 |
| 传输失败、schema 不完整、HTTP 非预期、`reply.content` 为空或缺失 | `BLOCKED`,按 runtime/schema/transport 分析。 |
只有“真实 DEV 路由 + `completed` + 非空 assistant reply”能作为 DEV-LIVE 回复通过依据。
不得把 mock、fixture、本地 echo、source report、静态检查或前端状态当作通过。
## 自然语言单一路由
`/v1/agent/chat` 的自然语言请求唯一执行路径是 repo-owned Codex stdio long-lived
session。cloud-api 不再把自然语言预分类到 M3 Skill CLI、`/v1/m3/io`
`external.network.check``session_context``security.hardware-boundary`
`hardware.invoke.shell` shortcut 或 OpenAI text fallback。
自然语言里即使出现 M3、DO/DI、DAP、PWM、gateway、box-simu、patch-panel、Keil、
serial-monitor、Windows skill、串口、下载、烧录、启动日志等词,也必须把完整请求交给
Codex stdio turn。Codex turn 自己根据仓库、skill 文档和可用工具决定调用 repo wrapper、
Windows skill CLI、项目脚本或其他真实可达路径;cloud-api 只负责 session 生命周期、trace、
result 轮询和 schema 化返回。
如果 Codex stdio 不具备运行条件,`/v1/agent/chat` 只能返回 Codex stdio readiness
blocker,不能降级到 M3 Skill CLI、受控硬件 shortcut、外网专用检查或普通 OpenAI 文本回复。
显式 `/v1/m3/io` 控制面可以作为独立 API 或 UI 控制面继续存在,但聊天自然语言不得自动路由
到该 API,也不得保留要求自然语言先满足 M3 白名单的源码检查或测试。该显式控制面也不得在
进入 gateway 前保留固定 `DO1/DI1` 或固定 gateway 身份白名单预拦截;真实下游执行失败可以
返回执行失败,但不能由 cloud-api 用旧白名单提前拒绝。
持久 session 是默认合同:同一个 `conversationId/sessionId` 必须映射到 repo-owned Codex
thread 和固定 workspace,刷新前端、重新打开页面或短连接 result 轮询不得创建新的短期 runner。
除非 Pod 重建或 Codex supervisor 明确重启,workspace、thread/session 绑定和可见 trace 应持续
存在。
## PC Gateway Windows Skill 调用
Code Agent 通过已登记 PC gateway 执行 Windows 侧命令时,必须让 Codex turn 自己调用仓库 wrapper,不能由 cloud-api 字符串匹配短路到 gateway
```sh
node /app/tools/hwlab-gateway-shell.mjs --json --timeout-ms <ms> --powershell-stdin <<'PS1'
<bounded PowerShell script>
PS1
```
PowerShell 默认使用 wrapper 的 `-EncodedCommand` 路径;不要手写 `cmd /c powershell ...` 的管道、引号或中文转义。简单 `cmd` 命令仍可用 `--command "cmd /d /s /c ..."`,但涉及目录枚举、Unicode、管道、排序或 JSON 输出时优先用 `--powershell-stdin`
Workbench 会把“Gateway 命令超时”控件的毫秒值随 `/v1/agent/chat` 传入 `gatewayShellTimeoutMs`。Codex prompt 必须把该值落实到 wrapper 的 `--timeout-ms`cloud-api `hardware.invoke.shell` dispatch timeout 必须取环境配置、请求 `input.timeoutMs` 和 120s 默认值中的较大值并加 grace;不得让 20s/30s 的旧默认提前返回 `dispatchStatus=timed_out`。wrapper 自身 HTTP request timeout 要比 shell timeout 稍长,确保用户看到的是 gateway/cloud 返回的结构化 `status/operationId/dispatch`,不是 wrapper 先超时丢失结果。
调大 timeout 不能替代正确的长任务控制语义。Gateway poll loop 必须支持后台 in-flight 执行,长 Keil/UV4 命令运行期间仍能处理短 `job-status`、state/log 读取和健康探测;如果 trace 出现 `shellExecuted=false` 的 dispatch timeout,优先检查 gateway 是否队头阻塞或离线,而不是把所有 wrapper 调用改成长等待。
Workbench trace 对已知 JSON-RPC gateway 响应应按普通 tool call 展示:前端首行用中性 `tool gateway.shell status=<status> op=<operationId> exit=<exitCode> s=<duration>`,正文展示 request、gateway/resource/capability、dispatch、command、audit/evidence 以及有界 stdout/stderr。不要把整段 JSON 原样刷屏;复制/下载完整 trace 仍保留原始 JSON。
## 短连接 result 轮询
Workbench 与 Code Agent 的用户请求必须是短连接 submit + 短连接 result/trace 轮询;浏览器或 cloud-web 不应持有一次长 HTTP 请求等待整个 Codex turn 结束。`POST /v1/agent/chat` 返回 `202` 后,前端轮询 `/v1/agent/chat/result/<traceId>` 获取终态,并用 `/v1/agent/chat/trace/<traceId>` 刷新可视 trace。
cloud-web 同源代理必须把短连接语义原样转发给 cloud-api,至少包括 `Prefer: respond-async``X-HWLAB-Short-Connection``X-Trace-Id`。如果这些 header 在 cloud-web 层被过滤,cloud-api 会把同一个请求当成长同步请求处理,用户入口会表现为 16666 卡住或代理超时,而 16667 直连 cloud-api 正常。此类问题应先比对同一 trace 在 16666 与 16667 的 submit 行为,再修代理 header 透传,而不是调大前端等待时间。
`/v1/agent/chat/result/<traceId>` 是终态摘要接口,不是完整 trace 下载接口。它可以携带压缩后的 `runnerTrace` 窗口用于当前 UI 刷新,但必须保留 `eventCount``lastEvent``providerTrace``threadId/sessionId` 和终态 reply/blocker;完整 trace 只能从 `/v1/agent/chat/trace/<traceId>`、复制 JSON 或下载 trace 入口取得。默认 result trace 窗口上限由 `HWLAB_CODE_AGENT_RESULT_TRACE_EVENT_LIMIT` 控制;不要把数百个大 chunk 原样塞进 result 响应,避免 cloud-web 代理层或浏览器 fetch 把“正常执行中的大响应”表现成 503、非 JSON 或空响应。
result 轮询的 408/425/429/5xx、浏览器 timeout、非 JSON 或空响应应按“可恢复传输抖动”处理:前端先拉取一次 trace 刷新活性,再带退避继续轮询,只有后端返回结构化 terminal blocker、真实终态失败,或 trace 按无新事件 idle timeout 超时,才向用户显示失败。只要 `/trace` 仍显示新事件或 `waitingFor` 仍在推进,就不能把一次 result poll 失败标成“Code Agent API 错误”并停止。
Windows 侧 skill、编译器、脚本工具和多参数命令都应走同一个通用传输模式,不新增某个工具的专用 wrapper 子命令:
- 工作目录优先用 wrapper 的 `--cwd <windows path>` 或脚本内 `Set-Location -LiteralPath <path>` 表达,不要在 prompt 里拼 `cmd /c "cd ... && ..."`
- 命令参数在 PowerShell 脚本里用数组或显式变量传递,例如 `$args = @("subcommand", "-p", $projectPath)``& $exe @args`,避免让模型手动嵌套引号。
- 对所有 Windows skill 都先复用 `C:\Users\liang\.agents\skills\<skill>\SKILL.md` 和该 skill 自带 CLICode Agent 只负责通过 repo wrapper 调用,不把 skill 行为复制到 cloud-api 或 wrapper。
- 一次探测命令失败后,只做一次更窄、更结构化的修正;若仍失败,返回失败 `operationId`、stderr 摘要和下一步,而不是连续试错。
Windows 文件系统探测必须是有界小输出:
-`F:\work``F:\work\ConStart` 或同类目录先做顶层目录/项目标记探测,不要读取 Secret、env、kubeconfig、DB URL 或完整源码内容。
- 使用 `-LiteralPath``Select-Object -First <N>``ConvertTo-Json -Compress -Depth <N>`stdout 目标控制在约 12 KB 内。
- wrapper 的 PowerShell prologue 已设置 UTF-8 console/output,并提供 `Read-HwlabText``Select-HwlabText``ConvertTo-HwlabJson`。读取中文 `SKILL.md`、Keil 日志或 manifest 时优先用这些 helper,避免 `Get-Content`/`Select-String` 的扩展对象字段和系统代码页造成乱码。
- 不要先输出完整目录 JSON 再依赖终端截断;需要更多信息时按明确候选项目二次查询。
- 如果命令已经到达 gateway 但因脚本语法或输出大小失败,只允许简化修正一次;最终回复要记录失败 `operationId`、修正后的成功 `operationId` 和有界输出摘要。
Keil 编译、下载或探测请求必须优先使用 Windows 侧 skill,而不是在 prompt 中重写 Keil 调用逻辑:
```sh
cd C:\Users\liang\.agents\skills\keil
py -3 keil-cli.py build -p <project.uvprojx> -t <target>
py -3 keil-cli.py job-status <job_id>
```
多 probe、烧录和 reset-run 的具体参数以 Windows 侧 `C:\Users\liang\.agents\skills\keil\SKILL.md` 为准;Code Agent 只负责通过 repo wrapper 调用该 skill CLI 并返回 trace、operation/evidence 和 bounded stdout/stderr 摘要。
对 build/download 这类长任务,Code Agent 应优先使用 skill 自带的异步 job 语义:启动命令用短 wrapper timeout 拿到 job id 或明确的启动失败,再用短 `job-status`、state 文件和日志读取轮询进展。除非用户明确要求同步等待并设置了足够大的 Gateway 命令超时,不要通过 gateway 执行 `--wait` 长轮询;同步等待会占用一个 in-flight 槽位,旧 gateway 还会造成队头阻塞。
串口启动日志请求必须优先使用 Windows 侧 `serial-monitor` skill,而不是在 cloud-api 新增串口专用 route
```sh
cd C:\Users\liang\.agents\skills\serial-monitor
npm run cli -- server status
npm run cli -- server start
npm run cli -- monitor start -p <COMx> -b <baud>
npm run cli -- fetch --session-only --no-dedup
```
Keil 下载后的启动日志抓取应和 build/download 共用同一个 Codex stdio session 与 gateway wrapper trace。71-FREQ 类项目的串口参数以 Windows 侧 `serial-monitor\SKILL.md` 和实时设备枚举为准;需要轮询时用短 wrapper 调用读取 session/state/log,而不是新增聊天层白名单或 blocker。
## Smoke Checks
本地合同检查:
```sh
node scripts/code-agent-chat-smoke.mjs
```
该命令验证 schema、`provider_unavailable` provider gap、`OPENAI_API_KEY`
missing-env 分类,以及本地 stub completion 不能升级为 DEV-LIVE pass。
Workbench 静态接线检查:
```sh
node scripts/dev-cloud-workbench-smoke.mjs --static
node scripts/dev-cloud-workbench-smoke.mjs --dom-only --url http://74.48.78.17:16666/
```
该命令验证 Workbench 默认页、同源只读边界和 `/v1/agent/chat` 前端主流程接线。它只产出
`SOURCE` 级证据。`--dom-only` 会保留部署 runtime/web-asset identity preflight
但只做真实 DEV DOM/help 只读观察;它不会发送 `/v1/agent/chat`Code Agent journey
必须记录为 `not_applicable`,不能冒充真实 DEV-LIVE reply。
授权凭证注入后的真实 DEV 复测:
```sh
node scripts/code-agent-chat-smoke.mjs --live --url http://74.48.78.17:16666/
```
`--live` 会向真实 DEV `/v1/agent/chat` 发送一条最小聊天请求。输出只包含
readiness、provider/model/backend、assistant 回复是否非空和长度、错误分类等摘要;不打印
assistant 回复正文,不读取或打印任何 Secret 值。
## 复测结果解释
- 若输出 `readiness.level: "BLOCKED/credential"`,后续动作是由授权路径注入
`hwlab-code-agent-provider/openai-api-key`,不是由 runner 临时补 Secret。
- 若输出 `readiness.level: "#143 DEV-LIVE reply pass"`,只说明真实回复链路通过;
它不自动证明 M3、M4、M5 或硬件闭环通过。
-`scripts/dev-cloud-workbench-smoke.mjs --static` 通过,而 `--live` 未通过,结论是
Workbench 接线和源合同通过,但真实 provider readiness 仍 blocked。
## 稳定来源
- [docs/reference/cloud-workbench.md](cloud-workbench.md)Cloud Workbench 默认页和同源边界。
- [docs/reference/dev-runtime-boundary.md](dev-runtime-boundary.md):DEV 端口、k3s 与运行态边界。
- [docs/reference/architecture.md](architecture.md)`SOURCE``LOCAL``DRY-RUN`
`DEV-LIVE``BLOCKED` 证据分级。