Skip to content

Repository files navigation

Codex Queue

Codex Queue 是一个面向 macOS 和 Windows 11 的 Tauri 桌面任务队列。桌面端使用 React、Vite 和 shadcn/ui,默认显示中文并支持英文、浅色和深色主题;Rust 内核负责校验队列、解析依赖、按顺序执行任务,以及在网络或 API 暂时不可用时进行指数退避重试。

应用首页同时提供 Task Supervisor 工作台。Tauri 桌面端每 3 秒刷新 Codex Desktop 的本地 thread、Thread Goal、token 用量和 turn 时间线,并在有活动目标的任务异常停止或卡住时恢复同一任务;浏览器开发模式继续使用本地演示快照。原有任务队列仍可从侧边栏进入。

这个项目提供两个入口,但共用同一份队列格式和 Rust 执行内核:

  • 桌面 UI:查看、编辑和手动运行队列,适合日常交互操作。
  • CLI + 系统调度器:每天本地时间 01:00 自动拉起 Codex 并运行队列,适合无人值守任务。

Task Supervisor MVP

Supervisor 当前包含:

  • Tauri 模式读取 ~/.codex/state_*.sqlitegoals_*.sqlite 与 session rollout JSONL,显示最近 50 个未归档主任务,并过滤内部 subagent thread。
  • 根据 task_startedtask_completeturn_abortedthread_goal_updated 事件展示真实运行状态、错误、目标和时间线;rollout 使用增量缓存读取。
  • 仅对状态为 active 的目标自动恢复:turn 结束但目标未完成,或运行中的 rollout 超过 15 分钟没有进展且 Codex 已释放原生 thread writer lock 时,使用 codex exec resume <thread-id> 在原工作区继续同一任务。writer 仍存活时不会强制抢占,避免同一工作区出现两个 turn。
  • 恢复任务使用 workspace-write sandbox、never approval 和现有的 45 分钟进程上限;同一时刻最多恢复 4 个任务,恢复失败按 30 至 900 秒退避,每个 active goal 最多记录 6 次恢复 turn。
  • “恢复执行”可手动继续异常任务;“目标完成”会启动一次验证 turn,只有验证目标确实达成后才由 Codex 标记完成,而不是直接改写状态。
  • 浏览器模式保留 running -> waiting -> resuming -> completed 演示状态流、故障标记、健康检查、暂停、恢复、目标完成和数据重置操作。

Supervisor 不启动实验性的长驻 codex app-server。它只读查询 Codex Desktop 已维护的 SQLite 与 rollout;恢复和完成验证通过稳定的 Codex CLI resume 命令写入原 thread。浏览器开发模式不会意外启动 Codex 或执行工作区操作。

watchdog 随 Tauri 应用进程运行,关闭应用后停止。已安装的 macOS LaunchAgent 或 Windows Task Scheduler 仍只负责执行 JSON 队列;队列使用 --ephemeral,不会出现在 Supervisor 中。

功能

  • priority 降序、createdAt 升序、id 升序选择当前可执行任务。
  • 只在全部 dependsOn 任务成功后执行依赖任务。
  • 依赖失败时将下游任务标记为 blocked,同时继续处理互不依赖的任务。
  • runningsucceededfailedblocked 状态持久化到 JSON 队列。
  • 使用文件锁阻止桌面端、CLI 或定时任务重复执行同一队列。
  • 在 macOS 通过 bundle ID 打开 Codex Desktop,在 Windows 通过 codex app <workspace> 打开工作区。
  • 通过标准输入调用 codex exec 执行任务;codex appcodex exec 是本 Demo 使用的 Codex CLI 命令契约。
  • 将每次执行的事件、标准错误和最终结果保存到 runs/
  • 在任务菜单中查看最终结果、事件流、错误输出和最近 100 条运行记录。
  • 对网络、限流和暂时性 API 错误使用有上限的指数退避。
  • 为每次 codex exec 设置 45 分钟上限;超时会终止并回收子进程,再按暂时性错误重试。
  • 桌面端保存时校验队列 revision,拒绝用旧 UI 快照覆盖调度器刚写入的执行结果。
  • 无人值守执行固定使用 workspace-write sandbox 和 never approval mode。

架构

React + Vite + shadcn/ui
          |
          | Tauri commands
          v
   src-tauri (desktop adapter) ----> native file dialog / app data
          |
          v
   Rust queue core <--------------- CLI / OS scheduler at 01:00
          |
          +----> queue.json + file lock
          +----> Codex Desktop + Codex CLI
          +----> runs/<timestamp>-<task-id>-attempt-<n>-<suffix>/

主要目录:

路径 职责
src/ React UI、国际化、主题和 Tauri 前端桥接;Rust 根 crate 同时位于该目录
src-tauri/ Tauri v2 应用、commands、capabilities 和桌面配置
tests/ 队列契约、CLI 和 worker 行为测试
scripts/ macOS LaunchAgent 与 Windows Task Scheduler 安装脚本
demo/queue.json 可用于 dry-run 的示例队列

环境要求

  • 运行桌面应用或 scheduler:已安装并登录的 Codex CLI。桌面端会自动检查显式设置、CODEX_BINPATH 和平台默认安装位置。
  • 当队列设置 launchApp: true 时,当前用户需要安装 Codex Desktop。
  • 从源码开发:Node.js 24、npm 和 Rust 1.88;crate 清单和 CI 均固定使用这个 MSRV。
  • macOS 需要 Xcode Command Line Tools;Windows 11 需要 Microsoft C++ Build Tools 和 WebView2。完整平台依赖参见 Tauri prerequisites

桌面端开发

安装锁定版本的前端依赖并启动 Tauri:

npm ci
npm run tauri dev

仅启动浏览器前端:

npm run dev

浏览器模式用于 UI 开发;文件对话框、应用数据目录和真实队列执行等原生能力需要在 Tauri 窗口中验证。支持 Web Locks API 时,浏览器模式会跨标签页串行化队列保存;不支持该 API 的开发浏览器仅保证单标签页内的 revision 冲突保护。

常用质量检查:

npm run format:check
npm run lint
npm test
npm run build
cargo fmt --all -- --check
cargo test --locked --workspace --all-targets
cargo clippy --locked --workspace --all-targets --all-features -- -D warnings

构建当前平台的安装包:

npm run tauri build

workspace 构建产物位于 target/release/bundle/

CLI 使用

构建 CLI 并预览执行计划;dry-run 不会启动 Codex,也不会修改队列:

cargo build --locked --release --package codex-queue-demo
./target/release/codex-queue-demo run --queue demo/queue.json --dry-run

示例计划:

Plan: independent-priority -> environment-check -> dependent-finish

macOS 实际执行:

./target/release/codex-queue-demo run --queue demo/queue.json

Windows 11 实际执行:

.\target\release\codex-queue-demo.exe run --queue .\demo\queue.json

从创建任务到查看输出

新建或保存任务只会更新 queue.json,不会立即调用 Codex。需要在桌面端点击顶部的“运行队列”,或先按下一节安装每天 01:00 的系统调度器。已经成功、失败或阻塞的任务不会自动再次执行;需要在任务菜单中选择“重新入队”后再运行。

创建任务时需要注意:

  • workspace 建议填写要修改项目的绝对路径,例如 macOS 的 /Users/name/projects/app 或 Windows 的 C:\Users\name\projects\app
  • 相对路径(包括 .)以 queue.json 所在目录为基准。默认队列中的 . 指向 Codex Queue 的 app-data 目录,不是当前打开的工程。
  • prompt 应明确描述要完成的工程工作、期望结果和验证方式。只有“测试”或“1111”这类输入通常只会得到一段文字回复,不会修改项目。

任务至少执行过一次后,状态会显示尝试次数。打开任务右上角的“更多操作”,选择“查看输出”,可在“最终结果 / 事件 / 错误输出”之间切换,也可以刷新刚完成的后台记录。尚未执行的任务会显示空状态。

原始文件与队列位于同一目录下的 runs/

runs/<timestamp>-<task-id>-attempt-<n>-<suffix>/
  final.txt
  events.jsonl
  stderr.log

默认队列的原始输出目录:

# macOS
open "$HOME/Library/Application Support/io.github.baicie.codex-queue/runs"
# Windows 11
explorer "$env:APPDATA\io.github.baicie.codex-queue\runs"

Worker 使用 codex exec --json --ephemeral 进行无人值守执行,并由 Codex Queue 自己保存上述产物。Codex CLI 文档说明 --ephemeral 不会把 session rollout 文件持久化到磁盘,因此该后台执行不会作为可恢复任务出现在 Codex Desktop 的任务列表中;launchApp: true 只负责打开对应工作区。参见 Codex CLI exec 参考

实际执行前会运行一次 codex --version,确认 CLI 及其解释器可用;检查失败不会修改队列或增加任务尝试次数。默认发现位置包括 macOS 的 ~/.local/bin/codex、Codex/ChatGPT 应用内置 CLI,以及 Windows 的 %LOCALAPPDATA%\Programs\OpenAI\Codex\bin\codex.exe。也可以在队列设置中填写绝对路径,或通过 CODEX_BIN / --codex-bin 指定。后台进程不会继承交互式 shell 配置,因此仅指向 npm wrapper 还不够,其 node 解释器也必须位于运行环境的 PATH 中。参见 Codex CLI 安装Codex 环境变量

每日 01:00 调度

GitHub Release 中的 codex-queue-scheduler-*.zip 已包含当前平台的 CLI 和安装脚本。下载与机器架构匹配的 ZIP、核对 SHA256SUMS 并解压后,可直接安装当前用户的系统任务,不需要 Rust。源码开发者也可以先运行上面的 CLI release 构建,再使用仓库内脚本。

默认队列与 Tauri UI 使用同一 app-data 文件:macOS 为 ~/Library/Application Support/io.github.baicie.codex-queue/queue.json,Windows 为 %APPDATA%\io.github.baicie.codex-queue\queue.json。安装器会把 scheduler CLI 复制到稳定的用户数据目录,在默认文件缺失时初始化空队列,并保留已有队列内容。

安装器不会原地覆盖已安装的 scheduler。升级时先运行对应平台的卸载脚本,再安装新版本;卸载会保留队列和运行日志。

macOS LaunchAgent:

# Release ZIP 解压目录
./install-macos.sh --dry-run
./install-macos.sh

# 源码仓库,可选自定义队列
./scripts/install-macos.sh --dry-run
./scripts/install-macos.sh --queue ./demo/queue.json

Windows 11 Task Scheduler:

# Release ZIP 解压目录
.\install-windows.ps1 -WhatIf
.\install-windows.ps1

# 源码仓库,可选自定义队列
.\scripts\install-windows.ps1 -WhatIf
.\scripts\install-windows.ps1 -QueuePath .\demo\queue.json

上例通过 --queue / -QueuePath 改用 demo/queue.json;省略参数即可使用 app-data 默认队列。两个安装器都按本地时间每天 01:00 运行,并禁止重叠执行。Windows 使用 Interactive 登录模式,因为 launchApp: true 需要当前用户的桌面会话和 Codex 登录状态;支持时会请求 wake timer。macOS LaunchAgent 会在 Mac 唤醒后补跑错过的日历事件。

macOS 上的两个应用启动目标不同:

# 手动打开队列管理界面
open -b io.github.baicie.codex-queue

# worker 在 launchApp: true 时打开实际执行任务的 Codex
open -b com.openai.codex

open 只向 LaunchServices 请求启动应用,不会绕过 Gatekeeper。稳定正式版本的 Codex Queue 必须通过 Developer ID 签名和 Apple notarization;带 - 的开发预发布 DMG 可以不签名,但首次打开时需要按下文说明手动授权。

卸载调度器会保留队列和运行日志:

./uninstall-macos.sh
.\uninstall-windows.ps1

重试策略

队列级策略示例:

{
  "retryPolicy": {
    "maxAttempts": 4,
    "initialDelaySeconds": 30,
    "maxDelaySeconds": 900
  }
}

maxAttempts 包含第一次执行。以上配置在连续发生暂时性错误后等待 30、60、120 秒,每次翻倍并受 maxDelaySeconds 限制。旧队列未配置该字段时使用相同默认值。某个任务等待重试期间,依赖已经满足的其他任务仍会继续执行;只有没有可运行任务时 worker 才会等待。

可重试错误包括 HTTP 408、409、425、429、5xx,以及 Codex 报告的连接、DNS、超时、限流、过载和流中断错误。单次 codex exec 超过 45 分钟时,worker 会终止并回收子进程,将该次尝试记录为暂时性超时后进入相同的退避流程。认证失败、无效 API key、额度耗尽、未知错误和任务自身失败不会重试。

每次等待前,worker 会原子写入错误与 nextRetryAt。进程中断后,下次运行只等待剩余时间并继续相同的尝试序列。该模型提供 at-least-once execution,因此 prompt 必须可重复执行:先检查 workspace 当前状态,并避免重复执行不可逆的外部操作。

参数约束:maxAttempts 为 1-20;延迟必须为正数;maxDelaySeconds 不得小于初始延迟,也不得超过 86,400 秒。

CI 与自动 Release

.github/workflows/ci.yml 在 main push、pull request 和手动触发时执行:

  • 前端 format、lint、Vitest 和生产构建。
  • npm 与 RustSec 依赖安全审计。
  • Rust workspace format、tests 和 Clippy,并在 Windows 运行真实 workspace tests。
  • GitHub Actions workflow lint。
  • macOS 与 Windows 上的 Tauri backend check、原生应用构建和调度脚本验证;Windows 额外构建 MSI 与 NSIS 安装包。

推送与应用版本一致的 v* tag 会触发 .github/workflows/release.yml

git tag v0.3.0-dev.2
git push origin v0.3.0-dev.2

如果 tag 已受仓库规则保护而需要重新发布,可从 main 手动运行 workflow,并将 tag 输入设为目标 tag:

gh workflow run release.yml --ref main -f tag=v0.3.0-dev.2

Release workflow 只接受位于 main 历史上的 tag,并在任何发布构建开始前重新执行完整的前端、Rust 和调度脚本质量门。质量门通过后会生成:

  • macOS Apple Silicon (aarch64) DMG 和 scheduler ZIP。
  • macOS Intel (x86_64) DMG 和 scheduler ZIP。
  • Windows x64 MSI、NSIS installer 和 scheduler ZIP。
  • 覆盖全部安装包与 scheduler ZIP 的 SHA256SUMS

每个 scheduler ZIP 都包含对应平台的预编译 CLI、安装/卸载脚本和 MIT License。Workflow 会先核对预期资产并验证校验和,再发布 GitHub Release。稳定版本的 macOS 构建必须通过 Developer ID、hardened runtime、notary ticket、syspolicy_checkspctl 检查;版本中带 - 的预发布会生成未签名 DMG,并挂载检查其中应用二进制的 arm64 / x86_64 架构。所有第三方 Actions 都固定到经过审计的完整 commit SHA。

当前不构建 Linux 安装包。发布前需要同步更新 package.jsonCargo.tomlsrc-tauri/Cargo.tomlsrc-tauri/tauri.conf.json 中的版本。

安装包签名说明

稳定版 macOS Release 中的 app bundle 强制使用 Developer ID Application 证书并完成 Apple notarization。Workflow 会只读挂载生成的 DMG 并检查其中的实际 app;缺少以下任一 GitHub Actions repository secret 时,稳定版 Release 会在构建前失败。DMG 内的 app 未通过构建时的签名、公证或 Gatekeeper 检查时也不会发布:

  • APPLE_CERTIFICATE:Developer ID Application .p12 的 Base64 内容。
  • APPLE_CERTIFICATE_PASSWORD:导出 .p12 时设置的密码。
  • APPLE_ID:Apple Developer 账号邮箱。
  • APPLE_PASSWORD:该账号的 app-specific password,不是登录密码。
  • APPLE_TEAM_ID:Apple Developer Team ID。

可使用 GitHub CLI 交互式写入 Secrets,避免把密码保留在 shell history:

gh secret set APPLE_CERTIFICATE < certificate-base64.txt
gh secret set APPLE_CERTIFICATE_PASSWORD
gh secret set APPLE_ID
gh secret set APPLE_PASSWORD
gh secret set APPLE_TEAM_ID

Apple notarization 需要付费 Apple Developer Program 账号;免费账号只能用于开发测试。证书准备和环境变量定义参见 Tauri macOS signingTauri environment variables

版本中带 - 的开发预发布不要求这些凭据,Workflow 会使用 --no-sign 分别打包 Apple Silicon (arm64) 与 Intel (x86_64) DMG,并验证 DMG 内应用的芯片架构。这些 DMG 未签名且没有 notarization。核对校验和后,可先尝试打开一次,再到“系统设置 > 隐私与安全性 > 安全性”选择“仍要打开”进行一次性授权。也可以对已核验来源的本地副本执行:

xattr -dr com.apple.quarantine "/Applications/Codex Queue.app"
open -b io.github.baicie.codex-queue

xattr -dr 会递归移除该 app 的 quarantine 属性,相当于绕过这一副本的 Gatekeeper 隔离。只应对已核对 Release 校验和的历史包使用;它不是正式的签名或发布修复。

Windows 安装包目前仍未签名,Microsoft Defender SmartScreen 可能显示未知发布者警告。请只运行从本仓库 Release 获取并核对版本的文件。参见 Tauri Windows signing

Demo 限制

  • 机器完全关机时无法在 01:00 执行。Windows wake timer 取决于硬件和电源设置;macOS 会在唤醒后补跑。
  • macOS LaunchAgent 需要用户已登录;Windows 任务也按设计要求交互式会话。
  • Windows Task Scheduler 会在四小时后停止任务。中断的 running 任务会在仍有尝试次数时于下次调用恢复;最后一次尝试被中断则标记为 failed
  • 本 Demo 选择操作系统调度器,使 Tauri UI 未运行时仍可启动 scheduler CLI;任务执行仍要求当前用户的 Codex CLI 登录状态有效。
  • JSON 加文件锁适合单 worker demo。生产多 worker 队列应使用带 lease 和 idempotency key 的 SQLite 或服务端数据库。
  • 重跑示例队列前,需要将状态重置为 pending,并移除 attemptsstartedAtfinishedAtlastErrornextRetryAt

License

MIT

About

Cross-platform Rust scheduler for dependency-aware Codex task queues

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages