create-byan-agent 2.0.1 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API-BYAN-V2.md +741 -0
- package/BMAD-QUICK-REFERENCE.md +370 -0
- package/CHANGELOG-v2.1.0.md +371 -0
- package/LICENSE +1 -1
- package/MIGRATION-v2.0-to-v2.1.md +430 -0
- package/README-BYAN-V2.md +446 -0
- package/README.md +264 -201
- package/install/.eslintrc.js +20 -0
- package/install/.prettierrc +7 -0
- package/install/BUGFIX-CHALK.md +173 -0
- package/install/BUGFIX-DOCUMENTATION-INDEX.md +299 -0
- package/install/BUGFIX-PATH-RESOLUTION.md +293 -0
- package/install/BUGFIX-QUICKSTART.md +184 -0
- package/install/BUGFIX-SUMMARY.txt +91 -0
- package/install/BUGFIX-VISUAL-SUMMARY.md +253 -0
- package/install/DEPLOYMENT-GUIDE-V2.md +431 -0
- package/install/DOCS-INDEX.md +261 -0
- package/install/GUIDE-INSTALLATION-BYAN-SIMPLE.md +1083 -0
- package/install/INSTALLER-V2-CHANGES.md +472 -0
- package/install/LICENSE +21 -0
- package/install/PUBLICATION-CHECKLIST.md +265 -0
- package/install/PUBLISH-GUIDE.md +190 -0
- package/install/QUICKSTART.md +311 -0
- package/install/README-NPM-PUBLISH.md +298 -0
- package/install/README-NPM-SHORT.md +298 -0
- package/install/README-NPM.md +433 -0
- package/install/README-RACHID.md +302 -0
- package/install/README-V2-INDEX.md +306 -0
- package/install/README.md +298 -0
- package/install/RESUME-EXECUTIF-YAN.md +408 -0
- package/install/UPDATE-SUMMARY.md +205 -0
- package/install/__tests__/integration/detection-flow.test.js +154 -0
- package/install/__tests__/platforms/claude-code.test.js +175 -0
- package/install/__tests__/platforms/codex.test.js +80 -0
- package/install/__tests__/platforms/copilot-cli.test.js +118 -0
- package/install/__tests__/platforms/vscode.test.js +67 -0
- package/install/__tests__/utils/file-utils.test.js +87 -0
- package/install/__tests__/utils/git-detector.test.js +80 -0
- package/install/__tests__/utils/logger.test.js +83 -0
- package/install/__tests__/utils/node-detector.test.js +71 -0
- package/install/__tests__/utils/os-detector.test.js +63 -0
- package/install/__tests__/utils/yaml-utils.test.js +85 -0
- package/install/__tests__/yanstaller/detector.test.js +210 -0
- package/install/coverage/clover.xml +219 -0
- package/install/coverage/coverage-final.json +13 -0
- package/install/coverage/lcov-report/base.css +224 -0
- package/install/coverage/lcov-report/block-navigation.js +87 -0
- package/install/coverage/lcov-report/favicon.png +0 -0
- package/install/coverage/lcov-report/index.html +146 -0
- package/install/coverage/lcov-report/lib/errors.js.html +268 -0
- package/install/coverage/lcov-report/lib/exit-codes.js.html +247 -0
- package/install/coverage/lcov-report/lib/index.html +131 -0
- package/install/coverage/lcov-report/lib/platforms/claude-code.js.html +343 -0
- package/install/coverage/lcov-report/lib/platforms/codex.js.html +361 -0
- package/install/coverage/lcov-report/lib/platforms/copilot-cli.js.html +454 -0
- package/install/coverage/lcov-report/lib/platforms/index.html +176 -0
- package/install/coverage/lcov-report/lib/platforms/index.js.html +127 -0
- package/install/coverage/lcov-report/lib/platforms/vscode.js.html +238 -0
- package/install/coverage/lcov-report/lib/utils/config-loader.js.html +322 -0
- package/install/coverage/lcov-report/lib/utils/file-utils.js.html +397 -0
- package/install/coverage/lcov-report/lib/utils/git-detector.js.html +190 -0
- package/install/coverage/lcov-report/lib/utils/index.html +206 -0
- package/install/coverage/lcov-report/lib/utils/logger.js.html +277 -0
- package/install/coverage/lcov-report/lib/utils/node-detector.js.html +259 -0
- package/install/coverage/lcov-report/lib/utils/os-detector.js.html +307 -0
- package/install/coverage/lcov-report/lib/utils/yaml-utils.js.html +346 -0
- package/install/coverage/lcov-report/lib/yanstaller/backuper.js.html +409 -0
- package/install/coverage/lcov-report/lib/yanstaller/detector.js.html +508 -0
- package/install/coverage/lcov-report/lib/yanstaller/index.html +236 -0
- package/install/coverage/lcov-report/lib/yanstaller/index.js.html +364 -0
- package/install/coverage/lcov-report/lib/yanstaller/installer.js.html +505 -0
- package/install/coverage/lcov-report/lib/yanstaller/interviewer.js.html +349 -0
- package/install/coverage/lcov-report/lib/yanstaller/recommender.js.html +379 -0
- package/install/coverage/lcov-report/lib/yanstaller/troubleshooter.js.html +352 -0
- package/install/coverage/lcov-report/lib/yanstaller/validator.js.html +679 -0
- package/install/coverage/lcov-report/lib/yanstaller/wizard.js.html +412 -0
- package/install/coverage/lcov-report/platforms/claude-code.js.html +343 -0
- package/install/coverage/lcov-report/platforms/codex.js.html +361 -0
- package/install/coverage/lcov-report/platforms/copilot-cli.js.html +454 -0
- package/install/coverage/lcov-report/platforms/index.html +176 -0
- package/install/coverage/lcov-report/platforms/index.js.html +127 -0
- package/install/coverage/lcov-report/platforms/vscode.js.html +238 -0
- package/install/coverage/lcov-report/prettify.css +1 -0
- package/install/coverage/lcov-report/prettify.js +2 -0
- package/install/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/install/coverage/lcov-report/sorter.js +210 -0
- package/install/coverage/lcov-report/utils/file-utils.js.html +397 -0
- package/install/coverage/lcov-report/utils/git-detector.js.html +190 -0
- package/install/coverage/lcov-report/utils/index.html +191 -0
- package/install/coverage/lcov-report/utils/logger.js.html +277 -0
- package/install/coverage/lcov-report/utils/node-detector.js.html +259 -0
- package/install/coverage/lcov-report/utils/os-detector.js.html +307 -0
- package/install/coverage/lcov-report/utils/yaml-utils.js.html +346 -0
- package/install/coverage/lcov-report/yanstaller/detector.js.html +508 -0
- package/install/coverage/lcov-report/yanstaller/index.html +116 -0
- package/install/coverage/lcov.info +414 -0
- package/install/install.sh +239 -0
- package/install/jest.config.js +33 -0
- package/install/lib/errors.js +61 -0
- package/install/lib/exit-codes.js +54 -0
- package/install/lib/platforms/claude-code.js +86 -0
- package/install/lib/platforms/codex.js +92 -0
- package/install/lib/platforms/copilot-cli.js +123 -0
- package/install/lib/platforms/index.js +14 -0
- package/install/lib/platforms/vscode.js +51 -0
- package/install/lib/utils/config-loader.js +79 -0
- package/install/lib/utils/file-utils.js +104 -0
- package/install/lib/utils/git-detector.js +35 -0
- package/install/lib/utils/logger.js +64 -0
- package/install/lib/utils/node-detector.js +58 -0
- package/install/lib/utils/os-detector.js +74 -0
- package/install/lib/utils/yaml-utils.js +87 -0
- package/install/lib/yanstaller/backuper.js +108 -0
- package/install/lib/yanstaller/detector.js +141 -0
- package/install/lib/yanstaller/index.js +93 -0
- package/install/lib/yanstaller/installer.js +140 -0
- package/install/lib/yanstaller/interviewer.js +88 -0
- package/install/lib/yanstaller/recommender.js +98 -0
- package/install/lib/yanstaller/troubleshooter.js +89 -0
- package/install/lib/yanstaller/validator.js +198 -0
- package/install/lib/yanstaller/wizard.js +109 -0
- package/install/package-npm.json +55 -0
- package/install/package.json +63 -0
- package/install/src/byan-v2/context/copilot-context.js +79 -0
- package/install/src/byan-v2/context/session-state.js +98 -0
- package/install/src/byan-v2/dispatcher/complexity-scorer.js +232 -0
- package/install/src/byan-v2/dispatcher/local-executor.js +221 -0
- package/install/src/byan-v2/dispatcher/task-router.js +122 -0
- package/install/src/byan-v2/dispatcher/task-tool-interface-mock.js +134 -0
- package/install/src/byan-v2/dispatcher/task-tool-interface.js +123 -0
- package/install/src/byan-v2/generation/agent-profile-validator.js +113 -0
- package/install/src/byan-v2/generation/profile-template.js +113 -0
- package/install/src/byan-v2/generation/templates/default-agent.md +49 -0
- package/install/src/byan-v2/generation/templates/test-template.md +1 -0
- package/install/src/byan-v2/index.js +199 -0
- package/install/src/byan-v2/observability/error-tracker.js +105 -0
- package/install/src/byan-v2/observability/logger.js +154 -0
- package/install/src/byan-v2/observability/metrics-collector.js +194 -0
- package/install/src/byan-v2/orchestrator/analysis-state.js +268 -0
- package/install/src/byan-v2/orchestrator/generation-state.js +340 -0
- package/install/src/byan-v2/orchestrator/interview-state.js +271 -0
- package/install/src/byan-v2/orchestrator/state-machine.js +204 -0
- package/install/src/core/cache/cache.js +126 -0
- package/install/src/core/context/context.js +86 -0
- package/install/src/core/dispatcher/dispatcher.js +135 -0
- package/install/src/core/worker-pool/worker-pool.js +194 -0
- package/install/src/core/workflow/workflow-executor.js +220 -0
- package/install/src/index.js +139 -0
- package/install/src/observability/dashboard/dashboard.js +191 -0
- package/install/src/observability/logger/structured-logger.js +254 -0
- package/install/src/observability/metrics/metrics-collector.js +325 -0
- package/install/switch-to-v2.sh +126 -0
- package/install/test-chalk-fix.sh +210 -0
- package/install/test-installer-v2.sh +204 -0
- package/install/test-path-resolution.sh +200 -0
- package/package.json +53 -33
- package/src/byan-v2/context/copilot-context.js +79 -0
- package/src/byan-v2/context/session-state.js +98 -0
- package/src/byan-v2/data/mantras.json +852 -0
- package/src/byan-v2/dispatcher/complexity-scorer.js +232 -0
- package/src/byan-v2/dispatcher/five-whys-analyzer.js +310 -0
- package/src/byan-v2/dispatcher/local-executor.js +221 -0
- package/src/byan-v2/dispatcher/task-router.js +122 -0
- package/src/byan-v2/dispatcher/task-tool-interface-mock.js +134 -0
- package/src/byan-v2/dispatcher/task-tool-interface.js +123 -0
- package/src/byan-v2/generation/agent-profile-validator.js +113 -0
- package/src/byan-v2/generation/mantra-validator.js +416 -0
- package/src/byan-v2/generation/profile-template.js +113 -0
- package/src/byan-v2/generation/templates/default-agent.md +49 -0
- package/src/byan-v2/generation/templates/test-template.md +1 -0
- package/src/byan-v2/index.js +652 -0
- package/src/byan-v2/integration/voice-integration.js +295 -0
- package/src/byan-v2/observability/error-tracker.js +105 -0
- package/src/byan-v2/observability/logger.js +154 -0
- package/src/byan-v2/observability/metrics-collector.js +194 -0
- package/src/byan-v2/orchestrator/active-listener.js +541 -0
- package/src/byan-v2/orchestrator/analysis-state.js +268 -0
- package/src/byan-v2/orchestrator/generation-state.js +340 -0
- package/src/byan-v2/orchestrator/glossary-builder.js +431 -0
- package/src/byan-v2/orchestrator/interview-state.js +353 -0
- package/src/byan-v2/orchestrator/state-machine.js +253 -0
- package/src/core/cache/cache.js +126 -0
- package/src/core/context/context.js +86 -0
- package/src/core/dispatcher/dispatcher.js +135 -0
- package/src/core/worker-pool/worker-pool.js +194 -0
- package/src/core/workflow/workflow-executor.js +220 -0
- package/src/index.js +139 -0
- package/src/observability/dashboard/dashboard.js +191 -0
- package/src/observability/logger/structured-logger.js +254 -0
- package/src/observability/metrics/metrics-collector.js +325 -0
- package/templates/.github/agents/bmad-agent-test-dynamic.md +0 -21
- package/templates/.github/agents/franck.md +0 -379
- /package/{CHANGELOG.md → install/CHANGELOG.md} +0 -0
- /package/{bin → install/bin}/create-byan-agent-backup.js +0 -0
- /package/{bin → install/bin}/create-byan-agent-fixed.js +0 -0
- /package/{bin → install/bin}/create-byan-agent-v2.js +0 -0
- /package/{bin → install/bin}/create-byan-agent.js +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmad-master.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-agent-builder.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-module-builder.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-workflow-builder.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-analyst.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-architect.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-dev.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-pm.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-quick-flow-solo-dev.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-quinn.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-sm.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-tech-writer.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-ux-designer.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-byan-test.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-byan.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-carmack.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-brainstorming-coach.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-creative-problem-solver.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-design-thinking-coach.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-innovation-strategist.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-presentation-master.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-storyteller.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-marc.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-patnote.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-rachid.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-tea-tea.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/agent-builder.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/byan-test.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/byan.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/marc.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/module-builder.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/patnote.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/rachid.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/workflow-builder.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/data/mantras.yaml +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/data/templates.yaml +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/delete-agent-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/edit-agent-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/interview-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/quick-create-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/templates/base-agent-template.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/validate-agent-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/core/agents/carmack.md +0 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured Logger for BYAN v2.0
|
|
3
|
+
* Provides structured logging with JSON format, log levels, and metadata
|
|
4
|
+
*
|
|
5
|
+
* @module observability/logger/structured-logger
|
|
6
|
+
* @version 2.0.0-HYPER-MVP
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Log levels supported by the logger
|
|
11
|
+
*/
|
|
12
|
+
const LOG_LEVELS = {
|
|
13
|
+
DEBUG: 'debug',
|
|
14
|
+
INFO: 'info',
|
|
15
|
+
WARN: 'warn',
|
|
16
|
+
ERROR: 'error',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Numeric priorities for log levels
|
|
21
|
+
*/
|
|
22
|
+
const LOG_PRIORITIES = {
|
|
23
|
+
debug: 0,
|
|
24
|
+
info: 1,
|
|
25
|
+
warn: 2,
|
|
26
|
+
error: 3,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Structured Logger - Provides JSON-formatted logging with metadata
|
|
31
|
+
*
|
|
32
|
+
* @class StructuredLogger
|
|
33
|
+
* @example
|
|
34
|
+
* const logger = new StructuredLogger();
|
|
35
|
+
* logger.info('User logged in', { userId: '123', ip: '192.168.1.1' });
|
|
36
|
+
*/
|
|
37
|
+
class StructuredLogger {
|
|
38
|
+
constructor(options = {}) {
|
|
39
|
+
this.level = options.level || LOG_LEVELS.INFO;
|
|
40
|
+
this.logs = []; // In-memory storage for tests
|
|
41
|
+
this.enableConsole = options.enableConsole !== false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Set the minimum log level
|
|
46
|
+
*
|
|
47
|
+
* @param {string} level - Log level (debug, info, warn, error)
|
|
48
|
+
* @returns {void}
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* logger.setLevel('debug'); // Show all logs
|
|
52
|
+
* logger.setLevel('error'); // Show only errors
|
|
53
|
+
*/
|
|
54
|
+
setLevel(level) {
|
|
55
|
+
if (!LOG_PRIORITIES.hasOwnProperty(level)) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`Invalid log level: ${level}. Must be one of: debug, info, warn, error`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
this.level = level;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Log debug message
|
|
65
|
+
*
|
|
66
|
+
* @param {string} message - Log message
|
|
67
|
+
* @param {Object} [meta={}] - Additional metadata
|
|
68
|
+
* @returns {void}
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* logger.debug('Cache hit', { key: 'user:123', ttl: 3600 });
|
|
72
|
+
*/
|
|
73
|
+
debug(message, meta = {}) {
|
|
74
|
+
this._log(LOG_LEVELS.DEBUG, message, meta);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Log info message
|
|
79
|
+
*
|
|
80
|
+
* @param {string} message - Log message
|
|
81
|
+
* @param {Object} [meta={}] - Additional metadata
|
|
82
|
+
* @returns {void}
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* logger.info('Task started', { taskId: '123', agent: 'dev' });
|
|
86
|
+
*/
|
|
87
|
+
info(message, meta = {}) {
|
|
88
|
+
this._log(LOG_LEVELS.INFO, message, meta);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Log warning message
|
|
93
|
+
*
|
|
94
|
+
* @param {string} message - Log message
|
|
95
|
+
* @param {Object} [meta={}] - Additional metadata
|
|
96
|
+
* @returns {void}
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* logger.warn('Rate limit approaching', { limit: 1000, used: 950 });
|
|
100
|
+
*/
|
|
101
|
+
warn(message, meta = {}) {
|
|
102
|
+
this._log(LOG_LEVELS.WARN, message, meta);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Log error message
|
|
107
|
+
*
|
|
108
|
+
* @param {string} message - Log message
|
|
109
|
+
* @param {Object} [meta={}] - Additional metadata
|
|
110
|
+
* @returns {void}
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* logger.error('Task failed', { taskId: '123', error: 'Timeout' });
|
|
114
|
+
*/
|
|
115
|
+
error(message, meta = {}) {
|
|
116
|
+
this._log(LOG_LEVELS.ERROR, message, meta);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Internal log method
|
|
121
|
+
*
|
|
122
|
+
* @private
|
|
123
|
+
* @param {string} level - Log level
|
|
124
|
+
* @param {string} message - Log message
|
|
125
|
+
* @param {Object} meta - Metadata
|
|
126
|
+
* @returns {void}
|
|
127
|
+
*/
|
|
128
|
+
_log(level, message, meta) {
|
|
129
|
+
// Check if this log should be recorded based on level
|
|
130
|
+
if (LOG_PRIORITIES[level] < LOG_PRIORITIES[this.level]) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const logEntry = {
|
|
135
|
+
timestamp: new Date().toISOString(),
|
|
136
|
+
level,
|
|
137
|
+
message,
|
|
138
|
+
meta: { ...meta },
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// Store in memory
|
|
142
|
+
this.logs.push(logEntry);
|
|
143
|
+
|
|
144
|
+
// Output to console if enabled
|
|
145
|
+
if (this.enableConsole) {
|
|
146
|
+
this._outputToConsole(logEntry);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Output log entry to console
|
|
152
|
+
*
|
|
153
|
+
* @private
|
|
154
|
+
* @param {Object} logEntry - Log entry
|
|
155
|
+
* @returns {void}
|
|
156
|
+
*/
|
|
157
|
+
_outputToConsole(logEntry) {
|
|
158
|
+
const output = JSON.stringify(logEntry);
|
|
159
|
+
|
|
160
|
+
switch (logEntry.level) {
|
|
161
|
+
case LOG_LEVELS.DEBUG:
|
|
162
|
+
console.debug(output);
|
|
163
|
+
break;
|
|
164
|
+
case LOG_LEVELS.INFO:
|
|
165
|
+
console.info(output);
|
|
166
|
+
break;
|
|
167
|
+
case LOG_LEVELS.WARN:
|
|
168
|
+
console.warn(output);
|
|
169
|
+
break;
|
|
170
|
+
case LOG_LEVELS.ERROR:
|
|
171
|
+
console.error(output);
|
|
172
|
+
break;
|
|
173
|
+
default:
|
|
174
|
+
console.log(output);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get all logs
|
|
180
|
+
*
|
|
181
|
+
* @returns {Array<Object>} Array of log entries
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* const logs = logger.getLogs();
|
|
185
|
+
* logs.forEach(log => {
|
|
186
|
+
* console.log(`[${log.level}] ${log.message}`);
|
|
187
|
+
* });
|
|
188
|
+
*/
|
|
189
|
+
getLogs() {
|
|
190
|
+
return [...this.logs];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Get logs filtered by level
|
|
195
|
+
*
|
|
196
|
+
* @param {string} level - Log level to filter by
|
|
197
|
+
* @returns {Array<Object>} Filtered log entries
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* const errors = logger.getLogsByLevel('error');
|
|
201
|
+
*/
|
|
202
|
+
getLogsByLevel(level) {
|
|
203
|
+
return this.logs.filter((log) => log.level === level);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Clear all logs
|
|
208
|
+
*
|
|
209
|
+
* @returns {void}
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* logger.clear(); // Remove all logs from memory
|
|
213
|
+
*/
|
|
214
|
+
clear() {
|
|
215
|
+
this.logs = [];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Get log count
|
|
220
|
+
*
|
|
221
|
+
* @returns {number} Number of logs
|
|
222
|
+
*/
|
|
223
|
+
count() {
|
|
224
|
+
return this.logs.length;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Get log count by level
|
|
229
|
+
*
|
|
230
|
+
* @returns {Object} Count of logs per level
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* const stats = logger.getStats();
|
|
234
|
+
* // { debug: 10, info: 25, warn: 3, error: 1 }
|
|
235
|
+
*/
|
|
236
|
+
getStats() {
|
|
237
|
+
const stats = {
|
|
238
|
+
debug: 0,
|
|
239
|
+
info: 0,
|
|
240
|
+
warn: 0,
|
|
241
|
+
error: 0,
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
this.logs.forEach((log) => {
|
|
245
|
+
if (stats.hasOwnProperty(log.level)) {
|
|
246
|
+
stats[log.level]++;
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
return stats;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
module.exports = { StructuredLogger, LOG_LEVELS };
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics Collector for BYAN v2.0
|
|
3
|
+
* Collects and manages system metrics (counters, gauges, timings)
|
|
4
|
+
*
|
|
5
|
+
* @module observability/metrics/metrics-collector
|
|
6
|
+
* @version 2.0.0-HYPER-MVP
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Metrics Collector - Records and tracks system metrics
|
|
11
|
+
*
|
|
12
|
+
* @class MetricsCollector
|
|
13
|
+
* @example
|
|
14
|
+
* const metrics = new MetricsCollector();
|
|
15
|
+
* metrics.increment('api.calls', { endpoint: '/chat' });
|
|
16
|
+
* metrics.recordDuration('request.duration', 150);
|
|
17
|
+
*/
|
|
18
|
+
class MetricsCollector {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.metrics = new Map();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Record a metric with a specific value
|
|
25
|
+
*
|
|
26
|
+
* @param {string} name - Metric name
|
|
27
|
+
* @param {number} value - Metric value
|
|
28
|
+
* @param {Object} [tags={}] - Optional tags for filtering
|
|
29
|
+
* @returns {void}
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* metrics.recordMetric('memory.usage', 1024, { unit: 'MB', service: 'api' });
|
|
33
|
+
*/
|
|
34
|
+
recordMetric(name, value, tags = {}) {
|
|
35
|
+
if (!name || typeof name !== 'string') {
|
|
36
|
+
throw new Error('Metric name must be a non-empty string');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (typeof value !== 'number') {
|
|
40
|
+
throw new Error('Metric value must be a number');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (isNaN(value)) {
|
|
44
|
+
throw new Error('Metric value cannot be NaN');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const key = this._generateKey(name, tags);
|
|
48
|
+
|
|
49
|
+
this.metrics.set(key, {
|
|
50
|
+
name,
|
|
51
|
+
value,
|
|
52
|
+
tags: { ...tags },
|
|
53
|
+
timestamp: new Date().toISOString(),
|
|
54
|
+
type: 'gauge',
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Increment a counter metric
|
|
60
|
+
*
|
|
61
|
+
* @param {string} name - Metric name
|
|
62
|
+
* @param {Object} [tags={}] - Optional tags
|
|
63
|
+
* @param {number} [delta=1] - Increment amount
|
|
64
|
+
* @returns {void}
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* metrics.increment('api.calls', { endpoint: '/chat' });
|
|
68
|
+
* metrics.increment('cache.hits', {}, 5); // Increment by 5
|
|
69
|
+
*/
|
|
70
|
+
increment(name, tags = {}, delta = 1) {
|
|
71
|
+
if (!name || typeof name !== 'string') {
|
|
72
|
+
throw new Error('Metric name must be a non-empty string');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (typeof delta !== 'number') {
|
|
76
|
+
throw new Error('Delta must be a number');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const key = this._generateKey(name, tags);
|
|
80
|
+
const existing = this.metrics.get(key);
|
|
81
|
+
|
|
82
|
+
if (existing) {
|
|
83
|
+
this.metrics.set(key, {
|
|
84
|
+
...existing,
|
|
85
|
+
value: existing.value + delta,
|
|
86
|
+
timestamp: new Date().toISOString(),
|
|
87
|
+
});
|
|
88
|
+
} else {
|
|
89
|
+
this.metrics.set(key, {
|
|
90
|
+
name,
|
|
91
|
+
value: delta,
|
|
92
|
+
tags: { ...tags },
|
|
93
|
+
timestamp: new Date().toISOString(),
|
|
94
|
+
type: 'counter',
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Decrement a counter metric
|
|
101
|
+
*
|
|
102
|
+
* @param {string} name - Metric name
|
|
103
|
+
* @param {Object} [tags={}] - Optional tags
|
|
104
|
+
* @param {number} [delta=1] - Decrement amount
|
|
105
|
+
* @returns {void}
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* metrics.decrement('active.connections', { server: 'main' });
|
|
109
|
+
*/
|
|
110
|
+
decrement(name, tags = {}, delta = 1) {
|
|
111
|
+
this.increment(name, tags, -delta);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Record a duration/timing metric
|
|
116
|
+
*
|
|
117
|
+
* @param {string} name - Metric name
|
|
118
|
+
* @param {number} durationMs - Duration in milliseconds
|
|
119
|
+
* @param {Object} [tags={}] - Optional tags
|
|
120
|
+
* @returns {void}
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* metrics.recordDuration('request.duration', 150, { status: '200' });
|
|
124
|
+
*/
|
|
125
|
+
recordDuration(name, durationMs, tags = {}) {
|
|
126
|
+
if (!name || typeof name !== 'string') {
|
|
127
|
+
throw new Error('Metric name must be a non-empty string');
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (typeof durationMs !== 'number') {
|
|
131
|
+
throw new Error('Duration must be a number');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (durationMs < 0) {
|
|
135
|
+
throw new Error('Duration cannot be negative');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const key = this._generateKey(name, tags);
|
|
139
|
+
|
|
140
|
+
this.metrics.set(key, {
|
|
141
|
+
name,
|
|
142
|
+
value: durationMs,
|
|
143
|
+
tags: { ...tags },
|
|
144
|
+
timestamp: new Date().toISOString(),
|
|
145
|
+
type: 'timing',
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Generate unique key for metric with tags
|
|
151
|
+
*
|
|
152
|
+
* @private
|
|
153
|
+
* @param {string} name - Metric name
|
|
154
|
+
* @param {Object} tags - Tags
|
|
155
|
+
* @returns {string} Unique key
|
|
156
|
+
*/
|
|
157
|
+
_generateKey(name, tags) {
|
|
158
|
+
if (Object.keys(tags).length === 0) {
|
|
159
|
+
return name;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const sortedTags = Object.keys(tags)
|
|
163
|
+
.sort()
|
|
164
|
+
.map((key) => `${key}:${tags[key]}`)
|
|
165
|
+
.join(',');
|
|
166
|
+
|
|
167
|
+
return `${name}[${sortedTags}]`;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Get all metrics
|
|
172
|
+
*
|
|
173
|
+
* @returns {Object} All metrics as key-value pairs
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* const allMetrics = metrics.getMetrics();
|
|
177
|
+
* Object.entries(allMetrics).forEach(([key, metric]) => {
|
|
178
|
+
* console.log(`${key}: ${metric.value}`);
|
|
179
|
+
* });
|
|
180
|
+
*/
|
|
181
|
+
getMetrics() {
|
|
182
|
+
const result = {};
|
|
183
|
+
|
|
184
|
+
for (const [key, value] of this.metrics.entries()) {
|
|
185
|
+
result[key] = { ...value };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Get a specific metric
|
|
193
|
+
*
|
|
194
|
+
* @param {string} name - Metric name
|
|
195
|
+
* @param {Object} [tags={}] - Optional tags
|
|
196
|
+
* @returns {Object|null} Metric or null if not found
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* const apiCalls = metrics.getMetric('api.calls', { endpoint: '/chat' });
|
|
200
|
+
* console.log(`API calls: ${apiCalls.value}`);
|
|
201
|
+
*/
|
|
202
|
+
getMetric(name, tags = {}) {
|
|
203
|
+
const key = this._generateKey(name, tags);
|
|
204
|
+
const metric = this.metrics.get(key);
|
|
205
|
+
|
|
206
|
+
return metric ? { ...metric } : null;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Get metrics filtered by name prefix
|
|
211
|
+
*
|
|
212
|
+
* @param {string} prefix - Name prefix
|
|
213
|
+
* @returns {Object} Filtered metrics
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* const apiMetrics = metrics.getMetricsByPrefix('api.');
|
|
217
|
+
* // Returns all metrics starting with 'api.'
|
|
218
|
+
*/
|
|
219
|
+
getMetricsByPrefix(prefix) {
|
|
220
|
+
const result = {};
|
|
221
|
+
|
|
222
|
+
for (const [key, value] of this.metrics.entries()) {
|
|
223
|
+
if (value.name.startsWith(prefix)) {
|
|
224
|
+
result[key] = { ...value };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Get metrics filtered by type
|
|
233
|
+
*
|
|
234
|
+
* @param {string} type - Metric type (gauge, counter, timing)
|
|
235
|
+
* @returns {Object} Filtered metrics
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* const counters = metrics.getMetricsByType('counter');
|
|
239
|
+
*/
|
|
240
|
+
getMetricsByType(type) {
|
|
241
|
+
const result = {};
|
|
242
|
+
|
|
243
|
+
for (const [key, value] of this.metrics.entries()) {
|
|
244
|
+
if (value.type === type) {
|
|
245
|
+
result[key] = { ...value };
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Clear all metrics
|
|
254
|
+
*
|
|
255
|
+
* @returns {void}
|
|
256
|
+
*
|
|
257
|
+
* @example
|
|
258
|
+
* metrics.clear(); // Remove all metrics
|
|
259
|
+
*/
|
|
260
|
+
clear() {
|
|
261
|
+
this.metrics.clear();
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get metrics count
|
|
266
|
+
*
|
|
267
|
+
* @returns {number} Number of metrics
|
|
268
|
+
*/
|
|
269
|
+
count() {
|
|
270
|
+
return this.metrics.size;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Reset a specific metric to zero
|
|
275
|
+
*
|
|
276
|
+
* @param {string} name - Metric name
|
|
277
|
+
* @param {Object} [tags={}] - Optional tags
|
|
278
|
+
* @returns {boolean} True if metric was reset, false if not found
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* metrics.resetMetric('api.calls', { endpoint: '/chat' });
|
|
282
|
+
*/
|
|
283
|
+
resetMetric(name, tags = {}) {
|
|
284
|
+
const key = this._generateKey(name, tags);
|
|
285
|
+
const existing = this.metrics.get(key);
|
|
286
|
+
|
|
287
|
+
if (existing) {
|
|
288
|
+
this.metrics.set(key, {
|
|
289
|
+
...existing,
|
|
290
|
+
value: 0,
|
|
291
|
+
timestamp: new Date().toISOString(),
|
|
292
|
+
});
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Get summary statistics
|
|
301
|
+
*
|
|
302
|
+
* @returns {Object} Summary stats
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* const stats = metrics.getStats();
|
|
306
|
+
* // { total: 10, byType: { counter: 5, gauge: 3, timing: 2 } }
|
|
307
|
+
*/
|
|
308
|
+
getStats() {
|
|
309
|
+
const byType = {};
|
|
310
|
+
|
|
311
|
+
for (const metric of this.metrics.values()) {
|
|
312
|
+
if (!byType[metric.type]) {
|
|
313
|
+
byType[metric.type] = 0;
|
|
314
|
+
}
|
|
315
|
+
byType[metric.type]++;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return {
|
|
319
|
+
total: this.metrics.size,
|
|
320
|
+
byType,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
module.exports = { MetricsCollector };
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: 'test-dynamic'
|
|
3
|
-
description: 'Test Dynamic Loading - Phase B Validation'
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
<agent-activation CRITICAL="TRUE">
|
|
7
|
-
1. LOAD the FULL agent file from {project-root}/_bmad/core/agents/test-dynamic.md
|
|
8
|
-
2. READ its entire contents
|
|
9
|
-
3. FOLLOW activation steps precisely
|
|
10
|
-
4. WAIT for user input
|
|
11
|
-
</agent-activation>
|
|
12
|
-
|
|
13
|
-
```xml
|
|
14
|
-
<agent id="test-dynamic" name="TEST-DYNAMIC" title="Dynamic Loading Test" icon="🧪">
|
|
15
|
-
<activation>
|
|
16
|
-
<step n="1">Load from {project-root}/_bmad/core/agents/test-dynamic.md</step>
|
|
17
|
-
<step n="2">Test inheritance from base agent</step>
|
|
18
|
-
<step n="3">Display menu</step>
|
|
19
|
-
</activation>
|
|
20
|
-
</agent>
|
|
21
|
-
```
|