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,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;
|