@@ -17,6 +17,7 @@ import (
1717 "charm.land/fantasy/providers/bedrock"
1818 "charm.land/fantasy/providers/google"
1919 "charm.land/fantasy/providers/openai"
20+ "charm.land/fantasy/providers/openrouter"
2021 "github.com/charmbracelet/catwalk/pkg/catwalk"
2122 "github.com/charmbracelet/crush/internal/agent/tools"
2223 "github.com/charmbracelet/crush/internal/config"
@@ -349,7 +350,7 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
349350 finishReason = message.FinishReasonToolUse
350351 }
351352 currentAssistant.AddFinish(finishReason, "", "")
352− a.updateSessionUsage(a.largeModel, ¤tSession, stepResult.Usage)
353+ a.updateSessionUsage(a.largeModel, ¤tSession, stepResult.Usage, a.openrouterCost(stepResult.ProviderMetadata))
353354 sessionLock.Lock()
354355 _, sessionErr := a.sessions.Save(genCtx, currentSession)
355356 sessionLock.Unlock()
@@ -562,7 +563,19 @@ func (a *sessionAgent) Summarize(ctx context.Context, sessionID string, opts fan
562563 return err
563564 }
564565
565− a.updateSessionUsage(a.largeModel, ¤tSession, resp.TotalUsage)
566+ var openrouterCost *float64
567+ for _, step := range resp.Steps {
568+ stepCost := a.openrouterCost(step.ProviderMetadata)
569+ if stepCost != nil {
570+ newCost := *stepCost
571+ if openrouterCost != nil {
572+ newCost += *openrouterCost
573+ }
574+ openrouterCost = &newCost
575+ }
576+ }
577+
578+ a.updateSessionUsage(a.largeModel, ¤tSession, resp.TotalUsage, openrouterCost)
566579
567580 // just in case get just the last usage
568581 usage := resp.Response.Usage
@@ -690,7 +703,20 @@ func (a *sessionAgent) generateTitle(ctx context.Context, session *session.Sessi
690703 }
691704
692705 session.Title = title
693− a.updateSessionUsage(a.smallModel, session, resp.TotalUsage)
706+
707+ var openrouterCost *float64
708+ for _, step := range resp.Steps {
709+ stepCost := a.openrouterCost(step.ProviderMetadata)
710+ if stepCost != nil {
711+ newCost := *stepCost
712+ if openrouterCost != nil {
713+ newCost += *openrouterCost
714+ }
715+ openrouterCost = &newCost
716+ }
717+ }
718+
719+ a.updateSessionUsage(a.smallModel, session, resp.TotalUsage, openrouterCost)
694720 _, saveErr := a.sessions.Save(ctx, *session)
695721 if saveErr != nil {
696722 slog.Error("failed to save session title & usage", "error", saveErr)
@@ -698,7 +724,20 @@ func (a *sessionAgent) generateTitle(ctx context.Context, session *session.Sessi
698724 }
699725}
700726
701−func (a *sessionAgent) updateSessionUsage(model Model, session *session.Session, usage fantasy.Usage) {
727+func (a *sessionAgent) openrouterCost(metadata fantasy.ProviderMetadata) *float64 {
728+ openrouterMetadata, ok := metadata[openrouter.Name]
729+ if !ok {
730+ return nil
731+ }
732+
733+ opts, ok := openrouterMetadata.(*openrouter.ProviderMetadata)
734+ if !ok {
735+ return nil
736+ }
737+ return &opts.Usage.Cost
738+}
739+
740+func (a *sessionAgent) updateSessionUsage(model Model, session *session.Session, usage fantasy.Usage, overrideCost *float64) {
702741 modelConfig := model.CatwalkCfg
703742 cost := modelConfig.CostPer1MInCached/1e6*float64(usage.CacheCreationTokens) +
704743 modelConfig.CostPer1MOutCached/1e6*float64(usage.CacheReadTokens) +
@@ -707,7 +746,12 @@ func (a *sessionAgent) updateSessionUsage(model Model, session *session.Session,
707746
708747 a.eventTokensUsed(session.ID, model, usage, cost)
709748
710− session.Cost += cost
749+ if overrideCost != nil {
750+ session.Cost += *overrideCost
751+ } else {
752+ session.Cost += cost
753+ }
754+
711755 session.CompletionTokens = usage.OutputTokens + usage.CacheReadTokens
712756 session.PromptTokens = usage.InputTokens + usage.CacheCreationTokens
713757}