swarm-orchestrator 7.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +15 -0
- package/README.md +199 -0
- package/agents/reviewer.agent.md +50 -0
- package/agents/worker.agent.md +41 -0
- package/config/default-agents.yaml +56 -0
- package/config/pm-agent.yaml +36 -0
- package/config/quality-gates.yaml +88 -0
- package/config/repair-agent.yaml +34 -0
- package/config/semgrep-rules/complexity-mismatch.yaml +6 -0
- package/config/semgrep-rules/exception-swallowing.yaml +13 -0
- package/config/semgrep-rules/hardcoded-answer.yaml +6 -0
- package/config/semgrep-rules/mock-mutation.yaml +6 -0
- package/config/semgrep-rules/test-modification.yaml +6 -0
- package/config/user-agents.yaml +23 -0
- package/dist/src/adapters/adapter-factory.js +29 -0
- package/dist/src/adapters/agent-adapter.js +32 -0
- package/dist/src/adapters/claude-code-adapter.js +126 -0
- package/dist/src/adapters/claude-code-teams.js +119 -0
- package/dist/src/adapters/codex-adapter.js +118 -0
- package/dist/src/adapters/copilot-adapter.js +224 -0
- package/dist/src/adapters/fatal-error-classifier.js +88 -0
- package/dist/src/adapters/index.js +44 -0
- package/dist/src/adapters/persistent-session.js +204 -0
- package/dist/src/adapters/process-supervisor.js +199 -0
- package/dist/src/agents-exporter.js +398 -0
- package/dist/src/analytics-log.js +161 -0
- package/dist/src/baseline-scanner.js +65 -0
- package/dist/src/bootstrap-evidence.js +88 -0
- package/dist/src/bootstrap-orchestrator.js +205 -0
- package/dist/src/bootstrap-types.js +5 -0
- package/dist/src/branch-merger.js +427 -0
- package/dist/src/cli/attest-handlers.js +44 -0
- package/dist/src/cli/cost-prompt.js +51 -0
- package/dist/src/cli/demo-handlers.js +274 -0
- package/dist/src/cli/flags.js +152 -0
- package/dist/src/cli/index.js +57 -0
- package/dist/src/cli/live-status.js +186 -0
- package/dist/src/cli/misc-handlers.js +242 -0
- package/dist/src/cli/plan-handlers.js +350 -0
- package/dist/src/cli/share-handlers.js +163 -0
- package/dist/src/cli/status-handlers.js +457 -0
- package/dist/src/cli/swarm-handlers.js +638 -0
- package/dist/src/cli/usage.js +72 -0
- package/dist/src/cli.js +217 -0
- package/dist/src/commit-pattern-detector.js +143 -0
- package/dist/src/commit-quality-analyzer.js +38 -0
- package/dist/src/config-loader.js +339 -0
- package/dist/src/context-broker.js +358 -0
- package/dist/src/copilot-cli-wrapper.js +258 -0
- package/dist/src/cost-estimator.js +241 -0
- package/dist/src/defaults.js +18 -0
- package/dist/src/demo-mode.js +180 -0
- package/dist/src/deployment-handler.js +78 -0
- package/dist/src/deployment-manager.js +228 -0
- package/dist/src/execution-queue.js +196 -0
- package/dist/src/external-tool-manager.js +184 -0
- package/dist/src/gate-prompt-builder.js +117 -0
- package/dist/src/gate-remediation.js +173 -0
- package/dist/src/github-issues-ingester.js +152 -0
- package/dist/src/github-mcp-integrator.js +164 -0
- package/dist/src/hook-generator.js +229 -0
- package/dist/src/index.js +48 -0
- package/dist/src/knowledge-base.js +300 -0
- package/dist/src/logger.js +111 -0
- package/dist/src/meta-analyzer.js +208 -0
- package/dist/src/metrics-collector.js +209 -0
- package/dist/src/metrics-types.js +5 -0
- package/dist/src/multi-repo-coordinator.js +179 -0
- package/dist/src/orchestrator/async-meta-analysis.js +84 -0
- package/dist/src/orchestrator/fatal-run-error.js +43 -0
- package/dist/src/orchestrator/final-gates-remediation.js +258 -0
- package/dist/src/orchestrator/git-state-utils.js +119 -0
- package/dist/src/orchestrator/pause-controller.js +55 -0
- package/dist/src/orchestrator/replan-runner.js +258 -0
- package/dist/src/orchestrator/step-executor.js +391 -0
- package/dist/src/orchestrator/wave-scheduler-loop.js +204 -0
- package/dist/src/owasp-mapper.js +153 -0
- package/dist/src/owasp-report-renderer.js +39 -0
- package/dist/src/plan-files.js +142 -0
- package/dist/src/plan-generator.js +1207 -0
- package/dist/src/pm-agent.js +296 -0
- package/dist/src/post-run-reporter.js +203 -0
- package/dist/src/pr-automation.js +103 -0
- package/dist/src/pr-manager.js +318 -0
- package/dist/src/presenter/index.js +209 -0
- package/dist/src/prompt-builder.js +173 -0
- package/dist/src/quality-gates/config-loader.js +196 -0
- package/dist/src/quality-gates/default-config.js +243 -0
- package/dist/src/quality-gates/file-utils.js +152 -0
- package/dist/src/quality-gates/gate-runner.js +171 -0
- package/dist/src/quality-gates/gates/accessibility.js +355 -0
- package/dist/src/quality-gates/gates/duplicate-blocks.js +144 -0
- package/dist/src/quality-gates/gates/hardcoded-config.js +52 -0
- package/dist/src/quality-gates/gates/readme-claims.js +62 -0
- package/dist/src/quality-gates/gates/runtime-checks.js +265 -0
- package/dist/src/quality-gates/gates/scaffold-defaults.js +108 -0
- package/dist/src/quality-gates/gates/test-coverage.js +240 -0
- package/dist/src/quality-gates/gates/test-file-protection.js +85 -0
- package/dist/src/quality-gates/gates/test-isolation.js +74 -0
- package/dist/src/quality-gates/index.js +17 -0
- package/dist/src/quality-gates/registry.js +205 -0
- package/dist/src/quality-gates/types.js +2 -0
- package/dist/src/quick-fix-mode.js +302 -0
- package/dist/src/recipe-loader.js +122 -0
- package/dist/src/repair-agent.js +396 -0
- package/dist/src/repo-analyzer.js +342 -0
- package/dist/src/report-generator.js +146 -0
- package/dist/src/report-renderer.js +90 -0
- package/dist/src/requirement-filter.js +52 -0
- package/dist/src/sarif-formatter.js +140 -0
- package/dist/src/scheduling/dependency-analyzer.js +178 -0
- package/dist/src/scheduling/work-stealing-queue.js +123 -0
- package/dist/src/secret-redactor.js +90 -0
- package/dist/src/session-executor.js +587 -0
- package/dist/src/session-manager.js +221 -0
- package/dist/src/share/transcript-verification.js +128 -0
- package/dist/src/share-parser.js +477 -0
- package/dist/src/spinner.js +146 -0
- package/dist/src/step-runner.js +365 -0
- package/dist/src/swarm-orchestrator.js +686 -0
- package/dist/src/task-classifier.js +134 -0
- package/dist/src/test-command-discovery.js +123 -0
- package/dist/src/text-similarity.js +24 -0
- package/dist/src/tier-maps.js +158 -0
- package/dist/src/types.js +5 -0
- package/dist/src/url-shortener.js +135 -0
- package/dist/src/verification/attestation.js +166 -0
- package/dist/src/verification/cheat-detector.js +240 -0
- package/dist/src/verification/command-runner.js +70 -0
- package/dist/src/verification/composite-score.js +157 -0
- package/dist/src/verification/cosign-attestation.js +137 -0
- package/dist/src/verification/diff-analysis.js +89 -0
- package/dist/src/verification/differential-gate.js +173 -0
- package/dist/src/verification/index.js +41 -0
- package/dist/src/verification/mutation-gate.js +242 -0
- package/dist/src/verification/property-gate.js +201 -0
- package/dist/src/verification/test-synthesizer.js +243 -0
- package/dist/src/verifier/outcome-checks.js +396 -0
- package/dist/src/verifier/transcript-checks.js +207 -0
- package/dist/src/verifier/verification-reporters.js +148 -0
- package/dist/src/verifier-engine.js +491 -0
- package/dist/src/wave-resizer.js +131 -0
- package/dist/src/wave-scheduler.js +44 -0
- package/dist/src/worktree-manager.js +368 -0
- package/dist/src/worktree-reserved-paths.js +97 -0
- package/package.json +80 -0
- package/plugin/agents/.gitkeep +0 -0
- package/plugin/agents/backend_master.agent.md +72 -0
- package/plugin/agents/devops_pro.agent.md +45 -0
- package/plugin/agents/frontend_expert.agent.md +59 -0
- package/plugin/agents/integrator_finalizer.agent.md +44 -0
- package/plugin/agents/meta_reviewer.agent.md +44 -0
- package/plugin/agents/security_auditor.agent.md +43 -0
- package/plugin/agents/tester_elite.agent.md +43 -0
- package/plugin/hooks/hooks.json +19 -0
- package/plugin/hooks/post-tool-use.json +9 -0
- package/plugin/hooks/pre-tool-use.json +9 -0
- package/plugin/plugin.json +47 -0
- package/plugin/skills/swarm-gates/SKILL.md +53 -0
- package/plugin/skills/swarm-orchestrate/SKILL.md +34 -0
- package/plugin/skills/swarm-verify/SKILL.md +44 -0
- package/templates/README.md +35 -0
- package/templates/cli-tool.json +31 -0
- package/templates/fullstack.json +52 -0
- package/templates/library.json +38 -0
- package/templates/react-app.json +45 -0
- package/templates/recipes/add-api-docs.json +35 -0
- package/templates/recipes/add-auth.json +47 -0
- package/templates/recipes/add-ci.json +39 -0
- package/templates/recipes/add-tests.json +39 -0
- package/templates/recipes/migrate-to-ts.json +42 -0
- package/templates/recipes/refactor-modularize.json +44 -0
- package/templates/recipes/security-audit.json +35 -0
- package/templates/rest-api.json +38 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Miscellaneous CLI command handlers extracted from cli-handlers.ts.
|
|
4
|
+
* Covers recipes, recipe-info, agents export, and the `use` command.
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
40
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.handleUseCommand = handleUseCommand;
|
|
44
|
+
exports.handleRecipesCommand = handleRecipesCommand;
|
|
45
|
+
exports.handleRecipeInfoCommand = handleRecipeInfoCommand;
|
|
46
|
+
exports.handleAgentsCommand = handleAgentsCommand;
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
const plan_files_1 = require("../plan-files");
|
|
49
|
+
const recipe_loader_1 = require("../recipe-loader");
|
|
50
|
+
const agents_exporter_1 = __importDefault(require("../agents-exporter"));
|
|
51
|
+
const flags_1 = require("./flags");
|
|
52
|
+
const logger_1 = require("../logger");
|
|
53
|
+
const logger = (0, logger_1.getLogger)('cli:misc');
|
|
54
|
+
const swarm_handlers_1 = require("./swarm-handlers");
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// recipe command handlers
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
async function handleUseCommand(args) {
|
|
59
|
+
const recipeName = args[1];
|
|
60
|
+
if (!recipeName) {
|
|
61
|
+
logger.error('Error: recipe name required\nUsage: swarm use <recipe> [--param key=value ...]');
|
|
62
|
+
return 1;
|
|
63
|
+
}
|
|
64
|
+
let recipe;
|
|
65
|
+
try {
|
|
66
|
+
recipe = (0, recipe_loader_1.loadRecipe)(recipeName);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
logger.error(error instanceof Error ? error.message : String(error));
|
|
70
|
+
return 1;
|
|
71
|
+
}
|
|
72
|
+
// Parse --param key=value pairs from remaining args
|
|
73
|
+
const userParams = {};
|
|
74
|
+
for (let i = 2; i < args.length; i++) {
|
|
75
|
+
if (args[i] === '--param' && args[i + 1]) {
|
|
76
|
+
const eq = args[i + 1].indexOf('=');
|
|
77
|
+
if (eq === -1) {
|
|
78
|
+
logger.error(`Invalid parameter format: "${args[i + 1]}". Expected key=value`);
|
|
79
|
+
return 1;
|
|
80
|
+
}
|
|
81
|
+
const key = args[i + 1].substring(0, eq);
|
|
82
|
+
const value = args[i + 1].substring(eq + 1);
|
|
83
|
+
userParams[key] = value;
|
|
84
|
+
i++; // skip the value token
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
let plan;
|
|
88
|
+
try {
|
|
89
|
+
plan = (0, recipe_loader_1.parameterizeRecipe)(recipe, userParams);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
logger.error(error instanceof Error ? error.message : String(error));
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
logger.info(`🐝 Recipe: ${recipe.name}\n`);
|
|
96
|
+
logger.info(` ${recipe.description}`);
|
|
97
|
+
logger.info(` Category: ${recipe.category}`);
|
|
98
|
+
logger.info(` Steps: ${plan.steps.length}\n`);
|
|
99
|
+
plan.steps.forEach(step => {
|
|
100
|
+
logger.info(` Step ${step.stepNumber}: ${step.task.substring(0, 80)}${step.task.length > 80 ? '...' : ''}`);
|
|
101
|
+
});
|
|
102
|
+
logger.info('');
|
|
103
|
+
// Save the parameterized plan, then delegate to executeSwarm
|
|
104
|
+
const planPath = (0, plan_files_1.savePlanFile)(plan, `recipe-${recipeName}-${Date.now()}.json`);
|
|
105
|
+
logger.info(`Plan saved: ${planPath}\n`);
|
|
106
|
+
try {
|
|
107
|
+
const options = (0, flags_1.parseSwarmFlags)(args);
|
|
108
|
+
const exitCode = await (0, swarm_handlers_1.executeSwarm)(path.basename(planPath), options);
|
|
109
|
+
// Record recipe run in knowledge base after execution
|
|
110
|
+
try {
|
|
111
|
+
const { KnowledgeBaseManager } = await Promise.resolve().then(() => __importStar(require('../knowledge-base')));
|
|
112
|
+
const kb = new KnowledgeBaseManager();
|
|
113
|
+
kb.recordRecipeRun({
|
|
114
|
+
recipe: recipeName,
|
|
115
|
+
parameters: userParams,
|
|
116
|
+
tool: options.cliAgent || 'copilot',
|
|
117
|
+
passed: exitCode === 0,
|
|
118
|
+
duration: 0,
|
|
119
|
+
stepsCompleted: plan.steps.length,
|
|
120
|
+
totalSteps: plan.steps.length,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Knowledge base recording is non-critical
|
|
125
|
+
}
|
|
126
|
+
return exitCode;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
logger.error('Error executing recipe:', error instanceof Error ? error.message : error);
|
|
130
|
+
return 1;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function handleRecipesCommand() {
|
|
134
|
+
const recipes = (0, recipe_loader_1.listRecipeDetails)();
|
|
135
|
+
if (recipes.length === 0) {
|
|
136
|
+
logger.info('No recipes found.');
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
logger.info('\n╔══════════════════════════════════════════════════════════════════════╗');
|
|
140
|
+
logger.info('║ Available Recipes ║');
|
|
141
|
+
logger.info('╚══════════════════════════════════════════════════════════════════════╝\n');
|
|
142
|
+
for (const recipe of recipes) {
|
|
143
|
+
logger.info(` ${recipe.name}`);
|
|
144
|
+
logger.info(` ${recipe.description}`);
|
|
145
|
+
logger.info(` Category: ${recipe.category} | Steps: ${recipe.steps.length}`);
|
|
146
|
+
const paramNames = Object.keys(recipe.parameters);
|
|
147
|
+
if (paramNames.length > 0) {
|
|
148
|
+
logger.info(` Parameters: ${paramNames.join(', ')}`);
|
|
149
|
+
}
|
|
150
|
+
logger.info('');
|
|
151
|
+
}
|
|
152
|
+
logger.info('Usage: swarm use <recipe> [--param key=value ...]\n');
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
function handleRecipeInfoCommand(args) {
|
|
156
|
+
const recipeName = args[1];
|
|
157
|
+
if (!recipeName) {
|
|
158
|
+
logger.error('Error: recipe name required\nUsage: swarm recipe-info <name>');
|
|
159
|
+
return 1;
|
|
160
|
+
}
|
|
161
|
+
let recipe;
|
|
162
|
+
try {
|
|
163
|
+
recipe = (0, recipe_loader_1.loadRecipe)(recipeName);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
logger.error(error instanceof Error ? error.message : String(error));
|
|
167
|
+
return 1;
|
|
168
|
+
}
|
|
169
|
+
logger.info(`\nRecipe: ${recipe.name}`);
|
|
170
|
+
logger.info(`Description: ${recipe.description}`);
|
|
171
|
+
logger.info(`Category: ${recipe.category}\n`);
|
|
172
|
+
logger.info('Parameters:');
|
|
173
|
+
for (const [key, param] of Object.entries(recipe.parameters)) {
|
|
174
|
+
const defaultStr = param.default !== undefined ? ` (default: ${param.default})` : ' (required)';
|
|
175
|
+
const optionsStr = param.options ? ` [${param.options.join(' | ')}]` : '';
|
|
176
|
+
logger.info(` --param ${key}=<value> ${param.description}${defaultStr}${optionsStr}`);
|
|
177
|
+
}
|
|
178
|
+
logger.info('');
|
|
179
|
+
logger.info('Steps:');
|
|
180
|
+
for (const step of recipe.steps) {
|
|
181
|
+
const deps = step.dependencies.length > 0 ? ` (after step ${step.dependencies.join(', ')})` : '';
|
|
182
|
+
logger.info(` ${step.stepNumber}. [${step.agentName}] ${step.task.substring(0, 70)}${step.task.length > 70 ? '...' : ''}${deps}`);
|
|
183
|
+
}
|
|
184
|
+
logger.info('');
|
|
185
|
+
return 0;
|
|
186
|
+
}
|
|
187
|
+
// ---------------------------------------------------------------------------
|
|
188
|
+
// agents command handler
|
|
189
|
+
// ---------------------------------------------------------------------------
|
|
190
|
+
async function handleAgentsCommand(args) {
|
|
191
|
+
const subcommand = args[1];
|
|
192
|
+
if (subcommand !== 'export') {
|
|
193
|
+
logger.error('Usage: swarm agents export [--output-dir dir] [--min-runs N] [--diff]');
|
|
194
|
+
return 1;
|
|
195
|
+
}
|
|
196
|
+
// Parse flags
|
|
197
|
+
const outputDirIdx = args.indexOf('--output-dir');
|
|
198
|
+
const outputDir = outputDirIdx !== -1 && args[outputDirIdx + 1]
|
|
199
|
+
? args[outputDirIdx + 1]
|
|
200
|
+
: path.join(process.cwd(), 'agents');
|
|
201
|
+
const minRunsIdx = args.indexOf('--min-runs');
|
|
202
|
+
let minRuns = 5;
|
|
203
|
+
if (minRunsIdx !== -1 && args[minRunsIdx + 1]) {
|
|
204
|
+
const parsed = parseInt(args[minRunsIdx + 1], 10);
|
|
205
|
+
if (!isNaN(parsed) && parsed > 0)
|
|
206
|
+
minRuns = parsed;
|
|
207
|
+
}
|
|
208
|
+
const diff = args.includes('--diff');
|
|
209
|
+
logger.info('🐝 Swarm Orchestrator - Agent Export\n');
|
|
210
|
+
logger.info(`Output directory: ${outputDir}`);
|
|
211
|
+
logger.info(`Minimum runs for data-driven export: ${minRuns}`);
|
|
212
|
+
if (diff)
|
|
213
|
+
logger.info('Diff mode: enabled\n');
|
|
214
|
+
else
|
|
215
|
+
logger.info('');
|
|
216
|
+
const exporter = new agents_exporter_1.default();
|
|
217
|
+
const result = exporter.export({ outputDir, minRuns, diff });
|
|
218
|
+
if (result.fromData) {
|
|
219
|
+
logger.info(`Exported ${result.agentsExported.length} agent(s) with data-driven recommendations.`);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
logger.info(`Exported ${result.agentsExported.length} agent(s) from base definitions (insufficient run data).`);
|
|
223
|
+
}
|
|
224
|
+
for (const name of result.agentsExported) {
|
|
225
|
+
const filename = name.toLowerCase().replace(/[^a-z0-9]+/g, '_') + '.agent.md';
|
|
226
|
+
logger.info(` - ${filename}`);
|
|
227
|
+
}
|
|
228
|
+
if (diff && result.diffs.length > 0) {
|
|
229
|
+
logger.info(`\nChanges detected (${result.diffs.length} diff(s)):`);
|
|
230
|
+
for (const d of result.diffs) {
|
|
231
|
+
logger.info(` ${d.agentName} / ${d.field}:`);
|
|
232
|
+
if (d.previous)
|
|
233
|
+
logger.info(` - ${d.previous.slice(0, 100)}`);
|
|
234
|
+
logger.info(` + ${d.current.slice(0, 100)}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else if (diff) {
|
|
238
|
+
logger.info('\nNo changes detected since last export.');
|
|
239
|
+
}
|
|
240
|
+
logger.info(`\nAgent files written to: ${outputDir}`);
|
|
241
|
+
return 0;
|
|
242
|
+
}
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Plan-related CLI command handlers extracted from cli-handlers.ts.
|
|
4
|
+
* Each handler validates its arguments, performs the work, and returns an
|
|
5
|
+
* exit code (0 = success, 1 = failure). No handler calls process.exit.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.generatePlan = generatePlan;
|
|
42
|
+
exports.importPlanFromTranscript = importPlanFromTranscript;
|
|
43
|
+
exports.executePlan = executePlan;
|
|
44
|
+
exports.handlePlanCommand = handlePlanCommand;
|
|
45
|
+
exports.handleExecuteCommand = handleExecuteCommand;
|
|
46
|
+
const fs = __importStar(require("fs"));
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
const config_loader_1 = require("../config-loader");
|
|
49
|
+
const plan_generator_1 = require("../plan-generator");
|
|
50
|
+
const plan_files_1 = require("../plan-files");
|
|
51
|
+
const step_runner_1 = require("../step-runner");
|
|
52
|
+
const adapters_1 = require("../adapters");
|
|
53
|
+
const flags_1 = require("./flags");
|
|
54
|
+
const usage_1 = require("./usage");
|
|
55
|
+
const logger_1 = require("../logger");
|
|
56
|
+
const logger = (0, logger_1.getLogger)('cli:plan');
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// Plan helpers (exported from this module; called by the handle* functions)
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
function generatePlan(goal, copilotMode = false) {
|
|
61
|
+
const configLoader = new config_loader_1.ConfigLoader();
|
|
62
|
+
const agents = configLoader.loadAllAgents();
|
|
63
|
+
const generator = new plan_generator_1.PlanGenerator(agents);
|
|
64
|
+
if (copilotMode) {
|
|
65
|
+
logger.info('╔══════════════════════════════════════════════════════════════════════╗');
|
|
66
|
+
logger.info('║ COPILOT CLI PLANNING MODE ║');
|
|
67
|
+
logger.info('╚══════════════════════════════════════════════════════════════════════╝\n');
|
|
68
|
+
logger.info('📋 Goal:', goal, '\n');
|
|
69
|
+
logger.info('Instructions:');
|
|
70
|
+
logger.info(' 1. Copy the prompt below');
|
|
71
|
+
logger.info(' 2. Start a new Copilot CLI session: copilot');
|
|
72
|
+
logger.info(' 3. Paste the prompt and press Enter');
|
|
73
|
+
logger.info(' 4. When Copilot responds with JSON, run: /share');
|
|
74
|
+
logger.info(' 5. Save the /share transcript to a file');
|
|
75
|
+
logger.info(' 6. Import the plan: swarm plan import <runid> <transcript-path>\n');
|
|
76
|
+
logger.info('═'.repeat(70));
|
|
77
|
+
logger.info('PROMPT (copy from next line until the marker):');
|
|
78
|
+
logger.info('═'.repeat(70));
|
|
79
|
+
logger.info();
|
|
80
|
+
const prompt = generator.generateCopilotPlanningPrompt(goal);
|
|
81
|
+
logger.info(prompt);
|
|
82
|
+
logger.info();
|
|
83
|
+
logger.info('═'.repeat(70));
|
|
84
|
+
logger.info('END OF PROMPT');
|
|
85
|
+
logger.info('═'.repeat(70));
|
|
86
|
+
logger.info();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
logger.info('╔══════════════════════════════════════════════════════════════════════╗');
|
|
90
|
+
logger.info('║ INTELLIGENT PLAN GENERATION (Fallback Mode) ║');
|
|
91
|
+
logger.info('╚══════════════════════════════════════════════════════════════════════╝\n');
|
|
92
|
+
logger.info('📋 Goal:', goal, '\n');
|
|
93
|
+
logger.info('💡 Tip: Use --copilot for Copilot CLI-generated plans\n');
|
|
94
|
+
logger.info(`Loaded ${agents.length} agent profiles:`);
|
|
95
|
+
agents.forEach(agent => {
|
|
96
|
+
logger.info(` ✓ ${agent.name}: ${agent.purpose}`);
|
|
97
|
+
});
|
|
98
|
+
logger.info();
|
|
99
|
+
const plan = generator.createPlan(goal);
|
|
100
|
+
logger.info('Generated Execution Plan:');
|
|
101
|
+
logger.info('═'.repeat(70));
|
|
102
|
+
logger.info();
|
|
103
|
+
plan.steps.forEach(step => {
|
|
104
|
+
logger.info(`Step ${step.stepNumber}: ${step.task}`);
|
|
105
|
+
logger.info(` 👤 Agent: ${step.agentName}`);
|
|
106
|
+
if (step.dependencies.length > 0) {
|
|
107
|
+
logger.info(` 🔗 Dependencies: Steps ${step.dependencies.join(', ')}`);
|
|
108
|
+
}
|
|
109
|
+
logger.info(` 📦 Expected outputs:`);
|
|
110
|
+
step.expectedOutputs.forEach(output => {
|
|
111
|
+
logger.info(` • ${output}`);
|
|
112
|
+
});
|
|
113
|
+
logger.info();
|
|
114
|
+
});
|
|
115
|
+
const executionOrder = generator.getExecutionOrder(plan);
|
|
116
|
+
logger.info(`🔄 Execution Order: ${executionOrder.join(' → ')}\n`);
|
|
117
|
+
const planPath = (0, plan_files_1.savePlanFile)(plan);
|
|
118
|
+
logger.info(`✅ Plan saved to: ${planPath}`);
|
|
119
|
+
logger.info(`\n▶ To execute: swarm swarm ${path.basename(planPath)}\n`);
|
|
120
|
+
}
|
|
121
|
+
function importPlanFromTranscript(runId, transcriptPath) {
|
|
122
|
+
logger.info('╔══════════════════════════════════════════════════════════════════════╗');
|
|
123
|
+
logger.info('║ IMPORT COPILOT-GENERATED PLAN ║');
|
|
124
|
+
logger.info('╚══════════════════════════════════════════════════════════════════════╝\n');
|
|
125
|
+
logger.info('📁 Transcript:', transcriptPath);
|
|
126
|
+
logger.info('🆔 Run ID:', runId);
|
|
127
|
+
logger.info();
|
|
128
|
+
try {
|
|
129
|
+
if (!fs.existsSync(transcriptPath)) {
|
|
130
|
+
throw new Error(`Transcript file not found: ${transcriptPath}`);
|
|
131
|
+
}
|
|
132
|
+
const transcriptContent = fs.readFileSync(transcriptPath, 'utf-8');
|
|
133
|
+
const configLoader = new config_loader_1.ConfigLoader();
|
|
134
|
+
const agents = configLoader.loadAllAgents();
|
|
135
|
+
const generator = new plan_generator_1.PlanGenerator(agents);
|
|
136
|
+
logger.info('🔍 Parsing transcript for JSON plan...');
|
|
137
|
+
const plan = generator.parseCopilotPlanFromTranscript(transcriptContent);
|
|
138
|
+
logger.info('✅ Plan parsed successfully!\n');
|
|
139
|
+
logger.info('Plan details:');
|
|
140
|
+
logger.info(` Goal: ${plan.goal}`);
|
|
141
|
+
logger.info(` Steps: ${plan.steps.length}`);
|
|
142
|
+
logger.info(` Created: ${plan.createdAt}\n`);
|
|
143
|
+
logger.info('Steps:');
|
|
144
|
+
logger.info('═'.repeat(70));
|
|
145
|
+
plan.steps.forEach(step => {
|
|
146
|
+
logger.info(`\nStep ${step.stepNumber}: ${step.task}`);
|
|
147
|
+
logger.info(` 👤 Agent: ${step.agentName}`);
|
|
148
|
+
if (step.dependencies.length > 0) {
|
|
149
|
+
logger.info(` 🔗 Dependencies: ${step.dependencies.join(', ')}`);
|
|
150
|
+
}
|
|
151
|
+
logger.info(` 📦 Outputs: ${step.expectedOutputs.join(', ')}`);
|
|
152
|
+
});
|
|
153
|
+
logger.info('\n' + '═'.repeat(70));
|
|
154
|
+
const executionOrder = generator.getExecutionOrder(plan);
|
|
155
|
+
logger.info(`\n🔄 Execution Order: ${executionOrder.join(' → ')}`);
|
|
156
|
+
const planPath = (0, plan_files_1.savePlanFile)(plan);
|
|
157
|
+
logger.info(`\n✅ Plan saved to: ${planPath}`);
|
|
158
|
+
logger.info(`\n▶ To execute: swarm swarm ${path.basename(planPath)}\n`);
|
|
159
|
+
return 0;
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
logger.error('\n❌ Error importing plan:');
|
|
163
|
+
logger.error(' ', error instanceof Error ? error.message : String(error));
|
|
164
|
+
logger.error('\nTroubleshooting:');
|
|
165
|
+
logger.error(' • Ensure the transcript contains valid JSON output from Copilot');
|
|
166
|
+
logger.error(' • The JSON must match the ExecutionPlan schema');
|
|
167
|
+
logger.error(' • Check that all agent names are valid');
|
|
168
|
+
logger.error(' • Ensure dependencies form a valid DAG (no cycles)\n');
|
|
169
|
+
return 1;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function executePlan(planFilename, options) {
|
|
173
|
+
logger.info('Swarm Orchestrator - Plan Execution\n');
|
|
174
|
+
const plan = (0, plan_files_1.loadPlanFile)(planFilename);
|
|
175
|
+
logger.info(`Plan: ${plan.goal}`);
|
|
176
|
+
logger.info(`Steps: ${plan.steps.length}`);
|
|
177
|
+
const { CostEstimator } = require('../cost-estimator');
|
|
178
|
+
const seqModel = (0, adapters_1.defaultModelForAdapter)(options?.cliAgent);
|
|
179
|
+
const seqEstimator = new CostEstimator();
|
|
180
|
+
const seqEstimate = seqEstimator.estimate(plan, { modelName: seqModel });
|
|
181
|
+
logger.info(`\n💰 Cost Estimate: ${seqEstimate.lowEstimate}-${seqEstimate.totalPremiumRequests} premium requests`);
|
|
182
|
+
logger.info(` ${plan.steps.length} steps | ${seqModel} (${seqEstimate.modelMultiplier}x)`);
|
|
183
|
+
if (options?.delegate || options?.mcp) {
|
|
184
|
+
logger.info('\nGitHub Integration:');
|
|
185
|
+
if (options.delegate)
|
|
186
|
+
logger.info(' ✓ /delegate enabled - agents will be instructed to create PRs');
|
|
187
|
+
if (options.mcp)
|
|
188
|
+
logger.info(' ✓ MCP required - agents must provide GitHub context evidence');
|
|
189
|
+
}
|
|
190
|
+
logger.info('');
|
|
191
|
+
const configLoader = new config_loader_1.ConfigLoader();
|
|
192
|
+
const agents = configLoader.loadAllAgents();
|
|
193
|
+
const runner = new step_runner_1.StepRunner();
|
|
194
|
+
const context = runner.initializeExecution(plan, planFilename, options);
|
|
195
|
+
logger.info(`Execution ID: ${context.executionId}\n`);
|
|
196
|
+
const generator = new plan_generator_1.PlanGenerator(agents);
|
|
197
|
+
const executionOrder = generator.getExecutionOrder(plan);
|
|
198
|
+
logger.info(`Execution Order: ${executionOrder.join(' → ')}\n`);
|
|
199
|
+
logger.info('='.repeat(70));
|
|
200
|
+
logger.info('SEQUENTIAL EXECUTION GUIDE');
|
|
201
|
+
logger.info('='.repeat(70));
|
|
202
|
+
logger.info('');
|
|
203
|
+
logger.info('This tool will guide you through each step of the plan.');
|
|
204
|
+
logger.info('For each step, you will:');
|
|
205
|
+
logger.info(' 1. Receive a session prompt to copy/paste into Copilot CLI');
|
|
206
|
+
logger.info(' 2. Complete the work in that Copilot session');
|
|
207
|
+
logger.info(' 3. Run /share to capture the transcript');
|
|
208
|
+
logger.info(' 4. Save the transcript to the specified proof file');
|
|
209
|
+
logger.info(' 5. Return here to mark the step complete and get the next step');
|
|
210
|
+
logger.info('');
|
|
211
|
+
logger.info('Press ENTER to begin with Step 1...');
|
|
212
|
+
logger.info('');
|
|
213
|
+
const firstStepNumber = executionOrder[0];
|
|
214
|
+
if (firstStepNumber === undefined) {
|
|
215
|
+
logger.error('No steps to execute');
|
|
216
|
+
return 1;
|
|
217
|
+
}
|
|
218
|
+
const firstStep = plan.steps.find(s => s.stepNumber === firstStepNumber);
|
|
219
|
+
if (!firstStep) {
|
|
220
|
+
logger.error(`Step ${firstStepNumber} not found in plan`);
|
|
221
|
+
return 1;
|
|
222
|
+
}
|
|
223
|
+
const agent = agents.find(a => a.name === firstStep.agentName);
|
|
224
|
+
if (!agent) {
|
|
225
|
+
logger.error(`Agent ${firstStep.agentName} not found`);
|
|
226
|
+
return 1;
|
|
227
|
+
}
|
|
228
|
+
runner.displayStepInstructions(firstStep, agent, context);
|
|
229
|
+
const contextPath = runner.saveExecutionContext(context);
|
|
230
|
+
logger.info(`\n✓ Execution context saved to: ${contextPath}`);
|
|
231
|
+
logger.info(`\nTo continue execution after completing this step, run:`);
|
|
232
|
+
logger.info(` swarm status ${context.executionId}\n`);
|
|
233
|
+
return 0;
|
|
234
|
+
}
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
// Exported command handlers
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
async function handlePlanCommand(args) {
|
|
239
|
+
const normalizedArgs = (0, flags_1.normalizeLeadingGlobalFlags)(args);
|
|
240
|
+
const outputFormat = (0, flags_1.parseOutputFormat)(normalizedArgs);
|
|
241
|
+
const positional = (0, flags_1.extractPositionalArgs)(normalizedArgs.slice(1), {
|
|
242
|
+
booleanFlags: ['--help', '-h', '--verbose', '--json', '--copilot'],
|
|
243
|
+
valueFlags: ['--output'],
|
|
244
|
+
});
|
|
245
|
+
if (normalizedArgs.includes('--help') || normalizedArgs.includes('-h') || positional.length === 0) {
|
|
246
|
+
(0, usage_1.showUsage)();
|
|
247
|
+
return 0;
|
|
248
|
+
}
|
|
249
|
+
const subcommand = positional[0];
|
|
250
|
+
if (subcommand === 'import') {
|
|
251
|
+
if (positional.length < 3) {
|
|
252
|
+
logger.error('Error: plan import requires: <runid> <transcript-path>\n');
|
|
253
|
+
(0, usage_1.showUsage)();
|
|
254
|
+
return 1;
|
|
255
|
+
}
|
|
256
|
+
const runId = positional[1];
|
|
257
|
+
const transcriptPath = positional[2];
|
|
258
|
+
if (!runId || !transcriptPath) {
|
|
259
|
+
logger.error('Error: all arguments required\n');
|
|
260
|
+
(0, usage_1.showUsage)();
|
|
261
|
+
return 1;
|
|
262
|
+
}
|
|
263
|
+
if (outputFormat === 'json') {
|
|
264
|
+
try {
|
|
265
|
+
if (!fs.existsSync(transcriptPath)) {
|
|
266
|
+
throw new Error(`Transcript file not found: ${transcriptPath}`);
|
|
267
|
+
}
|
|
268
|
+
const transcriptContent = fs.readFileSync(transcriptPath, 'utf-8');
|
|
269
|
+
const configLoader = new config_loader_1.ConfigLoader();
|
|
270
|
+
const agents = configLoader.loadAllAgents();
|
|
271
|
+
const generator = new plan_generator_1.PlanGenerator(agents);
|
|
272
|
+
const plan = generator.parseCopilotPlanFromTranscript(transcriptContent);
|
|
273
|
+
const planPath = (0, plan_files_1.savePlanFile)(plan);
|
|
274
|
+
(0, logger_1.writeStructuredOutput)({ runId, transcriptPath, planFile: planPath, plan });
|
|
275
|
+
return 0;
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
logger.error('Error importing plan:', error instanceof Error ? error.message : error);
|
|
279
|
+
return 1;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return importPlanFromTranscript(runId, transcriptPath);
|
|
283
|
+
}
|
|
284
|
+
if (normalizedArgs.includes('--copilot')) {
|
|
285
|
+
const goal = positional.join(' ');
|
|
286
|
+
if (!goal) {
|
|
287
|
+
logger.error('Error: goal required for --copilot mode\n');
|
|
288
|
+
(0, usage_1.showUsage)();
|
|
289
|
+
return 1;
|
|
290
|
+
}
|
|
291
|
+
try {
|
|
292
|
+
if (outputFormat === 'json') {
|
|
293
|
+
const configLoader = new config_loader_1.ConfigLoader();
|
|
294
|
+
const agents = configLoader.loadAllAgents();
|
|
295
|
+
const generator = new plan_generator_1.PlanGenerator(agents);
|
|
296
|
+
(0, logger_1.writeStructuredOutput)({
|
|
297
|
+
goal,
|
|
298
|
+
mode: 'copilot',
|
|
299
|
+
prompt: generator.generateCopilotPlanningPrompt(goal),
|
|
300
|
+
});
|
|
301
|
+
return 0;
|
|
302
|
+
}
|
|
303
|
+
generatePlan(goal, true);
|
|
304
|
+
return 0;
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
logger.error('Error generating Copilot prompt:', error instanceof Error ? error.message : error);
|
|
308
|
+
return 1;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// plan <goal> (regular mode)
|
|
312
|
+
const goal = positional.join(' ');
|
|
313
|
+
try {
|
|
314
|
+
if (outputFormat === 'json') {
|
|
315
|
+
const configLoader = new config_loader_1.ConfigLoader();
|
|
316
|
+
const agents = configLoader.loadAllAgents();
|
|
317
|
+
const generator = new plan_generator_1.PlanGenerator(agents);
|
|
318
|
+
const plan = generator.createPlan(goal);
|
|
319
|
+
const planPath = (0, plan_files_1.savePlanFile)(plan);
|
|
320
|
+
(0, logger_1.writeStructuredOutput)({ goal: plan.goal, planFile: planPath, plan });
|
|
321
|
+
return 0;
|
|
322
|
+
}
|
|
323
|
+
generatePlan(goal, false);
|
|
324
|
+
return 0;
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
logger.error('Error generating plan:', error instanceof Error ? error.message : error);
|
|
328
|
+
return 1;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
async function handleExecuteCommand(args) {
|
|
332
|
+
if (args.length < 2 || !args[1]) {
|
|
333
|
+
logger.error('Error: Plan filename required\n');
|
|
334
|
+
(0, usage_1.showUsage)();
|
|
335
|
+
return 1;
|
|
336
|
+
}
|
|
337
|
+
const planFilename = args[1];
|
|
338
|
+
const options = {};
|
|
339
|
+
if (args.includes('--delegate'))
|
|
340
|
+
options.delegate = true;
|
|
341
|
+
if (args.includes('--mcp'))
|
|
342
|
+
options.mcp = true;
|
|
343
|
+
try {
|
|
344
|
+
return executePlan(planFilename, Object.keys(options).length > 0 ? options : undefined);
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
logger.error('Error executing plan:', error instanceof Error ? error.message : error);
|
|
348
|
+
return 1;
|
|
349
|
+
}
|
|
350
|
+
}
|