Changeset 0.15.0 (#71)

This commit is contained in:
2026-02-26 21:19:55 +00:00
parent e2149e249d
commit 2d79ff593b
35 changed files with 3218 additions and 504 deletions

View File

@@ -0,0 +1,57 @@
package compaction
import (
"git.gobha.me/xcaliber/chat-switchboard/treepath"
)
// ── Token Estimation ────────────────────────
//
// Rough heuristic matching the frontend Tokens.estimate() (~4 chars/token).
// Good enough for threshold checks. Swap in a real tokenizer later if
// over/under-triggering becomes a problem.
// EstimateTokens returns a rough token count for a string.
// Uses the ~4 chars/token heuristic for English (GPT/Claude average).
func EstimateTokens(text string) int {
return (len(text) + 3) / 4
}
// EstimatePath returns total estimated tokens for a message path.
// Adds +4 per message for role/delimiter overhead, matching the frontend.
func EstimatePath(path []treepath.PathMessage) int {
total := 0
for i := range path {
total += EstimateTokens(path[i].Content) + 4
}
return total
}
// EstimatePathFromSummary returns estimated tokens for messages after
// the most recent summary boundary. Returns 0 and false if a summary
// exists but fewer than minMessages follow it.
func EstimatePathFromSummary(path []treepath.PathMessage, minMessages int) (tokens int, msgCount int, ok bool) {
startIdx := 0
for i := range path {
if treepath.IsSummaryMessage(&path[i]) {
startIdx = i + 1
}
}
post := path[startIdx:]
// Count non-system, non-summary messages
count := 0
est := 0
for i := range post {
if post[i].Role == "system" || treepath.IsSummaryMessage(&post[i]) {
continue
}
count++
est += EstimateTokens(post[i].Content) + 4
}
if count < minMessages {
return 0, count, false
}
return est, count, true
}