executeStep 执行单个步骤
(ctx context.Context, plan *ExecutionPlan, step *Step, toolCtx *tools.ToolContext)
| 280 | |
| 281 | // executeStep 执行单个步骤 |
| 282 | func (e *Executor) executeStep(ctx context.Context, plan *ExecutionPlan, step *Step, toolCtx *tools.ToolContext) error { |
| 283 | // 获取工具 |
| 284 | tool, ok := e.tools[step.ToolName] |
| 285 | if !ok { |
| 286 | step.Status = StepStatusFailed |
| 287 | step.Error = "tool not found: " + step.ToolName |
| 288 | return fmt.Errorf("tool not found: %s", step.ToolName) |
| 289 | } |
| 290 | |
| 291 | // 标记步骤开始 |
| 292 | plan.MarkStepStarted(step.Index) |
| 293 | |
| 294 | // 触发步骤开始回调 |
| 295 | if e.onStepStart != nil { |
| 296 | e.onStepStart(plan, step) |
| 297 | } |
| 298 | |
| 299 | // 准备输入参数 |
| 300 | var inputParams map[string]any |
| 301 | if len(step.Parameters) > 0 { |
| 302 | inputParams = step.Parameters |
| 303 | } else if step.Input != "" { |
| 304 | // 尝试从 Input 字符串解析 JSON |
| 305 | inputParams = make(map[string]any) |
| 306 | if err := json.Unmarshal([]byte(step.Input), &inputParams); err != nil { |
| 307 | // 如果解析失败,将整个输入作为 "input" 参数 |
| 308 | inputParams["input"] = step.Input |
| 309 | } |
| 310 | } else { |
| 311 | inputParams = make(map[string]any) |
| 312 | } |
| 313 | |
| 314 | // 执行工具(带超时) |
| 315 | execCtx := ctx |
| 316 | if plan.Options != nil && plan.Options.StepTimeoutMs > 0 { |
| 317 | var cancel context.CancelFunc |
| 318 | execCtx, cancel = context.WithTimeout(ctx, time.Duration(plan.Options.StepTimeoutMs)*time.Millisecond) |
| 319 | defer cancel() |
| 320 | } |
| 321 | |
| 322 | // 重试逻辑 |
| 323 | var result any |
| 324 | var execErr error |
| 325 | maxRetries := max(step.MaxRetries, |
| 326 | // 默认不重试 |
| 327 | 0) |
| 328 | |
| 329 | retryLoop: |
| 330 | for attempt := 0; attempt <= maxRetries; attempt++ { |
| 331 | if attempt > 0 { |
| 332 | step.RetryCount = attempt |
| 333 | // 重试延迟 |
| 334 | if step.RetryDelayMs > 0 { |
| 335 | select { |
| 336 | case <-execCtx.Done(): |
| 337 | execErr = execCtx.Err() |
| 338 | break retryLoop |
| 339 | case <-time.After(time.Duration(step.RetryDelayMs) * time.Millisecond): |
no test coverage detected