adding logging, cleaning up configs

This commit is contained in:
2026-08-12 06:38:02 -05:00
parent 84945cd9be
commit 1ad2ab4010
24 changed files with 2504 additions and 208 deletions
+186 -12
View File
@@ -11,7 +11,8 @@ use crate::server::cloud_objects::update_manager::UpdateManager;
use crate::server::server_api::ServerApiProvider;
use crate::server::sync_queue::SyncQueue;
use crate::settings::{
AcpAgentSettings, AcpConfigOptionSettings, AcpConfigValueSettings, OpenAIModelConfig,
AcpAgentSettings, AcpConfigOptionSettings, AcpConfigValueSettings, AcpProviderConfig,
OpenAIModelConfig,
};
use crate::test_util::settings::initialize_settings_for_tests;
use crate::workspaces::team_tester::TeamTesterStatus;
@@ -210,6 +211,7 @@ fn empty_preferences() -> LLMPreferences {
custom_model_routers: Vec::new(),
openai_provider_routing: HashMap::new(),
fetched_openai_models: Vec::new(),
chatgpt_subscription_models_refresh_in_flight: false,
acp_selections: HashMap::new(),
}
}
@@ -299,6 +301,7 @@ fn acp_models_are_injected_only_while_acp_is_enabled() {
custom_model_routers: Vec::new(),
openai_provider_routing: HashMap::new(),
fetched_openai_models: Vec::new(),
chatgpt_subscription_models_refresh_in_flight: false,
acp_selections: HashMap::new(),
};
app.read(|ctx| preferences.inject_acp_models(ctx));
@@ -452,7 +455,7 @@ fn acp_models_expand_reasoning_levels_for_only_the_configured_agent() {
.iter()
.map(|model| model.display_name.as_str())
.collect::<HashSet<_>>(),
HashSet::from(["GPT Test (High)", "GPT Test (Xhigh)"])
HashSet::from(["GPT Test (High) · OpenCode", "GPT Test (Xhigh) · OpenCode"])
);
assert!(models.iter().all(|model| {
model.provider == LLMProvider::Acp && !model.display_name.contains("Read-only")
@@ -464,6 +467,82 @@ fn acp_models_expand_reasoning_levels_for_only_the_configured_agent() {
});
}
#[test]
fn acp_models_are_scoped_to_each_configured_provider() {
App::test((), |mut app| async move {
initialize_settings_for_tests(&mut app);
let config_options = vec![acp_select_option(
"model",
"model",
"gpt-test",
&[("gpt-test", "GPT Test")],
)];
AISettings::handle(&app).update(&mut app, |settings, ctx| {
settings
.acp_enabled
.set_value(true, ctx)
.expect("ACP setting should update");
settings
.bedrock_enabled
.set_value(false, ctx)
.expect("Bedrock setting should update");
settings
.acp_providers
.set_value(
vec![
AcpProviderConfig {
id: "work".to_owned(),
enabled: true,
name: "Codex Work".to_owned(),
agent_id: "codex".to_owned(),
command: String::new(),
args: Vec::new(),
config_options: config_options.clone(),
},
AcpProviderConfig {
id: "personal".to_owned(),
enabled: true,
name: "Codex Personal".to_owned(),
agent_id: "codex".to_owned(),
command: String::new(),
args: Vec::new(),
config_options,
},
],
ctx,
)
.expect("ACP providers should update");
});
let mut preferences = empty_preferences();
app.read(|ctx| preferences.inject_acp_models(ctx));
let models = preferences
.models_by_feature
.agent_mode
.choices
.iter()
.filter(|model| model.provider == LLMProvider::Acp)
.collect::<Vec<_>>();
assert_eq!(models.len(), 2);
assert_eq!(
models
.iter()
.map(|model| model.display_name.as_str())
.collect::<HashSet<_>>(),
HashSet::from(["GPT Test · Codex Work", "GPT Test · Codex Personal"])
);
assert_eq!(
preferences
.acp_selections
.values()
.map(|selection| selection.provider_id.as_str())
.collect::<HashSet<_>>(),
HashSet::from(["work", "personal"])
);
});
}
#[test]
fn acp_bedrock_models_are_hidden_while_bedrock_is_disabled() {
App::test((), |mut app| async move {
@@ -510,7 +589,7 @@ fn acp_bedrock_models_are_hidden_while_bedrock_is_disabled() {
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"
"GPT Test · OpenCode"
);
AISettings::handle(&app).update(&mut app, |settings, ctx| {
@@ -578,9 +657,6 @@ fn chatgpt_reasoning_modes_route_with_catalog_context_metadata() {
let gpt_56_sol = configured_model("gpt-5.6-sol");
assert_eq!(gpt_56_sol.context_size, 272_000);
assert_eq!(gpt_56_sol.max_input_tokens, Some(258_400));
let codex_spark = configured_model("gpt-5.3-codex-spark");
assert_eq!(codex_spark.context_size, 128_000);
assert_eq!(codex_spark.max_input_tokens, Some(121_600));
let uncached_model = configured_model("gpt-5.4-pro");
assert_eq!(uncached_model.context_size, 200_000);
assert_eq!(uncached_model.max_input_tokens, None);
@@ -648,12 +724,12 @@ fn chatgpt_reasoning_modes_route_with_catalog_context_metadata() {
assert_eq!(ultra_routing.reasoning_effort.as_deref(), Some("ultra"));
assert_eq!(ultra_routing.max_input_tokens, Some(258_400));
let spark_id = "gpt-5.3-codex-spark";
assert_fixed_context(spark_id, 121_600);
let spark_routing = preferences
.openai_client_config_for_model(spark_id)
.expect("GPT-5.3 Codex Spark should have a routing entry");
assert_eq!(spark_routing.max_input_tokens, Some(121_600));
let uncached_id = "gpt-5.4-pro";
assert_fixed_context(uncached_id, 200_000);
let uncached_routing = preferences
.openai_client_config_for_model(uncached_id)
.expect("GPT-5.4 Pro should have a routing entry");
assert_eq!(uncached_routing.max_input_tokens, Some(200_000));
});
}
@@ -670,3 +746,101 @@ fn provider_discovery_enables_rig_for_new_models_and_keeps_manual_models() {
assert_eq!(merged[0].supports_system_messages, Some(false));
assert_eq!(merged[1].model_id, "manual-model");
}
#[test]
fn codex_release_json_yields_client_version() {
let release = serde_json::json!({
"tag_name": "rust-v0.147.0",
"name": "0.147.0"
});
assert_eq!(
codex_client_version_from_release_json(&release).as_deref(),
Some("0.147.0")
);
}
#[test]
fn chatgpt_codex_models_parse_visible_catalog_entries() {
let body = serde_json::json!({
"models": [
{
"slug": "gpt-5.6-sol",
"display_name": "GPT-5.6-Sol",
"visibility": "list",
"context_window": 272000,
"max_context_window": 272000,
"effective_context_window_percent": 95,
"input_modalities": ["text", "image"],
"supported_reasoning_levels": [
{"effort": "low", "description": "Fast"},
{"effort": "xhigh", "description": "Deep"},
{"effort": "ultra", "description": "Delegated"}
]
},
{
"slug": "hidden",
"display_name": "Hidden",
"visibility": "hide",
"context_window": 128000,
"input_modalities": ["text"],
"supported_reasoning_levels": []
},
{
"slug": "gpt-text-only",
"display_name": "GPT Text Only",
"visibility": "list",
"max_context_window": 128000,
"effective_context_window_percent": 90,
"input_modalities": ["text"],
"supported_reasoning_levels": [{"effort": "medium"}]
}
]
});
let models = chatgpt_models_from_codex_response(&body);
assert_eq!(models.len(), 2);
assert_eq!(models[0].model_id, "gpt-5.6-sol");
assert_eq!(models[0].display_name, "GPT-5.6-Sol");
assert!(models[0].vision_supported);
assert_eq!(models[0].context_size, 272_000);
assert_eq!(models[0].max_input_tokens, Some(258_400));
assert_eq!(models[0].reasoning_efforts, ["low", "xhigh", "ultra"]);
assert!(models[0].use_rig);
assert_eq!(models[0].provider.as_deref(), Some("openai"));
assert_eq!(models[0].supports_system_messages, Some(true));
assert_eq!(models[1].model_id, "gpt-text-only");
assert!(!models[1].vision_supported);
assert_eq!(models[1].context_size, 128_000);
assert_eq!(models[1].max_input_tokens, Some(115_200));
}
#[test]
fn chatgpt_catalog_merge_drops_stale_models_but_preserves_overrides() {
let mut existing = openai_model("gpt-5.6-sol");
existing.enabled = false;
existing.use_rig = false;
existing.capability_overrides.insert(
"vision".to_string(),
crate::settings::ModelCapabilityOverride::Unsupported,
);
let stale = openai_model("stale-model");
let mut discovered = openai_model("gpt-5.6-sol");
discovered.display_name = "GPT-5.6-Sol".to_string();
discovered.vision_supported = true;
discovered.use_rig = true;
let merged = merge_discovered_chatgpt_subscription_models(&[existing, stale], vec![discovered]);
assert_eq!(merged.len(), 1);
assert_eq!(merged[0].model_id, "gpt-5.6-sol");
assert!(!merged[0].enabled);
assert!(!merged[0].use_rig);
assert_eq!(
merged[0].capability_override("vision"),
crate::settings::ModelCapabilityOverride::Unsupported
);
}