import { describe, it, expect } from 'vitest'; const { Scheduler } = require('../../core/scheduler'); describe('Scheduler', () => { describe('getExecutionGroups', () => { it('should return single group when no dependencies', () => { const agents = { coder: { type: 'executor' }, reviewer: { type: 'executor' } }; const calls = [ { agent: 'coder', task: 'task1' }, { agent: 'reviewer', task: 'task2' } ]; const groups = Scheduler.getExecutionGroups(agents, calls); expect(groups).toHaveLength(1); expect(groups[0]).toContain('coder'); expect(groups[0]).toContain('reviewer'); }); it('should separate dependent agents into different groups', () => { const agents = { coder: { type: 'executor' }, verifier: { type: 'validator', dependsOn: ['coder'] } }; const calls = [ { agent: 'coder', task: 'task1' }, { agent: 'verifier', task: 'task2' } ]; const groups = Scheduler.getExecutionGroups(agents, calls); expect(groups).toHaveLength(2); expect(groups[0]).toEqual(['coder']); expect(groups[1]).toEqual(['verifier']); }); it('should group agents with same dependencies together', () => { const agents = { coder: { type: 'executor' }, verifier: { type: 'validator', dependsOn: ['coder'] }, tester: { type: 'validator', dependsOn: ['coder'] } }; const calls = [ { agent: 'coder', task: 'task1' }, { agent: 'verifier', task: 'task2' }, { agent: 'tester', task: 'task3' } ]; const groups = Scheduler.getExecutionGroups(agents, calls); expect(groups).toHaveLength(2); expect(groups[0]).toEqual(['coder']); expect(groups[1]).toHaveLength(2); expect(groups[1]).toContain('verifier'); expect(groups[1]).toContain('tester'); }); it('should handle chain dependencies', () => { const agents = { a: { type: 'executor' }, b: { type: 'executor', dependsOn: ['a'] }, c: { type: 'executor', dependsOn: ['b'] } }; const calls = [ { agent: 'a', task: 't1' }, { agent: 'b', task: 't2' }, { agent: 'c', task: 't3' } ]; const groups = Scheduler.getExecutionGroups(agents, calls); expect(groups).toHaveLength(3); expect(groups[0]).toEqual(['a']); expect(groups[1]).toEqual(['b']); expect(groups[2]).toEqual(['c']); }); it('should throw on circular dependency', () => { const agents = { a: { type: 'executor', dependsOn: ['b'] }, b: { type: 'executor', dependsOn: ['a'] } }; const calls = [ { agent: 'a', task: 't1' }, { agent: 'b', task: 't2' } ]; expect(() => Scheduler.getExecutionGroups(agents, calls)) .toThrow('Circular dependency'); }); it('should return empty array when no calls', () => { const agents = { coder: { type: 'executor' } }; const calls = []; const groups = Scheduler.getExecutionGroups(agents, calls); expect(groups).toEqual([]); }); it('should only consider called agents dependencies', () => { const agents = { coder: { type: 'executor' }, verifier: { type: 'validator', dependsOn: ['coder'] }, tester: { type: 'validator', dependsOn: ['coder'] } }; // 只调用 verifier,不调用 coder const calls = [ { agent: 'verifier', task: 'task' } ]; const groups = Scheduler.getExecutionGroups(agents, calls); // verifier 依赖 coder,但 coder 不在调用列表中,应该直接执行 expect(groups).toHaveLength(1); expect(groups[0]).toEqual(['verifier']); }); it('should handle multiple dependencies', () => { const agents = { a: { type: 'executor' }, b: { type: 'executor' }, c: { type: 'executor', dependsOn: ['a', 'b'] } }; const calls = [ { agent: 'a', task: 't1' }, { agent: 'b', task: 't2' }, { agent: 'c', task: 't3' } ]; const groups = Scheduler.getExecutionGroups(agents, calls); expect(groups).toHaveLength(2); expect(groups[0]).toContain('a'); expect(groups[0]).toContain('b'); expect(groups[1]).toEqual(['c']); }); }); describe('isComplete', () => { it('should return true when all validators pass and executors done', () => { const agents = { coder: { type: 'executor' }, verifier: { type: 'validator' } }; const results = [ { agent: 'coder', status: 'DONE' }, { agent: 'verifier', status: 'PASS' } ]; expect(Scheduler.isComplete(agents, results)).toBe(true); }); it('should return false when any validator fails', () => { const agents = { coder: { type: 'executor' }, verifier: { type: 'validator' } }; const results = [ { agent: 'coder', status: 'DONE' }, { agent: 'verifier', status: 'FAIL' } ]; expect(Scheduler.isComplete(agents, results)).toBe(false); }); it('should return false when any executor errors', () => { const agents = { coder: { type: 'executor' } }; const results = [ { agent: 'coder', status: 'ERROR' } ]; expect(Scheduler.isComplete(agents, results)).toBe(false); }); it('should return true with empty results', () => { const agents = {}; const results = []; expect(Scheduler.isComplete(agents, results)).toBe(true); }); it('should handle mixed results correctly', () => { const agents = { coder: { type: 'executor' }, verifier: { type: 'validator' }, tester: { type: 'validator' } }; const results = [ { agent: 'coder', status: 'DONE' }, { agent: 'verifier', status: 'PASS' }, { agent: 'tester', status: 'FAIL' } ]; expect(Scheduler.isComplete(agents, results)).toBe(false); }); }); });