fix: 修复ComfyUI SDK的cargo check和clippy警告
- 修复ComfyUIError中WebSocket变体过大的问题,使用Box包装 - 添加自定义From实现处理Box包装的WebSocket错误 - 修复所有格式化字符串警告,使用内联格式化 - 移除无用的类型转换(reqwest::Error::from) - 修复代码质量问题: - 简化if语句嵌套 - 使用?操作符替代显式错误处理 - 优化map迭代方式 - 使用is_some_and替代map_or 修复内容: - 44个clippy警告全部解决 - 所有测试通过 - cargo check --lib 无错误无警告
This commit is contained in:
@@ -66,11 +66,11 @@ impl ComfyUIClient {
|
|||||||
pub async fn connect(&mut self) -> Result<()> {
|
pub async fn connect(&mut self) -> Result<()> {
|
||||||
// Test HTTP connection first
|
// Test HTTP connection first
|
||||||
self.http_client.get_queue().await
|
self.http_client.get_queue().await
|
||||||
.map_err(|e| ComfyUIError::connection(format!("HTTP connection failed: {}", e)))?;
|
.map_err(|e| ComfyUIError::connection(format!("HTTP connection failed: {e}")))?;
|
||||||
|
|
||||||
// Connect WebSocket
|
// Connect WebSocket
|
||||||
self.ws_client.connect().await
|
self.ws_client.connect().await
|
||||||
.map_err(|e| ComfyUIError::connection(format!("WebSocket connection failed: {}", e)))?;
|
.map_err(|e| ComfyUIError::connection(format!("WebSocket connection failed: {e}")))?;
|
||||||
|
|
||||||
log::info!("Successfully connected to ComfyUI server");
|
log::info!("Successfully connected to ComfyUI server");
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -107,7 +107,7 @@ impl ComfyUIClient {
|
|||||||
let prompt_response = self.http_client.queue_prompt(&prompt_request).await?;
|
let prompt_response = self.http_client.queue_prompt(&prompt_request).await?;
|
||||||
let prompt_id = prompt_response.prompt_id.clone();
|
let prompt_id = prompt_response.prompt_id.clone();
|
||||||
|
|
||||||
log::info!("Submitted prompt with ID: {}", prompt_id);
|
log::info!("Submitted prompt with ID: {prompt_id}");
|
||||||
|
|
||||||
// Wait for completion if WebSocket is connected
|
// Wait for completion if WebSocket is connected
|
||||||
if self.ws_client.is_connected().await {
|
if self.ws_client.is_connected().await {
|
||||||
@@ -186,8 +186,7 @@ impl ComfyUIClient {
|
|||||||
// Check timeout
|
// Check timeout
|
||||||
if start_time.elapsed() > timeout_duration {
|
if start_time.elapsed() > timeout_duration {
|
||||||
return Err(ComfyUIError::timeout(format!(
|
return Err(ComfyUIError::timeout(format!(
|
||||||
"Execution timed out after {:?}",
|
"Execution timed out after {timeout_duration:?}"
|
||||||
timeout_duration
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +209,7 @@ impl ComfyUIClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("Error checking history: {}", e);
|
log::warn!("Error checking history: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ impl HTTPClient {
|
|||||||
let response = request.send().await?;
|
let response = request.send().await?;
|
||||||
|
|
||||||
if !response.status().is_success() {
|
if !response.status().is_success() {
|
||||||
return Err(ComfyUIError::Http(reqwest::Error::from(
|
return Err(ComfyUIError::Http(
|
||||||
response.error_for_status().unwrap_err()
|
response.error_for_status().unwrap_err()
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let data: T = response.json().await?;
|
let data: T = response.json().await?;
|
||||||
@@ -115,9 +115,9 @@ impl HTTPClient {
|
|||||||
let response = request.send().await?;
|
let response = request.send().await?;
|
||||||
|
|
||||||
if !response.status().is_success() {
|
if !response.status().is_success() {
|
||||||
return Err(ComfyUIError::Http(reqwest::Error::from(
|
return Err(ComfyUIError::Http(
|
||||||
response.error_for_status().unwrap_err()
|
response.error_for_status().unwrap_err()
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let data: T = response.json().await?;
|
let data: T = response.json().await?;
|
||||||
@@ -144,7 +144,7 @@ impl HTTPClient {
|
|||||||
/// Gets execution history
|
/// Gets execution history
|
||||||
pub async fn get_history(&self, max_items: Option<u32>) -> Result<HashMap<String, HistoryItem>> {
|
pub async fn get_history(&self, max_items: Option<u32>) -> Result<HashMap<String, HistoryItem>> {
|
||||||
let endpoint = if let Some(max) = max_items {
|
let endpoint = if let Some(max) = max_items {
|
||||||
format!("/history?max_items={}", max)
|
format!("/history?max_items={max}")
|
||||||
} else {
|
} else {
|
||||||
"/history".to_string()
|
"/history".to_string()
|
||||||
};
|
};
|
||||||
@@ -154,7 +154,7 @@ impl HTTPClient {
|
|||||||
|
|
||||||
/// Gets history for a specific prompt
|
/// Gets history for a specific prompt
|
||||||
pub async fn get_history_by_prompt(&self, prompt_id: &str) -> Result<HashMap<String, HistoryItem>> {
|
pub async fn get_history_by_prompt(&self, prompt_id: &str) -> Result<HashMap<String, HistoryItem>> {
|
||||||
let endpoint = format!("/history/{}", prompt_id);
|
let endpoint = format!("/history/{prompt_id}");
|
||||||
self.get_with_retry(&endpoint).await
|
self.get_with_retry(&endpoint).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,9 +164,9 @@ impl HTTPClient {
|
|||||||
let response = self.client.delete(url).send().await?;
|
let response = self.client.delete(url).send().await?;
|
||||||
|
|
||||||
if !response.status().is_success() {
|
if !response.status().is_success() {
|
||||||
return Err(ComfyUIError::Http(reqwest::Error::from(
|
return Err(ComfyUIError::Http(
|
||||||
response.error_for_status().unwrap_err()
|
response.error_for_status().unwrap_err()
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -179,9 +179,9 @@ impl HTTPClient {
|
|||||||
let response = self.client.post(url).json(&body).send().await?;
|
let response = self.client.post(url).json(&body).send().await?;
|
||||||
|
|
||||||
if !response.status().is_success() {
|
if !response.status().is_success() {
|
||||||
return Err(ComfyUIError::Http(reqwest::Error::from(
|
return Err(ComfyUIError::Http(
|
||||||
response.error_for_status().unwrap_err()
|
response.error_for_status().unwrap_err()
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -209,7 +209,7 @@ impl HTTPClient {
|
|||||||
let part = multipart::Part::bytes(file_bytes)
|
let part = multipart::Part::bytes(file_bytes)
|
||||||
.file_name(filename.to_string())
|
.file_name(filename.to_string())
|
||||||
.mime_str("image/*")
|
.mime_str("image/*")
|
||||||
.map_err(|e| ComfyUIError::new(format!("Invalid MIME type: {}", e)))?;
|
.map_err(|e| ComfyUIError::new(format!("Invalid MIME type: {e}")))?;
|
||||||
|
|
||||||
let form = multipart::Form::new()
|
let form = multipart::Form::new()
|
||||||
.part("image", part)
|
.part("image", part)
|
||||||
@@ -219,9 +219,7 @@ impl HTTPClient {
|
|||||||
let response = self.client.post(url).multipart(form).send().await?;
|
let response = self.client.post(url).multipart(form).send().await?;
|
||||||
|
|
||||||
if !response.status().is_success() {
|
if !response.status().is_success() {
|
||||||
return Err(ComfyUIError::Http(reqwest::Error::from(
|
return Err(ComfyUIError::Http(response.error_for_status().unwrap_err()));
|
||||||
response.error_for_status().unwrap_err()
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let upload_response: UploadImageResponse = response.json().await?;
|
let upload_response: UploadImageResponse = response.json().await?;
|
||||||
@@ -230,23 +228,21 @@ impl HTTPClient {
|
|||||||
|
|
||||||
/// Gets an image by filename
|
/// Gets an image by filename
|
||||||
pub async fn get_image(&self, filename: &str, subfolder: Option<&str>, image_type: Option<&str>) -> Result<bytes::Bytes> {
|
pub async fn get_image(&self, filename: &str, subfolder: Option<&str>, image_type: Option<&str>) -> Result<bytes::Bytes> {
|
||||||
let mut endpoint = format!("/view?filename={}", filename);
|
let mut endpoint = format!("/view?filename={filename}");
|
||||||
|
|
||||||
if let Some(subfolder) = subfolder {
|
if let Some(subfolder) = subfolder {
|
||||||
endpoint.push_str(&format!("&subfolder={}", subfolder));
|
endpoint.push_str(&format!("&subfolder={subfolder}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(image_type) = image_type {
|
if let Some(image_type) = image_type {
|
||||||
endpoint.push_str(&format!("&type={}", image_type));
|
endpoint.push_str(&format!("&type={image_type}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = self.build_url(&endpoint)?;
|
let url = self.build_url(&endpoint)?;
|
||||||
let response = self.client.get(url).send().await?;
|
let response = self.client.get(url).send().await?;
|
||||||
|
|
||||||
if !response.status().is_success() {
|
if !response.status().is_success() {
|
||||||
return Err(ComfyUIError::Http(reqwest::Error::from(
|
return Err(ComfyUIError::Http(response.error_for_status().unwrap_err()));
|
||||||
response.error_for_status().unwrap_err()
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let bytes = response.bytes().await?;
|
let bytes = response.bytes().await?;
|
||||||
@@ -255,10 +251,10 @@ impl HTTPClient {
|
|||||||
|
|
||||||
/// Gets image metadata
|
/// Gets image metadata
|
||||||
pub async fn get_view_metadata(&self, filename: &str, subfolder: Option<&str>) -> Result<ViewMetadata> {
|
pub async fn get_view_metadata(&self, filename: &str, subfolder: Option<&str>) -> Result<ViewMetadata> {
|
||||||
let mut endpoint = format!("/view_metadata/{}", filename);
|
let mut endpoint = format!("/view_metadata/{filename}");
|
||||||
|
|
||||||
if let Some(subfolder) = subfolder {
|
if let Some(subfolder) = subfolder {
|
||||||
endpoint.push_str(&format!("?subfolder={}", subfolder));
|
endpoint.push_str(&format!("?subfolder={subfolder}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.get_with_retry(&endpoint).await
|
self.get_with_retry(&endpoint).await
|
||||||
@@ -268,7 +264,7 @@ impl HTTPClient {
|
|||||||
pub fn outputs_to_urls(&self, outputs: &HashMap<String, serde_json::Value>) -> Vec<String> {
|
pub fn outputs_to_urls(&self, outputs: &HashMap<String, serde_json::Value>) -> Vec<String> {
|
||||||
let mut urls = Vec::new();
|
let mut urls = Vec::new();
|
||||||
|
|
||||||
for (_node_id, output) in outputs {
|
for output in outputs.values() {
|
||||||
if let Some(output_obj) = output.as_object() {
|
if let Some(output_obj) = output.as_object() {
|
||||||
if let Some(images) = output_obj.get("images").and_then(|v| v.as_array()) {
|
if let Some(images) = output_obj.get("images").and_then(|v| v.as_array()) {
|
||||||
for image in images {
|
for image in images {
|
||||||
@@ -280,8 +276,7 @@ impl HTTPClient {
|
|||||||
) {
|
) {
|
||||||
let base_url_str = self.base_url.as_str().trim_end_matches('/');
|
let base_url_str = self.base_url.as_str().trim_end_matches('/');
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}/view?filename={}&subfolder={}&type={}",
|
"{base_url_str}/view?filename={filename}&subfolder={subfolder}&type={image_type}"
|
||||||
base_url_str, filename, subfolder, image_type
|
|
||||||
);
|
);
|
||||||
urls.push(url);
|
urls.push(url);
|
||||||
}
|
}
|
||||||
@@ -300,9 +295,7 @@ impl HTTPClient {
|
|||||||
let response = self.client.post(url).send().await?;
|
let response = self.client.post(url).send().await?;
|
||||||
|
|
||||||
if !response.status().is_success() {
|
if !response.status().is_success() {
|
||||||
return Err(ComfyUIError::Http(reqwest::Error::from(
|
return Err(ComfyUIError::Http(response.error_for_status().unwrap_err()));
|
||||||
response.error_for_status().unwrap_err()
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -314,9 +307,7 @@ impl HTTPClient {
|
|||||||
let response = self.client.post(url).send().await?;
|
let response = self.client.post(url).send().await?;
|
||||||
|
|
||||||
if !response.status().is_success() {
|
if !response.status().is_success() {
|
||||||
return Err(ComfyUIError::Http(reqwest::Error::from(
|
return Err(ComfyUIError::Http(response.error_for_status().unwrap_err()));
|
||||||
response.error_for_status().unwrap_err()
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ impl WebSocketClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let ws_url = self.build_websocket_url()?;
|
let ws_url = self.build_websocket_url()?;
|
||||||
log::info!("Connecting to WebSocket: {}", ws_url);
|
log::info!("Connecting to WebSocket: {ws_url}");
|
||||||
|
|
||||||
let (ws_stream, _) = connect_async(&ws_url).await?;
|
let (ws_stream, _) = connect_async(&ws_url).await?;
|
||||||
let (_ws_sender, mut ws_receiver) = ws_stream.split();
|
let (_ws_sender, mut ws_receiver) = ws_stream.split();
|
||||||
@@ -78,7 +78,7 @@ impl WebSocketClient {
|
|||||||
match message {
|
match message {
|
||||||
Some(Ok(Message::Text(text))) => {
|
Some(Ok(Message::Text(text))) => {
|
||||||
if let Err(e) = Self::handle_message(&text, &event_emitter).await {
|
if let Err(e) = Self::handle_message(&text, &event_emitter).await {
|
||||||
log::error!("Error handling WebSocket message: {}", e);
|
log::error!("Error handling WebSocket message: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(Ok(Message::Close(_))) => {
|
Some(Ok(Message::Close(_))) => {
|
||||||
@@ -86,7 +86,7 @@ impl WebSocketClient {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Some(Err(e)) => {
|
Some(Err(e)) => {
|
||||||
log::error!("WebSocket error: {}", e);
|
log::error!("WebSocket error: {e}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@@ -168,7 +168,7 @@ impl WebSocketClient {
|
|||||||
/// Handles incoming WebSocket messages
|
/// Handles incoming WebSocket messages
|
||||||
async fn handle_message(text: &str, event_emitter: &EventEmitter) -> Result<()> {
|
async fn handle_message(text: &str, event_emitter: &EventEmitter) -> Result<()> {
|
||||||
let message: WSMessage = serde_json::from_str(text)
|
let message: WSMessage = serde_json::from_str(text)
|
||||||
.map_err(|e| ComfyUIError::new(format!("Failed to parse WebSocket message: {}", e)))?;
|
.map_err(|e| ComfyUIError::new(format!("Failed to parse WebSocket message: {e}")))?;
|
||||||
|
|
||||||
match message {
|
match message {
|
||||||
WSMessage::Progress { data } => {
|
WSMessage::Progress { data } => {
|
||||||
@@ -204,7 +204,7 @@ impl WebSocketClient {
|
|||||||
event_emitter.emit_error(error).await;
|
event_emitter.emit_error(error).await;
|
||||||
}
|
}
|
||||||
WSMessage::Unknown => {
|
WSMessage::Unknown => {
|
||||||
log::debug!("Received unknown WebSocket message: {}", text);
|
log::debug!("Received unknown WebSocket message: {text}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ pub enum ComfyUIError {
|
|||||||
|
|
||||||
/// WebSocket errors
|
/// WebSocket errors
|
||||||
#[error("WebSocket error: {0}")]
|
#[error("WebSocket error: {0}")]
|
||||||
WebSocket(#[from] tokio_tungstenite::tungstenite::Error),
|
WebSocket(#[from] Box<tokio_tungstenite::tungstenite::Error>),
|
||||||
|
|
||||||
/// JSON serialization/deserialization errors
|
/// JSON serialization/deserialization errors
|
||||||
#[error("JSON error: {0}")]
|
#[error("JSON error: {0}")]
|
||||||
@@ -53,6 +53,12 @@ pub enum ComfyUIError {
|
|||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<tokio_tungstenite::tungstenite::Error> for ComfyUIError {
|
||||||
|
fn from(error: tokio_tungstenite::tungstenite::Error) -> Self {
|
||||||
|
Self::WebSocket(Box::new(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ComfyUIError {
|
impl ComfyUIError {
|
||||||
/// Create a new generic error
|
/// Create a new generic error
|
||||||
pub fn new(message: impl Into<String>) -> Self {
|
pub fn new(message: impl Into<String>) -> Self {
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ impl TemplateManager {
|
|||||||
pub fn create_instance(&self, template_id: &str, parameters: ParameterValues) -> Result<WorkflowInstance> {
|
pub fn create_instance(&self, template_id: &str, parameters: ParameterValues) -> Result<WorkflowInstance> {
|
||||||
let template = self.get_by_id(template_id)
|
let template = self.get_by_id(template_id)
|
||||||
.ok_or_else(|| ComfyUIError::template_validation(
|
.ok_or_else(|| ComfyUIError::template_validation(
|
||||||
format!("Template with ID '{}' not found", template_id)
|
format!("Template with ID '{template_id}' not found")
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
template.create_instance(parameters)
|
template.create_instance(parameters)
|
||||||
@@ -158,7 +158,7 @@ impl TemplateManager {
|
|||||||
|
|
||||||
if !validation.valid {
|
if !validation.valid {
|
||||||
return Err(ComfyUIError::template_validation(
|
return Err(ComfyUIError::template_validation(
|
||||||
format!("Template '{}' validation failed", id)
|
format!("Template '{id}' validation failed")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ impl WorkflowInstance {
|
|||||||
// Check if parameter exists in template
|
// Check if parameter exists in template
|
||||||
if !self.template.has_parameter(&name) {
|
if !self.template.has_parameter(&name) {
|
||||||
return Err(ComfyUIError::parameter_validation(
|
return Err(ComfyUIError::parameter_validation(
|
||||||
format!("Parameter '{}' does not exist in template", name)
|
format!("Parameter '{name}' does not exist in template")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ impl WorkflowInstance {
|
|||||||
for name in parameters.keys() {
|
for name in parameters.keys() {
|
||||||
if !self.template.has_parameter(name) {
|
if !self.template.has_parameter(name) {
|
||||||
return Err(ComfyUIError::parameter_validation(
|
return Err(ComfyUIError::parameter_validation(
|
||||||
format!("Parameter '{}' does not exist in template", name)
|
format!("Parameter '{name}' does not exist in template")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ where
|
|||||||
last_error = Some(error);
|
last_error = Some(error);
|
||||||
|
|
||||||
if attempt < config.max_attempts {
|
if attempt < config.max_attempts {
|
||||||
log::warn!("Attempt {} failed, retrying in {:?}", attempt, delay);
|
log::warn!("Attempt {attempt} failed, retrying in {delay:?}");
|
||||||
sleep(delay).await;
|
sleep(delay).await;
|
||||||
|
|
||||||
// Exponential backoff
|
// Exponential backoff
|
||||||
@@ -68,7 +68,7 @@ pub fn is_retryable_error(error: &ComfyUIError) -> bool {
|
|||||||
// Retry on network errors, timeouts, and 5xx status codes
|
// Retry on network errors, timeouts, and 5xx status codes
|
||||||
reqwest_error.is_timeout() ||
|
reqwest_error.is_timeout() ||
|
||||||
reqwest_error.is_connect() ||
|
reqwest_error.is_connect() ||
|
||||||
reqwest_error.status().map_or(false, |status| status.is_server_error())
|
reqwest_error.status().is_some_and(|status| status.is_server_error())
|
||||||
}
|
}
|
||||||
ComfyUIError::WebSocket(_) => true, // Most WebSocket errors are retryable
|
ComfyUIError::WebSocket(_) => true, // Most WebSocket errors are retryable
|
||||||
ComfyUIError::Connection(_) => true,
|
ComfyUIError::Connection(_) => true,
|
||||||
@@ -101,7 +101,7 @@ where
|
|||||||
last_error = Some(error);
|
last_error = Some(error);
|
||||||
|
|
||||||
if attempt < config.max_attempts {
|
if attempt < config.max_attempts {
|
||||||
log::warn!("Attempt {} failed with retryable error, retrying in {:?}", attempt, delay);
|
log::warn!("Attempt {attempt} failed with retryable error, retrying in {delay:?}");
|
||||||
sleep(delay).await;
|
sleep(delay).await;
|
||||||
|
|
||||||
// Exponential backoff
|
// Exponential backoff
|
||||||
@@ -130,8 +130,7 @@ where
|
|||||||
match tokio::time::timeout(timeout, operation).await {
|
match tokio::time::timeout(timeout, operation).await {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(_) => Err(ComfyUIError::timeout(format!(
|
Err(_) => Err(ComfyUIError::timeout(format!(
|
||||||
"Operation timed out after {:?}",
|
"Operation timed out after {timeout:?}"
|
||||||
timeout
|
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,7 +143,7 @@ pub trait ErrorContext<T> {
|
|||||||
impl<T> ErrorContext<T> for Result<T> {
|
impl<T> ErrorContext<T> for Result<T> {
|
||||||
fn with_context(self, context: &str) -> Result<T> {
|
fn with_context(self, context: &str) -> Result<T> {
|
||||||
self.map_err(|error| {
|
self.map_err(|error| {
|
||||||
ComfyUIError::new(format!("{}: {}", context, error))
|
ComfyUIError::new(format!("{context}: {error}"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ pub fn substitute_variables(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let regex = Regex::new(pattern)
|
let regex = Regex::new(pattern)
|
||||||
.map_err(|e| ComfyUIError::new(format!("Invalid regex pattern: {}", e)))?;
|
.map_err(|e| ComfyUIError::new(format!("Invalid regex pattern: {e}")))?;
|
||||||
|
|
||||||
let mut result = template.to_string();
|
let mut result = template.to_string();
|
||||||
let mut offset = 0i32;
|
let mut offset = 0i32;
|
||||||
@@ -96,7 +96,7 @@ pub fn substitute_variables(
|
|||||||
Some(value) => value_to_string(value)?,
|
Some(value) => value_to_string(value)?,
|
||||||
None => {
|
None => {
|
||||||
return Err(ComfyUIError::template_validation(
|
return Err(ComfyUIError::template_validation(
|
||||||
format!("Parameter '{}' not found", var_name)
|
format!("Parameter '{var_name}' not found")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -139,7 +139,7 @@ pub fn extract_variables(template: &str, syntax: VariableSyntax) -> Result<Vec<S
|
|||||||
};
|
};
|
||||||
|
|
||||||
let regex = Regex::new(pattern)
|
let regex = Regex::new(pattern)
|
||||||
.map_err(|e| ComfyUIError::new(format!("Invalid regex pattern: {}", e)))?;
|
.map_err(|e| ComfyUIError::new(format!("Invalid regex pattern: {e}")))?;
|
||||||
|
|
||||||
let mut variables = Vec::new();
|
let mut variables = Vec::new();
|
||||||
for captures in regex.captures_iter(template) {
|
for captures in regex.captures_iter(template) {
|
||||||
|
|||||||
@@ -13,15 +13,14 @@ pub fn validate_parameters(
|
|||||||
|
|
||||||
// Check required parameters
|
// Check required parameters
|
||||||
for (name, schema) in schemas {
|
for (name, schema) in schemas {
|
||||||
if schema.required.unwrap_or(false) {
|
if schema.required.unwrap_or(false)
|
||||||
if !parameters.contains_key(name) {
|
&& !parameters.contains_key(name) {
|
||||||
errors.push(ValidationError::new(
|
errors.push(ValidationError::new(
|
||||||
name,
|
name,
|
||||||
"Required parameter is missing",
|
"Required parameter is missing",
|
||||||
));
|
));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Validate parameter if present
|
// Validate parameter if present
|
||||||
if let Some(value) = parameters.get(name) {
|
if let Some(value) = parameters.get(name) {
|
||||||
@@ -85,7 +84,7 @@ pub fn validate_parameter_value(
|
|||||||
if !enum_values.contains(value) {
|
if !enum_values.contains(value) {
|
||||||
return Err(ValidationError::with_value(
|
return Err(ValidationError::with_value(
|
||||||
name,
|
name,
|
||||||
format!("Value must be one of: {:?}", enum_values),
|
format!("Value must be one of: {enum_values:?}"),
|
||||||
value.clone(),
|
value.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -109,7 +108,7 @@ fn validate_string_constraints(
|
|||||||
if !regex.is_match(value) {
|
if !regex.is_match(value) {
|
||||||
return Err(ValidationError::with_value(
|
return Err(ValidationError::with_value(
|
||||||
name,
|
name,
|
||||||
format!("String does not match pattern: {}", pattern),
|
format!("String does not match pattern: {pattern}"),
|
||||||
serde_json::Value::String(value.to_string()),
|
serde_json::Value::String(value.to_string()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -120,7 +119,7 @@ fn validate_string_constraints(
|
|||||||
if (value.len() as f64) < min {
|
if (value.len() as f64) < min {
|
||||||
return Err(ValidationError::with_value(
|
return Err(ValidationError::with_value(
|
||||||
name,
|
name,
|
||||||
format!("String length must be at least {}", min),
|
format!("String length must be at least {min}"),
|
||||||
serde_json::Value::String(value.to_string()),
|
serde_json::Value::String(value.to_string()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -130,7 +129,7 @@ fn validate_string_constraints(
|
|||||||
if (value.len() as f64) > max {
|
if (value.len() as f64) > max {
|
||||||
return Err(ValidationError::with_value(
|
return Err(ValidationError::with_value(
|
||||||
name,
|
name,
|
||||||
format!("String length must be at most {}", max),
|
format!("String length must be at most {max}"),
|
||||||
serde_json::Value::String(value.to_string()),
|
serde_json::Value::String(value.to_string()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -151,7 +150,7 @@ fn validate_number_constraints(
|
|||||||
if num_value < min {
|
if num_value < min {
|
||||||
return Err(ValidationError::with_value(
|
return Err(ValidationError::with_value(
|
||||||
name,
|
name,
|
||||||
format!("Number must be at least {}", min),
|
format!("Number must be at least {min}"),
|
||||||
serde_json::Value::Number(value.clone()),
|
serde_json::Value::Number(value.clone()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -161,7 +160,7 @@ fn validate_number_constraints(
|
|||||||
if num_value > max {
|
if num_value > max {
|
||||||
return Err(ValidationError::with_value(
|
return Err(ValidationError::with_value(
|
||||||
name,
|
name,
|
||||||
format!("Number must be at most {}", max),
|
format!("Number must be at most {max}"),
|
||||||
serde_json::Value::Number(value.clone()),
|
serde_json::Value::Number(value.clone()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -181,7 +180,7 @@ fn validate_array_constraints(
|
|||||||
if (value.len() as f64) < min {
|
if (value.len() as f64) < min {
|
||||||
return Err(ValidationError::with_value(
|
return Err(ValidationError::with_value(
|
||||||
name,
|
name,
|
||||||
format!("Array length must be at least {}", min),
|
format!("Array length must be at least {min}"),
|
||||||
serde_json::Value::Array(value.to_vec()),
|
serde_json::Value::Array(value.to_vec()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -191,7 +190,7 @@ fn validate_array_constraints(
|
|||||||
if (value.len() as f64) > max {
|
if (value.len() as f64) > max {
|
||||||
return Err(ValidationError::with_value(
|
return Err(ValidationError::with_value(
|
||||||
name,
|
name,
|
||||||
format!("Array length must be at most {}", max),
|
format!("Array length must be at most {max}"),
|
||||||
serde_json::Value::Array(value.to_vec()),
|
serde_json::Value::Array(value.to_vec()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -200,10 +199,8 @@ fn validate_array_constraints(
|
|||||||
// Validate items if schema is provided
|
// Validate items if schema is provided
|
||||||
if let Some(items_schema) = &schema.items {
|
if let Some(items_schema) = &schema.items {
|
||||||
for (index, item) in value.iter().enumerate() {
|
for (index, item) in value.iter().enumerate() {
|
||||||
let item_name = format!("{}[{}]", name, index);
|
let item_name = format!("{name}[{index}]");
|
||||||
if let Err(error) = validate_parameter_value(&item_name, item, items_schema) {
|
validate_parameter_value(&item_name, item, items_schema)?
|
||||||
return Err(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user