makecindy / makecindy/cindy

[Bug] Codex 通道正文非流式:host 退订 item/agentMessage/delta 导致正文只能在 completed 一次性渲染

Open
#203 3 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
2.7k
Forks
401
Avg merge
21h 48m
Merged PRs (30d)
776

Description

## 现象

Cindy 内 **Codex 通道**的助手**正文**是"一口气"一次性显示,不是逐字流式;而**思考(reasoning)是流式**的。三种来源表现完全一致:

- 官方订阅 GPT(`chatgpt.com/backend-api/codex` 原生 Responses)
- OpenRouter 原生 Responses 直连
- DeepSeek(经 Chat Completions 桥接)

对照组(均逐字流式):

- **官方 codex desktop app**:同样 2000 字逐字流式 → codex 后端本身是流式返回的。
- **Cindy 内 Claude Code 通道**(即使选 GPT 模型):逐字流式。

→ 与模型、后端、provider 来源均无关,锁定在 **Codex agent 通道(`codex app-server` JSON-RPC 集成)** 的正文渲染。

## 根因

`packages/maker-core/src/agents/codex/app-server/host.ts`:

- `NOTIFICATIONS_TO_OPT_OUT`(第 94-95 行)把 **`item/agentMessage/delta`(正文逐 token 增量)主动退订**,注释(第 71 行):"agentMessage 文本流我们仍走 item/updated 全量字段算 diff(省一类 delta)"。
- 但 codex app-server 对 agentMessage **不发中间 `item/updated`**,只在 `item/completed` 给全文。
- 于是 `translator.ts` 的 `handleAgentMessage`(约 501 行,靠 `itemTextLen` 做全量 diff)只能在 `item/completed` 一次性拿到全文 → **一口气**。

对比 reasoning:`SUBSCRIBED_METHODS` 订阅了 `item/reasoning/summaryTextDelta`(host.ts:84,注释明说"claude code 等价体验需要逐字出 thinking")→ 所以思考流式。

即"用 `item/updated` diff 替代 agentMessage delta"的假设不成立,正文退化为非流式。

## 证据

给正文加细分计数日志(每轮 stream done):正文 `textDeltas` 仅在 `item/completed` 时一次性产生;三来源一致;对照 Claude 通道逐 token 流式。

## 影响范围

所有 codex 会话的正文渲染(与模型 / provider 来源无关),先于任何 provider 改动就存在。

## 建议修复(与 reasoning 对称)

1. `host.ts`:把 `item/agentMessage/delta` 从 `NOTIFICATIONS_TO_OPT_OUT` 移入 `SUBSCRIBED_METHODS`,加分发 handler。
2. `protocol.ts`:新增 `AgentMessageDeltaNotification` 类型。
3. `translator.ts`:新增 `handleAgentMessageDelta`,逐 delta emit 正文增量(复用 `itemTextLen` 校准,`item/completed` 只做收尾、不重复吐)。

## 风险 / 门禁(AGENTS.md 规则 10)

maker-core 事件流改动:不动 prompt / cache / tool,仅细化正文 emit 粒度;需实测 delta + completed 文本不重复不丢、usage 不受影响;IPC 量随逐 token 增加(reasoning 已同量级,可接受)。

## 相关

- makecindy/cindy#108(借鉴 OpenCodex 补齐多协议 provider adapter)属 provider 层,与本 issue 的渲染层正交。

> 发现于给 Codex 接入 Chat-Completions 厂商(DeepSeek 等)的联调过程中,但问题与该桥接无关(官方订阅 GPT 同样如此)。

@MagicLizi 请评估修复优先级与方案。

Contributor guide

Open the contributing guide

Research direction

Start in packages/maker-core/src/agents/codex/app-server/host.ts, then trace the notification types and handlers in protocol.ts and translator.ts, especially handleAgentMessage and itemTextLen. Verify the agentMessage delta subscription and dispatch path against the reasoning delta path. Done means Codex正文 streams incrementally, item/completed does not duplicate or lose text, and usage remains unchanged across the described providers.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
ai, backend-api-design
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.