aided-dev 1.0.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.
@@ -0,0 +1,154 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { glob } from 'glob';
4
+ export const PROJECT_DOC_PATTERNS = {
5
+ brownfieldArchitecture: '{project}-brownfield-architecture.md',
6
+ integrationMap: '{project}-integration-map.md',
7
+ systemAnalysis: '{project}-system-analysis.md',
8
+ };
9
+ const DOC_LOCATIONS = ['', 'docs/', 'doc/', 'documentation/', '.aidev/'];
10
+ export async function detectProjectName(repoPath) {
11
+ const packageJsonPath = path.join(repoPath, 'package.json');
12
+ if (await fs.pathExists(packageJsonPath)) {
13
+ try {
14
+ const pkg = await fs.readJson(packageJsonPath);
15
+ if (pkg.name) {
16
+ return pkg.name.replace('@', '').replace('/', '-');
17
+ }
18
+ }
19
+ catch {
20
+ }
21
+ }
22
+ const pyprojectPath = path.join(repoPath, 'pyproject.toml');
23
+ if (await fs.pathExists(pyprojectPath)) {
24
+ try {
25
+ const content = await fs.readFile(pyprojectPath, 'utf-8');
26
+ const nameMatch = content.match(/name\s*=\s*["']([^"']+)["']/);
27
+ if (nameMatch) {
28
+ return nameMatch[1];
29
+ }
30
+ }
31
+ catch {
32
+ }
33
+ }
34
+ const cargoPath = path.join(repoPath, 'Cargo.toml');
35
+ if (await fs.pathExists(cargoPath)) {
36
+ try {
37
+ const content = await fs.readFile(cargoPath, 'utf-8');
38
+ const nameMatch = content.match(/name\s*=\s*["']([^"']+)["']/);
39
+ if (nameMatch) {
40
+ return nameMatch[1];
41
+ }
42
+ }
43
+ catch {
44
+ }
45
+ }
46
+ const goModPath = path.join(repoPath, 'go.mod');
47
+ if (await fs.pathExists(goModPath)) {
48
+ try {
49
+ const content = await fs.readFile(goModPath, 'utf-8');
50
+ const moduleMatch = content.match(/module\s+(\S+)/);
51
+ if (moduleMatch) {
52
+ const parts = moduleMatch[1].split('/');
53
+ return parts[parts.length - 1];
54
+ }
55
+ }
56
+ catch {
57
+ }
58
+ }
59
+ return path.basename(repoPath);
60
+ }
61
+ export async function findProjectNameFromDocs(repoPath) {
62
+ const patterns = [
63
+ '*-brownfield-architecture.md',
64
+ '*-integration-map.md',
65
+ '*-system-analysis.md',
66
+ ];
67
+ for (const location of DOC_LOCATIONS) {
68
+ const searchPath = path.join(repoPath, location);
69
+ if (!(await fs.pathExists(searchPath)))
70
+ continue;
71
+ for (const pattern of patterns) {
72
+ const matches = await glob(pattern, { cwd: searchPath });
73
+ if (matches.length > 0) {
74
+ const filename = path.basename(matches[0], '.md');
75
+ for (const suffix of ['-brownfield-architecture', '-integration-map', '-system-analysis']) {
76
+ if (filename.endsWith(suffix)) {
77
+ return filename.slice(0, -suffix.length);
78
+ }
79
+ }
80
+ }
81
+ }
82
+ }
83
+ return undefined;
84
+ }
85
+ export async function discoverProjectDocuments(repoPath) {
86
+ let projectName = await detectProjectName(repoPath);
87
+ if (!projectName) {
88
+ projectName = await findProjectNameFromDocs(repoPath);
89
+ }
90
+ if (!projectName) {
91
+ return undefined;
92
+ }
93
+ const docs = {
94
+ projectName,
95
+ };
96
+ for (const location of DOC_LOCATIONS) {
97
+ const basePath = path.join(repoPath, location);
98
+ if (!(await fs.pathExists(basePath)))
99
+ continue;
100
+ if (!docs.brownfieldArchitecture) {
101
+ const archPath = path.join(basePath, `${projectName}-brownfield-architecture.md`);
102
+ if (await fs.pathExists(archPath)) {
103
+ docs.brownfieldArchitecture = {
104
+ path: archPath,
105
+ content: await fs.readFile(archPath, 'utf-8'),
106
+ };
107
+ }
108
+ }
109
+ if (!docs.integrationMap) {
110
+ const intPath = path.join(basePath, `${projectName}-integration-map.md`);
111
+ if (await fs.pathExists(intPath)) {
112
+ docs.integrationMap = {
113
+ path: intPath,
114
+ content: await fs.readFile(intPath, 'utf-8'),
115
+ };
116
+ }
117
+ }
118
+ if (!docs.systemAnalysis) {
119
+ const sysPath = path.join(basePath, `${projectName}-system-analysis.md`);
120
+ if (await fs.pathExists(sysPath)) {
121
+ docs.systemAnalysis = {
122
+ path: sysPath,
123
+ content: await fs.readFile(sysPath, 'utf-8'),
124
+ };
125
+ }
126
+ }
127
+ }
128
+ if (docs.brownfieldArchitecture || docs.integrationMap || docs.systemAnalysis) {
129
+ return docs;
130
+ }
131
+ return undefined;
132
+ }
133
+ export function hasDocuments(docs) {
134
+ if (!docs)
135
+ return false;
136
+ return !!(docs.brownfieldArchitecture || docs.integrationMap || docs.systemAnalysis);
137
+ }
138
+ export function formatDocumentsForPrompt(docs) {
139
+ const parts = [];
140
+ parts.push(`## Project Source of Truth: ${docs.projectName}`);
141
+ if (docs.brownfieldArchitecture) {
142
+ parts.push('\n### Brownfield Architecture');
143
+ parts.push(docs.brownfieldArchitecture.content);
144
+ }
145
+ if (docs.integrationMap) {
146
+ parts.push('\n### Integration Map');
147
+ parts.push(docs.integrationMap.content);
148
+ }
149
+ if (docs.systemAnalysis) {
150
+ parts.push('\n### System Analysis');
151
+ parts.push(docs.systemAnalysis.content);
152
+ }
153
+ return parts.join('\n');
154
+ }
@@ -0,0 +1,2 @@
1
+ export { discoverProjectDocuments, detectProjectName, findProjectNameFromDocs, hasDocuments, formatDocumentsForPrompt, PROJECT_DOC_PATTERNS, type ProjectDocuments, } from './documents.js';
2
+ export { detectStack, formatStack, type ProjectStack, } from './detector.js';
@@ -0,0 +1,2 @@
1
+ export { discoverProjectDocuments, detectProjectName, findProjectNameFromDocs, hasDocuments, formatDocumentsForPrompt, PROJECT_DOC_PATTERNS, } from './documents.js';
2
+ export { detectStack, formatStack, } from './detector.js';
@@ -0,0 +1,5 @@
1
+ export { Orchestrator, TaskPlanner, AGENT_CAPABILITIES, type OrchestratorOptions, type WorkflowState, type ExecutionPlan, type PlannedStep, type TaskType, } from './orchestrator/index.js';
2
+ export { BMADLoader, getLoader, findBMADPath, buildSystemPrompt, type AgentConfig, type BMADAgent, type AgentMetadata, type AgentPersona, } from './bmad/index.js';
3
+ export { discoverProjectDocuments, detectStack, formatDocumentsForPrompt, formatStack, PROJECT_DOC_PATTERNS, type ProjectDocuments, type ProjectStack, } from './discovery/index.js';
4
+ export { getConfig, getApiKey, setApiKey, hasApiKey, getConfigPath, } from './config.js';
5
+ export { AgentCreator, quickCreateAgent, type AgentCreatorOptions, } from './agent-creator/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { Orchestrator, TaskPlanner, AGENT_CAPABILITIES, } from './orchestrator/index.js';
2
+ export { BMADLoader, getLoader, findBMADPath, buildSystemPrompt, } from './bmad/index.js';
3
+ export { discoverProjectDocuments, detectStack, formatDocumentsForPrompt, formatStack, PROJECT_DOC_PATTERNS, } from './discovery/index.js';
4
+ export { getConfig, getApiKey, setApiKey, hasApiKey, getConfigPath, } from './config.js';
5
+ export { AgentCreator, quickCreateAgent, } from './agent-creator/index.js';
@@ -0,0 +1,3 @@
1
+ export { Orchestrator, type OrchestratorOptions, type WorkflowState } from './orchestrator.js';
2
+ export { TaskPlanner, AGENT_CAPABILITIES, type ExecutionPlan, type PlannedStep, type TaskType, } from './planner.js';
3
+ export { BMADLoader, getLoader, type AgentConfig } from '../bmad/index.js';
@@ -0,0 +1,3 @@
1
+ export { Orchestrator } from './orchestrator.js';
2
+ export { TaskPlanner, AGENT_CAPABILITIES, } from './planner.js';
3
+ export { BMADLoader, getLoader } from '../bmad/index.js';
@@ -0,0 +1,40 @@
1
+ import { type ProjectDocuments, type ProjectStack } from '../discovery/index.js';
2
+ import { type ExecutionPlan } from './planner.js';
3
+ export interface OrchestratorOptions {
4
+ repoPath: string;
5
+ model?: string;
6
+ verbose?: boolean;
7
+ skipPlanning?: boolean;
8
+ }
9
+ export interface WorkflowState {
10
+ task: string;
11
+ repoPath: string;
12
+ projectDocuments?: ProjectDocuments;
13
+ stack?: ProjectStack;
14
+ plan?: ExecutionPlan;
15
+ outputs: Map<string, string>;
16
+ errors: string[];
17
+ }
18
+ export declare class Orchestrator {
19
+ private client;
20
+ private model;
21
+ private repoPath;
22
+ private verbose;
23
+ private skipPlanning;
24
+ private bmadLoader;
25
+ private agents;
26
+ private planner;
27
+ constructor(options: OrchestratorOptions);
28
+ private loadAgents;
29
+ private getAgent;
30
+ run(task: string): Promise<WorkflowState>;
31
+ private phaseDiscover;
32
+ private phasePlanning;
33
+ private executeplan;
34
+ private executeStep;
35
+ private buildContext;
36
+ private formatOutputTitle;
37
+ private buildStepPrompt;
38
+ private extractTextContent;
39
+ private printSummary;
40
+ }
@@ -0,0 +1,386 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import ora from 'ora';
3
+ import chalk from 'chalk';
4
+ import { discoverProjectDocuments, detectStack, formatDocumentsForPrompt, formatStack, } from '../discovery/index.js';
5
+ import { getLoader } from '../bmad/index.js';
6
+ import { getApiKey } from '../config.js';
7
+ import { TaskPlanner, AGENT_CAPABILITIES, } from './planner.js';
8
+ export class Orchestrator {
9
+ client;
10
+ model;
11
+ repoPath;
12
+ verbose;
13
+ skipPlanning;
14
+ bmadLoader;
15
+ agents = new Map();
16
+ planner = null;
17
+ constructor(options) {
18
+ const apiKey = getApiKey();
19
+ if (!apiKey) {
20
+ throw new Error('Anthropic API key not found. Run `aidev config --api-key <key>` or set ANTHROPIC_API_KEY environment variable.');
21
+ }
22
+ this.client = new Anthropic({ apiKey });
23
+ this.model = options.model || 'claude-sonnet-4-20250514';
24
+ this.repoPath = options.repoPath;
25
+ this.verbose = options.verbose || false;
26
+ this.skipPlanning = options.skipPlanning || false;
27
+ this.bmadLoader = getLoader();
28
+ }
29
+ async loadAgents() {
30
+ const allAgentNames = await this.bmadLoader.listAgents();
31
+ const coreAgents = ['analyst', 'architect', 'dev', 'tea', 'pm', 'sm', 'tech-writer', 'ux-designer'];
32
+ const agentNames = [...new Set([...allAgentNames, ...coreAgents])];
33
+ this.agents = await this.bmadLoader.loadAgents(agentNames);
34
+ if (this.bmadLoader.isAvailable()) {
35
+ console.log(chalk.dim(` BMAD-METHOD: ${this.bmadLoader.getPath()}`));
36
+ console.log(chalk.dim(` Loaded ${this.agents.size} agents`));
37
+ }
38
+ else {
39
+ console.log(chalk.dim(' BMAD-METHOD: Using fallback agents'));
40
+ }
41
+ this.planner = new TaskPlanner(this.client, this.model, this.agents);
42
+ }
43
+ getAgent(name) {
44
+ const nameMap = {
45
+ analyst: 'analyst',
46
+ architect: 'architect',
47
+ developer: 'dev',
48
+ dev: 'dev',
49
+ qa: 'tea',
50
+ tea: 'tea',
51
+ 'tech-writer': 'tech-writer',
52
+ 'ux-designer': 'ux-designer',
53
+ pm: 'pm',
54
+ sm: 'sm',
55
+ };
56
+ const bmadName = nameMap[name] || name;
57
+ return this.agents.get(bmadName);
58
+ }
59
+ async run(task) {
60
+ const state = {
61
+ task,
62
+ repoPath: this.repoPath,
63
+ outputs: new Map(),
64
+ errors: [],
65
+ };
66
+ console.log('');
67
+ console.log(chalk.bgBlue.white(' AI Dev Team - Smart Orchestration '));
68
+ console.log(chalk.dim(`Task: ${task}`));
69
+ console.log('');
70
+ await this.loadAgents();
71
+ await this.phaseDiscover(state);
72
+ if (state.errors.length > 0) {
73
+ this.printSummary(state);
74
+ return state;
75
+ }
76
+ await this.phasePlanning(state);
77
+ if (state.errors.length > 0 || !state.plan) {
78
+ this.printSummary(state);
79
+ return state;
80
+ }
81
+ await this.executeplan(state);
82
+ this.printSummary(state);
83
+ return state;
84
+ }
85
+ async phaseDiscover(state) {
86
+ const spinner = ora('Discovering project context...').start();
87
+ try {
88
+ state.stack = await detectStack(this.repoPath);
89
+ spinner.text = `Detected: ${state.stack.language}`;
90
+ state.projectDocuments = await discoverProjectDocuments(this.repoPath);
91
+ spinner.succeed(chalk.green('Discovery complete'));
92
+ console.log(chalk.dim(` Language: ${state.stack.language}`));
93
+ if (state.stack.framework) {
94
+ console.log(chalk.dim(` Framework: ${state.stack.framework}`));
95
+ }
96
+ if (state.projectDocuments) {
97
+ const docCount = [
98
+ state.projectDocuments.brownfieldArchitecture,
99
+ state.projectDocuments.integrationMap,
100
+ state.projectDocuments.systemAnalysis,
101
+ ].filter(Boolean).length;
102
+ console.log(chalk.green(` Found ${docCount} source-of-truth document(s)`));
103
+ }
104
+ console.log('');
105
+ }
106
+ catch (error) {
107
+ spinner.fail(chalk.red('Discovery failed'));
108
+ state.errors.push(`Discovery error: ${error}`);
109
+ }
110
+ }
111
+ async phasePlanning(state) {
112
+ if (!this.planner) {
113
+ state.errors.push('Planner not initialized');
114
+ return;
115
+ }
116
+ const spinner = ora('Analyzing task and creating execution plan...').start();
117
+ try {
118
+ const plan = await this.planner.createPlan(state.task, {
119
+ stack: state.stack,
120
+ hasProjectDocs: !!state.projectDocuments,
121
+ existingCode: state.stack?.language !== 'unknown',
122
+ });
123
+ const validation = this.planner.validatePlan(plan);
124
+ if (!validation.valid) {
125
+ spinner.warn(chalk.yellow('Plan has issues, adjusting...'));
126
+ if (this.verbose) {
127
+ validation.errors.forEach((e) => console.log(chalk.dim(` - ${e}`)));
128
+ }
129
+ }
130
+ state.plan = plan;
131
+ spinner.succeed(chalk.green('Execution plan created'));
132
+ console.log('');
133
+ console.log(chalk.cyan(`Task Type: ${plan.taskType}`));
134
+ console.log(chalk.cyan(`Complexity: ${plan.estimatedComplexity}`));
135
+ console.log(chalk.dim(`Reasoning: ${plan.reasoning}`));
136
+ console.log('');
137
+ console.log(chalk.bold('Execution Plan:'));
138
+ for (let i = 0; i < plan.steps.length; i++) {
139
+ const step = plan.steps[i];
140
+ const agent = this.getAgent(step.agent);
141
+ const agentInfo = AGENT_CAPABILITIES[step.agent];
142
+ const icon = agent?.icon || '🤖';
143
+ const name = agent?.name || agentInfo?.name || step.agent;
144
+ const priorityIcon = step.priority === 'required' ? '●' :
145
+ step.priority === 'recommended' ? '◐' : '○';
146
+ console.log(chalk.dim(` ${i + 1}. ${priorityIcon} ${icon} ${name}: ${step.action}`));
147
+ }
148
+ console.log('');
149
+ }
150
+ catch (error) {
151
+ spinner.fail(chalk.red('Planning failed'));
152
+ state.errors.push(`Planning error: ${error}`);
153
+ }
154
+ }
155
+ async executeplan(state) {
156
+ if (!state.plan)
157
+ return;
158
+ for (const step of state.plan.steps) {
159
+ const missingDeps = step.dependsOn.filter((dep) => !state.outputs.has(dep));
160
+ if (missingDeps.length > 0 && step.priority === 'required') {
161
+ state.errors.push(`Cannot execute ${step.outputKey}: missing dependencies ${missingDeps.join(', ')}`);
162
+ continue;
163
+ }
164
+ await this.executeStep(step, state);
165
+ if (step.priority === 'required' &&
166
+ !state.outputs.has(step.outputKey) &&
167
+ state.errors.length > 0) {
168
+ break;
169
+ }
170
+ }
171
+ }
172
+ async executeStep(step, state) {
173
+ const agent = this.getAgent(step.agent);
174
+ if (!agent) {
175
+ if (step.priority === 'required') {
176
+ state.errors.push(`Agent '${step.agent}' not available`);
177
+ }
178
+ return;
179
+ }
180
+ const spinner = ora(`${agent.icon} ${agent.name} (${agent.title}): ${step.action}...`).start();
181
+ try {
182
+ const context = this.buildContext(state, step);
183
+ const prompt = this.buildStepPrompt(step, state);
184
+ const response = await this.client.messages.create({
185
+ model: this.model,
186
+ max_tokens: 8192,
187
+ system: agent.systemPrompt,
188
+ messages: [
189
+ {
190
+ role: 'user',
191
+ content: `${context}\n\n${prompt}`,
192
+ },
193
+ ],
194
+ });
195
+ const output = this.extractTextContent(response);
196
+ state.outputs.set(step.outputKey, output);
197
+ spinner.succeed(chalk.green(`${agent.icon} ${step.action} complete`));
198
+ if (this.verbose) {
199
+ console.log(chalk.dim(`\n--- ${step.outputKey} Output ---`));
200
+ console.log(chalk.dim(output.substring(0, 500) + '...'));
201
+ console.log('');
202
+ }
203
+ }
204
+ catch (error) {
205
+ const errorMsg = `${step.action} failed: ${error}`;
206
+ if (step.priority === 'optional') {
207
+ spinner.warn(chalk.yellow(`${agent.icon} ${step.action} skipped (optional)`));
208
+ }
209
+ else if (step.priority === 'recommended') {
210
+ spinner.warn(chalk.yellow(`${agent.icon} ${step.action} failed (non-blocking)`));
211
+ }
212
+ else {
213
+ spinner.fail(chalk.red(`${agent.icon} ${step.action} failed`));
214
+ state.errors.push(errorMsg);
215
+ }
216
+ }
217
+ }
218
+ buildContext(state, step) {
219
+ const parts = [];
220
+ if (state.stack) {
221
+ parts.push('## Project Stack');
222
+ parts.push(formatStack(state.stack));
223
+ }
224
+ if (state.projectDocuments) {
225
+ parts.push('\n' + formatDocumentsForPrompt(state.projectDocuments));
226
+ }
227
+ for (const dep of step.dependsOn) {
228
+ const depOutput = state.outputs.get(dep);
229
+ if (depOutput) {
230
+ parts.push(`\n## ${this.formatOutputTitle(dep)}`);
231
+ parts.push(depOutput);
232
+ }
233
+ }
234
+ return parts.join('\n');
235
+ }
236
+ formatOutputTitle(key) {
237
+ return key
238
+ .replace(/_/g, ' ')
239
+ .replace(/\b\w/g, (c) => c.toUpperCase());
240
+ }
241
+ buildStepPrompt(step, state) {
242
+ const task = state.task;
243
+ const promptTemplates = {
244
+ prd: `## Task
245
+ ${task}
246
+
247
+ ## Instructions
248
+ Create a Product Requirements Document (PRD) for this task. Include:
249
+ 1. Project overview and goals
250
+ 2. Core features (prioritized)
251
+ 3. User stories with acceptance criteria
252
+ 4. Out of scope items
253
+ 5. Success metrics
254
+ 6. Technical constraints
255
+
256
+ Respond in a structured markdown format.`,
257
+ architecture: `## Task
258
+ ${task}
259
+
260
+ ## Instructions
261
+ Design the technical architecture for this project. Include:
262
+ 1. Tech stack selection with justification
263
+ 2. File/folder structure
264
+ 3. API design (endpoints, methods, request/response)
265
+ 4. Data models
266
+ 5. Framework patterns to follow
267
+ 6. Configuration requirements
268
+
269
+ Consider the existing project context and follow established patterns.
270
+ Respond in a structured markdown format with code blocks where appropriate.`,
271
+ implementation: `## Task
272
+ ${task}
273
+
274
+ ## Instructions
275
+ Implement the code according to the specifications provided.
276
+ - Follow the architecture/design if provided
277
+ - Implement all required functionality
278
+ - Include proper error handling
279
+ - Add inline documentation
280
+ - Follow framework conventions
281
+
282
+ Output each file with its path and complete code.`,
283
+ tests: `## Task
284
+ ${task}
285
+
286
+ ## Instructions
287
+ Generate comprehensive tests for the implementation:
288
+ - Unit tests for core functions
289
+ - Integration tests for API endpoints
290
+ - Edge cases and error scenarios
291
+ - Use appropriate test framework for the stack
292
+
293
+ Output test files with paths and complete test code.`,
294
+ fix: `## Task
295
+ ${task}
296
+
297
+ ## Instructions
298
+ Analyze and fix the reported issue:
299
+ 1. Identify the root cause
300
+ 2. Implement the fix
301
+ 3. Ensure no regressions
302
+ 4. Document the changes
303
+
304
+ Output the fixed code with explanations.`,
305
+ design: `## Task
306
+ ${task}
307
+
308
+ ## Instructions
309
+ Create a design document for this task:
310
+ 1. Analyze current state
311
+ 2. Propose improvements
312
+ 3. Define the approach
313
+ 4. List changes needed
314
+
315
+ Respond in a structured markdown format.`,
316
+ docs: `## Task
317
+ ${task}
318
+
319
+ ## Instructions
320
+ Create documentation for this task:
321
+ 1. Overview and purpose
322
+ 2. Usage instructions
323
+ 3. API reference (if applicable)
324
+ 4. Examples
325
+ 5. Troubleshooting
326
+
327
+ Use clear, technical writing style.`,
328
+ analysis: `## Task
329
+ ${task}
330
+
331
+ ## Instructions
332
+ Analyze the requirements and provide:
333
+ 1. Problem breakdown
334
+ 2. Key considerations
335
+ 3. Recommendations
336
+ 4. Risks and mitigations
337
+
338
+ Be thorough and specific.`,
339
+ };
340
+ const templateKey = Object.keys(promptTemplates).find((key) => step.outputKey.includes(key) || step.action.toLowerCase().includes(key));
341
+ if (templateKey) {
342
+ return promptTemplates[templateKey];
343
+ }
344
+ return `## Task
345
+ ${task}
346
+
347
+ ## Your Action
348
+ ${step.action}
349
+
350
+ ## Instructions
351
+ ${step.description}
352
+
353
+ Provide your output in a clear, structured format.`;
354
+ }
355
+ extractTextContent(response) {
356
+ return response.content
357
+ .filter((block) => block.type === 'text')
358
+ .map((block) => block.text)
359
+ .join('\n');
360
+ }
361
+ printSummary(state) {
362
+ console.log('');
363
+ if (state.errors.length > 0) {
364
+ console.log(chalk.red('Workflow completed with errors:'));
365
+ for (const error of state.errors) {
366
+ console.log(chalk.red(` - ${error}`));
367
+ }
368
+ }
369
+ else {
370
+ console.log(chalk.green('✓ Workflow complete!'));
371
+ }
372
+ if (state.outputs.size > 0) {
373
+ console.log('');
374
+ console.log(chalk.dim('Outputs generated:'));
375
+ for (const key of state.outputs.keys()) {
376
+ console.log(chalk.dim(` - ${this.formatOutputTitle(key)}`));
377
+ }
378
+ }
379
+ if (state.plan) {
380
+ console.log('');
381
+ console.log(chalk.dim(`Task type: ${state.plan.taskType}`));
382
+ console.log(chalk.dim(`Complexity: ${state.plan.estimatedComplexity}`));
383
+ }
384
+ console.log('');
385
+ }
386
+ }
@@ -0,0 +1,44 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import type { AgentConfig } from '../bmad/index.js';
3
+ export interface PlannedStep {
4
+ agent: string;
5
+ action: string;
6
+ description: string;
7
+ dependsOn: string[];
8
+ outputKey: string;
9
+ priority: 'required' | 'recommended' | 'optional';
10
+ }
11
+ export interface ExecutionPlan {
12
+ task: string;
13
+ taskType: TaskType;
14
+ summary: string;
15
+ steps: PlannedStep[];
16
+ estimatedComplexity: 'simple' | 'moderate' | 'complex';
17
+ reasoning: string;
18
+ }
19
+ export type TaskType = 'new_feature' | 'bug_fix' | 'refactor' | 'documentation' | 'testing' | 'code_review' | 'architecture' | 'analysis' | 'general';
20
+ export declare const AGENT_CAPABILITIES: Record<string, {
21
+ name: string;
22
+ capabilities: string[];
23
+ bestFor: string[];
24
+ }>;
25
+ export declare class TaskPlanner {
26
+ private client;
27
+ private model;
28
+ private availableAgents;
29
+ constructor(client: Anthropic, model: string, availableAgents: Map<string, AgentConfig>);
30
+ createPlan(task: string, context: {
31
+ stack?: {
32
+ language: string;
33
+ framework?: string;
34
+ };
35
+ hasProjectDocs: boolean;
36
+ existingCode: boolean;
37
+ }): Promise<ExecutionPlan>;
38
+ private buildAgentDescriptions;
39
+ private createDefaultPlan;
40
+ validatePlan(plan: ExecutionPlan): {
41
+ valid: boolean;
42
+ errors: string[];
43
+ };
44
+ }