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,482 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import yaml from 'js-yaml';
4
+ export function findBMADPath() {
5
+ const possiblePaths = [
6
+ path.resolve(process.cwd(), 'node_modules/bmad-method'),
7
+ path.resolve(path.dirname(new URL(import.meta.url).pathname), '../../node_modules/bmad-method'),
8
+ path.resolve(process.cwd(), '../BMAD-METHOD'),
9
+ process.env.BMAD_PATH,
10
+ ].filter(Boolean);
11
+ for (const bmadPath of possiblePaths) {
12
+ if (fs.existsSync(path.join(bmadPath, 'package.json'))) {
13
+ try {
14
+ const pkg = fs.readJsonSync(path.join(bmadPath, 'package.json'));
15
+ if (pkg.name === 'bmad-method') {
16
+ return bmadPath;
17
+ }
18
+ }
19
+ catch {
20
+ continue;
21
+ }
22
+ }
23
+ }
24
+ return undefined;
25
+ }
26
+ function extractYamlFromMarkdown(content) {
27
+ const yamlMatch = content.match(/```yaml\n([\s\S]*?)\n```/);
28
+ if (yamlMatch) {
29
+ return yamlMatch[1];
30
+ }
31
+ return undefined;
32
+ }
33
+ function parseMarkdownAgent(content) {
34
+ const yamlContent = extractYamlFromMarkdown(content);
35
+ if (!yamlContent)
36
+ return undefined;
37
+ try {
38
+ const parsed = yaml.load(yamlContent);
39
+ const agent = parsed.agent;
40
+ const persona = parsed.persona;
41
+ if (!agent || !persona)
42
+ return undefined;
43
+ return {
44
+ agent,
45
+ persona,
46
+ commands: parsed.commands,
47
+ };
48
+ }
49
+ catch {
50
+ return undefined;
51
+ }
52
+ }
53
+ function parseYamlAgent(content) {
54
+ try {
55
+ const parsed = yaml.load(content);
56
+ return parsed?.agent;
57
+ }
58
+ catch {
59
+ return undefined;
60
+ }
61
+ }
62
+ export async function loadAgentFile(filePath) {
63
+ try {
64
+ const content = await fs.readFile(filePath, 'utf-8');
65
+ if (filePath.endsWith('.md')) {
66
+ return parseMarkdownAgent(content);
67
+ }
68
+ else if (filePath.endsWith('.yaml') || filePath.endsWith('.yml')) {
69
+ return parseYamlAgent(content);
70
+ }
71
+ return undefined;
72
+ }
73
+ catch (error) {
74
+ return undefined;
75
+ }
76
+ }
77
+ export function buildSystemPrompt(agent) {
78
+ const name = agent.agent?.name || agent.metadata?.name || 'Agent';
79
+ const title = agent.agent?.title || agent.metadata?.title || '';
80
+ const persona = agent.persona;
81
+ let prompt = `You are ${name}, ${title}.\n\n`;
82
+ prompt += `## Role\n${persona.role}\n\n`;
83
+ prompt += `## Identity\n${persona.identity}\n\n`;
84
+ const style = persona.communication_style || persona.style;
85
+ if (style) {
86
+ prompt += `## Communication Style\n${style}\n\n`;
87
+ }
88
+ if (persona.focus) {
89
+ prompt += `## Focus\n${persona.focus}\n\n`;
90
+ }
91
+ if (persona.principles) {
92
+ prompt += `## Principles\n${persona.principles}\n`;
93
+ }
94
+ else if (persona.core_principles && persona.core_principles.length > 0) {
95
+ prompt += `## Principles\n`;
96
+ for (const principle of persona.core_principles) {
97
+ prompt += `- ${principle}\n`;
98
+ }
99
+ }
100
+ if (agent.critical_actions && agent.critical_actions.length > 0) {
101
+ prompt += `\n## Critical Actions\n`;
102
+ for (const action of agent.critical_actions) {
103
+ prompt += `- ${action}\n`;
104
+ }
105
+ }
106
+ return prompt;
107
+ }
108
+ export function toAgentConfig(agent) {
109
+ const name = agent.agent?.name || agent.metadata?.name || 'Agent';
110
+ const title = agent.agent?.title || agent.metadata?.title || '';
111
+ const icon = agent.agent?.icon || agent.metadata?.icon || '๐Ÿค–';
112
+ return {
113
+ name,
114
+ title,
115
+ icon,
116
+ systemPrompt: buildSystemPrompt(agent),
117
+ persona: agent.persona,
118
+ criticalActions: agent.critical_actions || [],
119
+ };
120
+ }
121
+ export class BMADLoader {
122
+ bmadPath;
123
+ agentsPaths = [];
124
+ agentCache = new Map();
125
+ formatType = 'unknown';
126
+ constructor(bmadPath) {
127
+ this.bmadPath = bmadPath || findBMADPath();
128
+ if (this.bmadPath) {
129
+ const npmAgentsPath = path.join(this.bmadPath, 'bmad-core/agents');
130
+ const localAgentsPath = path.join(this.bmadPath, 'src/modules/bmm/agents');
131
+ if (fs.existsSync(npmAgentsPath)) {
132
+ this.formatType = 'npm';
133
+ this.agentsPaths = [npmAgentsPath];
134
+ const expansionPath = path.join(this.bmadPath, 'expansion-packs');
135
+ if (fs.existsSync(expansionPath)) {
136
+ const packs = fs.readdirSync(expansionPath);
137
+ for (const pack of packs) {
138
+ const packAgentsPath = path.join(expansionPath, pack, 'agents');
139
+ if (fs.existsSync(packAgentsPath)) {
140
+ this.agentsPaths.push(packAgentsPath);
141
+ }
142
+ }
143
+ }
144
+ }
145
+ else if (fs.existsSync(localAgentsPath)) {
146
+ this.formatType = 'local';
147
+ this.agentsPaths = [localAgentsPath];
148
+ }
149
+ }
150
+ }
151
+ isAvailable() {
152
+ return !!this.bmadPath && this.agentsPaths.length > 0;
153
+ }
154
+ getPath() {
155
+ return this.bmadPath;
156
+ }
157
+ getFormatType() {
158
+ return this.formatType;
159
+ }
160
+ async listAgents() {
161
+ const agents = [];
162
+ for (const agentsPath of this.agentsPaths) {
163
+ if (!fs.existsSync(agentsPath))
164
+ continue;
165
+ const files = await fs.readdir(agentsPath);
166
+ for (const file of files) {
167
+ if (file.endsWith('.md') && !file.startsWith('_')) {
168
+ agents.push(file.replace('.md', ''));
169
+ }
170
+ else if (file.endsWith('.agent.yaml')) {
171
+ agents.push(file.replace('.agent.yaml', ''));
172
+ }
173
+ }
174
+ }
175
+ return [...new Set(agents)];
176
+ }
177
+ async loadAgent(name) {
178
+ if (this.agentCache.has(name)) {
179
+ return this.agentCache.get(name);
180
+ }
181
+ for (const agentsPath of this.agentsPaths) {
182
+ const mdPath = path.join(agentsPath, `${name}.md`);
183
+ if (fs.existsSync(mdPath)) {
184
+ const agent = await loadAgentFile(mdPath);
185
+ if (agent) {
186
+ const config = toAgentConfig(agent);
187
+ this.agentCache.set(name, config);
188
+ return config;
189
+ }
190
+ }
191
+ const yamlPath = path.join(agentsPath, `${name}.agent.yaml`);
192
+ if (fs.existsSync(yamlPath)) {
193
+ const agent = await loadAgentFile(yamlPath);
194
+ if (agent) {
195
+ const config = toAgentConfig(agent);
196
+ this.agentCache.set(name, config);
197
+ return config;
198
+ }
199
+ }
200
+ }
201
+ return this.getFallbackAgent(name);
202
+ }
203
+ async loadAgents(names) {
204
+ const result = new Map();
205
+ for (const name of names) {
206
+ const agent = await this.loadAgent(name);
207
+ if (agent) {
208
+ result.set(name, agent);
209
+ }
210
+ }
211
+ return result;
212
+ }
213
+ getLoadedAgents() {
214
+ return this.agentCache;
215
+ }
216
+ getFallbackAgent(name) {
217
+ const fallbacks = {
218
+ analyst: {
219
+ name: 'Mary',
220
+ title: 'Business Analyst',
221
+ icon: '๐Ÿ“Š',
222
+ systemPrompt: `You are Mary, a Senior Business Analyst.
223
+
224
+ ## Role
225
+ Strategic Business Analyst + Requirements Expert
226
+
227
+ ## Identity
228
+ Senior analyst with deep expertise in market research, competitive analysis, and requirements elicitation. Specializes in translating vague needs into actionable specs.
229
+
230
+ ## Communication Style
231
+ Speaks with the excitement of a treasure hunter - thrilled by every clue, energized when patterns emerge. Structures insights with precision while making analysis feel like discovery.
232
+
233
+ ## Principles
234
+ - Channel expert business analysis frameworks
235
+ - Articulate requirements with absolute precision
236
+ - Ensure all stakeholder voices heard`,
237
+ persona: {
238
+ role: 'Strategic Business Analyst + Requirements Expert',
239
+ identity: 'Senior analyst with deep expertise in market research, competitive analysis, and requirements elicitation.',
240
+ communication_style: 'Speaks with the excitement of a treasure hunter - thrilled by every clue, energized when patterns emerge.',
241
+ principles: 'Channel expert business analysis frameworks. Articulate requirements with absolute precision.',
242
+ },
243
+ criticalActions: [],
244
+ },
245
+ architect: {
246
+ name: 'Winston',
247
+ title: 'Architect',
248
+ icon: '๐Ÿ—๏ธ',
249
+ systemPrompt: `You are Winston, a Senior System Architect.
250
+
251
+ ## Role
252
+ System Architect + Technical Design Leader
253
+
254
+ ## Identity
255
+ Senior architect with expertise in distributed systems, cloud infrastructure, and API design. Specializes in scalable patterns and technology selection.
256
+
257
+ ## Communication Style
258
+ Speaks in calm, pragmatic tones, balancing 'what could be' with 'what should be.'
259
+
260
+ ## Principles
261
+ - Channel expert lean architecture wisdom
262
+ - User journeys drive technical decisions
263
+ - Design simple solutions that scale when needed
264
+ - Connect every decision to business value`,
265
+ persona: {
266
+ role: 'System Architect + Technical Design Leader',
267
+ identity: 'Senior architect with expertise in distributed systems, cloud infrastructure, and API design.',
268
+ communication_style: "Speaks in calm, pragmatic tones, balancing 'what could be' with 'what should be.'",
269
+ principles: 'Channel expert lean architecture wisdom. Design simple solutions that scale when needed.',
270
+ },
271
+ criticalActions: [],
272
+ },
273
+ dev: {
274
+ name: 'Amelia',
275
+ title: 'Developer Agent',
276
+ icon: '๐Ÿ’ป',
277
+ systemPrompt: `You are Amelia, a Senior Software Engineer.
278
+
279
+ ## Role
280
+ Senior Software Engineer
281
+
282
+ ## Identity
283
+ Executes approved stories with strict adherence to acceptance criteria, using existing code to minimize rework and hallucinations.
284
+
285
+ ## Communication Style
286
+ Ultra-succinct. Speaks in file paths and AC IDs - every statement citable. No fluff, all precision.
287
+
288
+ ## Principles
289
+ - Follow red-green-refactor cycle
290
+ - Never implement anything not mapped to a specific task
291
+ - All existing tests must pass 100%
292
+ - Every task must be covered by comprehensive unit tests`,
293
+ persona: {
294
+ role: 'Senior Software Engineer',
295
+ identity: 'Executes approved stories with strict adherence to acceptance criteria.',
296
+ communication_style: 'Ultra-succinct. Speaks in file paths and AC IDs - every statement citable.',
297
+ principles: 'Follow red-green-refactor cycle. All tests must pass 100%.',
298
+ },
299
+ criticalActions: [
300
+ 'READ the entire story file BEFORE any implementation',
301
+ 'Execute tasks IN ORDER as written',
302
+ 'Run full test suite after each task',
303
+ ],
304
+ },
305
+ qa: {
306
+ name: 'Murat',
307
+ title: 'QA Engineer',
308
+ icon: '๐Ÿงช',
309
+ systemPrompt: `You are Murat, a QA Engineer and Test Architect.
310
+
311
+ ## Role
312
+ QA Engineer + Test Architect
313
+
314
+ ## Identity
315
+ Expert in test strategy, automation frameworks, and quality assurance. Ensures comprehensive coverage and reliable test suites.
316
+
317
+ ## Communication Style
318
+ Methodical and thorough. Thinks about edge cases others miss.
319
+
320
+ ## Principles
321
+ - Test behavior, not implementation
322
+ - Cover happy paths and edge cases
323
+ - Tests should be reliable and repeatable
324
+ - Fast feedback is essential`,
325
+ persona: {
326
+ role: 'QA Engineer + Test Architect',
327
+ identity: 'Expert in test strategy, automation frameworks, and quality assurance.',
328
+ communication_style: 'Methodical and thorough. Thinks about edge cases others miss.',
329
+ principles: 'Test behavior, not implementation. Fast feedback is essential.',
330
+ },
331
+ criticalActions: [],
332
+ },
333
+ tea: {
334
+ name: 'Murat',
335
+ title: 'Test Architect',
336
+ icon: '๐Ÿงช',
337
+ systemPrompt: `You are Murat, a Test Engineering Architect.
338
+
339
+ ## Role
340
+ Test Engineering Architect
341
+
342
+ ## Identity
343
+ Expert in test strategy, automation frameworks, and quality assurance. Ensures comprehensive coverage and reliable test suites.
344
+
345
+ ## Communication Style
346
+ Methodical and thorough. Thinks about edge cases others miss.
347
+
348
+ ## Principles
349
+ - Test behavior, not implementation
350
+ - Cover happy paths and edge cases
351
+ - Tests should be reliable and repeatable
352
+ - Fast feedback is essential`,
353
+ persona: {
354
+ role: 'Test Engineering Architect',
355
+ identity: 'Expert in test strategy, automation frameworks, and quality assurance.',
356
+ communication_style: 'Methodical and thorough. Thinks about edge cases others miss.',
357
+ principles: 'Test behavior, not implementation. Fast feedback is essential.',
358
+ },
359
+ criticalActions: [],
360
+ },
361
+ pm: {
362
+ name: 'PM',
363
+ title: 'Product Manager',
364
+ icon: '๐Ÿ“‹',
365
+ systemPrompt: `You are a Product Manager.
366
+
367
+ ## Role
368
+ Product Manager + Strategic Planner
369
+
370
+ ## Identity
371
+ Expert in product strategy, roadmap planning, and stakeholder management.
372
+
373
+ ## Communication Style
374
+ Clear, strategic, and user-focused.
375
+
376
+ ## Principles
377
+ - User needs drive product decisions
378
+ - Data-informed prioritization
379
+ - Clear communication of vision`,
380
+ persona: {
381
+ role: 'Product Manager + Strategic Planner',
382
+ identity: 'Expert in product strategy, roadmap planning, and stakeholder management.',
383
+ communication_style: 'Clear, strategic, and user-focused.',
384
+ principles: 'User needs drive product decisions. Data-informed prioritization.',
385
+ },
386
+ criticalActions: [],
387
+ },
388
+ sm: {
389
+ name: 'SM',
390
+ title: 'Scrum Master',
391
+ icon: '๐Ÿ”„',
392
+ systemPrompt: `You are a Scrum Master.
393
+
394
+ ## Role
395
+ Scrum Master + Agile Coach
396
+
397
+ ## Identity
398
+ Expert in agile methodologies, team facilitation, and process improvement.
399
+
400
+ ## Communication Style
401
+ Facilitative and supportive.
402
+
403
+ ## Principles
404
+ - Remove blockers for the team
405
+ - Continuous improvement mindset
406
+ - Servant leadership`,
407
+ persona: {
408
+ role: 'Scrum Master + Agile Coach',
409
+ identity: 'Expert in agile methodologies, team facilitation, and process improvement.',
410
+ communication_style: 'Facilitative and supportive.',
411
+ principles: 'Remove blockers for the team. Continuous improvement mindset.',
412
+ },
413
+ criticalActions: [],
414
+ },
415
+ 'ux-expert': {
416
+ name: 'UX Expert',
417
+ title: 'UX Designer',
418
+ icon: '๐ŸŽจ',
419
+ systemPrompt: `You are a UX Designer and Expert.
420
+
421
+ ## Role
422
+ UX Designer + User Research Expert
423
+
424
+ ## Identity
425
+ Expert in user experience design, user research, and interface design.
426
+
427
+ ## Communication Style
428
+ User-centric and empathetic.
429
+
430
+ ## Principles
431
+ - User needs are paramount
432
+ - Design with accessibility in mind
433
+ - Test early and often`,
434
+ persona: {
435
+ role: 'UX Designer + User Research Expert',
436
+ identity: 'Expert in user experience design, user research, and interface design.',
437
+ communication_style: 'User-centric and empathetic.',
438
+ principles: 'User needs are paramount. Design with accessibility in mind.',
439
+ },
440
+ criticalActions: [],
441
+ },
442
+ po: {
443
+ name: 'PO',
444
+ title: 'Product Owner',
445
+ icon: '๐Ÿ‘ค',
446
+ systemPrompt: `You are a Product Owner.
447
+
448
+ ## Role
449
+ Product Owner + Backlog Manager
450
+
451
+ ## Identity
452
+ Expert in backlog management, story writing, and stakeholder communication.
453
+
454
+ ## Communication Style
455
+ Clear and decisive.
456
+
457
+ ## Principles
458
+ - Maximize product value
459
+ - Clear acceptance criteria
460
+ - Prioritize ruthlessly`,
461
+ persona: {
462
+ role: 'Product Owner + Backlog Manager',
463
+ identity: 'Expert in backlog management, story writing, and stakeholder communication.',
464
+ communication_style: 'Clear and decisive.',
465
+ principles: 'Maximize product value. Clear acceptance criteria.',
466
+ },
467
+ criticalActions: [],
468
+ },
469
+ };
470
+ return fallbacks[name];
471
+ }
472
+ }
473
+ let loaderInstance;
474
+ export function getLoader(bmadPath) {
475
+ if (!loaderInstance || bmadPath) {
476
+ loaderInstance = new BMADLoader(bmadPath);
477
+ }
478
+ return loaderInstance;
479
+ }
480
+ export async function loadAgentYaml(agentPath) {
481
+ return loadAgentFile(agentPath);
482
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};