Skip to main content

aster/skills/
executor.rs

1//! Skill Execution Engine
2//!
3//! 定义 LLM Provider trait、执行回调接口和 Skill 执行器,用于 Skills 系统的执行引擎。
4//!
5//! # 概述
6//!
7//! 本模块提供了 Skills 执行引擎的核心抽象:
8//! - `LlmProvider`: LLM 调用接口,由应用层实现
9//! - `ExecutionCallback`: 执行进度回调接口,用于 UI 进度展示
10//! - `NoopCallback`: 空回调实现,用于无 UI 场景
11//! - `SkillExecutor`: Skill 执行器,根据执行模式分发到不同执行方法
12//!
13//! # 设计原则
14//!
15//! - **解耦设计**:框架层通过 trait 定义接口,应用层实现具体 LLM 调用
16//! - **可扩展性**:支持流式和非流式两种调用方式
17//! - **可测试性**:通过 trait 抽象便于 Mock 测试
18//!
19//! # 示例
20//!
21//! ```rust,ignore
22//! use aster::skills::executor::{LlmProvider, ExecutionCallback, NoopCallback, SkillExecutor};
23//! use aster::skills::error::SkillError;
24//! use async_trait::async_trait;
25//!
26//! // 实现 LlmProvider
27//! struct MyProvider;
28//!
29//! #[async_trait]
30//! impl LlmProvider for MyProvider {
31//!     async fn chat(
32//!         &self,
33//!         system_prompt: &str,
34//!         user_message: &str,
35//!         model: Option<&str>,
36//!     ) -> Result<String, SkillError> {
37//!         // 调用实际的 LLM API
38//!         Ok("LLM 响应".to_string())
39//!     }
40//! }
41//!
42//! // 创建执行器并执行 Skill
43//! let provider = MyProvider;
44//! let executor = SkillExecutor::new(provider);
45//! // let result = executor.execute(&skill, "用户输入", None).await;
46//!
47//! // 使用 NoopCallback
48//! let callback = NoopCallback;
49//! callback.on_step_start("step1", "分析步骤", 3);
50//! ```
51
52use async_trait::async_trait;
53
54use super::error::SkillError;
55use super::types::{SkillDefinition, SkillExecutionMode, SkillExecutionResult};
56
57/// LLM Provider trait(应用层实现)
58///
59/// 定义 LLM 调用的抽象接口,由应用层(如 ProxyCast)实现具体的 API 调用逻辑。
60///
61/// # 设计说明
62///
63/// - `chat`: 必须实现的同步聊天方法
64/// - `chat_stream`: 可选的流式聊天方法,默认回退到非流式实现
65///
66/// # 线程安全
67///
68/// 实现必须是 `Send + Sync`,以支持在异步上下文中使用。
69///
70/// # 示例
71///
72/// ```rust,ignore
73/// use aster::skills::executor::LlmProvider;
74/// use aster::skills::error::SkillError;
75/// use async_trait::async_trait;
76///
77/// struct OpenAIProvider {
78///     api_key: String,
79/// }
80///
81/// #[async_trait]
82/// impl LlmProvider for OpenAIProvider {
83///     async fn chat(
84///         &self,
85///         system_prompt: &str,
86///         user_message: &str,
87///         model: Option<&str>,
88///     ) -> Result<String, SkillError> {
89///         let model = model.unwrap_or("gpt-4");
90///         // 调用 OpenAI API...
91///         Ok("响应内容".to_string())
92///     }
93/// }
94/// ```
95#[async_trait]
96pub trait LlmProvider: Send + Sync {
97    /// 发送聊天请求
98    ///
99    /// # Arguments
100    ///
101    /// * `system_prompt` - 系统提示词,定义 LLM 的行为和角色
102    /// * `user_message` - 用户消息,实际的输入内容
103    /// * `model` - 可选的模型名称,如 "gpt-4"、"claude-3-opus" 等
104    ///
105    /// # Returns
106    ///
107    /// 成功时返回 LLM 响应文本,失败时返回 `SkillError`
108    ///
109    /// # Errors
110    ///
111    /// - `SkillError::ProviderError`: API 调用失败(网络错误、认证失败等)
112    /// - `SkillError::ExecutionFailed`: 响应处理失败
113    async fn chat(
114        &self,
115        system_prompt: &str,
116        user_message: &str,
117        model: Option<&str>,
118    ) -> Result<String, SkillError>;
119
120    /// 流式聊天(可选实现)
121    ///
122    /// 支持流式响应的 LLM 调用,通过回调函数实时返回生成的内容片段。
123    ///
124    /// # Arguments
125    ///
126    /// * `system_prompt` - 系统提示词
127    /// * `user_message` - 用户消息
128    /// * `model` - 可选的模型名称
129    /// * `callback` - 流式回调函数,每次收到新内容时调用
130    ///
131    /// # Returns
132    ///
133    /// 成功时返回完整的 LLM 响应文本,失败时返回 `SkillError`
134    ///
135    /// # Default Implementation
136    ///
137    /// 默认实现回退到非流式 `chat` 方法,忽略 callback 参数。
138    /// 如果需要真正的流式支持,应用层应覆盖此方法。
139    ///
140    /// # 示例
141    ///
142    /// ```rust,ignore
143    /// let callback = Box::new(|chunk: &str| {
144    ///     print!("{}", chunk);
145    /// });
146    /// let result = provider.chat_stream(
147    ///     "你是一个助手",
148    ///     "你好",
149    ///     Some("gpt-4"),
150    ///     callback,
151    /// ).await?;
152    /// ```
153    async fn chat_stream(
154        &self,
155        system_prompt: &str,
156        user_message: &str,
157        model: Option<&str>,
158        _callback: Box<dyn Fn(&str) + Send>,
159    ) -> Result<String, SkillError> {
160        // 默认实现:回退到非流式
161        self.chat(system_prompt, user_message, model).await
162    }
163}
164
165/// 执行回调 trait(应用层实现,用于 UI 进度展示)
166///
167/// 定义执行过程中的进度回调接口,应用层可实现此 trait 来展示执行进度。
168///
169/// # 回调时机
170///
171/// - `on_step_start`: 步骤开始执行时调用
172/// - `on_step_complete`: 步骤成功完成时调用
173/// - `on_step_error`: 步骤执行失败时调用
174/// - `on_complete`: 整体执行完成时调用
175///
176/// # 线程安全
177///
178/// 实现必须是 `Send + Sync`,以支持在异步上下文中使用。
179///
180/// # 示例
181///
182/// ```rust
183/// use aster::skills::executor::ExecutionCallback;
184///
185/// struct ConsoleCallback;
186///
187/// impl ExecutionCallback for ConsoleCallback {
188///     fn on_step_start(&self, step_id: &str, step_name: &str, total_steps: usize) {
189///         println!("[{}/{}] 开始: {}", step_id, total_steps, step_name);
190///     }
191///
192///     fn on_step_complete(&self, step_id: &str, output: &str) {
193///         println!("[{}] 完成: {}...", step_id, &output[..50.min(output.len())]);
194///     }
195///
196///     fn on_step_error(&self, step_id: &str, error: &str, will_retry: bool) {
197///         if will_retry {
198///             println!("[{}] 失败,将重试: {}", step_id, error);
199///         } else {
200///             println!("[{}] 失败: {}", step_id, error);
201///         }
202///     }
203///
204///     fn on_complete(&self, success: bool, final_output: Option<&str>) {
205///         if success {
206///             println!("执行成功!");
207///         } else {
208///             println!("执行失败");
209///         }
210///     }
211/// }
212/// ```
213pub trait ExecutionCallback: Send + Sync {
214    /// 步骤开始
215    ///
216    /// # Arguments
217    ///
218    /// * `step_id` - 步骤唯一标识符
219    /// * `step_name` - 步骤显示名称
220    /// * `total_steps` - 总步骤数
221    fn on_step_start(&self, step_id: &str, step_name: &str, total_steps: usize);
222
223    /// 步骤完成
224    ///
225    /// # Arguments
226    ///
227    /// * `step_id` - 步骤唯一标识符
228    /// * `output` - 步骤输出内容
229    fn on_step_complete(&self, step_id: &str, output: &str);
230
231    /// 步骤失败
232    ///
233    /// # Arguments
234    ///
235    /// * `step_id` - 步骤唯一标识符
236    /// * `error` - 错误信息
237    /// * `will_retry` - 是否将进行重试
238    fn on_step_error(&self, step_id: &str, error: &str, will_retry: bool);
239
240    /// 整体完成
241    ///
242    /// # Arguments
243    ///
244    /// * `success` - 是否执行成功
245    /// * `final_output` - 最终输出内容(成功时有值)
246    fn on_complete(&self, success: bool, final_output: Option<&str>);
247}
248
249/// 空回调实现(用于无 UI 场景)
250///
251/// 当不需要进度回调时使用此实现,所有方法都是空操作。
252///
253/// # 示例
254///
255/// ```rust
256/// use aster::skills::executor::{ExecutionCallback, NoopCallback};
257///
258/// let callback = NoopCallback;
259/// callback.on_step_start("step1", "测试步骤", 1);
260/// // 不会产生任何输出
261/// ```
262#[derive(Debug, Clone, Copy, Default)]
263pub struct NoopCallback;
264
265impl ExecutionCallback for NoopCallback {
266    fn on_step_start(&self, _step_id: &str, _step_name: &str, _total_steps: usize) {}
267
268    fn on_step_complete(&self, _step_id: &str, _output: &str) {}
269
270    fn on_step_error(&self, _step_id: &str, _error: &str, _will_retry: bool) {}
271
272    fn on_complete(&self, _success: bool, _final_output: Option<&str>) {}
273}
274
275// ==================== SkillExecutor ====================
276
277/// Skill 执行器
278///
279/// 根据 Skill 的执行模式分发到不同的执行方法。
280///
281/// # 类型参数
282///
283/// * `P` - 实现 `LlmProvider` trait 的类型,用于 LLM API 调用
284///
285/// # 执行模式
286///
287/// - `Prompt`: 单次对话,注入 System Prompt
288/// - `Workflow`: 多步骤工作流
289/// - `Agent`: 多轮迭代探索(未实现)
290///
291/// # 示例
292///
293/// ```rust,ignore
294/// use aster::skills::executor::{SkillExecutor, LlmProvider, NoopCallback};
295/// use aster::skills::error::SkillError;
296/// use async_trait::async_trait;
297///
298/// struct MyProvider;
299///
300/// #[async_trait]
301/// impl LlmProvider for MyProvider {
302///     async fn chat(
303///         &self,
304///         system_prompt: &str,
305///         user_message: &str,
306///         model: Option<&str>,
307///     ) -> Result<String, SkillError> {
308///         Ok("响应".to_string())
309///     }
310/// }
311///
312/// let executor = SkillExecutor::new(MyProvider);
313/// // let result = executor.execute(&skill, "输入", None).await;
314/// ```
315pub struct SkillExecutor<P: LlmProvider> {
316    provider: P,
317}
318
319impl<P: LlmProvider> SkillExecutor<P> {
320    /// 创建新的执行器
321    ///
322    /// # Arguments
323    ///
324    /// * `provider` - 实现 `LlmProvider` trait 的 LLM 提供者
325    ///
326    /// # Returns
327    ///
328    /// 新的 `SkillExecutor` 实例
329    ///
330    /// # 示例
331    ///
332    /// ```rust,ignore
333    /// let executor = SkillExecutor::new(my_provider);
334    /// ```
335    pub fn new(provider: P) -> Self {
336        Self { provider }
337    }
338
339    /// 获取 Provider 的引用
340    ///
341    /// # Returns
342    ///
343    /// Provider 的不可变引用
344    pub fn provider(&self) -> &P {
345        &self.provider
346    }
347
348    /// 执行 Skill
349    ///
350    /// 根据 Skill 的执行模式分发到不同的执行方法:
351    /// - `Prompt` 模式:调用 `execute_prompt_mode`
352    /// - `Workflow` 模式:调用 `execute_workflow_mode`
353    /// - `Agent` 模式:返回 `NotImplemented` 错误
354    ///
355    /// # Arguments
356    ///
357    /// * `skill` - Skill 定义
358    /// * `input` - 用户输入
359    /// * `callback` - 可选的执行回调,用于进度通知
360    ///
361    /// # Returns
362    ///
363    /// 执行结果或错误
364    ///
365    /// # Errors
366    ///
367    /// - `SkillError::NotImplemented`: Agent 模式尚未实现
368    /// - `SkillError::InvalidConfig`: Workflow 模式缺少 workflow 定义
369    /// - `SkillError::ProviderError`: LLM API 调用失败
370    /// - `SkillError::ExecutionFailed`: 执行过程中发生错误
371    ///
372    /// # 示例
373    ///
374    /// ```rust,ignore
375    /// let result = executor.execute(&skill, "分析这段代码", None).await?;
376    /// if result.success {
377    ///     println!("输出: {}", result.output.unwrap_or_default());
378    /// }
379    /// ```
380    pub async fn execute(
381        &self,
382        skill: &SkillDefinition,
383        input: &str,
384        callback: Option<&dyn ExecutionCallback>,
385    ) -> Result<SkillExecutionResult, SkillError> {
386        // 使用 NoopCallback 作为默认回调
387        let noop = NoopCallback;
388        let callback = callback.unwrap_or(&noop);
389
390        // 根据执行模式分发
391        match skill.execution_mode {
392            SkillExecutionMode::Prompt => self.execute_prompt_mode(skill, input, callback).await,
393            SkillExecutionMode::Workflow => {
394                self.execute_workflow_mode(skill, input, callback).await
395            }
396            SkillExecutionMode::Agent => Err(SkillError::not_implemented(
397                "Agent 模式尚未实现,请使用 Prompt 或 Workflow 模式",
398            )),
399        }
400    }
401
402    /// 执行 Prompt 模式
403    ///
404    /// 将 Skill 的 markdown_content 作为 system_prompt,用户输入作为 user_message,
405    /// 调用 LLM Provider 进行对话。
406    ///
407    /// # Arguments
408    ///
409    /// * `skill` - Skill 定义
410    /// * `input` - 用户输入
411    /// * `callback` - 执行回调
412    ///
413    /// # Returns
414    ///
415    /// 执行结果或错误
416    ///
417    /// # 实现说明
418    ///
419    /// 此方法将在 Task 5.4 中完整实现。当前为占位实现。
420    pub(crate) async fn execute_prompt_mode(
421        &self,
422        skill: &SkillDefinition,
423        input: &str,
424        callback: &dyn ExecutionCallback,
425    ) -> Result<SkillExecutionResult, SkillError> {
426        // 通知步骤开始
427        callback.on_step_start("prompt", &skill.display_name, 1);
428
429        // 调用 LLM Provider
430        let model = skill.model.as_deref();
431        let result = self
432            .provider
433            .chat(&skill.markdown_content, input, model)
434            .await;
435
436        match result {
437            Ok(output) => {
438                // 通知步骤完成
439                callback.on_step_complete("prompt", &output);
440                callback.on_complete(true, Some(&output));
441
442                Ok(SkillExecutionResult {
443                    success: true,
444                    output: Some(output),
445                    error: None,
446                    steps_completed: vec![],
447                    command_name: Some(skill.skill_name.clone()),
448                    allowed_tools: skill.allowed_tools.clone(),
449                    model: skill.model.clone(),
450                })
451            }
452            Err(e) => {
453                // 通知步骤失败
454                let error_msg = e.to_string();
455                callback.on_step_error("prompt", &error_msg, false);
456                callback.on_complete(false, None);
457
458                Ok(SkillExecutionResult {
459                    success: false,
460                    output: None,
461                    error: Some(error_msg),
462                    steps_completed: vec![],
463                    command_name: Some(skill.skill_name.clone()),
464                    allowed_tools: skill.allowed_tools.clone(),
465                    model: skill.model.clone(),
466                })
467            }
468        }
469    }
470
471    /// 执行 Workflow 模式
472    ///
473    /// 执行多步骤工作流,按依赖顺序执行各步骤,支持变量插值和重试机制。
474    ///
475    /// # Arguments
476    ///
477    /// * `skill` - Skill 定义(必须包含 workflow 字段)
478    /// * `input` - 用户输入
479    /// * `callback` - 执行回调
480    ///
481    /// # Returns
482    ///
483    /// 执行结果或错误
484    ///
485    /// # Errors
486    ///
487    /// - `SkillError::InvalidConfig`: 缺少 workflow 定义
488    /// - `SkillError::CyclicDependency`: 工作流存在循环依赖
489    /// - `SkillError::MissingDependency`: 步骤引用不存在的依赖
490    ///
491    /// # Requirements
492    ///
493    /// - **5.1**: 验证 workflow 定义存在
494    /// - **5.2**: 执行拓扑排序
495    /// - **5.3**: 按依赖顺序执行步骤
496    /// - **5.4**: 执行变量插值
497    /// - **5.5**: 将步骤输出存储到上下文
498    /// - **5.6**: 返回最后一个步骤的输出作为结果
499    /// - **8.3**: 重试耗尽且 continue_on_failure 为 false 时中止
500    /// - **8.4**: 重试耗尽且 continue_on_failure 为 true 时继续
501    pub(crate) async fn execute_workflow_mode(
502        &self,
503        skill: &SkillDefinition,
504        input: &str,
505        callback: &dyn ExecutionCallback,
506    ) -> Result<SkillExecutionResult, SkillError> {
507        use super::types::StepResult;
508        use super::workflow::{interpolate_variables, topological_sort};
509        use std::collections::HashMap;
510        use tracing::{debug, error, info, warn};
511
512        // 1. 验证 workflow 定义存在 (Requirement 5.1)
513        let workflow = skill.workflow.as_ref().ok_or_else(|| {
514            callback.on_complete(false, None);
515            SkillError::invalid_config("Workflow 模式需要定义 workflow 字段")
516        })?;
517
518        info!(
519            skill_name = %skill.skill_name,
520            steps_count = workflow.steps.len(),
521            max_retries = workflow.max_retries,
522            continue_on_failure = workflow.continue_on_failure,
523            "开始执行 Workflow 模式"
524        );
525
526        // 2. 拓扑排序步骤 (Requirement 5.2)
527        let sorted_steps = topological_sort(&workflow.steps).inspect_err(|_| {
528            callback.on_complete(false, None);
529        })?;
530
531        let total_steps = sorted_steps.len();
532        debug!(total_steps = total_steps, "拓扑排序完成");
533
534        // 3. 初始化上下文,添加 user_input
535        let mut context: HashMap<String, String> = HashMap::new();
536        context.insert("user_input".to_string(), input.to_string());
537
538        // 4. 记录已完成的步骤结果
539        let mut steps_completed: Vec<StepResult> = Vec::with_capacity(total_steps);
540        let mut final_output: Option<String> = None;
541        let mut had_failure = false;
542
543        // 5. 循环执行步骤 (Requirement 5.3)
544        for step in sorted_steps {
545            // 5.1 执行变量插值 (Requirement 5.4)
546            let interpolated_prompt = interpolate_variables(&step.prompt, &context);
547            debug!(step_id = %step.id, "执行步骤,变量插值完成");
548
549            // 5.2 执行步骤(带重试机制)
550            match self
551                .execute_step_with_retry(
552                    step,
553                    &interpolated_prompt,
554                    workflow.max_retries,
555                    total_steps,
556                    callback,
557                )
558                .await
559            {
560                Ok(output) => {
561                    info!(step_id = %step.id, output_len = output.len(), "步骤执行成功");
562                    // 5.3 将输出存储到上下文 (Requirement 5.5)
563                    context.insert(step.output.clone(), output.clone());
564                    context.insert(format!("{}.output", step.id), output.clone());
565                    callback.on_step_complete(&step.id, &output);
566                    steps_completed.push(StepResult::success(&step.id, &step.name, &output));
567                    final_output = Some(output);
568                }
569                Err(e) => {
570                    let error_msg = e.to_string();
571                    error!(step_id = %step.id, error = %error_msg, "步骤执行失败");
572                    had_failure = true;
573                    steps_completed.push(StepResult::failure(&step.id, &step.name, &error_msg));
574
575                    if workflow.continue_on_failure {
576                        warn!(step_id = %step.id, "continue_on_failure=true,继续执行");
577                        context.insert(step.output.clone(), String::new());
578                        context.insert(format!("{}.output", step.id), String::new());
579                    } else {
580                        callback.on_complete(false, None);
581                        return Ok(SkillExecutionResult {
582                            success: false,
583                            output: None,
584                            error: Some(format!("步骤 '{}' 执行失败: {}", step.id, error_msg)),
585                            steps_completed,
586                            command_name: Some(skill.skill_name.clone()),
587                            allowed_tools: skill.allowed_tools.clone(),
588                            model: skill.model.clone(),
589                        });
590                    }
591                }
592            }
593        }
594
595        // 6. 所有步骤执行完成,返回结果 (Requirement 5.6)
596        let success = !had_failure;
597        info!(
598            success = success,
599            steps_completed = steps_completed.len(),
600            "Workflow 执行完成"
601        );
602
603        callback.on_complete(success, final_output.as_deref());
604
605        Ok(SkillExecutionResult {
606            success,
607            output: final_output,
608            error: if had_failure {
609                Some("部分步骤执行失败".to_string())
610            } else {
611                None
612            },
613            steps_completed,
614            command_name: Some(skill.skill_name.clone()),
615            allowed_tools: skill.allowed_tools.clone(),
616            model: skill.model.clone(),
617        })
618    }
619
620    /// 执行单个步骤(带重试机制)
621    ///
622    /// 执行工作流中的单个步骤,支持指数退避重试。当步骤执行失败时,
623    /// 会按照指数退避策略进行重试,直到成功或达到最大重试次数。
624    ///
625    /// # 重试策略
626    ///
627    /// - 基础延迟:100ms
628    /// - 指数退避:100ms * 2^attempt(attempt 从 0 开始)
629    /// - 第 0 次重试:100ms
630    /// - 第 1 次重试:200ms
631    /// - 第 2 次重试:400ms
632    /// - 以此类推...
633    ///
634    /// # Arguments
635    ///
636    /// * `step` - 要执行的工作流步骤
637    /// * `interpolated_prompt` - 已完成变量插值的提示词
638    /// * `max_retries` - 最大重试次数
639    /// * `total_steps` - 工作流总步骤数(用于回调通知)
640    /// * `callback` - 执行回调,用于通知重试状态
641    ///
642    /// # Returns
643    ///
644    /// 成功时返回 LLM 响应文本,失败时返回最后一次错误
645    ///
646    /// # 回调通知
647    ///
648    /// - 每次重试前调用 `on_step_error` 并设置 `will_retry=true`
649    /// - 最后一次失败时调用 `on_step_error` 并设置 `will_retry=false`
650    ///
651    /// # 示例
652    ///
653    /// ```rust,ignore
654    /// let result = executor.execute_step_with_retry(
655    ///     &step,
656    ///     "处理用户输入:Hello",
657    ///     2,  // 最多重试 2 次
658    ///     3,  // 总共 3 个步骤
659    ///     &callback,
660    /// ).await;
661    /// ```
662    ///
663    /// # Requirements
664    ///
665    /// - **8.1**: 步骤失败时重试最多 max_retries 次
666    /// - **8.2**: 使用指数退避(100ms * 2^attempt)
667    /// - **8.5**: 通过 ExecutionCallback 通知每次重试尝试
668    pub(crate) async fn execute_step_with_retry(
669        &self,
670        step: &super::types::WorkflowStep,
671        interpolated_prompt: &str,
672        max_retries: u32,
673        total_steps: usize,
674        callback: &dyn ExecutionCallback,
675    ) -> Result<String, SkillError> {
676        use std::time::Duration;
677        use tokio::time::sleep;
678        use tracing::{info, warn};
679
680        // 基础延迟:100ms
681        const BASE_DELAY_MS: u64 = 100;
682
683        // 通知步骤开始
684        callback.on_step_start(&step.id, &step.name, total_steps);
685
686        let mut last_error: Option<SkillError> = None;
687
688        // 尝试执行,包括初始执行 + 重试
689        // attempt = 0 是初始执行,attempt = 1..=max_retries 是重试
690        for attempt in 0..=max_retries {
691            // 如果不是第一次尝试,先等待(指数退避)
692            if attempt > 0 {
693                let delay_ms = BASE_DELAY_MS * (1 << (attempt - 1)); // 100ms * 2^(attempt-1)
694                let delay = Duration::from_millis(delay_ms);
695
696                warn!(
697                    step_id = %step.id,
698                    attempt = attempt,
699                    max_retries = max_retries,
700                    delay_ms = delay_ms,
701                    "步骤执行失败,等待后重试"
702                );
703
704                sleep(delay).await;
705            }
706
707            info!(
708                step_id = %step.id,
709                step_name = %step.name,
710                attempt = attempt,
711                "执行步骤"
712            );
713
714            // 调用 LLM Provider 执行步骤
715            // 注意:工作流步骤使用空的 system_prompt,prompt 作为 user_message
716            match self.provider.chat("", interpolated_prompt, None).await {
717                Ok(output) => {
718                    // 执行成功
719                    info!(
720                        step_id = %step.id,
721                        attempt = attempt,
722                        "步骤执行成功"
723                    );
724                    return Ok(output);
725                }
726                Err(e) => {
727                    // 执行失败
728                    let error_msg = e.to_string();
729                    last_error = Some(e);
730
731                    // 判断是否还有重试机会
732                    let will_retry = attempt < max_retries;
733
734                    // 通知回调
735                    callback.on_step_error(&step.id, &error_msg, will_retry);
736
737                    if will_retry {
738                        warn!(
739                            step_id = %step.id,
740                            attempt = attempt,
741                            max_retries = max_retries,
742                            error = %error_msg,
743                            "步骤执行失败,将进行重试"
744                        );
745                    } else {
746                        warn!(
747                            step_id = %step.id,
748                            attempt = attempt,
749                            max_retries = max_retries,
750                            error = %error_msg,
751                            "步骤执行失败,重试次数已耗尽"
752                        );
753                    }
754                }
755            }
756        }
757
758        // 所有重试都失败了,返回最后一次错误
759        Err(last_error.unwrap_or_else(|| {
760            SkillError::execution_failed(format!("步骤 '{}' 执行失败", step.id))
761        }))
762    }
763}
764
765#[cfg(test)]
766mod tests {
767    use super::*;
768    use std::sync::atomic::{AtomicUsize, Ordering};
769    use std::sync::Arc;
770
771    // ==================== Mock Provider 实现 ====================
772
773    /// 测试用 Mock Provider
774    struct MockProvider {
775        response: String,
776        should_fail: bool,
777    }
778
779    impl MockProvider {
780        fn new(response: &str) -> Self {
781            Self {
782                response: response.to_string(),
783                should_fail: false,
784            }
785        }
786
787        fn failing() -> Self {
788            Self {
789                response: String::new(),
790                should_fail: true,
791            }
792        }
793    }
794
795    #[async_trait]
796    impl LlmProvider for MockProvider {
797        async fn chat(
798            &self,
799            _system_prompt: &str,
800            _user_message: &str,
801            _model: Option<&str>,
802        ) -> Result<String, SkillError> {
803            if self.should_fail {
804                Err(SkillError::provider_error("Mock provider error"))
805            } else {
806                Ok(self.response.clone())
807            }
808        }
809    }
810
811    // ==================== Mock Callback 实现 ====================
812
813    /// 测试用 Mock Callback,记录调用次数
814    struct MockCallback {
815        step_start_count: AtomicUsize,
816        step_complete_count: AtomicUsize,
817        step_error_count: AtomicUsize,
818        complete_count: AtomicUsize,
819    }
820
821    impl MockCallback {
822        fn new() -> Self {
823            Self {
824                step_start_count: AtomicUsize::new(0),
825                step_complete_count: AtomicUsize::new(0),
826                step_error_count: AtomicUsize::new(0),
827                complete_count: AtomicUsize::new(0),
828            }
829        }
830    }
831
832    impl ExecutionCallback for MockCallback {
833        fn on_step_start(&self, _step_id: &str, _step_name: &str, _total_steps: usize) {
834            self.step_start_count.fetch_add(1, Ordering::SeqCst);
835        }
836
837        fn on_step_complete(&self, _step_id: &str, _output: &str) {
838            self.step_complete_count.fetch_add(1, Ordering::SeqCst);
839        }
840
841        fn on_step_error(&self, _step_id: &str, _error: &str, _will_retry: bool) {
842            self.step_error_count.fetch_add(1, Ordering::SeqCst);
843        }
844
845        fn on_complete(&self, _success: bool, _final_output: Option<&str>) {
846            self.complete_count.fetch_add(1, Ordering::SeqCst);
847        }
848    }
849
850    // ==================== LlmProvider trait 测试 ====================
851
852    #[tokio::test]
853    async fn test_mock_provider_chat_success() {
854        let provider = MockProvider::new("Hello, world!");
855        let result = provider
856            .chat("System prompt", "User message", Some("gpt-4"))
857            .await;
858
859        assert!(result.is_ok());
860        assert_eq!(result.unwrap(), "Hello, world!");
861    }
862
863    #[tokio::test]
864    async fn test_mock_provider_chat_failure() {
865        let provider = MockProvider::failing();
866        let result = provider.chat("System prompt", "User message", None).await;
867
868        assert!(result.is_err());
869        let err = result.unwrap_err();
870        assert!(err.is_provider_error());
871    }
872
873    #[tokio::test]
874    async fn test_chat_stream_default_implementation() {
875        let provider = MockProvider::new("Streamed response");
876        let callback = Box::new(|_chunk: &str| {
877            // 默认实现不会调用 callback
878        });
879
880        let result = provider
881            .chat_stream("System prompt", "User message", Some("gpt-4"), callback)
882            .await;
883
884        assert!(result.is_ok());
885        assert_eq!(result.unwrap(), "Streamed response");
886    }
887
888    #[tokio::test]
889    async fn test_chat_with_none_model() {
890        let provider = MockProvider::new("Response");
891        let result = provider.chat("System", "User", None).await;
892
893        assert!(result.is_ok());
894    }
895
896    #[tokio::test]
897    async fn test_chat_with_empty_prompts() {
898        let provider = MockProvider::new("Response");
899        let result = provider.chat("", "", None).await;
900
901        assert!(result.is_ok());
902    }
903
904    // ==================== ExecutionCallback trait 测试 ====================
905
906    #[test]
907    fn test_mock_callback_step_start() {
908        let callback = MockCallback::new();
909        callback.on_step_start("step1", "Test Step", 3);
910
911        assert_eq!(callback.step_start_count.load(Ordering::SeqCst), 1);
912    }
913
914    #[test]
915    fn test_mock_callback_step_complete() {
916        let callback = MockCallback::new();
917        callback.on_step_complete("step1", "Output content");
918
919        assert_eq!(callback.step_complete_count.load(Ordering::SeqCst), 1);
920    }
921
922    #[test]
923    fn test_mock_callback_step_error() {
924        let callback = MockCallback::new();
925        callback.on_step_error("step1", "Error message", true);
926
927        assert_eq!(callback.step_error_count.load(Ordering::SeqCst), 1);
928    }
929
930    #[test]
931    fn test_mock_callback_complete() {
932        let callback = MockCallback::new();
933        callback.on_complete(true, Some("Final output"));
934
935        assert_eq!(callback.complete_count.load(Ordering::SeqCst), 1);
936    }
937
938    #[test]
939    fn test_mock_callback_multiple_calls() {
940        let callback = MockCallback::new();
941
942        callback.on_step_start("step1", "Step 1", 3);
943        callback.on_step_complete("step1", "Output 1");
944        callback.on_step_start("step2", "Step 2", 3);
945        callback.on_step_error("step2", "Error", true);
946        callback.on_step_start("step2", "Step 2 retry", 3);
947        callback.on_step_complete("step2", "Output 2");
948        callback.on_complete(true, Some("Final"));
949
950        assert_eq!(callback.step_start_count.load(Ordering::SeqCst), 3);
951        assert_eq!(callback.step_complete_count.load(Ordering::SeqCst), 2);
952        assert_eq!(callback.step_error_count.load(Ordering::SeqCst), 1);
953        assert_eq!(callback.complete_count.load(Ordering::SeqCst), 1);
954    }
955
956    // ==================== NoopCallback 测试 ====================
957
958    #[test]
959    fn test_noop_callback_step_start() {
960        let callback = NoopCallback;
961        // 应该不会 panic
962        callback.on_step_start("step1", "Test Step", 3);
963    }
964
965    #[test]
966    fn test_noop_callback_step_complete() {
967        let callback = NoopCallback;
968        callback.on_step_complete("step1", "Output content");
969    }
970
971    #[test]
972    fn test_noop_callback_step_error() {
973        let callback = NoopCallback;
974        callback.on_step_error("step1", "Error message", true);
975    }
976
977    #[test]
978    fn test_noop_callback_complete() {
979        let callback = NoopCallback;
980        callback.on_complete(true, Some("Final output"));
981    }
982
983    #[test]
984    fn test_noop_callback_complete_with_none() {
985        let callback = NoopCallback;
986        callback.on_complete(false, None);
987    }
988
989    #[test]
990    fn test_noop_callback_is_default() {
991        let callback = NoopCallback;
992        callback.on_step_start("step1", "Test", 1);
993    }
994
995    #[test]
996    fn test_noop_callback_is_clone() {
997        let callback = NoopCallback;
998        let cloned = callback;
999        cloned.on_step_start("step1", "Test", 1);
1000    }
1001
1002    #[test]
1003    fn test_noop_callback_debug() {
1004        let callback = NoopCallback;
1005        let debug_str = format!("{:?}", callback);
1006        assert!(debug_str.contains("NoopCallback"));
1007    }
1008
1009    // ==================== Send + Sync 测试 ====================
1010
1011    #[test]
1012    fn test_mock_provider_is_send_sync() {
1013        fn assert_send_sync<T: Send + Sync>() {}
1014        assert_send_sync::<MockProvider>();
1015    }
1016
1017    #[test]
1018    fn test_mock_callback_is_send_sync() {
1019        fn assert_send_sync<T: Send + Sync>() {}
1020        assert_send_sync::<MockCallback>();
1021    }
1022
1023    #[test]
1024    fn test_noop_callback_is_send_sync() {
1025        fn assert_send_sync<T: Send + Sync>() {}
1026        assert_send_sync::<NoopCallback>();
1027    }
1028
1029    // ==================== Arc 包装测试 ====================
1030
1031    #[test]
1032    fn test_callback_with_arc() {
1033        let callback = Arc::new(MockCallback::new());
1034        let callback_clone = Arc::clone(&callback);
1035
1036        callback.on_step_start("step1", "Test", 1);
1037        callback_clone.on_step_complete("step1", "Output");
1038
1039        assert_eq!(callback.step_start_count.load(Ordering::SeqCst), 1);
1040        assert_eq!(callback.step_complete_count.load(Ordering::SeqCst), 1);
1041    }
1042
1043    // ==================== 边界情况测试 ====================
1044
1045    #[tokio::test]
1046    async fn test_chat_with_unicode_content() {
1047        let provider = MockProvider::new("你好,世界!🌍");
1048        let result = provider
1049            .chat("系统提示词", "用户消息 🎉", Some("gpt-4"))
1050            .await;
1051
1052        assert!(result.is_ok());
1053        assert_eq!(result.unwrap(), "你好,世界!🌍");
1054    }
1055
1056    #[tokio::test]
1057    async fn test_chat_with_long_content() {
1058        let long_response = "a".repeat(10000);
1059        let provider = MockProvider::new(&long_response);
1060        let result = provider.chat("System", "User", None).await;
1061
1062        assert!(result.is_ok());
1063        assert_eq!(result.unwrap().len(), 10000);
1064    }
1065
1066    #[test]
1067    fn test_callback_with_empty_strings() {
1068        let callback = MockCallback::new();
1069        callback.on_step_start("", "", 0);
1070        callback.on_step_complete("", "");
1071        callback.on_step_error("", "", false);
1072        callback.on_complete(false, Some(""));
1073
1074        assert_eq!(callback.step_start_count.load(Ordering::SeqCst), 1);
1075        assert_eq!(callback.step_complete_count.load(Ordering::SeqCst), 1);
1076        assert_eq!(callback.step_error_count.load(Ordering::SeqCst), 1);
1077        assert_eq!(callback.complete_count.load(Ordering::SeqCst), 1);
1078    }
1079
1080    // ==================== SkillExecutor 测试 ====================
1081
1082    use super::super::types::{SkillSource, WorkflowDefinition, WorkflowStep};
1083    use std::path::PathBuf;
1084
1085    /// 创建测试用 SkillDefinition
1086    fn create_test_skill(mode: SkillExecutionMode) -> SkillDefinition {
1087        SkillDefinition {
1088            skill_name: "test:test-skill".to_string(),
1089            display_name: "Test Skill".to_string(),
1090            description: "A test skill".to_string(),
1091            has_user_specified_description: true,
1092            markdown_content: "You are a helpful assistant.".to_string(),
1093            allowed_tools: Some(vec!["tool1".to_string(), "tool2".to_string()]),
1094            argument_hint: Some("input".to_string()),
1095            when_to_use: Some("When testing".to_string()),
1096            version: Some("1.0.0".to_string()),
1097            model: Some("gpt-4".to_string()),
1098            disable_model_invocation: false,
1099            user_invocable: true,
1100            source: SkillSource::User,
1101            base_dir: PathBuf::from("/test"),
1102            file_path: PathBuf::from("/test/SKILL.md"),
1103            supporting_files: vec![],
1104            execution_mode: mode,
1105            provider: None,
1106            workflow: None,
1107        }
1108    }
1109
1110    /// 创建带 Workflow 的测试 SkillDefinition
1111    fn create_workflow_skill() -> SkillDefinition {
1112        let mut skill = create_test_skill(SkillExecutionMode::Workflow);
1113        skill.workflow = Some(WorkflowDefinition::new(vec![
1114            WorkflowStep::new("step1", "步骤一", "处理 ${user_input}", "result1"),
1115            WorkflowStep::new("step2", "步骤二", "继续 ${result1}", "result2")
1116                .with_dependency("step1"),
1117        ]));
1118        skill
1119    }
1120
1121    // -------------------- SkillExecutor 创建测试 --------------------
1122
1123    #[test]
1124    fn test_skill_executor_new() {
1125        let provider = MockProvider::new("response");
1126        let executor = SkillExecutor::new(provider);
1127
1128        // 验证 executor 创建成功,provider 可以访问
1129        let _provider_ref = executor.provider();
1130    }
1131
1132    #[test]
1133    fn test_skill_executor_provider_ref() {
1134        let provider = MockProvider::new("test response");
1135        let executor = SkillExecutor::new(provider);
1136
1137        // 验证可以获取 provider 引用
1138        let _provider_ref = executor.provider();
1139    }
1140
1141    // -------------------- execute 方法分发测试 --------------------
1142
1143    #[tokio::test]
1144    async fn test_execute_dispatches_to_prompt_mode() {
1145        let provider = MockProvider::new("Prompt mode response");
1146        let executor = SkillExecutor::new(provider);
1147        let skill = create_test_skill(SkillExecutionMode::Prompt);
1148
1149        let result = executor.execute(&skill, "test input", None).await;
1150
1151        assert!(result.is_ok());
1152        let result = result.unwrap();
1153        assert!(result.success);
1154        assert_eq!(result.output, Some("Prompt mode response".to_string()));
1155    }
1156
1157    #[tokio::test]
1158    async fn test_execute_dispatches_to_workflow_mode_without_workflow() {
1159        let provider = MockProvider::new("response");
1160        let executor = SkillExecutor::new(provider);
1161        let skill = create_test_skill(SkillExecutionMode::Workflow);
1162
1163        let result = executor.execute(&skill, "test input", None).await;
1164
1165        // 应该返回 InvalidConfig 错误,因为没有 workflow 定义
1166        assert!(result.is_err());
1167        let err = result.unwrap_err();
1168        assert!(err.is_invalid_config());
1169        assert!(err.message().contains("workflow"));
1170    }
1171
1172    #[tokio::test]
1173    async fn test_execute_dispatches_to_workflow_mode_with_workflow() {
1174        let provider = MockProvider::new("response");
1175        let executor = SkillExecutor::new(provider);
1176        let skill = create_workflow_skill();
1177
1178        let result = executor.execute(&skill, "test input", None).await;
1179
1180        // Workflow 模式应该成功执行
1181        assert!(result.is_ok());
1182        let result = result.unwrap();
1183        assert!(result.success);
1184        // 应该有两个步骤完成
1185        assert_eq!(result.steps_completed.len(), 2);
1186        // 最终输出应该是最后一个步骤的输出
1187        assert!(result.output.is_some());
1188    }
1189
1190    #[tokio::test]
1191    async fn test_execute_returns_not_implemented_for_agent_mode() {
1192        let provider = MockProvider::new("response");
1193        let executor = SkillExecutor::new(provider);
1194        let skill = create_test_skill(SkillExecutionMode::Agent);
1195
1196        let result = executor.execute(&skill, "test input", None).await;
1197
1198        assert!(result.is_err());
1199        let err = result.unwrap_err();
1200        assert!(err.is_not_implemented());
1201        assert!(err.message().contains("Agent"));
1202    }
1203
1204    // -------------------- Prompt 模式执行测试 --------------------
1205
1206    #[tokio::test]
1207    async fn test_prompt_mode_success() {
1208        let provider = MockProvider::new("LLM response");
1209        let executor = SkillExecutor::new(provider);
1210        let skill = create_test_skill(SkillExecutionMode::Prompt);
1211
1212        let result = executor.execute(&skill, "user input", None).await;
1213
1214        assert!(result.is_ok());
1215        let result = result.unwrap();
1216        assert!(result.success);
1217        assert_eq!(result.output, Some("LLM response".to_string()));
1218        assert!(result.error.is_none());
1219        assert_eq!(result.command_name, Some("test:test-skill".to_string()));
1220        assert_eq!(result.model, Some("gpt-4".to_string()));
1221    }
1222
1223    #[tokio::test]
1224    async fn test_prompt_mode_failure() {
1225        let provider = MockProvider::failing();
1226        let executor = SkillExecutor::new(provider);
1227        let skill = create_test_skill(SkillExecutionMode::Prompt);
1228
1229        let result = executor.execute(&skill, "user input", None).await;
1230
1231        assert!(result.is_ok()); // execute 返回 Ok,但 result.success 为 false
1232        let result = result.unwrap();
1233        assert!(!result.success);
1234        assert!(result.output.is_none());
1235        assert!(result.error.is_some());
1236        assert!(result.error.unwrap().contains("Provider"));
1237    }
1238
1239    #[tokio::test]
1240    async fn test_prompt_mode_with_callback() {
1241        let provider = MockProvider::new("response");
1242        let executor = SkillExecutor::new(provider);
1243        let skill = create_test_skill(SkillExecutionMode::Prompt);
1244        let callback = MockCallback::new();
1245
1246        let result = executor.execute(&skill, "input", Some(&callback)).await;
1247
1248        assert!(result.is_ok());
1249        assert_eq!(callback.step_start_count.load(Ordering::SeqCst), 1);
1250        assert_eq!(callback.step_complete_count.load(Ordering::SeqCst), 1);
1251        assert_eq!(callback.complete_count.load(Ordering::SeqCst), 1);
1252        assert_eq!(callback.step_error_count.load(Ordering::SeqCst), 0);
1253    }
1254
1255    #[tokio::test]
1256    async fn test_prompt_mode_failure_with_callback() {
1257        let provider = MockProvider::failing();
1258        let executor = SkillExecutor::new(provider);
1259        let skill = create_test_skill(SkillExecutionMode::Prompt);
1260        let callback = MockCallback::new();
1261
1262        let result = executor.execute(&skill, "input", Some(&callback)).await;
1263
1264        assert!(result.is_ok());
1265        let result = result.unwrap();
1266        assert!(!result.success);
1267        assert_eq!(callback.step_start_count.load(Ordering::SeqCst), 1);
1268        assert_eq!(callback.step_error_count.load(Ordering::SeqCst), 1);
1269        assert_eq!(callback.complete_count.load(Ordering::SeqCst), 1);
1270        assert_eq!(callback.step_complete_count.load(Ordering::SeqCst), 0);
1271    }
1272
1273    #[tokio::test]
1274    async fn test_prompt_mode_without_callback() {
1275        let provider = MockProvider::new("response");
1276        let executor = SkillExecutor::new(provider);
1277        let skill = create_test_skill(SkillExecutionMode::Prompt);
1278
1279        // 传入 None 作为 callback,应该使用 NoopCallback
1280        let result = executor.execute(&skill, "input", None).await;
1281
1282        assert!(result.is_ok());
1283        assert!(result.unwrap().success);
1284    }
1285
1286    #[tokio::test]
1287    async fn test_prompt_mode_preserves_skill_metadata() {
1288        let provider = MockProvider::new("response");
1289        let executor = SkillExecutor::new(provider);
1290        let skill = create_test_skill(SkillExecutionMode::Prompt);
1291
1292        let result = executor.execute(&skill, "input", None).await.unwrap();
1293
1294        assert_eq!(result.command_name, Some("test:test-skill".to_string()));
1295        assert_eq!(
1296            result.allowed_tools,
1297            Some(vec!["tool1".to_string(), "tool2".to_string()])
1298        );
1299        assert_eq!(result.model, Some("gpt-4".to_string()));
1300    }
1301
1302    // -------------------- Workflow 模式验证测试 --------------------
1303
1304    #[tokio::test]
1305    async fn test_workflow_mode_validates_workflow_definition() {
1306        let provider = MockProvider::new("response");
1307        let executor = SkillExecutor::new(provider);
1308        let mut skill = create_test_skill(SkillExecutionMode::Workflow);
1309        skill.workflow = None; // 确保没有 workflow 定义
1310
1311        let result = executor.execute(&skill, "input", None).await;
1312
1313        assert!(result.is_err());
1314        let err = result.unwrap_err();
1315        assert!(err.is_invalid_config());
1316    }
1317
1318    // -------------------- 边界情况测试 --------------------
1319
1320    #[tokio::test]
1321    async fn test_execute_with_empty_input() {
1322        let provider = MockProvider::new("response");
1323        let executor = SkillExecutor::new(provider);
1324        let skill = create_test_skill(SkillExecutionMode::Prompt);
1325
1326        let result = executor.execute(&skill, "", None).await;
1327
1328        assert!(result.is_ok());
1329        assert!(result.unwrap().success);
1330    }
1331
1332    #[tokio::test]
1333    async fn test_execute_with_unicode_input() {
1334        let provider = MockProvider::new("你好,世界!");
1335        let executor = SkillExecutor::new(provider);
1336        let skill = create_test_skill(SkillExecutionMode::Prompt);
1337
1338        let result = executor.execute(&skill, "中文输入 🎉", None).await;
1339
1340        assert!(result.is_ok());
1341        let result = result.unwrap();
1342        assert!(result.success);
1343        assert_eq!(result.output, Some("你好,世界!".to_string()));
1344    }
1345
1346    #[tokio::test]
1347    async fn test_execute_with_long_input() {
1348        let long_input = "a".repeat(10000);
1349        let provider = MockProvider::new("response");
1350        let executor = SkillExecutor::new(provider);
1351        let skill = create_test_skill(SkillExecutionMode::Prompt);
1352
1353        let result = executor.execute(&skill, &long_input, None).await;
1354
1355        assert!(result.is_ok());
1356        assert!(result.unwrap().success);
1357    }
1358
1359    // -------------------- SkillExecutor Send + Sync 测试 --------------------
1360
1361    #[test]
1362    fn test_skill_executor_is_send_sync() {
1363        fn assert_send_sync<T: Send + Sync>() {}
1364        assert_send_sync::<SkillExecutor<MockProvider>>();
1365    }
1366
1367    // ==================== execute_step_with_retry 测试 ====================
1368
1369    /// 可配置失败次数的 Mock Provider
1370    /// 用于测试重试机制
1371    struct RetryMockProvider {
1372        /// 失败次数计数器
1373        fail_count: std::sync::atomic::AtomicU32,
1374        /// 在成功前应该失败的次数
1375        fail_until: u32,
1376        /// 成功时返回的响应
1377        success_response: String,
1378    }
1379
1380    impl RetryMockProvider {
1381        /// 创建一个在指定次数失败后成功的 Provider
1382        fn fail_then_succeed(fail_count: u32, response: &str) -> Self {
1383            Self {
1384                fail_count: std::sync::atomic::AtomicU32::new(0),
1385                fail_until: fail_count,
1386                success_response: response.to_string(),
1387            }
1388        }
1389
1390        /// 创建一个始终失败的 Provider
1391        fn always_fail() -> Self {
1392            Self {
1393                fail_count: std::sync::atomic::AtomicU32::new(0),
1394                fail_until: u32::MAX,
1395                success_response: String::new(),
1396            }
1397        }
1398
1399        /// 获取当前调用次数
1400        fn call_count(&self) -> u32 {
1401            self.fail_count.load(Ordering::SeqCst)
1402        }
1403    }
1404
1405    #[async_trait]
1406    impl LlmProvider for RetryMockProvider {
1407        async fn chat(
1408            &self,
1409            _system_prompt: &str,
1410            _user_message: &str,
1411            _model: Option<&str>,
1412        ) -> Result<String, SkillError> {
1413            let current = self.fail_count.fetch_add(1, Ordering::SeqCst);
1414            if current < self.fail_until {
1415                Err(SkillError::provider_error(format!(
1416                    "模拟失败 (第 {} 次调用)",
1417                    current + 1
1418                )))
1419            } else {
1420                Ok(self.success_response.clone())
1421            }
1422        }
1423    }
1424
1425    /// 记录重试详情的 Mock Callback
1426    struct RetryTrackingCallback {
1427        step_start_count: AtomicUsize,
1428        step_complete_count: AtomicUsize,
1429        step_error_count: AtomicUsize,
1430        /// 记录每次 on_step_error 的 will_retry 值
1431        will_retry_values: std::sync::Mutex<Vec<bool>>,
1432    }
1433
1434    impl RetryTrackingCallback {
1435        fn new() -> Self {
1436            Self {
1437                step_start_count: AtomicUsize::new(0),
1438                step_complete_count: AtomicUsize::new(0),
1439                step_error_count: AtomicUsize::new(0),
1440                will_retry_values: std::sync::Mutex::new(Vec::new()),
1441            }
1442        }
1443
1444        fn get_will_retry_values(&self) -> Vec<bool> {
1445            self.will_retry_values.lock().unwrap().clone()
1446        }
1447    }
1448
1449    impl ExecutionCallback for RetryTrackingCallback {
1450        fn on_step_start(&self, _step_id: &str, _step_name: &str, _total_steps: usize) {
1451            self.step_start_count.fetch_add(1, Ordering::SeqCst);
1452        }
1453
1454        fn on_step_complete(&self, _step_id: &str, _output: &str) {
1455            self.step_complete_count.fetch_add(1, Ordering::SeqCst);
1456        }
1457
1458        fn on_step_error(&self, _step_id: &str, _error: &str, will_retry: bool) {
1459            self.step_error_count.fetch_add(1, Ordering::SeqCst);
1460            self.will_retry_values.lock().unwrap().push(will_retry);
1461        }
1462
1463        fn on_complete(&self, _success: bool, _final_output: Option<&str>) {}
1464    }
1465
1466    // -------------------- 基本重试功能测试 --------------------
1467
1468    #[tokio::test]
1469    async fn test_execute_step_with_retry_success_first_try() {
1470        let provider = MockProvider::new("成功响应");
1471        let executor = SkillExecutor::new(provider);
1472        let step = WorkflowStep::new("step1", "测试步骤", "测试提示", "output");
1473        let callback = RetryTrackingCallback::new();
1474
1475        let result = executor
1476            .execute_step_with_retry(&step, "测试提示", 2, 1, &callback)
1477            .await;
1478
1479        assert!(result.is_ok());
1480        assert_eq!(result.unwrap(), "成功响应");
1481        // 应该调用一次 on_step_start,没有错误
1482        assert_eq!(callback.step_start_count.load(Ordering::SeqCst), 1);
1483        assert_eq!(callback.step_error_count.load(Ordering::SeqCst), 0);
1484    }
1485
1486    #[tokio::test]
1487    async fn test_execute_step_with_retry_success_after_one_retry() {
1488        // 第一次失败,第二次成功
1489        let provider = RetryMockProvider::fail_then_succeed(1, "重试后成功");
1490        let executor = SkillExecutor::new(provider);
1491        let step = WorkflowStep::new("step1", "测试步骤", "测试提示", "output");
1492        let callback = RetryTrackingCallback::new();
1493
1494        let result = executor
1495            .execute_step_with_retry(&step, "测试提示", 2, 1, &callback)
1496            .await;
1497
1498        assert!(result.is_ok());
1499        assert_eq!(result.unwrap(), "重试后成功");
1500        // 应该有一次错误回调,will_retry=true
1501        assert_eq!(callback.step_error_count.load(Ordering::SeqCst), 1);
1502        let will_retry_values = callback.get_will_retry_values();
1503        assert_eq!(will_retry_values, vec![true]);
1504    }
1505
1506    #[tokio::test]
1507    async fn test_execute_step_with_retry_success_after_two_retries() {
1508        // 前两次失败,第三次成功
1509        let provider = RetryMockProvider::fail_then_succeed(2, "两次重试后成功");
1510        let executor = SkillExecutor::new(provider);
1511        let step = WorkflowStep::new("step1", "测试步骤", "测试提示", "output");
1512        let callback = RetryTrackingCallback::new();
1513
1514        let result = executor
1515            .execute_step_with_retry(&step, "测试提示", 2, 1, &callback)
1516            .await;
1517
1518        assert!(result.is_ok());
1519        assert_eq!(result.unwrap(), "两次重试后成功");
1520        // 应该有两次错误回调,都是 will_retry=true
1521        assert_eq!(callback.step_error_count.load(Ordering::SeqCst), 2);
1522        let will_retry_values = callback.get_will_retry_values();
1523        assert_eq!(will_retry_values, vec![true, true]);
1524    }
1525
1526    #[tokio::test]
1527    async fn test_execute_step_with_retry_all_retries_exhausted() {
1528        // 始终失败
1529        let provider = RetryMockProvider::always_fail();
1530        let executor = SkillExecutor::new(provider);
1531        let step = WorkflowStep::new("step1", "测试步骤", "测试提示", "output");
1532        let callback = RetryTrackingCallback::new();
1533
1534        let result = executor
1535            .execute_step_with_retry(&step, "测试提示", 2, 1, &callback)
1536            .await;
1537
1538        assert!(result.is_err());
1539        // 应该有 3 次错误回调(初始 + 2 次重试)
1540        // will_retry: [true, true, false]
1541        assert_eq!(callback.step_error_count.load(Ordering::SeqCst), 3);
1542        let will_retry_values = callback.get_will_retry_values();
1543        assert_eq!(will_retry_values, vec![true, true, false]);
1544    }
1545
1546    #[tokio::test]
1547    async fn test_execute_step_with_retry_zero_retries() {
1548        // max_retries = 0,只尝试一次
1549        let provider = RetryMockProvider::always_fail();
1550        let executor = SkillExecutor::new(provider);
1551        let step = WorkflowStep::new("step1", "测试步骤", "测试提示", "output");
1552        let callback = RetryTrackingCallback::new();
1553
1554        let result = executor
1555            .execute_step_with_retry(&step, "测试提示", 0, 1, &callback)
1556            .await;
1557
1558        assert!(result.is_err());
1559        // 只有一次错误回调,will_retry=false
1560        assert_eq!(callback.step_error_count.load(Ordering::SeqCst), 1);
1561        let will_retry_values = callback.get_will_retry_values();
1562        assert_eq!(will_retry_values, vec![false]);
1563    }
1564
1565    // -------------------- 回调通知测试 --------------------
1566
1567    #[tokio::test]
1568    async fn test_execute_step_with_retry_calls_on_step_start() {
1569        let provider = MockProvider::new("响应");
1570        let executor = SkillExecutor::new(provider);
1571        let step = WorkflowStep::new("step1", "测试步骤", "测试提示", "output");
1572        let callback = RetryTrackingCallback::new();
1573
1574        let _ = executor
1575            .execute_step_with_retry(&step, "测试提示", 2, 5, &callback)
1576            .await;
1577
1578        // 应该只调用一次 on_step_start(不是每次重试都调用)
1579        assert_eq!(callback.step_start_count.load(Ordering::SeqCst), 1);
1580    }
1581
1582    #[tokio::test]
1583    async fn test_execute_step_with_retry_will_retry_flag_correct() {
1584        // 测试 will_retry 标志的正确性
1585        // max_retries = 3,始终失败
1586        let provider = RetryMockProvider::always_fail();
1587        let executor = SkillExecutor::new(provider);
1588        let step = WorkflowStep::new("step1", "测试步骤", "测试提示", "output");
1589        let callback = RetryTrackingCallback::new();
1590
1591        let _ = executor
1592            .execute_step_with_retry(&step, "测试提示", 3, 1, &callback)
1593            .await;
1594
1595        // 4 次尝试(初始 + 3 次重试)
1596        // will_retry: [true, true, true, false]
1597        let will_retry_values = callback.get_will_retry_values();
1598        assert_eq!(will_retry_values, vec![true, true, true, false]);
1599    }
1600
1601    // -------------------- Provider 调用次数测试 --------------------
1602
1603    #[tokio::test]
1604    async fn test_execute_step_with_retry_provider_call_count() {
1605        // 验证 Provider 被调用的次数
1606        let provider = RetryMockProvider::always_fail();
1607        let executor = SkillExecutor::new(provider);
1608        let step = WorkflowStep::new("step1", "测试步骤", "测试提示", "output");
1609        let callback = NoopCallback;
1610
1611        let _ = executor
1612            .execute_step_with_retry(&step, "测试提示", 2, 1, &callback)
1613            .await;
1614
1615        // 应该调用 3 次(初始 + 2 次重试)
1616        assert_eq!(executor.provider().call_count(), 3);
1617    }
1618
1619    #[tokio::test]
1620    async fn test_execute_step_with_retry_stops_on_success() {
1621        // 第二次成功,不应该继续重试
1622        let provider = RetryMockProvider::fail_then_succeed(1, "成功");
1623        let executor = SkillExecutor::new(provider);
1624        let step = WorkflowStep::new("step1", "测试步骤", "测试提示", "output");
1625        let callback = NoopCallback;
1626
1627        let _ = executor
1628            .execute_step_with_retry(&step, "测试提示", 5, 1, &callback)
1629            .await;
1630
1631        // 应该只调用 2 次(第一次失败,第二次成功)
1632        assert_eq!(executor.provider().call_count(), 2);
1633    }
1634
1635    // -------------------- 错误类型测试 --------------------
1636
1637    #[tokio::test]
1638    async fn test_execute_step_with_retry_returns_last_error() {
1639        let provider = RetryMockProvider::always_fail();
1640        let executor = SkillExecutor::new(provider);
1641        let step = WorkflowStep::new("step1", "测试步骤", "测试提示", "output");
1642        let callback = NoopCallback;
1643
1644        let result = executor
1645            .execute_step_with_retry(&step, "测试提示", 1, 1, &callback)
1646            .await;
1647
1648        assert!(result.is_err());
1649        let err = result.unwrap_err();
1650        // 应该是 ProviderError
1651        assert!(err.is_provider_error());
1652    }
1653
1654    // -------------------- 边界情况测试 --------------------
1655
1656    #[tokio::test]
1657    async fn test_execute_step_with_retry_empty_prompt() {
1658        let provider = MockProvider::new("响应");
1659        let executor = SkillExecutor::new(provider);
1660        let step = WorkflowStep::new("step1", "测试步骤", "", "output");
1661        let callback = NoopCallback;
1662
1663        let result = executor
1664            .execute_step_with_retry(&step, "", 2, 1, &callback)
1665            .await;
1666
1667        assert!(result.is_ok());
1668    }
1669
1670    #[tokio::test]
1671    async fn test_execute_step_with_retry_unicode_content() {
1672        let provider = MockProvider::new("中文响应 🎉");
1673        let executor = SkillExecutor::new(provider);
1674        let step = WorkflowStep::new("步骤1", "中文步骤名", "中文提示", "输出");
1675        let callback = NoopCallback;
1676
1677        let result = executor
1678            .execute_step_with_retry(&step, "中文提示 🚀", 2, 1, &callback)
1679            .await;
1680
1681        assert!(result.is_ok());
1682        assert_eq!(result.unwrap(), "中文响应 🎉");
1683    }
1684
1685    #[tokio::test]
1686    async fn test_execute_step_with_retry_large_max_retries() {
1687        // 测试大的 max_retries 值
1688        let provider = RetryMockProvider::fail_then_succeed(5, "成功");
1689        let executor = SkillExecutor::new(provider);
1690        let step = WorkflowStep::new("step1", "测试步骤", "测试提示", "output");
1691        let callback = NoopCallback;
1692
1693        let result = executor
1694            .execute_step_with_retry(&step, "测试提示", 10, 1, &callback)
1695            .await;
1696
1697        assert!(result.is_ok());
1698        // 应该调用 6 次(5 次失败 + 1 次成功)
1699        assert_eq!(executor.provider().call_count(), 6);
1700    }
1701
1702    // ==================== Workflow 模式执行测试 ====================
1703
1704    // -------------------- 基本功能测试 --------------------
1705
1706    #[tokio::test]
1707    async fn test_workflow_mode_single_step_success() {
1708        let provider = MockProvider::new("步骤输出");
1709        let executor = SkillExecutor::new(provider);
1710        let mut skill = create_test_skill(SkillExecutionMode::Workflow);
1711        skill.workflow = Some(WorkflowDefinition::new(vec![WorkflowStep::new(
1712            "step1",
1713            "唯一步骤",
1714            "处理 ${user_input}",
1715            "result",
1716        )]));
1717
1718        let result = executor.execute(&skill, "用户输入", None).await;
1719
1720        assert!(result.is_ok());
1721        let result = result.unwrap();
1722        assert!(result.success);
1723        assert_eq!(result.output, Some("步骤输出".to_string()));
1724        assert_eq!(result.steps_completed.len(), 1);
1725        assert_eq!(result.steps_completed[0].step_id, "step1");
1726        assert!(result.steps_completed[0].success);
1727    }
1728
1729    #[tokio::test]
1730    async fn test_workflow_mode_multiple_steps_success() {
1731        let provider = MockProvider::new("响应");
1732        let executor = SkillExecutor::new(provider);
1733        let skill = create_workflow_skill();
1734
1735        let result = executor.execute(&skill, "测试输入", None).await;
1736
1737        assert!(result.is_ok());
1738        let result = result.unwrap();
1739        assert!(result.success);
1740        assert_eq!(result.steps_completed.len(), 2);
1741        // 验证步骤顺序(step1 应该在 step2 之前)
1742        assert_eq!(result.steps_completed[0].step_id, "step1");
1743        assert_eq!(result.steps_completed[1].step_id, "step2");
1744    }
1745
1746    #[tokio::test]
1747    async fn test_workflow_mode_with_callback() {
1748        let provider = MockProvider::new("响应");
1749        let executor = SkillExecutor::new(provider);
1750        let skill = create_workflow_skill();
1751        let callback = MockCallback::new();
1752
1753        let result = executor.execute(&skill, "输入", Some(&callback)).await;
1754
1755        assert!(result.is_ok());
1756        // 应该有 2 次 step_start(每个步骤一次)
1757        assert_eq!(callback.step_start_count.load(Ordering::SeqCst), 2);
1758        // 应该有 2 次 step_complete
1759        assert_eq!(callback.step_complete_count.load(Ordering::SeqCst), 2);
1760        // 应该有 1 次 complete
1761        assert_eq!(callback.complete_count.load(Ordering::SeqCst), 1);
1762        // 没有错误
1763        assert_eq!(callback.step_error_count.load(Ordering::SeqCst), 0);
1764    }
1765
1766    // -------------------- 变量插值测试 --------------------
1767
1768    /// 记录接收到的提示词的 Mock Provider
1769    struct PromptRecordingProvider {
1770        prompts: std::sync::Mutex<Vec<String>>,
1771        response: String,
1772    }
1773
1774    impl PromptRecordingProvider {
1775        fn new(response: &str) -> Self {
1776            Self {
1777                prompts: std::sync::Mutex::new(Vec::new()),
1778                response: response.to_string(),
1779            }
1780        }
1781
1782        fn get_prompts(&self) -> Vec<String> {
1783            self.prompts.lock().unwrap().clone()
1784        }
1785    }
1786
1787    #[async_trait]
1788    impl LlmProvider for PromptRecordingProvider {
1789        async fn chat(
1790            &self,
1791            _system_prompt: &str,
1792            user_message: &str,
1793            _model: Option<&str>,
1794        ) -> Result<String, SkillError> {
1795            self.prompts.lock().unwrap().push(user_message.to_string());
1796            Ok(self.response.clone())
1797        }
1798    }
1799
1800    #[tokio::test]
1801    async fn test_workflow_mode_variable_interpolation_user_input() {
1802        let provider = PromptRecordingProvider::new("响应");
1803        let executor = SkillExecutor::new(provider);
1804        let mut skill = create_test_skill(SkillExecutionMode::Workflow);
1805        skill.workflow = Some(WorkflowDefinition::new(vec![WorkflowStep::new(
1806            "step1",
1807            "步骤一",
1808            "处理用户输入: ${user_input}",
1809            "result",
1810        )]));
1811
1812        let _ = executor.execute(&skill, "Hello World", None).await;
1813
1814        let prompts = executor.provider().get_prompts();
1815        assert_eq!(prompts.len(), 1);
1816        assert_eq!(prompts[0], "处理用户输入: Hello World");
1817    }
1818
1819    #[tokio::test]
1820    async fn test_workflow_mode_variable_interpolation_step_output() {
1821        let provider = PromptRecordingProvider::new("步骤输出");
1822        let executor = SkillExecutor::new(provider);
1823        let mut skill = create_test_skill(SkillExecutionMode::Workflow);
1824        skill.workflow = Some(WorkflowDefinition::new(vec![
1825            WorkflowStep::new("step1", "步骤一", "第一步", "result1"),
1826            WorkflowStep::new("step2", "步骤二", "基于 ${result1} 继续", "result2")
1827                .with_dependency("step1"),
1828        ]));
1829
1830        let _ = executor.execute(&skill, "输入", None).await;
1831
1832        let prompts = executor.provider().get_prompts();
1833        assert_eq!(prompts.len(), 2);
1834        assert_eq!(prompts[0], "第一步");
1835        // 第二步应该使用第一步的输出进行插值
1836        assert_eq!(prompts[1], "基于 步骤输出 继续");
1837    }
1838
1839    // -------------------- continue_on_failure 测试 --------------------
1840
1841    #[tokio::test]
1842    async fn test_workflow_mode_continue_on_failure_false_aborts() {
1843        let provider = RetryMockProvider::always_fail();
1844        let executor = SkillExecutor::new(provider);
1845        let mut skill = create_test_skill(SkillExecutionMode::Workflow);
1846        let mut workflow = WorkflowDefinition::new(vec![
1847            WorkflowStep::new("step1", "步骤一", "第一步", "result1"),
1848            WorkflowStep::new("step2", "步骤二", "第二步", "result2").with_dependency("step1"),
1849        ]);
1850        workflow.continue_on_failure = false;
1851        workflow.max_retries = 0; // 不重试,立即失败
1852        skill.workflow = Some(workflow);
1853
1854        let result = executor.execute(&skill, "输入", None).await;
1855
1856        assert!(result.is_ok());
1857        let result = result.unwrap();
1858        assert!(!result.success);
1859        // 只有第一个步骤被执行(失败)
1860        assert_eq!(result.steps_completed.len(), 1);
1861        assert!(!result.steps_completed[0].success);
1862        // 错误信息应该包含步骤 ID
1863        assert!(result.error.unwrap().contains("step1"));
1864    }
1865
1866    #[tokio::test]
1867    async fn test_workflow_mode_continue_on_failure_true_continues() {
1868        let provider = RetryMockProvider::always_fail();
1869        let executor = SkillExecutor::new(provider);
1870        let mut skill = create_test_skill(SkillExecutionMode::Workflow);
1871        let mut workflow = WorkflowDefinition::new(vec![
1872            WorkflowStep::new("step1", "步骤一", "第一步", "result1"),
1873            WorkflowStep::new("step2", "步骤二", "第二步", "result2"),
1874        ]);
1875        workflow.continue_on_failure = true;
1876        workflow.max_retries = 0; // 不重试
1877        skill.workflow = Some(workflow);
1878
1879        let result = executor.execute(&skill, "输入", None).await;
1880
1881        assert!(result.is_ok());
1882        let result = result.unwrap();
1883        // 虽然有失败,但因为 continue_on_failure=true,所以继续执行
1884        assert!(!result.success); // 整体失败
1885                                  // 两个步骤都被执行了
1886        assert_eq!(result.steps_completed.len(), 2);
1887        assert!(!result.steps_completed[0].success);
1888        assert!(!result.steps_completed[1].success);
1889    }
1890
1891    // -------------------- 拓扑排序错误测试 --------------------
1892
1893    #[tokio::test]
1894    async fn test_workflow_mode_cyclic_dependency_error() {
1895        let provider = MockProvider::new("响应");
1896        let executor = SkillExecutor::new(provider);
1897        let mut skill = create_test_skill(SkillExecutionMode::Workflow);
1898        skill.workflow = Some(WorkflowDefinition::new(vec![
1899            WorkflowStep::new("step1", "步骤一", "第一步", "result1").with_dependency("step2"),
1900            WorkflowStep::new("step2", "步骤二", "第二步", "result2").with_dependency("step1"),
1901        ]));
1902
1903        let result = executor.execute(&skill, "输入", None).await;
1904
1905        assert!(result.is_err());
1906        let err = result.unwrap_err();
1907        assert!(err.is_cyclic_dependency());
1908    }
1909
1910    #[tokio::test]
1911    async fn test_workflow_mode_missing_dependency_error() {
1912        let provider = MockProvider::new("响应");
1913        let executor = SkillExecutor::new(provider);
1914        let mut skill = create_test_skill(SkillExecutionMode::Workflow);
1915        skill.workflow = Some(WorkflowDefinition::new(vec![WorkflowStep::new(
1916            "step1",
1917            "步骤一",
1918            "第一步",
1919            "result1",
1920        )
1921        .with_dependency("nonexistent")]));
1922
1923        let result = executor.execute(&skill, "输入", None).await;
1924
1925        assert!(result.is_err());
1926        let err = result.unwrap_err();
1927        assert!(err.is_missing_dependency());
1928    }
1929
1930    // -------------------- 空工作流测试 --------------------
1931
1932    #[tokio::test]
1933    async fn test_workflow_mode_empty_steps() {
1934        let provider = MockProvider::new("响应");
1935        let executor = SkillExecutor::new(provider);
1936        let mut skill = create_test_skill(SkillExecutionMode::Workflow);
1937        skill.workflow = Some(WorkflowDefinition::new(vec![]));
1938
1939        let result = executor.execute(&skill, "输入", None).await;
1940
1941        assert!(result.is_ok());
1942        let result = result.unwrap();
1943        assert!(result.success);
1944        assert_eq!(result.steps_completed.len(), 0);
1945        assert!(result.output.is_none()); // 没有步骤,没有输出
1946    }
1947
1948    // -------------------- 元数据保留测试 --------------------
1949
1950    #[tokio::test]
1951    async fn test_workflow_mode_preserves_skill_metadata() {
1952        let provider = MockProvider::new("响应");
1953        let executor = SkillExecutor::new(provider);
1954        let skill = create_workflow_skill();
1955
1956        let result = executor.execute(&skill, "输入", None).await.unwrap();
1957
1958        assert_eq!(result.command_name, Some("test:test-skill".to_string()));
1959        assert_eq!(
1960            result.allowed_tools,
1961            Some(vec!["tool1".to_string(), "tool2".to_string()])
1962        );
1963        assert_eq!(result.model, Some("gpt-4".to_string()));
1964    }
1965}