feat(settings): protect model provider deletion and cascade credential updates

- Block deletion of a model provider when it is referenced by any agent,
  returning an error that lists the agent names so the user knows what to unlink first
- When a provider's api_url or api_key is updated, automatically propagate
  the new credentials to all dependent agents: updates env_json in the database
  and patches on-disk config files (Claude Code settings.json, Gemini settings.json,
  Codex auth.json + config.toml, OpenCode auth.json) using the same field names
  and structure as the agent settings UI
- Fix error message display in provider dialogs for both Tauri and web transports,
  which throw plain objects rather than Error instances

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
xintaofei
2026-04-07 00:25:01 +08:00
parent 4245df2f4a
commit a3d5335e7f
17 changed files with 254 additions and 41 deletions

View File

@@ -205,23 +205,15 @@ async fn reorder_once(conn: &DatabaseConnection, agent_types: &[AgentType]) -> R
Ok(())
}
pub async fn clear_model_provider_id(
pub async fn find_by_model_provider_id(
conn: &DatabaseConnection,
model_provider_id: i32,
) -> Result<(), DbError> {
) -> Result<Vec<agent_setting::Model>, DbError> {
let rows = agent_setting::Entity::find()
.filter(agent_setting::Column::ModelProviderId.eq(Some(model_provider_id)))
.all(conn)
.await?;
let now = Utc::now();
for row in rows {
if row.model_provider_id == Some(model_provider_id) {
let mut active = row.into_active_model();
active.model_provider_id = Set(None);
active.updated_at = Set(now);
active.update(conn).await?;
}
}
Ok(())
Ok(rows)
}
fn is_sqlite_full_error(err: &DbError) -> bool {