package cmd import ( "strings" "github.com/mark3labs/kit/internal/app" "github.com/mark3labs/kit/internal/config" "github.com/mark3labs/kit/internal/ui" kit "github.com/mark3labs/kit/pkg/kit" "github.com/spf13/viper" ) // CollectAgentMetadata extracts model display info and tool/server name lists // from the Kit instance, used to populate app.Options and UI setup. // It also returns the number of MCP tools and extension tools separately. func CollectAgentMetadata(k *kit.Kit, mcpConfig *config.Config) (provider, modelName string, serverNames, toolNames []string, mcpToolCount, extensionToolCount int) { modelString := viper.GetString("model") provider, modelName, _ = kit.ParseModelString(modelString) if modelName == "" { modelName = "Unknown" } for name := range mcpConfig.MCPServers { serverNames = append(serverNames, name) } toolNames = k.GetToolNames() mcpToolCount = k.GetMCPToolCount() extensionToolCount = k.GetExtensionToolCount() return provider, modelName, serverNames, toolNames, mcpToolCount, extensionToolCount } // BuildAppOptions constructs the app.Options struct from the current state. func BuildAppOptions(mcpConfig *config.Config, modelName string, serverNames, toolNames []string) app.Options { return app.Options{ MCPConfig: mcpConfig, ModelName: modelName, ServerNames: serverNames, ToolNames: toolNames, StreamingEnabled: viper.GetBool("stream"), Quiet: quietFlag, Debug: viper.GetBool("debug"), } } // DisplayDebugConfig builds and displays the debug configuration map through // the CLI for non-interactive mode. func DisplayDebugConfig(cli *ui.CLI, k *kit.Kit, mcpConfig *config.Config, provider string) { if quietFlag || cli == nil || !viper.GetBool("debug") { return } debugConfig := map[string]any{ "model": viper.GetString("model"), "max-steps": viper.GetInt("max-steps"), "max-tokens": viper.GetInt("max-tokens"), "temperature": viper.GetFloat64("temperature"), "top-p": viper.GetFloat64("top-p"), "top-k": viper.GetInt("top-k"), "provider-url": viper.GetString("provider-url"), "system-prompt": viper.GetString("system-prompt"), } if viper.GetBool("tls-skip-verify") { debugConfig["tls-skip-verify"] = true } if provider == "ollama" { debugConfig["num-gpu-layers"] = viper.GetInt("num-gpu-layers") debugConfig["main-gpu"] = viper.GetInt("main-gpu") } if stopSeqs := viper.GetStringSlice("stop-sequences"); len(stopSeqs) > 0 { debugConfig["stop-sequences"] = stopSeqs } if viper.GetString("provider-api-key") != "" { debugConfig["provider-api-key"] = "[SET]" } // MCP server info if len(mcpConfig.MCPServers) > 0 { mcpServers := make(map[string]any) loadedServerSet := make(map[string]bool) for _, name := range k.GetLoadedServerNames() { loadedServerSet[name] = true } for name, server := range mcpConfig.MCPServers { serverInfo := map[string]any{ "type": server.Type, "status": "failed", } if loadedServerSet[name] { serverInfo["status"] = "loaded" } if len(server.Command) > 0 { serverInfo["command"] = server.Command } if len(server.Environment) > 0 { maskedEnv := make(map[string]string) for k, v := range server.Environment { if strings.Contains(strings.ToLower(k), "token") || strings.Contains(strings.ToLower(k), "key") || strings.Contains(strings.ToLower(k), "secret") { maskedEnv[k] = "[MASKED]" } else { maskedEnv[k] = v } } serverInfo["environment"] = maskedEnv } if server.URL != "" { serverInfo["url"] = server.URL } mcpServers[name] = serverInfo } debugConfig["mcpServers"] = mcpServers } cli.DisplayDebugConfig(debugConfig) } // SetupCLIForNonInteractive creates the CLI display layer for non-interactive // mode (--prompt). Returns nil when quiet mode is active. func SetupCLIForNonInteractive(k *kit.Kit) (*ui.CLI, error) { agentAdapter := &kitUIAdapter{kit: k} return ui.SetupCLI(&ui.CLISetupOptions{ Agent: agentAdapter, ModelString: viper.GetString("model"), Debug: viper.GetBool("debug"), Quiet: quietFlag, ShowDebug: false, ProviderAPIKey: viper.GetString("provider-api-key"), }) }