Features (see spec.md v2): - Wire receipt classification into the upload flow; cheap model (Haiku 4.5) is now the default, shown as a footnote with per-scan cost in cents. - Skip-AI toggle to enter fields by hand. - Duplicate-transaction warning: live check on date+amount, gated submit. - Tally tab: person x year totals with margins and grand total. - Recent uploads / recent receipts tabs with paging and file serving. - People reconcile on startup: merge stray partial names (e.g. "Jude" -> "Jude Tremblay"), reassigning receipts; idempotent seeding. - scripts/build.sh builds the binary; scripts/run.sh builds and runs with .env. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
31 lines
879 B
Go
31 lines
879 B
Go
package classify
|
|
|
|
import (
|
|
"math"
|
|
"testing"
|
|
)
|
|
|
|
func TestCostCents_Haiku(t *testing.T) {
|
|
// 1500 input + 100 output on Haiku ($1/1M in, $5/1M out).
|
|
// input: 1500 * 100c/1e6 = 0.15c ; output: 100 * 500c/1e6 = 0.05c → 0.20c
|
|
got, ok := CostCents("claude-haiku-4-5-20251001", Usage{InputTokens: 1500, OutputTokens: 100})
|
|
if !ok {
|
|
t.Fatal("expected known model")
|
|
}
|
|
if math.Abs(got-0.20) > 1e-9 {
|
|
t.Errorf("cost = %v, want 0.20", got)
|
|
}
|
|
}
|
|
|
|
func TestCostCents_CacheTokensBilledAtInputRate(t *testing.T) {
|
|
got, _ := CostCents("claude-haiku-4-5", Usage{CacheReadTokens: 1_000_000})
|
|
if math.Abs(got-100) > 1e-9 { // 1M input-rate tokens = 100 cents
|
|
t.Errorf("cost = %v, want 100", got)
|
|
}
|
|
}
|
|
|
|
func TestCostCents_UnknownModel(t *testing.T) {
|
|
if _, ok := CostCents("some-future-model", Usage{InputTokens: 1000}); ok {
|
|
t.Error("expected ok=false for unknown model")
|
|
}
|
|
}
|