@@ -9,7 +9,7 @@ import (
99 "sync"
1010 "time"
1111
12− configv2 "github.com/charmbracelet/crush/internal/config"
12+ "github.com/charmbracelet/crush/internal/config"
1313 "github.com/charmbracelet/crush/internal/history"
1414 "github.com/charmbracelet/crush/internal/llm/prompt"
1515 "github.com/charmbracelet/crush/internal/llm/provider"
@@ -49,19 +49,18 @@ type AgentEvent struct {
4949
5050type Service interface {
5151 pubsub.Suscriber[AgentEvent]
52− Model() configv2.Model
52+ Model() config.Model
5353 Run(ctx context.Context, sessionID string, content string, attachments ...message.Attachment) (<-chan AgentEvent, error)
5454 Cancel(sessionID string)
5555 CancelAll()
5656 IsSessionBusy(sessionID string) bool
5757 IsBusy() bool
58− Update(model configv2.PreferredModel) (configv2.Model, error)
5958 Summarize(ctx context.Context, sessionID string) error
6059}
6160
6261type agent struct {
6362 *pubsub.Broker[AgentEvent]
64− agentCfg configv2.Agent
63+ agentCfg config.Agent
6564 sessions session.Service
6665 messages message.Service
6766
@@ -76,13 +75,13 @@ type agent struct {
7675 activeRequests sync.Map
7776}
7877
79−var agentPromptMap = map[configv2.AgentID]prompt.PromptID{
80− configv2.AgentCoder: prompt.PromptCoder,
81− configv2.AgentTask: prompt.PromptTask,
78+var agentPromptMap = map[config.AgentID]prompt.PromptID{
79+ config.AgentCoder: prompt.PromptCoder,
80+ config.AgentTask: prompt.PromptTask,
8281}
8382
8483func NewAgent(
85− agentCfg configv2.Agent,
84+ agentCfg config.Agent,
8685 // These services are needed in the tools
8786 permissions permission.Service,
8887 sessions session.Service,
@@ -91,7 +90,7 @@ func NewAgent(
9190 lspClients map[string]*lsp.Client,
9291) (Service, error) {
9392 ctx := context.Background()
94− cfg := configv2.Get()
93+ cfg := config.Get()
9594 otherTools := GetMcpTools(ctx, permissions)
9695 if len(lspClients) > 0 {
9796 otherTools = append(otherTools, tools.NewDiagnosticsTool(lspClients))
@@ -109,8 +108,8 @@ func NewAgent(
109108 tools.NewWriteTool(lspClients, permissions, history),
110109 }
111110
112− if agentCfg.ID == configv2.AgentCoder {
113− taskAgentCfg := configv2.Get().Agents[configv2.AgentTask]
111+ if agentCfg.ID == config.AgentCoder {
112+ taskAgentCfg := config.Get().Agents[config.AgentTask]
114113 if taskAgentCfg.ID == "" {
115114 return nil, fmt.Errorf("task agent not found in config")
116115 }
@@ -130,26 +129,14 @@ func NewAgent(
130129 }
131130
132131 allTools = append(allTools, otherTools...)
133− var providerCfg configv2.ProviderConfig
134− for _, p := range cfg.Providers {
135− if p.ID == agentCfg.Provider {
136− providerCfg = p
137− break
138− }
139− }
132+ providerCfg := config.GetAgentProvider(agentCfg.ID)
140133 if providerCfg.ID == "" {
141− return nil, fmt.Errorf("provider %s not found in config", agentCfg.Provider)
134+ return nil, fmt.Errorf("provider for agent %s not found in config", agentCfg.Name)
142135 }
136+ model := config.GetAgentModel(agentCfg.ID)
143137
144− var model configv2.Model
145− for _, m := range providerCfg.Models {
146− if m.ID == agentCfg.Model {
147− model = m
148− break
149− }
150− }
151138 if model.ID == "" {
152− return nil, fmt.Errorf("model %s not found in provider %s", agentCfg.Model, agentCfg.Provider)
139+ return nil, fmt.Errorf("model not found for agent %s", agentCfg.Name)
153140 }
154141
155142 promptID := agentPromptMap[agentCfg.ID]
@@ -157,7 +144,7 @@ func NewAgent(
157144 promptID = prompt.PromptDefault
158145 }
159146 opts := []provider.ProviderClientOption{
160− provider.WithModel(model),
147+ provider.WithModel(agentCfg.Model),
161148 provider.WithSystemMessage(prompt.GetPrompt(promptID, providerCfg.ID)),
162149 provider.WithMaxTokens(model.DefaultMaxTokens),
163150 }
@@ -167,9 +154,9 @@ func NewAgent(
167154 }
168155
169156 smallModelCfg := cfg.Models.Small
170− var smallModel configv2.Model
157+ var smallModel config.Model
171158
172− var smallModelProviderCfg configv2.ProviderConfig
159+ var smallModelProviderCfg config.ProviderConfig
173160 if smallModelCfg.Provider == providerCfg.ID {
174161 smallModelProviderCfg = providerCfg
175162 } else {
@@ -194,7 +181,7 @@ func NewAgent(
194181 }
195182
196183 titleOpts := []provider.ProviderClientOption{
197− provider.WithModel(smallModel),
184+ provider.WithModel(config.SmallModel),
198185 provider.WithSystemMessage(prompt.GetPrompt(prompt.PromptTitle, smallModelProviderCfg.ID)),
199186 provider.WithMaxTokens(40),
200187 }
@@ -203,7 +190,7 @@ func NewAgent(
203190 return nil, err
204191 }
205192 summarizeOpts := []provider.ProviderClientOption{
206− provider.WithModel(smallModel),
193+ provider.WithModel(config.SmallModel),
207194 provider.WithSystemMessage(prompt.GetPrompt(prompt.PromptSummarizer, smallModelProviderCfg.ID)),
208195 provider.WithMaxTokens(smallModel.DefaultMaxTokens),
209196 }
@@ -240,8 +227,8 @@ func NewAgent(
240227 return agent, nil
241228}
242229
243−func (a *agent) Model() configv2.Model {
244− return a.provider.Model()
230+func (a *agent) Model() config.Model {
231+ return config.GetAgentModel(a.agentCfg.ID)
245232}
246233
247234func (a *agent) Cancel(sessionID string) {
@@ -336,7 +323,7 @@ func (a *agent) err(err error) AgentEvent {
336323}
337324
338325func (a *agent) Run(ctx context.Context, sessionID string, content string, attachments ...message.Attachment) (<-chan AgentEvent, error) {
339− if !a.provider.Model().SupportsImages && attachments != nil {
326+ if !a.Model().SupportsImages && attachments != nil {
340327 attachments = nil
341328 }
342329 events := make(chan AgentEvent)
@@ -458,7 +445,7 @@ func (a *agent) streamAndHandleEvents(ctx context.Context, sessionID string, msg
458445 assistantMsg, err := a.messages.Create(ctx, sessionID, message.CreateMessageParams{
459446 Role: message.Assistant,
460447 Parts: []message.ContentPart{},
461− Model: a.provider.Model().ID,
448+ Model: a.Model().ID,
462449 Provider: a.providerID,
463450 })
464451 if err != nil {
@@ -609,13 +596,13 @@ func (a *agent) processEvent(ctx context.Context, sessionID string, assistantMsg
609596 if err := a.messages.Update(ctx, *assistantMsg); err != nil {
610597 return fmt.Errorf("failed to update message: %w", err)
611598 }
612− return a.TrackUsage(ctx, sessionID, a.provider.Model(), event.Response.Usage)
599+ return a.TrackUsage(ctx, sessionID, a.Model(), event.Response.Usage)
613600 }
614601
615602 return nil
616603}
617604
618−func (a *agent) TrackUsage(ctx context.Context, sessionID string, model configv2.Model, usage provider.TokenUsage) error {
605+func (a *agent) TrackUsage(ctx context.Context, sessionID string, model config.Model, usage provider.TokenUsage) error {
619606 sess, err := a.sessions.Get(ctx, sessionID)
620607 if err != nil {
621608 return fmt.Errorf("failed to get session: %w", err)
@@ -637,52 +624,6 @@ func (a *agent) TrackUsage(ctx context.Context, sessionID string, model configv2
637624 return nil
638625}
639626
640−func (a *agent) Update(modelCfg configv2.PreferredModel) (configv2.Model, error) {
641− if a.IsBusy() {
642− return configv2.Model{}, fmt.Errorf("cannot change model while processing requests")
643− }
644−
645− cfg := configv2.Get()
646− var providerCfg configv2.ProviderConfig
647− for _, p := range cfg.Providers {
648− if p.ID == modelCfg.Provider {
649− providerCfg = p
650− break
651− }
652− }
653− if providerCfg.ID == "" {
654− return configv2.Model{}, fmt.Errorf("provider %s not found in config", modelCfg.Provider)
655− }
656−
657− var model configv2.Model
658− for _, m := range providerCfg.Models {
659− if m.ID == modelCfg.ModelID {
660− model = m
661− break
662− }
663− }
664− if model.ID == "" {
665− return configv2.Model{}, fmt.Errorf("model %s not found in provider %s", modelCfg.ModelID, modelCfg.Provider)
666− }
667−
668− promptID := agentPromptMap[a.agentCfg.ID]
669− if promptID == "" {
670− promptID = prompt.PromptDefault
671− }
672− opts := []provider.ProviderClientOption{
673− provider.WithModel(model),
674− provider.WithSystemMessage(prompt.GetPrompt(promptID, providerCfg.ID)),
675− provider.WithMaxTokens(model.DefaultMaxTokens),
676− }
677− agentProvider, err := provider.NewProviderV2(providerCfg, opts...)
678− if err != nil {
679− return configv2.Model{}, err
680− }
681− a.provider = agentProvider
682−
683− return a.provider.Model(), nil
684−}
685−
686627func (a *agent) Summarize(ctx context.Context, sessionID string) error {
687628 if a.summarizeProvider == nil {
688629 return fmt.Errorf("summarize provider not available")