mirror of
https://github.com/ZSeven-W/openpencil.git
synced 2026-05-31 19:04:29 +07:00
fix(ai): dedupe built-in providers
This commit is contained in:
parent
14c6cd2bf3
commit
86cedad794
3 changed files with 101 additions and 5 deletions
|
|
@ -182,6 +182,21 @@ impl BuiltinAgentConfig {
|
|||
pub fn ready(&self) -> bool {
|
||||
self.enabled && !self.api_key.trim().is_empty() && !self.model.trim().is_empty()
|
||||
}
|
||||
|
||||
pub fn matches_config(
|
||||
&self,
|
||||
display_name: &str,
|
||||
api_key: &str,
|
||||
model: &str,
|
||||
kind: BuiltinAgentKind,
|
||||
base_url: &str,
|
||||
) -> bool {
|
||||
self.kind == kind
|
||||
&& self.display_name.trim() == display_name.trim()
|
||||
&& self.api_key.trim() == api_key.trim()
|
||||
&& self.model.trim() == model.trim()
|
||||
&& self.base_url.trim().trim_end_matches('/') == base_url.trim().trim_end_matches('/')
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
|
|
@ -474,15 +489,26 @@ impl AgentSettings {
|
|||
kind: BuiltinAgentKind,
|
||||
base_url: impl Into<String>,
|
||||
) -> String {
|
||||
let display_name = display_name.into();
|
||||
let api_key = api_key.into();
|
||||
let model = model.into();
|
||||
let base_url = base_url.into();
|
||||
if let Some(existing) = self
|
||||
.builtin_agents
|
||||
.iter()
|
||||
.find(|agent| agent.matches_config(&display_name, &api_key, &model, kind, &base_url))
|
||||
{
|
||||
return existing.id.clone();
|
||||
}
|
||||
let id = format!("builtin-{}", self.next_builtin_agent_id.max(1));
|
||||
self.next_builtin_agent_id = self.next_builtin_agent_id.max(1).saturating_add(1);
|
||||
self.builtin_agents.push(BuiltinAgentConfig {
|
||||
id: id.clone(),
|
||||
display_name: display_name.into(),
|
||||
display_name,
|
||||
kind,
|
||||
api_key: api_key.into(),
|
||||
model: model.into(),
|
||||
base_url: base_url.into(),
|
||||
api_key,
|
||||
model,
|
||||
base_url,
|
||||
enabled: true,
|
||||
});
|
||||
id
|
||||
|
|
|
|||
|
|
@ -1,5 +1,17 @@
|
|||
use crate::agent_settings::AgentSettings;
|
||||
|
||||
#[test]
|
||||
fn duplicate_builtin_agent_config_reuses_existing_provider() {
|
||||
let mut s = AgentSettings::default();
|
||||
|
||||
let first = s.add_builtin_agent_with_defaults("MINIMAX", "sk-test", "MiniMax-M2.7");
|
||||
let second = s.add_builtin_agent_with_defaults("MINIMAX", "sk-test", "MiniMax-M2.7");
|
||||
|
||||
assert_eq!(second, first);
|
||||
assert_eq!(s.builtin_agents.len(), 1);
|
||||
assert_eq!(s.next_builtin_agent_id, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builtin_agent_draft_does_not_persist_until_save() {
|
||||
let mut s = AgentSettings::default();
|
||||
|
|
|
|||
|
|
@ -252,10 +252,11 @@ fn apply_payload(state: &mut EditorState, payload: SettingsPayload) {
|
|||
eui.agent_settings.connected = c;
|
||||
}
|
||||
if let Some(agents) = payload.builtin_agents {
|
||||
eui.agent_settings.builtin_agents = agents
|
||||
let agents = agents
|
||||
.into_iter()
|
||||
.filter_map(builtin_agent_from_payload)
|
||||
.collect();
|
||||
eui.agent_settings.builtin_agents = dedupe_builtin_agents(agents);
|
||||
eui.agent_settings.next_builtin_agent_id =
|
||||
next_builtin_agent_id(&eui.agent_settings.builtin_agents);
|
||||
}
|
||||
|
|
@ -442,6 +443,25 @@ fn next_builtin_agent_id(agents: &[BuiltinAgentConfig]) -> u64 {
|
|||
.saturating_add(1)
|
||||
}
|
||||
|
||||
fn dedupe_builtin_agents(agents: Vec<BuiltinAgentConfig>) -> Vec<BuiltinAgentConfig> {
|
||||
let mut deduped: Vec<BuiltinAgentConfig> = Vec::new();
|
||||
for agent in agents {
|
||||
let is_duplicate = deduped.iter().any(|existing| {
|
||||
existing.matches_config(
|
||||
&agent.display_name,
|
||||
&agent.api_key,
|
||||
&agent.model,
|
||||
agent.kind,
|
||||
&agent.base_url,
|
||||
)
|
||||
});
|
||||
if !is_duplicate {
|
||||
deduped.push(agent);
|
||||
}
|
||||
}
|
||||
deduped
|
||||
}
|
||||
|
||||
fn next_acp_agent_id(agents: &[AcpAgentConfig]) -> u64 {
|
||||
agents
|
||||
.iter()
|
||||
|
|
@ -668,6 +688,44 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_builtin_agents_are_deduped_on_load() {
|
||||
let settings = r#"{
|
||||
"version": 1,
|
||||
"builtin_agents": [
|
||||
{
|
||||
"id": "builtin-1",
|
||||
"display_name": "MINIMAX",
|
||||
"kind": "openai-compat",
|
||||
"api_key": "sk-test",
|
||||
"model": "MiniMax-M2.7",
|
||||
"base_url": "https://api.minimaxi.com/v1",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": "builtin-2",
|
||||
"display_name": "MINIMAX",
|
||||
"kind": "openai-compat",
|
||||
"api_key": "sk-test",
|
||||
"model": "MiniMax-M2.7",
|
||||
"base_url": "https://api.minimaxi.com/v1",
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
}"#;
|
||||
let payload: SettingsPayload = serde_json::from_str(settings).unwrap();
|
||||
let mut dst = EditorState::new();
|
||||
|
||||
apply_payload(&mut dst, payload);
|
||||
|
||||
assert_eq!(dst.editor_ui.agent_settings.builtin_agents.len(), 1);
|
||||
assert_eq!(
|
||||
dst.editor_ui.agent_settings.builtin_agents[0].id,
|
||||
"builtin-1"
|
||||
);
|
||||
assert_eq!(dst.editor_ui.agent_settings.next_builtin_agent_id, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn acp_agents_round_trip_through_payload() {
|
||||
let mut src = EditorState::new();
|
||||
|
|
|
|||
Loading…
Reference in a new issue