use anyhow::Result;
use async_trait::async_trait;
use serde_json::Value as JsonValue;
use crate::context::WorkflowContext;
#[derive(Debug, Clone)]
pub enum WorkflowResult {
Continue,
Waiting(Vec<PollPredicate>),
Finished(String, String),
}
#[derive(Debug, Clone)]
pub struct PollPredicate {
pub resource_type: String,
pub resource_id: String,
pub step_name: String,
pub intent_desc: Option<String>,
}
#[derive(Debug, Clone)]
pub struct RouteListener {
pub intent_desc: String,
pub msg_filter: String,
pub needs_llm: bool,
}
impl Default for RouteListener {
fn default() -> Self {
Self {
intent_desc: String::new(),
msg_filter: "creator_last_message".to_string(),
needs_llm: true,
}
}
}
#[derive(Debug, Clone)]
pub struct TimeoutConfig {
pub interval_seconds: u64,
pub max_strikes: u32,
}
impl Default for TimeoutConfig {
fn default() -> Self {
Self {
interval_seconds: 43200,
max_strikes: 3,
}
}
}
#[async_trait]
pub trait BaseWorkflow: Send + Sync {
async fn run(&self, ctx: &mut WorkflowContext) -> Result<WorkflowResult>;
fn route_listener(&self) -> Option<&RouteListener> {
None
}
fn is_listening(&self, _ctx: &WorkflowContext) -> bool {
false
}
fn on_route_matched(&self, _ctx: &mut WorkflowContext, _payload: Option<JsonValue>) {}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_poll_predicate_creation() {
let poll = PollPredicate {
resource_type: "message".to_string(),
resource_id: "creator_123".to_string(),
step_name: "wait_for_reply".to_string(),
intent_desc: Some("User wants to negotiate".to_string()),
};
assert_eq!(poll.resource_type, "message");
assert_eq!(poll.step_name, "wait_for_reply");
assert!(poll.intent_desc.is_some());
}
#[test]
fn test_route_listener_default() {
let listener = RouteListener::default();
assert_eq!(listener.msg_filter, "creator_last_message");
assert!(listener.needs_llm);
}
#[test]
fn test_timeout_config_default() {
let config = TimeoutConfig::default();
assert_eq!(config.interval_seconds, 43200);
assert_eq!(config.max_strikes, 3);
}
#[test]
fn test_workflow_result_variants() {
let cont = WorkflowResult::Continue;
assert!(matches!(cont, WorkflowResult::Continue));
let waiting = WorkflowResult::Waiting(vec![]);
assert!(matches!(waiting, WorkflowResult::Waiting(_)));
let finished = WorkflowResult::Finished("SUCCESS".to_string(), "done".to_string());
assert!(matches!(finished, WorkflowResult::Finished(_, _)));
}
}