mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-13 06:15:25 +00:00
SetLastPromptTokens received TotalUsage.PromptTokens — the sum of prompt tokens across every think→act→observe iteration of a run — instead of the final iteration's own usage. A tool-heavy run inflated the stored value by the iteration count, so the sessions list showed e.g. 901K "context used" against a 258K window, and maybeSummarize over-triggered compaction once the inflation exceeded the 40% overhead clamp (observed: 83 compactions on a 4-message session). Track the final iteration's usage separately (ThinkState.LastUsage) and persist its actual context size: prompt tokens + cached segments (Anthropic reports input_tokens excluding cache read/creation) + output tokens (the final reply joins history, so it occupies the next request's prompt). The run-cumulative total still feeds AccumulateTokens for billing.
50 lines
1.3 KiB
Go
50 lines
1.3 KiB
Go
package providers
|
|
|
|
import "testing"
|
|
|
|
// TestUsage_ContextTokens guards the "current context size" computation used by
|
|
// the sessions context-usage display and compaction calibration. Anthropic-style
|
|
// accounting reports input_tokens EXCLUDING cached segments, so the real context
|
|
// of a call is prompt + cache_read + cache_creation. OpenAI-style accounting
|
|
// (PromptTokensIncludeCachedSegments=true) already includes cached tokens.
|
|
func TestUsage_ContextTokens(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
usage Usage
|
|
want int
|
|
}{
|
|
{
|
|
name: "anthropic-style excludes cached segments — add them back",
|
|
usage: Usage{
|
|
PromptTokens: 1000,
|
|
CacheReadTokens: 80000,
|
|
CacheCreationTokens: 5000,
|
|
},
|
|
want: 86000,
|
|
},
|
|
{
|
|
name: "openai-style already includes cached segments",
|
|
usage: Usage{
|
|
PromptTokens: 86000,
|
|
CacheReadTokens: 80000,
|
|
PromptTokensIncludeCachedSegments: true,
|
|
},
|
|
want: 86000,
|
|
},
|
|
{
|
|
name: "zero value",
|
|
usage: Usage{},
|
|
want: 0,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := tt.usage.ContextTokens(); got != tt.want {
|
|
t.Errorf("ContextTokens() = %d, want %d", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|