From 526faff3f259b709fe6c4ad532a62ee401c83b85 Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 29 May 2026 18:05:05 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=90=8C=E6=AD=A5=20v0.1=20backend=20p?= =?UTF-8?q?rofile=20=E8=A7=84=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 7 +-- docs/reference/architecture.md | 10 ++-- docs/reference/spec-v01-agentrun-mgr.md | 9 ++-- docs/reference/spec-v01-agentrun-runner.md | 11 ++-- docs/reference/spec-v01-backend-adapter.md | 28 +++++++--- docs/reference/spec-v01-backend-codex.md | 52 ++++++++++++++----- docs/reference/spec-v01-cicd.md | 2 +- docs/reference/spec-v01-cli.md | 10 +++- .../spec-v01-documentation-governance.md | 4 +- .../reference/spec-v01-secret-distribution.md | 39 +++++++++----- docs/reference/spec-v01-services.md | 28 +++++++--- docs/reference/spec-v01-validation.md | 23 ++++++-- 12 files changed, 161 insertions(+), 62 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b60902b..da0fc1f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -42,8 +42,9 @@ AgentRun 是面向 UniDesk 与 HWLAB 的共享 Agent 执行基础设施。本仓 ## Critical v0.1 Implementation Stack Rule - P0: AgentRun `v0.1` 自研 runtime、CLI、manager、runner、backend adapter、Codex backend 和后续 scheduler 的优先实现语言是 Bun + TypeScript;官方 TypeScript CLI 入口是 `scripts/agentrun-cli.ts`,G14/CI/人工非交互命令使用 `./scripts/agentrun` 启动同一入口,复杂逻辑拆入 `scripts/src/` 和 `src/`。 -- P0: `backendProfile=codex` 必须通过 Codex CLI app-server stdio 协议执行,启动受控 `codex app-server --listen stdio://`,使用 JSON-RPC 方法 `initialize`、`thread/start` 或 `thread/resume`、`turn/start`;不得在 `v0.1` 把 Codex backend 实现为直接 Responses HTTP 代理、文本 fallback 或 fake provider。 -- P0: 实现 Codex backend 前必须参考 UniDesk Code Queue 的 `src/components/microservices/code-queue/src/code-agent/codex.ts`、`common.ts`,以及 HWLAB 的 `internal/cloud/codex-stdio-session.mjs`、`scripts/code-agent-chat-smoke.mjs`;复用协议、redaction、trace、failure 分类和 Secret projection 经验,不复制环境专用路径或明文密钥。 +- P0: `backendProfile=codex` 与 `backendProfile=deepseek` 都必须通过同一个 Codex CLI app-server stdio backend kind 执行,启动受控 `codex app-server --listen stdio://`,使用 JSON-RPC 方法 `initialize`、`thread/start` 或 `thread/resume`、`turn/start`;DeepSeek 是 profile/config/SecretRef 选择,不是直接 Responses HTTP 代理、独立 fake provider 或文本 fallback。 +- P0: `codex` 与 `deepseek` profile 必须使用 profile-scoped SecretRef 和 writable `CODEX_HOME`,不得互相 fallback、复用运行态文件或污染默认 `codex` profile;切换顺序必须可验证为 `codex -> deepseek -> codex` 均独立。 +- P0: 实现 Codex stdio backend/profile 前必须参考 UniDesk Code Queue 的 `src/components/microservices/code-queue/src/code-agent/codex.ts`、`common.ts`,以及 HWLAB 的 `internal/cloud/codex-stdio-session.mjs`、`scripts/code-agent-chat-smoke.mjs`、`docs/reference/spec-v02-deepseek-proxy.md`、`docs/reference/code-agent-chat-readiness.md`;复用协议、redaction、trace、failure 分类、profile overlay 和 Secret projection 经验,不复制环境专用路径或明文密钥。 ## 长期参考文档 @@ -56,7 +57,7 @@ AgentRun 是面向 UniDesk 与 HWLAB 的共享 Agent 执行基础设施。本仓 - `docs/reference/spec-v01-agentrun-mgr.md`:v0.1 manager REST API、tenant boundary、runner claim 和 event/status authority。 - `docs/reference/spec-v01-agentrun-runner.md`:v0.1 短生命周期 runner、claim/poll/report、日志和 failureKind。 - `docs/reference/spec-v01-backend-adapter.md`:v0.1 backend adapter 合同、event normalization、failure mapping 和 redaction。 -- `docs/reference/spec-v01-backend-codex.md`:v0.1 第一真实 Codex backend、`~/.codex` 测试凭据 Secret projection 和真实 turn 验收。 +- `docs/reference/spec-v01-backend-codex.md`:v0.1 Codex app-server stdio backend、`codex`/`deepseek` profile、`~/.codex` 测试凭据 Secret projection 和真实 turn 验收。 - `docs/reference/spec-v01-cli.md`:v0.1 AgentRun CLI 命令族、JSON 输出、短返回和日志可见。 - `docs/reference/spec-v01-scheduler.md`:v0.1 自动 scheduler 的 deferred 边界。 - `docs/reference/architecture.md`:AgentRun 产品边界、服务架构、MVP 阶段、RESTful API 模型和数据模型。 diff --git a/docs/reference/architecture.md b/docs/reference/architecture.md index 473ef29..84944ba 100644 --- a/docs/reference/architecture.md +++ b/docs/reference/architecture.md @@ -21,7 +21,7 @@ UniDesk 与 HWLAB 是 tenant/client。UniDesk 负责平台入口、provider 清 - `projectId`,例如 `pikasTech/unidesk` 或 `pikasTech/HWLAB`; - `workspaceRef`,用于定位 source/worktree/workspace; - `providerId`,例如 `G14` 或 `D601`; -- `backendProfile`,例如 `codex`、`opencode`、`claudecode`、`host-native` 或 `windows-native`; +- `backendProfile`,`v0.1` allowlist 为 `codex` 与 `deepseek`;后续可以扩展 `opencode`、`claudecode`、`host-native` 或 `windows-native`; - `executionPolicy`,包含 sandbox、approval、timeout、network 和 secret scope; - `traceSink`,说明标准化 event 镜像到哪里。 @@ -51,9 +51,9 @@ Backend adapter 隐藏具体工具协议。Codex stdio JSON-RPC、OpenCode JSON AgentRun `v0.1` 自研 runtime 优先使用 Bun + TypeScript:manager、runner、backend adapter、Codex backend、CLI 和后续 scheduler 都按这一技术栈实现。`scripts/agentrun-cli.ts` 是官方 CLI 入口;复杂 CLI 逻辑进入 `scripts/src/`,服务和 runner 逻辑进入 `src/`。YAML manifest、Tekton/Argo CD 配置、Postgres 和 Kubernetes 仍按各自原生生态管理。 -Codex backend 固定采用 Codex CLI app-server JSON-RPC over stdio。实现必须启动受控 `codex app-server --listen stdio://`,执行 `initialize`、`thread/start` 或 `thread/resume`、`turn/start`,并把 stdout/stderr、notification、tool lifecycle、assistant output 和 terminal/error 状态归一化为 AgentRun events。直接 Responses HTTP、OpenAI SDK wrapper、`codex exec` 一次性输出或文本 fallback 不能作为 `v0.1` Codex backend 的正式执行路径。 +Codex stdio backend 固定采用 Codex CLI app-server JSON-RPC over stdio。实现必须启动受控 `codex app-server --listen stdio://`,执行 `initialize`、`thread/start` 或 `thread/resume`、`turn/start`,并把 stdout/stderr、notification、tool lifecycle、assistant output 和 terminal/error 状态归一化为 AgentRun events。`codex` 与 `deepseek` 是同一个 backend kind 下的 profile/config/SecretRef 选择;直接 Responses HTTP、OpenAI SDK wrapper、`codex exec` 一次性输出或文本 fallback 不能作为 `v0.1` Codex backend 的正式执行路径。 -实现参考优先级:UniDesk Code Queue 的 `src/components/microservices/code-queue/src/code-agent/codex.ts`、`common.ts`,以及 HWLAB v0.2 的 `internal/cloud/codex-stdio-session.mjs`、`scripts/code-agent-chat-smoke.mjs`。AgentRun 复用其协议、trace、redaction、Secret projection 和 failure 分类经验,但不复制 tenant 业务规则、环境专用路径或密钥材料。 +实现参考优先级:UniDesk Code Queue 的 `src/components/microservices/code-queue/src/code-agent/codex.ts`、`common.ts`,以及 HWLAB v0.2 的 `internal/cloud/codex-stdio-session.mjs`、`scripts/code-agent-chat-smoke.mjs`、`docs/reference/spec-v02-deepseek-proxy.md`、`docs/reference/code-agent-chat-readiness.md`。AgentRun 复用其协议、trace、redaction、Secret projection、profile overlay、DeepSeek/Moon Bridge 分层诊断和 failure 分类经验,但不复制 tenant 业务规则、环境专用路径、bridge host、namespace 或密钥材料。 ## MVP 顺序 @@ -69,7 +69,7 @@ AgentRun 必须按纵向切片推进,不要一开始大规模并行开发。 - `Runner` - `Backend` -第一切片只要求 `turn`、`interrupt`、`status` 和分页 `events`。不要一开始就做 `steer`、`resume`、judge/retry、UI、多 backend 路由或自动调度。 +第一切片只要求 `turn`、`interrupt`、`status` 和分页 `events`。不要一开始就做 `steer`、`resume`、judge/retry、UI、跨 backend kind 的自动路由或自动调度。`v0.1` 可做同一 Codex stdio backend kind 下的显式 profile 选择。 ### M1: 最小 Runner 加一个 Backend @@ -224,7 +224,7 @@ Control-plane service 应是长驻服务;runner 应是短生命周期 Job 或 - 迁移 UniDesk Code Queue; - 全局替换 HWLAB Code Agent; -- 多 backend 路由; +- 跨 backend kind 的自动多 backend 路由; - 最小诊断之外的 UI; - judge/retry 自动化; - 自动扩缩容; diff --git a/docs/reference/spec-v01-agentrun-mgr.md b/docs/reference/spec-v01-agentrun-mgr.md index 068d335..897a2af 100644 --- a/docs/reference/spec-v01-agentrun-mgr.md +++ b/docs/reference/spec-v01-agentrun-mgr.md @@ -61,7 +61,7 @@ POST /api/v1/commands/:commandId/ack | `projectId` | 必填,例如 `pikasTech/unidesk`、`pikasTech/HWLAB`。 | | `workspaceRef` | 必填,描述 source/worktree/workspace,不由 runner 猜测。 | | `providerId` | 必填,例如 `G14`、`D601`;只表示目标 provider,不直接授予业务权限。 | -| `backendProfile` | 必填,`v0.1` 默认真实 backend 为 `codex`。 | +| `backendProfile` | 必填,`v0.1` allowlist 为 `codex` 与 `deepseek`;两者共享 Codex stdio backend kind。 | | `executionPolicy` | 必填或由 manager 显式补齐默认值,至少包含 sandbox、approval、timeout、network 和 secretScope。 | | `traceSink` | 字段必须存在;可以为 `null` 或显式 sink。 | @@ -71,10 +71,10 @@ POST /api/v1/commands/:commandId/ack `v0.1` 不实现独立 policy engine。Manager 只做基础边界收敛: -- 校验 tenant/project/provider/backend 是否在 `v0.1` 允许集合内。 +- 校验 tenant/project/provider/backendProfile 是否在 `v0.1` 允许集合内;当前 backendProfile 允许 `codex` 与 `deepseek`。 - 校验 workspaceRef 形态存在且与 tenant 请求一致;不替 tenant 判断某个 repo 操作是否业务授权。 - 校验 executionPolicy 不扩大 sandbox、network、approval、timeout 和 secretScope。 -- 校验 secretScope 只引用 [spec-v01-secret-distribution.md](spec-v01-secret-distribution.md) 中允许的 SecretRef。 +- 校验 secretScope 只引用 [spec-v01-secret-distribution.md](spec-v01-secret-distribution.md) 中允许的 SecretRef,且存在与 `backendProfile` 同名的 provider credential;manager 只校验引用形态,不读取 Secret 值。 - 对 HWLAB live device mutation、UniDesk production deploy、GitHub issue/PR 写入等业务授权,Manager 只记录字段和审计事件,不把业务规则硬编码成通用门禁。 ## 最小 Observability 合同 @@ -93,7 +93,7 @@ POST /api/v1/commands/:commandId/ack ### T2 Run schema 与 tenant boundary -阅读本文和 [spec-v01-services.md](spec-v01-services.md),然后调用 `POST /api/v1/runs` 创建包含 tenant/project/workspace/provider/backend/execution/trace 字段的 run。确认缺失字段、非法 tenant、非法 backend 或扩大 secretScope 都返回结构化 failureKind,合法请求持久化后可用 `GET /api/v1/runs/:runId` 查询。 +阅读本文和 [spec-v01-services.md](spec-v01-services.md),然后调用 `POST /api/v1/runs` 创建包含 tenant/project/workspace/provider/backend/execution/trace 字段的 run。确认缺失字段、非法 tenant、非法 backend、`backendProfile=deepseek` 但缺少 matching provider credential、或扩大 secretScope 都返回结构化 failureKind,合法请求持久化后可用 `GET /api/v1/runs/:runId` 查询。 ### T3 Command idempotency @@ -110,5 +110,6 @@ POST /api/v1/commands/:commandId/ack | `agentrun-mgr` 服务规格 | 已定义 | 本文为 v0.1 manager 权威。 | | Manager REST API | 已实现/已通过主闭环 | 已有 run、command、event、backends、runner register、claim、lease heartbeat、poll、ack、status、runner Job 创建和 health/readiness 的 HTTP JSON API;真实 runtime 已通过 RESTful API 主闭环。 | | Tenant policy boundary | 已实现最小边界 | v0.1 已做 schema、tenant/backend allowlist、executionPolicy 和 secretScope 结构校验;业务授权仍由 UniDesk/HWLAB 自己判定。 | +| `deepseek` backendProfile allowlist | 已定义/待实现 | 需要扩展 manager validation、backend capability 和 matching SecretRef 校验。 | | Postgres durable adapter | 已实现/已通过主闭环 | live runtime 通过 `DATABASE_URL` 使用 Postgres durable store;memory store 仅用于显式 self-test/dev。见 [spec-v01-postgres.md](spec-v01-postgres.md)。 | | Observability 最小合同 | 已实现主路径 | events append-only、terminal status、failureKind、health/readiness store 状态、runner claim/lease/backend events 和 Secret/DSN redaction 已进入 manager;集中 trace 和部署级观测仍属后续工作。 | diff --git a/docs/reference/spec-v01-agentrun-runner.md b/docs/reference/spec-v01-agentrun-runner.md index b566ad4..a480bb4 100644 --- a/docs/reference/spec-v01-agentrun-runner.md +++ b/docs/reference/spec-v01-agentrun-runner.md @@ -27,7 +27,7 @@ Runner 启动参数必须显式包含: Runner Secret 只能通过 Kubernetes Secret projection、ServiceAccount/RBAC 或受控 Secret API 读取获得。Codex 测试凭据投影规则见 [spec-v01-secret-distribution.md](spec-v01-secret-distribution.md) 和 [spec-v01-backend-codex.md](spec-v01-backend-codex.md)。 -Kubernetes Job runner 必须把 credential source 与 runtime home 分开:Secret volume 只读挂在 `/var/run/agentrun/secrets/...`,`/home/agentrun` 由 `emptyDir` 提供可写空间,`CODEX_HOME` 指向 `/home/agentrun/.codex`,`AGENTRUN_CODEX_SECRET_HOME` 指向只读 projection。runner/backend 在启动 provider 前只复制授权文件,不打印内容。 +Kubernetes Job runner 必须把 credential source 与 runtime home 分开:Secret volume 只读挂在 `/var/run/agentrun/secrets/...`,`/home/agentrun` 由 `emptyDir` 提供可写空间,`CODEX_HOME` 指向当前 run/profile 的 writable runtime home,`AGENTRUN_CODEX_SECRET_HOME` 指向当前 `backendProfile` 对应的只读 projection。runner/backend 在启动 provider 前只复制授权文件,不打印内容。`codex` 与 `deepseek` profile 不得共享同一个可写 runtime home,除非它们运行在不同的 per-run Kubernetes Job 且该目录由 Job 独占 emptyDir 提供。 Kubernetes Job runner 必须设置有限保留时间。`v0.1` 默认 `ttlSecondsAfterFinished=86400`,用于保留最近完成 Job 的调试窗口,同时避免长期堆积 `Completed` runner Job 污染运行面观察。该 TTL 是 Job manifest 的运行面属性,不是 CI/CD 门禁;需要延长保留时间时必须通过受控 Job render/input 显式覆盖,并在 issue 或 PR 中说明原因。 @@ -48,7 +48,7 @@ claimed -> lease_lost - runner 必须先 register,再 claim run;claim 失败不能继续调用 backend。 - lease heartbeat 必须可观察;过期或冲突时写入 failure event 或明确退出原因。 - command 只能从 manager poll;不得从本地文件或临时参数伪造正式 command。 -- backend 产生的所有可见输出必须先经过 adapter normalization 和 redaction,再 append 到 manager。 +- backend 产生的所有可见输出必须先经过 adapter normalization 和 redaction,再 append 到 manager;backend_status 至少包含 redacted profile/backendKind/protocol 摘要。 - terminal status 上报后 runner 可以退出;退出码与 terminal status 必须一致或在日志中可解释。 ## Manager API 交互 @@ -97,7 +97,11 @@ Runner 日志必须实时 flush 到文件或 pod log,CLI 启动 runner 时必 ### T4 Missing Secret failure -阅读本文和 [spec-v01-secret-distribution.md](spec-v01-secret-distribution.md),然后用缺失 Codex SecretRef 的 run 启动 runner。确认 runner 不调用 provider,run 失败为 `secret-unavailable` 或等价 failureKind,日志和事件不泄露 Secret 值。 +阅读本文和 [spec-v01-secret-distribution.md](spec-v01-secret-distribution.md),然后分别用缺失 `codex` SecretRef 与缺失 `deepseek` SecretRef 的 run 启动 runner。确认 runner 不调用 provider,run 失败为 `secret-unavailable` 或等价 failureKind,不 fallback 到另一个 profile,日志和事件不泄露 Secret 值。 + +### T5 Profile switching + +阅读本文和 [spec-v01-backend-codex.md](spec-v01-backend-codex.md),然后按 `codex -> deepseek -> codex` 顺序启动三个真实 runner Job。确认每个 Job 只挂载和复制当前 profile 的 SecretRef,`CODEX_HOME` 互相隔离,且前后两个 `codex` run 不受 `deepseek` run 的 config/model/upstream 影响。 ## 规格的实现情况 @@ -108,3 +112,4 @@ Runner 日志必须实时 flush 到文件或 pod log,CLI 启动 runner 时必 | host process runner | 已实现 | `runner start` 和 `src/runner/main.ts` 进入同一套 `runOnce`,可通过 manager register/claim/poll/report 执行自测试。 | | claim/lease/report client | 已实现 | 已拆出 runner manager API client,覆盖 register、claim、lease heartbeat、poll command、ack、append event 和 terminal status;live runtime 通过 manager 写入 Postgres durable store。 | | runner redaction | 已实现主路径 | runner/backend event 和 Job 输出使用 redaction;复杂审计仍按 [spec-v01-validation.md](spec-v01-validation.md) 的人工验收抽查。 | +| `deepseek` profile runner selection | 已定义/待实现 | 需要按 run `backendProfile` 选择 matching SecretRef、projection、`CODEX_HOME` 和 backend metadata。 | diff --git a/docs/reference/spec-v01-backend-adapter.md b/docs/reference/spec-v01-backend-adapter.md index 604d5f1..2fa4ad7 100644 --- a/docs/reference/spec-v01-backend-adapter.md +++ b/docs/reference/spec-v01-backend-adapter.md @@ -4,7 +4,7 @@ Backend adapter 是 runner 与具体 Code Agent 工具之间的适配层。它 ## 在系统中的职责划分 -- 根据 `backendProfile` 选择具体 backend 实现;`v0.1` 必须至少证明一个真实 Agent backend,默认是 `codex`。 +- 根据 `backendProfile` 选择具体 backend profile;`v0.1` 必须支持 `codex` 与 `deepseek`,两者共享同一个 `codex-app-server-stdio` backend kind。 - 接收 manager 持久化后的 run、command 和 executionPolicy;不得自行扩大 workspace、network、approval 或 secret scope。 - 调用具体 backend,并把 backend 输出归一化为 AgentRun events。 - 负责 provider/auth/backend/protocol 错误到 failureKind 的映射。 @@ -24,9 +24,20 @@ finalize(executionContext) -> terminal status redact(value) -> redacted value ``` -Adapter 输入必须来自 manager 保存的 run/command 和 Kubernetes Secret projection;不得从 CLI 参数、临时环境变量或 Git 文件读取 provider credential 明文。 +Adapter 输入必须来自 manager 保存的 run/command 和 Kubernetes Secret projection;不得从 CLI 参数、临时环境变量或 Git 文件读取 provider credential 明文。`resolveProfile(profile)` 必须返回 profile、backendKind、protocol、transport、command、requiredSecretKeys 和 isolation policy;不得把 unknown profile 静默映射到默认 `codex`。 -`v0.1` 的第一真实 adapter 是 Codex adapter。它必须走 Codex CLI app-server JSON-RPC over stdio;adapter 合同把 Codex 的 thread、turn、notification、tool lifecycle 和 stderr/exit 信息归一化为 AgentRun 标准 events。 +`v0.1` 的第一真实 adapter 是 Codex stdio adapter。它必须走 Codex CLI app-server JSON-RPC over stdio;adapter 合同把 Codex 的 thread、turn、notification、tool lifecycle 和 stderr/exit 信息归一化为 AgentRun 标准 events。`codex` 与 `deepseek` 只是该 adapter 的 profile/config/SecretRef 选择,不允许复制两套协议实现。 + +## Backend Profile Registry + +`GET /api/v1/backends` 和 adapter 内部 registry 至少报告以下 profile: + +| profile | backendKind | protocol | transport | command | v0.1 状态 | +| --- | --- | --- | --- | --- | --- | +| `codex` | `codex-app-server-stdio` | `codex-app-server-jsonrpc-stdio` | `stdio` | `codex app-server --listen stdio://` | 已有主闭环,必须保持默认兼容。 | +| `deepseek` | `codex-app-server-stdio` | `codex-app-server-jsonrpc-stdio` | `stdio` | `codex app-server --listen stdio://` | 待实现 profile;实现后必须用独立 SecretRef 和 `CODEX_HOME` 真实联调。 | + +Registry 只表达能力和选择边界,不读取 Secret 值。Manager 负责校验 `backendProfile` 是否在 allowlist 内,并校验 `executionPolicy.secretScope.providerCredentials` 是否存在匹配 profile 的 SecretRef;runner 只为当前 run 选择的 profile 准备 Secret projection 和 runtime home。 ## 标准事件 @@ -79,14 +90,19 @@ Adapter 必须把 backend 错误映射为稳定 failureKind: ### T3 真实 backend 联调 -阅读本文、[spec-v01-backend-codex.md](spec-v01-backend-codex.md) 和 [spec-v01-validation.md](spec-v01-validation.md),然后用真实 Codex backend 完成一个最短 turn。确认 adapter 输出真实 assistant/backend_status/terminal_status events,且没有 Secret 泄露。 +阅读本文、[spec-v01-backend-codex.md](spec-v01-backend-codex.md) 和 [spec-v01-validation.md](spec-v01-validation.md),然后分别用 `backendProfile=codex` 与 `backendProfile=deepseek` 完成真实最短 turn。确认 adapter 输出真实 assistant/backend_status/terminal_status events,事件中包含 profile/backendKind/protocol 摘要,且没有 Secret 泄露。 + +### T4 Profile isolation 自测试 + +阅读本文,然后用 fake Codex app-server 和两个不同的 profile Secret fixture 做自测试。确认 adapter 只选择 run 指定 profile 的 SecretRef 和 `CODEX_HOME`,`deepseek` 缺失时失败为 `secret-unavailable`,不会 fallback 到 `codex`。 ## 规格的实现情况 | 规格项 | 状态 | 说明 | | --- | --- | --- | | Backend adapter 合同 | 已定义 | 本文为 v0.1 adapter 权威。 | -| 通用 adapter 模块 | 已实现最小形态 | `src/backend/adapter.ts` 作为 runner 进程内 adapter 入口,`v0.1` 只路由真实 `codex` profile;多 backend 路由仍 deferred。 | +| 通用 adapter 模块 | 已实现最小形态/待扩展 profile | `src/backend/adapter.ts` 作为 runner 进程内 adapter 入口;当前已路由真实 `codex` profile,仍需扩展 `deepseek` profile 但不应复制第二套 stdio 协议实现。 | | event normalization | 已实现主路径 | Codex backend 已把 backend_status、assistant_message、tool_call、command_output、error 和 terminal_status 归一化为 manager events;复杂事件审计按人工验收抽查。 | | failure mapping | 已实现主路径 | Codex backend 已覆盖 missing secret、auth/rate/availability、protocol、JSON parse、invalid response、spawn、timeout 和 cancel 分类;真实负向场景按 [spec-v01-validation.md](spec-v01-validation.md) T7 手动验收。 | -| 多 backend 路由 | Deferred | v0.1 只要求一个真实 backend 闭环。 | +| `deepseek` profile | 已定义/待实现 | v0.1 要求作为同一 Codex stdio backend kind 的 profile 进入 registry、validation、runner secret selection 和综合联调。 | +| 多 backend 路由 | Deferred | 跨 backend kind 的自动路由和 scheduler capacity selection 不进入 v0.1。 | diff --git a/docs/reference/spec-v01-backend-codex.md b/docs/reference/spec-v01-backend-codex.md index ba0b7bc..2d71a33 100644 --- a/docs/reference/spec-v01-backend-codex.md +++ b/docs/reference/spec-v01-backend-codex.md @@ -1,18 +1,18 @@ -# v0.1 Codex Backend 规格 +# v0.1 Codex Stdio Backend/Profile 规格 -Codex backend 是 AgentRun `v0.1` 的第一真实 Code Agent backend 候选。它用于证明 runner、backend adapter、Kubernetes Secret projection、真实 provider 调用、event normalization 和 terminal status 的完整闭环。 +Codex stdio backend 是 AgentRun `v0.1` 的第一真实 Code Agent backend kind。它用于证明 runner、backend adapter、Kubernetes Secret projection、真实 provider 调用、event normalization 和 terminal status 的完整闭环。`v0.1` 在同一个 backend kind 下支持 `codex` 与 `deepseek` 两个 profile;两者共享 Codex CLI app-server stdio 协议,只通过 profile/config/SecretRef 隔离上游和模型。 ## 在系统中的职责划分 -- 作为 `backendProfile=codex` 的具体实现。 +- 作为 `backendProfile=codex` 与 `backendProfile=deepseek` 的共同具体实现。 - 使用真实 Codex/Codex-compatible 配置执行最短 turn,不使用 fake provider 作为综合联调通过证据。 -- 消费 Kubernetes Secret projection 提供的 Codex 凭据文件。 +- 消费 Kubernetes Secret projection 提供的 profile 专属 Codex `auth.json` 与 `config.toml`。 - 把 Codex 输出归一化为 AgentRun 标准 events 和 terminal status。 - 将 provider/auth/protocol/timeout/cancel 错误映射为 [spec-v01-backend-adapter.md](spec-v01-backend-adapter.md) 定义的 failureKind。 ## 协议选型与实现参考 -`v0.1` Codex backend 的协议固定为 Codex CLI app-server JSON-RPC over stdio。Backend adapter 必须启动受控子进程: +`v0.1` Codex stdio backend 的协议固定为 Codex CLI app-server JSON-RPC over stdio。Backend adapter 必须启动受控子进程: ```bash codex app-server --listen stdio:// @@ -20,7 +20,7 @@ codex app-server --listen stdio:// Adapter 通过 stdin 写入换行分隔 JSON-RPC 请求,通过 stdout 逐行读取 JSON-RPC response 和 notification,stderr 只作为有界诊断日志。最小请求序列是 `initialize`、`thread/start` 或 `thread/resume`、`turn/start`;response 中必须提取 thread/turn identity,notification 和后续输出必须归一化为 `backend_status`、`assistant_message`、`tool_call`、`command_output`、`error` 和 `terminal_status` events。 -不得把以下路径作为 `v0.1` Codex backend 的正式实现或综合联调通过证据:直接 Responses HTTP 代理、OpenAI SDK wrapper、`codex exec` 一次性命令输出、fake provider、固定文本回复、只读 shortcut 或本地 shell 模拟。裸 HTTP 或 `codex exec --json` 可以作为 provider/upstream 诊断,但最终通过必须来自 app-server stdio turn。 +不得把以下路径作为 `v0.1` Codex stdio backend 的正式实现或综合联调通过证据:直接 Responses HTTP 代理、OpenAI SDK wrapper、`codex exec` 一次性命令输出、fake provider、固定文本回复、只读 shortcut 或本地 shell 模拟。裸 HTTP 或 `codex exec --json` 可以作为 provider/upstream 诊断,但最终通过必须来自 app-server stdio turn。 实现必须参考成熟代码: @@ -30,30 +30,49 @@ Adapter 通过 stdin 写入换行分隔 JSON-RPC 请求,通过 stdout 逐行 | UniDesk `src/components/microservices/code-queue/src/code-agent/common.ts` | backend port/capability、model/profile 边界、文本 input shape、Git/proxy env 处理和 provider 端口归一化。 | | HWLAB `internal/cloud/codex-stdio-session.mjs` | long-lived stdio session readiness、Codex home/workspace/protocol gate、child env redaction、trace recorder、cancel/timeout/failure kind。 | | HWLAB `scripts/code-agent-chat-smoke.mjs` | fake app-server 自测试方式、`thread/start` + `turn/start` 调用顺序、session reuse、tool trace 和 Secret 不泄露断言。 | +| HWLAB `docs/reference/spec-v02-deepseek-proxy.md` | DeepSeek profile 通过稳定 bridge/Responses-compatible 入口接入,而不是把 DeepSeek 做成绕过 Codex stdio 的直接 HTTP backend。 | +| HWLAB `docs/reference/code-agent-chat-readiness.md` | provider/profile 切换时按 profile overlay、认证、网络、模型、Codex CLI/app-server 分层验证,并防止一个 profile 的成功掩盖另一个 profile 的退化。 | 这些参考用于协议和质量标准,不复制 UniDesk/HWLAB 的业务 prompt、硬件路径、tenant policy、hostPath Secret 做法或任何明文密钥。 +## v0.1 Profile 定义 + +| backendProfile | SecretRef | 配置来源 | 规则 | +| --- | --- | --- | --- | +| `codex` | `agentrun-v01-provider-codex` | operator 当前 Codex `auth.json`/`config.toml` | 现有默认 profile;实现 DeepSeek 时不得改变其默认模型、config authority 或真实联调路径。 | +| `deepseek` | `agentrun-v01-provider-deepseek` | operator 准备的 DeepSeek-compatible Codex `auth.json`/`config.toml` | 使用同一 `codex app-server --listen stdio://` 协议,通过 `config.toml` 或等价 profile overlay 指向 DeepSeek-compatible upstream/model。 | + +`deepseek` 的上游形态借鉴 HWLAB v0.2:DeepSeek 是 provider profile,通过 Responses-compatible bridge、Moon Bridge 或等价稳定服务暴露给 Codex CLI;AgentRun 不在 backend adapter 里手写 DeepSeek HTTP 转换器,也不把 DeepSeek 作为绕过 Codex app-server 的独立 backend kind。上游 base URL、模型和 provider 名称可以作为 redacted metadata 输出;API Key 和 `auth.json`/`config.toml` 原文不得输出。 + +Profile 切换规则: + +- `backendProfile` 是 run 的显式字段,manager 不得静默改写。 +- runner/backend 只读取与 `backendProfile` 同名的 provider credential;缺失则 `secret-unavailable`。 +- 每次 run 必须使用 profile-scoped writable `CODEX_HOME`。Kubernetes Job 可以把选中 profile 的 Secret projection 复制到该 Job 独占的 `/home/agentrun/.codex`;host process 或复用进程必须使用 run/profile 独占目录,避免 `codex` 与 `deepseek` 互相污染。 +- `deepseek` 不得 fallback 到 `codex` Secret、模型或 upstream;`codex` 也不得读取 `deepseek` Secret。 +- command payload 中显式提供 model 时可以透传给 Codex turn;未显式提供时以 profile `config.toml` 为 authority,不在 adapter 中写死默认模型。 + ## 测试凭据来源 -`v0.1` 综合联调用的 Codex 测试凭据源固定为 operator 环境中的以下两个文件: +`v0.1` 综合联调用的 Codex stdio profile 测试凭据源固定为 operator 环境中的以下两个文件形态: ```text ~/.codex/auth.json ~/.codex/config.toml ``` -这两个文件只能作为 Kubernetes Secret 创建或轮换的输入源,不能通过 hostPath 挂载进 Pod,不能复制进镜像,不能提交到 source branch、GitOps branch、artifact catalog、issue、PR、event、trace、日志或 CLI 输出。 +这两个文件只能作为 Kubernetes Secret 创建或轮换的输入源,不能通过 hostPath 挂载进 Pod,不能复制进镜像,不能提交到 source branch、GitOps branch、artifact catalog、issue、PR、event、trace、日志或 CLI 输出。`codex` 与 `deepseek` 可以来自不同 operator profile 目录或显式文件参数,但进入 Kubernetes 后必须是不同 SecretRef,除非后续规格明确批准某个共享 SecretRef 场景。 `v0.1` 默认 Kubernetes Secret: | 对象 | v0.1 规格 | | --- | --- | | Namespace | `agentrun-v01` | -| Secret name | `agentrun-v01-provider-codex` | +| Secret name | `agentrun-v01-provider-codex` 或 `agentrun-v01-provider-deepseek` | | Secret key | `auth.json`,来自 `~/.codex/auth.json` | | Secret key | `config.toml`,来自 `~/.codex/config.toml` | | Consumer | runner 或 backend adapter Pod | -| Projection target | 容器用户的 `~/.codex/auth.json` 和 `~/.codex/config.toml` | +| Projection target | 只读 projection,再复制到当前 run/profile 的 writable `CODEX_HOME/auth.json` 和 `CODEX_HOME/config.toml` | | File mode | 只读,建议 `0400` 或等价最小权限 | Kubernetes Secret 的创建、轮换和权限控制属于集群密钥管理流程;source branch 只声明 SecretRef 名称、key 和 mount intent。`deploy/deploy.json` 和 rendered GitOps manifest 不得包含 Secret data。 @@ -70,7 +89,7 @@ Kubernetes Secret 的创建、轮换和权限控制属于集群密钥管理流 [spec-v01-secret-distribution.md](spec-v01-secret-distribution.md) 是 SecretRef、Kubernetes projection、redaction 和 missing secret failure 的权威。本文件只定义 Codex backend 对测试凭据文件的消费方式。 -Run 的 `executionPolicy.secretScope` 应引用 `agentrun-v01-provider-codex` 的 `auth.json` 和 `config.toml`,而不是携带 provider credential 或文件内容。 +Run 的 `executionPolicy.secretScope` 应引用与 `backendProfile` 匹配的 provider SecretRef 的 `auth.json` 和 `config.toml`,而不是携带 provider credential 或文件内容。 ## 测试规格 @@ -82,6 +101,10 @@ Run 的 `executionPolicy.secretScope` 应引用 `agentrun-v01-provider-codex` 阅读本文和 [spec-v01-validation.md](spec-v01-validation.md),然后用 `backendProfile=codex` 创建真实 run 并提交一个最短 `turn` command。确认 runner 调用真实 Codex provider,manager 可查询 backend_status、assistant 或 error event、terminal_status,且 Secret value 未泄露。 +### T2b 真实 DeepSeek profile 最短 turn + +阅读本文、HWLAB v0.2 DeepSeek profile 参考和 [spec-v01-validation.md](spec-v01-validation.md),然后用 `backendProfile=deepseek` 创建真实 run 并提交一个最短 `turn` command。确认 runner 仍调用 `codex app-server --listen stdio://`,但使用 `agentrun-v01-provider-deepseek` 的 profile SecretRef 和独立 `CODEX_HOME`;manager 可查询 profile 为 `deepseek` 的 backend_status、assistant 或 error event、terminal_status,且 Secret value 未泄露。 + ### T3 Missing auth/config failure 阅读本文,然后分别移除或改名 Secret 中的 `auth.json`、`config.toml` key,启动真实 run。确认 adapter 在调用 provider 前失败为 `secret-unavailable`,failure response 为 JSON,日志不包含 Secret value。 @@ -94,13 +117,18 @@ Run 的 `executionPolicy.secretScope` 应引用 `agentrun-v01-provider-codex` 阅读本文,然后用 mock/fake Codex app-server 自测试 HTTP 503 `Service Unavailable`、携带 5xx 的 `responseStreamDisconnected`、`method=error` retry notification 中 `willRetry=true` 且嵌套 `codexErrorInfo.responseStreamDisconnected.httpStatusCode=503` 的结构,或明确 temporary/provider unavailable 文案。确认 Codex adapter 返回 `provider-unavailable`,不会落到 `backend-failed`;综合联调若真实 provider 返回同类错误,应记录为外部 provider blocker,而不是本地 runner/backend 执行面 blocker。 +### T6 Profile switching isolation + +阅读本文,然后在真实 `agentrun-v01` 运行面按顺序执行 `backendProfile=codex`、`backendProfile=deepseek`、`backendProfile=codex` 三个最短 turn。确认第二个 run 使用 DeepSeek profile,前后两个 `codex` run 仍使用原 Codex profile;三者的 event、log、backend_status、model/upstream metadata 和 failureKind 不互相污染,且任何一个 profile SecretRef 缺失都不会 fallback 到另一个 profile。 + ## 规格的实现情况 | 规格项 | 状态 | 说明 | | --- | --- | --- | -| Codex backend 规格 | 已定义 | 本文为 v0.1 第一真实 backend 权威。 | +| Codex stdio backend/profile 规格 | 已定义 | 本文为 v0.1 Codex app-server stdio backend kind 和 profile 权威。 | | Codex Secret projection | 已实现/已通过主闭环 | runner Job 使用只读 Secret projection 和 writable `CODEX_HOME`,Codex 测试凭据来自 `agentrun-v01-provider-codex` 的 `auth.json`/`config.toml`。 | | Codex adapter | 已实现/已通过主闭环 | 当前代码已实现受控 `codex app-server --listen stdio://`、`initialize`/`thread/start`/`thread/resume`/`turn/start` response 校验、stderr 有界诊断、spawn/JSON parse/response invalid/timeout/provider 5xx availability failureKind,以及包含 retry error notification 的 fake app-server 自测试。 | | 错误可观测与脱敏 | 已实现主路径 | child env、cwd、workspace 和 Codex home 只输出摘要;stderr tail 有界且标记截断;事件和 failure 统一走 redaction。 | | 真实 provider turn | 已通过主闭环 | 真实 Codex provider turn 已经通过 RESTful API 和 CLI 综合联调;每次发布仍按 [spec-v01-validation.md](spec-v01-validation.md) 手动复验。 | +| `deepseek` profile | 已定义/待实现 | 需要作为同一 Codex stdio backend kind 的 profile 实现,使用 `agentrun-v01-provider-deepseek` 和独立 `CODEX_HOME` 完成真实联调。 | | hostPath `~/.codex` | 不采用 | 只能通过 Kubernetes Secret projection 注入。 | diff --git a/docs/reference/spec-v01-cicd.md b/docs/reference/spec-v01-cicd.md index 13fbb05..6d08452 100644 --- a/docs/reference/spec-v01-cicd.md +++ b/docs/reference/spec-v01-cicd.md @@ -130,7 +130,7 @@ Tekton promotion 可以读取 `deploy/deploy.json` 来 render runtime desired st - `argocd/agentrun-v01` AppProject destination 只能包含 `agentrun-v01`。 - `argocd/agentrun-g14-v01` source 必须指向 `v0.1-gitops:deploy/gitops/g14/runtime-v01`,destination 必须是 `agentrun-v01`。 - `v0.1` Secret、ServiceAccount、RBAC、PVC、ConfigMap 和 runtime config 必须独立命名或 namespace scope;文档、issue、trace 和 report 只记录 SecretRef 名称与 key,不记录值。 -- `agentrun-mgr` 和 runner Job 只能通过 `spec-v01-secret-distribution.md` 定义的 SecretRef 注入 Postgres DSN 和 Codex auth/config 文件;测试 Codex 凭据来自 `~/.codex/auth.json` 与 `~/.codex/config.toml` 的 Kubernetes Secret projection,不得从 `deploy/deploy.json`、artifact catalog 或 generated manifest 中读取明文。 +- `agentrun-mgr` 和 runner Job 只能通过 `spec-v01-secret-distribution.md` 定义的 SecretRef 注入 Postgres DSN 和 Codex stdio profile auth/config 文件;`codex` 默认 SecretRef 为 `agentrun-v01-provider-codex`,`deepseek` 默认 SecretRef 为 `agentrun-v01-provider-deepseek`。测试凭据来自 profile 专属 `auth.json` 与 `config.toml` 的 Kubernetes Secret projection,不得从 `deploy/deploy.json`、artifact catalog 或 generated manifest 中读取明文。 - Postgres `DATABASE_URL` Secret 必须使用实际创建的数据库名,v0.1 默认为 `agentrun_v01`;密码或其他 URL credential 必须 URL encode 后写入 DSN。Secret 值不进入 source/GitOps,runtime bootstrap 或 secret-management 流程负责创建与轮换。 - Codex provider Secret 在 GitOps manifest 中只能表现为 SecretRef 和只读 volume projection;runner Job manifest 还必须包含 writable runtime home,用于把 Secret projection 复制到 `CODEX_HOME` 后运行 Codex。 - `agentrun_dev` 和 `agentrun_prod` 不得作为 `v0.1` namespace、Argo destination、Pipeline target 或验收目标。 diff --git a/docs/reference/spec-v01-cli.md b/docs/reference/spec-v01-cli.md index e570e56..c651bce 100644 --- a/docs/reference/spec-v01-cli.md +++ b/docs/reference/spec-v01-cli.md @@ -40,7 +40,7 @@ CLI 官方 TypeScript 入口固定为 `scripts/agentrun-cli.ts`。在 G14 非交 ./scripts/agentrun runner start --run-id --backend ./scripts/agentrun runner job --run-id --command-id ./scripts/agentrun runner job --dry-run --run-id --command-id --image -./scripts/agentrun secrets codex render --dry-run [--codex-home ] +./scripts/agentrun secrets codex render --dry-run [--profile codex|deepseek] [--codex-home ] ./scripts/agentrun backends list ./scripts/agentrun server start|status ``` @@ -52,7 +52,8 @@ CLI 官方 TypeScript 入口固定为 `scripts/agentrun-cli.ts`。在 G14 非交 - 查询类命令返回当前 state、terminal_status、failureKind、event cursor 或 logPath。 - `events` 默认分页且有界,必须支持 `afterSeq` 和 `limit`。 - `server logs` 返回有界日志摘要,并指向完整日志文件或 Kubernetes pod identity。 -- `secrets codex render --dry-run` 返回 Codex provider Secret 创建计划、输入文件 bytes/hash、SecretRef、manifest 摘要和 apply 命令形状;它不得输出 Secret value 或执行 Kubernetes 写操作。 +- `secrets codex render --dry-run` 返回 Codex stdio profile Secret 创建计划、输入文件 bytes/hash、SecretRef、manifest 摘要和 apply 命令形状;`--profile codex` 默认 Secret name 为 `agentrun-v01-provider-codex`,`--profile deepseek` 默认 Secret name 为 `agentrun-v01-provider-deepseek`;它不得输出 Secret value 或执行 Kubernetes 写操作。 +- `backends list` 必须显示 `codex` 与 `deepseek` profile 的 backendKind、protocol、transport、command、requiredSecretKeys 和状态;不得因为 `deepseek` 尚未配置 Secret 就隐藏 capability。 ## 配置与 Secret 边界 @@ -79,6 +80,10 @@ CLI 官方 TypeScript 入口固定为 `scripts/agentrun-cli.ts`。在 G14 非交 阅读本文和 [spec-v01-agentrun-mgr.md](spec-v01-agentrun-mgr.md),然后对同一个 run 分别使用 CLI 和 RESTful API 查询 run、command、events 和 terminal_status。确认 CLI 不维护独立状态,两种交互面观察结果一致。 +### T5 Backend profile CLI 切换 + +阅读本文、[spec-v01-backend-codex.md](spec-v01-backend-codex.md) 和 [spec-v01-validation.md](spec-v01-validation.md),然后用正式 CLI 分别创建 `backendProfile=codex` 与 `backendProfile=deepseek` 的 run,按 `codex -> deepseek -> codex` 顺序执行真实 runner。确认 CLI 输出非空 JSON,backend_status 显示正确 profile/backendKind/protocol,缺失 `deepseek` SecretRef 时返回 `secret-unavailable`,不会 fallback 到 `codex`。 + ## 规格的实现情况 | 规格项 | 状态 | 说明 | @@ -88,3 +93,4 @@ CLI 官方 TypeScript 入口固定为 `scripts/agentrun-cli.ts`。在 G14 非交 | CLI 调 manager REST | 已实现 | CLI 通过 `ManagerClient` 调 manager REST;自测试可用内存 manager,综合联调必须指向真实 `agentrun-v01` manager。 | | runner start/job | 已实现 | `runner start` 可执行 host process runner;`runner job --dry-run` 可渲染 Kubernetes Job JSON;`runner job` 正式路径通过 manager REST 创建 Kubernetes Job 并快速返回 job identity、SecretRef、retention 和轮询命令。 | | CLI 测试规格 | 已定义/已验证主闭环 | 综合联调见 [spec-v01-validation.md](spec-v01-validation.md);每次发布仍按手动交互验收复跑。 | +| `deepseek` profile CLI | 已定义/待实现 | 需要扩展 secret render、backends list、run create examples 和 runner start/job 的 profile 可见性。 | diff --git a/docs/reference/spec-v01-documentation-governance.md b/docs/reference/spec-v01-documentation-governance.md index 7745fde..cb2f832 100644 --- a/docs/reference/spec-v01-documentation-governance.md +++ b/docs/reference/spec-v01-documentation-governance.md @@ -33,7 +33,7 @@ - `spec-v01-agentrun-mgr.md`:manager REST API、tenant boundary、runner claim、event/status authority。 - `spec-v01-agentrun-runner.md`:短生命周期 runner、claim/poll/report、日志和 failureKind。 - `spec-v01-backend-adapter.md`:backend adapter 合同、event normalization、failure mapping 和 redaction。 -- `spec-v01-backend-codex.md`:第一真实 Codex backend、`~/.codex` 测试凭据 Secret projection 和真实 turn 验收。 +- `spec-v01-backend-codex.md`:第一真实 Codex app-server stdio backend、`codex`/`deepseek` profile、`~/.codex` 测试凭据 Secret projection 和真实 turn 验收。 - `spec-v01-cli.md`:AgentRun CLI 命令族、JSON 输出、短返回、日志可见和测试规格。 - `spec-v01-scheduler.md`:自动 scheduler 的 deferred 边界。 - 未来新增单服务规格必须使用 `spec-v01-.md`。 @@ -63,7 +63,7 @@ - Manager 服务规格:[spec-v01-agentrun-mgr.md](spec-v01-agentrun-mgr.md)。 - Runner 服务规格:[spec-v01-agentrun-runner.md](spec-v01-agentrun-runner.md)。 - Backend adapter 规格:[spec-v01-backend-adapter.md](spec-v01-backend-adapter.md)。 -- Codex backend 规格:[spec-v01-backend-codex.md](spec-v01-backend-codex.md)。 +- Codex stdio backend/profile 规格:[spec-v01-backend-codex.md](spec-v01-backend-codex.md)。 - CLI 规格:[spec-v01-cli.md](spec-v01-cli.md)。 - Scheduler deferred 规格:[spec-v01-scheduler.md](spec-v01-scheduler.md)。 diff --git a/docs/reference/spec-v01-secret-distribution.md b/docs/reference/spec-v01-secret-distribution.md index 0b327ed..ebd3b89 100644 --- a/docs/reference/spec-v01-secret-distribution.md +++ b/docs/reference/spec-v01-secret-distribution.md @@ -1,6 +1,6 @@ # v0.1 Secret 与 provider credential 分发规格 -本文定义 AgentRun `v0.1` 的 Secret 和 Code Agent provider credential 分发边界。真实 Code Agent backend 需要上游模型凭据;Codex 测试凭据以 `~/.codex/auth.json` 与 `~/.codex/config.toml` 为输入源,通过 Kubernetes Secret 投影进入 runner/backend Pod。这些值不得进入 Git source、GitOps branch、artifact catalog、event、trace、日志或 CLI 输出。 +本文定义 AgentRun `v0.1` 的 Secret 和 Code Agent provider credential 分发边界。真实 Code Agent backend 需要上游模型凭据;Codex stdio profile 测试凭据以 `~/.codex/auth.json` 与 `~/.codex/config.toml` 形态为输入源,通过 Kubernetes Secret 投影进入 runner/backend Pod。这些值不得进入 Git source、GitOps branch、artifact catalog、event、trace、日志或 CLI 输出。 ## 设计目标 @@ -15,7 +15,7 @@ | Secret 类别 | 用途 | 默认消费者 | v0.1 规则 | | --- | --- | --- | --- | | Postgres DSN | manager 连接 durable store | `agentrun-mgr` | 只通过 `agentrun-v01-mgr-db/DATABASE_URL` 注入。 | -| Codex 测试凭据文件 | 真实 Code Agent backend 调上游模型 | runner 或 backend adapter | 测试来源固定为 `~/.codex/auth.json` 与 `~/.codex/config.toml`,只通过 Kubernetes SecretRef 文件投影注入,不写入 run payload。 | +| Codex stdio profile 凭据文件 | 真实 Code Agent backend 调上游模型 | runner 或 backend adapter | `codex` 与 `deepseek` 均使用 `auth.json`/`config.toml` 文件形态,只通过 profile-scoped Kubernetes SecretRef 文件投影注入,不写入 run payload。 | | Git SSH deploy key | Tekton checkout source/GitOps promotion,Argo 读取 GitOps branch | Tekton、Argo CD | 只存在于 `agentrun-ci` 或 `argocd` Secret;不进入 runtime Pod。 | | Registry credential | push/pull private registry | Tekton、runtime imagePullSecret | 只作为 ServiceAccount/imagePullSecret 引用。 | | Future tenant credential | tenant 专属工具或外部服务 | runner/backend adapter | 必须先定义 SecretRef 和 secret scope,再允许 run 引用。 | @@ -25,8 +25,9 @@ | 对象 | v0.1 建议 | | --- | --- | | Manager DB Secret | `agentrun-v01-mgr-db` key `DATABASE_URL` | -| Provider Secret | `agentrun-v01-provider-codex` keys `auth.json`、`config.toml` | -| Provider projection target | runner/backend 容器用户的 `~/.codex/auth.json`、`~/.codex/config.toml` | +| Codex Provider Secret | `agentrun-v01-provider-codex` keys `auth.json`、`config.toml` | +| DeepSeek Provider Secret | `agentrun-v01-provider-deepseek` keys `auth.json`、`config.toml` | +| Provider projection target | 只读 `/var/run/agentrun/secrets/-/auth.json`、`config.toml`,再复制到当前 run/profile 的 writable `CODEX_HOME` | | Provider config | 非敏感 base URL/model 可以来自 `config.toml` 或 ConfigMap;credential value 不得放入 ConfigMap。 | | Tekton Git SSH Secret | `agentrun-ci/agentrun-git-ssh` | | Argo Git SSH Secret | `argocd/agentrun-git-ssh` | @@ -36,24 +37,24 @@ ## Codex 测试凭据注入 -`v0.1` 综合联调使用的 Codex 测试凭据源固定为 operator 环境中的: +`v0.1` 综合联调使用的 Codex stdio profile 测试凭据源固定为 operator 环境中的文件形态: ```text ~/.codex/auth.json ~/.codex/config.toml ``` -这两个文件只能作为 Kubernetes Secret 创建或轮换的输入源。禁止把宿主机 `~/.codex` 以 hostPath 挂入 runner/backend Pod,禁止复制进镜像,禁止提交到 source branch、GitOps branch、artifact catalog、issue、PR、event、trace、日志或 CLI 输出。 +这两个文件只能作为 Kubernetes Secret 创建或轮换的输入源。`codex` profile 默认使用 operator 当前 Codex 配置;`deepseek` profile 使用 operator 准备的 DeepSeek-compatible Codex 配置,可以来自另一个 `--codex-home` 或显式 `--auth-file`/`--config-file`。禁止把宿主机 `~/.codex` 以 hostPath 挂入 runner/backend Pod,禁止复制进镜像,禁止提交到 source branch、GitOps branch、artifact catalog、issue、PR、event、trace、日志或 CLI 输出。 默认 Secret projection 规则: | 项目 | v0.1 规格 | | --- | --- | -| Kubernetes Secret | `agentrun-v01/agentrun-v01-provider-codex` | +| Kubernetes Secret | `agentrun-v01/agentrun-v01-provider-codex` 或 `agentrun-v01/agentrun-v01-provider-deepseek` | | Secret key | `auth.json`,来自 `~/.codex/auth.json` | | Secret key | `config.toml`,来自 `~/.codex/config.toml` | | Projection path | 只读 Secret projection 挂到 `/var/run/agentrun/secrets/-/auth.json` 和 `config.toml`;该路径只作为 credential source。 | -| Runtime config path | runner 启动时把授权的 Secret projection 复制到 writable `CODEX_HOME`,默认 `/home/agentrun/.codex/auth.json` 和 `config.toml`。 | +| Runtime config path | runner 启动时把当前 `backendProfile` 授权的 Secret projection 复制到 writable `CODEX_HOME`,Kubernetes Job 默认可以使用该 Job 独占的 `/home/agentrun/.codex/auth.json` 和 `config.toml`;复用进程必须使用 run/profile 独占目录。 | | Projection mode | 只读,建议 `0400` 或等价最小权限 | | Runtime env | `HOME=/home/agentrun`,`CODEX_HOME=/home/agentrun/.codex`,`AGENTRUN_CODEX_SECRET_HOME=`;不得 fallback 到节点宿主机 home。 | @@ -74,6 +75,15 @@ Run 的 `executionPolicy.secretScope` 只能包含引用,不包含值。示例 "keys": ["auth.json", "config.toml"], "mountPath": "~/.codex" } + }, + { + "profile": "deepseek", + "secretRef": { + "namespace": "agentrun-v01", + "name": "agentrun-v01-provider-deepseek", + "keys": ["auth.json", "config.toml"], + "mountPath": "~/.codex" + } } ], "allowCredentialEcho": false @@ -86,6 +96,7 @@ Run 的 `executionPolicy.secretScope` 只能包含引用,不包含值。示例 - `secretRef.namespace` 默认只能是 run 所在 lane namespace 或明确批准的 platform namespace。 - manager 可以保存 `secretRef`,但不得读取 Secret 值后存库。 - runner/backend adapter 获得 Secret 的方式必须来自 Kubernetes env/file projection 或受限 Secret API 读取;Codex 默认从只读 Secret projection 复制 `auth.json` 和 `config.toml` 到 writable `CODEX_HOME` 后启动 app-server,不得通过 run payload、event、CLI 参数或日志传递。 +- runner/backend adapter 只能选择与 run `backendProfile` 同名的 provider credential;`backendProfile=deepseek` 缺少 `deepseek` SecretRef 时必须 `secret-unavailable`,不得 fallback 到 `codex`。 - Secret projection 不能直接作为 `CODEX_HOME`。Codex app-server 会读取并可能维护默认配置、PATH 或运行态文件;把只读 Secret volume 直接挂到 `CODEX_HOME` 会造成启动期写入失败。v0.1 的固定边界是:Secret volume 只读、`/home/agentrun` 由 `emptyDir` 提供可写 runtime home、复制动作只发生在 runner/backend 容器内且不打印文件内容。 - SecretRef 不存在或 RBAC 不允许时,run 必须失败为结构化 `failureKind=secret-unavailable` 或等价错误,不得降级成无凭证重试风暴。 @@ -101,7 +112,7 @@ Tekton promotion Argo CD -> syncs workload references to agentrun-v01 Kubernetes Secret - -> created from ~/.codex/auth.json and ~/.codex/config.toml by operator or approved secret-management flow + -> created from profile-specific auth.json and config.toml by operator or approved secret-management flow runner/backend Pod -> receives Codex auth/config via read-only file projection -> copies authorized files into writable CODEX_HOME before starting Codex app-server @@ -111,18 +122,19 @@ Secret 创建和轮换不由 source branch 自动生成;source branch 只声 ## Codex Secret dry-run 工具 -`v0.1` 提供只读 CLI 工具,用 operator 本地 `~/.codex/auth.json` 与 `~/.codex/config.toml` 构造 Kubernetes Secret 创建计划: +`v0.1` 提供只读 CLI 工具,用 operator 本地 `~/.codex/auth.json` 与 `~/.codex/config.toml` 形态的文件构造 Kubernetes Secret 创建计划: ```bash -./scripts/agentrun secrets codex render --dry-run +./scripts/agentrun secrets codex render --dry-run [--profile codex|deepseek] ``` 可选参数: - `--codex-home `:覆盖默认 `~/.codex` 输入目录。 +- `--profile `:默认 `codex`;`deepseek` 使用同一文件形态但默认 Secret name 为 `agentrun-v01-provider-deepseek`。 - `--auth-file ` / `--config-file `:分别覆盖输入文件路径。 - `--namespace `:默认 `agentrun-v01`。 -- `--secret-name `:默认 `agentrun-v01-provider-codex`。 +- `--secret-name `:默认随 profile 变化,`codex` 为 `agentrun-v01-provider-codex`,`deepseek` 为 `agentrun-v01-provider-deepseek`。 输出必须是 JSON,并且只包含 `namespace`、`secretName`、`keys`、每个输入文件的 `bytes`、`sha256`/`contentHash`、整体 hash、redaction 状态、apply 命令形状和 Secret manifest 摘要。输出不得包含 Secret value、`auth.json` 明文、`config.toml` 明文、base64 `data` 字段或可直接恢复 credential 的内容。工具只支持 `--dry-run`;不得执行 `kubectl apply`。 @@ -143,7 +155,7 @@ Secret 创建和轮换不由 source branch 自动生成;source branch 只声 ### T2 Runner credential projection -阅读本文,然后启动一个最小 backend runner dry-run,确认 Pod file projection 挂在 `/var/run/agentrun/secrets/...` 且只读,`/home/agentrun` 是 writable runtime home,`CODEX_HOME=/home/agentrun/.codex`,runner/backend 会把授权文件复制到 `CODEX_HOME` 后再启动 Codex;event、日志和 CLI 输出只显示 redacted credential source,不显示文件内容。 +阅读本文,然后分别启动 `backendProfile=codex` 与 `backendProfile=deepseek` 的最小 backend runner dry-run,确认 Pod file projection 挂在 `/var/run/agentrun/secrets/...` 且只读,`/home/agentrun` 是 writable runtime home,runner/backend 只把当前 profile 授权文件复制到 `CODEX_HOME` 后再启动 Codex;event、日志和 CLI 输出只显示 redacted credential source,不显示文件内容。 ### T3 Missing secret failure @@ -157,5 +169,6 @@ Secret 创建和轮换不由 source branch 自动生成;source branch 只声 | Kubernetes SecretRef 注入 | 已实现/已通过主闭环 | runner Job dry-run 和正式 Job 创建路径已按 run `executionPolicy.secretScope.providerCredentials` 生成 Secret volume projection、writable runtime home 和 `AGENTRUN_CODEX_SECRET_HOME`;真实 Secret 与 Codex turn 已通过主闭环。 | | Codex Secret dry-run 工具 | 已实现 | `./scripts/agentrun secrets codex render --dry-run` 只输出 Secret 创建计划、hash 和 redacted manifest 摘要,不执行 apply。 | | Codex auth/config file projection | 已实现主路径 | backend readiness 检查 `auth.json`/`config.toml` 可读性,缺失时返回 `secret-unavailable`;真实 runner Job 将只读 projection 复制到 writable `CODEX_HOME`。 | +| DeepSeek profile SecretRef | 已定义/待实现 | 需要新增 `agentrun-v01-provider-deepseek` render、Job projection、profile 选择和负向 missing-secret 验收。 | | redaction 最小规则 | 已实现主路径 | Secret dry-run 工具、event、Job dry-run 输出、self-test 和真实主闭环均不打印 Secret value;复杂审计按 [spec-v01-validation.md](spec-v01-validation.md) 人工抽查。 | | 外部 secret manager | 未采用 | 如需 Vault/ExternalSecrets/SOPS,后续单独更新规格。 | diff --git a/docs/reference/spec-v01-services.md b/docs/reference/spec-v01-services.md index 5095457..a5f6f5e 100644 --- a/docs/reference/spec-v01-services.md +++ b/docs/reference/spec-v01-services.md @@ -10,7 +10,7 @@ AgentRun 是面向 UniDesk 与 HWLAB 的共享 Code Agent 执行基础设施。` - `agentrun-mgr` 是公共 RESTful API 和 durable facts authority,负责 run、command、event、runner、backend、lease 的持久状态和鉴权前置边界。 - `agentrun-runner` 是短生命周期 per-run 或 per-attempt 执行者,必须从 manager claim run,并把 event、heartbeat 和 terminal status 写回 manager。 -- Backend adapter 隐藏具体 Agent 工具协议,`v0.1` 只要求一个真实 Agent backend 形成闭环;其他 backend 不进入第一波实现。 +- Backend adapter 隐藏具体 Agent 工具协议,`v0.1` 使用一个真实 Codex stdio backend kind 形成闭环,并在该 kind 下支持 `codex` 与 `deepseek` profile;其他 backend kind 不进入第一波实现。 - AgentRun CLI 是受控操作入口,负责创建 run、提交 command、轮询 events、手动启动 runner 和查看 backend capability;CLI 不等待完整模型 turn。 - Scheduler 是后续自动派发能力;`v0.1` 可以保留规格和状态字段,但不把自动调度作为第一阶段验收目标。 @@ -18,9 +18,22 @@ AgentRun 是面向 UniDesk 与 HWLAB 的共享 Code Agent 执行基础设施。` AgentRun `v0.1` 的自研组件优先使用 Bun + TypeScript 实现:`agentrun-mgr`、`agentrun-runner`、backend adapter、Codex backend、AgentRun CLI 和后续 scheduler 都属于该边界。官方 TypeScript CLI 入口固定为 `scripts/agentrun-cli.ts`,入口只做参数解析和路由,复杂逻辑拆到 `scripts/src/` 与 `src/`;G14/CI/人工非交互命令使用 `./scripts/agentrun` launcher 启动同一入口。Postgres、Kubernetes、Tekton、Argo CD、YAML manifest 和 shell 级容器启动命令属于外部运行面或部署面,不受“必须 TypeScript 实现”的约束。 -`backendProfile=codex` 的 `v0.1` 协议固定为 Codex CLI app-server JSON-RPC over stdio:runner/backend adapter 启动受控 `codex app-server --listen stdio://` 子进程,经 stdin/stdout 发送换行分隔 JSON-RPC,请求顺序至少覆盖 `initialize`、`thread/start` 或 `thread/resume`、`turn/start`。直接调用 Responses HTTP、OpenAI SDK、`codex exec` 一次性输出或文本 fallback 只能作为诊断/自测试辅助,不能作为 Codex backend 综合联调通过证据。 +`backendProfile=codex` 与 `backendProfile=deepseek` 的 `v0.1` 协议固定为同一个 Codex CLI app-server JSON-RPC over stdio backend kind:runner/backend adapter 启动受控 `codex app-server --listen stdio://` 子进程,经 stdin/stdout 发送换行分隔 JSON-RPC,请求顺序至少覆盖 `initialize`、`thread/start` 或 `thread/resume`、`turn/start`。`backendProfile` 只选择 profile/config/SecretRef;`backendKind`、`protocol` 和进程生命周期仍是 `codex-app-server-stdio`。直接调用 Responses HTTP、OpenAI SDK、`codex exec` 一次性输出或文本 fallback 只能作为诊断/自测试辅助,不能作为 Codex backend 综合联调通过证据。 -实现参考必须优先读取并吸收两个成熟代码路径:UniDesk Code Queue 的 Bun/TS `src/components/microservices/code-queue/src/code-agent/codex.ts` 与 `common.ts`,以及 HWLAB v0.2 的 `internal/cloud/codex-stdio-session.mjs`、`scripts/code-agent-chat-smoke.mjs`。AgentRun 复用的是 stdio JSON-RPC、session/turn 生命周期、trace、redaction、Secret projection 和 failureKind 经验,不复制 UniDesk/HWLAB 的环境专用路径、业务 prompt 或明文凭据。 +实现参考必须优先读取并吸收两个成熟代码路径:UniDesk Code Queue 的 Bun/TS `src/components/microservices/code-queue/src/code-agent/codex.ts` 与 `common.ts`,以及 HWLAB v0.2 的 `internal/cloud/codex-stdio-session.mjs`、`scripts/code-agent-chat-smoke.mjs`、`docs/reference/spec-v02-deepseek-proxy.md`、`docs/reference/code-agent-chat-readiness.md`。AgentRun 复用的是 stdio JSON-RPC、session/turn 生命周期、trace、redaction、Secret projection、profile overlay、DeepSeek/Moon Bridge 分层诊断和 failureKind 经验,不复制 UniDesk/HWLAB 的环境专用路径、业务 prompt、bridge host、namespace 或明文凭据。 + +## Backend Profile 边界 + +`v0.1` 需要支持两个可手动选择的 backend profile,但不引入完整多 backend 调度: + +| backendProfile | backendKind | v0.1 处理 | SecretRef | 说明 | +| --- | --- | --- | --- | --- | +| `codex` | `codex-app-server-stdio` | 保留,P0 | `agentrun-v01-provider-codex` | 现有 GPT/Codex profile,必须保持默认行为不回归。 | +| `deepseek` | `codex-app-server-stdio` | 新增,P0 | `agentrun-v01-provider-deepseek` | DeepSeek-compatible Codex profile;通过 profile 专属 `auth.json`/`config.toml` 或等价 SecretRef 配置上游、模型和 base URL。 | + +完整多 backend 路由仍然 deferred,含 OpenCode、Claude Code、host-native、Windows-native、scheduler capacity selection 和跨 backend 自动选择。`v0.1` 只允许 manager/runner 按 run 中的 `backendProfile` 显式选择 `codex` 或 `deepseek`,并在 capability 中报告两者共享同一个 `protocol=codex-app-server-jsonrpc-stdio` 与 `transport=stdio`。 + +`codex` 与 `deepseek` 之间不得隐式 fallback:缺少 `deepseek` SecretRef 时必须失败为 `secret-unavailable`,不能改用 `codex` Secret;`deepseek` 运行失败也不能重试到 `codex`。同一轮发布的综合联调必须证明 `codex -> deepseek -> codex` 的切换不会污染彼此的 SecretRef、`CODEX_HOME`、模型或 upstream 配置。 ## 内部架构 @@ -59,14 +72,14 @@ Runner inbound API 只允许本地或私有诊断,不作为业务客户端入 | `agentrun-mgr` | 长驻服务 | 保留,P0 | 公共 RESTful API、durable facts、idempotency、runner claim、event append 和 status authority。 | `spec-v01-agentrun-mgr.md` | | `agentrun-runner` | 短生命周期执行入口 | 保留,P0 | per-run/per-attempt executor;claim run、poll command、调用 backend、写回 events/status。 | `spec-v01-agentrun-runner.md` | | Backend adapter | 执行适配层 | 保留,P0 | 统一 backend capability、event normalization、error mapping 和 credential boundary。 | `spec-v01-backend-adapter.md` | -| First real backend | 具体 Agent backend | 保留,P0 | `v0.1` 必须至少证明一个真实 Agent backend;默认候选是 Codex。 | `spec-v01-backend-codex.md` | +| Codex stdio backend profiles | 具体 Agent backend | 保留,P0 | `v0.1` 使用一个真实 Codex app-server stdio backend kind,必须支持 `codex` 与 `deepseek` 两个 profile;完整多 backend 路由仍 deferred。 | `spec-v01-backend-codex.md` | | AgentRun CLI | CLI/Job 工具 | 保留,P0 | JSON 输出、短返回、run/command/event/runner/backend 操作入口。 | `spec-v01-cli.md` | | Postgres durable store | 稳定外部服务 | 保留,P0 | 使用 `agentrun-v01-postgres` 保存 runs、commands、events、runners、backends、leases 和 migration ledger;不使用 file/sqlite 作为 v0.1 durable store。 | `spec-v01-postgres.md` | | Secret distribution | 系统能力 | 保留,P0 | Provider credential 只通过 Kubernetes SecretRef、ServiceAccount/RBAC 和 runner env/file projection 分发;Codex 测试凭据使用 `~/.codex/auth.json` 与 `~/.codex/config.toml` 生成 Secret projection;source、GitOps、logs 和 events 不保存明文。 | `spec-v01-secret-distribution.md` | | Tenant policy boundary | Run schema 合同 | 保留,P0 | 作为 `Run` 的必填字段和最小校验存在,不做独立 policy engine;tenant 的业务授权仍由 UniDesk/HWLAB 判定。 | 并入 `spec-v01-agentrun-mgr.md` | | Observability | 最小事件/日志合同 | 保留,P1 子项 | 作为 manager/runner 的 event、terminal status、failureKind、logPath 和 redaction 最小合同,不拆独立观测系统。 | 并入 `spec-v01-agentrun-mgr.md`、`spec-v01-agentrun-runner.md` | | `agentrun-scheduler` | 长驻调度器 | Deferred | M1-M3 稳定后再实现自动 pending scan、capacity selection 和 runner Job 创建。 | `spec-v01-scheduler.md` | -| 多 backend 路由 | 系统能力 | Deferred | `v0.1` 不做完整多 backend 调度,只保留 capability 模型。 | 后续版本 spec | +| 多 backend 路由 | 系统能力 | Deferred | `v0.1` 不做跨 backend kind 的自动路由和调度;仅支持同一 Codex stdio backend kind 下的 `codex`/`deepseek` profile 手动选择。 | 后续版本 spec | | UI | 前端 | Deferred | `v0.1` 不要求独立 UI;UniDesk/HWLAB canary 可通过 CLI/API 验证。 | 后续版本 spec | | judge/retry 自动化 | 系统能力 | Deferred | `v0.1` 只定义基础 terminal 和 failure visibility,不实现复杂 judge。 | 后续版本 spec | @@ -109,7 +122,7 @@ Run create 的最小字段合同: | `projectId` | 必填,例如 `pikasTech/unidesk`、`pikasTech/HWLAB`。 | | `workspaceRef` | 必填,描述 source/worktree/workspace,不由 runner 猜测。 | | `providerId` | 必填,例如 `G14`、`D601`;只表示目标 provider,不直接授予权限。 | -| `backendProfile` | 必填,例如 `codex`;`v0.1` 只要求一个真实 backend 闭环。 | +| `backendProfile` | 必填,`v0.1` allowlist 为 `codex` 与 `deepseek`;两者共享 `codex-app-server-stdio` backend kind。 | | `executionPolicy` | 必填或由 manager 显式写入默认值,至少包含 sandbox、approval、timeout、network 和 secret scope。 | | `traceSink` | 字段必须存在;可以为 `null` 或显式 sink,表示标准事件是否需要镜像给 tenant。 | @@ -169,5 +182,6 @@ Manager 负责校验、保存和返回这些字段;runner 只能消费已保 | Scheduler deferred 规格 | 已定义 | 见 [spec-v01-scheduler.md](spec-v01-scheduler.md)。 | | `agentrun-mgr` 实现 | 已实现/已通过主闭环 | 已有 REST API、Postgres durable store、migration ledger、runner claim/lease/report、health/readiness 和 self-test memory 模式;真实 `agentrun-v01` runtime 已通过 Postgres/GitOps/readiness 和 run lifecycle 主闭环。 | | `agentrun-runner` 实现 | 已实现/已通过主闭环 | host process runner 与 Kubernetes Job 共用 `runOnce`,runner 通过 manager API claim/poll/report,不直连 Postgres;真实 Kubernetes Job 已完成 Codex turn。 | -| 第一真实 backend | 已实现/已通过主闭环 | Codex app-server stdio backend 已有协议、失败分类、脱敏和 fake self-test;真实 Codex provider turn 已通过 RESTful API 与 CLI 主闭环。 | +| `codex` profile | 已实现/已通过主闭环 | Codex app-server stdio backend 已有协议、失败分类、脱敏和 fake self-test;真实 Codex provider turn 已通过 RESTful API 与 CLI 主闭环。 | +| `deepseek` profile | 已定义/待实现 | 规格要求 DeepSeek 作为同一 Codex stdio backend kind 的 profile/config/SecretRef 选择进入 v0.1;实现和真实联调尚未完成。 | | 自动 scheduler | Deferred | 不作为 `v0.1` 第一阶段验收目标。 | diff --git a/docs/reference/spec-v01-validation.md b/docs/reference/spec-v01-validation.md index b5c1371..a7618df 100644 --- a/docs/reference/spec-v01-validation.md +++ b/docs/reference/spec-v01-validation.md @@ -41,10 +41,11 @@ - 真实 `v0.1-gitops` artifact catalog 与 `deploy/gitops/g14/runtime-v01/**`。 - 真实 Argo CD Application `agentrun-g14-v01` 同步到 `agentrun-v01`。 - 真实 `agentrun-v01-postgres` StatefulSet、PVC、Service 和 migration ledger。 -- 真实 Kubernetes SecretRef 注入 Postgres DSN 和 Code Agent provider credential;Codex 测试凭据必须来自 `~/.codex/auth.json` 与 `~/.codex/config.toml` 的 Kubernetes Secret projection。 +- 真实 Kubernetes SecretRef 注入 Postgres DSN 和 Code Agent provider credential;Codex stdio profile 测试凭据必须来自 profile 专属 `auth.json` 与 `config.toml` 的 Kubernetes Secret projection。 - Codex Secret projection 必须先保持只读,再复制到 writable `CODEX_HOME` 后启动 app-server;综合联调不得把只读 Secret volume 直接当作 `CODEX_HOME` 的通过证据。 - 真实 `agentrun-mgr`、runner Job 或受控 runner process、真实 backend adapter。 -- 至少一个真实 Code Agent provider turn;Codex backend 必须通过 `codex app-server --listen stdio://` 的 JSON-RPC stdio turn 完成,mock、fixture、source-only、dry-run、fake provider、直接 Responses HTTP 或 `codex exec` 一次性输出不能作为通过证据。如果 provider credential SecretRef 缺失,综合联调必须标记 blocked,不能降级为 mock pass。 +- 至少一个真实 Code Agent provider turn;Codex stdio backend 必须通过 `codex app-server --listen stdio://` 的 JSON-RPC stdio turn 完成,mock、fixture、source-only、dry-run、fake provider、直接 Responses HTTP 或 `codex exec` 一次性输出不能作为通过证据。如果 provider credential SecretRef 缺失,综合联调必须标记 blocked,不能降级为 mock pass。 +- 若变更涉及 backend profile,综合联调必须分别覆盖 `backendProfile=codex` 与 `backendProfile=deepseek`,并按 `codex -> deepseek -> codex` 顺序证明 profile 切换不互相污染。 综合联调最小闭环: @@ -112,7 +113,7 @@ CLI 与 RESTful API 可以复用同一个真实 run 做联调。若两者观察 ### T2 综合联调真实性 -阅读本文,然后执行一次综合联调,确认所有关键依赖均为真实 `agentrun-v01` runtime、Postgres、SecretRef、runner、backend 和 provider credential;Codex 测试凭据必须通过 Kubernetes Secret projection 注入 `~/.codex/auth.json` 与 `~/.codex/config.toml`。任何缺失必须返回 blocked 或 failed。 +阅读本文,然后执行一次综合联调,确认所有关键依赖均为真实 `agentrun-v01` runtime、Postgres、SecretRef、runner、backend 和 provider credential;Codex stdio profile 测试凭据必须通过 Kubernetes Secret projection 注入当前 profile 的 `auth.json` 与 `config.toml`。任何缺失必须返回 blocked 或 failed。 ### T3 发布判定 @@ -138,18 +139,32 @@ CLI 与 RESTful API 可以复用同一个真实 run 做联调。若两者观察 - 对同一 run 使用相同 idempotency key 提交相同 command 两次,再用相同 key 提交不同 payload,确认前两次返回同一个 command,第三次结构化失败。 - 对同一 pending run 启动两个真实 runner 或重复 claim,确认只有一个 owner 成功,失败方为 `runner-lease-conflict` 或等价 failureKind,且不继续调用 backend。 - 用不存在的 provider SecretRef 创建 run 并启动 runner,确认失败为 `secret-unavailable`,不会降级为 mock pass,也不会打印 Secret value。 +- 用 `backendProfile=deepseek` 但只提供 `codex` SecretRef 的 run 启动 runner,确认失败为 `secret-unavailable`,不会 fallback 到 `codex`。 - 对同一 run 分页读取 events,确认 `seq` 单调、`afterSeq` 翻页无重复、重复读取同一页不会改变 durable facts。 T7 只定义人工验收的检查面和判定口径。若后续为减少人工操作引入 helper 命令,它只能输出手动步骤、当前证据或 dry-run 计划,不能把这些负向场景改造成阻断发布的自动门禁。 +### T8 Backend profile 真实切换验收 + +阅读本文、[spec-v01-services.md](spec-v01-services.md)、[spec-v01-backend-codex.md](spec-v01-backend-codex.md) 和 [spec-v01-secret-distribution.md](spec-v01-secret-distribution.md),然后在真实 `agentrun-v01` 运行面用正式 CLI 和 RESTful API 手动验证以下内容: + +- `GET /api/v1/backends` 和 `./scripts/agentrun backends list` 同时列出 `codex` 与 `deepseek`,并显示两者共享 `backendKind=codex-app-server-stdio`、`protocol=codex-app-server-jsonrpc-stdio`、`transport=stdio`。 +- 用 `backendProfile=codex` 完成一个真实 app-server stdio turn,记录 runId、commandId、terminal_status 和 redacted backend_status。 +- 用 `backendProfile=deepseek` 完成一个真实 app-server stdio turn,确认 SecretRef 为 `agentrun-v01-provider-deepseek`,runtime `CODEX_HOME` 与 `codex` run 隔离,assistant 回复非空或失败被正确归类为 provider blocker。 +- 再次用 `backendProfile=codex` 完成真实 turn,确认没有继承 DeepSeek model/base URL/config。 +- 删除或替换 `deepseek` SecretRef 后复测,必须 `secret-unavailable`,不能使用 `codex` SecretRef 或默认 Codex config。 + +T8 是涉及 backend profile 变更时的综合联调标准;不涉及 backend profile 的普通发布仍至少执行已有真实主闭环。 + ## 规格的实现情况 | 规格项 | 状态 | 说明 | | --- | --- | --- | | 两层验证模型 | 已定义 | 本文为 v0.1 验证权威。 | | 自测试 task | 已实现 | `src/selftest/run.ts` 自动发现 `src/selftest/cases/*.ts`;覆盖 redaction/Postgres contract、manager memory、runner Job render/create、Codex fake app-server stdio 和 Secret render。 | -| 综合联调验收规格 | 已增强 | 本文保留人工交互验收模型;T4-T7 定义 CLI、RESTful、一致性和负向场景的手动验收标准,不新增自动脚本或门禁。 | +| 综合联调验收规格 | 已增强 | 本文保留人工交互验收模型;T4-T8 定义 CLI、RESTful、一致性、负向场景和 backend profile 切换的手动验收标准,不新增自动脚本或门禁。 | | CLI 交互联调标准 | 已定义 | 必须只使用正式 CLI,验证真实 run 生命周期和可观测输出。 | | RESTful API 交互联调标准 | 已定义 | 必须直连真实 manager HTTP JSON API,验证服务合同和 durable facts。 | | 真实主闭环 | 已通过 | 当前 v0.1 已通过真实 Tekton/Argo、Postgres、SecretRef、Kubernetes runner Job、Codex stdio turn、RESTful API 和 CLI 主闭环;每次发布仍需按本文手动复验。 | +| `deepseek` profile 切换验收 | 已定义/待执行 | 实现 deepseek profile 后必须按 T8 做 100% 真实综合联调。 | | mock 作为发布证据 | 不采用 | mock 只能证明自测试通过。 |