diff --git a/.gitignore b/.gitignore index 2577b4a2..af576d67 100644 --- a/.gitignore +++ b/.gitignore @@ -34,8 +34,5 @@ trace_*.json .claude/settings.local.json .worktrees/ -# Python cache -__pycache__/ -*.pyc -*.pyo -*.pyd +# JetBrains IDE +.idea diff --git a/src/llm/nearai_auth.rs b/src/llm/nearai_auth.rs new file mode 100644 index 00000000..cbd4cbee --- /dev/null +++ b/src/llm/nearai_auth.rs @@ -0,0 +1,42 @@ +use secrecy::{ExposeSecret, SecretString}; + +use crate::llm::LlmError; +use crate::llm::session::SessionManager; + +/// Resolve the active NEAR AI bearer token. +/// +/// Priority order: +/// 1. Explicit API key from resolved config +/// 2. Existing session token +/// 3. Interactive session authentication +/// 4. `NEARAI_API_KEY` from runtime environment +pub async fn resolve_nearai_bearer_token( + api_key: Option<&SecretString>, + session: &SessionManager, +) -> Result { + if let Some(api_key) = api_key { + return Ok(api_key.expose_secret().to_string()); + } + + if session.has_token().await { + let token = session.get_token().await?; + return Ok(token.expose_secret().to_string()); + } + + session.ensure_authenticated().await?; + + if session.has_token().await { + let token = session.get_token().await?; + return Ok(token.expose_secret().to_string()); + } + + if let Ok(key) = std::env::var("NEARAI_API_KEY") + && !key.is_empty() + { + return Ok(key); + } + + Err(LlmError::AuthFailed { + provider: "nearai".to_string(), + }) +} diff --git a/src/tools/mcp/client.rs b/src/tools/mcp/client.rs index 206fdbc5..dca1e27d 100644 --- a/src/tools/mcp/client.rs +++ b/src/tools/mcp/client.rs @@ -704,10 +704,9 @@ fn normalize_mcp_tool_arguments(tool_name: &str, value: serde_json::Value) -> se .get("ui_lang") .and_then(serde_json::Value::as_str) .map(str::trim) + && (ui_lang.is_empty() || !ui_lang.contains('-')) { - if ui_lang.is_empty() || !ui_lang.contains('-') { - map.remove("ui_lang"); - } + map.remove("ui_lang"); } if let Some(freshness) = map