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:
@@ -245,6 +245,7 @@ pub struct AcpAgentInfo {
|
|||||||
pub codex_auth_json: Option<String>,
|
pub codex_auth_json: Option<String>,
|
||||||
pub codex_config_toml: Option<String>,
|
pub codex_config_toml: Option<String>,
|
||||||
pub cline_secrets_json: Option<String>,
|
pub cline_secrets_json: Option<String>,
|
||||||
|
pub model_provider_id: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lightweight status info for a single agent, used by connect() pre-check.
|
/// Lightweight status info for a single agent, used by connect() pre-check.
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ use crate::acp::types::{
|
|||||||
#[cfg(feature = "tauri-runtime")]
|
#[cfg(feature = "tauri-runtime")]
|
||||||
use crate::acp::types::{ConnectionInfo, ForkResultInfo, PromptInputBlock};
|
use crate::acp::types::{ConnectionInfo, ForkResultInfo, PromptInputBlock};
|
||||||
use crate::db::service::agent_setting_service;
|
use crate::db::service::agent_setting_service;
|
||||||
|
use crate::db::service::model_provider_service;
|
||||||
use crate::db::AppDatabase;
|
use crate::db::AppDatabase;
|
||||||
use crate::models::agent::AgentType;
|
use crate::models::agent::AgentType;
|
||||||
use crate::web::event_bridge::EventEmitter;
|
use crate::web::event_bridge::EventEmitter;
|
||||||
@@ -1121,6 +1122,11 @@ pub(crate) fn load_agent_local_config_json(agent_type: AgentType) -> Option<Stri
|
|||||||
fn merge_json_values(base: &mut serde_json::Value, patch: &serde_json::Value) {
|
fn merge_json_values(base: &mut serde_json::Value, patch: &serde_json::Value) {
|
||||||
if let (Some(base_obj), Some(patch_obj)) = (base.as_object_mut(), patch.as_object()) {
|
if let (Some(base_obj), Some(patch_obj)) = (base.as_object_mut(), patch.as_object()) {
|
||||||
for (key, patch_value) in patch_obj {
|
for (key, patch_value) in patch_obj {
|
||||||
|
if patch_value.is_null() {
|
||||||
|
// null in patch means "remove this key"
|
||||||
|
base_obj.remove(key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
match base_obj.get_mut(key) {
|
match base_obj.get_mut(key) {
|
||||||
Some(base_value) => merge_json_values(base_value, patch_value),
|
Some(base_value) => merge_json_values(base_value, patch_value),
|
||||||
None => {
|
None => {
|
||||||
@@ -1539,6 +1545,30 @@ pub(crate) fn build_runtime_env_from_setting(
|
|||||||
merged
|
merged
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolve model provider credentials into runtime env vars if `model_provider_id` is set.
|
||||||
|
pub(crate) async fn apply_model_provider_env(
|
||||||
|
agent_type: AgentType,
|
||||||
|
setting: Option<&crate::db::entities::agent_setting::Model>,
|
||||||
|
runtime_env: &mut BTreeMap<String, String>,
|
||||||
|
conn: &sea_orm::DatabaseConnection,
|
||||||
|
) {
|
||||||
|
let provider_id = match setting.and_then(|s| s.model_provider_id) {
|
||||||
|
Some(id) => id,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
let provider = match model_provider_service::get_by_id(conn, provider_id).await {
|
||||||
|
Ok(Some(p)) => p,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
let (url_key, key_key, _) = important_env_targets(agent_type);
|
||||||
|
if !provider.api_url.trim().is_empty() {
|
||||||
|
runtime_env.insert(url_key.to_string(), provider.api_url.clone());
|
||||||
|
}
|
||||||
|
if !provider.api_key.trim().is_empty() {
|
||||||
|
runtime_env.insert(key_key.to_string(), provider.api_key.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tauri-runtime", tauri::command)]
|
#[cfg_attr(feature = "tauri-runtime", tauri::command)]
|
||||||
pub async fn acp_preflight(
|
pub async fn acp_preflight(
|
||||||
agent_type: AgentType,
|
agent_type: AgentType,
|
||||||
@@ -1579,6 +1609,9 @@ pub async fn acp_connect(
|
|||||||
let mut runtime_env =
|
let mut runtime_env =
|
||||||
build_runtime_env_from_setting(agent_type, setting.as_ref(), local_config_json.as_deref());
|
build_runtime_env_from_setting(agent_type, setting.as_ref(), local_config_json.as_deref());
|
||||||
|
|
||||||
|
// Resolve model provider credentials if configured.
|
||||||
|
apply_model_provider_env(agent_type, setting.as_ref(), &mut runtime_env, &db.conn).await;
|
||||||
|
|
||||||
// For OpenClaw: when creating a new conversation (no session_id to resume),
|
// For OpenClaw: when creating a new conversation (no session_id to resume),
|
||||||
// signal that we want a fresh transcript via --reset-session.
|
// signal that we want a fresh transcript via --reset-session.
|
||||||
if agent_type == AgentType::OpenClaw && session_id.is_none() {
|
if agent_type == AgentType::OpenClaw && session_id.is_none() {
|
||||||
@@ -1859,6 +1892,7 @@ pub(crate) async fn acp_list_agents_core(
|
|||||||
codex_auth_json,
|
codex_auth_json,
|
||||||
codex_config_toml,
|
codex_config_toml,
|
||||||
cline_secrets_json,
|
cline_secrets_json,
|
||||||
|
model_provider_id: setting.and_then(|m| m.model_provider_id),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1943,7 +1977,11 @@ pub(crate) async fn acp_update_agent_preferences_core(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let patch = agent_setting_service::AgentSettingsUpdate { enabled, env_json };
|
let patch = agent_setting_service::AgentSettingsUpdate {
|
||||||
|
enabled,
|
||||||
|
env_json,
|
||||||
|
model_provider_id: None,
|
||||||
|
};
|
||||||
agent_setting_service::update(&db.conn, agent_type, patch)
|
agent_setting_service::update(&db.conn, agent_type, patch)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| AcpError::protocol(e.to_string()))?;
|
.map_err(|e| AcpError::protocol(e.to_string()))?;
|
||||||
@@ -2018,6 +2056,152 @@ pub async fn acp_update_agent_preferences(
|
|||||||
).await
|
).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn acp_update_agent_env_core(
|
||||||
|
agent_type: AgentType,
|
||||||
|
enabled: bool,
|
||||||
|
env: BTreeMap<String, String>,
|
||||||
|
model_provider_id: Option<i32>,
|
||||||
|
db: &AppDatabase,
|
||||||
|
emitter: &EventEmitter,
|
||||||
|
) -> Result<(), AcpError> {
|
||||||
|
let default = agent_setting_service::AgentDefaultInput {
|
||||||
|
agent_type,
|
||||||
|
registry_id: registry::registry_id_for(agent_type).to_string(),
|
||||||
|
default_sort_order: i32::MAX / 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
agent_setting_service::ensure_defaults(&db.conn, &[default])
|
||||||
|
.await
|
||||||
|
.map_err(|e| AcpError::protocol(e.to_string()))?;
|
||||||
|
|
||||||
|
let env_json = if env.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(serde_json::to_string(&env).map_err(|e| AcpError::protocol(e.to_string()))?)
|
||||||
|
};
|
||||||
|
|
||||||
|
let patch = agent_setting_service::AgentSettingsUpdate {
|
||||||
|
enabled,
|
||||||
|
env_json,
|
||||||
|
model_provider_id,
|
||||||
|
};
|
||||||
|
agent_setting_service::update(&db.conn, agent_type, patch)
|
||||||
|
.await
|
||||||
|
.map_err(|e| AcpError::protocol(e.to_string()))?;
|
||||||
|
|
||||||
|
emit_acp_agents_updated(emitter, "env_updated", Some(agent_type));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "tauri-runtime")]
|
||||||
|
#[cfg_attr(feature = "tauri-runtime", tauri::command)]
|
||||||
|
pub async fn acp_update_agent_env(
|
||||||
|
agent_type: AgentType,
|
||||||
|
enabled: bool,
|
||||||
|
env: BTreeMap<String, String>,
|
||||||
|
model_provider_id: Option<i32>,
|
||||||
|
db: State<'_, AppDatabase>,
|
||||||
|
app: tauri::AppHandle,
|
||||||
|
) -> Result<(), AcpError> {
|
||||||
|
let emitter = EventEmitter::Tauri(app);
|
||||||
|
acp_update_agent_env_core(agent_type, enabled, env, model_provider_id, &db, &emitter).await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub(crate) async fn acp_update_agent_config_core(
|
||||||
|
agent_type: AgentType,
|
||||||
|
config_json: Option<String>,
|
||||||
|
opencode_auth_json: Option<String>,
|
||||||
|
codex_auth_json: Option<String>,
|
||||||
|
codex_config_toml: Option<String>,
|
||||||
|
emitter: &EventEmitter,
|
||||||
|
) -> Result<(), AcpError> {
|
||||||
|
let config_json = config_json.and_then(|raw| {
|
||||||
|
let trimmed = raw.trim();
|
||||||
|
if trimmed.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(trimmed.to_string())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let opencode_auth_json = opencode_auth_json.and_then(|raw| {
|
||||||
|
let trimmed = raw.trim();
|
||||||
|
if trimmed.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(trimmed.to_string())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if let Some(raw) = config_json.as_deref() {
|
||||||
|
let parsed = serde_json::from_str::<serde_json::Value>(raw)
|
||||||
|
.map_err(|e| AcpError::protocol(format!("invalid config_json: {e}")))?;
|
||||||
|
if !parsed.is_object() {
|
||||||
|
return Err(AcpError::protocol(
|
||||||
|
"invalid config_json: root must be a JSON object",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if agent_type == AgentType::Codex {
|
||||||
|
if codex_auth_json.is_some() || codex_config_toml.is_some() {
|
||||||
|
persist_codex_native_config_files(
|
||||||
|
codex_auth_json.as_deref(),
|
||||||
|
codex_config_toml.as_deref(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
emit_acp_agents_updated(emitter, "config_updated", Some(agent_type));
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if agent_type == AgentType::OpenCode {
|
||||||
|
if let Some(raw_auth) = opencode_auth_json.as_deref() {
|
||||||
|
persist_opencode_auth_json(raw_auth)?;
|
||||||
|
}
|
||||||
|
if let Some(raw) = config_json.as_deref() {
|
||||||
|
persist_agent_local_config_json(agent_type, Some(raw))?;
|
||||||
|
}
|
||||||
|
emit_acp_agents_updated(emitter, "config_updated", Some(agent_type));
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if agent_type == AgentType::Cline {
|
||||||
|
if let Some(raw) = config_json.as_deref() {
|
||||||
|
persist_cline_local_config(Some(raw))?;
|
||||||
|
}
|
||||||
|
emit_acp_agents_updated(emitter, "config_updated", Some(agent_type));
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claude Code, Gemini, OpenClaw — write config JSON to local file without merging env
|
||||||
|
let local_patch_value = config_json
|
||||||
|
.as_deref()
|
||||||
|
.and_then(|raw| serde_json::from_str::<serde_json::Value>(raw).ok())
|
||||||
|
.filter(|value| value.is_object())
|
||||||
|
.unwrap_or_else(|| serde_json::json!({}));
|
||||||
|
let local_patch_json = serde_json::to_string(&local_patch_value)
|
||||||
|
.map_err(|e| AcpError::protocol(format!("serialize local patch failed: {e}")))?;
|
||||||
|
persist_agent_local_config_json(agent_type, Some(local_patch_json.as_str()))?;
|
||||||
|
emit_acp_agents_updated(emitter, "config_updated", Some(agent_type));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "tauri-runtime")]
|
||||||
|
#[cfg_attr(feature = "tauri-runtime", tauri::command)]
|
||||||
|
pub async fn acp_update_agent_config(
|
||||||
|
agent_type: AgentType,
|
||||||
|
config_json: Option<String>,
|
||||||
|
opencode_auth_json: Option<String>,
|
||||||
|
codex_auth_json: Option<String>,
|
||||||
|
codex_config_toml: Option<String>,
|
||||||
|
app: tauri::AppHandle,
|
||||||
|
) -> Result<(), AcpError> {
|
||||||
|
let emitter = EventEmitter::Tauri(app);
|
||||||
|
acp_update_agent_config_core(
|
||||||
|
agent_type, config_json, opencode_auth_json, codex_auth_json, codex_config_toml, &emitter,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) async fn acp_download_agent_binary_core(
|
pub(crate) async fn acp_download_agent_binary_core(
|
||||||
agent_type: AgentType,
|
agent_type: AgentType,
|
||||||
emitter: &EventEmitter,
|
emitter: &EventEmitter,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::app_error::AppCommandError;
|
use crate::app_error::AppCommandError;
|
||||||
use crate::db::service::model_provider_service;
|
use crate::db::service::{agent_setting_service, model_provider_service};
|
||||||
use crate::db::AppDatabase;
|
use crate::db::AppDatabase;
|
||||||
use crate::models::agent::AgentType;
|
use crate::models::agent::AgentType;
|
||||||
use crate::models::model_provider::ModelProviderInfo;
|
use crate::models::model_provider::ModelProviderInfo;
|
||||||
@@ -118,6 +118,10 @@ pub async fn delete_model_provider_core(
|
|||||||
db: &AppDatabase,
|
db: &AppDatabase,
|
||||||
id: i32,
|
id: i32,
|
||||||
) -> Result<(), AppCommandError> {
|
) -> Result<(), AppCommandError> {
|
||||||
|
// Clear any agent settings that reference this provider before deleting.
|
||||||
|
agent_setting_service::clear_model_provider_id(&db.conn, id)
|
||||||
|
.await
|
||||||
|
.map_err(AppCommandError::from)?;
|
||||||
model_provider_service::delete(&db.conn, id)
|
model_provider_service::delete(&db.conn, id)
|
||||||
.await
|
.await
|
||||||
.map_err(AppCommandError::from)?;
|
.map_err(AppCommandError::from)?;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ pub struct Model {
|
|||||||
pub sort_order: i32,
|
pub sort_order: i32,
|
||||||
pub installed_version: Option<String>,
|
pub installed_version: Option<String>,
|
||||||
pub env_json: Option<String>,
|
pub env_json: Option<String>,
|
||||||
|
pub model_provider_id: Option<i32>,
|
||||||
pub created_at: DateTimeUtc,
|
pub created_at: DateTimeUtc,
|
||||||
pub updated_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 m20260330_000001_chat_channel;
|
||||||
mod m20260401_000001_chat_channel_sender_context;
|
mod m20260401_000001_chat_channel_sender_context;
|
||||||
mod m20260404_000001_model_provider;
|
mod m20260404_000001_model_provider;
|
||||||
|
mod m20260406_000001_agent_setting_model_provider;
|
||||||
pub struct Migrator;
|
pub struct Migrator;
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
@@ -22,6 +23,7 @@ impl MigratorTrait for Migrator {
|
|||||||
Box::new(m20260330_000001_chat_channel::Migration),
|
Box::new(m20260330_000001_chat_channel::Migration),
|
||||||
Box::new(m20260401_000001_chat_channel_sender_context::Migration),
|
Box::new(m20260401_000001_chat_channel_sender_context::Migration),
|
||||||
Box::new(m20260404_000001_model_provider::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 struct AgentSettingsUpdate {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub env_json: Option<String>,
|
pub env_json: Option<String>,
|
||||||
|
pub model_provider_id: Option<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_enabled(agent_type: AgentType) -> bool {
|
fn default_enabled(agent_type: AgentType) -> bool {
|
||||||
@@ -67,6 +68,7 @@ pub async fn ensure_defaults(
|
|||||||
sort_order: Set(default.default_sort_order),
|
sort_order: Set(default.default_sort_order),
|
||||||
installed_version: Set(None),
|
installed_version: Set(None),
|
||||||
env_json: Set(None),
|
env_json: Set(None),
|
||||||
|
model_provider_id: Set(None),
|
||||||
created_at: Set(now),
|
created_at: Set(now),
|
||||||
updated_at: Set(now),
|
updated_at: Set(now),
|
||||||
};
|
};
|
||||||
@@ -133,6 +135,7 @@ pub async fn update(
|
|||||||
let mut active = model.into_active_model();
|
let mut active = model.into_active_model();
|
||||||
active.enabled = Set(patch.enabled);
|
active.enabled = Set(patch.enabled);
|
||||||
active.env_json = Set(patch.env_json);
|
active.env_json = Set(patch.env_json);
|
||||||
|
active.model_provider_id = Set(patch.model_provider_id);
|
||||||
active.updated_at = Set(Utc::now());
|
active.updated_at = Set(Utc::now());
|
||||||
active.update(conn).await?;
|
active.update(conn).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -202,6 +205,25 @@ async fn reorder_once(conn: &DatabaseConnection, agent_types: &[AgentType]) -> R
|
|||||||
Ok(())
|
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 {
|
fn is_sqlite_full_error(err: &DbError) -> bool {
|
||||||
let message = err.to_string();
|
let message = err.to_string();
|
||||||
message.contains("database or disk is full") || message.contains("(code: 13)")
|
message.contains("database or disk is full") || message.contains("(code: 13)")
|
||||||
|
|||||||
@@ -347,6 +347,8 @@ mod tauri_app {
|
|||||||
acp_commands::acp_prepare_npx_agent,
|
acp_commands::acp_prepare_npx_agent,
|
||||||
acp_commands::acp_uninstall_agent,
|
acp_commands::acp_uninstall_agent,
|
||||||
acp_commands::acp_update_agent_preferences,
|
acp_commands::acp_update_agent_preferences,
|
||||||
|
acp_commands::acp_update_agent_env,
|
||||||
|
acp_commands::acp_update_agent_config,
|
||||||
acp_commands::acp_reorder_agents,
|
acp_commands::acp_reorder_agents,
|
||||||
acp_commands::acp_list_agent_skills,
|
acp_commands::acp_list_agent_skills,
|
||||||
acp_commands::acp_read_agent_skill,
|
acp_commands::acp_read_agent_skill,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ pub struct ModelProviderInfo {
|
|||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub api_url: String,
|
pub api_url: String,
|
||||||
|
pub api_key: String,
|
||||||
pub api_key_masked: String,
|
pub api_key_masked: String,
|
||||||
pub agent_types: Vec<String>,
|
pub agent_types: Vec<String>,
|
||||||
pub created_at: String,
|
pub created_at: String,
|
||||||
@@ -33,6 +34,7 @@ impl From<crate::db::entities::model_provider::Model> for ModelProviderInfo {
|
|||||||
id: m.id,
|
id: m.id,
|
||||||
name: m.name,
|
name: m.name,
|
||||||
api_url: m.api_url,
|
api_url: m.api_url,
|
||||||
|
api_key: m.api_key.clone(),
|
||||||
api_key_masked: mask_api_key(&m.api_key),
|
api_key_masked: mask_api_key(&m.api_key),
|
||||||
agent_types,
|
agent_types,
|
||||||
created_at: m.created_at.to_rfc3339(),
|
created_at: m.created_at.to_rfc3339(),
|
||||||
|
|||||||
@@ -80,6 +80,15 @@ pub async fn acp_connect(
|
|||||||
local_config_json.as_deref(),
|
local_config_json.as_deref(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Resolve model provider credentials if configured.
|
||||||
|
acp_commands::apply_model_provider_env(
|
||||||
|
params.agent_type,
|
||||||
|
setting.as_ref(),
|
||||||
|
&mut runtime_env,
|
||||||
|
&db.conn,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
if params.agent_type == AgentType::OpenClaw && params.session_id.is_none() {
|
if params.agent_type == AgentType::OpenClaw && params.session_id.is_none() {
|
||||||
runtime_env.insert("OPENCLAW_RESET_SESSION".into(), "1".into());
|
runtime_env.insert("OPENCLAW_RESET_SESSION".into(), "1".into());
|
||||||
}
|
}
|
||||||
@@ -398,6 +407,62 @@ pub async fn acp_update_agent_preferences(
|
|||||||
Ok(Json(()))
|
Ok(Json(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct AcpUpdateAgentEnvParams {
|
||||||
|
pub agent_type: AgentType,
|
||||||
|
pub enabled: bool,
|
||||||
|
pub env: BTreeMap<String, String>,
|
||||||
|
pub model_provider_id: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn acp_update_agent_env(
|
||||||
|
Extension(state): Extension<Arc<AppState>>,
|
||||||
|
Json(params): Json<AcpUpdateAgentEnvParams>,
|
||||||
|
) -> Result<Json<()>, AppCommandError> {
|
||||||
|
let db = &state.db;
|
||||||
|
let emitter = state.emitter.clone();
|
||||||
|
acp_commands::acp_update_agent_env_core(
|
||||||
|
params.agent_type,
|
||||||
|
params.enabled,
|
||||||
|
params.env,
|
||||||
|
params.model_provider_id,
|
||||||
|
db,
|
||||||
|
&emitter,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|e| AppCommandError::task_execution_failed(e.to_string()))?;
|
||||||
|
Ok(Json(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct AcpUpdateAgentConfigParams {
|
||||||
|
pub agent_type: AgentType,
|
||||||
|
pub config_json: Option<String>,
|
||||||
|
pub opencode_auth_json: Option<String>,
|
||||||
|
pub codex_auth_json: Option<String>,
|
||||||
|
pub codex_config_toml: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn acp_update_agent_config(
|
||||||
|
Extension(state): Extension<Arc<AppState>>,
|
||||||
|
Json(params): Json<AcpUpdateAgentConfigParams>,
|
||||||
|
) -> Result<Json<()>, AppCommandError> {
|
||||||
|
let emitter = state.emitter.clone();
|
||||||
|
acp_commands::acp_update_agent_config_core(
|
||||||
|
params.agent_type,
|
||||||
|
params.config_json,
|
||||||
|
params.opencode_auth_json,
|
||||||
|
params.codex_auth_json,
|
||||||
|
params.codex_config_toml,
|
||||||
|
&emitter,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|e| AppCommandError::task_execution_failed(e.to_string()))?;
|
||||||
|
Ok(Json(()))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn acp_download_agent_binary(
|
pub async fn acp_download_agent_binary(
|
||||||
Extension(state): Extension<Arc<AppState>>,
|
Extension(state): Extension<Arc<AppState>>,
|
||||||
Json(params): Json<AgentTypeParams>,
|
Json(params): Json<AgentTypeParams>,
|
||||||
|
|||||||
@@ -164,6 +164,8 @@ pub fn build_router(state: Arc<AppState>, token: String, static_dir: std::path::
|
|||||||
.route("/acp_list_connections", post(handlers::acp::acp_list_connections))
|
.route("/acp_list_connections", post(handlers::acp::acp_list_connections))
|
||||||
.route("/acp_clear_binary_cache", post(handlers::acp::acp_clear_binary_cache))
|
.route("/acp_clear_binary_cache", post(handlers::acp::acp_clear_binary_cache))
|
||||||
.route("/acp_update_agent_preferences", post(handlers::acp::acp_update_agent_preferences))
|
.route("/acp_update_agent_preferences", post(handlers::acp::acp_update_agent_preferences))
|
||||||
|
.route("/acp_update_agent_env", post(handlers::acp::acp_update_agent_env))
|
||||||
|
.route("/acp_update_agent_config", post(handlers::acp::acp_update_agent_config))
|
||||||
.route("/acp_download_agent_binary", post(handlers::acp::acp_download_agent_binary))
|
.route("/acp_download_agent_binary", post(handlers::acp::acp_download_agent_binary))
|
||||||
.route("/acp_detect_agent_local_version", post(handlers::acp::acp_detect_agent_local_version))
|
.route("/acp_detect_agent_local_version", post(handlers::acp::acp_detect_agent_local_version))
|
||||||
.route("/acp_prepare_npx_agent", post(handlers::acp::acp_prepare_npx_agent))
|
.route("/acp_prepare_npx_agent", post(handlers::acp::acp_prepare_npx_agent))
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -565,7 +565,18 @@
|
|||||||
"gatewayTokenHint": "يُفضّل استخدام token-file بدل الرمز النصي متى أمكن؛ قم بالإعداد عبر openclaw CLI.",
|
"gatewayTokenHint": "يُفضّل استخدام token-file بدل الرمز النصي متى أمكن؛ قم بالإعداد عبر openclaw CLI.",
|
||||||
"sessionKeyHint": "اختياري. حدّد مفتاح جلسة gateway؛ واتركه فارغًا للتعيين التلقائي لجلسة معزولة."
|
"sessionKeyHint": "اختياري. حدّد مفتاح جلسة gateway؛ واتركه فارغًا للتعيين التلقائي لجلسة معزولة."
|
||||||
},
|
},
|
||||||
|
"authModeOfficialSubscription": "الاشتراك الرسمي",
|
||||||
|
"authModeCustomEndpoint": "نقطة نهاية مخصصة",
|
||||||
|
"authModeCustomEndpointHint": "تكوين عنوان API ومفتاح API يدوياً لنقطة نهاية مخصصة.",
|
||||||
|
"authModeModelProvider": "مزود النموذج",
|
||||||
|
"modelProvider": "مزود النموذج",
|
||||||
|
"modelProviderHint": "استخدم عنوان API ومفتاح API من مزود نموذج مُعدّ.",
|
||||||
|
"selectModelProvider": "اختر مزود النموذج",
|
||||||
|
"noModelProviderAvailable": "لا يوجد مزود نموذج مُعدّ لهذا الوكيل. انتقل إلى إعدادات مزود النموذج لإضافة واحد.",
|
||||||
"claude": {
|
"claude": {
|
||||||
|
"authMode": "وضع المصادقة",
|
||||||
|
"officialSubscription": "الاشتراك الرسمي",
|
||||||
|
"officialSubscriptionHint": "استخدم اشتراك Anthropic الرسمي، لا حاجة لمفتاح API.",
|
||||||
"mainModel": "النموذج الرئيسي",
|
"mainModel": "النموذج الرئيسي",
|
||||||
"reasoningModel": "نموذج الاستدلال (thinking)",
|
"reasoningModel": "نموذج الاستدلال (thinking)",
|
||||||
"haikuDefaultModel": "نموذج Haiku الافتراضي",
|
"haikuDefaultModel": "نموذج Haiku الافتراضي",
|
||||||
@@ -624,7 +635,8 @@
|
|||||||
"configSavedHint": "يجب إعادة فتح الجلسات الحالية لتطبيق التغييرات",
|
"configSavedHint": "يجب إعادة فتح الجلسات الحالية لتطبيق التغييرات",
|
||||||
"saveConfigManagementFailed": "فشل حفظ إدارة الإعدادات",
|
"saveConfigManagementFailed": "فشل حفظ إدارة الإعدادات",
|
||||||
"clineSaved": "تم حفظ تكوين Cline",
|
"clineSaved": "تم حفظ تكوين Cline",
|
||||||
"saveClineFailed": "فشل في حفظ تكوين Cline"
|
"saveClineFailed": "فشل في حفظ تكوين Cline",
|
||||||
|
"modelProviderRequired": "يرجى اختيار مزود نموذج قبل الحفظ."
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"statusLabel": "حالة الإصدار",
|
"statusLabel": "حالة الإصدار",
|
||||||
|
|||||||
@@ -565,7 +565,18 @@
|
|||||||
"gatewayTokenHint": "Wenn möglich token-file statt Klartext-Token verwenden; über openclaw CLI konfigurieren.",
|
"gatewayTokenHint": "Wenn möglich token-file statt Klartext-Token verwenden; über openclaw CLI konfigurieren.",
|
||||||
"sessionKeyHint": "Optional. Gateway-Session-Key angeben; leer lassen für automatische Zuweisung einer isolierten Session."
|
"sessionKeyHint": "Optional. Gateway-Session-Key angeben; leer lassen für automatische Zuweisung einer isolierten Session."
|
||||||
},
|
},
|
||||||
|
"authModeOfficialSubscription": "Offizielles Abonnement",
|
||||||
|
"authModeCustomEndpoint": "Benutzerdefinierter Endpunkt",
|
||||||
|
"authModeCustomEndpointHint": "API-URL und API-Key manuell für einen benutzerdefinierten Endpunkt konfigurieren.",
|
||||||
|
"authModeModelProvider": "Modellanbieter",
|
||||||
|
"modelProvider": "Modellanbieter",
|
||||||
|
"modelProviderHint": "API-URL und API-Key eines konfigurierten Modellanbieters verwenden.",
|
||||||
|
"selectModelProvider": "Modellanbieter auswählen",
|
||||||
|
"noModelProviderAvailable": "Kein Modellanbieter für diesen Agent konfiguriert. Gehen Sie zu den Modellanbieter-Einstellungen, um einen hinzuzufügen.",
|
||||||
"claude": {
|
"claude": {
|
||||||
|
"authMode": "Authentifizierungsmodus",
|
||||||
|
"officialSubscription": "Offizielles Abonnement",
|
||||||
|
"officialSubscriptionHint": "Offizielles Anthropic-Abonnement verwenden, kein API-Key erforderlich.",
|
||||||
"mainModel": "Hauptmodell",
|
"mainModel": "Hauptmodell",
|
||||||
"reasoningModel": "Reasoning-Modell (thinking)",
|
"reasoningModel": "Reasoning-Modell (thinking)",
|
||||||
"haikuDefaultModel": "Standard-Haiku-Modell",
|
"haikuDefaultModel": "Standard-Haiku-Modell",
|
||||||
@@ -624,7 +635,8 @@
|
|||||||
"configSavedHint": "Bestehende Sitzungen müssen neu geöffnet werden, damit die Änderungen wirksam werden",
|
"configSavedHint": "Bestehende Sitzungen müssen neu geöffnet werden, damit die Änderungen wirksam werden",
|
||||||
"saveConfigManagementFailed": "Speichern der Konfigurationsverwaltung fehlgeschlagen",
|
"saveConfigManagementFailed": "Speichern der Konfigurationsverwaltung fehlgeschlagen",
|
||||||
"clineSaved": "Cline-Konfiguration gespeichert",
|
"clineSaved": "Cline-Konfiguration gespeichert",
|
||||||
"saveClineFailed": "Cline-Konfiguration konnte nicht gespeichert werden"
|
"saveClineFailed": "Cline-Konfiguration konnte nicht gespeichert werden",
|
||||||
|
"modelProviderRequired": "Bitte wählen Sie vor dem Speichern einen Modellanbieter aus."
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"statusLabel": "Versionsstatus",
|
"statusLabel": "Versionsstatus",
|
||||||
|
|||||||
@@ -565,7 +565,18 @@
|
|||||||
"gatewayTokenHint": "Use token-file instead of plain token when possible; configure via openclaw CLI.",
|
"gatewayTokenHint": "Use token-file instead of plain token when possible; configure via openclaw CLI.",
|
||||||
"sessionKeyHint": "Optional. Specify gateway session key; leave empty to auto-assign isolated session."
|
"sessionKeyHint": "Optional. Specify gateway session key; leave empty to auto-assign isolated session."
|
||||||
},
|
},
|
||||||
|
"authModeOfficialSubscription": "Official Subscription",
|
||||||
|
"authModeCustomEndpoint": "Custom Endpoint",
|
||||||
|
"authModeCustomEndpointHint": "Manually configure API URL and API Key for a custom endpoint.",
|
||||||
|
"authModeModelProvider": "Model Provider",
|
||||||
|
"modelProvider": "Model Provider",
|
||||||
|
"modelProviderHint": "Use API URL and API Key from a configured model provider.",
|
||||||
|
"selectModelProvider": "Select Model Provider",
|
||||||
|
"noModelProviderAvailable": "No model provider configured for this agent. Go to Model Provider Settings to add one.",
|
||||||
"claude": {
|
"claude": {
|
||||||
|
"authMode": "Auth Mode",
|
||||||
|
"officialSubscription": "Official Subscription",
|
||||||
|
"officialSubscriptionHint": "Use official Anthropic subscription, no API Key required.",
|
||||||
"mainModel": "Main Model",
|
"mainModel": "Main Model",
|
||||||
"reasoningModel": "Reasoning Model (thinking)",
|
"reasoningModel": "Reasoning Model (thinking)",
|
||||||
"haikuDefaultModel": "Default Haiku Model",
|
"haikuDefaultModel": "Default Haiku Model",
|
||||||
@@ -624,7 +635,8 @@
|
|||||||
"configSavedHint": "Existing sessions need to be reopened to take effect",
|
"configSavedHint": "Existing sessions need to be reopened to take effect",
|
||||||
"saveConfigManagementFailed": "Failed to save config management",
|
"saveConfigManagementFailed": "Failed to save config management",
|
||||||
"clineSaved": "Cline config saved",
|
"clineSaved": "Cline config saved",
|
||||||
"saveClineFailed": "Failed to save Cline config"
|
"saveClineFailed": "Failed to save Cline config",
|
||||||
|
"modelProviderRequired": "Please select a model provider before saving."
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"statusLabel": "Version Status",
|
"statusLabel": "Version Status",
|
||||||
|
|||||||
@@ -565,7 +565,18 @@
|
|||||||
"gatewayTokenHint": "Usa token-file en lugar de token en texto plano cuando sea posible; configúralo con el CLI de openclaw.",
|
"gatewayTokenHint": "Usa token-file en lugar de token en texto plano cuando sea posible; configúralo con el CLI de openclaw.",
|
||||||
"sessionKeyHint": "Opcional. Especifica la session key del gateway; si se deja vacío se asigna automáticamente una sesión aislada."
|
"sessionKeyHint": "Opcional. Especifica la session key del gateway; si se deja vacío se asigna automáticamente una sesión aislada."
|
||||||
},
|
},
|
||||||
|
"authModeOfficialSubscription": "Suscripción oficial",
|
||||||
|
"authModeCustomEndpoint": "Endpoint personalizado",
|
||||||
|
"authModeCustomEndpointHint": "Configurar manualmente la URL de API y la clave API para un endpoint personalizado.",
|
||||||
|
"authModeModelProvider": "Proveedor de modelo",
|
||||||
|
"modelProvider": "Proveedor de modelo",
|
||||||
|
"modelProviderHint": "Usar la URL de API y la clave API de un proveedor de modelo configurado.",
|
||||||
|
"selectModelProvider": "Seleccionar proveedor de modelo",
|
||||||
|
"noModelProviderAvailable": "No hay proveedor de modelo configurado para este agente. Vaya a la configuración de proveedores de modelo para agregar uno.",
|
||||||
"claude": {
|
"claude": {
|
||||||
|
"authMode": "Modo de autenticación",
|
||||||
|
"officialSubscription": "Suscripción oficial",
|
||||||
|
"officialSubscriptionHint": "Usar la suscripción oficial de Anthropic, no se requiere API Key.",
|
||||||
"mainModel": "Modelo principal",
|
"mainModel": "Modelo principal",
|
||||||
"reasoningModel": "Modelo de razonamiento (thinking)",
|
"reasoningModel": "Modelo de razonamiento (thinking)",
|
||||||
"haikuDefaultModel": "Modelo Haiku predeterminado",
|
"haikuDefaultModel": "Modelo Haiku predeterminado",
|
||||||
@@ -624,7 +635,8 @@
|
|||||||
"configSavedHint": "Las sesiones existentes deben reabrirse para que surta efecto",
|
"configSavedHint": "Las sesiones existentes deben reabrirse para que surta efecto",
|
||||||
"saveConfigManagementFailed": "No se pudo guardar la gestión de configuración",
|
"saveConfigManagementFailed": "No se pudo guardar la gestión de configuración",
|
||||||
"clineSaved": "Configuración de Cline guardada",
|
"clineSaved": "Configuración de Cline guardada",
|
||||||
"saveClineFailed": "Error al guardar la configuración de Cline"
|
"saveClineFailed": "Error al guardar la configuración de Cline",
|
||||||
|
"modelProviderRequired": "Seleccione un proveedor de modelo antes de guardar."
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"statusLabel": "Estado de versión",
|
"statusLabel": "Estado de versión",
|
||||||
|
|||||||
@@ -565,7 +565,18 @@
|
|||||||
"gatewayTokenHint": "Utilisez token-file plutôt qu’un token en clair si possible ; configurez-le via le CLI openclaw.",
|
"gatewayTokenHint": "Utilisez token-file plutôt qu’un token en clair si possible ; configurez-le via le CLI openclaw.",
|
||||||
"sessionKeyHint": "Optionnel. Spécifie la session key de la gateway ; laisser vide pour auto-attribuer une session isolée."
|
"sessionKeyHint": "Optionnel. Spécifie la session key de la gateway ; laisser vide pour auto-attribuer une session isolée."
|
||||||
},
|
},
|
||||||
|
"authModeOfficialSubscription": "Abonnement officiel",
|
||||||
|
"authModeCustomEndpoint": "Endpoint personnalisé",
|
||||||
|
"authModeCustomEndpointHint": "Configurer manuellement l'URL API et la clé API pour un endpoint personnalisé.",
|
||||||
|
"authModeModelProvider": "Fournisseur de modèle",
|
||||||
|
"modelProvider": "Fournisseur de modèle",
|
||||||
|
"modelProviderHint": "Utiliser l'URL API et la clé API d'un fournisseur de modèle configuré.",
|
||||||
|
"selectModelProvider": "Sélectionner un fournisseur de modèle",
|
||||||
|
"noModelProviderAvailable": "Aucun fournisseur de modèle configuré pour cet agent. Allez dans les paramètres des fournisseurs de modèle pour en ajouter un.",
|
||||||
"claude": {
|
"claude": {
|
||||||
|
"authMode": "Mode d'authentification",
|
||||||
|
"officialSubscription": "Abonnement officiel",
|
||||||
|
"officialSubscriptionHint": "Utiliser l'abonnement officiel Anthropic, pas de clé API requise.",
|
||||||
"mainModel": "Modèle principal",
|
"mainModel": "Modèle principal",
|
||||||
"reasoningModel": "Modèle de raisonnement (thinking)",
|
"reasoningModel": "Modèle de raisonnement (thinking)",
|
||||||
"haikuDefaultModel": "Modèle Haiku par défaut",
|
"haikuDefaultModel": "Modèle Haiku par défaut",
|
||||||
@@ -624,7 +635,8 @@
|
|||||||
"configSavedHint": "Les sessions existantes doivent être rouvertes pour prendre effet",
|
"configSavedHint": "Les sessions existantes doivent être rouvertes pour prendre effet",
|
||||||
"saveConfigManagementFailed": "Échec de l’enregistrement de la gestion de configuration",
|
"saveConfigManagementFailed": "Échec de l’enregistrement de la gestion de configuration",
|
||||||
"clineSaved": "Configuration Cline enregistrée",
|
"clineSaved": "Configuration Cline enregistrée",
|
||||||
"saveClineFailed": "Échec de l'enregistrement de la configuration Cline"
|
"saveClineFailed": "Échec de l'enregistrement de la configuration Cline",
|
||||||
|
"modelProviderRequired": "Veuillez sélectionner un fournisseur de modèle avant d'enregistrer."
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"statusLabel": "Statut de version",
|
"statusLabel": "Statut de version",
|
||||||
|
|||||||
@@ -565,7 +565,18 @@
|
|||||||
"gatewayTokenHint": "可能な場合は平文トークンではなく token-file の使用を推奨します。openclaw CLI で設定してください。",
|
"gatewayTokenHint": "可能な場合は平文トークンではなく token-file の使用を推奨します。openclaw CLI で設定してください。",
|
||||||
"sessionKeyHint": "任意。gateway の session key を指定します。空欄の場合は分離されたセッションが自動割り当てされます。"
|
"sessionKeyHint": "任意。gateway の session key を指定します。空欄の場合は分離されたセッションが自動割り当てされます。"
|
||||||
},
|
},
|
||||||
|
"authModeOfficialSubscription": "公式サブスクリプション",
|
||||||
|
"authModeCustomEndpoint": "カスタムエンドポイント",
|
||||||
|
"authModeCustomEndpointHint": "API URL と API Key を手動で設定してカスタムエンドポイントに接続します。",
|
||||||
|
"authModeModelProvider": "モデルプロバイダー",
|
||||||
|
"modelProvider": "モデルプロバイダー",
|
||||||
|
"modelProviderHint": "設定済みモデルプロバイダーの API URL と API Key を使用します。",
|
||||||
|
"selectModelProvider": "モデルプロバイダーを選択",
|
||||||
|
"noModelProviderAvailable": "このエージェントにはモデルプロバイダーが設定されていません。モデルプロバイダー設定で追加してください。",
|
||||||
"claude": {
|
"claude": {
|
||||||
|
"authMode": "認証方式",
|
||||||
|
"officialSubscription": "公式サブスクリプション",
|
||||||
|
"officialSubscriptionHint": "Anthropic 公式サブスクリプションを使用、API Key 不要。",
|
||||||
"mainModel": "メインモデル",
|
"mainModel": "メインモデル",
|
||||||
"reasoningModel": "推論モデル(thinking)",
|
"reasoningModel": "推論モデル(thinking)",
|
||||||
"haikuDefaultModel": "デフォルト Haiku モデル",
|
"haikuDefaultModel": "デフォルト Haiku モデル",
|
||||||
@@ -624,7 +635,8 @@
|
|||||||
"configSavedHint": "既存のセッションは再度開く必要があります",
|
"configSavedHint": "既存のセッションは再度開く必要があります",
|
||||||
"saveConfigManagementFailed": "設定管理の保存に失敗しました",
|
"saveConfigManagementFailed": "設定管理の保存に失敗しました",
|
||||||
"clineSaved": "Cline設定を保存しました",
|
"clineSaved": "Cline設定を保存しました",
|
||||||
"saveClineFailed": "Cline設定の保存に失敗しました"
|
"saveClineFailed": "Cline設定の保存に失敗しました",
|
||||||
|
"modelProviderRequired": "保存する前にモデルプロバイダーを選択してください。"
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"statusLabel": "バージョン状態",
|
"statusLabel": "バージョン状態",
|
||||||
|
|||||||
@@ -565,7 +565,18 @@
|
|||||||
"gatewayTokenHint": "가능하면 평문 토큰 대신 token-file을 사용하세요. openclaw CLI로 설정하세요.",
|
"gatewayTokenHint": "가능하면 평문 토큰 대신 token-file을 사용하세요. openclaw CLI로 설정하세요.",
|
||||||
"sessionKeyHint": "선택 사항입니다. gateway 세션 키를 지정합니다. 비워두면 격리된 세션이 자동 할당됩니다."
|
"sessionKeyHint": "선택 사항입니다. gateway 세션 키를 지정합니다. 비워두면 격리된 세션이 자동 할당됩니다."
|
||||||
},
|
},
|
||||||
|
"authModeOfficialSubscription": "공식 구독",
|
||||||
|
"authModeCustomEndpoint": "사용자 정의 엔드포인트",
|
||||||
|
"authModeCustomEndpointHint": "API URL과 API Key를 수동으로 구성하여 사용자 정의 엔드포인트에 연결합니다.",
|
||||||
|
"authModeModelProvider": "모델 공급자",
|
||||||
|
"modelProvider": "모델 공급자",
|
||||||
|
"modelProviderHint": "구성된 모델 공급자의 API URL 및 API Key를 사용합니다.",
|
||||||
|
"selectModelProvider": "모델 공급자 선택",
|
||||||
|
"noModelProviderAvailable": "이 에이전트에 구성된 모델 공급자가 없습니다. 모델 공급자 설정에서 추가하세요.",
|
||||||
"claude": {
|
"claude": {
|
||||||
|
"authMode": "인증 방식",
|
||||||
|
"officialSubscription": "공식 구독",
|
||||||
|
"officialSubscriptionHint": "Anthropic 공식 구독 사용, API Key 불필요.",
|
||||||
"mainModel": "메인 모델",
|
"mainModel": "메인 모델",
|
||||||
"reasoningModel": "추론 모델 (thinking)",
|
"reasoningModel": "추론 모델 (thinking)",
|
||||||
"haikuDefaultModel": "기본 Haiku 모델",
|
"haikuDefaultModel": "기본 Haiku 모델",
|
||||||
@@ -624,7 +635,8 @@
|
|||||||
"configSavedHint": "기존 세션은 다시 열어야 적용됩니다",
|
"configSavedHint": "기존 세션은 다시 열어야 적용됩니다",
|
||||||
"saveConfigManagementFailed": "구성 관리 저장 실패",
|
"saveConfigManagementFailed": "구성 관리 저장 실패",
|
||||||
"clineSaved": "Cline 설정 저장됨",
|
"clineSaved": "Cline 설정 저장됨",
|
||||||
"saveClineFailed": "Cline 설정 저장 실패"
|
"saveClineFailed": "Cline 설정 저장 실패",
|
||||||
|
"modelProviderRequired": "저장하기 전에 모델 공급자를 선택하세요."
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"statusLabel": "버전 상태",
|
"statusLabel": "버전 상태",
|
||||||
|
|||||||
@@ -565,7 +565,18 @@
|
|||||||
"gatewayTokenHint": "Use token-file em vez de token em texto puro quando possível; configure via CLI do openclaw.",
|
"gatewayTokenHint": "Use token-file em vez de token em texto puro quando possível; configure via CLI do openclaw.",
|
||||||
"sessionKeyHint": "Opcional. Especifique a session key do gateway; deixe vazio para atribuição automática de sessão isolada."
|
"sessionKeyHint": "Opcional. Especifique a session key do gateway; deixe vazio para atribuição automática de sessão isolada."
|
||||||
},
|
},
|
||||||
|
"authModeOfficialSubscription": "Assinatura oficial",
|
||||||
|
"authModeCustomEndpoint": "Endpoint personalizado",
|
||||||
|
"authModeCustomEndpointHint": "Configurar manualmente a URL da API e a chave API para um endpoint personalizado.",
|
||||||
|
"authModeModelProvider": "Provedor de modelo",
|
||||||
|
"modelProvider": "Provedor de modelo",
|
||||||
|
"modelProviderHint": "Usar URL da API e chave API de um provedor de modelo configurado.",
|
||||||
|
"selectModelProvider": "Selecionar provedor de modelo",
|
||||||
|
"noModelProviderAvailable": "Nenhum provedor de modelo configurado para este agente. Vá para as configurações de provedores de modelo para adicionar um.",
|
||||||
"claude": {
|
"claude": {
|
||||||
|
"authMode": "Modo de autenticação",
|
||||||
|
"officialSubscription": "Assinatura oficial",
|
||||||
|
"officialSubscriptionHint": "Usar assinatura oficial da Anthropic, sem necessidade de API Key.",
|
||||||
"mainModel": "Modelo principal",
|
"mainModel": "Modelo principal",
|
||||||
"reasoningModel": "Modelo de raciocínio (thinking)",
|
"reasoningModel": "Modelo de raciocínio (thinking)",
|
||||||
"haikuDefaultModel": "Modelo Haiku padrão",
|
"haikuDefaultModel": "Modelo Haiku padrão",
|
||||||
@@ -624,7 +635,8 @@
|
|||||||
"configSavedHint": "Sessões existentes precisam ser reabertas para que as alterações tenham efeito",
|
"configSavedHint": "Sessões existentes precisam ser reabertas para que as alterações tenham efeito",
|
||||||
"saveConfigManagementFailed": "Falha ao salvar o gerenciamento de configuração",
|
"saveConfigManagementFailed": "Falha ao salvar o gerenciamento de configuração",
|
||||||
"clineSaved": "Configuração do Cline salva",
|
"clineSaved": "Configuração do Cline salva",
|
||||||
"saveClineFailed": "Falha ao salvar a configuração do Cline"
|
"saveClineFailed": "Falha ao salvar a configuração do Cline",
|
||||||
|
"modelProviderRequired": "Selecione um provedor de modelo antes de salvar."
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"statusLabel": "Status da versão",
|
"statusLabel": "Status da versão",
|
||||||
|
|||||||
@@ -565,7 +565,18 @@
|
|||||||
"gatewayTokenHint": "建议使用 token-file 替代明文 Token,可通过 openclaw 命令行配置。",
|
"gatewayTokenHint": "建议使用 token-file 替代明文 Token,可通过 openclaw 命令行配置。",
|
||||||
"sessionKeyHint": "可选。指定 Gateway Session Key,留空则自动分配隔离会话。"
|
"sessionKeyHint": "可选。指定 Gateway Session Key,留空则自动分配隔离会话。"
|
||||||
},
|
},
|
||||||
|
"authModeOfficialSubscription": "官网订阅",
|
||||||
|
"authModeCustomEndpoint": "自定义接口",
|
||||||
|
"authModeCustomEndpointHint": "手动配置 API URL 和 API Key 连接自定义接口。",
|
||||||
|
"authModeModelProvider": "模型供应商",
|
||||||
|
"modelProvider": "模型供应商",
|
||||||
|
"modelProviderHint": "使用已配置的模型供应商的 API URL 和 API Key。",
|
||||||
|
"selectModelProvider": "选择模型供应商",
|
||||||
|
"noModelProviderAvailable": "该代理未配置模型供应商。请前往模型供应商设置添加。",
|
||||||
"claude": {
|
"claude": {
|
||||||
|
"authMode": "认证方式",
|
||||||
|
"officialSubscription": "官方订阅",
|
||||||
|
"officialSubscriptionHint": "使用 Anthropic 官方订阅,无需 API Key。",
|
||||||
"mainModel": "主模型",
|
"mainModel": "主模型",
|
||||||
"reasoningModel": "推理模型(thinking)",
|
"reasoningModel": "推理模型(thinking)",
|
||||||
"haikuDefaultModel": "Haiku 默认模型",
|
"haikuDefaultModel": "Haiku 默认模型",
|
||||||
@@ -624,7 +635,8 @@
|
|||||||
"configSavedHint": "已有会话需要重新打开才能生效",
|
"configSavedHint": "已有会话需要重新打开才能生效",
|
||||||
"saveConfigManagementFailed": "保存配置管理失败",
|
"saveConfigManagementFailed": "保存配置管理失败",
|
||||||
"clineSaved": "Cline 配置已保存",
|
"clineSaved": "Cline 配置已保存",
|
||||||
"saveClineFailed": "保存 Cline 配置失败"
|
"saveClineFailed": "保存 Cline 配置失败",
|
||||||
|
"modelProviderRequired": "请先选择一个模型供应商再保存。"
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"statusLabel": "版本状态",
|
"statusLabel": "版本状态",
|
||||||
|
|||||||
@@ -565,7 +565,18 @@
|
|||||||
"gatewayTokenHint": "建議使用 token-file 取代明文 Token,可透過 openclaw 命令列配置。",
|
"gatewayTokenHint": "建議使用 token-file 取代明文 Token,可透過 openclaw 命令列配置。",
|
||||||
"sessionKeyHint": "可選。指定 Gateway Session Key,留空則自動分配隔離會話。"
|
"sessionKeyHint": "可選。指定 Gateway Session Key,留空則自動分配隔離會話。"
|
||||||
},
|
},
|
||||||
|
"authModeOfficialSubscription": "官網訂閱",
|
||||||
|
"authModeCustomEndpoint": "自定義介面",
|
||||||
|
"authModeCustomEndpointHint": "手動配置 API URL 和 API Key 連接自定義介面。",
|
||||||
|
"authModeModelProvider": "模型供應商",
|
||||||
|
"modelProvider": "模型供應商",
|
||||||
|
"modelProviderHint": "使用已配置的模型供應商的 API URL 和 API Key。",
|
||||||
|
"selectModelProvider": "選擇模型供應商",
|
||||||
|
"noModelProviderAvailable": "該代理未配置模型供應商。請前往模型供應商設定添加。",
|
||||||
"claude": {
|
"claude": {
|
||||||
|
"authMode": "認證方式",
|
||||||
|
"officialSubscription": "官方訂閱",
|
||||||
|
"officialSubscriptionHint": "使用 Anthropic 官方訂閱,無需 API Key。",
|
||||||
"mainModel": "主模型",
|
"mainModel": "主模型",
|
||||||
"reasoningModel": "推理模型(thinking)",
|
"reasoningModel": "推理模型(thinking)",
|
||||||
"haikuDefaultModel": "Haiku 預設模型",
|
"haikuDefaultModel": "Haiku 預設模型",
|
||||||
@@ -624,7 +635,8 @@
|
|||||||
"configSavedHint": "已有會話需要重新打開才能生效",
|
"configSavedHint": "已有會話需要重新打開才能生效",
|
||||||
"saveConfigManagementFailed": "儲存配置管理失敗",
|
"saveConfigManagementFailed": "儲存配置管理失敗",
|
||||||
"clineSaved": "Cline 配置已儲存",
|
"clineSaved": "Cline 配置已儲存",
|
||||||
"saveClineFailed": "儲存 Cline 配置失敗"
|
"saveClineFailed": "儲存 Cline 配置失敗",
|
||||||
|
"modelProviderRequired": "請先選擇一個模型供應商再儲存。"
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"statusLabel": "版本狀態",
|
"statusLabel": "版本狀態",
|
||||||
|
|||||||
@@ -228,6 +228,40 @@ export async function acpUpdateAgentPreferences(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function acpUpdateAgentEnv(
|
||||||
|
agentType: AgentType,
|
||||||
|
params: {
|
||||||
|
enabled: boolean
|
||||||
|
env: Record<string, string>
|
||||||
|
modelProviderId?: number | null
|
||||||
|
}
|
||||||
|
): Promise<void> {
|
||||||
|
return getTransport().call("acp_update_agent_env", {
|
||||||
|
agentType,
|
||||||
|
enabled: params.enabled,
|
||||||
|
env: params.env,
|
||||||
|
modelProviderId: params.modelProviderId ?? null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function acpUpdateAgentConfig(
|
||||||
|
agentType: AgentType,
|
||||||
|
params: {
|
||||||
|
config_json?: string | null
|
||||||
|
opencode_auth_json?: string | null
|
||||||
|
codex_auth_json?: string | null
|
||||||
|
codex_config_toml?: string | null
|
||||||
|
}
|
||||||
|
): Promise<void> {
|
||||||
|
return getTransport().call("acp_update_agent_config", {
|
||||||
|
agentType,
|
||||||
|
configJson: params.config_json ?? null,
|
||||||
|
opencodeAuthJson: params.opencode_auth_json ?? null,
|
||||||
|
codexAuthJson: params.codex_auth_json ?? null,
|
||||||
|
codexConfigToml: params.codex_config_toml ?? null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export async function acpReorderAgents(agentTypes: AgentType[]): Promise<void> {
|
export async function acpReorderAgents(agentTypes: AgentType[]): Promise<void> {
|
||||||
return getTransport().call("acp_reorder_agents", { agentTypes })
|
return getTransport().call("acp_reorder_agents", { agentTypes })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -475,6 +475,7 @@ export interface AcpAgentInfo {
|
|||||||
codex_auth_json: string | null
|
codex_auth_json: string | null
|
||||||
codex_config_toml: string | null
|
codex_config_toml: string | null
|
||||||
cline_secrets_json: string | null
|
cline_secrets_json: string | null
|
||||||
|
model_provider_id: number | null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lightweight agent status returned by acp_get_agent_status
|
// Lightweight agent status returned by acp_get_agent_status
|
||||||
@@ -902,6 +903,7 @@ export interface ModelProviderInfo {
|
|||||||
id: number
|
id: number
|
||||||
name: string
|
name: string
|
||||||
api_url: string
|
api_url: string
|
||||||
|
api_key: string
|
||||||
api_key_masked: string
|
api_key_masked: string
|
||||||
agent_types: AgentType[]
|
agent_types: AgentType[]
|
||||||
created_at: string
|
created_at: string
|
||||||
|
|||||||
Reference in New Issue
Block a user