fix(aliases): preserve payload rules for surviving channels

Scope payload cleanup to the selected OAuth protocol and retain rules still used by surviving OAuth aliases, API mappings, or real models. Preserve protocol-free shared rules while any matching mapping survives, and limit creation cleanup to its source protocol.

Validation: cargo test --locked tests::alias_delete (6 passed), including Codex/Claude collisions, wildcard selectors, same-protocol OAuth channels, and API mappings.
This commit is contained in:
lzt404 committed 2026-09-11 16:25:14 +08:00
1 parent e84e576d1d
commit a57c81e4e1
2 files changed
+170 -11

No files matched your search

+62
View File
@@ -63,3 +63,65 @@ fn plain_alias_deletion_preserves_real_models_with_the_same_name() {
);
assert!(remove_thinking_alias_from_yaml(&deleted, "plain").is_err());
}
#[test]
fn channel_deletion_preserves_other_protocols_and_shared_models() {
let original = "oauth-model-alias:\n codex: [{name: model-a, alias: shared}]\n claude: [{name: model-b, alias: shared}]\npayload:\n override:\n - models: [{name: shared, protocol: codex}]\n params: {reasoning.effort: high, service_tier: priority}\n - models: [{name: shared, protocol: claude}, {name: other, protocol: codex}]\n params: {output_config.effort: high}\n";
for speed in [false, true] {
let deleted = if speed {
remove_speed_alias_from_yaml_for_channel(original, "shared", Some("codex"))
} else {
remove_thinking_alias_from_yaml_for_channel(original, "shared", Some("codex"))
}
.unwrap();
let entries = thinking_aliases_from_yaml(&deleted).unwrap();
assert_eq!(entries.len(), 1);
assert_eq!(entries[0].oauth_channel.as_deref(), Some("claude"));
assert_eq!(entries[0].effort.as_deref(), Some("high"));
assert_eq!(
json(&deleted)["payload"]["override"],
serde_json::json!([json(original)["payload"]["override"][1]])
);
}
}
#[test]
fn channel_deletion_preserves_wildcard_rules_for_surviving_aliases() {
for protocol in ["", ", protocol: ''"] {
let original = format!("oauth-model-alias:\n codex: [{{name: model-a, alias: shared}}]\n claude: [{{name: model-b, alias: shared}}]\npayload:\n override:\n - models: [{{name: shared{protocol}}}]\n params: {{reasoning.effort: high, output_config.effort: high, service_tier: priority}}\n");
for speed in [false, true] {
let deleted = if speed {
remove_speed_alias_from_yaml_for_channel(&original, "shared", Some("codex"))
} else {
remove_thinking_alias_from_yaml_for_channel(&original, "shared", Some("codex"))
}
.unwrap();
assert_eq!(json(&deleted)["payload"], json(&original)["payload"]);
let deleted =
remove_thinking_alias_from_yaml_for_channel(&deleted, "shared", Some("claude"))
.unwrap();
assert!(json(&deleted).get("payload").is_none());
}
}
}
#[test]
fn channel_deletion_preserves_rules_used_by_same_protocol_mappings() {
for surviving in [
" xai: [{name: model-b, alias: shared}]\n",
"codex-api-key:\n - models: [{name: model-b, alias: shared}]\n",
"codex-api-key:\n - models: [{name: shared}]\n",
] {
let original = format!("oauth-model-alias:\n codex: [{{name: model-a, alias: shared}}]\n{surviving}payload:\n override:\n - models: [{{name: shared, protocol: codex}}]\n params: {{reasoning.effort: high, service_tier: priority}}\n");
for speed in [false, true] {
let deleted = if speed {
remove_speed_alias_from_yaml_for_channel(&original, "shared", Some("codex"))
} else {
remove_thinking_alias_from_yaml_for_channel(&original, "shared", Some("codex"))
}
.unwrap();
assert_eq!(json(&deleted)["payload"], json(&original)["payload"]);
assert!(json(&deleted)["oauth-model-alias"].get("codex").is_none());
}
}
}