170 lines
5.6 KiB
Rust
170 lines
5.6 KiB
Rust
//! WorkflowInstance implementation for executing parameterized workflows
|
|
|
|
use std::collections::HashMap;
|
|
use crate::types::{ComfyUIWorkflow, ParameterValues, ComfyUINode};
|
|
use crate::templates::WorkflowTemplate;
|
|
use crate::error::{ComfyUIError, Result};
|
|
use crate::utils::template_parser::apply_parameters;
|
|
|
|
/// Represents a workflow instance with applied parameters
|
|
#[derive(Debug, Clone)]
|
|
pub struct WorkflowInstance {
|
|
template: WorkflowTemplate,
|
|
parameters: ParameterValues,
|
|
resolved_workflow: ComfyUIWorkflow,
|
|
}
|
|
|
|
impl WorkflowInstance {
|
|
/// Creates a new WorkflowInstance
|
|
pub fn new(template: WorkflowTemplate, parameters: ParameterValues) -> Result<Self> {
|
|
// Apply parameters to the workflow
|
|
let resolved_workflow = apply_parameters(template.workflow(), ¶meters)?;
|
|
|
|
Ok(Self {
|
|
template,
|
|
parameters,
|
|
resolved_workflow,
|
|
})
|
|
}
|
|
|
|
/// Gets the original template
|
|
pub fn template(&self) -> &WorkflowTemplate {
|
|
&self.template
|
|
}
|
|
|
|
/// Gets the applied parameters
|
|
pub fn parameters(&self) -> &ParameterValues {
|
|
&self.parameters
|
|
}
|
|
|
|
/// Gets the resolved workflow with parameters applied
|
|
pub fn workflow(&self) -> &ComfyUIWorkflow {
|
|
&self.resolved_workflow
|
|
}
|
|
|
|
/// Gets the template ID
|
|
pub fn template_id(&self) -> &str {
|
|
self.template.id()
|
|
}
|
|
|
|
/// Gets the template name
|
|
pub fn template_name(&self) -> &str {
|
|
self.template.name()
|
|
}
|
|
|
|
/// Gets a specific parameter value
|
|
pub fn get_parameter(&self, name: &str) -> Option<&serde_json::Value> {
|
|
self.parameters.get(name)
|
|
}
|
|
|
|
/// Updates a parameter value and re-resolves the workflow
|
|
pub fn set_parameter(&mut self, name: String, value: serde_json::Value) -> Result<()> {
|
|
// Check if parameter exists in template
|
|
if !self.template.has_parameter(&name) {
|
|
return Err(ComfyUIError::parameter_validation(
|
|
format!("Parameter '{name}' does not exist in template")
|
|
));
|
|
}
|
|
|
|
// Update parameter
|
|
self.parameters.insert(name, value);
|
|
|
|
// Validate updated parameters
|
|
let validation = self.template.validate(&self.parameters);
|
|
if !validation.valid {
|
|
let error_messages: Vec<String> = validation.errors
|
|
.iter()
|
|
.map(|e| format!("{}: {}", e.path, e.message))
|
|
.collect();
|
|
return Err(ComfyUIError::parameter_validation(
|
|
format!("Invalid parameters after update: {}", error_messages.join(", "))
|
|
));
|
|
}
|
|
|
|
// Re-resolve workflow
|
|
self.resolved_workflow = apply_parameters(self.template.workflow(), &self.parameters)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Updates multiple parameters at once
|
|
pub fn set_parameters(&mut self, parameters: HashMap<String, serde_json::Value>) -> Result<()> {
|
|
// Check if all parameters exist in template
|
|
for name in parameters.keys() {
|
|
if !self.template.has_parameter(name) {
|
|
return Err(ComfyUIError::parameter_validation(
|
|
format!("Parameter '{name}' does not exist in template")
|
|
));
|
|
}
|
|
}
|
|
|
|
// Update parameters
|
|
for (name, value) in parameters {
|
|
self.parameters.insert(name, value);
|
|
}
|
|
|
|
// Validate updated parameters
|
|
let validation = self.template.validate(&self.parameters);
|
|
if !validation.valid {
|
|
let error_messages: Vec<String> = validation.errors
|
|
.iter()
|
|
.map(|e| format!("{}: {}", e.path, e.message))
|
|
.collect();
|
|
return Err(ComfyUIError::parameter_validation(
|
|
format!("Invalid parameters after update: {}", error_messages.join(", "))
|
|
));
|
|
}
|
|
|
|
// Re-resolve workflow
|
|
self.resolved_workflow = apply_parameters(self.template.workflow(), &self.parameters)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Gets a specific node from the resolved workflow
|
|
pub fn get_node(&self, node_id: &str) -> Option<&ComfyUINode> {
|
|
self.resolved_workflow.get(node_id)
|
|
}
|
|
|
|
/// Gets all node IDs in the workflow
|
|
pub fn get_node_ids(&self) -> Vec<&str> {
|
|
self.resolved_workflow.keys().map(|s| s.as_str()).collect()
|
|
}
|
|
|
|
/// Checks if the workflow contains a specific node
|
|
pub fn has_node(&self, node_id: &str) -> bool {
|
|
self.resolved_workflow.contains_key(node_id)
|
|
}
|
|
|
|
/// Gets the number of nodes in the workflow
|
|
pub fn node_count(&self) -> usize {
|
|
self.resolved_workflow.len()
|
|
}
|
|
|
|
/// Converts the instance to a JSON-serializable workflow
|
|
pub fn to_workflow_json(&self) -> Result<serde_json::Value> {
|
|
serde_json::to_value(&self.resolved_workflow)
|
|
.map_err(ComfyUIError::from)
|
|
}
|
|
|
|
/// Creates a clone with different parameters
|
|
pub fn with_parameters(&self, parameters: ParameterValues) -> Result<Self> {
|
|
Self::new(self.template.clone(), parameters)
|
|
}
|
|
|
|
/// Validates the current instance
|
|
pub fn validate(&self) -> Result<()> {
|
|
let validation = self.template.validate(&self.parameters);
|
|
if !validation.valid {
|
|
let error_messages: Vec<String> = validation.errors
|
|
.iter()
|
|
.map(|e| format!("{}: {}", e.path, e.message))
|
|
.collect();
|
|
return Err(ComfyUIError::parameter_validation(
|
|
format!("Instance validation failed: {}", error_messages.join(", "))
|
|
));
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|