vibecodingmachine-core 2026.2.26-1739 → 2026.3.9-850

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 (192) hide show
  1. package/package.json +1 -1
  2. package/src/agents/AgentCheckDiscoveryService.js +180 -0
  3. package/src/agents/AgentCheckService.js +18 -261
  4. package/src/agents/AgentCheckStatisticsService.js +195 -0
  5. package/src/agents/EnvironmentConfigurationManager.js +31 -380
  6. package/src/agents/InstallationType.js +19 -6
  7. package/src/agents/SimpleAgentCheckService.js +472 -0
  8. package/src/agents/config-managers/ConfigUtils.js +72 -0
  9. package/src/agents/config-managers/DefaultConfig.js +58 -0
  10. package/src/agents/config-managers/EnvVarLoader.js +66 -0
  11. package/src/agents/config-managers/FileConfigLoader.js +124 -0
  12. package/src/agents/config-managers/TypeConverters.js +61 -0
  13. package/src/agents/config-managers/VariableMappings.js +92 -0
  14. package/src/agents/discovery/AgentDiscoveryService-refactored.js +272 -0
  15. package/src/agents/discovery/AgentDiscoveryService.js +29 -403
  16. package/src/agents/discovery/agent-validator.js +262 -0
  17. package/src/agents/discovery/discovery-results.js +176 -0
  18. package/src/agents/discovery/discovery-scanner.js +268 -0
  19. package/src/agents/discovery/discovery-utils.js +161 -0
  20. package/src/agents/discovery/executable-analyzer.js +290 -0
  21. package/src/agents/discovery/history-manager.js +310 -0
  22. package/src/agents/verification/ResultAnalyzer-refactored.js +341 -0
  23. package/src/agents/verification/ResultAnalyzer.js +30 -431
  24. package/src/agents/verification/analysis-utils.js +310 -0
  25. package/src/agents/verification/batch-analyzer.js +440 -0
  26. package/src/agents/verification/pattern-recognizer.js +369 -0
  27. package/src/agents/verification/report-generator.js +320 -0
  28. package/src/agents/verification/test-analyzer.js +290 -0
  29. package/src/agents/windows/InstallerFactory.js +4 -0
  30. package/src/agents/windows/VSCodeExtensionInstaller.js +404 -0
  31. package/src/analysis/analysis-engine.js +314 -0
  32. package/src/analysis/ast-analyzer.js +342 -0
  33. package/src/analysis/boundary-detector-refactored.js +378 -0
  34. package/src/analysis/boundary-detector.js +200 -603
  35. package/src/analysis/boundary-scanner.js +609 -0
  36. package/src/analysis/boundary-types.js +118 -0
  37. package/src/analysis/boundary-utils.js +293 -0
  38. package/src/analysis/deadline-priority-calculator.js +18 -0
  39. package/src/analysis/detection-methods.js +347 -0
  40. package/src/analysis/importance-priority-calculator.js +18 -0
  41. package/src/analysis/priority/factor-calculators.js +204 -0
  42. package/src/analysis/priority/factor-helpers.js +71 -0
  43. package/src/analysis/priority/priority-constants.js +73 -0
  44. package/src/analysis/priority/priority-factor-calculators.js +301 -0
  45. package/src/analysis/priority/reasons-generator.js +44 -0
  46. package/src/analysis/priority-calculator.js +15 -580
  47. package/src/analysis/strategy-generator.js +16 -66
  48. package/src/analysis/type-priority-calculator.js +18 -0
  49. package/src/analysis/urgency-priority-calculator.js +18 -0
  50. package/src/auto-mode/AutoModeBusinessLogic.js +2 -40
  51. package/src/commands/disable-requirement.js +60 -0
  52. package/src/commands/disable-spec.js +60 -0
  53. package/src/commands/enable-requirement.js +60 -0
  54. package/src/commands/enable-spec.js +60 -0
  55. package/src/commands/registry.js +1 -6
  56. package/src/commands/requirements.js +8 -2
  57. package/src/ide-integration/applescript-manager.cjs +9 -24
  58. package/src/ide-integration/cdp-handlers/chat-reader.js +44 -0
  59. package/src/ide-integration/cdp-handlers/connection-handler.js +88 -0
  60. package/src/ide-integration/cdp-handlers/continuation-handler.js +314 -0
  61. package/src/ide-integration/cdp-handlers/message-submitter.js +75 -0
  62. package/src/ide-integration/cdp-handlers/text-sender.js +138 -0
  63. package/src/ide-integration/cdp-manager.js +28 -573
  64. package/src/ide-integration/claude-code-cli-manager.cjs +48 -12
  65. package/src/ide-integration/ide-openers/claude-opener.js +171 -0
  66. package/src/ide-integration/ide-openers/cursor-opener.js +53 -0
  67. package/src/ide-integration/ide-openers/other-ides-opener.js +230 -0
  68. package/src/ide-integration/ide-openers/vscode-opener.js +147 -0
  69. package/src/ide-integration/macos-ide-manager.js +20 -582
  70. package/src/ide-integration/macos-quota-checker.js +164 -0
  71. package/src/ide-integration/macos-text-sender.js +19 -38
  72. package/src/ide-integration/provider-manager.cjs +52 -7
  73. package/src/index.cjs +6 -0
  74. package/src/index.js +10 -0
  75. package/src/llm/direct-llm-manager.cjs +501 -0
  76. package/src/localization/translations/en-part1.js +363 -0
  77. package/src/localization/translations/en-part2.js +320 -0
  78. package/src/localization/translations/en.js +4 -687
  79. package/src/localization/translations/es-part1.js +363 -0
  80. package/src/localization/translations/es-part2.js +320 -0
  81. package/src/localization/translations/es.js +4 -688
  82. package/src/models/file-analysis-collection.js +139 -0
  83. package/src/models/file-analysis-metrics.js +50 -0
  84. package/src/models/file-analysis.js +15 -262
  85. package/src/models/plan-manager.js +410 -0
  86. package/src/models/refactoring-models.js +380 -0
  87. package/src/models/refactoring-plan-refactored.js +81 -0
  88. package/src/models/refactoring-plan.js +2 -663
  89. package/src/monitoring/alert-system.js +4 -45
  90. package/src/monitoring/continuous-scan-notifications.js +37 -191
  91. package/src/monitoring/notification-handlers/base-handler.js +58 -0
  92. package/src/monitoring/notification-handlers/error-handler.js +36 -0
  93. package/src/monitoring/notification-handlers/index.js +21 -0
  94. package/src/monitoring/notification-handlers/new-violation-handler.js +91 -0
  95. package/src/monitoring/notification-handlers/progress-handler.js +48 -0
  96. package/src/monitoring/notification-handlers/resolved-violation-handler.js +54 -0
  97. package/src/monitoring/notification-handlers/threshold-handler.js +36 -0
  98. package/src/provider-registry.js +8 -0
  99. package/src/refactoring/boundary/boundary-detector-refactored.js +58 -0
  100. package/src/refactoring/boundary/boundary-detector.js +26 -596
  101. package/src/refactoring/boundary/detectors/boundary-analyzers.js +281 -0
  102. package/src/refactoring/boundary/detectors/boundary-core.js +167 -0
  103. package/src/refactoring/boundary/detectors/class-detector.js +247 -0
  104. package/src/refactoring/boundary/detectors/config-detector.js +270 -0
  105. package/src/refactoring/boundary/detectors/constant-detector.js +269 -0
  106. package/src/refactoring/boundary/detectors/function-detector.js +248 -0
  107. package/src/refactoring/boundary/detectors/module-detector.js +249 -0
  108. package/src/refactoring/boundary/detectors/object-detector.js +247 -0
  109. package/src/refactoring/boundary/detectors/type-detectors.js +338 -0
  110. package/src/refactoring/boundary/detectors/utility-detector.js +270 -0
  111. package/src/refactoring/circular-dependency-resolver-original.js +16 -76
  112. package/src/refactoring/code-mover-refactored.js +309 -0
  113. package/src/refactoring/code-mover.js +48 -355
  114. package/src/refactoring/execution-status.js +18 -0
  115. package/src/refactoring/execution-strategies.js +172 -0
  116. package/src/refactoring/file-splitter-core.js +568 -0
  117. package/src/refactoring/file-splitter-types.js +136 -0
  118. package/src/refactoring/file-splitter.js +2 -682
  119. package/src/refactoring/functionality-validator.js +11 -51
  120. package/src/refactoring/import-manager-refactored.js +385 -0
  121. package/src/refactoring/import-manager.js +112 -487
  122. package/src/refactoring/import-models.js +189 -0
  123. package/src/refactoring/import-parser.js +306 -0
  124. package/src/refactoring/move-executor.js +431 -0
  125. package/src/refactoring/move-utils.js +368 -0
  126. package/src/refactoring/operation-executor.js +76 -0
  127. package/src/refactoring/plan-creator.js +36 -0
  128. package/src/refactoring/plan-executor.js +143 -0
  129. package/src/refactoring/plan-validator.js +68 -0
  130. package/src/refactoring/refactoring-executor-result.js +70 -0
  131. package/src/refactoring/refactoring-executor.js +34 -569
  132. package/src/refactoring/refactoring-operation.js +94 -0
  133. package/src/refactoring/refactoring-plan.js +69 -0
  134. package/src/refactoring/refactoring-rollback.js +22 -527
  135. package/src/refactoring/rollback-handlers/RollbackExecutor.js +107 -0
  136. package/src/refactoring/rollback-handlers/RollbackManager.js +265 -0
  137. package/src/refactoring/rollback-handlers/RollbackOperation.js +105 -0
  138. package/src/refactoring/rollback-handlers/RollbackResult.js +109 -0
  139. package/src/refactoring/rollback-handlers/RollbackStatistics.js +77 -0
  140. package/src/refactoring/test-validator.js +32 -448
  141. package/src/refactoring/validation/baseline-runner.js +71 -0
  142. package/src/refactoring/validation/report-generator.js +136 -0
  143. package/src/refactoring/validation/result-comparator.js +92 -0
  144. package/src/refactoring/validation/test-suite.js +59 -0
  145. package/src/refactoring/validation/test-validation-result.js +83 -0
  146. package/src/refactoring/validation/validation-runner.js +95 -0
  147. package/src/refactoring/validation/validation-status.js +18 -0
  148. package/src/rui/commands/AgentCommandParser.js +60 -369
  149. package/src/rui/commands/AgentResponseFormatter.js +7 -47
  150. package/src/rui/commands/parsers/CommandMapper.js +148 -0
  151. package/src/rui/commands/parsers/CommandValidator.js +228 -0
  152. package/src/rui/commands/parsers/ComponentExtractor.js +100 -0
  153. package/src/rui/commands/parsers/TokenParser.js +69 -0
  154. package/src/rui/commands/parsers/tokenizer.js +153 -0
  155. package/src/utils/current-requirement-operations.js +50 -1
  156. package/src/utils/report-generator.js +18 -514
  157. package/src/utils/report-generators/analysis-generator.js +115 -0
  158. package/src/utils/report-generators/base-generator.js +141 -0
  159. package/src/utils/report-generators/compliance-generator.js +41 -0
  160. package/src/utils/report-generators/format-handlers.js +185 -0
  161. package/src/utils/report-generators/refactoring-generator.js +46 -0
  162. package/src/utils/report-generators/validation-generator.js +63 -0
  163. package/src/utils/requirement-enable-disable.js +265 -0
  164. package/src/utils/requirement-helpers/requirement-file-ops.js +69 -1
  165. package/src/utils/requirement-helpers/requirement-mover.js +88 -1
  166. package/src/utils/requirement-helpers.js +5 -2
  167. package/src/utils/smoke-test-cli.js +45 -8
  168. package/src/utils/specification-enable-disable.js +122 -0
  169. package/src/utils/specification-helpers.js +30 -4
  170. package/src/utils/specification-migration.js +5 -5
  171. package/src/utils/test-comparator.js +118 -0
  172. package/src/utils/test-config.js +54 -0
  173. package/src/utils/test-executor.js +133 -0
  174. package/src/utils/test-parser.js +215 -0
  175. package/src/utils/test-runner-baseline.js +63 -0
  176. package/src/utils/test-runner-core.js +98 -0
  177. package/src/utils/test-runner-report.js +39 -0
  178. package/src/utils/test-runner-validation.js +71 -0
  179. package/src/utils/test-runner.js +11 -535
  180. package/src/validation/comparison-analyzer.js +333 -0
  181. package/src/validation/compliance-reporter-new.js +282 -0
  182. package/src/validation/compliance-reporter-refactored.js +344 -0
  183. package/src/validation/compliance-reporter.js +278 -591
  184. package/src/validation/compliance-utils.js +278 -0
  185. package/src/validation/html-generator.js +446 -0
  186. package/src/validation/metrics/category-calculator.js +137 -0
  187. package/src/validation/metrics/metrics-helpers.js +155 -0
  188. package/src/validation/metrics/overview-calculator.js +85 -0
  189. package/src/validation/metrics/overview-metrics.js +41 -0
  190. package/src/validation/metrics/quality-calculator.js +166 -0
  191. package/src/validation/metrics/size-calculator.js +69 -0
  192. package/src/validation/metrics-calculator.js +27 -551
@@ -0,0 +1,472 @@
1
+ /**
2
+ * Simple Agent Check Service
3
+ *
4
+ * Simplified agent checking that does exactly 5 steps:
5
+ * 1. Check if agent/IDE is installed
6
+ * 2. Add test requirement to hostname-specific requirements file
7
+ * 3. Send simple check command to agent
8
+ * 4. Check for test result
9
+ * 5. Delete test requirement (success or failure)
10
+ *
11
+ * Follows constitutional requirements: <555 lines, test-first approach.
12
+ */
13
+
14
+ const path = require('path');
15
+ const fs = require('fs').promises;
16
+ const fsSync = require('fs');
17
+ const os = require('os');
18
+ const { spawn } = require('child_process');
19
+
20
+ // Constants
21
+ const TEST_REQ_TITLE = 'VCM agent connectivity check';
22
+ const PENDING_HEADER = '## ⏳ Requirements not yet completed';
23
+ const VERIFIED_HEADER = '## ✅ Verified by AI';
24
+
25
+ /**
26
+ * Get hostname-based requirements file path
27
+ */
28
+ function getRequirementsPath(repoPath) {
29
+ const hostname = os.hostname();
30
+ return path.join(repoPath, '.vibecodingmachine', `REQUIREMENTS-${hostname}.md`);
31
+ }
32
+
33
+ /**
34
+ * Get result file path
35
+ */
36
+ function getResultFilePath(repoPath) {
37
+ return path.join(repoPath, '.vibecodingmachine', 'temp', 'TEMP_agent_check.txt');
38
+ }
39
+
40
+ /**
41
+ * Simple agent check service class
42
+ */
43
+ class SimpleAgentCheckService {
44
+ constructor(options = {}) {
45
+ this.logger = options.logger || null;
46
+ this.repoPath = options.repoPath || process.cwd();
47
+ this.timeout = options.timeout || 60000; // 1 minute default
48
+ }
49
+
50
+ /**
51
+ * Check if agent is installed
52
+ */
53
+ async checkAgentInstallation(agentId, agentConfig) {
54
+ if (agentConfig.type === 'ide') {
55
+ // Check if IDE process is running
56
+ const processName = agentConfig.process;
57
+ const { exec } = require('child_process');
58
+
59
+ return new Promise((resolve) => {
60
+ exec(`pgrep -f "${processName}"`, (error, stdout, stderr) => {
61
+ const isRunning = !error && stdout.trim().length > 0;
62
+ resolve({ installed: isRunning, processName });
63
+ });
64
+ });
65
+ } else {
66
+ // For CLI agents, check if command exists
67
+ const command = agentConfig.command;
68
+ const { exec } = require('child_process');
69
+
70
+ return new Promise((resolve) => {
71
+ exec(`which ${command}`, (error, stdout, stderr) => {
72
+ const isInstalled = !error;
73
+ resolve({ installed: isInstalled, command });
74
+ });
75
+ });
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Add test requirement to requirements file
81
+ */
82
+ async addTestRequirement(agentId) {
83
+ const reqPath = getRequirementsPath(this.repoPath);
84
+ const resultFile = getResultFilePath(this.repoPath);
85
+
86
+ let content = '';
87
+ try {
88
+ content = await fs.readFile(reqPath, 'utf8');
89
+ } catch (error) {
90
+ if (error.code === 'ENOENT') {
91
+ // Create file with basic structure
92
+ content = `## ⏳ Requirements not yet completed
93
+
94
+ ## ✅ Verified by AI
95
+
96
+ `;
97
+ } else {
98
+ throw error;
99
+ }
100
+ }
101
+
102
+ // Already present?
103
+ if (content.includes(TEST_REQ_TITLE)) {
104
+ return { added: false, reason: 'already_exists' };
105
+ }
106
+
107
+ const testBlock = `### 1. ${TEST_REQ_TITLE}
108
+ 🚦 Current Status: PREPARE
109
+ Create a new file at the following absolute path: ${resultFile}
110
+ The file must contain exactly this text on the first line: VCM_CHECK_OK
111
+ Do not modify any other files. This is an automated connectivity test.
112
+
113
+ `;
114
+
115
+ const pendingIndex = content.indexOf('## ⏳ Requirements not yet completed');
116
+ if (pendingIndex !== -1) {
117
+ // Insert after the pending header
118
+ const afterHeader = pendingIndex + '## ⏳ Requirements not yet completed'.length;
119
+ const before = content.slice(0, afterHeader);
120
+ const after = content.slice(afterHeader).replace(/^\n+/, '');
121
+ const newContent = before + '\n\n' + testBlock + after;
122
+ await fs.writeFile(reqPath, newContent, 'utf8');
123
+ } else {
124
+ // If no pending header, add it
125
+ const newContent = `## ⏳ Requirements not yet completed
126
+
127
+ ${testBlock}
128
+
129
+ ## ✅ Verified by AI
130
+
131
+ `;
132
+ await fs.writeFile(reqPath, newContent, 'utf8');
133
+ }
134
+
135
+ return { added: true, reqPath, resultFile };
136
+ }
137
+
138
+ /**
139
+ * Send simple check command to agent
140
+ */
141
+ async sendCheckCommand(agentId, agentConfig) {
142
+ if (agentConfig.type === 'ide') {
143
+ // For IDE agents, use auto mode
144
+ const CLI_ENTRY_POINT = path.join(this.repoPath, 'bin', 'vibecodingmachine.js');
145
+ const args = ['auto', 'start', '--ide', agentId, '--max-chats', '1'];
146
+
147
+ return new Promise((resolve) => {
148
+ const child = spawn('node', args, {
149
+ cwd: this.repoPath,
150
+ stdio: ['ignore', 'pipe', 'pipe'],
151
+ detached: false
152
+ });
153
+
154
+ let output = '';
155
+ child.stdout.on('data', (data) => {
156
+ output += data.toString();
157
+ });
158
+
159
+ child.stderr.on('data', (data) => {
160
+ output += data.toString();
161
+ });
162
+
163
+ child.on('exit', (code) => {
164
+ resolve({ success: code === 0, output, exitCode: code });
165
+ });
166
+
167
+ // Timeout
168
+ setTimeout(() => {
169
+ if (!child.killed) {
170
+ child.kill();
171
+ resolve({ success: false, output, exitCode: 'TIMEOUT' });
172
+ }
173
+ }, this.timeout);
174
+ });
175
+ } else {
176
+ // For CLI agents, send agent test command
177
+ const command = agentConfig.command;
178
+ const args = ['agent', 'test', '--repo', this.repoPath, '--result', getResultFilePath(this.repoPath)];
179
+
180
+ return new Promise((resolve) => {
181
+ const child = spawn(command, args, {
182
+ cwd: this.repoPath,
183
+ stdio: ['ignore', 'pipe', 'pipe'],
184
+ detached: false
185
+ });
186
+
187
+ let output = '';
188
+ child.stdout.on('data', (data) => {
189
+ output += data.toString();
190
+ });
191
+
192
+ child.stderr.on('data', (data) => {
193
+ output += data.toString();
194
+ });
195
+
196
+ child.on('exit', (code) => {
197
+ resolve({ success: code === 0, output, exitCode: code });
198
+ });
199
+
200
+ // Timeout
201
+ setTimeout(() => {
202
+ if (!child.killed) {
203
+ child.kill();
204
+ resolve({ success: false, output, exitCode: 'TIMEOUT' });
205
+ }
206
+ }, this.timeout);
207
+ });
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Check for test result
213
+ */
214
+ async checkTestResult(agentId) {
215
+ const resultFile = getResultFilePath(this.repoPath);
216
+
217
+ // Wait a bit for file to be created
218
+ await new Promise(resolve => setTimeout(resolve, 2000));
219
+
220
+ try {
221
+ if (fsSync.existsSync(resultFile)) {
222
+ const content = fsSync.readFileSync(resultFile, 'utf8');
223
+ const success = content.includes('VCM_CHECK_OK');
224
+
225
+ return { success, content };
226
+ } else {
227
+ return { success: false, reason: 'file_not_found' };
228
+ }
229
+ } catch (error) {
230
+ return { success: false, reason: 'error', error: error.message };
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Remove test requirement
236
+ */
237
+ async removeTestRequirement(agentId) {
238
+ const reqPath = getRequirementsPath(this.repoPath);
239
+
240
+ try {
241
+ let content = '';
242
+ try {
243
+ content = await fs.readFile(reqPath, 'utf8');
244
+ } catch {
245
+ return { removed: false, reason: 'file_not_found' };
246
+ }
247
+
248
+ if (!content.includes(TEST_REQ_TITLE)) {
249
+ return { removed: false, reason: 'not_found' };
250
+ }
251
+
252
+ const lines = content.split('\n');
253
+ let blockStart = -1;
254
+
255
+ for (let i = 0; i < lines.length; i++) {
256
+ if (lines[i].includes(TEST_REQ_TITLE)) {
257
+ blockStart = i;
258
+ break;
259
+ }
260
+ }
261
+
262
+ if (blockStart === -1) {
263
+ return { removed: false, reason: 'not_found' };
264
+ }
265
+
266
+ let blockEnd = blockStart + 1;
267
+ while (blockEnd < lines.length && !lines[blockEnd].startsWith('###') && !lines[blockEnd].startsWith('## ')) {
268
+ blockEnd++;
269
+ }
270
+
271
+ lines.splice(blockStart, blockEnd - blockStart);
272
+ const cleaned = lines.join('\n').replace(/\n{3,}/g, '\n\n').trimEnd() + '\n';
273
+ await fs.writeFile(reqPath, cleaned, 'utf8');
274
+
275
+ return { removed: true };
276
+ } catch (error) {
277
+ return { removed: false, reason: 'error', error: error.message };
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Clean up test result file
283
+ */
284
+ async cleanupTestResult(agentId) {
285
+ const resultFile = getResultFilePath(this.repoPath);
286
+
287
+ try {
288
+ if (fsSync.existsSync(resultFile)) {
289
+ fsSync.unlinkSync(resultFile);
290
+ }
291
+ } catch (error) {
292
+ // Silently handle cleanup errors
293
+ }
294
+ }
295
+
296
+ /**
297
+ * Check single agent - simplified 5-step process
298
+ */
299
+ async checkAgent(agent, options = {}) {
300
+ const agentId = agent.id;
301
+ const startTime = Date.now();
302
+ const onProgress = options.onProgress || (() => {});
303
+
304
+ try {
305
+ // Step 1: Check installation
306
+ onProgress(agentId, {
307
+ phase: 'step1',
308
+ step: 1,
309
+ message: 'INSTALLED?',
310
+ detail: `Checking ${agent.name} installation...`
311
+ });
312
+
313
+ const installCheck = await this.checkAgentInstallation(agentId, agent);
314
+
315
+ const installDetail = agent.type === 'ide'
316
+ ? `Process: ${installCheck.processName || agent.process} - ${installCheck.installed ? 'RUNNING' : 'NOT RUNNING'}`
317
+ : `Command: ${installCheck.command || agent.command} - ${installCheck.installed ? 'AVAILABLE' : 'NOT FOUND'}`;
318
+
319
+ onProgress(agentId, {
320
+ phase: 'step1',
321
+ step: 1,
322
+ message: 'INSTALLED?',
323
+ detail: installDetail
324
+ });
325
+
326
+ if (!installCheck.installed) {
327
+ const message = agent.type === 'ide'
328
+ ? `${agent.name} is not running (process: ${installCheck.processName || agent.process})`
329
+ : `${agent.name} is not installed (command: ${installCheck.command || agent.command})`;
330
+
331
+ return {
332
+ success: false,
333
+ agentId,
334
+ status: 'not_installed',
335
+ message,
336
+ duration: Date.now() - startTime,
337
+ timestamp: new Date().toISOString()
338
+ };
339
+ }
340
+
341
+ // Step 2: Add test requirement
342
+ onProgress(agentId, {
343
+ phase: 'step2',
344
+ step: 2,
345
+ message: 'REQUIREMENTS',
346
+ detail: 'Adding test requirement to requirements file...'
347
+ });
348
+
349
+ const reqResult = await this.addTestRequirement(agentId);
350
+
351
+ const reqDetail = reqResult.added
352
+ ? `Added test requirement to ${reqResult.reqPath}`
353
+ : `Failed to add requirement: ${reqResult.reason}`;
354
+
355
+ onProgress(agentId, {
356
+ phase: 'step2',
357
+ step: 2,
358
+ message: 'REQUIREMENTS',
359
+ detail: reqDetail
360
+ });
361
+
362
+ if (!reqResult.added) {
363
+ return {
364
+ success: false,
365
+ agentId,
366
+ status: 'requirement_error',
367
+ message: `Failed to add test requirement: ${reqResult.reason}`,
368
+ duration: Date.now() - startTime,
369
+ timestamp: new Date().toISOString()
370
+ };
371
+ }
372
+
373
+ // Step 3: Send check command
374
+ onProgress(agentId, {
375
+ phase: 'step3',
376
+ step: 3,
377
+ message: 'TEST',
378
+ detail: `Sending check command to ${agent.name}...`
379
+ });
380
+
381
+ const cmdResult = await this.sendCheckCommand(agentId, agent);
382
+
383
+ const cmdDetail = cmdResult.success
384
+ ? `Command sent successfully`
385
+ : `Command failed: ${cmdResult.exitCode === 'TIMEOUT' ? 'TIMEOUT' : `Exit code ${cmdResult.exitCode}`}`;
386
+
387
+ onProgress(agentId, {
388
+ phase: 'step3',
389
+ step: 3,
390
+ message: 'TEST',
391
+ detail: cmdDetail
392
+ });
393
+
394
+ // Step 4: Check test result
395
+ const testResult = await this.checkTestResult(agentId);
396
+
397
+ const testDetail = testResult.success
398
+ ? `Test result: SUCCESS`
399
+ : `Test result: ${testResult.reason || 'FAILED'}`;
400
+
401
+ onProgress(agentId, {
402
+ phase: 'step4',
403
+ step: 4,
404
+ message: 'DELETE',
405
+ detail: 'Cleaning up test requirement...'
406
+ });
407
+
408
+ // Step 5: Remove test requirement
409
+ const removeResult = await this.removeTestRequirement(agentId);
410
+
411
+ const removeDetail = removeResult.removed
412
+ ? `Test requirement removed successfully`
413
+ : `Remove failed: ${removeResult.reason}`;
414
+
415
+ onProgress(agentId, {
416
+ phase: 'step5',
417
+ step: 5,
418
+ message: 'STATUS',
419
+ detail: testDetail
420
+ });
421
+
422
+ // Clean up test result file
423
+ await this.cleanupTestResult(agentId);
424
+
425
+ // Determine final status
426
+ let status, message;
427
+ if (testResult.success) {
428
+ status = 'reachable';
429
+ message = `${agent.name} is reachable and responding`;
430
+ } else if (cmdResult.exitCode === 'TIMEOUT') {
431
+ status = 'timeout';
432
+ message = `${agent.name} timed out - may need authentication`;
433
+ } else if (cmdResult.output && cmdResult.output.toLowerCase().includes('rate limit')) {
434
+ status = 'rate_limited';
435
+ message = `${agent.name} is rate limited`;
436
+ } else {
437
+ status = 'unreachable';
438
+ message = `${agent.name} is not responding - check authentication`;
439
+ }
440
+
441
+ const duration = Date.now() - startTime;
442
+
443
+ return {
444
+ success: testResult.success,
445
+ agentId,
446
+ status,
447
+ message,
448
+ duration,
449
+ timestamp: new Date().toISOString(),
450
+ details: {
451
+ installCheck,
452
+ reqResult,
453
+ cmdResult,
454
+ testResult
455
+ }
456
+ };
457
+
458
+ } catch (error) {
459
+ return {
460
+ success: false,
461
+ agentId,
462
+ status: 'error',
463
+ message: `Check failed: ${error.message}`,
464
+ duration: Date.now() - startTime,
465
+ timestamp: new Date().toISOString(),
466
+ error: error.message
467
+ };
468
+ }
469
+ }
470
+ }
471
+
472
+ module.exports = SimpleAgentCheckService;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Configuration Utilities Module
3
+ *
4
+ * Provides utility functions for configuration management.
5
+ * Follows constitutional requirements: <555 lines, test-first approach.
6
+ */
7
+
8
+ /**
9
+ * Set nested configuration value
10
+ * @param {Object} obj - Target object
11
+ * @param {string} path - Dot-separated path
12
+ * @param {*} value - Value to set
13
+ */
14
+ function setNestedValue(obj, path, value) {
15
+ const keys = path.split('.');
16
+ let current = obj;
17
+
18
+ for (let i = 0; i < keys.length - 1; i++) {
19
+ const key = keys[i];
20
+ if (!(key in current) || typeof current[key] !== 'object') {
21
+ current[key] = {};
22
+ }
23
+ current = current[key];
24
+ }
25
+
26
+ current[keys[keys.length - 1]] = value;
27
+ }
28
+
29
+ /**
30
+ * Get nested configuration value
31
+ * @param {Object} obj - Source object
32
+ * @param {string} path - Dot-separated path
33
+ * @returns {*} - Configuration value
34
+ */
35
+ function getNestedValue(obj, path) {
36
+ const keys = path.split('.');
37
+ let current = obj;
38
+
39
+ for (const key of keys) {
40
+ if (current && typeof current === 'object' && key in current) {
41
+ current = current[key];
42
+ } else {
43
+ return undefined;
44
+ }
45
+ }
46
+
47
+ return current;
48
+ }
49
+
50
+ /**
51
+ * Deep merge objects
52
+ * @param {Object} target - Target object
53
+ * @param {Object} source - Source object
54
+ */
55
+ function deepMerge(target, source) {
56
+ for (const key in source) {
57
+ if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
58
+ if (!target[key] || typeof target[key] !== 'object') {
59
+ target[key] = {};
60
+ }
61
+ deepMerge(target[key], source[key]);
62
+ } else {
63
+ target[key] = source[key];
64
+ }
65
+ }
66
+ }
67
+
68
+ module.exports = {
69
+ setNestedValue,
70
+ getNestedValue,
71
+ deepMerge
72
+ };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Default Configuration Module
3
+ *
4
+ * Defines default configuration schema.
5
+ * Follows constitutional requirements: <555 lines, test-first approach.
6
+ */
7
+
8
+ /**
9
+ * Get default configuration schema
10
+ * @returns {Object} - Default configuration
11
+ */
12
+ function getDefaultConfig() {
13
+ return {
14
+ installation: {
15
+ timeout: 300000,
16
+ maxConcurrent: 2,
17
+ retryAttempts: 3,
18
+ retryDelay: 5000,
19
+ autoElevate: false
20
+ },
21
+ logging: {
22
+ level: 'info',
23
+ file: null,
24
+ format: 'json',
25
+ verbose: false
26
+ },
27
+ cache: {
28
+ directory: './cache',
29
+ maxSize: 100 * 1024 * 1024, // 100MB
30
+ ttl: 3600000 // 1 hour
31
+ },
32
+ network: {
33
+ timeout: 30000,
34
+ proxy: null,
35
+ userAgent: null,
36
+ rateLimitDelay: 1000
37
+ },
38
+ security: {
39
+ strictMode: true,
40
+ maxFileSize: 100 * 1024 * 1024, // 100MB
41
+ allowedExtensions: ['.exe', '.msi', '.zip', '.tar', '.gz']
42
+ },
43
+ performance: {
44
+ monitoring: true,
45
+ metricsFile: null,
46
+ flushInterval: 60000
47
+ },
48
+ agents: {
49
+ defaultFile: './config/agents.json',
50
+ discoveryEnabled: true,
51
+ autoUpdate: false
52
+ }
53
+ };
54
+ }
55
+
56
+ module.exports = {
57
+ getDefaultConfig
58
+ };
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Environment Variable Loader Module
3
+ *
4
+ * Handles loading configuration from environment variables.
5
+ * Follows constitutional requirements: <555 lines, test-first approach.
6
+ */
7
+
8
+ const { setNestedValue } = require('./ConfigUtils');
9
+
10
+ /**
11
+ * Load configuration from environment variables
12
+ * @param {Object} variableMappings - Variable mappings
13
+ * @param {string} prefix - Environment variable prefix
14
+ * @param {Object} logger - Logger instance
15
+ * @returns {Object} - Environment configuration
16
+ */
17
+ function loadEnvironmentVariables(variableMappings, prefix, logger) {
18
+ const config = {};
19
+
20
+ for (const [envVar, configPath] of Object.entries(variableMappings)) {
21
+ const fullEnvVar = prefix + envVar;
22
+ const value = process.env[fullEnvVar];
23
+
24
+ if (value !== undefined) {
25
+ setNestedValue(config, configPath, value);
26
+
27
+ if (logger) {
28
+ logger.debug('Loaded environment variable', {
29
+ variable: fullEnvVar,
30
+ configPath,
31
+ value
32
+ });
33
+ }
34
+ }
35
+ }
36
+
37
+ return config;
38
+ }
39
+
40
+ /**
41
+ * Export configuration to environment file
42
+ * @param {Object} config - Configuration object
43
+ * @param {Object} defaultConfig - Default configuration
44
+ * @param {Object} variableMappings - Variable mappings
45
+ * @param {string} prefix - Environment variable prefix
46
+ * @param {Function} getNestedValue - Get nested value function
47
+ * @returns {Array<string>} - Environment variable lines
48
+ */
49
+ function exportToEnvironmentVariables(config, defaultConfig, variableMappings, prefix, getNestedValue) {
50
+ const envVars = [];
51
+
52
+ for (const [envVar, configPath] of Object.entries(variableMappings)) {
53
+ const value = getNestedValue(config, configPath);
54
+ if (value !== undefined && value !== getNestedValue(defaultConfig, configPath)) {
55
+ const fullEnvVar = prefix + envVar;
56
+ envVars.push(`${fullEnvVar}=${JSON.stringify(value)}`);
57
+ }
58
+ }
59
+
60
+ return envVars;
61
+ }
62
+
63
+ module.exports = {
64
+ loadEnvironmentVariables,
65
+ exportToEnvironmentVariables
66
+ };