Skip to main content

pidgin_lang/
router.rs

1use serde::Serialize;
2
3use crate::ast::{FieldValue, PgnPacket};
4use crate::registry::WorkflowRegistry;
5use crate::safety::SafetyResult;
6
7#[derive(Debug, Serialize)]
8pub struct RouteDecision {
9    pub recommended_executor: String,
10    pub fallback_executor: String,
11    pub reason: String,
12    pub human_required: bool,
13}
14
15pub fn route(
16    packet: &PgnPacket,
17    registry: &WorkflowRegistry,
18    safety: &SafetyResult,
19) -> RouteDecision {
20    let wf_name = packet
21        .fields
22        .get("wf")
23        .and_then(|v| match v {
24            FieldValue::Scalar(s) => Some(s.as_str()),
25            _ => None,
26        })
27        .unwrap_or("unknown");
28
29    let explicit_route = packet.fields.get("route").and_then(|v| match v {
30        FieldValue::Scalar(s) => Some(s.clone()),
31        _ => None,
32    });
33
34    let (recommended, fallback) = if let Some(route_val) = &explicit_route {
35        (route_val.clone(), registry.workflows.get(wf_name).map(|w| w.fallback_executor.clone()).unwrap_or_else(|| "unknown".to_string()))
36    } else if let Some(entry) = registry.workflows.get(wf_name) {
37        (entry.recommended_executor.clone(), entry.fallback_executor.clone())
38    } else {
39        ("unknown".to_string(), "unknown".to_string())
40    };
41
42    RouteDecision {
43        recommended_executor: recommended,
44        fallback_executor: fallback,
45        reason: if explicit_route.is_some() {
46            "explicit_route".to_string()
47        } else {
48            format!("workflow_{}", wf_name)
49        },
50        human_required: safety.human_required,
51    }
52}
53
54pub fn explain_route(decision: &RouteDecision) -> String {
55    format!(
56        "Route: {} (fallback: {}), human_required: {}, reason: {}",
57        decision.recommended_executor,
58        decision.fallback_executor,
59        decision.human_required,
60        decision.reason
61    )
62}