mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-24 12:44:18 +08:00
fix(codex): use relative filename for model_catalog_json (#3614)
* fix(codex): use relative filename for model_catalog_json Instead of writing an absolute path (which breaks on WSL/symlink setups), write only the filename "cc-switch-model-catalog.json" to config.toml. Codex CLI resolves relative paths from the config directory, and both files always reside in the same directory (~/.codex/). This eliminates the need for UNC-to-Linux path translation and makes the config portable across Windows, WSL, and symlinked directories. Also simplifies ownership checks in resolve_cc_switch_catalog_path() and set_codex_model_catalog_json_field() by removing dead string-equality comparisons that never matched on WSL. Closes farion1231/cc-switch#3573 Related: farion1231/cc-switch#3569 * style(codex): fix rustfmt violations in model_catalog tests Wrap a >100-col UNC-path line and remove a trailing blank line that broke 'cargo fmt --check' in Backend CI. Style-only, no logic change. --------- Co-authored-by: steponeerror <huxaio0207@qq.com> Co-authored-by: Jason <farion1231@gmail.com>
This commit is contained in:
+114
-11
@@ -682,20 +682,18 @@ fn set_codex_model_catalog_json_field(
|
||||
let mut doc = config_text
|
||||
.parse::<DocumentMut>()
|
||||
.map_err(|e| AppError::Message(format!("Invalid Codex config.toml: {e}")))?;
|
||||
let generated_path = get_codex_model_catalog_path();
|
||||
|
||||
match catalog_path {
|
||||
Some(path) => {
|
||||
doc["model_catalog_json"] = toml_edit::value(path.to_string_lossy().as_ref());
|
||||
Some(_) => {
|
||||
doc["model_catalog_json"] = toml_edit::value(CC_SWITCH_CODEX_MODEL_CATALOG_FILENAME);
|
||||
}
|
||||
None => {
|
||||
let should_remove = doc
|
||||
.get("model_catalog_json")
|
||||
.and_then(|item| item.as_str())
|
||||
.map(|path| {
|
||||
path == generated_path.to_string_lossy().as_ref()
|
||||
|| Path::new(path).file_name().and_then(|name| name.to_str())
|
||||
== Some(CC_SWITCH_CODEX_MODEL_CATALOG_FILENAME)
|
||||
Path::new(path).file_name().and_then(|name| name.to_str())
|
||||
== Some(CC_SWITCH_CODEX_MODEL_CATALOG_FILENAME)
|
||||
})
|
||||
.unwrap_or(false);
|
||||
if should_remove {
|
||||
@@ -780,9 +778,8 @@ fn resolve_cc_switch_catalog_path(config_text: &str, generated_path: &Path) -> O
|
||||
.filter(|s| !s.is_empty())?;
|
||||
|
||||
let referenced_path = Path::new(catalog_path_str);
|
||||
let is_cc_switch_owned = catalog_path_str == generated_path.to_string_lossy().as_ref()
|
||||
|| referenced_path.file_name().and_then(|name| name.to_str())
|
||||
== Some(CC_SWITCH_CODEX_MODEL_CATALOG_FILENAME);
|
||||
let is_cc_switch_owned = referenced_path.file_name().and_then(|name| name.to_str())
|
||||
== Some(CC_SWITCH_CODEX_MODEL_CATALOG_FILENAME);
|
||||
if !is_cc_switch_owned {
|
||||
return None;
|
||||
}
|
||||
@@ -1791,7 +1788,7 @@ base_url = "https://production.api/v1"
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn model_catalog_json_field_operates_on_top_level() {
|
||||
fn model_catalog_json_field_writes_relative_filename() {
|
||||
let input = r#"model_provider = "any"
|
||||
|
||||
[model_providers.any]
|
||||
@@ -1805,7 +1802,7 @@ name = "any"
|
||||
parsed
|
||||
.get("model_catalog_json")
|
||||
.and_then(|value| value.as_str()),
|
||||
Some("/tmp/cc-switch-model-catalog.json")
|
||||
Some(CC_SWITCH_CODEX_MODEL_CATALOG_FILENAME)
|
||||
);
|
||||
assert!(
|
||||
parsed
|
||||
@@ -2026,4 +2023,110 @@ name = "any"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "windows")]
|
||||
fn set_catalog_json_field_writes_filename_ignoring_unc_path() {
|
||||
let input = r#"model_provider = "custom"
|
||||
model = "glm-5"
|
||||
"#;
|
||||
// Simulate a WSL UNC path as cc-switch would see it on Windows;
|
||||
// the function now writes just the relative filename.
|
||||
let unc_path =
|
||||
Path::new(r"\\wsl.localhost\Ubuntu\home\user\.codex\cc-switch-model-catalog.json");
|
||||
|
||||
let result = set_codex_model_catalog_json_field(input, Some(unc_path)).unwrap();
|
||||
let parsed: toml::Value = toml::from_str(&result).unwrap();
|
||||
|
||||
let written_path = parsed
|
||||
.get("model_catalog_json")
|
||||
.and_then(|v| v.as_str())
|
||||
.expect("model_catalog_json should be set");
|
||||
assert_eq!(
|
||||
written_path, CC_SWITCH_CODEX_MODEL_CATALOG_FILENAME,
|
||||
"should write only the relative filename, not the UNC path"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_catalog_json_field_writes_filename_for_any_path() {
|
||||
let input = r#"model_provider = "custom"
|
||||
model = "glm-5"
|
||||
"#;
|
||||
let regular_path = Path::new("/home/user/.codex/cc-switch-model-catalog.json");
|
||||
|
||||
let result = set_codex_model_catalog_json_field(input, Some(regular_path)).unwrap();
|
||||
let parsed: toml::Value = toml::from_str(&result).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
parsed.get("model_catalog_json").and_then(|v| v.as_str()),
|
||||
Some(CC_SWITCH_CODEX_MODEL_CATALOG_FILENAME),
|
||||
"should write only the relative filename, not the full path"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_catalog_json_none_removes_cc_switch_owned_by_filename() {
|
||||
// After the WSL fix, TOML may contain a Linux-style path.
|
||||
// The None arm must still remove it (file_name match catches any format).
|
||||
let input = r#"model_catalog_json = "/home/user/.codex/cc-switch-model-catalog.json"
|
||||
"#;
|
||||
let result = set_codex_model_catalog_json_field(input, None).unwrap();
|
||||
let parsed: toml::Value = toml::from_str(&result).unwrap();
|
||||
assert!(
|
||||
parsed.get("model_catalog_json").is_none(),
|
||||
"None arm should remove cc-switch-owned field regardless of path format"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_catalog_json_none_preserves_user_owned_catalog() {
|
||||
let input = r#"model_catalog_json = "/Users/me/.codex/my-custom-catalog.json"
|
||||
"#;
|
||||
let result = set_codex_model_catalog_json_field(input, None).unwrap();
|
||||
let parsed: toml::Value = toml::from_str(&result).unwrap();
|
||||
assert_eq!(
|
||||
parsed.get("model_catalog_json").and_then(|v| v.as_str()),
|
||||
Some("/Users/me/.codex/my-custom-catalog.json"),
|
||||
"None arm should NOT remove user-owned catalog"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_catalog_finds_relative_filename() {
|
||||
let config_text = r#"model_provider = "custom"
|
||||
model_catalog_json = "cc-switch-model-catalog.json"
|
||||
"#;
|
||||
let generated_path = PathBuf::from("/home/user/.codex/cc-switch-model-catalog.json");
|
||||
let result = resolve_cc_switch_catalog_path(config_text, &generated_path);
|
||||
assert_eq!(
|
||||
result,
|
||||
Some(generated_path),
|
||||
"relative filename should resolve to generated_path for file I/O"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_catalog_ignores_user_owned_relative() {
|
||||
let config_text = r#"model_catalog_json = "my-custom-catalog.json"
|
||||
"#;
|
||||
let generated_path = PathBuf::from("/home/user/.codex/cc-switch-model-catalog.json");
|
||||
let result = resolve_cc_switch_catalog_path(config_text, &generated_path);
|
||||
assert_eq!(
|
||||
result, None,
|
||||
"user-owned catalog should not be claimed by cc-switch"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_catalog_json_none_removes_relative_path() {
|
||||
let input = r#"model_catalog_json = "cc-switch-model-catalog.json"
|
||||
"#;
|
||||
let result = set_codex_model_catalog_json_field(input, None).unwrap();
|
||||
let parsed: toml::Value = toml::from_str(&result).unwrap();
|
||||
assert!(
|
||||
parsed.get("model_catalog_json").is_none(),
|
||||
"None arm should remove relative cc-switch-owned field"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user