feat: add comfyui sdk
This commit is contained in:
133
cargos/comfyui-sdk/types/api.rs
Normal file
133
cargos/comfyui-sdk/types/api.rs
Normal file
@@ -0,0 +1,133 @@
|
||||
//! API types for ComfyUI SDK
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Queue status response
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct QueueStatus {
|
||||
pub queue_running: Vec<QueueItem>,
|
||||
pub queue_pending: Vec<QueueItem>,
|
||||
}
|
||||
|
||||
/// Queue item
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct QueueItem {
|
||||
pub prompt_id: String,
|
||||
pub number: u32,
|
||||
pub outputs: HashMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
/// Prompt request
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PromptRequest {
|
||||
pub prompt: HashMap<String, serde_json::Value>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub client_id: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub extra_data: Option<HashMap<String, serde_json::Value>>,
|
||||
}
|
||||
|
||||
/// Prompt response
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PromptResponse {
|
||||
pub prompt_id: String,
|
||||
pub number: u32,
|
||||
pub node_errors: HashMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
/// History item
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HistoryItem {
|
||||
pub prompt: Vec<serde_json::Value>,
|
||||
pub outputs: HashMap<String, HashMap<String, Vec<HistoryOutput>>>,
|
||||
pub status: HistoryStatus,
|
||||
}
|
||||
|
||||
/// History output
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HistoryOutput {
|
||||
pub filename: String,
|
||||
pub subfolder: String,
|
||||
#[serde(rename = "type")]
|
||||
pub output_type: String,
|
||||
}
|
||||
|
||||
/// History status
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HistoryStatus {
|
||||
pub status_str: String,
|
||||
pub completed: bool,
|
||||
pub messages: Vec<Vec<serde_json::Value>>,
|
||||
}
|
||||
|
||||
/// System stats
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SystemStats {
|
||||
pub system: SystemInfo,
|
||||
pub devices: Vec<DeviceInfo>,
|
||||
}
|
||||
|
||||
/// System information
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SystemInfo {
|
||||
pub os: String,
|
||||
pub python_version: String,
|
||||
pub embedded_python: bool,
|
||||
}
|
||||
|
||||
/// Device information
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DeviceInfo {
|
||||
pub name: String,
|
||||
pub device_type: String,
|
||||
pub vram_total: u64,
|
||||
pub vram_free: u64,
|
||||
pub torch_vram_total: u64,
|
||||
pub torch_vram_free: u64,
|
||||
}
|
||||
|
||||
/// Object info response
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ObjectInfo {
|
||||
#[serde(flatten)]
|
||||
pub nodes: HashMap<String, NodeInfo>,
|
||||
}
|
||||
|
||||
/// Node information
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct NodeInfo {
|
||||
pub input: NodeInputInfo,
|
||||
pub output: Vec<String>,
|
||||
pub output_is_list: Vec<bool>,
|
||||
pub output_name: Vec<String>,
|
||||
pub name: String,
|
||||
pub display_name: String,
|
||||
pub description: String,
|
||||
pub category: String,
|
||||
pub python_module: String,
|
||||
}
|
||||
|
||||
/// Node input information
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct NodeInputInfo {
|
||||
pub required: HashMap<String, Vec<serde_json::Value>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub optional: Option<HashMap<String, Vec<serde_json::Value>>>,
|
||||
}
|
||||
|
||||
/// Upload image response
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UploadImageResponse {
|
||||
pub name: String,
|
||||
pub subfolder: String,
|
||||
#[serde(rename = "type")]
|
||||
pub image_type: String,
|
||||
}
|
||||
|
||||
/// View metadata response
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ViewMetadata {
|
||||
#[serde(flatten)]
|
||||
pub metadata: HashMap<String, serde_json::Value>,
|
||||
}
|
||||
160
cargos/comfyui-sdk/types/events.rs
Normal file
160
cargos/comfyui-sdk/types/events.rs
Normal file
@@ -0,0 +1,160 @@
|
||||
//! Event types for ComfyUI SDK
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use chrono::{DateTime, Utc};
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Execution progress information
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ExecutionProgress {
|
||||
pub node_id: String,
|
||||
pub progress: u32,
|
||||
pub max: u32,
|
||||
pub timestamp: DateTime<Utc>,
|
||||
}
|
||||
|
||||
/// Execution result information
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ExecutionResult {
|
||||
pub prompt_id: String,
|
||||
pub outputs: HashMap<String, serde_json::Value>,
|
||||
pub execution_time: u64,
|
||||
pub timestamp: DateTime<Utc>,
|
||||
}
|
||||
|
||||
/// Execution error information
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ExecutionError {
|
||||
pub node_id: Option<String>,
|
||||
pub message: String,
|
||||
pub details: Option<serde_json::Value>,
|
||||
pub timestamp: DateTime<Utc>,
|
||||
}
|
||||
|
||||
/// Callback trait for execution events
|
||||
pub trait ExecutionCallbacks: Send + Sync {
|
||||
/// Called when progress is updated
|
||||
fn on_progress(&self, _progress: ExecutionProgress) {}
|
||||
|
||||
/// Called when a node starts executing
|
||||
fn on_executing(&self, _node_id: String) {}
|
||||
|
||||
/// Called when execution completes successfully
|
||||
fn on_executed(&self, _result: ExecutionResult) {}
|
||||
|
||||
/// Called when an error occurs
|
||||
fn on_error(&self, _error: ExecutionError) {}
|
||||
}
|
||||
|
||||
/// WebSocket message types
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum WSMessage {
|
||||
#[serde(rename = "progress")]
|
||||
Progress {
|
||||
data: WSProgressData,
|
||||
},
|
||||
#[serde(rename = "executing")]
|
||||
Executing {
|
||||
data: WSExecutingData,
|
||||
},
|
||||
#[serde(rename = "executed")]
|
||||
Executed {
|
||||
data: WSExecutedData,
|
||||
},
|
||||
#[serde(rename = "execution_error")]
|
||||
ExecutionError {
|
||||
data: WSErrorData,
|
||||
},
|
||||
#[serde(other)]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// WebSocket progress message data
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct WSProgressData {
|
||||
pub value: u32,
|
||||
pub max: u32,
|
||||
pub node: Option<String>,
|
||||
}
|
||||
|
||||
/// WebSocket executing message data
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct WSExecutingData {
|
||||
pub node: Option<String>,
|
||||
pub prompt_id: String,
|
||||
}
|
||||
|
||||
/// WebSocket executed message data
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct WSExecutedData {
|
||||
pub node: String,
|
||||
pub output: HashMap<String, serde_json::Value>,
|
||||
pub prompt_id: String,
|
||||
}
|
||||
|
||||
/// WebSocket error message data
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct WSErrorData {
|
||||
pub node_id: Option<String>,
|
||||
pub message: String,
|
||||
pub details: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
/// Execution options
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ExecutionOptions {
|
||||
pub timeout: Option<std::time::Duration>,
|
||||
pub priority: Option<i32>,
|
||||
}
|
||||
|
||||
impl Default for ExecutionOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
timeout: Some(std::time::Duration::from_secs(300)), // 5 minutes default
|
||||
priority: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Template execution result
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TemplateExecutionResult {
|
||||
pub prompt_id: String,
|
||||
pub success: bool,
|
||||
pub outputs: Option<HashMap<String, serde_json::Value>>,
|
||||
pub error: Option<ExecutionError>,
|
||||
pub execution_time: u64,
|
||||
}
|
||||
|
||||
impl TemplateExecutionResult {
|
||||
/// Create a successful execution result
|
||||
pub fn success(
|
||||
prompt_id: String,
|
||||
outputs: HashMap<String, serde_json::Value>,
|
||||
execution_time: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
prompt_id,
|
||||
success: true,
|
||||
outputs: Some(outputs),
|
||||
error: None,
|
||||
execution_time,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a failed execution result
|
||||
pub fn failure(
|
||||
prompt_id: String,
|
||||
error: ExecutionError,
|
||||
execution_time: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
prompt_id,
|
||||
success: false,
|
||||
outputs: None,
|
||||
error: Some(error),
|
||||
execution_time,
|
||||
}
|
||||
}
|
||||
}
|
||||
192
cargos/comfyui-sdk/types/mod.rs
Normal file
192
cargos/comfyui-sdk/types/mod.rs
Normal file
@@ -0,0 +1,192 @@
|
||||
//! Core types for ComfyUI SDK
|
||||
|
||||
use std::collections::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
pub mod api;
|
||||
pub mod events;
|
||||
|
||||
// Re-export all types
|
||||
pub use api::*;
|
||||
pub use events::*;
|
||||
|
||||
/// Base ComfyUI node definition
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ComfyUINode {
|
||||
pub class_type: String,
|
||||
pub inputs: HashMap<String, serde_json::Value>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub _meta: Option<NodeMeta>,
|
||||
}
|
||||
|
||||
/// Node metadata
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct NodeMeta {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub title: Option<String>,
|
||||
}
|
||||
|
||||
/// ComfyUI workflow definition
|
||||
pub type ComfyUIWorkflow = HashMap<String, ComfyUINode>;
|
||||
|
||||
/// Parameter schema types
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum ParameterType {
|
||||
String,
|
||||
Number,
|
||||
Boolean,
|
||||
Array,
|
||||
Object,
|
||||
}
|
||||
|
||||
/// Parameter schema definition
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ParameterSchema {
|
||||
#[serde(rename = "type")]
|
||||
pub param_type: ParameterType,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub required: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub default: Option<serde_json::Value>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub description: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub r#enum: Option<Vec<serde_json::Value>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub min: Option<f64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub max: Option<f64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub pattern: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub items: Option<Box<ParameterSchema>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub properties: Option<HashMap<String, ParameterSchema>>,
|
||||
}
|
||||
|
||||
/// Template metadata
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct TemplateMetadata {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub description: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub version: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub author: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tags: Option<Vec<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub category: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub created_at: Option<DateTime<Utc>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub updated_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
/// Workflow template data
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct WorkflowTemplateData {
|
||||
pub metadata: TemplateMetadata,
|
||||
pub workflow: ComfyUIWorkflow,
|
||||
pub parameters: HashMap<String, ParameterSchema>,
|
||||
}
|
||||
|
||||
/// Client configuration
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ComfyUIClientConfig {
|
||||
pub base_url: String,
|
||||
pub timeout: Option<std::time::Duration>,
|
||||
pub retry_attempts: Option<u32>,
|
||||
pub retry_delay: Option<std::time::Duration>,
|
||||
pub headers: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
||||
impl Default for ComfyUIClientConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
base_url: "http://localhost:8188".to_string(),
|
||||
timeout: Some(std::time::Duration::from_secs(30)),
|
||||
retry_attempts: Some(3),
|
||||
retry_delay: Some(std::time::Duration::from_millis(1000)),
|
||||
headers: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameter values type
|
||||
pub type ParameterValues = HashMap<String, serde_json::Value>;
|
||||
|
||||
/// Variable syntax options
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum VariableSyntax {
|
||||
DoubleBrace, // {{}}
|
||||
DollarBrace, // ${}
|
||||
AtBrace, // @{}
|
||||
}
|
||||
|
||||
/// Template validation result
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValidationResult {
|
||||
pub valid: bool,
|
||||
pub errors: Vec<ValidationError>,
|
||||
}
|
||||
|
||||
/// Validation error
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValidationError {
|
||||
pub path: String,
|
||||
pub message: String,
|
||||
pub value: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
impl ValidationResult {
|
||||
/// Create a successful validation result
|
||||
pub fn success() -> Self {
|
||||
Self {
|
||||
valid: true,
|
||||
errors: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a failed validation result with errors
|
||||
pub fn failure(errors: Vec<ValidationError>) -> Self {
|
||||
Self {
|
||||
valid: false,
|
||||
errors,
|
||||
}
|
||||
}
|
||||
|
||||
/// Add an error to the validation result
|
||||
pub fn add_error(&mut self, error: ValidationError) {
|
||||
self.valid = false;
|
||||
self.errors.push(error);
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidationError {
|
||||
/// Create a new validation error
|
||||
pub fn new(path: impl Into<String>, message: impl Into<String>) -> Self {
|
||||
Self {
|
||||
path: path.into(),
|
||||
message: message.into(),
|
||||
value: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new validation error with value
|
||||
pub fn with_value(
|
||||
path: impl Into<String>,
|
||||
message: impl Into<String>,
|
||||
value: serde_json::Value,
|
||||
) -> Self {
|
||||
Self {
|
||||
path: path.into(),
|
||||
message: message.into(),
|
||||
value: Some(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user