Skip to main content

swarm_engine_eval/scenario/
dependency.rs

1//! DependencyGraph Configuration
2//!
3//! 依存グラフの設定と関連する型の定義。
4
5use serde::{Deserialize, Serialize};
6
7// ============================================================================
8// DependencyGraph Type
9// ============================================================================
10
11/// 依存グラフの種類
12#[derive(Debug, Clone, Serialize, Deserialize)]
13#[serde(tag = "type", rename_all = "snake_case")]
14pub enum DependencyGraphType {
15    /// 組み込みパターンを使用
16    Static {
17        /// パターン名 (code_search, file_exploration)
18        #[serde(default = "default_pattern")]
19        pattern: String,
20    },
21    /// 明示的にグラフを定義
22    Custom {
23        /// 依存エッジ
24        edges: Vec<DependencyEdgeConfig>,
25        /// 開始ノード
26        start: Vec<String>,
27        /// 終端ノード
28        terminal: Vec<String>,
29        /// パラメータバリアント(action → (key, values))
30        #[serde(default)]
31        param_variants: Vec<ParamVariantConfig>,
32    },
33    /// LLM で動的生成(将来用)
34    Llm {},
35}
36
37impl Default for DependencyGraphType {
38    fn default() -> Self {
39        Self::Static {
40            pattern: default_pattern(),
41        }
42    }
43}
44
45fn default_pattern() -> String {
46    "code_search".to_string()
47}
48
49// ============================================================================
50// DependencyEdge Configuration
51// ============================================================================
52
53/// 依存エッジ設定
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct DependencyEdgeConfig {
56    /// 元アクション
57    pub from: String,
58    /// 先アクション
59    pub to: String,
60    /// 確信度 (0.0-1.0)
61    #[serde(default = "default_confidence")]
62    pub confidence: f64,
63}
64
65fn default_confidence() -> f64 {
66    0.9
67}
68
69// ============================================================================
70// ParamVariant Configuration
71// ============================================================================
72
73/// パラメータバリアント設定
74///
75/// アクションごとのパラメータバリエーションを定義。
76/// ExplorationSpace が後続ノード展開時に各バリアントごとにノードを生成する。
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct ParamVariantConfig {
79    /// アクション名(例: "Move")
80    pub action: String,
81    /// パラメータのキー名(例: "target")
82    pub key: String,
83    /// 取り得る値のリスト(例: ["north", "south", "east", "west"])
84    pub values: Vec<String>,
85}
86
87// ============================================================================
88// DependencyGraph Configuration
89// ============================================================================
90
91/// 依存グラフ設定
92///
93/// TOML で定義された依存グラフを Core の DependencyGraph に変換。
94#[derive(Debug, Clone, Serialize, Deserialize, Default)]
95pub struct DependencyGraphConfig {
96    /// 依存グラフの種類
97    #[serde(flatten)]
98    pub graph_type: DependencyGraphType,
99}
100
101impl DependencyGraphConfig {
102    /// Core の DependencyGraph に変換
103    pub fn to_core_graph(
104        &self,
105        available_actions: &[String],
106    ) -> Option<swarm_engine_core::exploration::DependencyGraph> {
107        use swarm_engine_core::exploration::{
108            DependencyGraph, DependencyPlanner, StaticDependencyPlanner,
109        };
110
111        match &self.graph_type {
112            DependencyGraphType::Static { pattern } => {
113                let planner = match pattern.as_str() {
114                    "code_search" => StaticDependencyPlanner::new().with_code_search_pattern(),
115                    "file_exploration" => {
116                        StaticDependencyPlanner::new().with_file_exploration_pattern()
117                    }
118                    _ => StaticDependencyPlanner::new().with_code_search_pattern(),
119                };
120                planner.plan("task", available_actions).ok()
121            }
122            DependencyGraphType::Custom {
123                edges,
124                start,
125                terminal,
126                param_variants,
127            } => {
128                let mut builder = DependencyGraph::builder()
129                    .available_actions(available_actions.iter().cloned())
130                    .start_nodes(start.iter().cloned())
131                    .terminal_nodes(terminal.iter().cloned());
132
133                for edge in edges {
134                    builder = builder.edge(&edge.from, &edge.to, edge.confidence);
135                }
136
137                // パラメータバリアントを設定
138                for pv in param_variants {
139                    builder =
140                        builder.param_variants(&pv.action, &pv.key, pv.values.iter().cloned());
141                }
142
143                Some(builder.build())
144            }
145            DependencyGraphType::Llm {} => {
146                // LLM 生成は将来実装
147                None
148            }
149        }
150    }
151}
152
153// ============================================================================
154// Tests
155// ============================================================================
156
157#[cfg(test)]
158mod tests {
159    use super::*;
160
161    #[test]
162    fn test_dependency_graph_type_default() {
163        let graph_type = DependencyGraphType::default();
164        match graph_type {
165            DependencyGraphType::Static { pattern } => {
166                assert_eq!(pattern, "code_search");
167            }
168            _ => panic!("Expected Static variant"),
169        }
170    }
171
172    #[test]
173    fn test_dependency_edge_config_default_confidence() {
174        let toml_str = r#"
175            from = "grep"
176            to = "read"
177        "#;
178        let edge: DependencyEdgeConfig = toml::from_str(toml_str).unwrap();
179        assert_eq!(edge.from, "grep");
180        assert_eq!(edge.to, "read");
181        assert!((edge.confidence - 0.9).abs() < 0.001);
182    }
183
184    #[test]
185    fn test_dependency_graph_config_static() {
186        let config = DependencyGraphConfig::default();
187        let actions = vec!["grep".to_string(), "read".to_string(), "done".to_string()];
188        let graph = config.to_core_graph(&actions);
189        assert!(graph.is_some());
190    }
191}