UNPKG

@every-env/cli

Version:

Multi-agent orchestrator for AI-powered development workflows

93 lines 4.19 kB
import { FilePatternMatcher } from "./file-pattern.js"; import { ContentPatternMatcher } from "./content-pattern.js"; const ESSENTIAL_TOOLS = ["Read", "Write", "Edit", "Glob"]; function uniq(arr) { return Array.from(new Set(arr)); } export class PatternManager { findPatterns(config, patternNames) { const patterns = config.patterns || config.docs?.patterns || []; if (!patternNames || patternNames.length === 0) return patterns; return patterns.filter((p) => patternNames.includes(p.name)); } validatePattern(pattern) { const errors = []; if (!pattern.name) errors.push("Pattern must have a name"); if (!pattern.agents || pattern.agents.length === 0) errors.push("Pattern must have agents"); for (const agent of pattern.agents || []) { if (!agent.id) errors.push(`Agent in pattern "${pattern.name}" must have an id`); if (!agent.promptFile) errors.push(`Agent "${agent.id ?? "unknown"}" must have a promptFile`); // Do not require output/outputPattern for dry-run or simple execution paths } return errors; } async prepareTasks(patterns, config, basePath = process.cwd()) { const tasks = []; const fileMatcher = new FilePatternMatcher(); const contentMatcher = new ContentPatternMatcher(); const defaultAllowed = config.defaultAllowedTools ?? []; for (const pattern of patterns) { this.validatePattern(pattern); // Non-blocking: proceed even if validation errors; validation is asserted separately in tests // Resolve file matches if any let fileMatches = []; if (pattern.match?.files && pattern.match.files.length > 0) { const fm = await fileMatcher.match({ files: pattern.match.files, exclude: pattern.match.exclude }, basePath); // Support mocks returning string[] or objects fileMatches = fm.map((v) => (typeof v === "string" ? v : (v.relativePath ?? v.path ?? v))); } // Resolve content matches if needed let contentMatches = []; if (pattern.match?.content && fileMatches.length > 0) { const cm = await contentMatcher.match(pattern.match.content, fileMatches); contentMatches = cm; } for (const agent of pattern.agents) { const mergedTools = uniq([...ESSENTIAL_TOOLS, ...defaultAllowed, ...(agent.allowedTools ?? [])]); const baseAgent = { id: agent.id, promptFile: agent.promptFile, output: agent.output, outputPattern: agent.outputPattern, allowedTools: mergedTools, workingDir: agent.workingDir, flags: agent.flags, command: agent.command, }; const forEach = agent.forEach; if (forEach === "match" || forEach === "file") { for (const f of fileMatches) { tasks.push({ agent: baseAgent, variables: { file: f }, }); } } else if (forEach === "content") { for (const m of contentMatches) { const caps = m?.captures; const spreadCaps = caps && typeof caps === "object" ? caps : {}; tasks.push({ agent: baseAgent, variables: { match: m.match, file: m.file, ...spreadCaps }, }); } } else { // Single task without iteration tasks.push({ agent: baseAgent, variables: {}, }); } } } return tasks; } } //# sourceMappingURL=pattern-manager.js.map