scheduler.js 2.43 KB
/**
 * Scheduler - 依赖分析和并行调度
 */
class Scheduler {
  /**
   * 根据依赖关系将 Agent 调用分组
   * 同一组内的 Agent 可以并行执行
   *
   * @param {Object} agents - Agent 配置 { name: { type, dependsOn } }
   * @param {Array<{agent: string, task: string}>} calls - 待执行的调用
   * @returns {Array<string[]>} - 执行组,每组可并行
   */
  static getExecutionGroups(agents, calls) {
    if (calls.length === 0) return [];

    const pending = new Set(calls.map(c => c.agent));
    const completed = new Set();
    const groups = [];

    while (pending.size > 0) {
      const ready = [];

      for (const name of pending) {
        const agent = agents[name] || {};
        const deps = agent.dependsOn || [];

        // 只检查在调用列表中的依赖
        const relevantDeps = deps.filter(d => calls.some(c => c.agent === d));
        const depsCompleted = relevantDeps.every(d => completed.has(d));

        if (depsCompleted) {
          ready.push(name);
        }
      }

      if (ready.length === 0) {
        throw new Error('Circular dependency detected');
      }

      groups.push(ready);

      for (const name of ready) {
        pending.delete(name);
        completed.add(name);
      }
    }

    return groups;
  }

  /**
   * 检查执行结果是否完成
   * - executor: 需要 DONE
   * - validator: 所有配置的 validator 都必须被调用且返回 PASS
   *
   * @param {Object} agents - Agent 配置
   * @param {Array<{agent: string, status: string}>} results - 执行结果
   * @returns {boolean}
   */
  static isComplete(agents, results) {
    // 获取所有配置的 validator
    const allValidators = Object.entries(agents)
      .filter(([_, cfg]) => cfg.type === 'validator')
      .map(([name]) => name);

    // 所有 validator 都必须有 PASS 结果
    const allValidatorsPass = allValidators.every(validatorName => {
      const result = results.find(r => r.agent === validatorName);
      return result && result.status === 'PASS';
    });

    if (!allValidatorsPass) return false;

    // 检查已调用的 executor/orchestrator 是否都返回 DONE
    const executorResults = results.filter(r => {
      const agent = agents[r.agent];
      return agent?.type === 'executor' || agent?.type === 'orchestrator';
    });

    const allExecutorsDone = executorResults.every(r => r.status === 'DONE');

    return allExecutorsDone;
  }
}

module.exports = { Scheduler };