@@ -9,7 +9,7 @@ import (
12− configv2 "github.com/charmbracelet/crush/internal/config"
12+ "github.com/charmbracelet/crush/internal/config"
13 "github.com/charmbracelet/crush/internal/history"
13 "github.com/charmbracelet/crush/internal/history"
14 "github.com/charmbracelet/crush/internal/llm/prompt"
14 "github.com/charmbracelet/crush/internal/llm/prompt"
15 "github.com/charmbracelet/crush/internal/llm/provider"
15 "github.com/charmbracelet/crush/internal/llm/provider"
@@ -49,19 +49,18 @@ type AgentEvent struct {
50type Service interface {
50type Service interface {
51 pubsub.Suscriber[AgentEvent]
51 pubsub.Suscriber[AgentEvent]
52− Model() configv2.Model
52+ Model() config.Model
53 Run(ctx context.Context, sessionID string, content string, attachments ...message.Attachment) (<-chan AgentEvent, error)
53 Run(ctx context.Context, sessionID string, content string, attachments ...message.Attachment) (<-chan AgentEvent, error)
54 Cancel(sessionID string)
54 Cancel(sessionID string)
55 CancelAll()
55 CancelAll()
56 IsSessionBusy(sessionID string) bool
56 IsSessionBusy(sessionID string) bool
57 IsBusy() bool
57 IsBusy() bool
58− Update(model configv2.PreferredModel) (configv2.Model, error)
59 Summarize(ctx context.Context, sessionID string) error
58 Summarize(ctx context.Context, sessionID string) error
62type agent struct {
61type agent struct {
63 *pubsub.Broker[AgentEvent]
62 *pubsub.Broker[AgentEvent]
64− agentCfg configv2.Agent
63+ agentCfg config.Agent
65 sessions session.Service
64 sessions session.Service
66 messages message.Service
65 messages message.Service
@@ -76,13 +75,13 @@ type agent struct {
76 activeRequests sync.Map
75 activeRequests sync.Map
79−var agentPromptMap = map[configv2.AgentID]prompt.PromptID{
78+var agentPromptMap = map[config.AgentID]prompt.PromptID{
80− configv2.AgentCoder: prompt.PromptCoder,
79+ config.AgentCoder: prompt.PromptCoder,
81− configv2.AgentTask: prompt.PromptTask,
80+ config.AgentTask: prompt.PromptTask,
84func NewAgent(
83func NewAgent(
85− agentCfg configv2.Agent,
84+ agentCfg config.Agent,
86 // These services are needed in the tools
85 // These services are needed in the tools
87 permissions permission.Service,
86 permissions permission.Service,
88 sessions session.Service,
87 sessions session.Service,
@@ -91,7 +90,7 @@ func NewAgent(
91 lspClients map[string]*lsp.Client,
90 lspClients map[string]*lsp.Client,
92) (Service, error) {
91) (Service, error) {
93 ctx := context.Background()
92 ctx := context.Background()
94− cfg := configv2.Get()
93+ cfg := config.Get()
95 otherTools := GetMcpTools(ctx, permissions)
94 otherTools := GetMcpTools(ctx, permissions)
96 if len(lspClients) > 0 {
95 if len(lspClients) > 0 {
97 otherTools = append(otherTools, tools.NewDiagnosticsTool(lspClients))
96 otherTools = append(otherTools, tools.NewDiagnosticsTool(lspClients))
@@ -109,8 +108,8 @@ func NewAgent(
109 tools.NewWriteTool(lspClients, permissions, history),
108 tools.NewWriteTool(lspClients, permissions, history),
112− if agentCfg.ID == configv2.AgentCoder {
111+ if agentCfg.ID == config.AgentCoder {
113− taskAgentCfg := configv2.Get().Agents[configv2.AgentTask]
112+ taskAgentCfg := config.Get().Agents[config.AgentTask]
114 if taskAgentCfg.ID == "" {
113 if taskAgentCfg.ID == "" {
115 return nil, fmt.Errorf("task agent not found in config")
114 return nil, fmt.Errorf("task agent not found in config")
@@ -130,26 +129,14 @@ func NewAgent(
132 allTools = append(allTools, otherTools...)
131 allTools = append(allTools, otherTools...)
133− var providerCfg configv2.ProviderConfig
132+ providerCfg := config.GetAgentProvider(agentCfg.ID)
134− for _, p := range cfg.Providers {
135− if p.ID == agentCfg.Provider {
140 if providerCfg.ID == "" {
133 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)
136+ model := config.GetAgentModel(agentCfg.ID)
144− var model configv2.Model
145− for _, m := range providerCfg.Models {
146− if m.ID == agentCfg.Model {
151 if model.ID == "" {
138 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)
155 promptID := agentPromptMap[agentCfg.ID]
142 promptID := agentPromptMap[agentCfg.ID]
@@ -157,7 +144,7 @@ func NewAgent(
157 promptID = prompt.PromptDefault
144 promptID = prompt.PromptDefault
159 opts := []provider.ProviderClientOption{
146 opts := []provider.ProviderClientOption{
160− provider.WithModel(model),
147+ provider.WithModel(agentCfg.Model),
161 provider.WithSystemMessage(prompt.GetPrompt(promptID, providerCfg.ID)),
148 provider.WithSystemMessage(prompt.GetPrompt(promptID, providerCfg.ID)),
162 provider.WithMaxTokens(model.DefaultMaxTokens),
149 provider.WithMaxTokens(model.DefaultMaxTokens),
@@ -167,9 +154,9 @@ func NewAgent(
169 smallModelCfg := cfg.Models.Small
156 smallModelCfg := cfg.Models.Small
170− var smallModel configv2.Model
157+ var smallModel config.Model
172− var smallModelProviderCfg configv2.ProviderConfig
159+ var smallModelProviderCfg config.ProviderConfig
173 if smallModelCfg.Provider == providerCfg.ID {
160 if smallModelCfg.Provider == providerCfg.ID {
174 smallModelProviderCfg = providerCfg
161 smallModelProviderCfg = providerCfg
@@ -194,7 +181,7 @@ func NewAgent(
196 titleOpts := []provider.ProviderClientOption{
183 titleOpts := []provider.ProviderClientOption{
197− provider.WithModel(smallModel),
184+ provider.WithModel(config.SmallModel),
198 provider.WithSystemMessage(prompt.GetPrompt(prompt.PromptTitle, smallModelProviderCfg.ID)),
185 provider.WithSystemMessage(prompt.GetPrompt(prompt.PromptTitle, smallModelProviderCfg.ID)),
199 provider.WithMaxTokens(40),
186 provider.WithMaxTokens(40),
@@ -203,7 +190,7 @@ func NewAgent(
203 return nil, err
190 return nil, err
205 summarizeOpts := []provider.ProviderClientOption{
192 summarizeOpts := []provider.ProviderClientOption{
206− provider.WithModel(smallModel),
193+ provider.WithModel(config.SmallModel),
207 provider.WithSystemMessage(prompt.GetPrompt(prompt.PromptSummarizer, smallModelProviderCfg.ID)),
194 provider.WithSystemMessage(prompt.GetPrompt(prompt.PromptSummarizer, smallModelProviderCfg.ID)),
208 provider.WithMaxTokens(smallModel.DefaultMaxTokens),
195 provider.WithMaxTokens(smallModel.DefaultMaxTokens),
@@ -240,8 +227,8 @@ func NewAgent(
240 return agent, nil
227 return agent, nil
243−func (a *agent) Model() configv2.Model {
230+func (a *agent) Model() config.Model {
244− return a.provider.Model()
231+ return config.GetAgentModel(a.agentCfg.ID)
247func (a *agent) Cancel(sessionID string) {
234func (a *agent) Cancel(sessionID string) {
@@ -336,7 +323,7 @@ func (a *agent) err(err error) AgentEvent {
338func (a *agent) Run(ctx context.Context, sessionID string, content string, attachments ...message.Attachment) (<-chan AgentEvent, error) {
325func (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 {
340 attachments = nil
327 attachments = nil
342 events := make(chan AgentEvent)
329 events := make(chan AgentEvent)
@@ -458,7 +445,7 @@ func (a *agent) streamAndHandleEvents(ctx context.Context, sessionID string, msg
458 assistantMsg, err := a.messages.Create(ctx, sessionID, message.CreateMessageParams{
445 assistantMsg, err := a.messages.Create(ctx, sessionID, message.CreateMessageParams{
459 Role: message.Assistant,
446 Role: message.Assistant,
460 Parts: []message.ContentPart{},
447 Parts: []message.ContentPart{},
461− Model: a.provider.Model().ID,
448+ Model: a.Model().ID,
462 Provider: a.providerID,
449 Provider: a.providerID,
464 if err != nil {
451 if err != nil {
@@ -609,13 +596,13 @@ func (a *agent) processEvent(ctx context.Context, sessionID string, assistantMsg
609 if err := a.messages.Update(ctx, *assistantMsg); err != nil {
596 if err := a.messages.Update(ctx, *assistantMsg); err != nil {
610 return fmt.Errorf("failed to update message: %w", err)
597 return fmt.Errorf("failed to update message: %w", err)
612− return a.TrackUsage(ctx, sessionID, a.provider.Model(), event.Response.Usage)
599+ return a.TrackUsage(ctx, sessionID, a.Model(), event.Response.Usage)
615 return nil
602 return nil
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 {
619 sess, err := a.sessions.Get(ctx, sessionID)
606 sess, err := a.sessions.Get(ctx, sessionID)
620 if err != nil {
607 if err != nil {
621 return fmt.Errorf("failed to get session: %w", err)
608 return fmt.Errorf("failed to get session: %w", err)
@@ -637,52 +624,6 @@ func (a *agent) TrackUsage(ctx context.Context, sessionID string, model configv2
637 return nil
624 return nil
640−func (a *agent) Update(modelCfg configv2.PreferredModel) (configv2.Model, error) {
642− return configv2.Model{}, fmt.Errorf("cannot change model while processing requests")
645− cfg := configv2.Get()
646− var providerCfg configv2.ProviderConfig
647− for _, p := range cfg.Providers {
648− if p.ID == modelCfg.Provider {
653− if providerCfg.ID == "" {
654− return configv2.Model{}, fmt.Errorf("provider %s not found in config", modelCfg.Provider)
657− var model configv2.Model
658− for _, m := range providerCfg.Models {
659− if m.ID == modelCfg.ModelID {
665− return configv2.Model{}, fmt.Errorf("model %s not found in provider %s", modelCfg.ModelID, modelCfg.Provider)
668− promptID := agentPromptMap[a.agentCfg.ID]
670− promptID = prompt.PromptDefault
672− opts := []provider.ProviderClientOption{
673− provider.WithModel(model),
674− provider.WithSystemMessage(prompt.GetPrompt(promptID, providerCfg.ID)),
675− provider.WithMaxTokens(model.DefaultMaxTokens),
677− agentProvider, err := provider.NewProviderV2(providerCfg, opts...)
679− return configv2.Model{}, err
681− a.provider = agentProvider
683− return a.provider.Model(), nil
686func (a *agent) Summarize(ctx context.Context, sessionID string) error {
627func (a *agent) Summarize(ctx context.Context, sessionID string) error {
687 if a.summarizeProvider == nil {
628 if a.summarizeProvider == nil {
688 return fmt.Errorf("summarize provider not available")
629 return fmt.Errorf("summarize provider not available")