pm-orchestrator-enhancement
Version:
PM Orchestrator Enhancement - Multi-agent parallel execution system
229 lines • 8.52 kB
JavaScript
;
/**
* Workflow Manager
*
* ワークフロー設定ファイルの読み込み、検証、条件分岐ロジックを提供します。
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.WorkflowManager = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const yaml = __importStar(require("js-yaml"));
class WorkflowManager {
constructor(configPath) {
this.workflows = new Map();
this.configPath = configPath || path.join(__dirname, '../../workflows');
}
/**
* ワークフロー設定ファイルを読み込む
*/
async loadWorkflows() {
this.workflows.clear();
// YAMLファイルを読み込む
const yamlFiles = fs.readdirSync(this.configPath).filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
for (const file of yamlFiles) {
await this.loadYamlFile(path.join(this.configPath, file));
}
// JSONファイルを読み込む
const jsonFiles = fs.readdirSync(this.configPath).filter(f => f.endsWith('.json'));
for (const file of jsonFiles) {
await this.loadJsonFile(path.join(this.configPath, file));
}
}
/**
* YAMLファイルを読み込む
*/
async loadYamlFile(filePath) {
const content = fs.readFileSync(filePath, 'utf8');
const workflows = yaml.load(content);
for (const workflow of workflows) {
this.validateWorkflow(workflow);
this.workflows.set(workflow.pattern, workflow);
}
}
/**
* JSONファイルを読み込む
*/
async loadJsonFile(filePath) {
const content = fs.readFileSync(filePath, 'utf8');
const workflows = JSON.parse(content);
for (const workflow of workflows) {
this.validateWorkflow(workflow);
this.workflows.set(workflow.pattern, workflow);
}
}
/**
* ワークフロー設定を検証する
*/
validateWorkflow(workflow) {
if (!workflow.name || !workflow.pattern) {
throw new Error(`Invalid workflow: name and pattern are required`);
}
if (!workflow.subagents || workflow.subagents.length === 0) {
throw new Error(`Invalid workflow ${workflow.name}: at least one subagent is required`);
}
// 依存関係の検証
const subagentNames = new Set(workflow.subagents.map(s => s.name));
for (const subagent of workflow.subagents) {
if (subagent.dependsOn) {
for (const dep of subagent.dependsOn) {
if (!subagentNames.has(dep)) {
throw new Error(`Invalid workflow ${workflow.name}: subagent ${subagent.name} depends on non-existent subagent ${dep}`);
}
}
}
}
// 循環依存の検証
this.detectCircularDependency(workflow);
}
/**
* 循環依存を検出する
*/
detectCircularDependency(workflow) {
const visited = new Set();
const stack = new Set();
const visit = (name) => {
if (stack.has(name)) {
throw new Error(`Circular dependency detected in workflow ${workflow.name}: ${name}`);
}
if (visited.has(name)) {
return;
}
stack.add(name);
visited.add(name);
const subagent = workflow.subagents.find(s => s.name === name);
if (subagent?.dependsOn) {
for (const dep of subagent.dependsOn) {
visit(dep);
}
}
stack.delete(name);
};
for (const subagent of workflow.subagents) {
visit(subagent.name);
}
}
/**
* パターンに一致するワークフローを取得する
*/
getWorkflow(pattern) {
return this.workflows.get(pattern);
}
/**
* タスク入力からワークフローを選択する
*/
selectWorkflow(userInput, detectedPattern) {
// 検出されたパターンに基づいて選択
if (detectedPattern) {
const workflow = this.getWorkflow(detectedPattern);
if (workflow) {
return workflow;
}
}
// パターンマッチングによる選択
for (const [pattern, workflow] of this.workflows.entries()) {
if (this.matchesPattern(userInput, pattern)) {
return workflow;
}
}
return undefined;
}
/**
* パターンマッチング
*/
matchesPattern(userInput, pattern) {
const lowerInput = userInput.toLowerCase();
// パターンごとのキーワードマッチング
const patternKeywords = {
PR_REVIEW_RESPONSE: ['pr', 'pull request', 'review', 'coderabbit'],
LIST_MODIFICATION: ['version', 'update', '箇所', 'すべて', '全て'],
COMPLEX_IMPLEMENTATION: ['実装', 'implement', 'feature', '機能'],
QUALITY_CHECK: ['test', 'lint', 'typecheck', 'build', 'quality'],
CODERABBIT_RESOLVE: ['coderabbit', 'resolve', '解決'],
SECURITY_REVIEW: ['security', 'セキュリティ', '脆弱性', 'vulnerability']
};
const keywords = patternKeywords[pattern] || [];
return keywords.some(keyword => lowerInput.includes(keyword));
}
/**
* 実行順序を決定する
*/
determineExecutionOrder(workflow) {
const subagents = workflow.subagents;
const levels = [];
const completed = new Set();
while (completed.size < subagents.length) {
const currentLevel = [];
for (const subagent of subagents) {
if (completed.has(subagent.name)) {
continue;
}
// 依存関係がすべて満たされているかチェック
const allDependenciesMet = !subagent.dependsOn || subagent.dependsOn.every(dep => completed.has(dep));
if (allDependenciesMet) {
currentLevel.push(subagent.name);
}
}
if (currentLevel.length === 0) {
throw new Error(`Cannot determine execution order for workflow ${workflow.name}`);
}
levels.push(currentLevel);
currentLevel.forEach(name => completed.add(name));
}
return levels;
}
/**
* 全ワークフロー設定を取得する
*/
getAllWorkflows() {
return Array.from(this.workflows.values());
}
/**
* ワークフロー設定を追加する
*/
addWorkflow(workflow) {
this.validateWorkflow(workflow);
this.workflows.set(workflow.pattern, workflow);
}
/**
* ワークフロー設定を削除する
*/
removeWorkflow(pattern) {
return this.workflows.delete(pattern);
}
}
exports.WorkflowManager = WorkflowManager;
//# sourceMappingURL=workflow-manager.js.map