@@ -15,6 +15,7 @@ import (
17 "log/slog"
17 "log/slog"
18 "net/http"
19 "net/http"
@@ -978,6 +979,7 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (result *
979 usage, estimated := fallbackStepUsage(stepMessages, stepResult)
980 usage, estimated := fallbackStepUsage(stepMessages, stepResult)
980 a.updateSessionUsage(largeModel, &updatedSession, usage, a.openrouterCost(stepResult.ProviderMetadata), estimated)
981 a.updateSessionUsage(largeModel, &updatedSession, usage, a.openrouterCost(stepResult.ProviderMetadata), estimated)
982+ extractHyperCredits(stepResult.ProviderMetadata)
981 _, sessionErr := a.sessions.Save(ctx, updatedSession)
983 _, sessionErr := a.sessions.Save(ctx, updatedSession)
982 if sessionErr != nil {
984 if sessionErr != nil {
983 return sessionErr
985 return sessionErr
@@ -1386,6 +1388,7 @@ func (a *sessionAgent) Summarize(ctx context.Context, sessionID string, opts fan
1387 openrouterCost = &newCost
1389 openrouterCost = &newCost
1391+ extractHyperCredits(step.ProviderMetadata)
1391 a.updateSessionUsage(largeModel, ¤tSession, resp.TotalUsage, openrouterCost, false)
1394 a.updateSessionUsage(largeModel, ¤tSession, resp.TotalUsage, openrouterCost, false)
@@ -1752,6 +1755,7 @@ func (a *sessionAgent) GenerateTitle(ctx context.Context, sessionID string, user
1753 openrouterCost = &newCost
1756 openrouterCost = &newCost
1758+ extractHyperCredits(step.ProviderMetadata)
1757 modelConfig := model.CatwalkCfg
1761 modelConfig := model.CatwalkCfg
@@ -1796,6 +1800,25 @@ func (a *sessionAgent) openrouterCost(metadata fantasy.ProviderMetadata) *float6
1796 return &opts.Usage.Cost
1800 return &opts.Usage.Cost
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]
1810+ pm, ok := openaiMeta.(*openai.ProviderMetadata)
1814+ var remaining struct {
1815+ Hypercredits float64 `json:"hypercredits"`
1817+ if pm.ExtraField("remaining", &remaining) && remaining.Hypercredits > 0 {
1818+ hyper.SetBalance(int(math.Round(remaining.Hypercredits)))
1799func (a *sessionAgent) updateSessionUsage(model Model, session *session.Session, usage fantasy.Usage, overrideCost *float64, estimated bool) {
1822func (a *sessionAgent) updateSessionUsage(model Model, session *session.Session, usage fantasy.Usage, overrideCost *float64, estimated bool) {
1800 if !usageIsZero(usage) {
1823 if !usageIsZero(usage) {
1801 session.EstimatedUsage = estimated
1824 session.EstimatedUsage = estimated