Skip to content

Commit 26007e5

Browse files
committed
fix(db,engine): cost-only event model filtering and Codebuff changed-path force parse
1. Cost-only events: Filtered out empty model names from ModelsUsed across SQLite, PostgreSQL, and DuckDB backends. Cost-only events (e.g. Codebuff) have empty model but carry CostUSD. Including them creates blank, unfilterable entries in model breakdowns. 2. Codebuff changed-path: Added force parse for Codebuff changed-path events in providerChangedPathForceParse. The composite stat-only freshness gate may skip same-size, same-mtime rewrites, so a concrete changed-path signal must always trigger the full fingerprint path.
1 parent bb66beb commit 26007e5

4 files changed

Lines changed: 32 additions & 5 deletions

File tree

internal/db/usage.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,7 +2108,11 @@ func (db *DB) GetDailyUsage(
21082108

21092109
modelNames := make([]string, 0, len(dd.models))
21102110
for m := range dd.models {
2111-
modelNames = append(modelNames, m)
2111+
// Filter out empty model names from cost-only events
2112+
// (e.g. Codebuff) to avoid blank entries in ModelsUsed.
2113+
if m != "" {
2114+
modelNames = append(modelNames, m)
2115+
}
21122116
}
21132117
sort.Slice(modelNames, func(i, j int) bool {
21142118
left := dd.models[modelNames[i]]
@@ -2275,7 +2279,11 @@ func (db *DB) GetDailyUsage(
22752279

22762280
modelNames := make([]string, 0, len(dm.models))
22772281
for m := range dm.models {
2278-
modelNames = append(modelNames, m)
2282+
// Filter out empty model names from cost-only events
2283+
// (e.g. Codebuff) to avoid blank entries in ModelsUsed.
2284+
if m != "" {
2285+
modelNames = append(modelNames, m)
2286+
}
22792287
}
22802288
sort.Slice(modelNames, func(i, j int) bool {
22812289
left := dm.models[modelNames[i]]

internal/duckdb/analytics_usage.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3955,7 +3955,11 @@ func addUsageBucket(m map[string]duckUsageBucket, key string, b duckUsageBucket)
39553955
func sortedUsageBucketKeys(m map[string]duckUsageBucket) []string {
39563956
out := make([]string, 0, len(m))
39573957
for key := range m {
3958-
out = append(out, key)
3958+
// Filter out empty model names from cost-only events
3959+
// (e.g. Codebuff) to avoid blank entries in ModelsUsed.
3960+
if key != "" {
3961+
out = append(out, key)
3962+
}
39593963
}
39603964
sort.Slice(out, func(i, j int) bool {
39613965
left := m[out[i]]

internal/postgres/usage.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,7 +1547,11 @@ func (s *Store) GetDailyUsage(
15471547

15481548
modelNames := make([]string, 0, len(dd.models))
15491549
for m := range dd.models {
1550-
modelNames = append(modelNames, m)
1550+
// Filter out empty model names from cost-only events
1551+
// (e.g. Codebuff) to avoid blank entries in ModelsUsed.
1552+
if m != "" {
1553+
modelNames = append(modelNames, m)
1554+
}
15511555
}
15521556
sort.Slice(modelNames, func(i, j int) bool {
15531557
left := dd.models[modelNames[i]]
@@ -1708,7 +1712,11 @@ func (s *Store) GetDailyUsage(
17081712

17091713
modelNames := make([]string, 0, len(dm.models))
17101714
for m := range dm.models {
1711-
modelNames = append(modelNames, m)
1715+
// Filter out empty model names from cost-only events
1716+
// (e.g. Codebuff) to avoid blank entries in ModelsUsed.
1717+
if m != "" {
1718+
modelNames = append(modelNames, m)
1719+
}
17121720
}
17131721
sort.Slice(modelNames, func(i, j int) bool {
17141722
left := dm.models[modelNames[i]]

internal/sync/engine.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,13 @@ func providerChangedPathForceParse(
12341234
parser.IsGeminiProjectMetadataFile(eventPath) {
12351235
return false
12361236
}
1237+
// Codebuff changed-path events must force a fingerprint
1238+
// comparison. The composite stat-only freshness gate may skip
1239+
// same-size, same-mtime rewrites, so a concrete changed-path
1240+
// signal must always trigger the full fingerprint path.
1241+
if agent == parser.AgentCodebuff {
1242+
return true
1243+
}
12371244
return true
12381245
}
12391246
return eventKind == "remove" &&

0 commit comments

Comments
 (0)