@@ -15,6 +15,7 @@ import (
1515 "errors"
1616 "fmt"
1717 "log/slog"
18+ "math"
1819 "net/http"
1920 "os"
2021 "regexp"
@@ -978,6 +979,7 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (result *
978979 }
979980 usage, estimated := fallbackStepUsage(stepMessages, stepResult)
980981 a.updateSessionUsage(largeModel, &updatedSession, usage, a.openrouterCost(stepResult.ProviderMetadata), estimated)
982+ extractHyperCredits(stepResult.ProviderMetadata)
981983 _, sessionErr := a.sessions.Save(ctx, updatedSession)
982984 if sessionErr != nil {
983985 return sessionErr
@@ -1386,6 +1388,7 @@ func (a *sessionAgent) Summarize(ctx context.Context, sessionID string, opts fan
13861388 }
13871389 openrouterCost = &newCost
13881390 }
1391+ extractHyperCredits(step.ProviderMetadata)
13891392 }
13901393
13911394 a.updateSessionUsage(largeModel, ¤tSession, resp.TotalUsage, openrouterCost, false)
@@ -1752,6 +1755,7 @@ func (a *sessionAgent) GenerateTitle(ctx context.Context, sessionID string, user
17521755 }
17531756 openrouterCost = &newCost
17541757 }
1758+ extractHyperCredits(step.ProviderMetadata)
17551759 }
17561760
17571761 modelConfig := model.CatwalkCfg
@@ -1796,6 +1800,25 @@ func (a *sessionAgent) openrouterCost(metadata fantasy.ProviderMetadata) *float6
17961800 return &opts.Usage.Cost
17971801}
17981802
1803+// extractHyperCredits reads usage.remaining.hypercredits from OpenAI
1804+// provider metadata and stores it for the next FetchCredits call.
1805+func extractHyperCredits(metadata fantasy.ProviderMetadata) {
1806+ openaiMeta, ok := metadata[openai.Name]
1807+ if !ok {
1808+ return
1809+ }
1810+ pm, ok := openaiMeta.(*openai.ProviderMetadata)
1811+ if !ok {
1812+ return
1813+ }
1814+ var remaining struct {
1815+ Hypercredits float64 `json:"hypercredits"`
1816+ }
1817+ if pm.ExtraField("remaining", &remaining) && remaining.Hypercredits > 0 {
1818+ hyper.SetBalance(int(math.Round(remaining.Hypercredits)))
1819+ }
1820+}
1821+
17991822func (a *sessionAgent) updateSessionUsage(model Model, session *session.Session, usage fantasy.Usage, overrideCost *float64, estimated bool) {
18001823 if !usageIsZero(usage) {
18011824 session.EstimatedUsage = estimated