从消息通知到继续会话:Push9 的 Codex Runner 实现

简介: 介绍 Push9 Codex Runner 的实现:网页下发任务、本机执行 Codex CLI、回传摘要并发送通知,以及通过原会话继续任务。重点涉及任务与通知分离、领取与提交幂等、断线恢复、结果通知状态和本地会话恢复边界。

从消息通知到继续会话:Push9 的 Codex Runner 实现

跑一个耗时的代码任务时,真正影响使用体验的,往往是完成之后的那一步:人已经离开电脑,结果还停在终端里;手机收到通知,又得回到原设备才能补充要求。

我在 Push9 中做的 Codex Runner,围绕这两个间隙设计:网页下发任务,本机运行 Codex CLI,完成后回传摘要并发送消息;打开消息详情,可以继续同一项目里的原会话。本文只讨论这个功能的实现,不展开介绍其他消息渠道。

以下依据项目中 Runner 0.6.0 的 Go 客户端、Java 后端及接入文档整理。界面图片来自项目已有的隔离演示环境,结果为演示数据;本文没有另外执行真实模型任务,也不将演示截图当作效果测试。

1. 把任务执行与结果通知分开

任务、执行与消息回传的闭环

图 1:按当前实现整理的架构示意。任务通过 Runner 协议领取,Topic 只负责可选的结果通知。

这个闭环有四个角色:网页负责选择设备、项目和提交自然语言指令;后端保存任务、校验归属并管理领取状态;Runner 在本机调用执行器;消息系统投递执行后的摘要。

这里有一个容易混淆的边界:发一条普通推送,不等于创建一个 Codex 任务。 普通推送 API Token 不具有 Runner 执行权限,任务也不依赖 Topic。未配置通知 Topic,仍然可以在网页下发任务并查看结果。

接入消息的目的,是把“结果到了”和“还要做什么”串起来,而不是让每一条通知都变成远程命令。

2. Runner 主动出站,项目路径留在本机

Runner 是独立的 Go 可执行程序,主动访问服务端领取任务,因此这条任务链不要求开发电脑开放公网入站端口。执行 Codex 任务时,仍需在本机另外安装 Codex CLI 并完成登录;Runner 不内置模型。

首次使用分成三步:

  1. 在网页创建 Runner 设备,获取一次性绑定码。当前有效期为 10 分钟,只能使用一次。
  2. 在本机运行客户端,输入绑定码,登记允许操作的项目目录。
  3. 保持 Runner 运行,回网页选择设备和项目,提交任务。

Runner 首次配置与项目选择

图 2:项目已有的客户端向导展示,路径与绑定码是示例值,图中的 CLI 版本只代表该演示素材,不代表当前推荐版本。

命令行也可以显式完成配置。以 Windows 为例:

.\push9-runner.exe setup --server https://push9.top `
  --project "D:\work\example-project" --sandbox read-only

这条命令用于配置,不应理解为已经完成绑定或执行任务;继续按客户端提示输入网页生成的绑定码。第一次验证建议使用只读项目,再发送“介绍目录结构,不修改文件”这样的任务。

项目的实际路径与沙箱策略保存在本地。服务端以项目标识调度,不能在任务正文里指定一个新的任意工作目录。配置目录包含设备凭据,不应放进代码仓库或截图共享。

3. 下发任务先处理幂等,再考虑执行

选择设备、项目并下发只读任务

图 3:隔离演示环境中的任务表单。每台设备同时执行一个任务。

管理侧创建任务使用登录凭据,而不是普通推送 Token。当前请求结构如下,所有 ID 均应来自当前账号的设备与项目列表:

POST /api/runner-tasks
Authorization: Bearer <console-jwt>
Content-Type: application/json
{
   
  "runnerId": "<runner-id>",
  "projectId": "<project-id>",
  "prompt": "只读取项目并介绍目录结构,不修改文件。",
  "requestKey": "a7f18392c6e04b5fa0d297c84e63b159"
}

requestKey 是同一次提交的幂等标识,需要生成 32–128 位、由字母数字下划线或短横线组成的安全随机值。示例仅展示格式,不能在不同任务里复用固定值。

如果网络断开,客户端不知道任务是否创建成功,应保持同一个键和同一份内容重试。服务端返回原任务;真正创建下一条任务时才换新键。仅在前端把按钮变灰,不能解决刷新页面、并发请求或响应丢失带来的重复创建。

Runner 的领取又有另一层幂等:它先把随机 claimId 写进本地执行日志,再请求 /api/runner/v1/claim。领取响应丢失时,继续使用原 claimId,而不是再领一个任务。服务端通过设备锁、任务状态和租约校验,限制同设备并发执行。

4. Codex 是本机子进程,输入通过 stdin 传入

客户端 executor.go 中的基础参数构造可概括为:

args := []string{
   "-a", "on-request", "-s", project.Sandbox, "exec"}
if task.SessionID != "" {
   
    args = append(args, "resume", task.SessionID)
}
args = append(args, "--json", "--skip-git-repo-check", "-")

这是该项目当前版本的实现片段,不是适用于所有版本的安装说明。执行器使用原生进程调用,工作目录取自已登记项目,任务文本通过标准输入传入,不把用户指令拼接成 Shell 命令。项目只允许 read-only 和 workspace-write 两种沙箱配置。

--skip-git-repo-check 用于跳过 Git 仓库前置检查,不是关闭沙箱;本机认证、项目规则与审批约束仍然存在。遇到需要确认而当前执行方式无法完成的情况,任务可报告 WAITING_CONFIRMATION,用户需要回到本机检查。

比起抓取整段终端文本,Runner 更关心结构化事件:

Codex JSONL 事件 Runner 的处理
thread.started 校验并记录会话 UUID
item.completed,且类型为 agent_message 更新最后一条 Agent 回复摘要
turn.completed 记录完成标记
turn.failed 或 error 记录失败,必要时提示本机确认

判断结果会结合会话、完成事件和进程状态,而不是见到一行输出就认定成功。回传的摘要最多 4000 字符,当前实现不上传完整 Shell 输出或推理日志。

5. 断线恢复最重要的是“不再执行一次”

写代码、运行脚本都可能已经产生副作用。一次网络重试可以接受,盲目重跑任务则可能重复修改文件。

Runner 在本地保存三个主要阶段:

claim      先记录领取标识,再向服务器领取
executing  记录已开始执行,随后运行 Codex
report     先保存结果,再尝试回传

如果任务执行完成、但结果上传失败,重启后继续回传已保存的结果。如果重启时日志停在 executing,客户端不会假定任务未执行,而是记录中断并上报 INTERRUPTED,要求检查本机进程与文件变化。

这不是对所有外部副作用的“严格恰好一次”保证,而是把网络重试与任务重跑区分开。取消或终止进程也不会撤销已发生的文件修改或外部操作。

6. 通知失败,不能把已完成任务变成失败

服务端保存任务结果后,如果配置了通知 Topic,会把通知状态设为 PENDING。后台 RunnerWorker 使用独立的 outbox 逻辑发送消息,并使用如下键关联同一任务的结果通知:

runner-result:<task-id>

当前消息正文取最后摘要,最多截断至 3600 字符。通知提交失败会按实现中的尝试次数与退避策略重试;消息系统接受通知后记录 ACCEPTED。这只表示通知已进入消息系统,不等于用户手机已收到或已读,还要看渠道投递结果。

因此,应分别观察两种状态:

  • 任务 COMPLETED,通知 FAILED:任务结果已保存,检查消息投递链路,不要重跑 Codex。
  • 任务 FAILED,通知已受理:失败摘要仍可以发送,方便用户及时发现问题。

通知 Topic 可能有多个成员。摘要虽然不是完整日志,仍可能包含业务信息,配置前应确认接收范围。

7. 从通知继续原会话,不能只靠一个链接

查看结果摘要与继续会话入口

图 4:隔离演示环境的结果详情,截图中的“已完成”及摘要均为演示数据,不代表本文新执行了任务。

网页里的“继续会话”会创建后续任务,客户端使用明确的 sessionId 执行 exec resume,不会恢复“最近一个会话”。本地还必须保留原会话文件,并使用对应的系统用户、项目和 Codex 环境。

消息详情也提供下一条指令入口:

POST /api/runner-tasks/from-message/{messageId}
Authorization: Bearer <console-jwt>
X-Message-Key: <message-view-key>
Content-Type: application/json
{
   "prompt":"继续检查测试入口,先说明计划,不修改文件。"}

消息查看密钥和账号登录需要同时满足;持有分享链接,或只是 Topic 成员,都不能直接控制设备。设备、项目和会话由原任务确定,不接受请求方随意替换。

当前实现中,每条通知只能提交一次下一条指令。同内容重试返回同一个后续任务,换内容再次提交会产生冲突;后续任务完成后,新通知才提供新的继续入口。身份验证或打开通知本身不会自动提交指令,仍需用户点击发送。

本地已结束的 Codex 会话也可以通过客户端 attach 选择后登记。登记只上传会话标识与标题摘要,不把整段聊天同步到云端,也不能接管桌面里正在运行的会话。

8. 实际排查时,先分清哪一段没有完成

现象 优先检查
网页一直排队 Runner 是否运行、设备是否在线、项目是否登记并启用
提示需本机确认 Codex 是否安装登录、执行器路径及审批要求
任务已完成但没有推送 是否选择通知 Topic、通知状态及渠道投递回执
不能继续会话 原 session 文件、系统用户、项目与 CODEX_HOME 是否保持一致
Runner 重启后显示中断 检查进程和文件变更,不直接重复发送原任务

这套实现目前也有明确边界:Runner 需要持续运行;后台启动不等于开机自启;没有网页远程审批或实时终端;云端会话记录不能替代本机历史。它解决的是“任务下发—本机执行—结果通知—原会话继续”的协作流程,而非把开发电脑完整搬到网页里。

实现参考:Push9 Runner 接入文档 push9.top/docs#runner。源码核对位置为项目内的 runner.go、executor.go、RunnerService.java 与 RunnerWorker.java;本文基于现有实现与文档整理,未提供额外性能测试结论。

目录
相关文章
|
存储 自然语言处理 Java
Elasticsearch常见面试题
Elasticsearch常见面试题
|
存储 分布式计算 监控
Hologres产品介绍与技术揭秘
近年来,随着数据实时化的诉求加剧,催生了一系列的实时数仓架构,Lambda架构也应运而生,但是随着场景的复杂度和业务多维需求,Lambda架构的痛点也越来越明显。HSAP的理念则是服务分析一体化,在本文中,来自阿里巴巴的资深技术专家将会深度剖析HSAP技术实现Hologres的设计原理,解读其产品典型场景。
13769 0
Hologres产品介绍与技术揭秘
|
移动开发 算法 调度
【贪心算法】一文让你学会“贪心”(贪心算法详解及经典案例)
贪心算法是一种非常常见的算法,它的简单和高效性使其在实际应用中被广泛使用。 贪心算法的核心思想是在每一步都采取当前状态下最优的选择,而不考虑未来可能产生的影响。虽然贪心算法不能保证总是得到最优解,但在很多情况下,它可以获得很好的结果。 本篇文章将介绍贪心算法的基本概念和一些经典应用,以及如何通过贪心算法来解决一些实际问题。希望通过本文的阅读,读者可以对贪心算法有更加深刻的理解,并能够在实际问题中应用贪心算法来得到更好的解决方案。 让我们暴打贪心算法吧!
7213 0
|
8月前
|
监控 数据可视化 Linux
从0到1部署OpenClaw保姆级教程:阿里云/本地免费大模型API配置+ClawDeckX可视化管理及常见问题解答
OpenClaw作为开源AI智能体框架,凭借可操控本地系统、对接多平台工具的特性成为技术圈关注的焦点,而ClawDeckX的出现则为其搭建了友好的Web可视化管理平台,大幅降低了OpenClaw的使用门槛。2026年,针对阿里云、MacOS、Linux、Windows11多环境的零基础部署需求,本文将从环境准备、部署实操、阿里云百炼API配置、ClawDeckX使用到常见问题解答进行全流程拆解,同时融入代码命令与实操细节,让新手也能完成OpenClaw(Clawdbot)的本地部署与调试。
2039 5
|
存储 前端开发 算法
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析(一)
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析
1153 0
|
7月前
|
人工智能 自然语言处理 数据可视化
阿里云百炼上线DeepSeek-V4:API 价格与官网一致,百万Tokens输入最低1元、输出最低2元
阿里云百炼正式推出DeepSeek-V4系列模型,包含DeepSeek-V4-pro和DeepSeek-V4-flash两款,全模型享受低至4.5折优惠,API价格与DeepSeek官网一致,百万Tokens输入最低1元、输出最低2元。该系列模型覆盖全面、成本优化显著且使用便捷,支持跨模型使用,承诺消费越高、周期越长,折扣越大。活动提供多种包月、包季套餐及特惠价格,满足不同用户需求,助力企业和开发者轻松实现AI落地,广泛应用于电商营销、广告创作、短剧漫剧、AI Coding、智能客服及AI办公等领域。
10400 4
|
敏捷开发 Devops 测试技术
阿里云开发测试工程师专项认证,为你的DevOps能力加码!
面对日益增长的发展就业机会和残酷的市场竞争环境,作为一名开发测试工程师,我们该如何提升个人能力和价值,成为企业迫切需求的DevOps高级人才,为晋升加码?
10358 101
|
人工智能 小程序 前端开发
AI | Stable Diffusion系列教程(二)
上一期更新了如何安装以及简单使用,这一期简单的讲讲常用的几个功能,以及下载模型,通过模型来生图。
934 0
AI | Stable Diffusion系列教程(二)
|
Kubernetes 架构师 测试技术
软件测试|测试专家(前阿里P8)聊测试职业发展常见瓶颈
软件测试|测试专家(前阿里P8)聊测试职业发展常见瓶颈
|
机器学习/深度学习 数据采集 存储
机器学习实战 | 机器学习特征工程最全解读
本篇内容给大家详细讲解了特征工程的知识,包括数据清洗(数据对齐、缺失值处理、异常值处理),特征构建,特征变换,特征选择与实战特征工程经验等内容。
6711 1
机器学习实战 | 机器学习特征工程最全解读

热门文章

最新文章