makecindy / makecindy/cindy

修改子代理配置后,已完成的 Codex 会话新输入被全局冻结并持续显示 Stop

Open
#2,672 1 comment 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
2.7k
Forks
395
Avg merge
21h 48m
Merged PRs (30d)
776

Description

**提交人**: zym
**客户端版本**: 0.1.46

---

## 现象

在多个本地 Codex 会话同时运行时修改子代理启动配置,会触发全局 Codex 延迟重启。某个会话已经输出最终回复并完成持久化后,继续发送新消息仍会进入等待队列,无法开始执行;界面同时继续显示 Stop 按钮,看起来像上一轮任务尚未结束。

fork 成新会话后可以正常发送,因此问题集中在修改配置前已经存在的本地 Codex 会话。

## 复现步骤

1. 同时运行多个本地 Codex 会话,其中至少保留一个较长时间运行的任务。
2. 在设置中修改会影响 Codex 启动的子代理配置。
3. 等待其中一个会话正常输出最终回复并显示完成。
4. 在这个已完成的旧会话中发送下一条消息。
5. 观察消息进入队列且无法执行,输入区域显示 Stop。
6. fork 或新建会话后发送消息,可以正常开始执行。

## 期望行为

- 已完成会话的新输入应正常派发;如果必须等待共享 Codex 服务重启,应明确显示“等待其他任务结束后自动发送”及阻塞原因。
- 单纯存在等待消息时,不应显示成模型仍在运行,也不应显示 Stop。
- 一个长任务不应在无明确提示的情况下冻结所有已完成旧会话的后续输入。

## 实际行为

- 修改配置后进入全局延迟重启状态。
- 延迟重启完成前,所有已经存在的本地 Codex live 会话的队列派发都被阻止。
- 已完成会话发送的新消息只进入普通队列,没有出现配置重启等待提示。
- Renderer 将“队列中有消息且队列未暂停”直接计为 busy,因此持续显示 Stop。
- 新建或 fork 会话可以运行,导致旧会话看起来像状态没有收口。

## 复现频率

已经多次出现。通常与运行中存在多个 Codex 会话、修改子代理启动配置、至少一个其他任务长时间未结束同时发生。

## 已尝试

- 等待原会话正常输出最终回复,问题仍存在。
- 在原会话继续发送,新消息持续留在队列。
- fork 为新会话后可以正常运行。
- 已只读检查本地日志、会话数据库和对应源码,没有通过退出或重启 Cindy 规避问题。

## 脱敏诊断摘要

用户同意公开以下脱敏摘要:

- 复现版本为 Cindy 0.1.46。
- 某次复现中,配置变更后日志记录全局延迟 Codex 重启,原因是仍有多个本地 Codex 会话处于 busy。
- 随后目标会话的 Codex rollout 已产生最终回复和 `task_complete`;会话数据库中结束时间晚于本轮开始时间,持久化层已确认该轮结束。
- 约 1 分钟后发送的新输入出现在输入队列快照中,但没有被派发。
- 同期仍有其他 Codex 长任务真实运行,全局延迟重启一直未进入 applied 状态。
- 源码中的延迟重启门禁会在 pending 期间拦截所有既有本地 Codex live 会话;此拦截发生在真正发送前,因此没有进入现有的可见 credential-switch wait 分支。
- Renderer 的 busy 判断包含 `pendingQueueLength > 0 && !queuePaused`,所以等待队列会直接表现为 Stop 按钮。

诊断摘要不包含会话 ID、个人路径、邮箱、令牌、业务对话或无关文件内容。

## 建议修复

1. 延迟 Codex 重启阻止派发时,将等待原因和阻塞会话投影到界面,复用现有可取消的等待横幅。
2. 区分“模型运行中”和“消息等待共享服务重启”,等待态不要显示 Stop。
3. 评估让已完成会话关闭旧 handle,并在下一次输入时按新配置懒重建,缩小全局冻结范围。
4. 增加多会话、长任务、配置变更、旧会话续发及 fork 的回归测试。
---
**版本区域**: CN
**OS**: darwin arm64 (25.5.0)
**界面语言**: zh-CN

Contributor guide

Open the contributing guide

Research direction

Start by tracing the delayed Codex restart gate, the queue-dispatch path for existing live sessions, and the renderer busy predicate that uses pendingQueueLength and queuePaused. Compare this with the existing credential-switch wait branch. Done means completed sessions can accept later input, restart blocking is visible with its reason, waiting does not show Stop, and regression coverage exercises multiple sessions, a long task, configuration changes, and forked sessions.

Written by the indexing model from the issue text.

Assessment

Tech stack
electron, typescript
Domain
backend, desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.