kotoba_workflow_core/
lib.rs

1//! # Kotoba Workflow Core
2//!
3//! Minimal workflow engine interface for Kotoba.
4//! Provides core workflow execution functionality without heavy dependencies.
5
6pub mod engine;
7pub mod types;
8
9pub use engine::WorkflowEngine;
10pub use types::*;
11
12/// Prelude module for convenient imports
13pub mod prelude {
14    pub use super::{
15        WorkflowEngine,
16        WorkflowIR,
17        WorkflowExecution,
18        WorkflowExecutionId,
19        ExecutionStatus,
20        StartWorkflowResponse,
21        WorkflowError,
22    };
23}
24
25use async_trait::async_trait;
26use serde::{Deserialize, Serialize};
27use std::fmt;
28
29/// Workflow execution identifier
30#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
31pub struct WorkflowExecutionId(pub String);
32
33impl fmt::Display for WorkflowExecutionId {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        write!(f, "{}", self.0)
36    }
37}
38
39impl From<String> for WorkflowExecutionId {
40    fn from(s: String) -> Self {
41        Self(s)
42    }
43}
44
45impl From<&str> for WorkflowExecutionId {
46    fn from(s: &str) -> Self {
47        Self(s.to_string())
48    }
49}
50
51/// Workflow execution status
52#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
53pub enum ExecutionStatus {
54    Pending,
55    Running,
56    Completed,
57    Failed,
58    Cancelled,
59}
60
61/// Workflow execution state
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct WorkflowExecution {
64    pub execution_id: WorkflowExecutionId,
65    pub workflow_id: String,
66    pub status: ExecutionStatus,
67    pub created_at: chrono::DateTime<chrono::Utc>,
68    pub updated_at: chrono::DateTime<chrono::Utc>,
69    pub result: Option<serde_json::Value>,
70    pub error: Option<String>,
71}
72
73/// Start workflow response
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct StartWorkflowResponse {
76    pub execution_id: String,
77}
78
79/// Minimal workflow IR representation
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct WorkflowIR {
82    pub id: String,
83    pub name: String,
84    pub description: Option<String>,
85    pub activities: Vec<ActivityIR>,
86    pub connections: Vec<Connection>,
87}
88
89/// Activity IR representation
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct ActivityIR {
92    pub id: String,
93    pub name: String,
94    pub activity_type: String,
95    pub config: serde_json::Value,
96}
97
98/// Connection between activities
99#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct Connection {
101    pub from: String,
102    pub to: String,
103    pub condition: Option<String>,
104}
105
106/// Workflow engine interface
107#[async_trait]
108pub trait WorkflowEngineInterface: Send + Sync {
109    async fn start_workflow(
110        &self,
111        workflow: &WorkflowIR,
112        context: serde_json::Value,
113    ) -> Result<WorkflowExecutionId, WorkflowError>;
114
115    async fn get_execution(
116        &self,
117        execution_id: &WorkflowExecutionId,
118    ) -> Result<Option<WorkflowExecution>, WorkflowError>;
119
120    async fn list_executions(&self) -> Result<Vec<WorkflowExecution>, WorkflowError>;
121
122    async fn cancel_execution(
123        &self,
124        execution_id: &WorkflowExecutionId,
125    ) -> Result<(), WorkflowError>;
126}
127
128/// Workflow-specific error type
129#[derive(Debug, thiserror::Error)]
130pub enum WorkflowError {
131    #[error("Workflow not found: {0}")]
132    NotFound(String),
133
134    #[error("Workflow validation failed: {0}")]
135    Validation(String),
136
137    #[error("Workflow execution failed: {0}")]
138    Execution(String),
139
140    #[error("Storage error: {0}")]
141    Storage(String),
142
143    #[error("Serialization error: {0}")]
144    Serialization(#[from] serde_json::Error),
145
146    #[error("Unknown error: {0}")]
147    Unknown(String),
148}
149
150impl From<kotoba_errors::KotobaError> for WorkflowError {
151    fn from(err: kotoba_errors::KotobaError) -> Self {
152        match err {
153            kotoba_errors::KotobaError::NotFound(msg) => WorkflowError::NotFound(msg),
154            kotoba_errors::KotobaError::Validation(msg) => WorkflowError::Validation(msg),
155            _ => WorkflowError::Unknown(err.to_string()),
156        }
157    }
158}
159