ACP Wrap up
This commit is contained in:
@@ -155,6 +155,62 @@ fn openai_model(model_id: &str) -> OpenAIModelConfig {
|
||||
}
|
||||
}
|
||||
|
||||
fn acp_select_option(
|
||||
id: &str,
|
||||
category: &str,
|
||||
current_value: &str,
|
||||
values: &[(&str, &str)],
|
||||
) -> AcpConfigOptionSettings {
|
||||
AcpConfigOptionSettings {
|
||||
id: id.to_owned(),
|
||||
name: id.to_owned(),
|
||||
description: None,
|
||||
category: Some(category.to_owned()),
|
||||
kind: "select".to_owned(),
|
||||
current_value: serde_json::json!(current_value),
|
||||
options: values
|
||||
.iter()
|
||||
.map(|(value, name)| AcpConfigValueSettings {
|
||||
value: serde_json::json!(value),
|
||||
name: (*name).to_owned(),
|
||||
description: None,
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn acp_agent(
|
||||
id: &str,
|
||||
name: &str,
|
||||
config_options: Vec<AcpConfigOptionSettings>,
|
||||
) -> AcpAgentSettings {
|
||||
AcpAgentSettings {
|
||||
id: id.to_owned(),
|
||||
name: name.to_owned(),
|
||||
version: None,
|
||||
description: None,
|
||||
icon_url: None,
|
||||
capabilities: Vec::new(),
|
||||
config_options,
|
||||
discovery_timestamp: None,
|
||||
discovery_source: None,
|
||||
discovery_error: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn empty_preferences() -> LLMPreferences {
|
||||
LLMPreferences {
|
||||
models_by_feature: ModelsByFeature::default(),
|
||||
last_update: None,
|
||||
base_llm_for_terminal_view: HashMap::new(),
|
||||
custom_llms: Vec::new(),
|
||||
custom_model_routers: Vec::new(),
|
||||
openai_provider_routing: HashMap::new(),
|
||||
fetched_openai_models: Vec::new(),
|
||||
acp_selections: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn provider_discovery_preserves_local_model_overrides() {
|
||||
let mut existing = openai_model("codex-gpt-5.6-sol-xhigh");
|
||||
@@ -275,6 +331,231 @@ fn acp_models_are_injected_only_while_acp_is_enabled() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn acp_is_selectable_before_protocol_model_discovery_completes() {
|
||||
App::test((), |mut app| async move {
|
||||
initialize_settings_for_tests(&mut app);
|
||||
AISettings::handle(&app).update(&mut app, |settings, ctx| {
|
||||
settings
|
||||
.acp_enabled
|
||||
.set_value(true, ctx)
|
||||
.expect("ACP setting should update");
|
||||
settings
|
||||
.acp_agent_id
|
||||
.set_value("opencode".to_owned(), ctx)
|
||||
.expect("ACP agent should update");
|
||||
settings
|
||||
.bedrock_enabled
|
||||
.set_value(false, ctx)
|
||||
.expect("Bedrock setting should update");
|
||||
settings
|
||||
.acp_agents
|
||||
.set_value(Vec::new(), ctx)
|
||||
.expect("ACP discovery cache should update");
|
||||
});
|
||||
|
||||
let mut preferences = empty_preferences();
|
||||
app.read(|ctx| {
|
||||
preferences.inject_bedrock_models(ctx);
|
||||
preferences.inject_acp_models(ctx);
|
||||
});
|
||||
|
||||
let models = &preferences.models_by_feature.agent_mode.choices;
|
||||
assert_eq!(models.len(), 1);
|
||||
assert_eq!(models[0].display_name, "OpenCode");
|
||||
assert_eq!(models[0].provider, LLMProvider::Acp);
|
||||
assert_eq!(
|
||||
preferences
|
||||
.acp_selections
|
||||
.get(&models[0].id)
|
||||
.map(|selection| selection.agent_id.as_str()),
|
||||
Some("opencode")
|
||||
);
|
||||
assert!(preferences.has_any_provider_models());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn acp_models_expand_reasoning_levels_for_only_the_configured_agent() {
|
||||
App::test((), |mut app| async move {
|
||||
initialize_settings_for_tests(&mut app);
|
||||
AISettings::handle(&app).update(&mut app, |settings, ctx| {
|
||||
settings
|
||||
.acp_enabled
|
||||
.set_value(true, ctx)
|
||||
.expect("ACP setting should update");
|
||||
settings
|
||||
.acp_agent_id
|
||||
.set_value("opencode".to_owned(), ctx)
|
||||
.expect("ACP agent should update");
|
||||
settings
|
||||
.bedrock_enabled
|
||||
.set_value(false, ctx)
|
||||
.expect("Bedrock setting should update");
|
||||
settings
|
||||
.acp_agents
|
||||
.set_value(
|
||||
vec![
|
||||
acp_agent(
|
||||
"codex",
|
||||
"Codex",
|
||||
vec![acp_select_option(
|
||||
"model",
|
||||
"model",
|
||||
"stale-model",
|
||||
&[("stale-model", "Stale Model")],
|
||||
)],
|
||||
),
|
||||
acp_agent(
|
||||
"opencode",
|
||||
"OpenCode",
|
||||
vec![
|
||||
acp_select_option(
|
||||
"model",
|
||||
"model",
|
||||
"gpt-test",
|
||||
&[("gpt-test", "GPT Test")],
|
||||
),
|
||||
acp_select_option(
|
||||
"mode",
|
||||
"mode",
|
||||
"read-only",
|
||||
&[("read-only", "Read-only")],
|
||||
),
|
||||
acp_select_option(
|
||||
"thought_level",
|
||||
"thought_level",
|
||||
"xhigh",
|
||||
&[("high", "High"), ("xhigh", "Xhigh")],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
ctx,
|
||||
)
|
||||
.expect("ACP agents should update");
|
||||
});
|
||||
|
||||
let mut preferences = empty_preferences();
|
||||
app.read(|ctx| {
|
||||
preferences.inject_bedrock_models(ctx);
|
||||
preferences.inject_acp_models(ctx);
|
||||
});
|
||||
|
||||
let models = &preferences.models_by_feature.agent_mode.choices;
|
||||
assert_eq!(models.len(), 2);
|
||||
assert_eq!(
|
||||
models
|
||||
.iter()
|
||||
.map(|model| model.display_name.as_str())
|
||||
.collect::<HashSet<_>>(),
|
||||
HashSet::from(["GPT Test (High)", "GPT Test (Xhigh)"])
|
||||
);
|
||||
assert!(models.iter().all(|model| {
|
||||
model.provider == LLMProvider::Acp && !model.display_name.contains("Read-only")
|
||||
}));
|
||||
assert!(preferences.acp_selections.values().all(|selection| {
|
||||
selection.agent_id == "opencode"
|
||||
&& selection.config_values.get("mode") == Some(&serde_json::json!("read-only"))
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn acp_bedrock_models_are_hidden_while_bedrock_is_disabled() {
|
||||
App::test((), |mut app| async move {
|
||||
initialize_settings_for_tests(&mut app);
|
||||
AISettings::handle(&app).update(&mut app, |settings, ctx| {
|
||||
settings
|
||||
.acp_enabled
|
||||
.set_value(true, ctx)
|
||||
.expect("ACP setting should update");
|
||||
settings
|
||||
.acp_agent_id
|
||||
.set_value("opencode".to_owned(), ctx)
|
||||
.expect("ACP agent should update");
|
||||
settings
|
||||
.bedrock_enabled
|
||||
.set_value(false, ctx)
|
||||
.expect("Bedrock setting should update");
|
||||
settings
|
||||
.acp_agents
|
||||
.set_value(
|
||||
vec![acp_agent(
|
||||
"opencode",
|
||||
"OpenCode",
|
||||
vec![acp_select_option(
|
||||
"model",
|
||||
"model",
|
||||
"openai/gpt-test",
|
||||
&[
|
||||
("amazon-bedrock/claude-test", "Bedrock Claude"),
|
||||
("openai/gpt-test", "GPT Test"),
|
||||
],
|
||||
)],
|
||||
)],
|
||||
ctx,
|
||||
)
|
||||
.expect("ACP agents should update");
|
||||
});
|
||||
|
||||
let mut preferences = empty_preferences();
|
||||
app.read(|ctx| {
|
||||
preferences.inject_bedrock_models(ctx);
|
||||
preferences.inject_acp_models(ctx);
|
||||
});
|
||||
assert_eq!(preferences.models_by_feature.agent_mode.choices.len(), 1);
|
||||
assert_eq!(
|
||||
preferences.models_by_feature.agent_mode.choices[0].display_name,
|
||||
"GPT Test"
|
||||
);
|
||||
|
||||
AISettings::handle(&app).update(&mut app, |settings, ctx| {
|
||||
settings
|
||||
.bedrock_enabled
|
||||
.set_value(true, ctx)
|
||||
.expect("Bedrock setting should update");
|
||||
});
|
||||
app.read(|ctx| preferences.inject_acp_models(ctx));
|
||||
assert_eq!(preferences.models_by_feature.agent_mode.choices.len(), 2);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn disabled_providers_do_not_leave_models_in_the_runtime_inventory() {
|
||||
App::test((), |mut app| async move {
|
||||
initialize_settings_for_tests(&mut app);
|
||||
AISettings::handle(&app).update(&mut app, |settings, ctx| {
|
||||
settings
|
||||
.bedrock_enabled
|
||||
.set_value(false, ctx)
|
||||
.expect("Bedrock setting should update");
|
||||
settings
|
||||
.openai_enabled
|
||||
.set_value(false, ctx)
|
||||
.expect("OpenAI setting should update");
|
||||
settings
|
||||
.acp_enabled
|
||||
.set_value(false, ctx)
|
||||
.expect("ACP setting should update");
|
||||
});
|
||||
|
||||
let mut preferences = empty_preferences();
|
||||
app.read(|ctx| {
|
||||
preferences.inject_bedrock_models(ctx);
|
||||
preferences.inject_openai_models(ctx);
|
||||
});
|
||||
|
||||
assert!(preferences.models_by_feature.agent_mode.choices.is_empty());
|
||||
assert!(preferences.models_by_feature.coding.choices.is_empty());
|
||||
assert!(preferences
|
||||
.models_by_feature
|
||||
.cli_agent
|
||||
.as_ref()
|
||||
.is_none_or(|models| models.choices.is_empty()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn provider_discovery_enables_rig_for_new_models_and_keeps_manual_models() {
|
||||
let manual = openai_model("manual-model");
|
||||
|
||||
Reference in New Issue
Block a user