@@ -55,7 +55,7 @@ Todo Note 数据迁移后必须验证:`microservice proxy todo-note /api/insta
- Provider: `main-server` ,由本机 provider-gateway 通过 `microservice.http` 访问同一 Compose 网络内的 `http://codex-queue:4222` 。
- 代码引用:`https://github.com/pikasTech/unidesk` 与配置中的 `repository.commitId` ;服务源码位于 `src/components/microservices/codex-queue` ,属于 UniDesk 自有控制面组件。
- 部署引用:UniDesk 根仓库 `docker-compose.yml` 中的 `codex-queue` service, Dockerfile 为 `src/components/microservices/codex-queue/Dockerfile` ,容器名为 `codex-queue-backend` 。
- Codex 认证:容器只从主 server 的 `/root/.codex/config.toml` 同步 Codex provider 配置到 `.state/codex-queue/codex-home` ,并通过运行时环境透传 `OPENAI_API_KEY` 、`CRS_OAI_KEY` 等 provider 所需变量;新增 provider 的 `env_key` 时必须增加同类运行时透传,禁止把 Codex 或 MiniMax 密钥写入仓库文件。
- Codex 认证:容器只从主 server 的 `/root/.codex/config.toml` 同步 Codex provider 配置到 `.state/codex-queue/codex-home` ,并通过运行时环境透传 `OPENAI_API_KEY` 、`CRS_OAI_KEY` 等 provider 所需变量;新增 provider 的 `env_key` 时必须增加同类运行时透传,禁止把 Codex 或 MiniMax 密钥写入仓库文件。Codex Queue 开发容器必须只读挂载 host 的 root SSH 目录到 `/root/.ssh` (默认 `${UNIDESK_HOST_ROOT_SSH_DIR:-/root/.ssh}` ),让容器内 `git push` 、 `ssh -T git@github.com` 与 host 使用同一套 GitHub SSH key/known_hosts;不得把私钥复制进镜像或仓库。
- Develop-ready 镜像:Codex Queue 镜像必须在启动前预装 UniDesk/Pipeline 调试所需工具,至少包含 `codex` 、`bun` 、`node` 、`npm` /`npx` 、`git` 、`rg` 、`curl` 、`python3` /`pip3` 、`docker` 、`docker compose` 、`docker-compose` 、`jq` 、`ssh` 、`rsync` 、`make` 、`gcc` /`g++` 、`tar` 、`gzip` 和 `unzip` ;不得依赖 Codex 任务运行时再 `apt-get install` 这些基础环境。
- Codex 控制:服务内部启动 `codex app-server --listen stdio://` ,用 JSON-RPC 调用 `thread/start` 、`turn/start` 、`turn/steer` 和 `turn/interrupt` ,并监听 `turn/completed` 、assistant delta、reasoning delta、command output delta、file diff delta 等通知生成前端可轮询的 transcript。
- 队列语义:`POST /api/tasks` 或 `/api/tasks/batch` 入队,服务始终只运行一个 Codex turn;当前任务真正终止后才推进下一个任务。`GET /api/tasks` 与 `GET /api/tasks/{id}` 返回队列、attempt、judge 和输出;`POST /api/tasks/{id}/steer` 向运行中 turn 推入 prompt; `POST /api/tasks/{id}/interrupt` 或 `DELETE /api/tasks/{id}` 打断/取消;`POST /api/tasks/{id}/retry` 手动重试。队列 worker 必须隔离单个 task 的异常,不能因为某个 app-server 或 judge 异常让后续 queued 任务停止;当存在 queued/retry_wait 且 worker 空闲时,watchdog 必须自动重新调度。
@@ -63,7 +63,7 @@ Todo Note 数据迁移后必须验证:`microservice proxy todo-note /api/insta
- Retry/推进语义:`retry` 不是新开一个独立任务或完全新 session;只要已有 `codexThreadId` ,服务必须 `thread/resume` 原 thread 并 append 一个继续执行 prompt。只有 judge 判定 `complete` 后,队列 worker 才把当前任务标为成功并推进下一个 queued/retry_wait 任务。
- Judge 探针:`GET|POST /api/judge/probe` 使用同一套 judge 逻辑跑内置 synthetic execution records,覆盖正常完成、正常结束但只给计划、传输中断和用户打断四类样本,返回 `hits` 、`total` 、`hitRate` 、每例 `expected` 与 `decision` ;该接口不得回显 MiniMax API key。
- 模型选择:默认 Codex 模型是 `gpt-5.4-mini` ,内置模型队列包含 `gpt-5.4-mini` 、`gpt-5.4` 、`gpt-5.5` ;每个入队任务可通过前端模型下拉菜单或 API 覆盖 `model` 、`cwd` 、`reasoningEffort` 和 `maxAttempts` 。
- 状态与日志:默认工作目录为容器内 `/root/unidesk` ,该路径映射主 server 的 `~/unidesk` ;同时保留 `/workspace` 映射以兼容历史任务。队列状态保存在 `.state/codex-queue/state.json` 对应的容器挂载路径,日志写入 UniDesk `logs/{YYYYMMDD}/..._codex-queue.jsonl` , `/logs` 端点返回最近结构化日志。`/health` 的 `queue.devReady` 和 `/api/dev-ready` 必须暴露 develop-ready 自检,包括必需工具、Docker socket、`docker compose` 、默认工作目录和 Codex config 状态。Codex CLI-like 输出可能很大,服务必须对输出条数设上限并节流状态持久化,禁止对每个 output delta 同步重写完整 state 导致 `/health` 和控制 API 卡死;容器 healthcheck 必须使用带超时的 HTTP 探针,不能留下堆积的无超时探针进程。
- 状态与日志:默认工作目录为容器内 `/root/unidesk` ,该路径映射主 server 的 `~/unidesk` ;同时保留 `/workspace` 映射以兼容历史任务。队列状态保存在 `.state/codex-queue/state.json` 对应的容器挂载路径,日志写入 UniDesk `logs/{YYYYMMDD}/..._codex-queue.jsonl` , `/logs` 端点返回最近结构化日志。`/health` 的 `queue.devReady` 和 `/api/dev-ready` 必须暴露 develop-ready 自检,包括必需工具、Docker socket、`docker compose` 、默认工作目录、 Codex config 状态和 `/root/.ssh` 共享 SSH key 状态。Codex CLI-like 输出可能很大,服务必须对输出条数设上限并节流状态持久化,禁止对每个 output delta 同步重写完整 state 导致 `/health` 和控制 API 卡死;容器 healthcheck 必须使用带超时的 HTTP 探针,不能留下堆积的无超时探针进程。
- 代理路径:只允许 `/health` 、`/logs` 和 `/api/` 前缀;允许方法为 `GET` 、`HEAD` 、`POST` 、`DELETE` 。Codex Queue 只在 Compose 内网暴露 `4222/tcp` ,不得映射或开放到公网。
- UniDesk 前端:`微服务 / Codex Queue` React 页面负责展示队列卡片、默认模型、模型下拉、显式入队份数、MiniMax judge 状态、Codex CLI-like 输出流、attempt 终态、追加 prompt、打断和手动重试控件;连续执行同一 prompt 应使用 `入队份数` 一次性生成多条队列任务,而不是依赖快速连点按钮;原始任务 JSON 只能通过显式 `查看原始JSON` 打开。