create-byan-agent 2.0.1 → 2.1.1
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/API-BYAN-V2.md +741 -0
- package/BMAD-QUICK-REFERENCE.md +370 -0
- package/CHANGELOG-v2.1.0.md +371 -0
- package/LICENSE +1 -1
- package/MIGRATION-v2.0-to-v2.1.md +430 -0
- package/README-BYAN-V2.md +446 -0
- package/README.md +264 -201
- package/install/.eslintrc.js +20 -0
- package/install/.prettierrc +7 -0
- package/install/BUGFIX-CHALK.md +173 -0
- package/install/BUGFIX-DOCUMENTATION-INDEX.md +299 -0
- package/install/BUGFIX-PATH-RESOLUTION.md +293 -0
- package/install/BUGFIX-QUICKSTART.md +184 -0
- package/install/BUGFIX-SUMMARY.txt +91 -0
- package/install/BUGFIX-VISUAL-SUMMARY.md +253 -0
- package/install/DEPLOYMENT-GUIDE-V2.md +431 -0
- package/install/DOCS-INDEX.md +261 -0
- package/install/GUIDE-INSTALLATION-BYAN-SIMPLE.md +1083 -0
- package/install/INSTALLER-V2-CHANGES.md +472 -0
- package/install/LICENSE +21 -0
- package/install/PUBLICATION-CHECKLIST.md +265 -0
- package/install/PUBLISH-GUIDE.md +190 -0
- package/install/QUICKSTART.md +311 -0
- package/install/README-NPM-PUBLISH.md +298 -0
- package/install/README-NPM-SHORT.md +298 -0
- package/install/README-NPM.md +433 -0
- package/install/README-RACHID.md +302 -0
- package/install/README-V2-INDEX.md +306 -0
- package/install/README.md +298 -0
- package/install/RESUME-EXECUTIF-YAN.md +408 -0
- package/install/UPDATE-SUMMARY.md +205 -0
- package/install/__tests__/integration/detection-flow.test.js +154 -0
- package/install/__tests__/platforms/claude-code.test.js +175 -0
- package/install/__tests__/platforms/codex.test.js +80 -0
- package/install/__tests__/platforms/copilot-cli.test.js +118 -0
- package/install/__tests__/platforms/vscode.test.js +67 -0
- package/install/__tests__/utils/file-utils.test.js +87 -0
- package/install/__tests__/utils/git-detector.test.js +80 -0
- package/install/__tests__/utils/logger.test.js +83 -0
- package/install/__tests__/utils/node-detector.test.js +71 -0
- package/install/__tests__/utils/os-detector.test.js +63 -0
- package/install/__tests__/utils/yaml-utils.test.js +85 -0
- package/install/__tests__/yanstaller/detector.test.js +210 -0
- package/install/coverage/clover.xml +219 -0
- package/install/coverage/coverage-final.json +13 -0
- package/install/coverage/lcov-report/base.css +224 -0
- package/install/coverage/lcov-report/block-navigation.js +87 -0
- package/install/coverage/lcov-report/favicon.png +0 -0
- package/install/coverage/lcov-report/index.html +146 -0
- package/install/coverage/lcov-report/lib/errors.js.html +268 -0
- package/install/coverage/lcov-report/lib/exit-codes.js.html +247 -0
- package/install/coverage/lcov-report/lib/index.html +131 -0
- package/install/coverage/lcov-report/lib/platforms/claude-code.js.html +343 -0
- package/install/coverage/lcov-report/lib/platforms/codex.js.html +361 -0
- package/install/coverage/lcov-report/lib/platforms/copilot-cli.js.html +454 -0
- package/install/coverage/lcov-report/lib/platforms/index.html +176 -0
- package/install/coverage/lcov-report/lib/platforms/index.js.html +127 -0
- package/install/coverage/lcov-report/lib/platforms/vscode.js.html +238 -0
- package/install/coverage/lcov-report/lib/utils/config-loader.js.html +322 -0
- package/install/coverage/lcov-report/lib/utils/file-utils.js.html +397 -0
- package/install/coverage/lcov-report/lib/utils/git-detector.js.html +190 -0
- package/install/coverage/lcov-report/lib/utils/index.html +206 -0
- package/install/coverage/lcov-report/lib/utils/logger.js.html +277 -0
- package/install/coverage/lcov-report/lib/utils/node-detector.js.html +259 -0
- package/install/coverage/lcov-report/lib/utils/os-detector.js.html +307 -0
- package/install/coverage/lcov-report/lib/utils/yaml-utils.js.html +346 -0
- package/install/coverage/lcov-report/lib/yanstaller/backuper.js.html +409 -0
- package/install/coverage/lcov-report/lib/yanstaller/detector.js.html +508 -0
- package/install/coverage/lcov-report/lib/yanstaller/index.html +236 -0
- package/install/coverage/lcov-report/lib/yanstaller/index.js.html +364 -0
- package/install/coverage/lcov-report/lib/yanstaller/installer.js.html +505 -0
- package/install/coverage/lcov-report/lib/yanstaller/interviewer.js.html +349 -0
- package/install/coverage/lcov-report/lib/yanstaller/recommender.js.html +379 -0
- package/install/coverage/lcov-report/lib/yanstaller/troubleshooter.js.html +352 -0
- package/install/coverage/lcov-report/lib/yanstaller/validator.js.html +679 -0
- package/install/coverage/lcov-report/lib/yanstaller/wizard.js.html +412 -0
- package/install/coverage/lcov-report/platforms/claude-code.js.html +343 -0
- package/install/coverage/lcov-report/platforms/codex.js.html +361 -0
- package/install/coverage/lcov-report/platforms/copilot-cli.js.html +454 -0
- package/install/coverage/lcov-report/platforms/index.html +176 -0
- package/install/coverage/lcov-report/platforms/index.js.html +127 -0
- package/install/coverage/lcov-report/platforms/vscode.js.html +238 -0
- package/install/coverage/lcov-report/prettify.css +1 -0
- package/install/coverage/lcov-report/prettify.js +2 -0
- package/install/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/install/coverage/lcov-report/sorter.js +210 -0
- package/install/coverage/lcov-report/utils/file-utils.js.html +397 -0
- package/install/coverage/lcov-report/utils/git-detector.js.html +190 -0
- package/install/coverage/lcov-report/utils/index.html +191 -0
- package/install/coverage/lcov-report/utils/logger.js.html +277 -0
- package/install/coverage/lcov-report/utils/node-detector.js.html +259 -0
- package/install/coverage/lcov-report/utils/os-detector.js.html +307 -0
- package/install/coverage/lcov-report/utils/yaml-utils.js.html +346 -0
- package/install/coverage/lcov-report/yanstaller/detector.js.html +508 -0
- package/install/coverage/lcov-report/yanstaller/index.html +116 -0
- package/install/coverage/lcov.info +414 -0
- package/install/install.sh +239 -0
- package/install/jest.config.js +33 -0
- package/install/lib/errors.js +61 -0
- package/install/lib/exit-codes.js +54 -0
- package/install/lib/platforms/claude-code.js +86 -0
- package/install/lib/platforms/codex.js +92 -0
- package/install/lib/platforms/copilot-cli.js +123 -0
- package/install/lib/platforms/index.js +14 -0
- package/install/lib/platforms/vscode.js +51 -0
- package/install/lib/utils/config-loader.js +79 -0
- package/install/lib/utils/file-utils.js +104 -0
- package/install/lib/utils/git-detector.js +35 -0
- package/install/lib/utils/logger.js +64 -0
- package/install/lib/utils/node-detector.js +58 -0
- package/install/lib/utils/os-detector.js +74 -0
- package/install/lib/utils/yaml-utils.js +87 -0
- package/install/lib/yanstaller/backuper.js +108 -0
- package/install/lib/yanstaller/detector.js +141 -0
- package/install/lib/yanstaller/index.js +93 -0
- package/install/lib/yanstaller/installer.js +140 -0
- package/install/lib/yanstaller/interviewer.js +88 -0
- package/install/lib/yanstaller/recommender.js +98 -0
- package/install/lib/yanstaller/troubleshooter.js +89 -0
- package/install/lib/yanstaller/validator.js +198 -0
- package/install/lib/yanstaller/wizard.js +109 -0
- package/install/package-npm.json +55 -0
- package/install/package.json +63 -0
- package/install/src/byan-v2/context/copilot-context.js +79 -0
- package/install/src/byan-v2/context/session-state.js +98 -0
- package/install/src/byan-v2/dispatcher/complexity-scorer.js +232 -0
- package/install/src/byan-v2/dispatcher/local-executor.js +221 -0
- package/install/src/byan-v2/dispatcher/task-router.js +122 -0
- package/install/src/byan-v2/dispatcher/task-tool-interface-mock.js +134 -0
- package/install/src/byan-v2/dispatcher/task-tool-interface.js +123 -0
- package/install/src/byan-v2/generation/agent-profile-validator.js +113 -0
- package/install/src/byan-v2/generation/profile-template.js +113 -0
- package/install/src/byan-v2/generation/templates/default-agent.md +49 -0
- package/install/src/byan-v2/generation/templates/test-template.md +1 -0
- package/install/src/byan-v2/index.js +199 -0
- package/install/src/byan-v2/observability/error-tracker.js +105 -0
- package/install/src/byan-v2/observability/logger.js +154 -0
- package/install/src/byan-v2/observability/metrics-collector.js +194 -0
- package/install/src/byan-v2/orchestrator/analysis-state.js +268 -0
- package/install/src/byan-v2/orchestrator/generation-state.js +340 -0
- package/install/src/byan-v2/orchestrator/interview-state.js +271 -0
- package/install/src/byan-v2/orchestrator/state-machine.js +204 -0
- package/install/src/core/cache/cache.js +126 -0
- package/install/src/core/context/context.js +86 -0
- package/install/src/core/dispatcher/dispatcher.js +135 -0
- package/install/src/core/worker-pool/worker-pool.js +194 -0
- package/install/src/core/workflow/workflow-executor.js +220 -0
- package/install/src/index.js +139 -0
- package/install/src/observability/dashboard/dashboard.js +191 -0
- package/install/src/observability/logger/structured-logger.js +254 -0
- package/install/src/observability/metrics/metrics-collector.js +325 -0
- package/install/switch-to-v2.sh +126 -0
- package/install/test-chalk-fix.sh +210 -0
- package/install/test-installer-v2.sh +204 -0
- package/install/test-path-resolution.sh +200 -0
- package/package.json +53 -33
- package/src/byan-v2/context/copilot-context.js +79 -0
- package/src/byan-v2/context/session-state.js +98 -0
- package/src/byan-v2/data/mantras.json +852 -0
- package/src/byan-v2/dispatcher/complexity-scorer.js +232 -0
- package/src/byan-v2/dispatcher/five-whys-analyzer.js +310 -0
- package/src/byan-v2/dispatcher/local-executor.js +221 -0
- package/src/byan-v2/dispatcher/task-router.js +122 -0
- package/src/byan-v2/dispatcher/task-tool-interface-mock.js +134 -0
- package/src/byan-v2/dispatcher/task-tool-interface.js +123 -0
- package/src/byan-v2/generation/agent-profile-validator.js +113 -0
- package/src/byan-v2/generation/mantra-validator.js +416 -0
- package/src/byan-v2/generation/profile-template.js +113 -0
- package/src/byan-v2/generation/templates/default-agent.md +49 -0
- package/src/byan-v2/generation/templates/test-template.md +1 -0
- package/src/byan-v2/index.js +652 -0
- package/src/byan-v2/integration/voice-integration.js +295 -0
- package/src/byan-v2/observability/error-tracker.js +105 -0
- package/src/byan-v2/observability/logger.js +154 -0
- package/src/byan-v2/observability/metrics-collector.js +194 -0
- package/src/byan-v2/orchestrator/active-listener.js +541 -0
- package/src/byan-v2/orchestrator/analysis-state.js +268 -0
- package/src/byan-v2/orchestrator/generation-state.js +340 -0
- package/src/byan-v2/orchestrator/glossary-builder.js +431 -0
- package/src/byan-v2/orchestrator/interview-state.js +353 -0
- package/src/byan-v2/orchestrator/state-machine.js +253 -0
- package/src/core/cache/cache.js +126 -0
- package/src/core/context/context.js +86 -0
- package/src/core/dispatcher/dispatcher.js +135 -0
- package/src/core/worker-pool/worker-pool.js +194 -0
- package/src/core/workflow/workflow-executor.js +220 -0
- package/src/index.js +139 -0
- package/src/observability/dashboard/dashboard.js +191 -0
- package/src/observability/logger/structured-logger.js +254 -0
- package/src/observability/metrics/metrics-collector.js +325 -0
- package/templates/.github/agents/bmad-agent-test-dynamic.md +0 -21
- package/templates/.github/agents/franck.md +0 -379
- /package/{CHANGELOG.md → install/CHANGELOG.md} +0 -0
- /package/{bin → install/bin}/create-byan-agent-backup.js +0 -0
- /package/{bin → install/bin}/create-byan-agent-fixed.js +0 -0
- /package/{bin → install/bin}/create-byan-agent-v2.js +0 -0
- /package/{bin → install/bin}/create-byan-agent.js +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmad-master.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-agent-builder.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-module-builder.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-workflow-builder.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-analyst.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-architect.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-dev.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-pm.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-quick-flow-solo-dev.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-quinn.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-sm.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-tech-writer.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-ux-designer.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-byan-test.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-byan.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-carmack.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-brainstorming-coach.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-creative-problem-solver.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-design-thinking-coach.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-innovation-strategist.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-presentation-master.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-storyteller.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-marc.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-patnote.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-rachid.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-tea-tea.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/agent-builder.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/byan-test.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/byan.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/marc.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/module-builder.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/patnote.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/rachid.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/workflow-builder.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/data/mantras.yaml +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/data/templates.yaml +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/delete-agent-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/edit-agent-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/interview-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/quick-create-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/templates/base-agent-template.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/validate-agent-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/core/agents/carmack.md +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const yaml = require('js-yaml');
|
|
4
|
+
|
|
5
|
+
class ProfileTemplate {
|
|
6
|
+
static render(template, data) {
|
|
7
|
+
let result = template;
|
|
8
|
+
|
|
9
|
+
const placeholders = this.extractPlaceholders(template);
|
|
10
|
+
|
|
11
|
+
for (const placeholder of placeholders) {
|
|
12
|
+
const value = this.resolvePlaceholder(placeholder, data);
|
|
13
|
+
|
|
14
|
+
if (value !== undefined && value !== null) {
|
|
15
|
+
const regex = new RegExp(`\\{\\{${placeholder.replace(/\./g, '\\.')}\\}\\}`, 'g');
|
|
16
|
+
result = result.replace(regex, value);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static loadTemplate(templateName) {
|
|
24
|
+
const templatesDir = path.join(__dirname, 'templates');
|
|
25
|
+
const templatePath = path.join(templatesDir, `${templateName}.md`);
|
|
26
|
+
|
|
27
|
+
if (!fs.existsSync(templatePath)) {
|
|
28
|
+
throw new Error(`Template not found: ${templateName}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return fs.readFileSync(templatePath, 'utf-8');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static renderFromFile(templateName, data) {
|
|
35
|
+
const template = this.loadTemplate(templateName);
|
|
36
|
+
return this.render(template, data);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static validateTemplate(template, requiredPlaceholders = []) {
|
|
40
|
+
const result = {
|
|
41
|
+
valid: true,
|
|
42
|
+
errors: [],
|
|
43
|
+
warnings: []
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const frontmatterMatch = template.match(/^---\n([\s\S]*?)\n---/);
|
|
47
|
+
|
|
48
|
+
if (!frontmatterMatch) {
|
|
49
|
+
result.valid = false;
|
|
50
|
+
result.errors.push('Missing YAML frontmatter');
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
yaml.load(frontmatterMatch[1]);
|
|
56
|
+
} catch (e) {
|
|
57
|
+
result.valid = false;
|
|
58
|
+
result.errors.push(`Invalid YAML frontmatter: ${e.message}`);
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const templatePlaceholders = this.extractPlaceholders(template);
|
|
63
|
+
|
|
64
|
+
for (const required of requiredPlaceholders) {
|
|
65
|
+
if (!templatePlaceholders.includes(required)) {
|
|
66
|
+
result.warnings.push(`Missing required placeholder: ${required}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const xmlMatch = template.match(/```xml\n([\s\S]*?)\n```/);
|
|
71
|
+
if (xmlMatch) {
|
|
72
|
+
const xmlContent = xmlMatch[1];
|
|
73
|
+
const openTags = (xmlContent.match(/<(\w+)[^>]*>/g) || []).map(tag => tag.match(/<(\w+)/)[1]);
|
|
74
|
+
const closeTags = (xmlContent.match(/<\/(\w+)>/g) || []).map(tag => tag.match(/<\/(\w+)>/)[1]);
|
|
75
|
+
|
|
76
|
+
if (openTags.length !== closeTags.length) {
|
|
77
|
+
result.warnings.push('Potentially malformed XML: tag count mismatch');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static extractPlaceholders(template) {
|
|
85
|
+
const regex = /\{\{([^}]+)\}\}/g;
|
|
86
|
+
const matches = [];
|
|
87
|
+
let match;
|
|
88
|
+
|
|
89
|
+
while ((match = regex.exec(template)) !== null) {
|
|
90
|
+
if (!matches.includes(match[1])) {
|
|
91
|
+
matches.push(match[1]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return matches;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
static resolvePlaceholder(path, data) {
|
|
99
|
+
const parts = path.split('.');
|
|
100
|
+
let current = data;
|
|
101
|
+
|
|
102
|
+
for (const part of parts) {
|
|
103
|
+
if (current === undefined || current === null) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
current = current[part];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return current;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
module.exports = ProfileTemplate;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "{{agent_name}}"
|
|
3
|
+
description: "{{description}}"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
|
|
7
|
+
|
|
8
|
+
```xml
|
|
9
|
+
<agent id="{{agent_id}}" name="{{agent_name}}" title="{{title}}" icon="{{icon}}">
|
|
10
|
+
<activation critical="MANDATORY">
|
|
11
|
+
<step n="1">Load persona from current file</step>
|
|
12
|
+
<step n="2">Load config from {project-root}/_bmad/{{module}}/config.yaml - store {user_name}, {communication_language}, {output_folder}</step>
|
|
13
|
+
<step n="3">Show greeting using {user_name} in {communication_language}</step>
|
|
14
|
+
<step n="4">Inform about `/bmad-help` command</step>
|
|
15
|
+
<step n="5">WAIT for user input</step>
|
|
16
|
+
<rules>
|
|
17
|
+
<r>Communicate in {communication_language}</r>
|
|
18
|
+
<r>Stay in character until EXIT</r>
|
|
19
|
+
<r>Apply Merise Agile + TDD + 64 mantras</r>
|
|
20
|
+
</rules>
|
|
21
|
+
</activation>
|
|
22
|
+
|
|
23
|
+
<persona>
|
|
24
|
+
<role>{{role}}</role>
|
|
25
|
+
<identity>{{identity}}</identity>
|
|
26
|
+
<communication_style>{{communication_style}}</communication_style>
|
|
27
|
+
|
|
28
|
+
<principles>
|
|
29
|
+
{{principles}}
|
|
30
|
+
</principles>
|
|
31
|
+
</persona>
|
|
32
|
+
|
|
33
|
+
<knowledge_base>
|
|
34
|
+
{{knowledge_base}}
|
|
35
|
+
</knowledge_base>
|
|
36
|
+
|
|
37
|
+
<capabilities>
|
|
38
|
+
{{capabilities}}
|
|
39
|
+
</capabilities>
|
|
40
|
+
|
|
41
|
+
<anti_patterns>
|
|
42
|
+
{{anti_patterns}}
|
|
43
|
+
</anti_patterns>
|
|
44
|
+
|
|
45
|
+
<exit_protocol>
|
|
46
|
+
EXIT: Save state → Summarize → Next steps → File locations → Remind reactivation → Return control
|
|
47
|
+
</exit_protocol>
|
|
48
|
+
</agent>
|
|
49
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Agent: {{agent_name}}, Role: {{role}}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
const SessionState = require('./context/session-state');
|
|
2
|
+
const TaskRouter = require('./dispatcher/task-router');
|
|
3
|
+
const StateMachine = require('./orchestrator/state-machine');
|
|
4
|
+
const InterviewState = require('./orchestrator/interview-state');
|
|
5
|
+
const AnalysisState = require('./orchestrator/analysis-state');
|
|
6
|
+
const GenerationState = require('./orchestrator/generation-state');
|
|
7
|
+
const Logger = require('./observability/logger');
|
|
8
|
+
const MetricsCollector = require('./observability/metrics-collector');
|
|
9
|
+
const crypto = require('crypto');
|
|
10
|
+
|
|
11
|
+
class ByanV2 {
|
|
12
|
+
constructor(config = {}) {
|
|
13
|
+
this.config = this._loadConfig(config);
|
|
14
|
+
|
|
15
|
+
if (config.sessionState) {
|
|
16
|
+
this.sessionState = config.sessionState;
|
|
17
|
+
} else {
|
|
18
|
+
const sessionId = this.config.sessionId || crypto.randomUUID();
|
|
19
|
+
this.sessionState = new SessionState(sessionId);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (config.logger) {
|
|
23
|
+
this.logger = config.logger;
|
|
24
|
+
} else {
|
|
25
|
+
this.logger = new Logger();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
this.metrics = new MetricsCollector();
|
|
29
|
+
this.dispatcher = new TaskRouter();
|
|
30
|
+
|
|
31
|
+
const ErrorTracker = require('./observability/error-tracker');
|
|
32
|
+
this.errorTracker = new ErrorTracker();
|
|
33
|
+
|
|
34
|
+
if (config.stateMachine) {
|
|
35
|
+
this.stateMachine = config.stateMachine;
|
|
36
|
+
} else {
|
|
37
|
+
this.stateMachine = new StateMachine({
|
|
38
|
+
logger: this.logger,
|
|
39
|
+
errorTracker: this.errorTracker
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
this.interviewState = new InterviewState(this.sessionState);
|
|
43
|
+
this.analysisState = new AnalysisState(this.sessionState);
|
|
44
|
+
this.generationState = new GenerationState(this.sessionState);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
_loadConfig(customConfig) {
|
|
49
|
+
const defaults = {
|
|
50
|
+
maxQuestions: 12,
|
|
51
|
+
complexityThresholds: {
|
|
52
|
+
low: 30,
|
|
53
|
+
medium: 60
|
|
54
|
+
},
|
|
55
|
+
outputDir: './_bmad-output/bmb-creations',
|
|
56
|
+
env: customConfig.env || (process.env.GITHUB_COPILOT ? 'copilot' : 'standalone')
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return { ...defaults, ...customConfig };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
isCopilotContext() {
|
|
63
|
+
return this.config.env === 'copilot' || process.env.GITHUB_COPILOT === 'true';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async startSession() {
|
|
67
|
+
this.logger.info('Starting BYAN session', {
|
|
68
|
+
event: 'session_start',
|
|
69
|
+
sessionId: this.sessionState.sessionId
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
this.metrics.increment('sessionsStarted');
|
|
73
|
+
|
|
74
|
+
await this.stateMachine.transition('INTERVIEW');
|
|
75
|
+
|
|
76
|
+
this.logger.info('State transition', {
|
|
77
|
+
event: 'state_transition',
|
|
78
|
+
from: 'INIT',
|
|
79
|
+
to: 'INTERVIEW'
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return this.sessionState.sessionId;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async getNextQuestion() {
|
|
86
|
+
const currentState = this.stateMachine.getCurrentState();
|
|
87
|
+
|
|
88
|
+
if (currentState.name !== 'INTERVIEW') {
|
|
89
|
+
throw new Error('Not in INTERVIEW state');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const question = this.interviewState.askNextQuestion();
|
|
93
|
+
|
|
94
|
+
this.metrics.increment('questionsAsked');
|
|
95
|
+
|
|
96
|
+
return typeof question === 'string' ? question : question?.text || question;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async submitResponse(response) {
|
|
100
|
+
if (!response || response.trim().length === 0) {
|
|
101
|
+
this.metrics.increment('errors');
|
|
102
|
+
throw new Error('Response cannot be empty');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const sanitized = response.substring(0, 100);
|
|
106
|
+
this.logger.info('User response received', {
|
|
107
|
+
event: 'response_submitted',
|
|
108
|
+
response: sanitized
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const currentState = this.stateMachine.getCurrentState();
|
|
112
|
+
|
|
113
|
+
if (currentState.name === 'INTERVIEW') {
|
|
114
|
+
const isComplete = this.interviewState.processResponse(response);
|
|
115
|
+
|
|
116
|
+
if (isComplete) {
|
|
117
|
+
await this.stateMachine.transition('ANALYSIS');
|
|
118
|
+
|
|
119
|
+
this.logger.info('State transition', {
|
|
120
|
+
event: 'state_transition',
|
|
121
|
+
from: 'INTERVIEW',
|
|
122
|
+
to: 'ANALYSIS'
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return { success: true };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async generateProfile() {
|
|
131
|
+
const currentState = this.stateMachine.getCurrentState();
|
|
132
|
+
|
|
133
|
+
if (currentState.name === 'INTERVIEW') {
|
|
134
|
+
await this.stateMachine.transition('ANALYSIS');
|
|
135
|
+
await this.stateMachine.transition('GENERATION');
|
|
136
|
+
} else if (currentState.name === 'ANALYSIS') {
|
|
137
|
+
await this.stateMachine.transition('GENERATION');
|
|
138
|
+
} else if (currentState.name !== 'GENERATION') {
|
|
139
|
+
this.metrics.increment('errors');
|
|
140
|
+
throw new Error('Cannot generate profile in current state');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
this.logger.info('Generating agent profile', {
|
|
144
|
+
event: 'profile_generation_start'
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const profile = await this.generationState.generateProfile();
|
|
148
|
+
|
|
149
|
+
this.metrics.increment('profilesGenerated');
|
|
150
|
+
|
|
151
|
+
await this.stateMachine.transition('COMPLETED');
|
|
152
|
+
|
|
153
|
+
this.logger.info('Profile generation complete', {
|
|
154
|
+
event: 'profile_generation_complete'
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
return profile;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async endSession() {
|
|
161
|
+
const currentState = this.stateMachine.getCurrentState();
|
|
162
|
+
|
|
163
|
+
if (currentState.name !== 'COMPLETED' && currentState.name !== 'ERROR') {
|
|
164
|
+
// Force transition through states if needed
|
|
165
|
+
if (currentState.name === 'INTERVIEW') {
|
|
166
|
+
await this.stateMachine.transition('ANALYSIS');
|
|
167
|
+
await this.stateMachine.transition('GENERATION');
|
|
168
|
+
} else if (currentState.name === 'ANALYSIS') {
|
|
169
|
+
await this.stateMachine.transition('GENERATION');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (this.stateMachine.getCurrentState().name === 'GENERATION') {
|
|
173
|
+
await this.stateMachine.transition('COMPLETED');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
this.logger.info('Session ended', {
|
|
178
|
+
event: 'session_end',
|
|
179
|
+
sessionId: this.sessionState.sessionId
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return { success: true };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
getMetricsSummary() {
|
|
186
|
+
return this.metrics.getSummary();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async getSessionSummary() {
|
|
190
|
+
return {
|
|
191
|
+
sessionId: this.sessionState.sessionId,
|
|
192
|
+
questionsAsked: this.sessionState.userResponses.length,
|
|
193
|
+
state: this.stateMachine.getCurrentState().name,
|
|
194
|
+
timestamp: new Date().toISOString()
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
module.exports = ByanV2;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ErrorTracker - Track and store errors with context
|
|
3
|
+
*
|
|
4
|
+
* Error Types:
|
|
5
|
+
* - ROUTING_ERROR: Errors during task routing
|
|
6
|
+
* - EXECUTION_ERROR: Errors during task execution
|
|
7
|
+
* - VALIDATION_ERROR: Errors during validation
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Store up to maxErrors (default 100) in FIFO order
|
|
11
|
+
* - Track error type, message, stack, context, timestamp
|
|
12
|
+
* - Filter errors by type
|
|
13
|
+
* - Get error statistics
|
|
14
|
+
*
|
|
15
|
+
* Methods:
|
|
16
|
+
* - trackError(errorData)
|
|
17
|
+
* - getErrors()
|
|
18
|
+
* - getErrorsByType(type)
|
|
19
|
+
* - getErrorStats()
|
|
20
|
+
* - clearErrors()
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
class ErrorTracker {
|
|
24
|
+
constructor(options = {}) {
|
|
25
|
+
this.maxErrors = options.maxErrors || 100;
|
|
26
|
+
this.errors = [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Track an error with full context
|
|
31
|
+
* @param {Object} errorData - Error data with type, message, error, context
|
|
32
|
+
*/
|
|
33
|
+
trackError(errorData) {
|
|
34
|
+
if (!errorData) return;
|
|
35
|
+
|
|
36
|
+
const { type, message, error, context } = errorData;
|
|
37
|
+
|
|
38
|
+
// Build error entry
|
|
39
|
+
const errorEntry = {
|
|
40
|
+
type,
|
|
41
|
+
message: message || error?.message,
|
|
42
|
+
stack: error?.stack,
|
|
43
|
+
context,
|
|
44
|
+
timestamp: new Date().toISOString()
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Add to errors array
|
|
48
|
+
this.errors.push(errorEntry);
|
|
49
|
+
|
|
50
|
+
// Enforce max size (FIFO)
|
|
51
|
+
if (this.errors.length > this.maxErrors) {
|
|
52
|
+
this.errors.shift(); // Remove oldest
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get all tracked errors
|
|
58
|
+
* @returns {Array} Array of error objects
|
|
59
|
+
*/
|
|
60
|
+
getErrors() {
|
|
61
|
+
// Return copy to prevent external modification
|
|
62
|
+
return [...this.errors];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get errors filtered by type
|
|
67
|
+
* @param {string} type - Error type to filter by
|
|
68
|
+
* @returns {Array} Array of errors matching type
|
|
69
|
+
*/
|
|
70
|
+
getErrorsByType(type) {
|
|
71
|
+
return this.errors.filter(error => error.type === type);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get error statistics
|
|
76
|
+
* @returns {Object} Statistics with total and breakdown by type
|
|
77
|
+
*/
|
|
78
|
+
getErrorStats() {
|
|
79
|
+
const stats = {
|
|
80
|
+
total: this.errors.length,
|
|
81
|
+
byType: {
|
|
82
|
+
ROUTING_ERROR: 0,
|
|
83
|
+
EXECUTION_ERROR: 0,
|
|
84
|
+
VALIDATION_ERROR: 0
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
this.errors.forEach(error => {
|
|
89
|
+
if (stats.byType[error.type] !== undefined) {
|
|
90
|
+
stats.byType[error.type]++;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
return stats;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Clear all tracked errors
|
|
99
|
+
*/
|
|
100
|
+
clearErrors() {
|
|
101
|
+
this.errors = [];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = ErrorTracker;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger - Winston-based structured logging
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - JSON format logging
|
|
6
|
+
* - File + Console output
|
|
7
|
+
* - Methods: logTaskRouting(), logTaskExecution(), logError()
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const winston = require('winston');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
class Logger {
|
|
15
|
+
constructor(options = {}) {
|
|
16
|
+
const {
|
|
17
|
+
logDir = path.join(process.cwd(), 'logs'),
|
|
18
|
+
logFile = 'byan.log',
|
|
19
|
+
consoleOutput = true,
|
|
20
|
+
level = 'info'
|
|
21
|
+
} = options;
|
|
22
|
+
|
|
23
|
+
this.logDir = logDir;
|
|
24
|
+
this.logFile = logFile;
|
|
25
|
+
this.logPath = path.join(logDir, logFile);
|
|
26
|
+
|
|
27
|
+
// Ensure log directory exists
|
|
28
|
+
if (!fs.existsSync(logDir)) {
|
|
29
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Configure transports
|
|
33
|
+
const transports = [
|
|
34
|
+
new winston.transports.File({
|
|
35
|
+
filename: this.logPath,
|
|
36
|
+
format: winston.format.json()
|
|
37
|
+
})
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
if (consoleOutput) {
|
|
41
|
+
transports.push(
|
|
42
|
+
new winston.transports.Console({
|
|
43
|
+
format: winston.format.combine(
|
|
44
|
+
winston.format.colorize(),
|
|
45
|
+
winston.format.simple()
|
|
46
|
+
)
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Create Winston logger
|
|
52
|
+
this.logger = winston.createLogger({
|
|
53
|
+
level,
|
|
54
|
+
format: winston.format.combine(
|
|
55
|
+
winston.format.timestamp(),
|
|
56
|
+
winston.format.json()
|
|
57
|
+
),
|
|
58
|
+
transports
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Log task routing decision
|
|
64
|
+
* @param {Object} routingData - Routing decision data
|
|
65
|
+
*/
|
|
66
|
+
logTaskRouting(routingData) {
|
|
67
|
+
if (!routingData) return;
|
|
68
|
+
|
|
69
|
+
const { task, executor, complexity, canFallback, reasoning } = routingData;
|
|
70
|
+
|
|
71
|
+
this.logger.info('Task routing decision', {
|
|
72
|
+
taskType: task?.type,
|
|
73
|
+
prompt: task?.prompt,
|
|
74
|
+
metadata: task?.metadata,
|
|
75
|
+
executor,
|
|
76
|
+
complexity,
|
|
77
|
+
canFallback,
|
|
78
|
+
reasoning
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Log task execution result
|
|
84
|
+
* @param {Object} executionData - Execution result data
|
|
85
|
+
*/
|
|
86
|
+
logTaskExecution(executionData) {
|
|
87
|
+
if (!executionData) return;
|
|
88
|
+
|
|
89
|
+
const { task, executor, duration, success, result, error, tokens } = executionData;
|
|
90
|
+
|
|
91
|
+
this.logger.info('Task execution completed', {
|
|
92
|
+
taskType: task?.type,
|
|
93
|
+
prompt: task?.prompt,
|
|
94
|
+
executor,
|
|
95
|
+
duration,
|
|
96
|
+
success,
|
|
97
|
+
result,
|
|
98
|
+
error,
|
|
99
|
+
tokens
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Log error with context
|
|
105
|
+
* @param {Object} errorData - Error data with type, message, error, context
|
|
106
|
+
*/
|
|
107
|
+
logError(errorData) {
|
|
108
|
+
if (!errorData) return;
|
|
109
|
+
|
|
110
|
+
const { type, message, error, context } = errorData;
|
|
111
|
+
|
|
112
|
+
this.logger.error(message || 'Error occurred', {
|
|
113
|
+
errorType: type,
|
|
114
|
+
stack: error?.stack,
|
|
115
|
+
context
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Generic info log
|
|
121
|
+
* @param {string} message - Log message
|
|
122
|
+
* @param {Object} data - Additional data
|
|
123
|
+
*/
|
|
124
|
+
info(message, data = {}) {
|
|
125
|
+
this.logger.info(message, data);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Generic warn log
|
|
130
|
+
* @param {string} message - Log message
|
|
131
|
+
* @param {Object} data - Additional data
|
|
132
|
+
*/
|
|
133
|
+
warn(message, data = {}) {
|
|
134
|
+
this.logger.warn(message, data);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Generic error log
|
|
139
|
+
* @param {string} message - Log message
|
|
140
|
+
* @param {Object} data - Additional data
|
|
141
|
+
*/
|
|
142
|
+
error(message, data = {}) {
|
|
143
|
+
this.logger.error(message, data);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Close logger and flush transports
|
|
148
|
+
*/
|
|
149
|
+
close() {
|
|
150
|
+
this.logger.close();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = Logger;
|