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,541 @@
1
+ /**
2
+ * ActiveListener - Reformulates and validates user understanding
3
+ * Mantra IA-23: Zero emojis
4
+ *
5
+ * Principles: KISS, DRY, SOLID
6
+ * Performance target: < 100ms per reformulation
7
+ */
8
+
9
+ const Logger = require('../observability/logger');
10
+
11
+ class ActiveListener {
12
+ constructor(sessionState, logger = null) {
13
+ this.sessionState = sessionState;
14
+ this.logger = logger || new Logger('active-listener');
15
+ this.history = [];
16
+ this.validationFrequency = 3; // Ask for validation every N responses
17
+ this.responseCount = 0;
18
+ this.clarityThresholdMin = 0.0;
19
+ this.clarityThresholdMax = 1.0;
20
+
21
+ // Filler words to remove
22
+ this.fillerWords = [
23
+ 'um', 'uh', 'like', 'you know', 'i mean', 'sort of', 'kind of',
24
+ 'basically', 'actually', 'literally', 'really', 'very', 'just',
25
+ 'maybe', 'probably', 'perhaps', 'i guess', 'i think'
26
+ ];
27
+ }
28
+
29
+ /**
30
+ * Process user response through active listening workflow
31
+ * @param {string} userResponse - Raw user input
32
+ * @returns {Object} Listening result with reformulation and summary
33
+ */
34
+ listen(userResponse) {
35
+ const startTime = Date.now();
36
+
37
+ if (!userResponse || typeof userResponse !== 'string') {
38
+ return {
39
+ valid: false,
40
+ error: 'Invalid input: response must be a non-empty string'
41
+ };
42
+ }
43
+
44
+ this.logger.info('Processing user response', { length: userResponse.length });
45
+
46
+ const trimmed = userResponse.trim();
47
+ if (trimmed.length === 0) {
48
+ return {
49
+ valid: false,
50
+ error: 'Invalid input: response cannot be empty'
51
+ };
52
+ }
53
+
54
+ // Reformulate the response
55
+ const reformulated = this.reformulate(trimmed);
56
+
57
+ // Extract key points
58
+ const keyPoints = this.extractKeyPoints(reformulated.text);
59
+
60
+ // Generate summary
61
+ const summary = this.generateSummary(keyPoints);
62
+
63
+ // Track in history
64
+ this.responseCount++;
65
+ const record = {
66
+ original: trimmed,
67
+ reformulated: reformulated.text,
68
+ clarityScore: reformulated.clarityScore,
69
+ keyPoints: keyPoints,
70
+ summary: summary,
71
+ timestamp: Date.now(),
72
+ needsValidation: this.needsValidation()
73
+ };
74
+ this.history.push(record);
75
+
76
+ const duration = Date.now() - startTime;
77
+ this.logger.info('Response processed', {
78
+ duration: duration,
79
+ clarityScore: reformulated.clarityScore,
80
+ keyPointsCount: keyPoints.length
81
+ });
82
+
83
+ return {
84
+ valid: true,
85
+ reformulated: reformulated.text,
86
+ clarityScore: reformulated.clarityScore,
87
+ keyPoints: keyPoints,
88
+ summary: summary,
89
+ needsValidation: record.needsValidation,
90
+ processingTime: duration
91
+ };
92
+ }
93
+
94
+ /**
95
+ * Reformulate text in clear, simple language
96
+ * @param {string} text - Text to reformulate
97
+ * @returns {Object} Reformulated text with clarity score
98
+ */
99
+ reformulate(text) {
100
+ if (!text || typeof text !== 'string') {
101
+ return { text: '', clarityScore: 0.0 };
102
+ }
103
+
104
+ let improved = text.trim();
105
+ let improvementScore = 0;
106
+ const maxImprovements = 5;
107
+
108
+ // 1. Remove filler words
109
+ const beforeFillers = improved;
110
+ improved = this._removeFiller(improved);
111
+ if (improved !== beforeFillers) improvementScore++;
112
+
113
+ // 2. Convert to active voice (basic patterns)
114
+ const beforeVoice = improved;
115
+ improved = this._toActiveVoice(improved);
116
+ if (improved !== beforeVoice) improvementScore++;
117
+
118
+ // 3. Simplify complex sentences
119
+ const beforeSimplify = improved;
120
+ improved = this._simplifyComplexSentences(improved);
121
+ if (improved !== beforeSimplify) improvementScore++;
122
+
123
+ // 4. Remove redundancy
124
+ const beforeRedundancy = improved;
125
+ improved = this._removeRedundancy(improved);
126
+ if (improved !== beforeRedundancy) improvementScore++;
127
+
128
+ // 5. Normalize whitespace
129
+ const beforeWhitespace = improved;
130
+ improved = this._normalizeWhitespace(improved);
131
+ if (improved !== beforeWhitespace) improvementScore++;
132
+
133
+ // Calculate clarity score
134
+ const clarityScore = this._calculateClarityScore(text, improved, improvementScore, maxImprovements);
135
+
136
+ return {
137
+ text: improved,
138
+ clarityScore: clarityScore
139
+ };
140
+ }
141
+
142
+ /**
143
+ * Extract 3-5 key points from text
144
+ * @param {string} text - Text to analyze
145
+ * @returns {Array<string>} Key points (3-5 items)
146
+ */
147
+ extractKeyPoints(text) {
148
+ if (!text || typeof text !== 'string' || text.trim().length === 0) {
149
+ return [];
150
+ }
151
+
152
+ // Split into sentences
153
+ const sentences = this._splitIntoSentences(text);
154
+
155
+ if (sentences.length === 0) {
156
+ return [];
157
+ }
158
+
159
+ // For short texts, return all sentences (max 5)
160
+ if (sentences.length <= 5) {
161
+ return sentences.slice(0, 5);
162
+ }
163
+
164
+ // For longer texts, score and select top sentences
165
+ const scoredSentences = sentences.map(sentence => ({
166
+ text: sentence,
167
+ score: this._scoreSentenceImportance(sentence, sentences)
168
+ }));
169
+
170
+ // Sort by score and take top 5
171
+ scoredSentences.sort((a, b) => b.score - a.score);
172
+
173
+ // Return 3-5 points based on content density
174
+ const pointCount = Math.min(5, Math.max(3, Math.ceil(sentences.length / 3)));
175
+ return scoredSentences.slice(0, pointCount).map(s => s.text);
176
+ }
177
+
178
+ /**
179
+ * Generate "So if I understand correctly..." summary
180
+ * @param {Array<string>} keyPoints - Key points to summarize
181
+ * @returns {string} Summary with validation question
182
+ */
183
+ generateSummary(keyPoints) {
184
+ if (!Array.isArray(keyPoints) || keyPoints.length === 0) {
185
+ return 'So if I understand correctly, you have not provided enough information yet. Could you elaborate?';
186
+ }
187
+
188
+ // Combine key points into cohesive narrative
189
+ let narrative = '';
190
+
191
+ if (keyPoints.length === 1) {
192
+ narrative = keyPoints[0];
193
+ } else if (keyPoints.length === 2) {
194
+ narrative = `${keyPoints[0]} Additionally, ${this._lowercaseFirst(keyPoints[1])}`;
195
+ } else {
196
+ // First point
197
+ narrative = keyPoints[0];
198
+
199
+ // Middle points
200
+ for (let i = 1; i < keyPoints.length - 1; i++) {
201
+ narrative += ` ${this._lowercaseFirst(keyPoints[i])}`;
202
+ }
203
+
204
+ // Last point
205
+ narrative += ` Finally, ${this._lowercaseFirst(keyPoints[keyPoints.length - 1])}`;
206
+ }
207
+
208
+ return `So if I understand correctly, ${this._lowercaseFirst(narrative)} Is that accurate?`;
209
+ }
210
+
211
+ /**
212
+ * Check if validation is needed based on frequency
213
+ * @returns {boolean} True if validation should be requested
214
+ */
215
+ needsValidation() {
216
+ return this.responseCount % this.validationFrequency === 0;
217
+ }
218
+
219
+ /**
220
+ * Process user's validation response
221
+ * @param {boolean|string} userConfirmation - User's yes/no response
222
+ * @param {string} summary - The summary being validated
223
+ * @returns {Object} Validation result
224
+ */
225
+ validateUnderstanding(userConfirmation, summary) {
226
+ const confirmed = this._parseConfirmation(userConfirmation);
227
+ const needsCorrection = !confirmed && userConfirmation !== true && userConfirmation !== false;
228
+
229
+ const result = {
230
+ validated: confirmed,
231
+ needsCorrection: needsCorrection && !confirmed,
232
+ ambiguous: !confirmed && !needsCorrection,
233
+ timestamp: Date.now(),
234
+ summary: summary,
235
+ clarificationPrompt: needsCorrection ? 'Please clarify what I misunderstood so I can correct my understanding.' : null
236
+ };
237
+
238
+ // Update last history entry with validation result
239
+ if (this.history.length > 0) {
240
+ this.history[this.history.length - 1].validationResult = result;
241
+ }
242
+
243
+ this.logger.info('Understanding validated', { validated: confirmed, needsCorrection: needsCorrection });
244
+
245
+ return result;
246
+ }
247
+
248
+ /**
249
+ * Process correction from user when understanding was wrong
250
+ * @param {string} correction - User's correction text
251
+ * @returns {Object} Correction result with updated summary
252
+ */
253
+ processCorrection(correction) {
254
+ if (!correction || typeof correction !== 'string') {
255
+ return { updated: false, error: 'Invalid correction' };
256
+ }
257
+
258
+ const reformulated = this.reformulate(correction);
259
+ const keyPoints = this.extractKeyPoints(reformulated.text);
260
+ const newSummary = this.generateSummary(keyPoints);
261
+
262
+ this.history.push({
263
+ original: correction,
264
+ reformulated: reformulated.text,
265
+ clarityScore: reformulated.clarityScore,
266
+ keyPoints: keyPoints,
267
+ summary: newSummary,
268
+ timestamp: Date.now(),
269
+ isCorrection: true
270
+ });
271
+
272
+ this.logger.info('Correction processed', { correctionLength: correction.length });
273
+
274
+ return {
275
+ updated: true,
276
+ reformulated: reformulated.text,
277
+ newSummary: newSummary,
278
+ keyPoints: keyPoints
279
+ };
280
+ }
281
+
282
+ /**
283
+ * Get consolidated summary from all responses
284
+ * @returns {string} Comprehensive summary
285
+ */
286
+ generateConsolidatedSummary() {
287
+ if (this.history.length === 0) {
288
+ return 'No information collected yet.';
289
+ }
290
+
291
+ const allKeyPoints = [];
292
+ this.history.forEach(record => {
293
+ if (record.keyPoints && record.keyPoints.length > 0) {
294
+ allKeyPoints.push(...record.keyPoints);
295
+ }
296
+ });
297
+
298
+ // Remove duplicates and keep most relevant
299
+ const uniquePoints = [...new Set(allKeyPoints)].slice(0, 5);
300
+
301
+ return this.generateSummary(uniquePoints);
302
+ }
303
+
304
+ /**
305
+ * Get specific history record by index
306
+ * @param {number} index - Index of the record
307
+ * @returns {Object} History record
308
+ */
309
+ getHistoryRecord(index) {
310
+ if (index < 0 || index >= this.history.length) {
311
+ return null;
312
+ }
313
+ return this.history[index];
314
+ }
315
+
316
+ /**
317
+ * Export listening session data
318
+ * @returns {Object} Complete session export
319
+ */
320
+ export() {
321
+ return {
322
+ totalResponses: this.responseCount,
323
+ history: this.history,
324
+ summary: this.generateConsolidatedSummary(),
325
+ averageClarityScore: this._calculateAverageClarityScore(),
326
+ validationFrequency: this.validationFrequency,
327
+ exportTimestamp: Date.now(),
328
+ metadata: {
329
+ sessionId: this.sessionState?.sessionId || 'unknown',
330
+ totalResponses: this.responseCount,
331
+ validationFrequency: this.validationFrequency,
332
+ exportedAt: new Date().toISOString()
333
+ }
334
+ };
335
+ }
336
+
337
+ /**
338
+ * Export as markdown format
339
+ * @returns {string} Markdown formatted export
340
+ */
341
+ exportAsMarkdown() {
342
+ const lines = [
343
+ '# Active Listening Session',
344
+ '',
345
+ `**Total Responses:** ${this.responseCount}`,
346
+ `**Average Clarity Score:** ${(this._calculateAverageClarityScore() * 100).toFixed(1)}%`,
347
+ '',
348
+ '## Summary',
349
+ '',
350
+ this.generateConsolidatedSummary(),
351
+ '',
352
+ '## Responses',
353
+ ''
354
+ ];
355
+
356
+ this.history.forEach((record, index) => {
357
+ lines.push(`### Response ${index + 1}`);
358
+ lines.push('');
359
+ lines.push(`**Original:** ${record.original}`);
360
+ lines.push('');
361
+ lines.push(`**Reformulated:** ${record.reformulated}`);
362
+ lines.push('');
363
+ lines.push(`**Clarity Score:** ${(record.clarityScore * 100).toFixed(1)}%`);
364
+ lines.push('');
365
+ if (record.keyPoints && record.keyPoints.length > 0) {
366
+ lines.push('**Key Points:**');
367
+ record.keyPoints.forEach(kp => lines.push(`- ${kp}`));
368
+ lines.push('');
369
+ }
370
+ });
371
+
372
+ return lines.join('\n');
373
+ }
374
+
375
+ /**
376
+ * Export as JSON format
377
+ * @returns {string} JSON formatted export
378
+ */
379
+ exportAsJSON() {
380
+ return JSON.stringify(this.export(), null, 2);
381
+ }
382
+
383
+ // Private helper methods
384
+
385
+ _removeFiller(text) {
386
+ let result = text;
387
+
388
+ this.fillerWords.forEach(filler => {
389
+ const pattern = new RegExp(`\\b${filler}\\b,?\\s*`, 'gi');
390
+ result = result.replace(pattern, '');
391
+ });
392
+
393
+ return result;
394
+ }
395
+
396
+ _toActiveVoice(text) {
397
+ // Basic passive to active voice conversions
398
+ const patterns = [
399
+ { passive: /was (\w+ed) by/gi, active: (match, verb) => verb },
400
+ { passive: /were (\w+ed) by/gi, active: (match, verb) => verb },
401
+ { passive: /is being (\w+ed)/gi, active: (match, verb) => verb },
402
+ { passive: /has been (\w+ed)/gi, active: (match, verb) => verb }
403
+ ];
404
+
405
+ let result = text;
406
+ patterns.forEach(({ passive }) => {
407
+ result = result.replace(passive, '');
408
+ });
409
+
410
+ return result;
411
+ }
412
+
413
+ _simplifyComplexSentences(text) {
414
+ // Replace complex conjunctions with simpler ones
415
+ let result = text;
416
+
417
+ const replacements = {
418
+ 'in order to': 'to',
419
+ 'due to the fact that': 'because',
420
+ 'in the event that': 'if',
421
+ 'at this point in time': 'now',
422
+ 'for the purpose of': 'for',
423
+ 'in spite of': 'despite',
424
+ 'on the basis of': 'based on'
425
+ };
426
+
427
+ Object.entries(replacements).forEach(([complex, simple]) => {
428
+ const pattern = new RegExp(complex, 'gi');
429
+ result = result.replace(pattern, simple);
430
+ });
431
+
432
+ return result;
433
+ }
434
+
435
+ _removeRedundancy(text) {
436
+ // Remove repeated words
437
+ const words = text.split(/\s+/);
438
+ const filtered = [];
439
+ let previous = null;
440
+
441
+ words.forEach(word => {
442
+ const normalized = word.toLowerCase().replace(/[.,!?;:]$/, '');
443
+ if (normalized !== previous) {
444
+ filtered.push(word);
445
+ previous = normalized;
446
+ }
447
+ });
448
+
449
+ return filtered.join(' ');
450
+ }
451
+
452
+ _normalizeWhitespace(text) {
453
+ return text
454
+ .replace(/\s+/g, ' ')
455
+ .replace(/\s+([.,!?;:])/g, '$1')
456
+ .trim();
457
+ }
458
+
459
+ _calculateClarityScore(original, improved, improvementScore, maxImprovements) {
460
+ // Base score from improvements made
461
+ const improvementRatio = improvementScore / maxImprovements;
462
+
463
+ // Length reduction bonus (shorter is often clearer)
464
+ const lengthReduction = Math.max(0, (original.length - improved.length) / original.length);
465
+
466
+ // Combined score
467
+ const score = (improvementRatio * 0.7) + (lengthReduction * 0.3);
468
+
469
+ // Normalize to 0.0-1.0 range
470
+ return Math.max(this.clarityThresholdMin, Math.min(this.clarityThresholdMax, score));
471
+ }
472
+
473
+ _splitIntoSentences(text) {
474
+ // Split on sentence boundaries
475
+ const sentences = text
476
+ .split(/[.!?]+/)
477
+ .map(s => s.trim())
478
+ .filter(s => s.length > 0);
479
+
480
+ return sentences;
481
+ }
482
+
483
+ _scoreSentenceImportance(sentence, allSentences) {
484
+ let score = 0;
485
+
486
+ // Longer sentences often contain more information
487
+ score += Math.min(10, sentence.length / 10);
488
+
489
+ // First and last sentences are often important
490
+ const index = allSentences.indexOf(sentence);
491
+ if (index === 0 || index === allSentences.length - 1) {
492
+ score += 5;
493
+ }
494
+
495
+ // Sentences with numbers or specific terms
496
+ if (/\d+/.test(sentence)) {
497
+ score += 3;
498
+ }
499
+
500
+ // Sentences with key business terms
501
+ const keyTerms = ['need', 'want', 'require', 'must', 'should', 'important', 'critical', 'essential'];
502
+ keyTerms.forEach(term => {
503
+ if (sentence.toLowerCase().includes(term)) {
504
+ score += 2;
505
+ }
506
+ });
507
+
508
+ return score;
509
+ }
510
+
511
+ _lowercaseFirst(text) {
512
+ if (!text || text.length === 0) return text;
513
+ return text.charAt(0).toLowerCase() + text.slice(1);
514
+ }
515
+
516
+ _parseConfirmation(input) {
517
+ if (typeof input === 'boolean') {
518
+ return input;
519
+ }
520
+
521
+ if (typeof input === 'string') {
522
+ const normalized = input.toLowerCase().trim();
523
+ const positive = ['yes', 'y', 'yeah', 'yep', 'correct', 'right', 'true', 'ok', 'okay'];
524
+ const negative = ['no', 'n', 'nope', 'incorrect', 'wrong', 'false'];
525
+
526
+ if (positive.includes(normalized)) return true;
527
+ if (negative.includes(normalized)) return false;
528
+ }
529
+
530
+ return false;
531
+ }
532
+
533
+ _calculateAverageClarityScore() {
534
+ if (this.history.length === 0) return 0.0;
535
+
536
+ const sum = this.history.reduce((acc, record) => acc + record.clarityScore, 0);
537
+ return sum / this.history.length;
538
+ }
539
+ }
540
+
541
+ module.exports = ActiveListener;