Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions agent/compaction/compaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -696,3 +696,40 @@ func messageTexts(messages []*message.Message) []string {
}
return texts
}

func TestNewProvider_KeepsRetainedHistorySourceAcrossTurns(t *testing.T) {
// A compaction provider generates only summary messages; genuine prior-turn
// history returned from the persisted index must keep its original Source.
// Across turns the index is rebuilt from persisted groups whose message
// pointers differ from this turn's input, so identity-based attribution
// wrongly stamps real history as context-provider generated.
provider := compaction.NewContextProvider(compaction.ContextProviderConfig{
Strategy: &compaction.TruncationStrategy{Trigger: compaction.Never()},
SourceID: "compaction-test",
})
session := agenttest.CreateSession()

if _, _, err := invokeProvider(provider, t.Context(), []*message.Message{
textMessage(message.RoleUser, "u1"),
textMessage(message.RoleAssistant, "a1"),
}, agent.WithSession(session)); err != nil {
t.Fatalf("turn 1: %v", err)
}

out, _, err := invokeProvider(provider, t.Context(), []*message.Message{
textMessage(message.RoleUser, "u1"),
textMessage(message.RoleAssistant, "a1"),
textMessage(message.RoleUser, "u2"),
textMessage(message.RoleAssistant, "a2"),
}, agent.WithSession(session))
if err != nil {
t.Fatalf("turn 2: %v", err)
}

cp := message.Source{Type: agent.SourceTypeContextProvider, ID: "compaction-test"}
for i, msg := range out {
if msg.Source == cp {
t.Errorf("message %d (%q) mislabeled as context-provider generated; genuine history must keep its original Source", i, msg.String())
}
}
}
22 changes: 16 additions & 6 deletions agent/compaction/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,17 @@ func (p *contextProvider) markGeneratedMessages(messages, inputMessages []*messa
if len(messages) == 0 {
return messages
}
originals := make(map[*message.Message]struct{}, len(inputMessages))
for _, msg := range inputMessages {
originals[msg] = struct{}{}
}
source := message.Source{Type: agent.SourceTypeContextProvider, ID: p.sourceID}
for i, msg := range messages {
if _, ok := originals[msg]; ok {
if msg == nil || msg.Source == source {
continue
}
if msg == nil || msg.Source == source {
// A message is provider-generated only when it is not one of this turn's
// input messages. Compare by content, not pointer identity: with a session
// the index is rebuilt from persisted groups whose message pointers differ
// from the incoming messages, so an identity check would wrongly stamp
// genuine prior-turn history as context-provider generated.
if containsMessageByContent(inputMessages, msg) {
continue
Comment thread
qmuntal marked this conversation as resolved.
}
marked := msg.Clone()
Expand All @@ -146,3 +147,12 @@ func (p *contextProvider) markGeneratedMessages(messages, inputMessages []*messa
}
return messages
}

func containsMessageByContent(messages []*message.Message, target *message.Message) bool {
for _, candidate := range messages {
if messageContentEqual(candidate, target) {
return true
}
}
return false
}
Loading