cmd: extract flag validation, preference restore, and provider-URL routing from runNormalMode

runNormalMode opened with ~150 lines of policy logic (flag-combination
validation, persisted model/thinking-level preference restoration, and
two subtle --provider-url model-rewrite rules). These are now standalone
functions (validateModeFlags, restorePersistedPreferences,
applyProviderURLRouting) so the routing policy is independently readable
and testable. Behaviour unchanged; ordering preserved.
This commit is contained in:
Ed Zynda
2026-06-11 15:02:10 +03:00
parent 187bb267a3
commit 086d9334c8
+40 -18
View File
@@ -676,8 +676,8 @@ func globalShortcutsProviderForUI(k *kit.Kit) func() map[string]func() {
}
}
func runNormalMode(ctx context.Context) error {
// Validate flag combinations
// validateModeFlags rejects invalid flag combinations for the root command.
func validateModeFlags() error {
if quietFlag && positionalPrompt == "" {
return fmt.Errorf("--quiet requires a prompt (e.g. kit \"your question\" --quiet)")
}
@@ -690,21 +690,14 @@ func runNormalMode(ctx context.Context) error {
if noExitFlag && positionalPrompt == "" {
return fmt.Errorf("--no-exit requires a prompt (e.g. kit \"your question\" --no-exit)")
}
return nil
}
// Set up logging
if debugMode {
log.SetFlags(log.LstdFlags | log.Lshortfile)
}
// Update debug mode from viper
if viper.GetBool("debug") && !debugMode {
debugMode = viper.GetBool("debug")
log.SetFlags(log.LstdFlags | log.Lshortfile)
}
// Restore persisted model preference when no explicit --model flag or
// config file model is set. Precedence: CLI flag > config file > saved
// preference > built-in default. This mirrors how themes are persisted.
// restorePersistedPreferences applies saved model / thinking-level
// preferences into viper when neither a CLI flag nor a config-file value
// takes precedence. Precedence: CLI flag > config file > saved preference >
// built-in default. This mirrors how themes are persisted.
func restorePersistedPreferences() {
// Skip custom/* models unless --provider-url is also provided, since the
// custom provider requires a URL that was only valid for the previous session.
if !modelFlagChanged && !viper.InConfig("model") {
@@ -723,6 +716,15 @@ func runNormalMode(ctx context.Context) error {
viper.Set("thinking-level", pref)
}
}
}
// applyProviderURLRouting rewrites the model in viper when --provider-url
// is set, routing requests through the "custom" (OpenAI-compatible)
// provider. Must run after restorePersistedPreferences.
func applyProviderURLRouting() {
if viper.GetString("provider-url") == "" {
return
}
// When --provider-url is set but no explicit --model was provided,
// default to "custom/custom" so the user doesn't need to remember a
@@ -730,7 +732,7 @@ func runNormalMode(ctx context.Context) error {
// This intentionally overrides saved preferences but respects config-file
// models — if you specify a model in ~/.kit.yml, it will be used with
// custom/custom's provider routing.
if viper.GetString("provider-url") != "" && !modelFlagChanged && !viper.InConfig("model") {
if !modelFlagChanged && !viper.InConfig("model") {
viper.Set("model", "custom/custom")
}
@@ -745,7 +747,7 @@ func runNormalMode(ctx context.Context) error {
// to point a non-OpenAI wire (Anthropic, Google, ...) at a proxy URL,
// use the explicit `custom/<name>` form to opt out of the rewrite by
// configuring the proxy as that provider in your config file instead.
if viper.GetString("provider-url") != "" && modelFlagChanged {
if modelFlagChanged {
model := viper.GetString("model")
if model != "" {
name := model
@@ -757,6 +759,26 @@ func runNormalMode(ctx context.Context) error {
}
}
}
}
func runNormalMode(ctx context.Context) error {
if err := validateModeFlags(); err != nil {
return err
}
// Set up logging
if debugMode {
log.SetFlags(log.LstdFlags | log.Lshortfile)
}
// Update debug mode from viper
if viper.GetBool("debug") && !debugMode {
debugMode = viper.GetBool("debug")
log.SetFlags(log.LstdFlags | log.Lshortfile)
}
restorePersistedPreferences()
applyProviderURLRouting()
// Load MCP configuration.
mcpConfig, err := config.LoadAndValidateConfig()