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.
Files changed (240) hide show
  1. package/API-BYAN-V2.md +741 -0
  2. package/BMAD-QUICK-REFERENCE.md +370 -0
  3. package/CHANGELOG-v2.1.0.md +371 -0
  4. package/LICENSE +1 -1
  5. package/MIGRATION-v2.0-to-v2.1.md +430 -0
  6. package/README-BYAN-V2.md +446 -0
  7. package/README.md +264 -201
  8. package/install/.eslintrc.js +20 -0
  9. package/install/.prettierrc +7 -0
  10. package/install/BUGFIX-CHALK.md +173 -0
  11. package/install/BUGFIX-DOCUMENTATION-INDEX.md +299 -0
  12. package/install/BUGFIX-PATH-RESOLUTION.md +293 -0
  13. package/install/BUGFIX-QUICKSTART.md +184 -0
  14. package/install/BUGFIX-SUMMARY.txt +91 -0
  15. package/install/BUGFIX-VISUAL-SUMMARY.md +253 -0
  16. package/install/DEPLOYMENT-GUIDE-V2.md +431 -0
  17. package/install/DOCS-INDEX.md +261 -0
  18. package/install/GUIDE-INSTALLATION-BYAN-SIMPLE.md +1083 -0
  19. package/install/INSTALLER-V2-CHANGES.md +472 -0
  20. package/install/LICENSE +21 -0
  21. package/install/PUBLICATION-CHECKLIST.md +265 -0
  22. package/install/PUBLISH-GUIDE.md +190 -0
  23. package/install/QUICKSTART.md +311 -0
  24. package/install/README-NPM-PUBLISH.md +298 -0
  25. package/install/README-NPM-SHORT.md +298 -0
  26. package/install/README-NPM.md +433 -0
  27. package/install/README-RACHID.md +302 -0
  28. package/install/README-V2-INDEX.md +306 -0
  29. package/install/README.md +298 -0
  30. package/install/RESUME-EXECUTIF-YAN.md +408 -0
  31. package/install/UPDATE-SUMMARY.md +205 -0
  32. package/install/__tests__/integration/detection-flow.test.js +154 -0
  33. package/install/__tests__/platforms/claude-code.test.js +175 -0
  34. package/install/__tests__/platforms/codex.test.js +80 -0
  35. package/install/__tests__/platforms/copilot-cli.test.js +118 -0
  36. package/install/__tests__/platforms/vscode.test.js +67 -0
  37. package/install/__tests__/utils/file-utils.test.js +87 -0
  38. package/install/__tests__/utils/git-detector.test.js +80 -0
  39. package/install/__tests__/utils/logger.test.js +83 -0
  40. package/install/__tests__/utils/node-detector.test.js +71 -0
  41. package/install/__tests__/utils/os-detector.test.js +63 -0
  42. package/install/__tests__/utils/yaml-utils.test.js +85 -0
  43. package/install/__tests__/yanstaller/detector.test.js +210 -0
  44. package/install/coverage/clover.xml +219 -0
  45. package/install/coverage/coverage-final.json +13 -0
  46. package/install/coverage/lcov-report/base.css +224 -0
  47. package/install/coverage/lcov-report/block-navigation.js +87 -0
  48. package/install/coverage/lcov-report/favicon.png +0 -0
  49. package/install/coverage/lcov-report/index.html +146 -0
  50. package/install/coverage/lcov-report/lib/errors.js.html +268 -0
  51. package/install/coverage/lcov-report/lib/exit-codes.js.html +247 -0
  52. package/install/coverage/lcov-report/lib/index.html +131 -0
  53. package/install/coverage/lcov-report/lib/platforms/claude-code.js.html +343 -0
  54. package/install/coverage/lcov-report/lib/platforms/codex.js.html +361 -0
  55. package/install/coverage/lcov-report/lib/platforms/copilot-cli.js.html +454 -0
  56. package/install/coverage/lcov-report/lib/platforms/index.html +176 -0
  57. package/install/coverage/lcov-report/lib/platforms/index.js.html +127 -0
  58. package/install/coverage/lcov-report/lib/platforms/vscode.js.html +238 -0
  59. package/install/coverage/lcov-report/lib/utils/config-loader.js.html +322 -0
  60. package/install/coverage/lcov-report/lib/utils/file-utils.js.html +397 -0
  61. package/install/coverage/lcov-report/lib/utils/git-detector.js.html +190 -0
  62. package/install/coverage/lcov-report/lib/utils/index.html +206 -0
  63. package/install/coverage/lcov-report/lib/utils/logger.js.html +277 -0
  64. package/install/coverage/lcov-report/lib/utils/node-detector.js.html +259 -0
  65. package/install/coverage/lcov-report/lib/utils/os-detector.js.html +307 -0
  66. package/install/coverage/lcov-report/lib/utils/yaml-utils.js.html +346 -0
  67. package/install/coverage/lcov-report/lib/yanstaller/backuper.js.html +409 -0
  68. package/install/coverage/lcov-report/lib/yanstaller/detector.js.html +508 -0
  69. package/install/coverage/lcov-report/lib/yanstaller/index.html +236 -0
  70. package/install/coverage/lcov-report/lib/yanstaller/index.js.html +364 -0
  71. package/install/coverage/lcov-report/lib/yanstaller/installer.js.html +505 -0
  72. package/install/coverage/lcov-report/lib/yanstaller/interviewer.js.html +349 -0
  73. package/install/coverage/lcov-report/lib/yanstaller/recommender.js.html +379 -0
  74. package/install/coverage/lcov-report/lib/yanstaller/troubleshooter.js.html +352 -0
  75. package/install/coverage/lcov-report/lib/yanstaller/validator.js.html +679 -0
  76. package/install/coverage/lcov-report/lib/yanstaller/wizard.js.html +412 -0
  77. package/install/coverage/lcov-report/platforms/claude-code.js.html +343 -0
  78. package/install/coverage/lcov-report/platforms/codex.js.html +361 -0
  79. package/install/coverage/lcov-report/platforms/copilot-cli.js.html +454 -0
  80. package/install/coverage/lcov-report/platforms/index.html +176 -0
  81. package/install/coverage/lcov-report/platforms/index.js.html +127 -0
  82. package/install/coverage/lcov-report/platforms/vscode.js.html +238 -0
  83. package/install/coverage/lcov-report/prettify.css +1 -0
  84. package/install/coverage/lcov-report/prettify.js +2 -0
  85. package/install/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  86. package/install/coverage/lcov-report/sorter.js +210 -0
  87. package/install/coverage/lcov-report/utils/file-utils.js.html +397 -0
  88. package/install/coverage/lcov-report/utils/git-detector.js.html +190 -0
  89. package/install/coverage/lcov-report/utils/index.html +191 -0
  90. package/install/coverage/lcov-report/utils/logger.js.html +277 -0
  91. package/install/coverage/lcov-report/utils/node-detector.js.html +259 -0
  92. package/install/coverage/lcov-report/utils/os-detector.js.html +307 -0
  93. package/install/coverage/lcov-report/utils/yaml-utils.js.html +346 -0
  94. package/install/coverage/lcov-report/yanstaller/detector.js.html +508 -0
  95. package/install/coverage/lcov-report/yanstaller/index.html +116 -0
  96. package/install/coverage/lcov.info +414 -0
  97. package/install/install.sh +239 -0
  98. package/install/jest.config.js +33 -0
  99. package/install/lib/errors.js +61 -0
  100. package/install/lib/exit-codes.js +54 -0
  101. package/install/lib/platforms/claude-code.js +86 -0
  102. package/install/lib/platforms/codex.js +92 -0
  103. package/install/lib/platforms/copilot-cli.js +123 -0
  104. package/install/lib/platforms/index.js +14 -0
  105. package/install/lib/platforms/vscode.js +51 -0
  106. package/install/lib/utils/config-loader.js +79 -0
  107. package/install/lib/utils/file-utils.js +104 -0
  108. package/install/lib/utils/git-detector.js +35 -0
  109. package/install/lib/utils/logger.js +64 -0
  110. package/install/lib/utils/node-detector.js +58 -0
  111. package/install/lib/utils/os-detector.js +74 -0
  112. package/install/lib/utils/yaml-utils.js +87 -0
  113. package/install/lib/yanstaller/backuper.js +108 -0
  114. package/install/lib/yanstaller/detector.js +141 -0
  115. package/install/lib/yanstaller/index.js +93 -0
  116. package/install/lib/yanstaller/installer.js +140 -0
  117. package/install/lib/yanstaller/interviewer.js +88 -0
  118. package/install/lib/yanstaller/recommender.js +98 -0
  119. package/install/lib/yanstaller/troubleshooter.js +89 -0
  120. package/install/lib/yanstaller/validator.js +198 -0
  121. package/install/lib/yanstaller/wizard.js +109 -0
  122. package/install/package-npm.json +55 -0
  123. package/install/package.json +63 -0
  124. package/install/src/byan-v2/context/copilot-context.js +79 -0
  125. package/install/src/byan-v2/context/session-state.js +98 -0
  126. package/install/src/byan-v2/dispatcher/complexity-scorer.js +232 -0
  127. package/install/src/byan-v2/dispatcher/local-executor.js +221 -0
  128. package/install/src/byan-v2/dispatcher/task-router.js +122 -0
  129. package/install/src/byan-v2/dispatcher/task-tool-interface-mock.js +134 -0
  130. package/install/src/byan-v2/dispatcher/task-tool-interface.js +123 -0
  131. package/install/src/byan-v2/generation/agent-profile-validator.js +113 -0
  132. package/install/src/byan-v2/generation/profile-template.js +113 -0
  133. package/install/src/byan-v2/generation/templates/default-agent.md +49 -0
  134. package/install/src/byan-v2/generation/templates/test-template.md +1 -0
  135. package/install/src/byan-v2/index.js +199 -0
  136. package/install/src/byan-v2/observability/error-tracker.js +105 -0
  137. package/install/src/byan-v2/observability/logger.js +154 -0
  138. package/install/src/byan-v2/observability/metrics-collector.js +194 -0
  139. package/install/src/byan-v2/orchestrator/analysis-state.js +268 -0
  140. package/install/src/byan-v2/orchestrator/generation-state.js +340 -0
  141. package/install/src/byan-v2/orchestrator/interview-state.js +271 -0
  142. package/install/src/byan-v2/orchestrator/state-machine.js +204 -0
  143. package/install/src/core/cache/cache.js +126 -0
  144. package/install/src/core/context/context.js +86 -0
  145. package/install/src/core/dispatcher/dispatcher.js +135 -0
  146. package/install/src/core/worker-pool/worker-pool.js +194 -0
  147. package/install/src/core/workflow/workflow-executor.js +220 -0
  148. package/install/src/index.js +139 -0
  149. package/install/src/observability/dashboard/dashboard.js +191 -0
  150. package/install/src/observability/logger/structured-logger.js +254 -0
  151. package/install/src/observability/metrics/metrics-collector.js +325 -0
  152. package/install/switch-to-v2.sh +126 -0
  153. package/install/test-chalk-fix.sh +210 -0
  154. package/install/test-installer-v2.sh +204 -0
  155. package/install/test-path-resolution.sh +200 -0
  156. package/package.json +53 -33
  157. package/src/byan-v2/context/copilot-context.js +79 -0
  158. package/src/byan-v2/context/session-state.js +98 -0
  159. package/src/byan-v2/data/mantras.json +852 -0
  160. package/src/byan-v2/dispatcher/complexity-scorer.js +232 -0
  161. package/src/byan-v2/dispatcher/five-whys-analyzer.js +310 -0
  162. package/src/byan-v2/dispatcher/local-executor.js +221 -0
  163. package/src/byan-v2/dispatcher/task-router.js +122 -0
  164. package/src/byan-v2/dispatcher/task-tool-interface-mock.js +134 -0
  165. package/src/byan-v2/dispatcher/task-tool-interface.js +123 -0
  166. package/src/byan-v2/generation/agent-profile-validator.js +113 -0
  167. package/src/byan-v2/generation/mantra-validator.js +416 -0
  168. package/src/byan-v2/generation/profile-template.js +113 -0
  169. package/src/byan-v2/generation/templates/default-agent.md +49 -0
  170. package/src/byan-v2/generation/templates/test-template.md +1 -0
  171. package/src/byan-v2/index.js +652 -0
  172. package/src/byan-v2/integration/voice-integration.js +295 -0
  173. package/src/byan-v2/observability/error-tracker.js +105 -0
  174. package/src/byan-v2/observability/logger.js +154 -0
  175. package/src/byan-v2/observability/metrics-collector.js +194 -0
  176. package/src/byan-v2/orchestrator/active-listener.js +541 -0
  177. package/src/byan-v2/orchestrator/analysis-state.js +268 -0
  178. package/src/byan-v2/orchestrator/generation-state.js +340 -0
  179. package/src/byan-v2/orchestrator/glossary-builder.js +431 -0
  180. package/src/byan-v2/orchestrator/interview-state.js +353 -0
  181. package/src/byan-v2/orchestrator/state-machine.js +253 -0
  182. package/src/core/cache/cache.js +126 -0
  183. package/src/core/context/context.js +86 -0
  184. package/src/core/dispatcher/dispatcher.js +135 -0
  185. package/src/core/worker-pool/worker-pool.js +194 -0
  186. package/src/core/workflow/workflow-executor.js +220 -0
  187. package/src/index.js +139 -0
  188. package/src/observability/dashboard/dashboard.js +191 -0
  189. package/src/observability/logger/structured-logger.js +254 -0
  190. package/src/observability/metrics/metrics-collector.js +325 -0
  191. package/templates/.github/agents/bmad-agent-test-dynamic.md +0 -21
  192. package/templates/.github/agents/franck.md +0 -379
  193. /package/{CHANGELOG.md → install/CHANGELOG.md} +0 -0
  194. /package/{bin → install/bin}/create-byan-agent-backup.js +0 -0
  195. /package/{bin → install/bin}/create-byan-agent-fixed.js +0 -0
  196. /package/{bin → install/bin}/create-byan-agent-v2.js +0 -0
  197. /package/{bin → install/bin}/create-byan-agent.js +0 -0
  198. /package/{templates → install/templates}/.github/agents/bmad-agent-bmad-master.md +0 -0
  199. /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-agent-builder.md +0 -0
  200. /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-module-builder.md +0 -0
  201. /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-workflow-builder.md +0 -0
  202. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-analyst.md +0 -0
  203. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-architect.md +0 -0
  204. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-dev.md +0 -0
  205. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-pm.md +0 -0
  206. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-quick-flow-solo-dev.md +0 -0
  207. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-quinn.md +0 -0
  208. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-sm.md +0 -0
  209. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-tech-writer.md +0 -0
  210. /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-ux-designer.md +0 -0
  211. /package/{templates → install/templates}/.github/agents/bmad-agent-byan-test.md +0 -0
  212. /package/{templates → install/templates}/.github/agents/bmad-agent-byan.md +0 -0
  213. /package/{templates → install/templates}/.github/agents/bmad-agent-carmack.md +0 -0
  214. /package/{templates → install/templates}/.github/agents/bmad-agent-cis-brainstorming-coach.md +0 -0
  215. /package/{templates → install/templates}/.github/agents/bmad-agent-cis-creative-problem-solver.md +0 -0
  216. /package/{templates → install/templates}/.github/agents/bmad-agent-cis-design-thinking-coach.md +0 -0
  217. /package/{templates → install/templates}/.github/agents/bmad-agent-cis-innovation-strategist.md +0 -0
  218. /package/{templates → install/templates}/.github/agents/bmad-agent-cis-presentation-master.md +0 -0
  219. /package/{templates → install/templates}/.github/agents/bmad-agent-cis-storyteller.md +0 -0
  220. /package/{templates → install/templates}/.github/agents/bmad-agent-marc.md +0 -0
  221. /package/{templates → install/templates}/.github/agents/bmad-agent-patnote.md +0 -0
  222. /package/{templates → install/templates}/.github/agents/bmad-agent-rachid.md +0 -0
  223. /package/{templates → install/templates}/.github/agents/bmad-agent-tea-tea.md +0 -0
  224. /package/{templates → install/templates}/_bmad/bmb/agents/agent-builder.md +0 -0
  225. /package/{templates → install/templates}/_bmad/bmb/agents/byan-test.md +0 -0
  226. /package/{templates → install/templates}/_bmad/bmb/agents/byan.md +0 -0
  227. /package/{templates → install/templates}/_bmad/bmb/agents/marc.md +0 -0
  228. /package/{templates → install/templates}/_bmad/bmb/agents/module-builder.md +0 -0
  229. /package/{templates → install/templates}/_bmad/bmb/agents/patnote.md +0 -0
  230. /package/{templates → install/templates}/_bmad/bmb/agents/rachid.md +0 -0
  231. /package/{templates → install/templates}/_bmad/bmb/agents/workflow-builder.md +0 -0
  232. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/data/mantras.yaml +0 -0
  233. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/data/templates.yaml +0 -0
  234. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/delete-agent-workflow.md +0 -0
  235. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/edit-agent-workflow.md +0 -0
  236. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/interview-workflow.md +0 -0
  237. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/quick-create-workflow.md +0 -0
  238. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/templates/base-agent-template.md +0 -0
  239. /package/{templates → install/templates}/_bmad/bmb/workflows/byan/validate-agent-workflow.md +0 -0
  240. /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;