Skip to content

fix(agent-core-v2): backport prompt-cache compaction fix (#4456) - #4471

Merged
7Sageer merged 1 commit into
release/2026-10-28from
backport/compaction-prompt-cache-20261028
Oct 27, 2026
Merged

7Sageer merged 1 commit into
release/2026-10-28from
backport/compaction-prompt-cache-20261028

Conversation

@7Sageer

@7Sageer 7Sageer commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Requirement or Bug

Bug Reproduction Steps

See #4456.

Root Cause

See #4456。这是那笔 squash 的原样回移,不是新的修复。

Code Changes

release/2026-10-28 @ 78b72fe (#4460)
  └─ cherry-pick 68a2838941 (#4456)

补丁与 68a2838941 逐字节一致,15 个文件,+614/-121。没有带入 #4457。

不新增 changeset。落地的 squash 在合入前删掉了 .changeset/fix-compaction-pre-shrink-cache.md,净 diff 里没有 changeset;#4195、#4383 的回移同样不加。release 上已有的 fix-compaction-prompt-cache-deferred-tools.md 属于 #4410,2.4.0 说明里已经有了。

合入这条 release 不会发版。发版仍要等 #4463 在这之后合入。

Behavior Changes and Affected Users

与 #4456 相同。

Behavior Before After Who relies on the old behavior Escape hatch
请求估算在「0.85 × (W − 预留) − overhead」到「W − 预留」之间时,compaction 首次请求的历史 从最旧消息开始裁掉,首次请求一定能放进安全预算 发送完整历史,输出上限钳到剩余窗口;估算偏低导致实际超窗时,走原有的 0.7/0.5/0.35 超窗回退 所有客户端(TUI、print 模式、desktop 与 web、VS Code、ACP、SDK)中窗口大于约 195k 的模型的自动 compaction,以及上下文超过约 0.744W 时的手动 /compact 无需退路:输入加钳制后的输出上限不超过窗口
请求估算超过「W − 预留」时 预裁剪到 0.85 安全预算 不变 — —
compaction 请求的 max_tokens 固定为 maxOutputSize(或默认 min(W, 128k)、modelOverrides.maxCompletionTokens),不随输入收窄 min(上述上限, W − 请求估算 − 2%W);显式 opt-out(≤ 0)仍不发送 所有 provider 方言的 compaction 请求 无需退路:只收窄超出窗口的部分
窗口未知(≤ 0)时 跳过预裁剪 不变 — —
413 之后继续追加媒体 每次请求重算「保留最近 2 张」,新图替换旧图,前缀断开 按 413 当时的降级数量钉住;继承的降级请求再次 413 且可见媒体超过 2 张时才重新降级,而不是直接 strip 所有会在超限后继续发图的客户端 无需退路
prompt_cache_probe 只有 fork 首个 turn 请求 增加 compaction 首个成功响应的 source=compaction;fork 行为不变 未按 source 过滤的缓存命中率聚合会混入 compaction 样本 按 source=fork / source=compaction 分别聚合
docs/state-manifest.d.ts 的 llmRequester.lastTurnRequest model、revision、system/tools hash、usage、时间 增加 messageCount / historyHash;不持久化消息,不新增 wire 字段 读取状态检查接口的调试工具 未知新增字段可忽略

受影响模块:packages/agent-core-v2/src/agent/fullCompaction/fullCompactionService.ts、src/agent/contextProjector/、src/agent/llmRequester/、src/app/telemetry/events.ts,以及 docs/state-manifest.d.ts。测试随 #4456 的提交一起回移,覆盖完整历史前缀、超窗预裁剪、输出上限钳制、媒体降级前缀和 compaction probe。

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue (external PRs: issue must have a maintainer's /approve).
  • I have added tests that prove my feature works.
  • The behavior-change table above is complete, and every removed behavior or flipped default is named in the changeset and either has an escape hatch or was explicitly approved by a maintainer in this PR.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

)

* fix(agent-core-v2): only pre-shrink compaction history when the request overflows the window

The pre-shrink budget (~0.74 of the window) sat below the auto-compaction trigger (min(0.85W, W-50k)), so every auto compaction on windows above ~195k dropped the oldest messages and broke the prompt-cache prefix. Gate pre-shrinking on the real input limit (window minus output reserve) and keep the safety budget as the shrink target.

* fix(agent-core-v2): pin degraded media to the count captured at the 413

Media degradation recomputed 'keep the 2 most recent' on every request, so each new image after a 413 replaced an older kept image and broke the prompt-cache prefix. Record how many leading media were degraded when the provider rejected the request, re-capture only when an inherited degraded request is rejected again with more than 2 visible media, and drop the prompt-cache guard's tolerance for rolling degradation.

* feat(agent-core-v2): probe compaction prompt cache prefixes

* chore: drop duplicate degraded media changeset

* fix(agent-core-v2): report prefix loss after compaction shrinks history

* fix(agent-core-v2): clamp compaction completion budget to the remaining window

Sending the full history leaves less room than the configured output cap,
so pass the estimated request size as usedContextTokens and let the
provider clamp max_tokens to the window that is actually left.

* Delete .changeset/fix-compaction-pre-shrink-cache.md

Signed-off-by: 7Sageer <sag77r@hotmail.com>

---------

Signed-off-by: 7Sageer <sag77r@hotmail.com>
(cherry picked from commit 68a2838)
@changeset-bot

changeset-bot Bot commented Oct 27, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 6ffd57c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-27T11:18:35.719606Z 6ffd57c PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@pkg-pr-new

pkg-pr-new Bot commented Oct 27, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@6ffd57c
npx https://pkg.pr.new/@moonshot-ai/kimi-code@6ffd57c

commit: 6ffd57c

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6ffd57c7fa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return media;
};
const captureMediaDegradePolicy = (): { readonly degradeCount: number } => {
const media = { degradeCount: this.projector.captureMediaDegradeCount(shaped) };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the existing media-recovery state variant

When a previous-release consumer reads an agent state snapshot after a request-size recovery, llmRequester.mediaRecovery.media now contains { degradeCount } instead of the documented 'degraded' literal, so clients matching the old variant will no longer recognize this state. Preserve compatibility or version/migrate the snapshot contract for those consumers.

AGENTS.md reference: AGENTS.md:L123-L125

Useful? React with 👍 / 👎.

toolsHash: recorded.toolsHash,
systemPromptHash: recorded.systemPromptHash,
messageCount: input.messages.length,
historyHash: fingerprint(JSON.stringify(input.messages)),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stream the history fingerprint instead of serializing it

When a turn carries large inline media (the resolver allows up to 20 MiB per request in AgentMediaResolverService), this JSON.stringify materializes another string for the entire provider-visible history on every successful turn step just to hash it. That adds large transient heap allocations and a full-history traversal to each such request, with spikes multiplying across concurrent agents; feed message segments to the hash incrementally instead of serializing the whole array at once.

Useful? React with 👍 / 👎.

if (media === 'degraded')
return degradeOlderMediaParts(projected, MEDIA_DEGRADE_KEEP_RECENT, undefined, mediaPaths);
if ('degradeCount' in media)
return degradeLeadingMediaParts(projected, media.degradeCount, undefined, mediaPaths);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recompute media degradation after pre-shrinking compaction history

When a prior turn saved degradeCount: 8 after a 413, a manual or automatic compaction in the same model and context revision can pre-shrink that history to only three media parts; the inherited count is still applied here, replacing all three instead of keeping the most recent two. This initial inherited projection does not trigger the warning path, so compaction can silently summarize without media still present in its retained history. Recompute or clamp the count for pre-shrunk histories.

AGENTS.md reference: AGENTS.md:L131-L133

Useful? React with 👍 / 👎.

@7Sageer
7Sageer merged commit ef663a9 into release/2026-10-28 Oct 27, 2026
16 checks passed
@7Sageer
7Sageer deleted the backport/compaction-prompt-cache-20261028 branch October 27, 2026 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant