@@ -1792,18 +1792,36 @@ func (m *UI) refreshHyperAndRetrySelect(msg dialog.ActionSelectModel) tea.Cmd {
17921792// remaining Hyper credits from the API.
17931793func (m *UI) fetchHyperCredits() tea.Cmd {
17941794 return func() tea.Msg {
1795− cfg := m.com.Config()
1796− if cfg == nil {
1797− return nil
1795+ var (
1796+ apiKey string
1797+ cfg *config.Config
1798+ providerCfg config.ProviderConfig
1799+ )
1800+ getAPIKey := func() (ok bool) {
1801+ if cfg = m.com.Config(); cfg == nil {
1802+ return false
1803+ }
1804+ if providerCfg, ok = cfg.Providers.Get(hyper.Name); !ok {
1805+ return false
1806+ }
1807+ var err error
1808+ apiKey, err = m.com.Workspace.Resolver().ResolveValue(providerCfg.APIKey)
1809+ return err == nil && apiKey != ""
17981810 }
1799− providerCfg, ok := cfg.Providers.Get(hyper.Name)
1800− if !ok {
1811+ if !getAPIKey() {
18011812 return nil
18021813 }
1803− apiKey, err := m.com.Workspace.Resolver().ResolveValue(providerCfg.APIKey)
1804− if err != nil || apiKey == "" {
1805− return nil
1814+
1815+ if providerCfg.OAuthToken != nil && providerCfg.OAuthToken.IsExpired() {
1816+ ctxRefresh, cancelRefresh := context.WithTimeout(context.Background(), 15*time.Second)
1817+ defer cancelRefresh()
1818+ if err := m.com.Workspace.RefreshOAuthToken(ctxRefresh, config.ScopeGlobal, hyper.Name); err != nil {
1819+ slog.Warn("Hyper OAuth refresh failed before fetching credits, trying with existing token", "error", err)
1820+ } else if !getAPIKey() {
1821+ return nil
1822+ }
18061823 }
1824+
18071825 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
18081826 defer cancel()
18091827 credits, err := hyper.FetchCredits(ctx, apiKey)