Skip to content

fix(adapter): dedupe local-only command result output - #949

Open
ran411285752 wants to merge 3 commits into
agentclientprotocol:mainfrom
ran411285752:codex/fix-local-command-output-dedupe
Open

fix(adapter): dedupe local-only command result output#949
ran411285752 wants to merge 3 commits into
agentclientprotocol:mainfrom
ran411285752:codex/fix-local-command-output-dedupe

Conversation

@ran411285752

Copy link
Copy Markdown
Contributor

Summary

  • Deduplicate local-only slash command output at the SDK-to-ACP adapter boundary.
  • Cover both the current SDK sequence (assistant then terminal result) and the local_command_output compatibility path.
  • Keep evidence scoped to the originating turn or SDK cycle so ordinary assistant text and later turns are not globally deduplicated.

Root cause

A live Claude OAuth / Agent SDK 0.3.220 trace showed that /context currently emits:

assistant text: 2268 bytes
result text:    2270 bytes

The payloads are identical after removing the result's two trailing line feeds. The adapter forwarded the consolidated assistant text and then unconditionally forwarded the terminal result because the turn was classified as a local-only command.

The issue report described the first source as system/local_command_output; this PR retains coverage for that SDK shape, while also fixing the current observed assistant -> result sequence.

Implementation

  • Canonicalize only newline representation and trailing line feeds for local-command comparisons.
  • Retain source-identified local_command_output evidence on its Turn.
  • Retain consolidated assistant evidence only for the next SDK result cycle.
  • Clear cycle evidence on terminal results and non-owed idle boundaries, including autonomous, cancelled, and no-result paths.
  • Preserve result-only output, distinct output, repeated output in later turns, held-turn handoff, orphan lanes, and lagged-idle behavior.

Validation

Live end-to-end verification

Ran the built adapter as an ACP subprocess using the real local Claude OAuth login, created a real ACP session, and sent /context through session/prompt.

Before the final fix:

agent_message_chunk count: 2
lengths: 2268, 2270
Context Usage heading count: 2

After the fix:

agent_message_chunk count: 1
length: 2268
sha256: 605f8d220d1a0f628d05c1128c4310f6ce0b8786d7a024928a51ca8e1168de2e
Context Usage heading count: 1
stopReason: end_turn

Automated verification

  • Focused Vitest selection: 36 passed.
  • npm run build: passed.
  • npm run lint: passed.
  • npx prettier --check src/acp-agent.ts src/tests/acp-agent.test.ts: passed.
  • npm run test:run: 687 passed, 20 skipped, and the same 6 pre-existing Windows path-separator assertion failures (src/main.ts vs src\main.ts); no new failures.

Fixes #948

【BUG修复】:: 修复 /context 等本地命令完整文本被 ACP 客户端重复接收的问题。
【问题原因】:: Claude SDK 会从 local_command_output 与终态 result 提供相同文本,Adapter 丢失来源后将两者均映射为 agent_message_chunk。
【解决方案】:: 按 turn 记录已转发的本地命令原始文本,仅抑制终态 result 的完全相同副本,并覆盖 held turn、orphan lane 与跨 turn 边界。
【代码自测】:: 定向 Vitest 32 项通过;npm run build、npm run lint、定向 Prettier 与 git diff --cached --check 通过;全量 684 通过、6 个既有 Windows 路径断言失败。
【测试建议】:: 验证 /context 双来源相同文本只显示一次,并回归 result-only、不同文本、连续 turn、held turn 与 orphan 结果场景。
Refs: agentclientprotocol#948
【BUG修复】:: 修正真实 /context 链路仍重复输出的问题,并阻止去重证据跨自主、取消或无 result cycle 泄漏。
【问题原因】:: 当前 SDK 实际发送 consolidated assistant 后再发送多两个尾随换行的 result;初版仅按 local_command_output 完全匹配,未覆盖真实事件形态。
【解决方案】:: 规范化尾随换行,分别维护 turn 级明确来源与 cycle 级 assistant 候选,并在 result 或非 owed idle 收口时清理;补充 held、autonomous、cancel 边界测试。
【代码自测】:: 真实 OAuth ACP /context E2E 仅收到 1 个 2268 字符块;定向 36 项、build、lint、Prettier 通过;全量 687 通过,6 个既有 Windows 路径断言失败。
【测试建议】:: 复验真实 /context 单次展示,并回归不同正文、result-only、连续 turn、held autonomous followup、取消无 result 与 lagged idle。
Refs: agentclientprotocol#948
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.

Local-only slash command output is emitted twice via local_command_output and result

1 participant