Fix: banner on launch, config file loading, 7 providers match setup wizard

BUGFIXES:
- Banner now displays on 'gyandoot run' via gyandoot_tui::banner::print_banner()
- Config now loads from ~/.config/gyandoot/config.toml with fallback chain
  (XDG -> ~/.gyandoot/config.yaml -> hardcoded defaults), fixing 401 errors
- gyandoot init now writes visible placeholder api_key for users to edit

NEW PROVIDERS (4 added, now 7 total matching setup wizard):
- Google Gemini: Native API with x-goog-api-key auth, streamingGenerateContent
- DeepSeek: OpenAI-compatible wrapper at api.deepseek.com/v1
- OpenRouter: With HTTP-Referer/X-Title headers, model routing
- Groq: OpenAI-compatible wrapper at api.groq.com/openai/v1

All compile with 0 errors.
This commit is contained in:
2026-06-11 21:40:34 +05:30
parent dd21654555
commit fb01b2595a
9 changed files with 1202 additions and 13 deletions

View File

@@ -178,14 +178,13 @@ fn default_config_dir() -> PathBuf {
/// Run the agent in the given platform mode
async fn cmd_run(profile_name: &str, platform: &str, prompt: Option<&str>) -> anyhow::Result<()> {
// Print the banner on launch
gyandoot_tui::banner::print_banner();
tracing::info!("Running agent (profile={}, platform={})", profile_name, platform);
// Load config via resolver
let resolver = gyandoot_profile::ConfigResolver::default();
let _resolved = resolver.resolve();
// Initialize the agent loop using gyandoot-core config
let config = gyandoot_core::config::AgentConfig::default();
// Load config from user config files, falling back to defaults
let config = load_agent_config();
let agent = gyandoot_agent::agent_loop::AgentLoop::new(config);
if let Some(p) = prompt {
@@ -196,6 +195,51 @@ async fn cmd_run(profile_name: &str, platform: &str, prompt: Option<&str>) -> an
Ok(())
}
/// Load agent config from user config files with fallback to defaults.
///
/// Resolution order:
/// 1. `~/.config/gyandoot/config.toml` (XDG primary)
/// 2. `~/.gyandoot/config.yaml` (legacy)
/// 3. `AgentConfig::default()` (hardcoded defaults)
fn load_agent_config() -> gyandoot_core::config::AgentConfig {
// 1. Try XDG-style config: ~/.config/gyandoot/config.toml
if let Some(cfg_dir) = dirs::config_dir() {
let xdg_path = cfg_dir.join("gyandoot").join("config.toml");
if xdg_path.exists() {
match gyandoot_core::config::ConfigLoader::from_file(&xdg_path) {
Ok(gyandoot_cfg) => {
tracing::info!("Loaded config from {}", xdg_path.display());
return gyandoot_core::config::AgentConfig::from(gyandoot_cfg);
}
Err(e) => tracing::warn!("Failed to parse {}: {}", xdg_path.display(), e),
}
}
}
// 2. Try legacy config: ~/.gyandoot/config.yaml
if let Some(home) = dirs::home_dir() {
let legacy_path = home.join(".gyandoot").join("config.yaml");
if legacy_path.exists() {
match std::fs::read_to_string(&legacy_path) {
Ok(contents) => {
match serde_yaml::from_str::<gyandoot_core::config::GyandootConfig>(&contents) {
Ok(gyandoot_cfg) => {
tracing::info!("Loaded config from {}", legacy_path.display());
return gyandoot_core::config::AgentConfig::from(gyandoot_cfg);
}
Err(e) => tracing::warn!("Failed to parse {}: {}", legacy_path.display(), e),
}
}
Err(e) => tracing::warn!("Failed to read {}: {}", legacy_path.display(), e),
}
}
}
// 3. Fallback to hardcoded defaults
tracing::warn!("No config file found; using default configuration (API keys will be empty)");
gyandoot_core::config::AgentConfig::default()
}
/// Start the gateway server for multi-platform sessions
async fn cmd_serve(profile_name: &str, host: &str, port: u16) -> anyhow::Result<()> {
tracing::info!(
@@ -238,7 +282,7 @@ system_prompt = "You are GyanDoot, an AI Agent Platform."
default = "openai"
[providers.openai]
api_key = ""
api_key = "sk-your-api-key-here"
model = "gpt-4o"
[platform]