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,221 @@
1
+ /**
2
+ * LocalExecutor - Story 3.1
3
+ * Handles high-complexity tasks (>60) locally without delegation
4
+ *
5
+ * Integrates:
6
+ * - Logger: Log execution start/completion
7
+ * - MetricsCollector: Track execution metrics
8
+ * - ErrorTracker: Track errors
9
+ */
10
+
11
+ const Logger = require('../observability/logger');
12
+ const ErrorTracker = require('../observability/error-tracker');
13
+ const MetricsCollector = require('../observability/metrics-collector');
14
+
15
+ class LocalExecutor {
16
+ constructor() {
17
+ this.logger = new Logger();
18
+ this.errorTracker = new ErrorTracker();
19
+ this.metricsCollector = new MetricsCollector();
20
+ }
21
+
22
+ /**
23
+ * AC2: Execute task locally without delegation
24
+ * AC3: Returns { output, tokens, duration, executor: 'local' }
25
+ *
26
+ * @param {Object} task - Task object { type, prompt, complexity, metadata? }
27
+ * @returns {Promise<Object>} Execution result
28
+ */
29
+ async execute(task) {
30
+ const startTime = Date.now();
31
+
32
+ try {
33
+ // AC6: Validate task
34
+ if (!task || typeof task !== 'object') {
35
+ const error = new Error('Task must be a valid object');
36
+ this.errorTracker.track({
37
+ error,
38
+ component: 'LocalExecutor',
39
+ operation: 'execute',
40
+ task
41
+ });
42
+ throw error;
43
+ }
44
+
45
+ // AC5: Log execution start
46
+ this.logger.info('Local execution started', {
47
+ type: task.type,
48
+ complexity: task.complexity,
49
+ promptLength: task.prompt?.length || 0
50
+ });
51
+
52
+ // AC2: Process task locally (no delegation)
53
+ const output = await this._processTaskLocally(task);
54
+
55
+ // Calculate metrics
56
+ const duration = Date.now() - startTime;
57
+ const tokens = this._estimateTokens(task.prompt, output);
58
+
59
+ // AC3: Build result object
60
+ const result = {
61
+ output,
62
+ tokens,
63
+ duration,
64
+ executor: 'local'
65
+ };
66
+
67
+ // AC4: Record metrics
68
+ this.metricsCollector.recordTaskExecution({
69
+ executor: 'local',
70
+ duration,
71
+ tokens,
72
+ success: true,
73
+ taskType: task.type,
74
+ complexity: task.complexity
75
+ });
76
+
77
+ // AC5: Log completion
78
+ this.logger.info('Local execution completed', {
79
+ duration,
80
+ tokens,
81
+ outputLength: output.length
82
+ });
83
+
84
+ return result;
85
+
86
+ } catch (error) {
87
+ const duration = Date.now() - startTime;
88
+
89
+ // AC6: Track error
90
+ this.errorTracker.track({
91
+ error,
92
+ component: 'LocalExecutor',
93
+ operation: 'execute',
94
+ task,
95
+ duration
96
+ });
97
+
98
+ // Record failed execution
99
+ this.metricsCollector.recordTaskExecution({
100
+ executor: 'local',
101
+ duration,
102
+ tokens: 0,
103
+ success: false,
104
+ error: error.message
105
+ });
106
+
107
+ throw error;
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Process task using BYAN's expertise
113
+ * Simulates local processing for analysis/generation tasks
114
+ * @private
115
+ */
116
+ async _processTaskLocally(task) {
117
+ const { type, prompt, metadata = {} } = task;
118
+
119
+ // Simulate processing based on task type
120
+ switch (type) {
121
+ case 'analysis':
122
+ return this._processAnalysisTask(prompt, metadata);
123
+
124
+ case 'generation':
125
+ return this._processGenerationTask(prompt, metadata);
126
+
127
+ case 'task':
128
+ case 'general-purpose':
129
+ return this._processGeneralTask(prompt, metadata);
130
+
131
+ default:
132
+ return this._processGenericTask(prompt, metadata);
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Process analysis tasks (extract requirements, patterns)
138
+ * @private
139
+ */
140
+ _processAnalysisTask(prompt, metadata) {
141
+ // Simulated analysis output
142
+ const analysis = {
143
+ type: 'analysis',
144
+ input: prompt,
145
+ findings: [
146
+ 'Identified key requirements from prompt',
147
+ 'Detected patterns and themes',
148
+ 'Extracted structured information'
149
+ ],
150
+ context: metadata.context || {},
151
+ timestamp: new Date().toISOString()
152
+ };
153
+
154
+ return JSON.stringify(analysis, null, 2);
155
+ }
156
+
157
+ /**
158
+ * Process generation tasks (create agent profiles, content)
159
+ * @private
160
+ */
161
+ _processGenerationTask(prompt, metadata) {
162
+ // Simulated generation output
163
+ const generation = {
164
+ type: 'generation',
165
+ prompt,
166
+ generated: 'Generated content based on requirements',
167
+ metadata: metadata,
168
+ timestamp: new Date().toISOString()
169
+ };
170
+
171
+ return JSON.stringify(generation, null, 2);
172
+ }
173
+
174
+ /**
175
+ * Process general/task type tasks
176
+ * @private
177
+ */
178
+ _processGeneralTask(prompt, metadata) {
179
+ const result = {
180
+ type: 'general',
181
+ input: prompt,
182
+ output: 'Processed task locally with full BYAN expertise',
183
+ metadata,
184
+ timestamp: new Date().toISOString()
185
+ };
186
+
187
+ return JSON.stringify(result, null, 2);
188
+ }
189
+
190
+ /**
191
+ * Process generic tasks (fallback)
192
+ * @private
193
+ */
194
+ _processGenericTask(prompt, metadata) {
195
+ const result = {
196
+ type: 'generic',
197
+ input: prompt || '',
198
+ output: 'Processed with local executor',
199
+ metadata,
200
+ timestamp: new Date().toISOString()
201
+ };
202
+
203
+ return JSON.stringify(result, null, 2);
204
+ }
205
+
206
+ /**
207
+ * Estimate token count from input/output
208
+ * Simple heuristic: ~1.3 tokens per word
209
+ * @private
210
+ */
211
+ _estimateTokens(prompt = '', output = '') {
212
+ const promptWords = prompt.split(/\s+/).filter(w => w.length > 0).length;
213
+ const outputWords = output.split(/\s+/).filter(w => w.length > 0).length;
214
+
215
+ // Rough token estimation
216
+ const totalWords = promptWords + outputWords;
217
+ return Math.ceil(totalWords * 1.3);
218
+ }
219
+ }
220
+
221
+ module.exports = LocalExecutor;
@@ -0,0 +1,122 @@
1
+ /**
2
+ * TaskRouter - Routes tasks based on complexity
3
+ * Integrates ComplexityScorer + TaskToolInterface
4
+ *
5
+ * Thresholds:
6
+ * - < 30: task-tool only
7
+ * - 30-60: task-tool with fallback capability
8
+ * - > 60: local execution
9
+ */
10
+
11
+ class ComplexityScorer {
12
+ /**
13
+ * Calculate task complexity score (0-100)
14
+ * Based on: prompt length, type, metadata indicators
15
+ */
16
+ calculateComplexity(task) {
17
+ if (!task || typeof task !== 'object') {
18
+ return 0;
19
+ }
20
+
21
+ let score = 0;
22
+
23
+ // Base score from prompt length
24
+ const prompt = task.prompt || '';
25
+ const wordCount = prompt.split(/\s+/).filter(w => w.length > 0).length;
26
+ score += Math.min(wordCount * 0.4, 20); // Max 20 points from length
27
+
28
+ // Type-based scoring
29
+ const typeScores = {
30
+ 'explore': 8,
31
+ 'task': 28,
32
+ 'general-purpose': 50,
33
+ 'code-review': 40
34
+ };
35
+ score += typeScores[task.type] || 20;
36
+
37
+ // Metadata indicators
38
+ const metadata = task.metadata || {};
39
+ if (metadata.requiresContext) score += 10;
40
+ if (metadata.requiresMultipleSteps) score += 20;
41
+ if (metadata.requiresReasoning) score += 15;
42
+ if (metadata.estimatedDuration === 'medium') score += 8;
43
+ if (metadata.estimatedDuration === 'long') score += 20;
44
+
45
+ // Keyword analysis in prompt
46
+ const complexityKeywords = [
47
+ 'refactor', 'architecture', 'design', 'comprehensive',
48
+ 'multiple', 'across', 'entire', 'system', 'migration',
49
+ 'analyze', 'detailed'
50
+ ];
51
+
52
+ const lowerPrompt = prompt.toLowerCase();
53
+ complexityKeywords.forEach(keyword => {
54
+ if (lowerPrompt.includes(keyword)) {
55
+ score += 3;
56
+ }
57
+ });
58
+
59
+ // Cap at 100
60
+ return Math.min(Math.round(score), 100);
61
+ }
62
+ }
63
+
64
+ class TaskRouter {
65
+ constructor(customThresholds = {}) {
66
+ this.thresholds = {
67
+ taskToolOnly: customThresholds.taskToolOnly || 30,
68
+ taskToolWithFallback: customThresholds.taskToolWithFallback || 60
69
+ };
70
+
71
+ this.complexityScorer = new ComplexityScorer();
72
+ }
73
+
74
+ /**
75
+ * Route a task to appropriate executor
76
+ * @param {Object} task - Task object with type, prompt, metadata
77
+ * @returns {Object} Routing decision with executor, canFallback, complexity, reasoning
78
+ */
79
+ routeTask(task) {
80
+ // Validation
81
+ if (!task) {
82
+ throw new Error('Task cannot be null or undefined');
83
+ }
84
+
85
+ if (typeof task !== 'object' || Array.isArray(task)) {
86
+ throw new Error('Task must be an object');
87
+ }
88
+
89
+ // Calculate complexity
90
+ const complexity = this.complexityScorer.calculateComplexity(task);
91
+
92
+ // Determine executor and fallback capability
93
+ let executor;
94
+ let canFallback;
95
+ let reasoning;
96
+
97
+ if (complexity < this.thresholds.taskToolOnly) {
98
+ executor = 'task-tool';
99
+ canFallback = false;
100
+ reasoning = `Low complexity (${complexity}) - routing to task-tool only`;
101
+ } else if (complexity <= this.thresholds.taskToolWithFallback) {
102
+ executor = 'task-tool';
103
+ canFallback = true;
104
+ reasoning = `Medium complexity (${complexity}) - routing to task-tool with fallback capability`;
105
+ } else {
106
+ executor = 'local';
107
+ canFallback = false;
108
+ reasoning = `High complexity (${complexity}) - routing to local execution for comprehensive handling`;
109
+ }
110
+
111
+ return {
112
+ executor,
113
+ canFallback,
114
+ complexity,
115
+ task,
116
+ reasoning,
117
+ timestamp: new Date().toISOString()
118
+ };
119
+ }
120
+ }
121
+
122
+ module.exports = TaskRouter;
@@ -0,0 +1,134 @@
1
+ /**
2
+ * MockTaskToolInterface - Test double for TaskToolInterface
3
+ *
4
+ * Simulates GitHub Copilot Task Tool behavior for testing:
5
+ * - Predefined responses
6
+ * - Configurable delays
7
+ * - Call history tracking
8
+ * - Error simulation
9
+ */
10
+
11
+ const VALID_AGENT_TYPES = ['task', 'explore', 'general-purpose'];
12
+
13
+ class MockTaskToolInterface {
14
+ constructor(options = {}) {
15
+ this.delay = options.delay !== undefined ? options.delay : this._randomDelay();
16
+ this.responses = options.responses || {};
17
+ this.behavior = options.behavior || null;
18
+ this.callHistory = [];
19
+ this.maxRetries = options.maxRetries !== undefined ? options.maxRetries : 1;
20
+ }
21
+
22
+ /**
23
+ * Mock delegateTask - simulates Task Tool call
24
+ */
25
+ async delegateTask(taskPrompt, agentType) {
26
+ // Validation (same as real implementation)
27
+ if (!taskPrompt || taskPrompt.trim() === '') {
28
+ throw new Error('taskPrompt cannot be empty');
29
+ }
30
+
31
+ if (!agentType) {
32
+ throw new Error('agentType is required');
33
+ }
34
+
35
+ if (!VALID_AGENT_TYPES.includes(agentType)) {
36
+ throw new Error(`Invalid agent type: ${agentType}. Valid types: ${VALID_AGENT_TYPES.join(', ')}`);
37
+ }
38
+
39
+ // Record call
40
+ const call = {
41
+ prompt: taskPrompt,
42
+ agentType: agentType,
43
+ timestamp: Date.now()
44
+ };
45
+ this.callHistory.push(call);
46
+
47
+ // Simulate delay
48
+ await this._sleep(this.delay);
49
+
50
+ // Use custom behavior if provided (with retry logic for transient errors)
51
+ if (this.behavior) {
52
+ const TRANSIENT_ERRORS = ['ECONNRESET', 'ETIMEDOUT', 'ECONNREFUSED'];
53
+ let lastError;
54
+
55
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
56
+ try {
57
+ return this.behavior(taskPrompt, agentType);
58
+ } catch (error) {
59
+ lastError = error;
60
+
61
+ // Only retry on transient errors and if we have retries left
62
+ const isTransient = TRANSIENT_ERRORS.some(errCode => error.message.includes(errCode));
63
+ if (isTransient && attempt < this.maxRetries) {
64
+ await this._sleep(this.delay);
65
+ continue;
66
+ }
67
+
68
+ // Non-transient error or out of retries - throw immediately
69
+ break;
70
+ }
71
+ }
72
+
73
+ throw lastError;
74
+ }
75
+
76
+ // Check for predefined response
77
+ if (this.responses[taskPrompt]) {
78
+ return this.responses[taskPrompt];
79
+ }
80
+
81
+ // Generate default response
82
+ return this._generateDefaultResponse(taskPrompt, agentType);
83
+ }
84
+
85
+ /**
86
+ * Generate realistic mock response
87
+ */
88
+ _generateDefaultResponse(taskPrompt, agentType) {
89
+ const outputMap = {
90
+ 'task': `Task completed: ${taskPrompt}`,
91
+ 'explore': `Exploration results for: ${taskPrompt}`,
92
+ 'general-purpose': `General analysis: ${taskPrompt}`
93
+ };
94
+
95
+ return {
96
+ output: outputMap[agentType] || `Response for: ${taskPrompt}`,
97
+ metadata: {
98
+ tokens: Math.floor(Math.random() * 1000) + 100,
99
+ duration: Math.floor(Math.random() * 2000) + 500,
100
+ agentType: agentType
101
+ }
102
+ };
103
+ }
104
+
105
+ /**
106
+ * Random delay between 100-500ms
107
+ */
108
+ _randomDelay() {
109
+ return Math.floor(Math.random() * 400) + 100;
110
+ }
111
+
112
+ /**
113
+ * Sleep utility
114
+ */
115
+ _sleep(ms) {
116
+ return new Promise(resolve => setTimeout(resolve, ms));
117
+ }
118
+
119
+ /**
120
+ * Get call history
121
+ */
122
+ getCallHistory() {
123
+ return [...this.callHistory];
124
+ }
125
+
126
+ /**
127
+ * Clear call history
128
+ */
129
+ clearHistory() {
130
+ this.callHistory = [];
131
+ }
132
+ }
133
+
134
+ module.exports = MockTaskToolInterface;
@@ -0,0 +1,123 @@
1
+ /**
2
+ * TaskToolInterface - Interface to GitHub Copilot CLI Task Tool
3
+ *
4
+ * IMPORTANT: GitHub Copilot CLI does NOT expose a programmatic API for Task Tool.
5
+ * This is a conceptual interface for BYAN v2.0 architecture design.
6
+ *
7
+ * In production, this would:
8
+ * 1. Use future Copilot SDK when available
9
+ * 2. Or shell out to `gh copilot` CLI commands
10
+ * 3. Or use inter-process communication with Copilot CLI
11
+ *
12
+ * For MVP, this is a stub with comprehensive tests using MockTaskToolInterface.
13
+ */
14
+
15
+ const VALID_AGENT_TYPES = ['task', 'explore', 'general-purpose'];
16
+ const DEFAULT_TIMEOUT = 30000; // 30 seconds
17
+ const TRANSIENT_ERRORS = ['ECONNRESET', 'ETIMEDOUT', 'ECONNREFUSED'];
18
+
19
+ class TaskToolInterface {
20
+ constructor(options = {}) {
21
+ this.timeout = options.timeout || DEFAULT_TIMEOUT;
22
+ this.maxRetries = options.maxRetries || 1;
23
+ }
24
+
25
+ /**
26
+ * Delegate task to GitHub Copilot agent via Task Tool
27
+ *
28
+ * @param {string} taskPrompt - The task description for the agent
29
+ * @param {string} agentType - Agent type: 'task', 'explore', or 'general-purpose'
30
+ * @returns {Promise<{output: string, metadata: {tokens: number, duration: number}}>}
31
+ */
32
+ async delegateTask(taskPrompt, agentType) {
33
+ // Validation
34
+ if (!taskPrompt || taskPrompt.trim() === '') {
35
+ throw new Error('taskPrompt cannot be empty');
36
+ }
37
+
38
+ if (!agentType) {
39
+ throw new Error('agentType is required');
40
+ }
41
+
42
+ if (!VALID_AGENT_TYPES.includes(agentType)) {
43
+ throw new Error(`Invalid agent type: ${agentType}. Valid types: ${VALID_AGENT_TYPES.join(', ')}`);
44
+ }
45
+
46
+ // Attempt execution with retry logic
47
+ let lastError;
48
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
49
+ try {
50
+ return await this._executeTaskWithTimeout(taskPrompt, agentType);
51
+ } catch (error) {
52
+ lastError = error;
53
+
54
+ // Only retry on transient errors and if we have retries left
55
+ const isTransient = TRANSIENT_ERRORS.some(errCode => error.message.includes(errCode));
56
+ if (isTransient && attempt < this.maxRetries) {
57
+ continue;
58
+ }
59
+
60
+ // Non-transient error or out of retries - throw immediately
61
+ break;
62
+ }
63
+ }
64
+
65
+ throw lastError;
66
+ }
67
+
68
+ async _executeTaskWithTimeout(taskPrompt, agentType) {
69
+ return new Promise((resolve, reject) => {
70
+ const timeoutId = setTimeout(() => {
71
+ reject(new Error(`Task execution timeout after ${this.timeout}ms`));
72
+ }, this.timeout);
73
+
74
+ // TODO: Actual implementation would call Copilot Task Tool here
75
+ // For now, this is a stub that throws to force use of Mock in tests
76
+ clearTimeout(timeoutId);
77
+ reject(new Error('TaskToolInterface is a stub. Use MockTaskToolInterface for testing.'));
78
+ });
79
+ }
80
+
81
+ /**
82
+ * Build the call syntax for Task Tool (documentation)
83
+ * Format: Uses GitHub Copilot CLI agent invocation syntax
84
+ *
85
+ * @param {string} prompt - Task prompt
86
+ * @param {string} agentType - Agent type
87
+ * @returns {string} - Call syntax string
88
+ */
89
+ static buildTaskCallSyntax(prompt, agentType) {
90
+ // Escape and sanitize prompt
91
+ const sanitizedPrompt = prompt
92
+ .replace(/\n/g, ' ')
93
+ .replace(/"/g, '\\"');
94
+
95
+ // Documented syntax format (conceptual - actual CLI syntax may vary)
96
+ return `@${agentType} "${sanitizedPrompt}"`;
97
+ }
98
+
99
+ /**
100
+ * Get documentation for Task Tool call syntax
101
+ * @returns {string} - Documentation
102
+ */
103
+ static getCallSyntaxDocumentation() {
104
+ return `
105
+ GitHub Copilot CLI Task Tool Syntax (Conceptual):
106
+
107
+ @<agent_type> "<prompt>"
108
+
109
+ Where:
110
+ - agent_type: 'task' | 'explore' | 'general-purpose'
111
+ - prompt: Natural language task description
112
+
113
+ Examples:
114
+ - @task "Run all unit tests and report results"
115
+ - @explore "Find all API endpoint definitions"
116
+ - @general-purpose "Refactor authentication logic"
117
+
118
+ Note: Actual implementation depends on Copilot CLI SDK availability.
119
+ `.trim();
120
+ }
121
+ }
122
+
123
+ module.exports = TaskToolInterface;
@@ -0,0 +1,113 @@
1
+ const yaml = require('js-yaml');
2
+
3
+ class AgentProfileValidator {
4
+ validate(profileContent) {
5
+ const result = {
6
+ valid: true,
7
+ errors: [],
8
+ warnings: []
9
+ };
10
+
11
+ if (!this.checkFileSize(profileContent)) {
12
+ result.valid = false;
13
+ result.errors.push('Profile exceeds 50KB size limit');
14
+ return result;
15
+ }
16
+
17
+ const frontmatterResult = this.validateYamlFrontmatter(profileContent);
18
+ if (!frontmatterResult.valid) {
19
+ result.valid = false;
20
+ result.errors.push(...frontmatterResult.errors);
21
+ return result;
22
+ }
23
+
24
+ const { data } = frontmatterResult;
25
+
26
+ if (!data.name) {
27
+ result.valid = false;
28
+ result.errors.push('Missing required field: name');
29
+ } else if (!this.validateNameFormat(data.name)) {
30
+ result.valid = false;
31
+ result.errors.push('Invalid name format (use lowercase, alphanumeric, hyphens only)');
32
+ }
33
+
34
+ if (!data.description) {
35
+ result.valid = false;
36
+ result.errors.push('Missing required field: description');
37
+ } else if (!this.validateDescriptionLength(data.description)) {
38
+ result.valid = false;
39
+ result.errors.push('Description must be 10-200 characters');
40
+ }
41
+
42
+ if (this.detectEmojis(profileContent)) {
43
+ result.warnings.push('Emoji detected (Mantra IA-23: Zero Emoji Pollution)');
44
+ }
45
+
46
+ if (!this.hasCapabilitiesSection(profileContent)) {
47
+ result.warnings.push('No capabilities section found');
48
+ }
49
+
50
+ return result;
51
+ }
52
+
53
+ validateYamlFrontmatter(content) {
54
+ const result = {
55
+ valid: true,
56
+ errors: [],
57
+ data: null
58
+ };
59
+
60
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
61
+
62
+ if (!match) {
63
+ result.valid = false;
64
+ result.errors.push('Missing YAML frontmatter');
65
+ return result;
66
+ }
67
+
68
+ try {
69
+ result.data = yaml.load(match[1]);
70
+ } catch (e) {
71
+ result.valid = false;
72
+ result.errors.push(`Invalid YAML: ${e.message}`);
73
+ }
74
+
75
+ return result;
76
+ }
77
+
78
+ validateNameFormat(name) {
79
+ if (!name || name.length === 0) {
80
+ return false;
81
+ }
82
+
83
+ const validNameRegex = /^[a-z0-9-]+$/;
84
+ return validNameRegex.test(name);
85
+ }
86
+
87
+ validateDescriptionLength(description) {
88
+ if (!description) {
89
+ return false;
90
+ }
91
+
92
+ const len = description.length;
93
+ return len >= 10 && len <= 200;
94
+ }
95
+
96
+ detectEmojis(text) {
97
+ const emojiRegex = /[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]/u;
98
+ return emojiRegex.test(text);
99
+ }
100
+
101
+ checkFileSize(content) {
102
+ const sizeInBytes = Buffer.byteLength(content, 'utf-8');
103
+ const maxSize = 50 * 1024;
104
+ return sizeInBytes <= maxSize;
105
+ }
106
+
107
+ hasCapabilitiesSection(content) {
108
+ const capabilitiesRegex = /^#{1,3}\s+(Capabilit(y|ies))/mi;
109
+ return capabilitiesRegex.test(content);
110
+ }
111
+ }
112
+
113
+ module.exports = AgentProfileValidator;