on main help sign in
feat: open Hyper auth dialog automatically on unauthorized error
59943a8Andrey Nering
internal/agent/agent.go+8
@@ -531,6 +531,14 @@ func (a *sessionAgent) Run(ctx context.Context, call SessionAgentCall) (*fantasy
531 currentAssistant.AddFinish(message.FinishReasonPermissionDenied, "User denied permission", "")
531 currentAssistant.AddFinish(message.FinishReasonPermissionDenied, "User denied permission", "")
532 } else if errors.Is(err, hyper.ErrUnauthorized) {
532 } else if errors.Is(err, hyper.ErrUnauthorized) {
533 currentAssistant.AddFinish(message.FinishReasonError, "Unauthorized", `Authentication with Hyper failed. Please run "crush auth" to re-authenticate.`)
533 currentAssistant.AddFinish(message.FinishReasonError, "Unauthorized", `Authentication with Hyper failed. Please run "crush auth" to re-authenticate.`)
534+ if a.notify != nil {
535+ a.notify.Publish(pubsub.CreatedEvent, notify.Notification{
536+ SessionID: call.SessionID,
537+ SessionTitle: currentSession.Title,
538+ Type: notify.TypeReAuthenticate,
539+ ProviderID: largeModel.ModelCfg.Provider,
540+ })
541+ }
534 } else if errors.Is(err, hyper.ErrNoCredits) {
542 } else if errors.Is(err, hyper.ErrNoCredits) {
535 url := hyper.BaseURL()
543 url := hyper.BaseURL()
536 link := linkStyle.Hyperlink(url, "id=hyper").Render(url)
544 link := linkStyle.Hyperlink(url, "id=hyper").Render(url)
internal/agent/coordinator.go+2−1
@@ -921,7 +921,8 @@ func (c *coordinator) Summarize(ctx context.Context, sessionID string) error {
921
921
922func (c *coordinator) isUnauthorized(err error) bool {
922func (c *coordinator) isUnauthorized(err error) bool {
923 var providerErr *fantasy.ProviderError
923 var providerErr *fantasy.ProviderError
924− return errors.As(err, &providerErr) && providerErr.StatusCode == http.StatusUnauthorized
924+ return (errors.As(err, &providerErr) && providerErr.StatusCode == http.StatusUnauthorized) ||
925+ errors.Is(err, hyper.ErrUnauthorized)
925}
926}
926
927
927func (c *coordinator) refreshOAuth2Token(ctx context.Context, providerCfg config.ProviderConfig) error {
928func (c *coordinator) refreshOAuth2Token(ctx context.Context, providerCfg config.ProviderConfig) error {
internal/agent/notify/notify.go+4
@@ -9,6 +9,9 @@ type Type string
9const (
9const (
10 // TypeAgentFinished indicates the agent has completed its turn.
10 // TypeAgentFinished indicates the agent has completed its turn.
11 TypeAgentFinished Type = "agent_finished"
11 TypeAgentFinished Type = "agent_finished"
12+ // TypeReAuthenticate indicates the agent encountered an
13+ // authentication error and the user needs to re-authenticate.
14+ TypeReAuthenticate Type = "re_authenticate"
12)
15)
13
16
14// Notification represents a domain event published by the agent.
17// Notification represents a domain event published by the agent.
@@ -16,4 +19,5 @@ type Notification struct {
16 SessionID string
19 SessionID string
17 SessionTitle string
20 SessionTitle string
18 Type Type
21 Type Type
22+ ProviderID string
19}
23}
internal/ui/model/ui.go+18
@@ -3203,11 +3203,29 @@ func (m *UI) handleAgentNotification(n notify.Notification) tea.Cmd {
3203 Title: "Crush is waiting...",
3203 Title: "Crush is waiting...",
3204 Message: fmt.Sprintf("Agent's turn completed in \"%s\"", n.SessionTitle),
3204 Message: fmt.Sprintf("Agent's turn completed in \"%s\"", n.SessionTitle),
3205 })
3205 })
3206+ case notify.TypeReAuthenticate:
3207+ return m.handleReAuthenticate(n.ProviderID)
3206 default:
3208 default:
3207 return nil
3209 return nil
3208 }
3210 }
3209}
3211}
3210
3212
3213+func (m *UI) handleReAuthenticate(providerID string) tea.Cmd {
3214+ cfg := m.com.Config()
3215+ if cfg == nil {
3216+ return nil
3217+ }
3218+ providerCfg, ok := cfg.Providers.Get(providerID)
3219+ if !ok {
3220+ return nil
3221+ }
3222+ agentCfg, ok := cfg.Agents[config.AgentCoder]
3223+ if !ok {
3224+ return nil
3225+ }
3226+ return m.openAuthenticationDialog(providerCfg.ToProvider(), cfg.Models[agentCfg.Model], agentCfg.Model)
3227+}
3228+
3211// newSession clears the current session state and prepares for a new session.
3229// newSession clears the current session state and prepares for a new session.
3212// The actual session creation happens when the user sends their first message.
3230// The actual session creation happens when the user sends their first message.
3213// Returns a command to reload prompt history.
3231// Returns a command to reload prompt history.