mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-09-02 17:49:20 +00:00
Add event-driven workflow orchestration skill, webhook flow, and trace coverage
This commit is contained in:
@@ -65,6 +65,16 @@ pub enum Trigger {
|
||||
/// Regex pattern to match against message content.
|
||||
pattern: String,
|
||||
},
|
||||
/// Fire when a structured system event is emitted.
|
||||
SystemEvent {
|
||||
/// Event source namespace (e.g. "github", "workflow", "tool").
|
||||
source: String,
|
||||
/// Event type within the source (e.g. "issue.opened").
|
||||
event_type: String,
|
||||
/// Optional exact-match filters against payload top-level fields.
|
||||
#[serde(default)]
|
||||
filters: std::collections::HashMap<String, String>,
|
||||
},
|
||||
/// Fire on incoming webhook POST to /hooks/routine/{id}.
|
||||
Webhook {
|
||||
/// Optional webhook path suffix (defaults to routine id).
|
||||
@@ -82,6 +92,7 @@ impl Trigger {
|
||||
match self {
|
||||
Trigger::Cron { .. } => "cron",
|
||||
Trigger::Event { .. } => "event",
|
||||
Trigger::SystemEvent { .. } => "system_event",
|
||||
Trigger::Webhook { .. } => "webhook",
|
||||
Trigger::Manual => "manual",
|
||||
}
|
||||
@@ -116,6 +127,38 @@ impl Trigger {
|
||||
.map(String::from);
|
||||
Ok(Trigger::Event { channel, pattern })
|
||||
}
|
||||
"system_event" => {
|
||||
let source = config
|
||||
.get("source")
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or_else(|| RoutineError::MissingField {
|
||||
context: "system_event trigger".into(),
|
||||
field: "source".into(),
|
||||
})?
|
||||
.to_string();
|
||||
let event_type = config
|
||||
.get("event_type")
|
||||
.and_then(|v| v.as_str())
|
||||
.ok_or_else(|| RoutineError::MissingField {
|
||||
context: "system_event trigger".into(),
|
||||
field: "event_type".into(),
|
||||
})?
|
||||
.to_string();
|
||||
let filters = config
|
||||
.get("filters")
|
||||
.and_then(|v| v.as_object())
|
||||
.map(|m| {
|
||||
m.iter()
|
||||
.filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), s.to_string())))
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
Ok(Trigger::SystemEvent {
|
||||
source,
|
||||
event_type,
|
||||
filters,
|
||||
})
|
||||
}
|
||||
"webhook" => {
|
||||
let path = config
|
||||
.get("path")
|
||||
@@ -142,6 +185,15 @@ impl Trigger {
|
||||
"pattern": pattern,
|
||||
"channel": channel,
|
||||
}),
|
||||
Trigger::SystemEvent {
|
||||
source,
|
||||
event_type,
|
||||
filters,
|
||||
} => serde_json::json!({
|
||||
"source": source,
|
||||
"event_type": event_type,
|
||||
"filters": filters,
|
||||
}),
|
||||
Trigger::Webhook { path, secret } => serde_json::json!({
|
||||
"path": path,
|
||||
"secret": secret,
|
||||
@@ -451,6 +503,24 @@ mod tests {
|
||||
if channel == Some("telegram".to_string()) && pattern == r"deploy\s+\w+"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_system_event_trigger_roundtrip() {
|
||||
let mut filters = std::collections::HashMap::new();
|
||||
filters.insert("repo".to_string(), "nearai/ironclaw".to_string());
|
||||
filters.insert("action".to_string(), "opened".to_string());
|
||||
let trigger = Trigger::SystemEvent {
|
||||
source: "github".to_string(),
|
||||
event_type: "issue".to_string(),
|
||||
filters: filters.clone(),
|
||||
};
|
||||
let json = trigger.to_config_json();
|
||||
let parsed = Trigger::from_db("system_event", json).expect("parse system_event");
|
||||
assert!(
|
||||
matches!(parsed, Trigger::SystemEvent { source, event_type, filters: f }
|
||||
if source == "github" && event_type == "issue" && f == filters)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_action_lightweight_roundtrip() {
|
||||
let action = RoutineAction::Lightweight {
|
||||
@@ -552,6 +622,15 @@ mod tests {
|
||||
.type_tag(),
|
||||
"webhook"
|
||||
);
|
||||
assert_eq!(
|
||||
Trigger::SystemEvent {
|
||||
source: String::new(),
|
||||
event_type: String::new(),
|
||||
filters: std::collections::HashMap::new(),
|
||||
}
|
||||
.type_tag(),
|
||||
"system_event"
|
||||
);
|
||||
assert_eq!(Trigger::Manual.type_tag(), "manual");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user