Files
wehub-resource-sync f99010fae1
CI / lint (push) Failing after 1s
CI / frontend (push) Failing after 1s
CI / scripts (push) Failing after 1s
CI / Go Test (ubuntu-latest) (push) Failing after 0s
CI / frontend-node-25 (push) Failing after 1s
CI / docs (push) Failing after 0s
CI / coverage (push) Failing after 0s
CI / e2e (push) Failing after 0s
Docker / build-and-push (push) Failing after 1s
CI / integration (push) Failing after 4m43s
CI / Go Test (windows-latest) (push) Has been cancelled
CI / Desktop Unit Tests (Windows) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Linux (arm64)) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Linux) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Windows) (push) Has been cancelled
Desktop Artifacts (macOS) / Desktop Build (macOS (aarch64)) (push) Has been cancelled
Desktop Artifacts (macOS) / Desktop Build (macOS (x86_64)) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:36 +08:00

222 lines
6.4 KiB
Go

package sync
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.kenn.io/agentsview/internal/db"
"go.kenn.io/agentsview/internal/signals"
)
func TestExtractToolCallRows(t *testing.T) {
msgs := []db.Message{
{Ordinal: 0, Role: "user", Content: "do stuff"},
{
Ordinal: 1,
Role: "assistant",
ToolCalls: []db.ToolCall{
{
ToolName: "Bash",
Category: "Bash",
InputJSON: `{"command":"ls"}`,
ResultContent: "/tmp",
ResultEvents: []db.ToolResultEvent{
{Status: "completed", EventIndex: 0},
},
},
{
ToolName: "Edit",
Category: "Edit",
InputJSON: `{"file":"/a.go"}`,
ResultContent: "ok",
// Multiple events: latest wins.
ResultEvents: []db.ToolResultEvent{
{Status: "running", EventIndex: 0},
{Status: "errored", EventIndex: 1},
},
},
},
},
{
Ordinal: 2,
Role: "assistant",
ToolCalls: []db.ToolCall{
{
ToolName: "Read",
Category: "Read",
InputJSON: `{"file":"/b.go"}`,
},
},
},
}
got := extractToolCallRows(msgs)
want := []signals.ToolCallRow{
{
ToolName: "Bash",
Category: "Bash",
InputJSON: `{"command":"ls"}`,
ResultContent: "/tmp",
MessageOrdinal: 1,
CallIndex: 0,
EventStatus: "completed",
},
{
ToolName: "Edit",
Category: "Edit",
InputJSON: `{"file":"/a.go"}`,
ResultContent: "ok",
MessageOrdinal: 1,
CallIndex: 1,
EventStatus: "errored",
},
{
ToolName: "Read",
Category: "Read",
InputJSON: `{"file":"/b.go"}`,
MessageOrdinal: 2,
CallIndex: 0,
},
}
assert.Equal(t, want, got)
}
func TestExtractContextTokens(t *testing.T) {
msgs := []db.Message{
{Ordinal: 0, Role: "user"},
{
Ordinal: 1, Role: "assistant",
ContextTokens: 1000, HasContextTokens: true,
},
{Ordinal: 2, Role: "user"},
{
Ordinal: 3, Role: "assistant",
ContextTokens: 2000, HasContextTokens: true,
},
// Zero/missing tokens are still emitted (caller cares).
{Ordinal: 4, Role: "assistant"},
}
got := extractContextTokens(msgs)
want := []signals.ContextTokenRow{
{ContextTokens: 1000, HasContextTokens: true},
{ContextTokens: 2000, HasContextTokens: true},
{ContextTokens: 0, HasContextTokens: false},
}
assert.Equal(t, want, got)
}
func TestExtractCompactBoundaryOrdinals(t *testing.T) {
msgs := []db.Message{
{Ordinal: 0, Role: "user"},
{Ordinal: 1, Role: "assistant"},
{Ordinal: 2, Role: "user", IsCompactBoundary: true},
{Ordinal: 3, Role: "assistant"},
{Ordinal: 4, Role: "user", IsCompactBoundary: true},
}
got := extractCompactBoundaryOrdinals(msgs)
want := []int{2, 4}
assert.Equal(t, want, got)
assert.Nil(t, extractCompactBoundaryOrdinals(nil), "extractCompactBoundaryOrdinals(nil) should return nil")
}
func TestExtractMostCommonModel(t *testing.T) {
msgs := []db.Message{
{Role: "user"},
{Role: "assistant", Model: "claude-sonnet-4-5"},
{Role: "assistant", Model: "claude-sonnet-4-5"},
{Role: "assistant", Model: "claude-opus-4-6"},
{Role: "assistant", Model: ""}, // ignored
}
assert.Equal(t, "claude-sonnet-4-5", extractMostCommonModel(msgs))
// Tie broken by chronological-first.
tied := []db.Message{
{Role: "assistant", Model: "claude-sonnet-4-5"},
{Role: "assistant", Model: "claude-opus-4-6"},
}
assert.Equal(t, "claude-sonnet-4-5", extractMostCommonModel(tied), "tied")
assert.Empty(t, extractMostCommonModel(nil), "empty")
}
func TestExtractLastMessageRole(t *testing.T) {
msgs := []db.Message{
{Ordinal: 0, Role: "user", Content: "hi"},
{Ordinal: 1, Role: "assistant", Content: "hello"},
{Ordinal: 2, Role: "user", Content: "thanks"},
{Ordinal: 3, Role: "user", Content: "system noise", IsSystem: true},
}
role, content := extractLastMessageRole(msgs)
assert.Equal(t, "user", role)
assert.Equal(t, "thanks", content)
role, content = extractLastMessageRole(nil)
assert.Empty(t, role, "nil case role")
assert.Empty(t, content, "nil case content")
}
func TestComputeSignalsFromMessages_Errors(t *testing.T) {
// Session with a final tool failure: outcome should be
// "errored" (recent enough to be pending), penalties should
// reflect the failure streak, and HasToolCalls is true.
endedAt := "2099-12-31T00:00:00Z"
sess := db.Session{
ID: "s1",
MessageCount: 4,
EndedAt: &endedAt,
PeakContextTokens: 50_000,
}
msgs := []db.Message{
{Ordinal: 0, Role: "user", Content: "go"},
{
Ordinal: 1, Role: "assistant", Model: "claude-sonnet-4-5",
ContextTokens: 10_000, HasContextTokens: true,
ToolCalls: []db.ToolCall{{
ToolName: "Bash", Category: "Bash",
ResultEvents: []db.ToolResultEvent{
{Status: "errored", EventIndex: 0},
},
}},
},
{
Ordinal: 2, Role: "assistant", Model: "claude-sonnet-4-5",
ContextTokens: 12_000, HasContextTokens: true,
ToolCalls: []db.ToolCall{{
ToolName: "Bash", Category: "Bash",
ResultEvents: []db.ToolResultEvent{
{Status: "errored", EventIndex: 0},
},
}},
},
{Ordinal: 3, Role: "assistant", Content: "I give up"},
}
got := computeSignalsFromMessages(sess, msgs)
assert.True(t, got.HasToolCalls, "HasToolCalls = false, want true")
assert.True(t, got.HasContextData, "HasContextData = false, want true")
assert.NotZero(t, got.ToolFailureSignalCount, "ToolFailureSignalCount = 0, want > 0")
assert.NotZero(t, got.FinalFailureStreak, "FinalFailureStreak = 0, want > 0")
require.NotNil(t, got.HealthScore, "HealthScore is nil; want a value")
assert.Less(t, *got.HealthScore, 100, "HealthScore = %d, want < 100", *got.HealthScore)
require.NotNil(t, got.HealthGrade, "HealthGrade = nil, want non-empty")
assert.NotEmpty(t, *got.HealthGrade, "HealthGrade = %v, want non-empty", got.HealthGrade)
assert.Equal(t, "assistant", got.EndedWithRole)
}
func TestComputeSignalsFromMessages_ExplicitBoundariesOverrideHeuristic(t *testing.T) {
// Two explicit boundaries should win over zero token-drops.
sess := db.Session{ID: "s1", MessageCount: 5}
msgs := []db.Message{
{Ordinal: 0, Role: "user"},
{Ordinal: 1, Role: "assistant", Model: "claude-sonnet-4-5"},
{Ordinal: 2, Role: "user", IsCompactBoundary: true},
{Ordinal: 3, Role: "assistant", Model: "claude-sonnet-4-5"},
{Ordinal: 4, Role: "user", IsCompactBoundary: true},
}
got := computeSignalsFromMessages(sess, msgs)
assert.Equal(t, 2, got.CompactionCount)
}