修复客户端 Rust 格式检查失败

格式化客户端扩展实现以通过 cargo fmt 检查

同步整理客户端扩展模块在 main.rs 中的声明与导入顺序
This commit is contained in:
2026-09-01 09:09:49 +00:00
parent 7b87ed052b
commit fed177aea1
2 changed files with 181 additions and 185 deletions
@@ -1083,55 +1083,55 @@ pub(crate) fn prepare_enabled_client_skill_root(
pub(crate) fn prepare_enabled_client_mcp_servers() -> Result<Vec<ClientMcpRuntimeServer>, String> {
update_client_extension_index(|root, index| {
let mut servers = Vec::new();
let mut index_changed = false;
let mut servers = Vec::new();
let mut index_changed = false;
for item_index in 0..index.items.len() {
if index.items[item_index].extension_type != "mcp" || !index.items[item_index].enabled {
continue;
}
let source = index
.sources
.iter()
.find(|source| source.id == index.items[item_index].source_id)
.cloned();
let result = (|| {
if index.items[item_index].name == RESERVED_MCP_SERVER_NAME {
return Err("MCP Server 名称 agc_tools 为客户端内置保留名称".to_string());
for item_index in 0..index.items.len() {
if index.items[item_index].extension_type != "mcp" || !index.items[item_index].enabled {
continue;
}
let source = source.ok_or_else(|| "MCP Server 缺少导入来源".to_string())?;
let config = index.items[item_index]
.mcp_config
.as_ref()
.ok_or_else(|| "MCP Server 缺少原生配置".to_string())?;
let source_file = root
.join(&source.storage_path)
.join(&index.items[item_index].source_relative_path);
let source_directory = source_file
.parent()
.ok_or_else(|| "MCP Server 来源路径无效".to_string())?;
normalize_mcp_runtime_config(config, source_directory)
})();
match result {
Ok(config) => {
if index.items[item_index].last_error.take().is_some() {
index_changed = true;
let source = index
.sources
.iter()
.find(|source| source.id == index.items[item_index].source_id)
.cloned();
let result = (|| {
if index.items[item_index].name == RESERVED_MCP_SERVER_NAME {
return Err("MCP Server 名称 agc_tools 为客户端内置保留名称".to_string());
}
servers.push(ClientMcpRuntimeServer {
extension_id: index.items[item_index].id.clone(),
name: index.items[item_index].name.clone(),
config,
});
}
Err(error) => {
if index.items[item_index].last_error.as_deref() != Some(error.as_str()) {
index.items[item_index].last_error = Some(error);
index_changed = true;
let source = source.ok_or_else(|| "MCP Server 缺少导入来源".to_string())?;
let config = index.items[item_index]
.mcp_config
.as_ref()
.ok_or_else(|| "MCP Server 缺少原生配置".to_string())?;
let source_file = root
.join(&source.storage_path)
.join(&index.items[item_index].source_relative_path);
let source_directory = source_file
.parent()
.ok_or_else(|| "MCP Server 来源路径无效".to_string())?;
normalize_mcp_runtime_config(config, source_directory)
})();
match result {
Ok(config) => {
if index.items[item_index].last_error.take().is_some() {
index_changed = true;
}
servers.push(ClientMcpRuntimeServer {
extension_id: index.items[item_index].id.clone(),
name: index.items[item_index].name.clone(),
config,
});
}
Err(error) => {
if index.items[item_index].last_error.as_deref() != Some(error.as_str()) {
index.items[item_index].last_error = Some(error);
index_changed = true;
}
}
}
}
}
Ok((servers, index_changed))
Ok((servers, index_changed))
})
}
@@ -1341,76 +1341,79 @@ fn import_client_extension_at(
fingerprint: source_fingerprint,
};
update_client_extension_index_at(&root, |_, index| {
let mut used_names: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
for item in &index.items {
let mut used_names: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
for item in &index.items {
used_names
.entry(item.extension_type.clone())
.or_default()
.insert(item.name.clone());
}
used_names
.entry(item.extension_type.clone())
.entry("mcp".to_string())
.or_default()
.insert(item.name.clone());
}
used_names
.entry("mcp".to_string())
.or_default()
.insert(RESERVED_MCP_SERVER_NAME.to_string());
let mut imported = Vec::new();
let mut renamed = false;
let mut duplicate = false;
for candidate in candidates {
let extension_type = candidate.extension_type;
let enabled = extension_type != "unknown";
let duplicate_name = index
.items
.iter()
.find(|item| {
item.extension_type == extension_type
&& item.fingerprint == candidate.fingerprint
})
.map(|item| item.name.clone());
duplicate |= duplicate_name.is_some();
let names = used_names.entry(extension_type.clone()).or_default();
let requested_name = duplicate_name
.as_deref()
.unwrap_or(&candidate.original_name);
let (name, was_renamed) = if extension_type == "skill" {
allocate_skill_name(requested_name, names)
} else {
allocate_name(requested_name, names)
};
renamed |= was_renamed;
let stored = StoredExtensionItem {
id: new_id("extension"),
source_id: source_id.clone(),
extension_type,
name,
original_name: candidate.original_name,
source_relative_path: candidate.source_relative_path,
enabled,
fingerprint: candidate.fingerprint,
last_error: None,
mcp_config: candidate.mcp_config,
};
index.items.push(stored);
imported.push(stored_item_view(
&ClientExtensionIndex {
schema_version: index.schema_version.clone(),
sources: index
.sources
.iter()
.cloned()
.chain(std::iter::once(source_record.clone()))
.collect(),
items: index.items.clone(),
.insert(RESERVED_MCP_SERVER_NAME.to_string());
let mut imported = Vec::new();
let mut renamed = false;
let mut duplicate = false;
for candidate in candidates {
let extension_type = candidate.extension_type;
let enabled = extension_type != "unknown";
let duplicate_name = index
.items
.iter()
.find(|item| {
item.extension_type == extension_type
&& item.fingerprint == candidate.fingerprint
})
.map(|item| item.name.clone());
duplicate |= duplicate_name.is_some();
let names = used_names.entry(extension_type.clone()).or_default();
let requested_name = duplicate_name
.as_deref()
.unwrap_or(&candidate.original_name);
let (name, was_renamed) = if extension_type == "skill" {
allocate_skill_name(requested_name, names)
} else {
allocate_name(requested_name, names)
};
renamed |= was_renamed;
let stored = StoredExtensionItem {
id: new_id("extension"),
source_id: source_id.clone(),
extension_type,
name,
original_name: candidate.original_name,
source_relative_path: candidate.source_relative_path,
enabled,
fingerprint: candidate.fingerprint,
last_error: None,
mcp_config: candidate.mcp_config,
};
index.items.push(stored);
imported.push(stored_item_view(
&ClientExtensionIndex {
schema_version: index.schema_version.clone(),
sources: index
.sources
.iter()
.cloned()
.chain(std::iter::once(source_record.clone()))
.collect(),
items: index.items.clone(),
},
index.items.last().expect("stored extension item"),
));
}
index.sources.push(source_record);
Ok((
ClientExtensionImportResult {
imported,
source_name: source_display_name,
renamed,
duplicate,
},
index.items.last().expect("stored extension item"),
));
}
index.sources.push(source_record);
Ok((ClientExtensionImportResult {
imported,
source_name: source_display_name,
renamed,
duplicate,
}, true))
true,
))
})
})();
let _ = fs::remove_dir_all(&staging);
@@ -1433,7 +1436,10 @@ fn set_client_extension_enabled_at(
) -> Result<ClientExtensionItem, String> {
invalidate_client_mcp_connection(id.trim())?;
update_client_extension_index_at(root, |_, index| {
let item = index.items.iter_mut().find(|item| item.id == id.trim())
let item = index
.items
.iter_mut()
.find(|item| item.id == id.trim())
.ok_or_else(|| "未找到客户端扩展".to_string())?;
if item.extension_type == "unknown" && enabled {
return Err("未识别扩展不能启用".to_string());
@@ -1466,40 +1472,43 @@ fn rename_client_extension_at(
) -> Result<ClientExtensionItem, String> {
invalidate_client_mcp_connection(id.trim())?;
update_client_extension_index_at(root, |_, index| {
let item_index = index.items.iter().position(|item| item.id == id.trim())
.ok_or_else(|| "未找到客户端扩展".to_string())?;
let extension_type = index.items[item_index].extension_type.clone();
let conflict = (extension_type == "mcp" && normalized == RESERVED_MCP_SERVER_NAME)
|| index.items.iter().enumerate().any(|(index, item)| {
index != item_index
&& item.extension_type == extension_type
&& if extension_type == "skill" {
item.name.eq_ignore_ascii_case(&normalized)
} else {
item.name == normalized
}
});
let final_name = if conflict {
let mut names = index
let item_index = index
.items
.iter()
.filter(|item| item.extension_type == extension_type)
.map(|item| item.name.clone())
.collect::<BTreeSet<_>>();
if extension_type == "mcp" {
names.insert(RESERVED_MCP_SERVER_NAME.to_string());
}
if extension_type == "skill" {
allocate_skill_name(&normalized, &mut names).0
.position(|item| item.id == id.trim())
.ok_or_else(|| "未找到客户端扩展".to_string())?;
let extension_type = index.items[item_index].extension_type.clone();
let conflict = (extension_type == "mcp" && normalized == RESERVED_MCP_SERVER_NAME)
|| index.items.iter().enumerate().any(|(index, item)| {
index != item_index
&& item.extension_type == extension_type
&& if extension_type == "skill" {
item.name.eq_ignore_ascii_case(&normalized)
} else {
item.name == normalized
}
});
let final_name = if conflict {
let mut names = index
.items
.iter()
.filter(|item| item.extension_type == extension_type)
.map(|item| item.name.clone())
.collect::<BTreeSet<_>>();
if extension_type == "mcp" {
names.insert(RESERVED_MCP_SERVER_NAME.to_string());
}
if extension_type == "skill" {
allocate_skill_name(&normalized, &mut names).0
} else {
allocate_name(&normalized, &mut names).0
}
} else {
allocate_name(&normalized, &mut names).0
}
} else {
normalized.to_string()
};
index.items[item_index].name = final_name;
let view_item = index.items[item_index].clone();
Ok((stored_item_view(index, &view_item), true))
normalized.to_string()
};
index.items[item_index].name = final_name;
let view_item = index.items[item_index].clone();
Ok((stored_item_view(index, &view_item), true))
})
}
@@ -1512,7 +1521,10 @@ pub(crate) fn remove_client_extension(id: String) -> Result<(), String> {
fn remove_client_extension_at(root: &Path, id: &str) -> Result<(), String> {
invalidate_client_mcp_connection(id.trim())?;
update_client_extension_index_at(root, |_, index| {
let item_index = index.items.iter().position(|item| item.id == id.trim())
let item_index = index
.items
.iter()
.position(|item| item.id == id.trim())
.ok_or_else(|| "未找到客户端扩展".to_string())?;
index.items.remove(item_index);
Ok(((), true))
@@ -1616,7 +1628,10 @@ mod tests {
})
.collect::<BTreeSet<_>>();
if case.id == "unknown" {
assert!(candidates.is_empty(), "unknown fixture must have no candidates");
assert!(
candidates.is_empty(),
"unknown fixture must have no candidates"
);
assert_eq!(expected, BTreeSet::from([("unknown", "unknown.bin")]));
} else {
assert_eq!(actual, expected, "fixture case {}", case.id);
@@ -1690,14 +1705,15 @@ mod tests {
let disabled = set_client_extension_enabled_at(&root, &first_id, false)
.expect("disable imported skill");
assert_eq!(disabled.status, "disabled");
let enabled = set_client_extension_enabled_at(&root, &first_id, true)
.expect("enable imported skill");
let enabled =
set_client_extension_enabled_at(&root, &first_id, true).expect("enable imported skill");
assert_eq!(enabled.status, "enabled");
remove_client_extension_at(&root, &second.imported[0].id)
.expect("remove duplicate skill");
remove_client_extension_at(&root, &second.imported[0].id).expect("remove duplicate skill");
let remaining = list_client_extensions_at(&root).expect("list remaining extensions");
assert!(remaining.iter().any(|item| item.id == first_id));
assert!(!remaining.iter().any(|item| item.id == second.imported[0].id));
assert!(!remaining
.iter()
.any(|item| item.id == second.imported[0].id));
}
#[test]
@@ -2049,46 +2065,23 @@ mod tests {
})
.expect("insert MCP extension");
claim_client_mcp_connection_at(
&root,
[extension_id.to_string()],
"connection-old",
)
.expect("claim old MCP connection");
record_client_mcp_startup_status_at(
&root,
extension_id,
"connection-old",
"failed",
)
.expect("record old failure");
claim_client_mcp_connection_at(&root, [extension_id.to_string()], "connection-old")
.expect("claim old MCP connection");
record_client_mcp_startup_status_at(&root, extension_id, "connection-old", "failed")
.expect("record old failure");
claim_client_mcp_connection_at(
&root,
[extension_id.to_string()],
"connection-new",
)
.expect("claim new MCP connection");
record_client_mcp_startup_status_at(
&root,
extension_id,
"connection-old",
"ready",
)
.expect("ignore stale ready status");
claim_client_mcp_connection_at(&root, [extension_id.to_string()], "connection-new")
.expect("claim new MCP connection");
record_client_mcp_startup_status_at(&root, extension_id, "connection-old", "ready")
.expect("ignore stale ready status");
let index = read_index(&root).expect("read status after stale callback");
assert_eq!(
index.items[0].last_error.as_deref(),
Some("MCP Server 启动失败")
);
record_client_mcp_startup_status_at(
&root,
extension_id,
"connection-new",
"ready",
)
.expect("record current ready status");
record_client_mcp_startup_status_at(&root, extension_id, "connection-new", "ready")
.expect("record current ready status");
let index = read_index(&root).expect("read status after current callback");
assert_eq!(index.items[0].last_error, None);
release_client_mcp_connection([extension_id.to_string()], "connection-new")
@@ -2140,7 +2133,10 @@ mod tests {
})
});
left.join().expect("join left update").expect("left update");
right.join().expect("join right update").expect("right update");
right
.join()
.expect("join right update")
.expect("right update");
let index = read_index(&root).expect("read serialized index");
let ids = index
@@ -50,12 +50,12 @@ mod agent_native_tools;
mod assets;
mod browser;
mod cli;
mod client_extensions;
mod collaboration;
mod command_exec;
mod command_output;
mod command_sandbox;
mod command_sandbox_trampoline;
mod client_extensions;
mod commands;
mod config;
mod context_compaction;
@@ -89,11 +89,11 @@ use agent_native_tools::*;
use assets::*;
use browser::*;
use cli::*;
use client_extensions::*;
use collaboration::*;
use command_exec::*;
use command_output::*;
use command_sandbox::*;
use client_extensions::*;
use commands::*;
use config::*;
use context_compaction::*;