anthropics / anthropics/claude-code
Channel messages are merged into the previous user message and re-rendered on the next request, losing the prompt cache on non-Anthropic backends
- 主要语言
- Python
- 星标
- 145k
- 派生
- 23.1k
- PR 合并指标
- PR 指标待抓取
描述
**Environment:** Claude Code 2.1.268 (Linux/WSL2), Channels (experimental) via the Atrium plugin (`inject directly`), `ANTHROPIC_BASE_URL` → CLI Proxy API → OpenAI Responses (`gpt-5.6-sol` / `gpt-6-astra`). Also observed on 2.1.26x sessions routed to `gpt-6-astra`.
**What I observe.** With a metadata-only diff of consecutive upstream requests (per-item hashes and byte lengths, no content), a session receiving channel messages produces requests that are not append-only: the previous user message is re-rendered (1,516 B → 2,552 B when a channel message is delivered, then split into 364/436/317 B + a new item on the next request), and `reasoning`/thinking items of the affected turns are inserted or removed before an earlier assistant message. Example windows from the trace: `assistant:88 | user:1516` → `assistant:88 | user:2552`; `reasoning:1835 | reasoning:1535 | reasoning:1515 | assistant:86` → `reasoning:1835 | assistant:86 | user:…`.
It happens whether the channel message arrives during an open turn or while the session is idle (tested with a channel-side hold that delivers only after the Stop hook: same rewrites).
**Why it matters.** On Anthropic the change costs a small cache write (cache_control breakpoints + lookback). On OpenAI's GPT-5.6+ prefix cache, any change before the end of the prompt invalidates everything after it, and explicit breakpoints are rejected by the Codex/ChatGPT-OAuth backend. Measured: on ~300K-token sessions, 8–15 % of requests re-billed the whole context (e.g. 46 requests × ~250K uncached tokens in one day); on a fresh session, 14–21 rewrites over 20–30 requests. Related reports: #76606 (hook system-reminder transformed later), #78660 (task_reminder attached to an old human message), #64901, #80604, #48734.
**Expected.** A delivered channel message (and hook/system-reminder attachments) should be appended as a new user item, and already-sent items should stay byte-stable across requests, so that append-only prefix caches keep working.
**Repro.** Any session with a channel plugin: send a message via the channel while the session is idle, then another one; compare the two API request bodies item by item (or watch `cache_read_input_tokens` drop when routed to a prefix-cache backend). A full dossier (traces, journal of a channel-side hold, before/after runs) is available on request.
Am I missing a setting that changes how channel messages are injected? If this is by design, is there a supported delivery mode that does not rewrite earlier items?
贡献指南
这个仓库没有索引到贡献指南
调研方向
Start by tracing the Channels experimental plugin's `inject directly` delivery path and the construction of consecutive upstream API request bodies. Compare item hashes and lengths across idle and open-turn deliveries, then verify that delivered messages append as new user items, earlier items remain byte-stable, and prefix-cache reads no longer drop on supported backends.
由索引模型根据 Issue 内容生成。
评估
- 领域
- api, backend, performance
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 活跃
- 描述清晰度
- 基本清楚
- 新手友好度
- 45/100