Detect changes in hosted content types in compaction contentEqual - #1007
Conversation
contentEqual is the change-detection predicate MessageIndex.Update uses to locate the already-processed prefix. Its switch handled text/reasoning/data/ uri/error/function-call/function-result/hosted-file and returned true (equal) for everything else. So two messages differing only in an MCPServerToolCall/Result, CodeInterpreterToolCall/Result, or UsageContent were treated as equal, and Update would not rebuild - preserving stale group and exclusion state and mis-locating the prefix boundary. Add explicit equality cases for the hosted content types the framework produces (recursing into Outputs/Inputs via contentsEqual, DeepEqual for UsageDetails). The default stays 'equal' so a genuinely new, forward-compatible content type still does not force a rebuild.
There was a problem hiding this comment.
🟡 Changes recommended
The new contentsEqual(leftContent.Outputs/Inputs, ...) calls use message.Contents where contentsEqual expects []message.Content, which will not compile without explicit slice conversions.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR fixes change detection in agent/compaction by teaching contentEqual how to compare several hosted/registered content types that were previously treated as equal via the default branch, which could cause MessageIndex.Update to preserve stale indexing state when hosted tool/usage content changes.
Changes:
- Added explicit equality handling for
MCPServerTool*,CodeInterpreterTool*, andUsageContentincontentEqual. - Kept
default: return truefor forward-compatible unknown content types, while ensuring known hosted types are compared precisely. - Extended
TestMessageIndexUpdate_MatchesKnownContentTypeswith new rows covering these hosted types.
File summaries
| File | Description |
|---|---|
| agent/compaction/equality.go | Adds explicit equality cases for hosted tool-call/tool-result, code-interpreter, and usage content in contentEqual. |
| agent/compaction/equality_test.go | Extends the existing compaction equality/update test table with cases for the hosted content types. |
Review details
Suppressed comments (1)
agent/compaction/equality.go:87
Inputs/Outputsaremessage.Contents, butcontentsEqualtakes[]message.Content; these calls need an explicit conversion to avoid a compile error.
case *message.CodeInterpreterToolCallContent:
rightContent := right.(*message.CodeInterpreterToolCallContent)
return leftContent.CallID == rightContent.CallID && contentsEqual(leftContent.Inputs, rightContent.Inputs)
case *message.CodeInterpreterToolResultContent:
rightContent := right.(*message.CodeInterpreterToolResultContent)
return leftContent.CallID == rightContent.CallID && contentsEqual(leftContent.Outputs, rightContent.Outputs)
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| return leftContent.CallID == rightContent.CallID && leftContent.Name == rightContent.Name && | ||
| leftContent.ServerName == rightContent.ServerName && leftContent.Error == rightContent.Error && | ||
| contentsEqual(leftContent.Outputs, rightContent.Outputs) |
|
Scope: internal-only Changed Go contract: None. Upstream evidence reviewed: Not applicable — this PR only extends an existing unexported Result: out of scope — this is a self-contained internal bugfix restoring intended change-detection semantics within Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "github.com"
- "patchdiff.githubusercontent.com"See Network Configuration for more information.
|
Problem
contentEqual(agent/compaction/equality.go) is the change-detection predicate thatMessageIndex.Updateuses (viacontentsEqual/messageContentEqual) to locate the already-processed prefix, and thatcontainsMessageByContentuses for source attribution. Itsswitchhandles text/reasoning/data/uri/error/function-call/function-result/hosted-file and returnstrue(equal) for everything else.So two messages that differ only in a registered hosted content type —
MCPServerToolCallContent,MCPServerToolResultContent,CodeInterpreterToolCallContent,CodeInterpreterToolResultContent, orUsageContent— are reported equal.MessageIndex.Updatethen treats the changed message as unchanged and does not rebuild, preserving stale group/exclusion state and mis-locating the prefix boundary. The existingTestMessageIndexUpdate_MatchesKnownContentTypesencodes the intent that any differing value must trigger a rebuild; thedefaultviolated it for these types.Fix
Add explicit equality cases for the hosted content types the framework actually produces, comparing their identity fields (recursing into
Outputs/Inputsvia the existingcontentsEqual, andreflect.DeepEqualforUsageDetails). Thedefaultintentionally staysreturn trueso a genuinely new, forward-compatible content type does not force an index rebuild — only the known hosted types get precise comparison.Test
Extends
TestMessageIndexUpdate_MatchesKnownContentTypeswith rows for each hosted type: identical values still preserve the index; differingArguments/Outputs/Inputs/usage now correctly rebuild. The differing rows fail before the fix (treated as equal) and pass after.