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

72 lines
2.7 KiB
Go

package db
import "math"
// Schema v1 bucket boundaries. Changing any of these requires a
// schema_version bump (see session-analytics-design spec).
// Half-open intervals [lo, hi). The last bucket has hi = +Inf.
var durationMinutesEdges = []float64{0, 1, 5, 20, 60, 120, math.Inf(1)}
// user_messages scope_all: [0,2), [2,5], [6,15], [16,30], [31,50], [51,inf)
// user_messages scope_human: [2,5], [6,15], [16,30], [31,50], [51,inf)
// Values below 2 are filtered before accumulating scope_human, preserving
// the v1 bucket shape while keeping human mean and bucket counts consistent.
// Represented as two separate edge lists for clarity.
var userMessagesEdgesAll = []float64{0, 2, 6, 16, 31, 51, math.Inf(1)}
var userMessagesEdgesHuman = []float64{2, 6, 16, 31, 51, math.Inf(1)}
var peakContextEdges = []float64{0, 10_000, 50_000, 100_000, 150_000, 200_000, math.Inf(1)}
var toolsPerTurnEdges = []float64{0, 1, 2, 4, 7, 11, math.Inf(1)}
// cacheHitRatioEdges uses 1.000001 as an internal sentinel so values of
// exactly 1.0 fall into the last bucket under assignBucket's half-open
// rule. This sentinel must NOT be exposed via the v1 JSON schema; use
// buildCacheHitRatioBuckets to materialize buckets with the public
// upper edge clamped back to 1.0.
var cacheHitRatioEdges = []float64{0, 0.25, 0.5, 0.75, 0.95, 1.000001}
// assignBucket returns the index i such that edges[i] <= v < edges[i+1],
// or -1 if v < edges[0] or v >= edges[len-1] (shouldn't happen given Inf upper).
func assignBucket(edges []float64, v float64) int {
for i := 0; i < len(edges)-1; i++ {
if v >= edges[i] && v < edges[i+1] {
return i
}
}
return -1
}
// buildEmptyBuckets returns a pre-sized bucket slice matching edges[i]..edges[i+1].
// Top bucket's hi is represented as JSON null by leaving Edge[1] as nil pointer.
func buildEmptyBuckets(edges []float64) []DistributionBucketV1 {
out := make([]DistributionBucketV1, 0, len(edges)-1)
for i := 0; i < len(edges)-1; i++ {
lo := edges[i]
var hiPtr *float64
if !math.IsInf(edges[i+1], 1) {
hi := edges[i+1]
hiPtr = &hi
}
loPtr := lo
out = append(out, DistributionBucketV1{
Edge: [2]*float64{&loPtr, hiPtr},
Count: 0,
})
}
return out
}
// buildCacheHitRatioBuckets returns the cache-hit-ratio buckets with the
// internal 1.000001 sentinel rewritten to 1.0 for the JSON schema. The
// sentinel exists only so assignBucket can place ratio == 1.0 into the
// last bucket; the JSON contract advertises a clean [0.95, 1.0] band.
func buildCacheHitRatioBuckets() []DistributionBucketV1 {
buckets := buildEmptyBuckets(cacheHitRatioEdges)
if n := len(buckets); n > 0 && buckets[n-1].Edge[1] != nil {
one := 1.0
buckets[n-1].Edge[1] = &one
}
return buckets
}