Repository navigation
fix(chat): preserve long-running turns and accepted queued queries - #7790
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent | gpt-6.1-sol | OpenAI | runtime_reported | reasoning_effort=max
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
APPROVE:未发现阻塞问题。审查完整 head 289912d3fb90ee7199ad49dee7aaae106e0e00d1;结论覆盖源码切片,实际服务采用与原业务办结继续单独验收。
动机 / Motivation
普通 Chat 用户在一个持续产生活动的任务之后继续发消息时,会遇到执行被截断、后续输入尚未开始就丢失的问题。
旧版默认任务最长 15 分钟,已配置的正数期限也会中断仍有活动的工作,队列默认一小时过期;新版普通交互任务默认无总时长截止,已接受输入保持原身份等待执行,显式期限和 Stop 继续有效。
已验证源码能跨越原截止继续完成,并在两天后从原文件队列认领同一输入;这是源码行为资格,不代表现有安装已改变。
本 PR 不自动重放历史失败,不更换 Session、账号或权限,也不取消 Goal、租约、实验预算及有界 managed-host segment 的期限。
现有安装中的显式正数设置仍需经原服务管理器变更;历史失败的效果核对、剩余工作与原受众回传由原请求和接收者继续负责。
改动思路 / Approach
截止与排队策略留在原生 Chat 的既有 owner,复用既有可空期限、文件队列和共享启动解析,没有新增调度器、恢复日志或第二消费者。
本次可独立交付的边界是普通交互任务和已接收输入的寿命规则;安装采用与效果核对后的业务恢复分别验收。
与保持现状相比,单纯把执行上限再调大只能推迟中断,也无法解决后续输入一小时过期;另造恢复队列则会多出效果核对和幂等责任。这里直接修正原 owner 的默认值和转换规则。Codex 原循环已经独立判断 idle(多久没有收到活动);ACP 的等待改为同时取绝对截止和 idle 截止的较早者。明确指定的限时与停止操作都继续生效。
下表解释源码行为变化,绑定当前 head;它不是现场执行回执。
| 输入或状态 | 原行为 | 本次行为 |
|---|---|---|
| 普通交互默认值 | 总时长 900 秒 | 无默认总时长截止,仍有启动与 idle 检测 |
显式 hard 0 |
转为 0.1 秒 | 转为 None,只取消总时长截止 |
| 正数 hard / 显式队列 TTL | 到期中止 | 仍按原期限中止 |
| 默认排队输入 | 一小时未开始则过期 | 原身份保留至执行或停止,容量仍为 20 |
| 已安装的正数设置 | 保留 | 继续保留,普通升级不会擅自清除 |
具体改动 / Changes
完整差异为 14 个文件、+171/-24:生产代码 8 文件 +31/-22;测试和合成服务脚本 3 文件 +101/-2;文档 3 文件 +39。没有新增后台服务、业务重放器、持久字段或第二套恢复决策。
关键代码讲解
chat_server_options是 Chat/dashboard 和正常宿主使用的共享转换入口。它先拒绝负数、NaN、Infinity,再把0转成None;1800 等正数原值传递。错误发生在服务或模型启动之前。独立测试同时检查默认、零值和正数,避免只验证 parser 接受参数却没确认实际下游含义。ACPStdioAdapter._request只让绝对 deadline 可无限,仍使用min(deadline, idle_deadline)轮询真实消息;收到活动才续 idle。start_turn分类错误前检查 hard 是否存在,因此无活动仍返回idle_timeout,而显式 hard 到期仍返回hard_timeout。我通过公开start_turn路径测试,额外覆盖了只测私有等待函数可能漏掉的错误分类。ChatIngressStore.create_queued_turn复用原 Session 锁、client id 内容匹配和文件写入。默认把既有expires_at写成 null;显式 TTL 仍写日期。原claim_next_queued_turn已支持 null,所以不需要改历史记录或迁移器。两天后重开文件存储仍认领同一 Turn;相同 id 不同正文拒绝,21 条输入触发原容量拒绝。
规范依据是 PR 修改之前已接受的 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,spec_revision 0e78a19c277f4ca3d44313787162bc0444065172(固定版本)。本次涉及的原验收行映射如下:Acceptance 对应原身份与单次受理;Dispatch 对应排队/重启/准备失败;Correction/stop 对应精确停止;Managed 对应独立启动、idle 与期限;Authority 对应撤权拒绝及另一受众继续。上述各行在本切片均 implemented,分别由下列同输入对比、准备/停止与来源回归支撑;不据此宣称整张矩阵或安装态已经完成。修改中的 roadmap 只记录该范围,没有被用来反向定义验收标准。
对主干的风险 / Risks
最重要的反例是取消总时长截止时,连无活动检查或独立操作预算也被取消。已检查 Codex/ACP 两条路径及 unchanged operation-host 调用:前两者保留独立 idle;有界 managed-host segment 在 None 时仍回落 900 秒,operation host 继续传自己的显式期限。排队也继续经过原来源/grant 校验和精确 Stop,默认寿命变长没有赋予新权限。旧有限 expires_at 保持原到期结果,失败记录没有被重开。
验证均在当前完整 head 执行,使用合成协议与真实文件存储,未发起模型或基准任务:
- PASS:六个相关 pytest 文件 101 项;另选原受众隔离、撤权与 Stop 路径 5 项通过。
- PASS:独立相同 fixture(SHA256
a9132316d6590fb1e9b546b0b4ef7e61321ae28efa085eaf87bccfd175a25827)在 base 4 FAIL / 3 PASS,在 head 7 PASS。旧版失败逐项是 CLI 默认/零值、默认 native send、默认 ACP start_turn、两天后的原队列认领;显式期限、idle 和容量负例保留。两边 1131 个已加载 LoopX 模块均核对来自各自不可变源码根。时间被模拟,原决策循环实际执行,文件队列真实重开;这不是运行两天的现场模型试验。 - PASS:实际
macos-dashboard-launchagent.sh的完整合成 HOME/manager/provider fixture,经仓库标准uv run --extra test python examples/macos-dashboard-launchagent-status-smoke.py路径通过,零截止经 install/restart 保留,idle 与存储身份保留。最初系统 Python 调用在原有首个 install 步失败,内层 stderr 未捕获,原因仍未归类;原记录保留,未修改断言或产品代码来使后续通过,也不将它宣称为已修复故障。 - PASS:标准
canary premerge --from-git-diff --git-diff-base 0e78a19c277f4ca3d44313787162bc0444065172的 19 项选择检查无阻塞失败,另有直接差异、编译、双语 RFC、Ruff 和公开边界检查。维护性检查的既有host_process_transport.run_host_processadvisory 仍 FAIL:正确保留 tracked-set 的独立 base/head 全报告完全相同,规范化 SHA256 均为56c0da43debe595a03434f988d0b87c5ebfd9e57b2784fe8110463666f34f82c,该文件、检查源码及阈值未变;不把 advisory 写成通过。
语义与 CI 对齐
复用已有可空截止和队列字段,明确披露默认变化,没有新 actor 协议或扩大恢复、授权、配额义务。当前策略 wait_for_ci=false,本次没有查询、轮询或等待远端 CI。本地资格与 merge-readiness 分开;CQR 当前 Goal policy disabled,未伪造 receipt。可通过显式正数恢复有限执行期限;任何安装回退仍由正常服务管理器保留原 Session、来源和历史。
我的整体评价 / Verdict
这是 justified_increment:源码对持续工作和后续输入的保留已带来可独立验证的改进,long_horizon 与 user_experience 均为 improved。用户正常发一次消息即可等待原结果,不因默认年龄限制再增加一次提交;现有 Stop 和失败读回继续可用。生产机制规模合理,兼容层仅保留已有正数配置和历史有限期限,没有需要同步的第二份状态,也没有 default-off 隔离主张。
截止与排队策略留在原生 Chat 的既有 owner,复用既有可空期限、文件队列和共享启动解析,没有新增调度器、恢复日志或第二消费者。 本次可独立交付的边界是普通交互任务和已接收输入的寿命规则;安装采用与效果核对后的业务恢复分别验收。
视觉检查不适用:完整差异没有改变渲染呈现,复用了现有 Chat/Lark 进展与停止界面。仍未验证的范围是安装态长任务、实际模型采用和后续业务结果理解。取消总时长截止仍可能增加宿主额度消耗,idle 与 Stop 不是业务成功证明。已有服务正数配置、历史效果核对和原受众最终回传需要独立完成;这些限制不掩盖为本 PR 的“自动重放已完成”。未发现阻塞问题,保留以上残余风险。
English verdict: APPROVE this source slice at 289912d. Existing explicit limits and source/Stop boundaries remain; installed adoption and effect-aware recovery are separate acceptance.
Goal And Delivered Outcome
持续正常活动的交互任务会被默认硬截止中断;后续已接收消息也可能在前序工作结束前被默认一小时 TTL 丢弃。此前 CLI 还把
--hard-timeout-seconds 0压成 0.1 秒,无法表达取消总时长截止。普通 Codex/ACP Chat 默认取消总时长截止,并让
0经共享启动参数 owner 传成None。保留启动期限、无活动检测、显式正数期限和停止操作。ACP 等待循环支持无绝对期限,同时保留独立 idle deadline。排队输入默认没有隐式 TTL,显式 TTL、20 条容量、原消息幂等身份、来源和停止校验继续使用原 owner。macOS 服务配置接受并保留硬截止0;旧显式设置保持原值,必须经正常服务管理器改变后才生效。Author Declaration
Written by: model_agent — Codex, OpenAI GPT-6 family.
Implemented against: existing native Chat adapter, ingress and service-option contracts at base 0e78a19. Author implementation finished.
Capability/placement: existing builtin native-chat transport and service configuration; no new capability, shared state vocabulary or Python orchestration owner. Reuse the existing deadline loop, queue and shared startup option composition. The bounded managed-host segment retains its 900-second fallback. Existing operation-host callers explicitly pass their own deadline, including existing
None; experiment/task/lease budgets are unchanged.Validation
Tested revision:
289912d3fb90ee7199ad49dee7aaae106e0e00d1. Synthetic/local transport fixtures; no model or benchmark execution.Scope And Continuation
Default behavior change is intentional for interactive Chat. Continuous work still consumes host model/tool allowance. Existing installed positive deadlines remain effective until their configuration changes. Historical timed-out Turns and their effects stay immutable; this patch does not blindly replay operations, reset receipts, add a scheduler or widen authority. Installed activation and an effect-aware continuation of original failed requests require their normal source/recipient owners.
No visible layout changed; the existing frontend/Lark progress and Stop journey remains. The bilingual user guide explains finite/disabled limits, preserved protections, service adoption and recovery boundaries. This source PR does not claim an installed long-running model result or measured solver gain.