Detailed changes
@@ -67,7 +67,7 @@ func (c *coordinator) agentTool(ctx context.Context) (fantasy.AgentTool, error)
maxTokens = model.ModelCfg.MaxTokens
}
- providerCfg, ok := c.cfgSvc.Config().Providers[model.ModelCfg.Provider]
+ providerCfg, ok := c.cfgSvc.Provider(model.ModelCfg.Provider)
if !ok {
return fantasy.ToolResponse{}, errors.New("model provider not configured")
}
@@ -98,7 +98,7 @@ func (c *coordinator) agenticFetchTool(_ context.Context, client *http.Client) (
return fantasy.ToolResponse{}, permission.ErrorPermissionDenied
}
- tmpDir, err := os.MkdirTemp(c.cfgSvc.Config().Options.DataDirectory, "crush-fetch-*")
+ tmpDir, err := os.MkdirTemp(c.cfgSvc.DataDirectory(), "crush-fetch-*")
if err != nil {
return fantasy.NewTextErrorResponse(fmt.Sprintf("Failed to create temporary directory: %s", err)), nil
}
@@ -156,7 +156,7 @@ func (c *coordinator) agenticFetchTool(_ context.Context, client *http.Client) (
return fantasy.ToolResponse{}, fmt.Errorf("error building system prompt: %s", err)
}
- smallProviderCfg, ok := c.cfgSvc.Config().Providers[small.ModelCfg.Provider]
+ smallProviderCfg, ok := c.cfgSvc.Provider(small.ModelCfg.Provider)
if !ok {
return fantasy.ToolResponse{}, errors.New("small model provider not configured")
}
@@ -177,7 +177,7 @@ func (c *coordinator) agenticFetchTool(_ context.Context, client *http.Client) (
SmallModel: small,
SystemPromptPrefix: smallProviderCfg.SystemPromptPrefix,
SystemPrompt: systemPrompt,
- DisableAutoSummarize: c.cfgSvc.Config().Options.DisableAutoSummarize,
+ DisableAutoSummarize: c.cfgSvc.DisableAutoSummarize(),
IsYolo: c.permissions.SkipRequests(),
Sessions: c.sessions,
Messages: c.messages,
@@ -177,18 +177,18 @@ func coderAgent(r *vcr.Recorder, env fakeEnv, large, small fantasy.LanguageModel
// NOTE(@andreynering): Set a fixed config to ensure cassettes match
// independently of user config on `$HOME/.config/crush/crush.json`.
- cfg.Config().Options.Attribution = &config.Attribution{
+ cfg.SetAttribution(&config.Attribution{
TrailerStyle: "co-authored-by",
GeneratedWith: true,
- }
+ })
// Clear skills paths to ensure test reproducibility - user's skills
// would be included in prompt and break VCR cassette matching.
- cfg.Config().Options.SkillsPaths = []string{}
+ cfg.SetSkillsPaths([]string{})
// Clear LSP config to ensure test reproducibility - user's LSP config
// would be included in prompt and break VCR cassette matching.
- cfg.Config().LSP = nil
+ cfg.SetLSP(nil)
systemPrompt, err := prompt.Build(context.TODO(), large.Provider(), large.Model(), cfg)
if err != nil {
@@ -197,19 +197,19 @@ func coderAgent(r *vcr.Recorder, env fakeEnv, large, small fantasy.LanguageModel
// Get the model name for the bash tool
modelName := large.Model() // fallback to ID if Name not available
- if model := cfg.Config().GetModel(large.Provider(), large.Model()); model != nil {
+ if model := cfg.GetModel(large.Provider(), large.Model()); model != nil {
modelName = model.Name
}
allTools := []fantasy.AgentTool{
- tools.NewBashTool(env.permissions, env.workingDir, cfg.Config().Options.Attribution, modelName),
+ tools.NewBashTool(env.permissions, env.workingDir, cfg.Attribution(), modelName),
tools.NewDownloadTool(env.permissions, env.workingDir, r.GetDefaultClient()),
tools.NewEditTool(env.lspClients, env.permissions, env.history, *env.filetracker, env.workingDir),
tools.NewMultiEditTool(env.lspClients, env.permissions, env.history, *env.filetracker, env.workingDir),
tools.NewFetchTool(env.permissions, env.workingDir, r.GetDefaultClient()),
tools.NewGlobTool(env.workingDir),
tools.NewGrepTool(env.workingDir),
- tools.NewLsTool(env.permissions, env.workingDir, cfg.Config().Tools.Ls),
+ tools.NewLsTool(env.permissions, env.workingDir, cfg.ToolLsConfig()),
tools.NewSourcegraphTool(r.GetDefaultClient()),
tools.NewViewTool(env.lspClients, env.permissions, *env.filetracker, env.workingDir),
tools.NewWriteTool(env.lspClients, env.permissions, env.history, *env.filetracker, env.workingDir),
@@ -61,7 +61,6 @@ type Coordinator interface {
}
type coordinator struct {
- cfg *config.Config
cfgSvc *config.Service
sessions session.Service
messages message.Service
@@ -86,9 +85,7 @@ func NewCoordinator(
filetracker filetracker.Service,
lspClients *csync.Map[string, *lsp.Client],
) (Coordinator, error) {
- cfg := cfgSvc.Config()
c := &coordinator{
- cfg: cfg,
cfgSvc: cfgSvc,
sessions: sessions,
messages: messages,
@@ -99,7 +96,7 @@ func NewCoordinator(
agents: make(map[string]SessionAgent),
}
- agentCfg, ok := cfg.Agents[config.AgentCoder]
+ agentCfg, ok := cfgSvc.Agent(config.AgentCoder)
if !ok {
return nil, errors.New("coder agent not configured")
}
@@ -147,7 +144,7 @@ func (c *coordinator) Run(ctx context.Context, sessionID string, prompt string,
attachments = filteredAttachments
}
- providerCfg, ok := c.cfgSvc.Config().Providers[model.ModelCfg.Provider]
+ providerCfg, ok := c.cfgSvc.Provider(model.ModelCfg.Provider)
if !ok {
return nil, errors.New("model provider not configured")
}
@@ -360,7 +357,7 @@ func (c *coordinator) buildAgent(ctx context.Context, prompt *prompt.Prompt, age
return nil, err
}
- largeProviderCfg, _ := c.cfgSvc.Config().Providers[large.ModelCfg.Provider]
+ largeProviderCfg, _ := c.cfgSvc.Provider(large.ModelCfg.Provider)
result := NewSessionAgent(SessionAgentOptions{
large,
small,
@@ -415,7 +412,7 @@ func (c *coordinator) buildTools(ctx context.Context, agent config.Agent) ([]fan
// Get the model name for the agent
modelName := ""
- if modelCfg, ok := c.cfgSvc.Config().Models[agent.Model]; ok {
+ if modelCfg, ok := c.cfgSvc.SelectedModel(agent.Model); ok {
if model := c.cfgSvc.GetModel(modelCfg.Provider, modelCfg.Model); model != nil {
modelName = model.Name
}
@@ -479,16 +476,16 @@ func (c *coordinator) buildTools(ctx context.Context, agent config.Agent) ([]fan
// TODO: when we support multiple agents we need to change this so that we pass in the agent specific model config
func (c *coordinator) buildAgentModels(ctx context.Context, isSubAgent bool) (Model, Model, error) {
- largeModelCfg, ok := c.cfgSvc.Config().Models[config.SelectedModelTypeLarge]
+ largeModelCfg, ok := c.cfgSvc.SelectedModel(config.SelectedModelTypeLarge)
if !ok {
return Model{}, Model{}, errors.New("large model not selected")
}
- smallModelCfg, ok := c.cfgSvc.Config().Models[config.SelectedModelTypeSmall]
+ smallModelCfg, ok := c.cfgSvc.SelectedModel(config.SelectedModelTypeSmall)
if !ok {
return Model{}, Model{}, errors.New("small model not selected")
}
- largeProviderCfg, ok := c.cfgSvc.Config().Providers[largeModelCfg.Provider]
+ largeProviderCfg, ok := c.cfgSvc.Provider(largeModelCfg.Provider)
if !ok {
return Model{}, Model{}, errors.New("large model provider not configured")
}
@@ -498,7 +495,7 @@ func (c *coordinator) buildAgentModels(ctx context.Context, isSubAgent bool) (Mo
return Model{}, Model{}, err
}
- smallProviderCfg, ok := c.cfgSvc.Config().Providers[smallModelCfg.Provider]
+ smallProviderCfg, ok := c.cfgSvc.Provider(smallModelCfg.Provider)
if !ok {
return Model{}, Model{}, errors.New("large model provider not configured")
}
@@ -881,7 +878,7 @@ func (c *coordinator) QueuedPromptsList(sessionID string) []string {
}
func (c *coordinator) Summarize(ctx context.Context, sessionID string) error {
- providerCfg, ok := c.cfgSvc.Config().Providers[c.currentAgent.Model().ModelCfg.Provider]
+ providerCfg, ok := c.cfgSvc.Provider(c.currentAgent.Model().ModelCfg.Provider)
if !ok {
return errors.New("model provider not configured")
}
@@ -912,7 +909,7 @@ func (c *coordinator) refreshApiKeyTemplate(ctx context.Context, providerCfg con
}
providerCfg.APIKey = newAPIKey
- c.cfgSvc.Config().Providers[providerCfg.ID] = providerCfg
+ c.cfgSvc.SetProvider(providerCfg.ID, providerCfg)
if err := c.UpdateModels(ctx); err != nil {
return err
@@ -75,15 +75,15 @@ type App struct {
// New initializes a new application instance.
func New(ctx context.Context, conn *sql.DB, cfgSvc *config.Service) (*App, error) {
- cfg := cfgSvc.Config()
q := db.New(conn)
sessions := session.NewService(q, conn)
messages := message.NewService(q)
files := history.NewService(q, conn)
- skipPermissionsRequests := cfg.Permissions != nil && cfg.Permissions.SkipRequests
+ perms := cfgSvc.Permissions()
+ skipPermissionsRequests := perms != nil && perms.SkipRequests
var allowedTools []string
- if cfg.Permissions != nil && cfg.Permissions.AllowedTools != nil {
- allowedTools = cfg.Permissions.AllowedTools
+ if perms != nil && perms.AllowedTools != nil {
+ allowedTools = perms.AllowedTools
}
app := &App{
@@ -322,7 +322,7 @@ func (app *App) UpdateAgentModel(ctx context.Context) error {
// If largeModel is provided but smallModel is not, the small model defaults to
// the provider's default small model.
func (app *App) overrideModelsForNonInteractive(ctx context.Context, largeModel, smallModel string) error {
- providers := maps.Clone(app.configService.Config().Providers)
+ providers := maps.Clone(app.configService.AllProviders())
largeMatches, smallMatches, err := findModels(providers, largeModel, smallModel)
if err != nil {
@@ -370,11 +370,11 @@ func (app *App) overrideModelsForNonInteractive(ctx context.Context, largeModel,
// GetDefaultSmallModel returns the default small model for the given
// provider. Falls back to the large model if no default is found.
func (app *App) GetDefaultSmallModel(providerID string) config.SelectedModel {
- cfg := app.configService.Config()
- largeModelCfg := cfg.Models[config.SelectedModelTypeLarge]
+ svc := app.configService
+ largeModelCfg, _ := svc.SelectedModel(config.SelectedModelTypeLarge)
// Find the provider in the known providers list to get its default small model.
- knownProviders, _ := config.Providers(cfg)
+ knownProviders, _ := config.Providers(svc)
var knownProvider *catwalk.Provider
for _, p := range knownProviders {
if string(p.ID) == providerID {
@@ -390,7 +390,7 @@ func (app *App) GetDefaultSmallModel(providerID string) config.SelectedModel {
}
defaultSmallModelID := knownProvider.DefaultSmallModelID
- model := cfg.GetModel(providerID, defaultSmallModelID)
+ model := svc.GetModel(providerID, defaultSmallModelID)
if model == nil {
slog.Warn("Default small model not found, using large model", "provider", providerID, "model", largeModelCfg.Model)
return largeModelCfg
@@ -55,7 +55,7 @@ crush models gpt5`,
var providerIDs []string
providerModels := make(map[string][]string)
- for providerID, provider := range cfg.Config().Providers {
+ for providerID, provider := range cfg.AllProviders() {
if provider.Disable {
continue
}
@@ -128,7 +128,7 @@ func runStats(cmd *cobra.Command, _ []string) error {
if err != nil {
return fmt.Errorf("failed to initialize config: %w", err)
}
- dataDir = svc.Config().Options.DataDirectory
+ dataDir = svc.DataDirectory()
}
conn, err := db.Connect(ctx, dataDir)
@@ -376,8 +376,6 @@ type Config struct {
Permissions *Permissions `json:"permissions,omitempty" jsonschema:"description=Permission settings for tool usage"`
Tools Tools `json:"tools,omitempty" jsonschema:"description=Tool configurations"`
-
- Agents map[string]Agent `json:"-"`
}
func (c *Config) EnabledProviders() []ProviderConfig {
@@ -73,7 +73,7 @@ func Load(workingDir, dataDir string, debug bool) (*Service, error) {
}
// Load known providers, this loads the config from catwalk
- providers, err := Providers(cfg)
+ providers, err := Providers(svc)
if err != nil {
return nil, err
}
@@ -463,12 +463,13 @@ func TestConfig_setupAgentsWithNoDisabledTools(t *testing.T) {
},
}
- serviceFor(cfg).SetupAgents()
- coderAgent, ok := cfg.Agents[AgentCoder]
+ svc := serviceFor(cfg)
+ svc.SetupAgents()
+ coderAgent, ok := svc.Agents()[AgentCoder]
require.True(t, ok)
assert.Equal(t, allToolNames(), coderAgent.AllowedTools)
- taskAgent, ok := cfg.Agents[AgentTask]
+ taskAgent, ok := svc.Agents()[AgentTask]
require.True(t, ok)
assert.Equal(t, []string{"glob", "grep", "ls", "sourcegraph", "view"}, taskAgent.AllowedTools)
}
@@ -484,13 +485,14 @@ func TestConfig_setupAgentsWithDisabledTools(t *testing.T) {
},
}
- serviceFor(cfg).SetupAgents()
- coderAgent, ok := cfg.Agents[AgentCoder]
+ svc := serviceFor(cfg)
+ svc.SetupAgents()
+ coderAgent, ok := svc.Agents()[AgentCoder]
require.True(t, ok)
assert.Equal(t, []string{"agent", "bash", "job_output", "job_kill", "multiedit", "lsp_diagnostics", "lsp_references", "lsp_restart", "fetch", "agentic_fetch", "glob", "ls", "sourcegraph", "todos", "view", "write"}, coderAgent.AllowedTools)
- taskAgent, ok := cfg.Agents[AgentTask]
+ taskAgent, ok := svc.Agents()[AgentTask]
require.True(t, ok)
assert.Equal(t, []string{"glob", "ls", "sourcegraph", "view"}, taskAgent.AllowedTools)
}
@@ -508,12 +510,13 @@ func TestConfig_setupAgentsWithEveryReadOnlyToolDisabled(t *testing.T) {
},
}
- serviceFor(cfg).SetupAgents()
- coderAgent, ok := cfg.Agents[AgentCoder]
+ svc := serviceFor(cfg)
+ svc.SetupAgents()
+ coderAgent, ok := svc.Agents()[AgentCoder]
require.True(t, ok)
assert.Equal(t, []string{"agent", "bash", "job_output", "job_kill", "download", "edit", "multiedit", "lsp_diagnostics", "lsp_references", "lsp_restart", "fetch", "agentic_fetch", "todos", "write"}, coderAgent.AllowedTools)
- taskAgent, ok := cfg.Agents[AgentTask]
+ taskAgent, ok := svc.Agents()[AgentTask]
require.True(t, ok)
assert.Equal(t, []string{}, taskAgent.AllowedTools)
}
@@ -139,12 +139,12 @@ var (
// 2. load the cached providers
// 3. try to get the fresh list of providers, and return either this new list,
// the cached list, or the embedded list if all others fail.
-func Providers(cfg *Config) ([]catwalk.Provider, error) {
+func Providers(svc *Service) ([]catwalk.Provider, error) {
providerOnce.Do(func() {
var wg sync.WaitGroup
var errs []error
providers := csync.NewSlice[catwalk.Provider]()
- autoupdate := !cfg.Options.DisableProviderAutoUpdate
+ autoupdate := !svc.DisableProviderAutoUpdate()
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
defer cancel()
@@ -46,7 +46,7 @@ func TestProviders_Integration_AutoUpdateDisabled(t *testing.T) {
},
}
- providers, err := Providers(cfg)
+ providers, err := Providers(serviceFor(cfg))
require.NoError(t, err)
require.NotNil(t, providers)
require.Greater(t, len(providers), 5, "Expected embedded providers")
@@ -28,13 +28,6 @@ type Service struct {
agents map[string]Agent
}
-// Config returns the underlying Config struct. This is a temporary
-// escape hatch that will be removed once all callers migrate to
-// Service getter methods.
-func (s *Service) Config() *Config {
- return s.cfg
-}
-
// WorkingDir returns the working directory.
func (s *Service) WorkingDir() string {
return s.workingDir
@@ -116,7 +109,6 @@ func (s *Service) SetupAgents() {
AllowedMCP: map[string][]string{},
},
}
- s.cfg.Agents = s.agents
}
// Agents returns the agent configuration map.
@@ -184,6 +176,23 @@ func (s *Service) SelectedModel(modelType SelectedModelType) (SelectedModel, boo
return m, ok
}
+// Provider returns the provider config for the given ID and whether
+// it exists.
+func (s *Service) Provider(id string) (ProviderConfig, bool) {
+ p, ok := s.cfg.Providers[id]
+ return p, ok
+}
+
+// SetProvider sets the provider config for the given ID.
+func (s *Service) SetProvider(id string, p ProviderConfig) {
+ s.cfg.Providers[id] = p
+}
+
+// Providers returns all provider configs.
+func (s *Service) AllProviders() map[string]ProviderConfig {
+ return s.cfg.Providers
+}
+
// MCP returns the MCP configurations.
func (s *Service) MCP() MCPs {
return s.cfg.MCP
@@ -199,6 +208,21 @@ func (s *Service) Permissions() *Permissions {
return s.cfg.Permissions
}
+// SetAttribution sets the attribution settings.
+func (s *Service) SetAttribution(a *Attribution) {
+ s.cfg.Options.Attribution = a
+}
+
+// SetSkillsPaths sets the skills paths.
+func (s *Service) SetSkillsPaths(paths []string) {
+ s.cfg.Options.SkillsPaths = paths
+}
+
+// SetLSP sets the LSP configurations.
+func (s *Service) SetLSP(lsp LSPs) {
+ s.cfg.LSP = lsp
+}
+
// SetPermissions sets the permissions configuration.
func (s *Service) SetPermissions(p *Permissions) {
s.cfg.Permissions = p
@@ -186,12 +186,12 @@ type AssistantInfoItem struct {
id string
message *message.Message
sty *styles.Styles
- cfg *config.Config
+ cfg *config.Service
lastUserMessageTime time.Time
}
// NewAssistantInfoItem creates a new AssistantInfoItem.
-func NewAssistantInfoItem(sty *styles.Styles, message *message.Message, cfg *config.Config, lastUserMessageTime time.Time) MessageItem {
+func NewAssistantInfoItem(sty *styles.Styles, message *message.Message, cfg *config.Service, lastUserMessageTime time.Time) MessageItem {
return &AssistantInfoItem{
cachedMessageItem: &cachedMessageItem{},
id: AssistantInfoID(message.ID),
@@ -239,7 +239,7 @@ func (a *AssistantInfoItem) renderContent(width int) string {
}
modelFormatted := a.sty.Chat.Message.AssistantInfoModel.Render(model.Name)
providerName := a.message.Provider
- if providerConfig, ok := a.cfg.Providers[a.message.Provider]; ok {
+ if providerConfig, ok := a.cfg.Provider(a.message.Provider); ok {
providerName = providerConfig.Name
}
provider := a.sty.Chat.Message.AssistantInfoProvider.Render(fmt.Sprintf("via %s", providerName))
@@ -336,7 +336,6 @@ func (m *Models) FullHelp() [][]key.Binding {
func (m *Models) setProviderItems() error {
t := m.com.Styles
svc := m.com.ConfigService()
- cfg := svc.Config()
var selectedItemID string
selectedType := m.modelType.Config()
@@ -347,7 +346,7 @@ func (m *Models) setProviderItems() error {
addedProviders := make(map[string]bool)
// Get a list of known providers to compare against
- knownProviders, err := config.Providers(cfg)
+ knownProviders, err := config.Providers(svc)
if err != nil {
return fmt.Errorf("failed to get providers: %w", err)
}
@@ -361,7 +360,7 @@ func (m *Models) setProviderItems() error {
// itemsMap contains the keys of added model items.
itemsMap := make(map[string]*ModelItem)
groups := []ModelGroup{}
- for id, p := range cfg.Providers {
+ for id, p := range svc.AllProviders() {
if p.Disable {
continue
}
@@ -411,7 +410,7 @@ func (m *Models) setProviderItems() error {
continue
}
- providerConfig, providerConfigured := cfg.Providers[providerID]
+ providerConfig, providerConfigured := svc.Provider(providerID)
if providerConfigured && providerConfig.Disable {
continue
}
@@ -507,8 +506,7 @@ func (m *Models) setProviderItems() error {
}
func getFilteredProviders(svc *config.Service) ([]catwalk.Provider, error) {
- cfg := svc.Config()
- providers, err := config.Providers(cfg)
+ providers, err := config.Providers(svc)
if err != nil {
return nil, fmt.Errorf("failed to get providers: %w", err)
}
@@ -519,7 +517,7 @@ func getFilteredProviders(svc *config.Service) ([]catwalk.Provider, error) {
isCopilot = p.ID == catwalk.InferenceProviderCopilot
isHyper = string(p.ID) == "hyper"
hasAPIKeyEnv = strings.HasPrefix(p.APIKey, "$")
- _, isConfigured = cfg.Providers[string(p.ID)]
+ _, isConfigured = svc.Provider(string(p.ID))
)
if isAzure || isCopilot || isHyper || hasAPIKeyEnv || isConfigured {
filteredProviders = append(filteredProviders, p)
@@ -77,10 +77,10 @@ func (m *UI) skipInitializeProject() tea.Cmd {
// initializeView renders the project initialization prompt with Yes/No buttons.
func (m *UI) initializeView() string {
- cfg := m.com.ConfigService().Config()
+ cfg := m.com.ConfigService()
s := m.com.Styles.Initialize
cwd := home.Short(m.com.ConfigService().WorkingDir())
- initFile := cfg.Options.InitializeAs
+ initFile := cfg.InitializeAs()
header := s.Header.Render("Would you like to initialize this project?")
path := s.Accent.PaddingLeft(2).Render(cwd)
@@ -21,7 +21,7 @@ func (m *UI) modelInfo(width int) string {
if model != nil {
// Get provider name first
- providerConfig, ok := m.com.ConfigService().Config().Providers[model.ModelCfg.Provider]
+ providerConfig, ok := m.com.ConfigService().Provider(model.ModelCfg.Provider)
if ok {
providerName = providerConfig.Name
@@ -776,7 +776,7 @@ func (m *UI) setSessionMessages(msgs []message.Message) tea.Cmd {
case message.Assistant:
items = append(items, chat.ExtractMessageItems(m.com.Styles, msg, toolResultMap)...)
if msg.FinishPart() != nil && msg.FinishPart().Reason == message.FinishReasonEndTurn {
- infoItem := chat.NewAssistantInfoItem(m.com.Styles, msg, m.com.ConfigService().Config(), time.Unix(m.lastUserMessageTime, 0))
+ infoItem := chat.NewAssistantInfoItem(m.com.Styles, msg, m.com.ConfigService(), time.Unix(m.lastUserMessageTime, 0))
items = append(items, infoItem)
}
default:
@@ -906,7 +906,7 @@ func (m *UI) appendSessionMessage(msg message.Message) tea.Cmd {
}
}
if msg.FinishPart() != nil && msg.FinishPart().Reason == message.FinishReasonEndTurn {
- infoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, m.com.ConfigService().Config(), time.Unix(m.lastUserMessageTime, 0))
+ infoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, m.com.ConfigService(), time.Unix(m.lastUserMessageTime, 0))
m.chat.AppendMessages(infoItem)
if atBottom {
if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil {
@@ -977,7 +977,7 @@ func (m *UI) updateSessionMessage(msg message.Message) tea.Cmd {
if shouldRenderAssistant && msg.FinishPart() != nil && msg.FinishPart().Reason == message.FinishReasonEndTurn {
if infoItem := m.chat.MessageItem(chat.AssistantInfoID(msg.ID)); infoItem == nil {
- newInfoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, m.com.ConfigService().Config(), time.Unix(m.lastUserMessageTime, 0))
+ newInfoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, m.com.ConfigService(), time.Unix(m.lastUserMessageTime, 0))
m.chat.AppendMessages(newInfoItem)
}
}
@@ -1196,17 +1196,17 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
m.dialog.CloseDialog(dialog.CommandsID)
case dialog.ActionToggleThinking:
cmds = append(cmds, func() tea.Msg {
- cfg := m.com.ConfigService().Config()
+ cfg := m.com.ConfigService()
if cfg == nil {
return util.ReportError(errors.New("configuration not found"))()
}
- agentCfg, ok := cfg.Agents[config.AgentCoder]
+ agentCfg, ok := m.com.ConfigService().Agent(config.AgentCoder)
if !ok {
return util.ReportError(errors.New("agent configuration not found"))()
}
- currentModel := cfg.Models[agentCfg.Model]
+ currentModel, _ := cfg.SelectedModel(agentCfg.Model)
currentModel.Think = !currentModel.Think
if err := m.com.ConfigService().UpdatePreferredModel(agentCfg.Model, currentModel); err != nil {
return util.ReportError(err)()
@@ -1235,7 +1235,7 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
break
}
- cfg := m.com.ConfigService().Config()
+ cfg := m.com.ConfigService()
if cfg == nil {
cmds = append(cmds, util.ReportError(errors.New("configuration not found")))
break
@@ -1244,7 +1244,7 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
var (
providerID = msg.Model.Provider
isCopilot = providerID == string(catwalk.InferenceProviderCopilot)
- isConfigured = func() bool { _, ok := cfg.Providers[providerID]; return ok }
+ isConfigured = func() bool { _, ok := cfg.Provider(providerID); return ok }
)
// Attempt to import GitHub Copilot tokens from VSCode if available.
@@ -1262,7 +1262,7 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
if err := m.com.ConfigService().UpdatePreferredModel(msg.ModelType, msg.Model); err != nil {
cmds = append(cmds, util.ReportError(err))
- } else if _, ok := cfg.Models[config.SelectedModelTypeSmall]; !ok {
+ } else if _, ok := cfg.SelectedModel(config.SelectedModelTypeSmall); !ok {
// Ensure small model is set is unset.
smallModel := m.com.App.GetDefaultSmallModel(providerID)
if err := m.com.ConfigService().UpdatePreferredModel(config.SelectedModelTypeSmall, smallModel); err != nil {
@@ -1297,19 +1297,19 @@ func (m *UI) handleDialogMsg(msg tea.Msg) tea.Cmd {
break
}
- cfg := m.com.ConfigService().Config()
+ cfg := m.com.ConfigService()
if cfg == nil {
cmds = append(cmds, util.ReportError(errors.New("configuration not found")))
break
}
- agentCfg, ok := cfg.Agents[config.AgentCoder]
+ agentCfg, ok := m.com.ConfigService().Agent(config.AgentCoder)
if !ok {
cmds = append(cmds, util.ReportError(errors.New("agent configuration not found")))
break
}
- currentModel := cfg.Models[agentCfg.Model]
+ currentModel, _ := cfg.SelectedModel(agentCfg.Model)
currentModel.ReasoningEffort = msg.Effort
if err := m.com.ConfigService().UpdatePreferredModel(agentCfg.Model, currentModel); err != nil {
cmds = append(cmds, util.ReportError(err))