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

190 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
gate。
- `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 MCP
stdio session supervisor,并证明 `/workspace/hwlab` 可读写、`CODEX_HOME=/codex-home`
可写、`/app/node_modules/.bin/codex --version` 可执行、`codex mcp-server`
可通过 MCP initialize/tools/list 观测到 `codex``codex-reply`
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"``capabilityLevel: "read-only-session-tools"``session.status``idle/ready/busy``session.idleTimeoutMs``session.lastTraceId` 存在、`session.longLivedSession: true``longLivedSessionGate.status: "blocked"``runnerLimitations` 包含 `not-codex-stdio` / `not-write-capable` / `process-local-session-registry` | 可标为 #317 read-only long-lived session registry pass;不能关闭 full Codex stdio/session capability blocker。 |
| `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、静态检查或前端状态当作通过。
## Runner 能力边界
`/v1/agent/chat` 可以先落地受控只读能力,但必须诚实区分:
- `controlled-readonly-session-registry`:由 cloud-api 进程内 registry 保存
`conversationId/sessionId` 映射、`status`、workspace、sandbox、`createdAt``updatedAt`
`idleTimeoutMs``lastTraceId``turn` 计数与只读工具 trace。它可以覆盖 `pwd`
`skills.discover``ls``rg --files` 和 bounded `cat`,输出必须限长和脱敏。该模式是
read-only long-lived session,但 `longLivedSessionGate` 必须保持 `blocked`,直到 Codex
stdio 或等价 full Code Agent 协议通道真实接通。
- 该模式必须同时标记 `not-codex-stdio``not-write-capable``process-local-session-registry`。它不是
Codex stdio / workspace-write session,不提供写文件、任意 shell、硬件写、Secret/kubeconfig/DB URL
读取,也不证明 M3/M4/M5 trusted green。
- OpenAI Responses fallback 只能标记为 `openai-responses-fallback` /
`text-chat-only`,不得满足 Codex runner capability gate。默认路径不得用 fallback
冒充完整 Code Agent;仅明确允许 fallback 时才可作为普通文本备用通道返回。
- 已登记 PC gateway `shell.exec` capability 是受控硬件能力例外:当请求能从显式
`projectId/gatewaySessionId/resourceId/capabilityId` 或唯一 DEV MVP topology 解析时,
`/v1/agent/chat` 可以选择 `hwlab-hardware-capability` runner,经 cloud-api 进程内
JSON-RPC helper 调用 `hardware.invoke.shell`。该 helper 必须使用冻结的
`hwlab-cloud-api` service id 常量,返回 payload 需包含 `toolCalls[]``operationId`
`dispatchStatus``exitCode`、stdout/stderr 摘要、`runnerTrace.eventLabels`
`capabilityLevel`。拓扑缺失、不唯一、gateway offline、session/capability missing、
dispatch failed 或 JSON-RPC meta/serviceId 无效时必须返回结构化 blocker,不能转入
Codex stdio 或 OpenAI 文本 fallback 冒充成功。
- `security.hardware-boundary` 仍然阻断直接 gateway/box-simu/patch-panel URL、`/invoke`
`/sync/tick` 和泛化硬件写绕过;受控 `hardware.invoke.shell` capability route 只允许
已登记、可解析的 cloud-api 调用,不开放任意 shell。JSON-RPC/REST bridge 拒绝未知
`serviceId` 时,错误原因应可见为 `unknown serviceId ...` 或等价结构化 reason,且不得泄露
Secret/token。
当前 DEV/runtime 若要升级为完整 #275 runner,至少需要 repo-owned 的 Codex CLI/stdio 或等价
runner 二进制/协议适配、session supervisor 生命周期、workspace mount 与 sandbox 合同、token/Secret
注入边界、trace/cancel/reap 机制,以及与 cloud-api/workbench 的持久 session 映射。缺任一项时,必须
`codexStdioFeasibility` 中报告 blocker。
## PC Gateway Windows Skill 调用
Code Agent 通过已登记 PC gateway 执行 Windows 侧命令时,必须让 Codex turn 自己调用仓库 wrapper,不能由 cloud-api 字符串匹配短路到 gateway,也不能直接访问 gateway URL
```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 hardware.invoke.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。
`/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 还会造成队头阻塞。
## Smoke Gate
本地合同检查:
```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` 证据分级。