use std::path::Path;
use anyhow::Result;
use rigg_client::arm::AiServicesAccount;
use rigg_core::config::{Config, FoundryServiceConfig};
use rigg_core::resources::ResourceKind;
use super::discovery::{
discover_new_foundry_services, discover_new_search_services, try_authenticate,
};
pub(super) async fn run_additive(project_dir: &Path) -> Result<()> {
let mut config = Config::load(project_dir)?;
crate::banner::print_banner();
println!();
println!("Updating rigg project in {}", project_dir.display());
println!();
let ctx = try_authenticate().await?;
let env_name = config
.default_env_name()
.ok_or_else(|| anyhow::anyhow!("No default environment set"))?
.to_string();
let files_dir = config.files_root(project_dir);
let env_config = config
.environments
.get_mut(&env_name)
.ok_or_else(|| anyhow::anyhow!("Environment '{}' not found", env_name))?;
if crate::commands::confirm::prompt_yes_default("Manage Azure AI Search resources?")? {
let new_search = discover_new_search_services(&ctx, &env_config.search).await?;
let resolved = config
.resolve_env(Some(&env_name))
.map_err(|e| anyhow::anyhow!("{}", e))?;
for svc in &new_search {
let search_base = resolved.search_service_dir(&files_dir, svc);
for kind in ResourceKind::search_kinds() {
let dir = search_base.join(kind.directory_name());
std::fs::create_dir_all(&dir)?;
}
}
let env_config = config.environments.get_mut(&env_name).unwrap();
env_config.search.extend(new_search);
}
if crate::commands::confirm::prompt_yes_default("Manage Microsoft Foundry agents?")? {
let env_config = config.environments.get_mut(&env_name).unwrap();
let accounts = ctx
.arm
.list_ai_services_accounts(&ctx.subscription_id)
.await?;
refresh_foundry_endpoints(&mut env_config.foundry, &accounts);
let new_foundry =
discover_new_foundry_services(&ctx, &env_config.foundry, &accounts).await?;
let resolved = config
.resolve_env(Some(&env_name))
.map_err(|e| anyhow::anyhow!("{}", e))?;
for svc in &new_foundry {
let foundry_base = resolved.foundry_service_dir(&files_dir, svc);
std::fs::create_dir_all(foundry_base.join("agents"))?;
}
let env_config = config.environments.get_mut(&env_name).unwrap();
env_config.foundry.extend(new_foundry);
}
config.save(project_dir)?;
println!();
println!("Configuration updated.");
Ok(())
}
pub(crate) fn refresh_foundry_endpoints(
existing: &mut [FoundryServiceConfig],
accounts: &[AiServicesAccount],
) {
for config in existing.iter_mut() {
if let Some(account) = accounts.iter().find(|a| a.name == config.name) {
config.endpoint = Some(account.agents_endpoint());
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use rigg_client::arm::AiServicesAccountProperties;
#[test]
fn test_refresh_foundry_endpoints() {
let mut configs = vec![FoundryServiceConfig {
name: "my-ai-svc".to_string(),
project: "proj-1".to_string(),
label: None,
api_version: "2025-05-15-preview".to_string(),
endpoint: None,
subscription: None,
resource_group: None,
}];
let accounts = vec![AiServicesAccount {
name: "my-ai-svc".to_string(),
location: "eastus".to_string(),
kind: "AIServices".to_string(),
id: String::new(),
properties: AiServicesAccountProperties {
endpoint: Some("https://custom-sub.cognitiveservices.azure.com/".to_string()),
},
}];
refresh_foundry_endpoints(&mut configs, &accounts);
assert_eq!(
configs[0].endpoint.as_deref(),
Some("https://custom-sub.services.ai.azure.com")
);
}
#[test]
fn test_refresh_foundry_endpoints_no_match() {
let mut configs = vec![FoundryServiceConfig {
name: "my-ai-svc".to_string(),
project: "proj-1".to_string(),
label: None,
api_version: "2025-05-15-preview".to_string(),
endpoint: Some("https://old-endpoint.services.ai.azure.com".to_string()),
subscription: None,
resource_group: None,
}];
let accounts = vec![AiServicesAccount {
name: "different-svc".to_string(),
location: "eastus".to_string(),
kind: "AIServices".to_string(),
id: String::new(),
properties: AiServicesAccountProperties::default(),
}];
refresh_foundry_endpoints(&mut configs, &accounts);
assert_eq!(
configs[0].endpoint.as_deref(),
Some("https://old-endpoint.services.ai.azure.com")
);
}
}