Merge remote-tracking branch 'origin/main' into fix/setup-audit-fixes

Resolve conflicts between main's simplified config (no bootstrap param,
env-only DatabaseConfig) and our branch's typed ChannelSetupError.

- config.rs: take main's simpler resolve() signatures (no bootstrap)
- main.rs: remove dead check_onboard_needed block and CACHED_KEYCHAIN_KEY ref
- channels.rs: keep ChannelSetupError types, restore settings params from main
- wizard.rs: pass &self.settings to setup_telegram, use ? with From impl
- settings.rs: fix test_llm_backend_round_trip (use std::fs::write, tempfile::tempdir)

Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
Illia Polosukhin
2026-02-14 14:05:54 -08:00
co-authored by Claude Opus 4.6
48 changed files with 3760 additions and 2499 deletions
+74 -11
View File
@@ -89,7 +89,7 @@ impl SetupWizard {
pub fn new() -> Self {
Self {
config: SetupConfig::default(),
settings: Settings::load(),
settings: Settings::default(),
session_manager: None,
#[cfg(feature = "postgres")]
db_pool: None,
@@ -103,7 +103,7 @@ impl SetupWizard {
pub fn with_config(config: SetupConfig) -> Self {
Self {
config,
settings: Settings::load(),
settings: Settings::default(),
session_manager: None,
#[cfg(feature = "postgres")]
db_pool: None,
@@ -164,7 +164,7 @@ impl SetupWizard {
}
// Save settings and print summary
self.save_and_summarize()?;
self.save_and_summarize().await?;
Ok(())
}
@@ -999,6 +999,8 @@ impl SetupWizard {
session_path: crate::llm::session::default_session_path(),
api_mode: crate::config::NearAiApiMode::Responses,
api_key: None,
fallback_model: None,
max_retries: 3,
},
openai: None,
anthropic: None,
@@ -1198,7 +1200,7 @@ impl SetupWizard {
/// Step 6: Channel configuration.
async fn step_channels(&mut self) -> Result<(), SetupError> {
// First, configure tunnel (shared across all channels that need webhooks)
match setup_tunnel() {
match setup_tunnel(&self.settings) {
Ok(Some(url)) => {
self.settings.tunnel.public_url = Some(url);
}
@@ -1312,7 +1314,7 @@ impl SetupWizard {
if !cap_file.setup.required_secrets.is_empty() {
setup_wasm_channel(ctx, &channel_name, &cap_file.setup).await?
} else if channel_name == "telegram" {
let telegram_result = setup_telegram(ctx).await?;
let telegram_result = setup_telegram(ctx, &self.settings).await?;
if let Some(owner_id) = telegram_result.owner_id {
self.settings.channels.telegram_owner_id = Some(owner_id);
}
@@ -1395,16 +1397,77 @@ impl SetupWizard {
Ok(())
}
/// Save settings and print summary.
fn save_and_summarize(&mut self) -> Result<(), SetupError> {
/// Save settings to the database and `~/.ironclaw/.env`, then print summary.
async fn save_and_summarize(&mut self) -> Result<(), SetupError> {
self.settings.onboard_completed = true;
self.settings
.save()
.map_err(|e| std::io::Error::other(format!("Failed to save settings: {}", e)))?;
// Write all settings to the database (whichever backend is active).
{
let db_map = self.settings.to_db_map();
let saved = false;
#[cfg(feature = "postgres")]
let saved = if !saved {
if let Some(ref pool) = self.db_pool {
let store = crate::history::Store::from_pool(pool.clone());
store
.set_all_settings("default", &db_map)
.await
.map_err(|e| {
SetupError::Database(format!(
"Failed to save settings to database: {}",
e
))
})?;
true
} else {
false
}
} else {
saved
};
#[cfg(feature = "libsql")]
let saved = if !saved {
if let Some(ref backend) = self.db_backend {
use crate::db::Database as _;
backend
.set_all_settings("default", &db_map)
.await
.map_err(|e| {
SetupError::Database(format!(
"Failed to save settings to database: {}",
e
))
})?;
true
} else {
false
}
} else {
saved
};
if !saved {
return Err(SetupError::Database(
"No database connection, cannot save settings".to_string(),
));
}
}
// Save DATABASE_URL to ~/.ironclaw/.env (the only field that needs
// disk persistence before the DB is available).
if let Some(ref url) = self.settings.database_url {
crate::bootstrap::save_database_url(url).map_err(|e| {
SetupError::Io(std::io::Error::other(format!(
"Failed to save DATABASE_URL to .env: {}",
e
)))
})?;
}
println!();
print_success("Configuration saved to ~/.ironclaw/");
print_success("Configuration saved to database");
println!();
// Print summary