feat(settings): refactor agent auth modes and add model provider authentication
- Split env vars and config file persistence into separate save operations - Add model_provider_id field to agent_setting for tracking selected provider - Add "Model Provider" auth mode for Claude Code, Codex CLI, and Gemini CLI - Add "Custom Endpoint" auth mode for Claude Code (previously only official subscription) - Unify auth mode labels across all three agents (official subscription / custom endpoint / model provider) - When model provider is selected, fill api_url and api_key into env and config automatically - Resolve model provider credentials at ACP connect time as a backend fallback - Clear provider deletion cascades to agent_setting.model_provider_id - Claude Code writes API credentials to config.env (ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN) - Codex: switching auth modes patches config.toml instead of clearing it - Add i18n keys for new auth modes in all 10 supported languages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ pub struct Model {
|
||||
pub sort_order: i32,
|
||||
pub installed_version: Option<String>,
|
||||
pub env_json: Option<String>,
|
||||
pub model_provider_id: Option<i32>,
|
||||
pub created_at: DateTimeUtc,
|
||||
pub updated_at: DateTimeUtc,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.alter_table(
|
||||
Table::alter()
|
||||
.table(AgentSetting::Table)
|
||||
.add_column(ColumnDef::new(AgentSetting::ModelProviderId).integer().null())
|
||||
.to_owned(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.alter_table(
|
||||
Table::alter()
|
||||
.table(AgentSetting::Table)
|
||||
.drop_column(AgentSetting::ModelProviderId)
|
||||
.to_owned(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum AgentSetting {
|
||||
Table,
|
||||
ModelProviderId,
|
||||
}
|
||||
@@ -8,6 +8,7 @@ mod m20260227_000001_folder_parent_branch;
|
||||
mod m20260330_000001_chat_channel;
|
||||
mod m20260401_000001_chat_channel_sender_context;
|
||||
mod m20260404_000001_model_provider;
|
||||
mod m20260406_000001_agent_setting_model_provider;
|
||||
pub struct Migrator;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
@@ -22,6 +23,7 @@ impl MigratorTrait for Migrator {
|
||||
Box::new(m20260330_000001_chat_channel::Migration),
|
||||
Box::new(m20260401_000001_chat_channel_sender_context::Migration),
|
||||
Box::new(m20260404_000001_model_provider::Migration),
|
||||
Box::new(m20260406_000001_agent_setting_model_provider::Migration),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ pub struct AgentDefaultInput {
|
||||
pub struct AgentSettingsUpdate {
|
||||
pub enabled: bool,
|
||||
pub env_json: Option<String>,
|
||||
pub model_provider_id: Option<i32>,
|
||||
}
|
||||
|
||||
fn default_enabled(agent_type: AgentType) -> bool {
|
||||
@@ -67,6 +68,7 @@ pub async fn ensure_defaults(
|
||||
sort_order: Set(default.default_sort_order),
|
||||
installed_version: Set(None),
|
||||
env_json: Set(None),
|
||||
model_provider_id: Set(None),
|
||||
created_at: Set(now),
|
||||
updated_at: Set(now),
|
||||
};
|
||||
@@ -133,6 +135,7 @@ pub async fn update(
|
||||
let mut active = model.into_active_model();
|
||||
active.enabled = Set(patch.enabled);
|
||||
active.env_json = Set(patch.env_json);
|
||||
active.model_provider_id = Set(patch.model_provider_id);
|
||||
active.updated_at = Set(Utc::now());
|
||||
active.update(conn).await?;
|
||||
Ok(())
|
||||
@@ -202,6 +205,25 @@ async fn reorder_once(conn: &DatabaseConnection, agent_types: &[AgentType]) -> R
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn clear_model_provider_id(
|
||||
conn: &DatabaseConnection,
|
||||
model_provider_id: i32,
|
||||
) -> Result<(), DbError> {
|
||||
let rows = agent_setting::Entity::find()
|
||||
.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(())
|
||||
}
|
||||
|
||||
fn is_sqlite_full_error(err: &DbError) -> bool {
|
||||
let message = err.to_string();
|
||||
message.contains("database or disk is full") || message.contains("(code: 13)")
|
||||
|
||||
Reference in New Issue
Block a user