@@ -132,6 +132,13 @@ func (c *coordinator) Run(ctx context.Context, sessionID string, prompt string,
mergedOptions, temp, topP, topK, freqPenalty, presPenalty := mergeCallOptions(model, providerCfg)
+ if providerCfg.OAuthToken != nil && providerCfg.OAuthToken.IsExpired() {
+ slog.Info("Token needs to be refreshed", "provider", providerCfg.ID)
+ if err := c.refreshOAuth2Token(ctx, providerCfg); err != nil {
+ return nil, err
+ }
+ }
+
run := func() (*fantasy.AgentResult, error) {
return c.currentAgent.Run(ctx, SessionAgentCall{
SessionID: sessionID,
@@ -2,25 +2,14 @@ package util
import (
"context"
- "errors"
- "os/exec"
tea "charm.land/bubbletea/v2"
- "mvdan.cc/sh/v3/shell"
+ "github.com/charmbracelet/crush/internal/uiutil"
)
// ExecShell parses a shell command string and executes it with exec.Command.
// Uses shell.Fields for proper handling of shell syntax like quotes and
// arguments while preserving TTY handling for terminal editors.
func ExecShell(ctx context.Context, cmdStr string, callback tea.ExecCallback) tea.Cmd {
- fields, err := shell.Fields(cmdStr, nil)
- if err != nil {
- return ReportError(err)
- }
- if len(fields) == 0 {
- return ReportError(errors.New("empty command"))
- }
-
- cmd := exec.CommandContext(ctx, fields[0], fields[1:]...)
- return tea.ExecProcess(cmd, callback)
+ return uiutil.ExecShell(ctx, cmdStr, callback)
}
@@ -4,10 +4,14 @@
package uiutil
import (
+ "context"
+ "errors"
"log/slog"
+ "os/exec"
"time"
tea "charm.land/bubbletea/v2"
+ "mvdan.cc/sh/v3/shell"
)
type Cursor interface {
@@ -60,3 +64,19 @@ type (
}
ClearStatusMsg struct{}
)
+
+// ExecShell parses a shell command string and executes it with exec.Command.
+// Uses shell.Fields for proper handling of shell syntax like quotes and
+// arguments while preserving TTY handling for terminal editors.
+func ExecShell(ctx context.Context, cmdStr string, callback tea.ExecCallback) tea.Cmd {
+ fields, err := shell.Fields(cmdStr, nil)
+ if err != nil {
+ return ReportError(err)
+ }
+ if len(fields) == 0 {
+ return ReportError(errors.New("empty command"))
+ }
+
+ cmd := exec.CommandContext(ctx, fields[0], fields[1:]...)
+ return tea.ExecProcess(cmd, callback)
+}