Co-authored-by: Codex Agent <codex@hwlab.local>
15 KiB
v0.2 hwlab-cloud-api 服务规格
hwlab-cloud-api 是 v0.2 应用层核心服务,运行在 hwlab-v02 namespace,内部端口 6667,公网经 hwlab-edge-proxy 和 FRP 暴露为 http://74.48.78.17:19667。
在系统中的职责划分
- 承担 runtime health、DB readiness、登录鉴权、
AuthPrincipal、用户/session/API key 权限、Code Agent 对话、trace/result 轮询、gateway outbound registry、M3 IO 控制、device-pod authority/job 和 live build inventory。 - 是
hwlab-cloud-web、Code Agent session、device-pod 用户态操作和 gateway outbound poll 的唯一应用层收口点;普通用户不直接访问内部hwlab-device-podService。 - 读取
hwlab-cloud-api-v02-db/database-url、hwlab-v02-code-agent-provider/openai-api-key和hwlab-v02-code-agent-codex-auth/auth.json等 v02 独立 SecretRef;用户 API key 存在 Postgresapi_keys,不得再以hwlab-v02-device-pod-api-key/api-key这类跨用户 SecretRef 授权 device-pod。文档和日志只允许记录 SecretRef 名称、key、字节数或哈希指纹,不记录值。
内部架构
cmd/hwlab-cloud-api/main.ts负责启动 HTTP server、解析端口和 Code Agent timeout。internal/cloud/server.ts负责 HTTP route、REST/RPC bridge、health、live-builds、device-pod authority、gateway poll/result 和 Code Agent chat。internal/cloud/access-control.ts负责/auth/*、OIDC callback、Web session、用户 API key、admin/user、device pod profile/grant、device job lifecycle 和 Code Agent owner binding;登录与鉴权 authority 见 spec-v02-auth.md。当前本地/auth/login只作为 bootstrap/legacy fallback。internal/cloud/access-control.ts也是账号 workspace authority:account_workspaces记录同一账号的 Workbench 当前 workspace、selected conversation/session、active trace、provider profile 和 revision。- Code Agent session 生命周期必须显式化。Cloud API 目标入口为
POST /v1/agent/sessions创建 session、GET/PATCH /v1/agent/sessions*查询/选择/标记状态;POST /v1/agent/chat只接受显式传入或账号 workspace 中已显式选中的 usable session。没有 session 时返回session_required,session failed/stale/canceled 时返回session_not_usable,不得自动创建、滚动或替换 session。 - Code Agent session record 是 provider profile authority。
POST /v1/agent/chat带显式 session 且请求未显式给出 provider profile 时,Cloud API 必须继承该 session 的providerProfile并映射为 AgentRunbackendProfile;请求显式覆盖 provider profile 时,覆盖必须进入 trace/result 可见字段。账号 workspace 的 provider profile 只能在 selected session 与目标 session 完全一致时作为 fallback,不得让旧 workspace 覆盖显式 session。 internal/db/runtime-store.ts和internal/cloud/db-contract.ts负责 Postgres runtime store 与 readiness 分层。internal/cloud/code-agent-*.ts负责 Codex stdio session、trace store、result cache、provider profile 和取消/轮询。- AgentRun dispatch 的 policy 字段由 Cloud API adapter 固定归一化:
tenantId=hwlab、projectId=pikasTech/HWLAB、providerId=G14。Workbench project/workspace 只能作为 HWLAB metadata 或workspaceRef子字段保存,不能污染 AgentRunprojectId;出现 project/tenant 混乱时,临时处理是修 adapter 字段映射并用真实运行面最小请求复测,不放宽 AgentRun manager policy。 - AgentRun v0.1 接入只使用标准
threadId路径:POST /v1/agent/chat收到的conversationId/sessionId/threadId必须写入 AgentRun commandpayload.threadId和SessionRef.threadId;协议字段、trace、result 和 conversation facts 都以该字段为唯一 thread identity。 - AgentRun run 级 events 写回 HWLAB trace 时必须按当前
commandId归属过滤;同一 run 的旧 command 尾部事件不能混入后续 command trace。取消、失败或 blocked 轮次如果已有 assistant/tool 可读进展,必须以脱敏、限长的 conversation facts 写入 UI/trace/inspect 证据,供后续inspect/--from-trace可见性使用;这些 facts 不得作为下一轮模型上下文或 prompt 拼接来源。 - AgentRun completed 轮次续接必须依赖 Codex stdio 原生 session continuation。Cloud API 只把本轮原始
message/prompt和显式 session 的标准conversationId/sessionId/threadId写入 AgentRun command payload 与SessionRef;不得从请求、account workspace 或 account conversation 生成conversationContext,不得把历史消息拼入 prompt,也不得把请求体里的conversationContext/messages当作模型上下文。历史 conversation facts 只用于 UI、inspect、trace 和--from-trace的可见性证据;收到 synthetic context 字段时只能记录 ignored trace 并剥离。thread/resume失败时按 AgentRunthread-resume-failed终止本轮并标记当前 session failed/stale,不自动创建新 session。 - Code Agent 不允许存在 turn/session/conversation 总时长 timeout;只允许无新 app-server 响应、无 notification、无 assistant/tool/event activity 的 idle timeout。AgentRun command 失败、provider 失败或 idle timeout 只终结当前 command,并按 session policy 标记当前 session 状态;系统不得自动滚动到新 session。后续消息要么继续同一个 usable session/thread,要么由用户显式创建或选择另一个 session。
- runner pod 被删、runner Job 被重建或旧 lease 失效后,同一 HWLAB session 的恢复判定必须基于同一个
sessionId、threadId、providerProfile/backendProfile、AgentRunSessionRef和 PVC。replacement run/job 只能作为恢复执行壳;Cloud API 仍要把它映射为同一业务 session 的后续 turn,并在 trace/result 中分离业务 session identity 与执行 run/job identity。长期目标仍是在 runner reuse window 内复用同一 AgentRun run/runner。 - Cloud API 通过 AgentRun v0.1
runner-jobs.transientEnv传递本次 Code Agent turn 的短期上下文,例如HWLAB_RUNTIME_*、HWLAB_CODE_AGENT_ASSEMBLED_RUNTIME和映射到当前 session owner 的HWLAB_API_KEY。transientEnv不设固定 8 项上限,新增短期上下文时必须按 name 去重、只传本次 Job 需要的 value;HWLAB_RUNTIME_API_URL必须指向当前 namespace 内的hwlab-cloud-apiService,HWLAB_RUNTIME_WEB_URL才指向hwlab-cloud-web;HWLAB_API_KEY必须对应当前agent_sessions.owner_user_id,并继续禁止承载 GitHub token、provider key、长期 SSH key 或其他无关 credential;文档、日志和 trace 只允许保留脱敏后的 name、来源或摘要,不打印 Secret 值。 - 同 Pod sidecar
hwlab-codex-api-forwarder监听127.0.0.1:49280/responses,用于codex-apiprofile 直连 hyueapi,并保持 hyueapi 在NO_PROXY中。 hwlab-code-agent-workspacePVC 挂载到/workspace/hwlab,用于长会话 workspace;它是 cloud-api 运行资源,不是独立用户入口。
API 接口说明
| 接口 | 说明 |
|---|---|
GET /health、GET /health/live |
返回 service identity、environment、revision、DB/runtime/Code Agent readiness 和 blocker。 |
GET /live |
轻量 live 标记。 |
GET /v1 |
REST adapter 索引、RPC 方法、runtime readiness 和 device-pod/M3 能力摘要。 |
POST /rpc、POST /json-rpc |
JSON-RPC 入口,支持 system、adapter、gateway、hardware、audit、evidence 和 M3 方法。 |
POST /v1/rpc/{method} |
REST 到 JSON-RPC 的桥接入口。 |
GET /v1/device-pods... |
经 cloud-api 鉴权后读取服务端 profile/grant/job authority;probe GET 会创建只读 device job 并经 hwlab-device-pod executor/gateway 执行或返回同源 blocker,不会回退到 fake device pod 数据。 |
GET /auth/oidc/login、GET /auth/oidc/callback、GET /auth/session、POST /auth/logout |
Keycloak OIDC、Web session 24 小时轮换和 logout 入口,最终规格见 spec-v02-auth.md。 |
POST /auth/login |
本地账号密码 bootstrap/legacy fallback;目标 Web/CLI 登录不依赖该入口。 |
GET /v1/auth/session、GET /v1/users/me、GET /v1/access/status、GET /v1/setup/status |
v0.2 用户/session/setup 的 REST 状态和兼容入口;响应不得暴露 password hash、session token 原文或 Secret 值。 |
GET/POST /v1/api-keys... |
用户 API key 管理入口;CLI 和 AgentRun runner 内 hwpod 都使用 HWLAB_API_KEY,映射到用户后再按权限表授权。 |
POST /v1/admin/users、POST/PUT /v1/admin/device-pods、POST/DELETE /v1/admin/device-pod-grants... |
admin 管理用户、device pod profile 和 grant 的入口。 |
GET/PATCH /v1/workbench/workspace、POST /v1/workbench/workspace/{id}/reset、GET /events |
账号级共享 workspace authority;所有读写按 ownerUserId 隔离,写入使用 revision 观测冲突,active trace 只表示最近活动/当前选中 trace,不作为同账号 Code Agent 并发互斥锁。 |
POST /v1/agent/sessions、GET/PATCH /v1/agent/sessions... |
显式 Code Agent session 生命周期入口;创建/选择/状态标记 session,并与账号 workspace selection 同步。 |
GET /v1/m3/status、POST /v1/m3/io |
M3 只读/受控 IO 入口;写操作必须有明确 approval。 |
GET /v1/diagnostics/gate、GET /v1/live-builds |
诊断和 live build inventory。 |
GET /v1/gateway/sessions、POST /v1/gateway/poll、POST /v1/gateway/result |
gateway 主动出站注册、取任务和回传结果。 |
POST /v1/internal/device-pod/gateway-dispatch |
仅接受 hwlab-device-pod 内部服务凭据,用于把 executor job dispatch 到 gateway poll/result;普通用户和 Code Agent 不可调用。 |
POST /v1/agent/chat、POST /v1/agent/chat/steer、GET /v1/agent/chat/result/{traceId}、GET /v1/agent/chat/trace/{traceId}、POST /v1/agent/chat/cancel |
Code Agent 短连接提交、运行中 steer、轮询、trace 和取消;普通 chat 必须绑定显式 usable session。 |
/v1/live-builds 语义
/v1/live-builds 返回的是运行面服务清单,不是 Cloud Web 专属 health。latest 字段按所有 HWLAB runtime service 的 build time 排序,可能指向 hwlab-cloud-api、hwlab-cloud-web、hwlab-agent-skills 或其他本轮最近滚动的服务;当 API 比 Web 更新时,latest.serviceId=hwlab-cloud-api 是正常状态,不能据此判断 Cloud Web 构建时间缺失或 Web rollout 失败。
需要验证 Cloud Web 时必须读取 services[] 中 serviceId=hwlab-cloud-web 的行,并区分 build.createdAt、image.tag/digest、commit.id、revision 和 build.liveMetadataMatch。/health/live 只能证明当前服务 health/revision;Cloud Web 顶部 build chip 和详情弹窗展示的构建时间、env image 和实际 runtime commit 以 /v1/live-builds 的对应 service row 为准。
登录鉴权 API 的最终规格见 spec-v02-auth.md;用户、权限、device-pod 管理 API 的最终规格见 spec-user-access.md 和 spec-device-pod.md。
测试规格
T1
阅读 docs/reference/spec-v02-hwlab-cloud-api.md,然后用 cli 手动测试以下内容:访问 http://74.48.78.17:19667/health/live,确认 environment=v02、ready=true、DB runtime 为 Postgres,且响应不包含 Secret 值。
T2
阅读 docs/reference/spec-v02-hwlab-cloud-api.md,然后用 cli 手动测试以下内容:先显式创建 Code Agent session,再使用短连接 POST /v1/agent/chat 绑定该 session 提交一次对话,并轮询 /v1/agent/chat/result/{traceId};只有 status=completed 且 assistant reply 非空才算 Code Agent 通过。未绑定 session 的普通 chat 必须返回 session_required。对运行中请求使用 POST /v1/agent/chat/steer 时,响应必须包含 target trace、steerTraceId、AgentRun runId/targetCommandId/steerCommandId 和继续观察原 trace 的 result/trace URL。
T2.1
阅读 docs/reference/spec-v02-hwlab-cloud-api.md,然后用 cli 手动测试以下内容:在同一个显式 conversationId/sessionId/threadId 中先发起一轮会产生可见 assistant/tool 进展的 Code Agent 请求并取消,再发送“回答一下刚才调查结果”这类后续消息;如果 session 仍 usable,第二轮必须继续使用同一个标准 threadId,且 trace/result 不能混入上一 command 的尾部事件。如果取消导致 session failed/stale,API 必须拒绝继续并要求显式创建新 session,不能自动滚动。
T2.2
阅读 docs/reference/spec-v02-hwlab-cloud-api.md,然后用 cli 手动测试以下内容:在同一个显式 conversationId/sessionId/threadId 中先完成一轮“看看 device-pod 可用性?”这类 Code Agent 请求,再发送“总结我们刚才的对话内容”;第二轮 AgentRun command 必须只包含本轮原始 message/prompt、同一个标准 threadId 和必要运行元数据,不得包含 conversationContext/messages 或历史 prompt 拼接。assistant reply 必须通过 Codex stdio 原生 thread/resume 记住第一轮,不能回答“这是本会话第一条消息”或等价的新会话结论;若 thread/resume 失败,应以 thread-resume-failed 终止并标记 session failed/stale,继续前必须显式创建新 session。
T3
阅读 docs/reference/spec-v02-hwlab-cloud-api.md,然后用 cli 手动测试以下内容:未登录访问 /v1/device-pods 必须返回认证错误;登录后访问 device-pod list/status 时必须显示 contractVersion=device-pod-authority-v1 和 fake=false 来源,不得出现 fake fallback。
规格的实现情况
| 规格项 | 状态 | 说明 |
|---|---|---|
| health/readiness | 已实现 | /health/live 汇总 DB、runtime、Code Agent 和 blocker。 |
| Code Agent 短连接 submit/steer/result/trace/cancel | 已实现 | repo-owned Codex stdio、运行中 steer 和 provider profile 已接入。 |
| 显式 Code Agent session 生命周期 | 目标状态 | /v1/agent/sessions* 管理 session create/select/status;/v1/agent/chat 无 session 时返回 session_required,失败 session 不自动滚动。 |
| Postgres durable runtime | 已实现 | 通过 v02 独立 DB SecretRef 和 migration ledger 判定。 |
| gateway outbound poll/result | 已实现 | 支持 gateway 主动轮询和 hardware.invoke.shell 分发。 |
| device-pod 正式权限/profile/job | 部分实现 | profile/grant/list/status/job 持久化在 cloud-api;用户态 probe GET 已收敛为只读 job;已提供内部 gateway dispatch route 供 hwlab-device-pod executor 下发到 device-host-cli,无在线 gateway/device-host-cli 时返回 blocker。 |
| v0.2 登录鉴权与 admin/user 权限模型 | 部分实现 | 当前 /auth/* 是本地账号密码和 7 天 session;Keycloak OIDC、24 小时 Web session、CLI API key 和 AuthPrincipal 归一仍需按 spec-v02-auth 收敛。admin user/device-pod/grant API 和 Code Agent owner binding 已接入;生产 bootstrap 依赖 SecretRef。 |
| 账号共享 workspace authority | 已实现 | account_workspaces 持久化同账号 Web/CLI 共享 workspace,支持 revision 冲突可见性、账号隔离、最近 active trace 记录和 reset;同一用户不同 session/run 允许并发,互斥只在 session/thread/run 层处理。 |