rework config

This commit is contained in:
Dax Raad
2025-06-18 22:20:03 -04:00
parent 1e8a681de9
commit e5e9b3e3c0
14 changed files with 785 additions and 203 deletions

View File

@@ -22,8 +22,9 @@ type App struct {
Info client.AppInfo
Version string
StatePath string
Config *config.Config
Configg *client.ConfigInfo
Client *client.ClientWithResponses
State *config.State
Provider *client.ProviderInfo
Model *client.ModelInfo
Session *client.SessionInfo
@@ -54,14 +55,15 @@ func New(
) (*App, error) {
RootPath = appInfo.Path.Root
appConfigPath := filepath.Join(appInfo.Path.Config, "config")
appConfig, err := config.LoadConfig(appConfigPath)
configResponse, err := httpClient.PostConfigGetWithResponse(ctx)
if err != nil {
appConfig = config.NewConfig()
return nil, err
}
if len(appConfig.Keybinds) == 0 {
appConfig.Keybinds = make(map[string]string)
appConfig.Keybinds["leader"] = "ctrl+x"
configInfo := configResponse.JSON200
if configInfo.Keybinds == nil {
keybinds := make(map[string]string)
keybinds["leader"] = "ctrl+x"
configInfo.Keybinds = &keybinds
}
appStatePath := filepath.Join(appInfo.Path.State, "tui")
@@ -71,20 +73,25 @@ func New(
config.SaveState(appStatePath, appState)
}
mergedConfig := config.MergeState(appState, appConfig)
theme.SetTheme(mergedConfig.Theme)
if configInfo.Theme != nil {
appState.Theme = *configInfo.Theme
}
if appState.Theme != "" {
theme.SetTheme(appState.Theme)
}
slog.Debug("Loaded config", "config", mergedConfig)
slog.Debug("Loaded config", "config", configInfo)
app := &App{
Info: appInfo,
Version: version,
StatePath: appStatePath,
Config: mergedConfig,
Configg: configInfo,
State: appState,
Client: httpClient,
Session: &client.SessionInfo{},
Messages: []client.MessageInfo{},
Commands: commands.LoadFromConfig(mergedConfig),
Commands: commands.LoadFromConfig(configInfo),
}
return app, nil
@@ -130,11 +137,11 @@ func (a *App) InitializeProvider() tea.Cmd {
var currentProvider *client.ProviderInfo
var currentModel *client.ModelInfo
for _, provider := range providers {
if provider.Id == a.Config.Provider {
if provider.Id == a.State.Provider {
currentProvider = &provider
for _, model := range provider.Models {
if model.Id == a.Config.Model {
if model.Id == a.State.Model {
currentModel = &model
}
}
@@ -182,8 +189,7 @@ func (a *App) IsBusy() bool {
}
func (a *App) SaveState() {
state := config.ConfigToState(a.Config)
err := config.SaveState(a.StatePath, state)
err := config.SaveState(a.StatePath, a.State)
if err != nil {
slog.Error("Failed to save state", "error", err)
}

View File

@@ -5,7 +5,7 @@ import (
"strings"
tea "github.com/charmbracelet/bubbletea/v2"
"github.com/sst/opencode/internal/config"
"github.com/sst/opencode/pkg/client"
)
type ExecuteCommandMsg Command
@@ -106,8 +106,12 @@ func (k Command) Matches(msg tea.KeyPressMsg, leader bool) bool {
return false
}
func (k Command) FromConfig(config *config.Config) Command {
if keybind, ok := config.Keybinds[string(k.Name)]; ok {
func (k Command) FromConfig(config *client.ConfigInfo) Command {
if config.Keybinds == nil {
return k
}
keybinds := *config.Keybinds
if keybind, ok := keybinds[string(k.Name)]; ok {
k.Keybindings = parseBindings(keybind)
}
return k
@@ -129,7 +133,7 @@ func parseBindings(bindings ...string) []Keybinding {
return parsedBindings
}
func LoadFromConfig(config *config.Config) CommandRegistry {
func LoadFromConfig(config *client.ConfigInfo) CommandRegistry {
defaults := []Command{
{
Name: AppHelpCommand,

View File

@@ -7,6 +7,7 @@ import (
"os"
"github.com/BurntSushi/toml"
"github.com/sst/opencode/pkg/client"
)
type State struct {
@@ -15,44 +16,15 @@ type State struct {
Model string `toml:"model"`
}
type Config struct {
Theme string `toml:"theme"`
Provider string `toml:"provider"`
Model string `toml:"model"`
Keybinds map[string]string `toml:"keybinds"`
}
func NewState() *State {
return &State{
Theme: "opencode",
}
}
func NewConfig() *Config {
keybinds := make(map[string]string)
keybinds["leader"] = "ctrl+x"
return &Config{
Keybinds: keybinds,
}
}
func ConfigToState(config *Config) *State {
return &State{
Theme: config.Theme,
Provider: config.Provider,
Model: config.Model,
}
}
func MergeState(state *State, config *Config) *Config {
if config.Theme == "" {
config.Theme = state.Theme
}
if config.Provider == "" {
config.Provider = state.Provider
}
if config.Model == "" {
config.Model = state.Model
func MergeState(state *State, config *client.ConfigInfo) *client.ConfigInfo {
if config.Theme == nil {
config.Theme = &state.Theme
}
return config
}
@@ -79,19 +51,6 @@ func SaveState(filePath string, state *State) error {
return nil
}
// LoadConfig reads a Config struct from the specified TOML file.
// It returns a pointer to the Config struct and an error if any issues occur.
func LoadConfig(filePath string) (*Config, error) {
var config Config
if _, err := toml.DecodeFile(filePath, &config); err != nil {
if _, statErr := os.Stat(filePath); os.IsNotExist(statErr) {
return nil, fmt.Errorf("config file not found at %s: %w", filePath, statErr)
}
return nil, fmt.Errorf("failed to decode TOML from file %s: %w", filePath, err)
}
return &config, nil
}
// LoadState loads the state from the specified TOML file.
// It returns a pointer to the State struct and an error if any issues occur.
func LoadState(filePath string) (*State, error) {

View File

@@ -249,11 +249,11 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case app.ModelSelectedMsg:
a.app.Provider = &msg.Provider
a.app.Model = &msg.Model
a.app.Config.Provider = msg.Provider.Id
a.app.Config.Model = msg.Model.Id
a.app.State.Provider = msg.Provider.Id
a.app.State.Model = msg.Model.Id
a.app.SaveState()
case dialog.ThemeSelectedMsg:
a.app.Config.Theme = msg.ThemeName
a.app.State.Theme = msg.ThemeName
a.app.SaveState()
}
@@ -509,7 +509,7 @@ func NewModel(app *app.App) tea.Model {
messagesContainer := layout.NewContainer(messages)
var leaderBinding *key.Binding
if leader, ok := app.Config.Keybinds["leader"]; ok {
if leader, ok := (*app.Configg.Keybinds)["leader"]; ok {
binding := key.NewBinding(key.WithKeys(leader))
leaderBinding = &binding
}