buildhive-agent 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/README.md +166 -0
  2. package/dist/__tests__/fakes/FakeDockerManager.d.ts +115 -0
  3. package/dist/__tests__/fakes/FakeDockerManager.d.ts.map +1 -0
  4. package/dist/__tests__/fakes/FakeDockerManager.js +203 -0
  5. package/dist/__tests__/fakes/FakeDockerManager.js.map +1 -0
  6. package/dist/acceptanceChecker.d.ts +26 -0
  7. package/dist/acceptanceChecker.d.ts.map +1 -0
  8. package/dist/acceptanceChecker.js +64 -0
  9. package/dist/acceptanceChecker.js.map +1 -0
  10. package/dist/advancedAgent.d.ts +161 -0
  11. package/dist/advancedAgent.d.ts.map +1 -0
  12. package/dist/advancedAgent.js +604 -0
  13. package/dist/advancedAgent.js.map +1 -0
  14. package/dist/agent.d.ts +101 -0
  15. package/dist/agent.d.ts.map +1 -0
  16. package/dist/agent.js +490 -0
  17. package/dist/agent.js.map +1 -0
  18. package/dist/api/jobStatusApi.d.ts +88 -0
  19. package/dist/api/jobStatusApi.d.ts.map +1 -0
  20. package/dist/api/jobStatusApi.js +240 -0
  21. package/dist/api/jobStatusApi.js.map +1 -0
  22. package/dist/autoUpdater.d.ts +135 -0
  23. package/dist/autoUpdater.d.ts.map +1 -0
  24. package/dist/autoUpdater.js +494 -0
  25. package/dist/autoUpdater.js.map +1 -0
  26. package/dist/cacheManager.d.ts +108 -0
  27. package/dist/cacheManager.d.ts.map +1 -0
  28. package/dist/cacheManager.js +300 -0
  29. package/dist/cacheManager.js.map +1 -0
  30. package/dist/cli.d.ts +11 -0
  31. package/dist/cli.d.ts.map +1 -0
  32. package/dist/cli.js +749 -0
  33. package/dist/cli.js.map +1 -0
  34. package/dist/config/index.d.ts +30 -0
  35. package/dist/config/index.d.ts.map +1 -0
  36. package/dist/config/index.js +35 -0
  37. package/dist/config/index.js.map +1 -0
  38. package/dist/config/loader.d.ts +45 -0
  39. package/dist/config/loader.d.ts.map +1 -0
  40. package/dist/config/loader.js +269 -0
  41. package/dist/config/loader.js.map +1 -0
  42. package/dist/config/types.d.ts +193 -0
  43. package/dist/config/types.d.ts.map +1 -0
  44. package/dist/config/types.js +90 -0
  45. package/dist/config/types.js.map +1 -0
  46. package/dist/config/validation.d.ts +28 -0
  47. package/dist/config/validation.d.ts.map +1 -0
  48. package/dist/config/validation.js +397 -0
  49. package/dist/config/validation.js.map +1 -0
  50. package/dist/docker.d.ts +96 -0
  51. package/dist/docker.d.ts.map +1 -0
  52. package/dist/docker.js +411 -0
  53. package/dist/docker.js.map +1 -0
  54. package/dist/enhancedJobExecutor.d.ts +81 -0
  55. package/dist/enhancedJobExecutor.d.ts.map +1 -0
  56. package/dist/enhancedJobExecutor.js +223 -0
  57. package/dist/enhancedJobExecutor.js.map +1 -0
  58. package/dist/executors/executorFactory.d.ts +46 -0
  59. package/dist/executors/executorFactory.d.ts.map +1 -0
  60. package/dist/executors/executorFactory.js +80 -0
  61. package/dist/executors/executorFactory.js.map +1 -0
  62. package/dist/executors/index.d.ts +7 -0
  63. package/dist/executors/index.d.ts.map +1 -0
  64. package/dist/executors/index.js +6 -0
  65. package/dist/executors/index.js.map +1 -0
  66. package/dist/executors/nativeExecutor.d.ts +60 -0
  67. package/dist/executors/nativeExecutor.d.ts.map +1 -0
  68. package/dist/executors/nativeExecutor.js +311 -0
  69. package/dist/executors/nativeExecutor.js.map +1 -0
  70. package/dist/executors/types.d.ts +38 -0
  71. package/dist/executors/types.d.ts.map +1 -0
  72. package/dist/executors/types.js +9 -0
  73. package/dist/executors/types.js.map +1 -0
  74. package/dist/healthMonitor.d.ts +213 -0
  75. package/dist/healthMonitor.d.ts.map +1 -0
  76. package/dist/healthMonitor.js +547 -0
  77. package/dist/healthMonitor.js.map +1 -0
  78. package/dist/index.d.ts +16 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +16 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/jobExecutor.d.ts +117 -0
  83. package/dist/jobExecutor.d.ts.map +1 -0
  84. package/dist/jobExecutor.js +458 -0
  85. package/dist/jobExecutor.js.map +1 -0
  86. package/dist/lifecycleExecutor.d.ts +54 -0
  87. package/dist/lifecycleExecutor.d.ts.map +1 -0
  88. package/dist/lifecycleExecutor.js +230 -0
  89. package/dist/lifecycleExecutor.js.map +1 -0
  90. package/dist/main.d.ts +15 -0
  91. package/dist/main.d.ts.map +1 -0
  92. package/dist/main.js +77 -0
  93. package/dist/main.js.map +1 -0
  94. package/dist/metrics.d.ts +103 -0
  95. package/dist/metrics.d.ts.map +1 -0
  96. package/dist/metrics.js +360 -0
  97. package/dist/metrics.js.map +1 -0
  98. package/dist/recipes/builtinRecipes.d.ts +11 -0
  99. package/dist/recipes/builtinRecipes.d.ts.map +1 -0
  100. package/dist/recipes/builtinRecipes.js +688 -0
  101. package/dist/recipes/builtinRecipes.js.map +1 -0
  102. package/dist/recipes/index.d.ts +18 -0
  103. package/dist/recipes/index.d.ts.map +1 -0
  104. package/dist/recipes/index.js +17 -0
  105. package/dist/recipes/index.js.map +1 -0
  106. package/dist/recipes/recipeRegistry.d.ts +49 -0
  107. package/dist/recipes/recipeRegistry.d.ts.map +1 -0
  108. package/dist/recipes/recipeRegistry.js +264 -0
  109. package/dist/recipes/recipeRegistry.js.map +1 -0
  110. package/dist/recipes/types.d.ts +116 -0
  111. package/dist/recipes/types.d.ts.map +1 -0
  112. package/dist/recipes/types.js +10 -0
  113. package/dist/recipes/types.js.map +1 -0
  114. package/dist/recovery.d.ts +133 -0
  115. package/dist/recovery.d.ts.map +1 -0
  116. package/dist/recovery.js +299 -0
  117. package/dist/recovery.js.map +1 -0
  118. package/dist/registration/apiClient.d.ts +44 -0
  119. package/dist/registration/apiClient.d.ts.map +1 -0
  120. package/dist/registration/apiClient.js +149 -0
  121. package/dist/registration/apiClient.js.map +1 -0
  122. package/dist/registration/index.d.ts +41 -0
  123. package/dist/registration/index.d.ts.map +1 -0
  124. package/dist/registration/index.js +141 -0
  125. package/dist/registration/index.js.map +1 -0
  126. package/dist/registration/machineId.d.ts +30 -0
  127. package/dist/registration/machineId.d.ts.map +1 -0
  128. package/dist/registration/machineId.js +89 -0
  129. package/dist/registration/machineId.js.map +1 -0
  130. package/dist/registration/types.d.ts +32 -0
  131. package/dist/registration/types.d.ts.map +1 -0
  132. package/dist/registration/types.js +9 -0
  133. package/dist/registration/types.js.map +1 -0
  134. package/dist/resourceGovernor.d.ts +57 -0
  135. package/dist/resourceGovernor.d.ts.map +1 -0
  136. package/dist/resourceGovernor.js +125 -0
  137. package/dist/resourceGovernor.js.map +1 -0
  138. package/dist/security/secretManager.d.ts +107 -0
  139. package/dist/security/secretManager.d.ts.map +1 -0
  140. package/dist/security/secretManager.js +361 -0
  141. package/dist/security/secretManager.js.map +1 -0
  142. package/dist/security.d.ts +134 -0
  143. package/dist/security.d.ts.map +1 -0
  144. package/dist/security.js +470 -0
  145. package/dist/security.js.map +1 -0
  146. package/dist/storage/artifactUploader.d.ts +155 -0
  147. package/dist/storage/artifactUploader.d.ts.map +1 -0
  148. package/dist/storage/artifactUploader.js +554 -0
  149. package/dist/storage/artifactUploader.js.map +1 -0
  150. package/dist/types.d.ts +49 -0
  151. package/dist/types.d.ts.map +1 -0
  152. package/dist/types.js +7 -0
  153. package/dist/types.js.map +1 -0
  154. package/dist/utils/capabilities.d.ts +23 -0
  155. package/dist/utils/capabilities.d.ts.map +1 -0
  156. package/dist/utils/capabilities.js +200 -0
  157. package/dist/utils/capabilities.js.map +1 -0
  158. package/dist/utils/logger.d.ts +20 -0
  159. package/dist/utils/logger.d.ts.map +1 -0
  160. package/dist/utils/logger.js +188 -0
  161. package/dist/utils/logger.js.map +1 -0
  162. package/dist/utils/sdkScanner.d.ts +105 -0
  163. package/dist/utils/sdkScanner.d.ts.map +1 -0
  164. package/dist/utils/sdkScanner.js +459 -0
  165. package/dist/utils/sdkScanner.js.map +1 -0
  166. package/dist/websocketClient.d.ts +154 -0
  167. package/dist/websocketClient.d.ts.map +1 -0
  168. package/dist/websocketClient.js +422 -0
  169. package/dist/websocketClient.js.map +1 -0
  170. package/package.json +64 -0
@@ -0,0 +1,101 @@
1
+ /**
2
+ * BuildHive Agent - Core Agent Implementation
3
+ *
4
+ * Core agent class that manages the lifecycle of the BuildHive agent,
5
+ * including registration, job execution, and communication with the platform.
6
+ *
7
+ * Requirements: 1.1, 1.2, 1.5, 1.6, 4.1, 4.2, 4.3, 4.4, 4.5
8
+ */
9
+ import { AgentConfig } from './config/types.js';
10
+ import { AgentCapabilities, JobSubmissionRequest } from './types.js';
11
+ export interface JobResult {
12
+ jobId: string;
13
+ status: 'COMPLETED' | 'FAILED' | 'CANCELLED';
14
+ exitCode?: number;
15
+ logs?: string;
16
+ errorMessage?: string;
17
+ artifactUrls?: string[];
18
+ actualDuration?: number;
19
+ startedAt: Date;
20
+ completedAt: Date;
21
+ }
22
+ export declare class BuildHiveAgent {
23
+ private config;
24
+ private jobExecutor;
25
+ private enhancedJobExecutor;
26
+ private websocketClient;
27
+ private metricsCollector;
28
+ private jobStatusApi;
29
+ private recoveryManager;
30
+ private heartbeatInterval;
31
+ private metricsInterval;
32
+ private dockerHealthMonitor;
33
+ private isRunning;
34
+ private capabilities;
35
+ private activeJobs;
36
+ constructor(config: AgentConfig, capabilities?: AgentCapabilities);
37
+ /**
38
+ * Create agent with capability detection
39
+ */
40
+ static create(config: AgentConfig): Promise<BuildHiveAgent>;
41
+ /**
42
+ * Start the agent
43
+ */
44
+ start(): Promise<void>;
45
+ /**
46
+ * Stop the agent
47
+ */
48
+ stop(): Promise<void>;
49
+ /**
50
+ * Execute a job
51
+ */
52
+ executeJob(job: JobSubmissionRequest): Promise<JobResult>;
53
+ /**
54
+ * Get current agent status
55
+ */
56
+ getStatus(): {
57
+ isRunning: boolean;
58
+ activeJobs: number;
59
+ capabilities: AgentCapabilities;
60
+ uptime: number;
61
+ };
62
+ private startTime;
63
+ /**
64
+ * Initialize the EnhancedJobExecutor from config.
65
+ * Returns null if enhanced config sections are missing (backward compat).
66
+ */
67
+ private initEnhancedExecutor;
68
+ /**
69
+ * Convert a JobSubmissionRequest to an EnhancedJobRequest
70
+ */
71
+ private toEnhancedRequest;
72
+ /**
73
+ * Set up event handlers for WebSocket client
74
+ */
75
+ private setupEventHandlers;
76
+ /**
77
+ * Start heartbeat mechanism
78
+ */
79
+ private consecutiveHeartbeatFailures;
80
+ private static readonly MAX_HEARTBEAT_FAILURES;
81
+ private startHeartbeat;
82
+ /**
83
+ * Start metrics reporting
84
+ */
85
+ private startMetricsReporting;
86
+ /**
87
+ * Start Docker health monitoring (MVP.4.3.2)
88
+ *
89
+ * Continuously monitors Docker daemon health and attempts recovery on failure
90
+ */
91
+ private startDockerHealthMonitoring;
92
+ /**
93
+ * Calculate current load based on active jobs and system metrics
94
+ */
95
+ private calculateCurrentLoad;
96
+ /**
97
+ * Clean up resources
98
+ */
99
+ private cleanup;
100
+ }
101
+ //# sourceMappingURL=agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKhD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAarE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,IAAI,CAAC;CACnB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,mBAAmB,CAA+B;IAC1D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,UAAU,CAAiG;gBAEvG,MAAM,EAAE,WAAW,EAAE,YAAY,CAAC,EAAE,iBAAiB;IA8BjE;;OAEG;WACU,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;IAKjE;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkD5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB3B;;OAEG;IACG,UAAU,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC,SAAS,CAAC;IAmJ/D;;OAEG;IACH,SAAS,IAAI;QACX,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,iBAAiB,CAAC;QAChC,MAAM,EAAE,MAAM,CAAC;KAChB;IASD,OAAO,CAAC,SAAS,CAAc;IAE/B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IA0C5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAYzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAwD1B;;OAEG;IACH,OAAO,CAAC,4BAA4B,CAAK;IACzC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAK;IAEnD,OAAO,CAAC,cAAc;IAkCtB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAgB7B;;;;OAIG;IACH,OAAO,CAAC,2BAA2B;IA2BnC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAK5B;;OAEG;YACW,OAAO;CA6CtB"}
package/dist/agent.js ADDED
@@ -0,0 +1,490 @@
1
+ /**
2
+ * BuildHive Agent - Core Agent Implementation
3
+ *
4
+ * Core agent class that manages the lifecycle of the BuildHive agent,
5
+ * including registration, job execution, and communication with the platform.
6
+ *
7
+ * Requirements: 1.1, 1.2, 1.5, 1.6, 4.1, 4.2, 4.3, 4.4, 4.5
8
+ */
9
+ import { JobExecutor } from './jobExecutor.js';
10
+ import { WebSocketClient } from './websocketClient.js';
11
+ import { MetricsCollector } from './metrics.js';
12
+ import { createLogger } from './utils/logger.js';
13
+ import { detectCapabilities } from './utils/capabilities.js';
14
+ import { JobStatusApi } from './api/jobStatusApi.js';
15
+ import { RecoveryManager } from './recovery.js';
16
+ import { EnhancedJobExecutor } from './enhancedJobExecutor.js';
17
+ import { RecipeRegistry } from './recipes/recipeRegistry.js';
18
+ import { CacheManager } from './cacheManager.js';
19
+ import { AcceptanceChecker } from './acceptanceChecker.js';
20
+ import { ResourceGovernor } from './resourceGovernor.js';
21
+ const logger = createLogger('agent');
22
+ export class BuildHiveAgent {
23
+ config;
24
+ jobExecutor;
25
+ enhancedJobExecutor = null;
26
+ websocketClient;
27
+ metricsCollector;
28
+ jobStatusApi;
29
+ recoveryManager;
30
+ heartbeatInterval = null;
31
+ metricsInterval = null;
32
+ dockerHealthMonitor = null;
33
+ isRunning = false;
34
+ capabilities;
35
+ activeJobs = new Map();
36
+ constructor(config, capabilities) {
37
+ this.config = config;
38
+ // If capabilities provided (from async detection), use them; otherwise use empty placeholder
39
+ this.capabilities = capabilities || {
40
+ os: '',
41
+ arch: '',
42
+ cpuCores: 0,
43
+ memoryGB: 0,
44
+ diskSpaceGB: 0
45
+ };
46
+ // Initialize components
47
+ this.jobExecutor = new JobExecutor(config);
48
+ this.websocketClient = new WebSocketClient(config, this.capabilities);
49
+ this.metricsCollector = new MetricsCollector(config);
50
+ this.recoveryManager = new RecoveryManager();
51
+ // Initialize JobStatusApi for REST-based job status updates (MVP.4.2.2)
52
+ this.jobStatusApi = new JobStatusApi(config.platformUrl, config.apiKey);
53
+ // Initialize EnhancedJobExecutor if enhanced config sections are present
54
+ this.enhancedJobExecutor = this.initEnhancedExecutor(config);
55
+ // Set up event handlers
56
+ this.setupEventHandlers();
57
+ }
58
+ /**
59
+ * Create agent with capability detection
60
+ */
61
+ static async create(config) {
62
+ const capabilities = await detectCapabilities();
63
+ return new BuildHiveAgent(config, capabilities);
64
+ }
65
+ /**
66
+ * Start the agent
67
+ */
68
+ async start() {
69
+ if (this.isRunning) {
70
+ logger.warn('Agent is already running');
71
+ return;
72
+ }
73
+ try {
74
+ logger.info(`Starting BuildHive Agent: ${this.config.name}`);
75
+ logger.info('Detected capabilities:', this.capabilities);
76
+ // Clean up orphaned containers from previous crashes
77
+ try {
78
+ const cleaned = await this.jobExecutor.cleanupOrphanedContainers();
79
+ if (cleaned > 0) {
80
+ logger.info(`Cleaned ${cleaned} orphaned container(s) from previous run`);
81
+ }
82
+ }
83
+ catch (error) {
84
+ logger.warn('Orphan container cleanup failed (non-fatal):', error);
85
+ }
86
+ // Start metrics collection
87
+ await this.metricsCollector.start();
88
+ logger.info('Metrics collector started');
89
+ // Connect to platform via WebSocket
90
+ await this.websocketClient.connect();
91
+ logger.info('Connected to BuildHive platform');
92
+ // Start heartbeat
93
+ this.startHeartbeat();
94
+ logger.info('Heartbeat started');
95
+ // Start metrics reporting
96
+ this.startMetricsReporting();
97
+ logger.info('Metrics reporting started');
98
+ // Start Docker health monitoring (MVP.4.3.2)
99
+ this.startDockerHealthMonitoring();
100
+ logger.info('Docker health monitoring started');
101
+ this.isRunning = true;
102
+ logger.info('BuildHive Agent started successfully');
103
+ }
104
+ catch (error) {
105
+ logger.error('Failed to start agent:', error);
106
+ await this.cleanup();
107
+ throw error;
108
+ }
109
+ }
110
+ /**
111
+ * Stop the agent
112
+ */
113
+ async stop() {
114
+ if (!this.isRunning) {
115
+ logger.warn('Agent is not running');
116
+ return;
117
+ }
118
+ logger.info('Stopping BuildHive Agent...');
119
+ try {
120
+ // Cancel all active jobs
121
+ for (const [jobId] of this.activeJobs) {
122
+ logger.info(`Cancelling active job: ${jobId}`);
123
+ await this.jobExecutor.cancelJob(jobId);
124
+ }
125
+ await this.cleanup();
126
+ this.isRunning = false;
127
+ logger.info('BuildHive Agent stopped successfully');
128
+ }
129
+ catch (error) {
130
+ logger.error('Error during agent shutdown:', error);
131
+ throw error;
132
+ }
133
+ }
134
+ /**
135
+ * Execute a job
136
+ */
137
+ async executeJob(job) {
138
+ const startTime = new Date();
139
+ // Use database jobId for API calls if available (set by onJobAssigned), fall back to externalId
140
+ const apiJobId = job.jobId || job.externalId;
141
+ logger.info(`Starting job execution: ${job.externalId} (apiId: ${apiJobId})`);
142
+ // Atomic capacity check: reserve slot immediately to prevent TOCTOU race
143
+ if (this.activeJobs.size >= this.config.maxConcurrentJobs) {
144
+ throw new Error(`Agent is at maximum capacity (${this.config.maxConcurrentJobs} jobs)`);
145
+ }
146
+ this.activeJobs.set(job.externalId, { startTime, job });
147
+ try {
148
+ // Update agent status to busy if this is our first job
149
+ if (this.activeJobs.size === 1) {
150
+ await this.websocketClient.updateStatus('BUSY');
151
+ }
152
+ // Mark job as RUNNING via REST API with retry (MVP.4.2.2 + MVP.4.3.2)
153
+ await this.recoveryManager.retryOperation(() => this.jobStatusApi.markJobRunning(apiJobId), {}, `mark job ${apiJobId} as RUNNING`);
154
+ logger.info(`Job ${job.externalId} marked as RUNNING (apiId: ${apiJobId})`);
155
+ // Progress and log callbacks for REST API streaming
156
+ const progressCallback = (progress) => {
157
+ this.recoveryManager.retryOperation(() => this.jobStatusApi.updateJobProgress(apiJobId, progress), { maxAttempts: 2 }, `progress update for ${apiJobId}`).catch(error => {
158
+ logger.error('Failed to send progress update after retries', error);
159
+ });
160
+ };
161
+ const logsCallback = (logs) => {
162
+ this.recoveryManager.retryOperation(() => this.jobStatusApi.appendJobLogs(apiJobId, logs), { maxAttempts: 2 }, `log update for ${apiJobId}`).catch(error => {
163
+ logger.error('Failed to send log update after retries', error);
164
+ });
165
+ };
166
+ let result;
167
+ // Enforce job-level timeout (agent kills the job if it exceeds the limit)
168
+ const timeoutMs = (this.config.jobTimeoutMinutes || 60) * 60 * 1000;
169
+ const jobEntry = this.activeJobs.get(job.externalId);
170
+ const executionPromise = this.jobExecutor.executeJob(job, progressCallback, logsCallback);
171
+ const timeoutPromise = new Promise((_, reject) => {
172
+ const tid = setTimeout(() => {
173
+ logger.warn(`Job ${job.externalId} exceeded timeout of ${this.config.jobTimeoutMinutes}min — killing`);
174
+ this.jobExecutor.cancelJob(job.externalId).catch(() => { });
175
+ reject(new Error(`Job timed out after ${this.config.jobTimeoutMinutes} minutes`));
176
+ }, timeoutMs);
177
+ // Store timeout ID so we can clear it on completion
178
+ if (jobEntry)
179
+ jobEntry.timeoutId = tid;
180
+ });
181
+ try {
182
+ // Use base Docker executor (enhanced executor disabled — it selects Docker
183
+ // but lifecycleExecutor spawns shell directly, bypassing Docker entirely)
184
+ // TODO: Fix enhancedJobExecutor to wire up Docker executor properly
185
+ result = await Promise.race([executionPromise, timeoutPromise]);
186
+ }
187
+ finally {
188
+ // Clear the timeout timer on completion (success or failure)
189
+ if (jobEntry?.timeoutId)
190
+ clearTimeout(jobEntry.timeoutId);
191
+ }
192
+ const completedAt = new Date();
193
+ const actualDuration = Math.floor((completedAt.getTime() - startTime.getTime()) / 1000);
194
+ const jobResult = {
195
+ jobId: apiJobId,
196
+ status: result.success ? 'COMPLETED' : 'FAILED',
197
+ exitCode: result.exitCode,
198
+ logs: result.logs,
199
+ errorMessage: result.errorMessage,
200
+ artifactUrls: result.artifactUrls,
201
+ actualDuration,
202
+ startedAt: startTime,
203
+ completedAt
204
+ };
205
+ // Report job completion via REST API with retry (MVP.4.2.2 + MVP.4.3.2)
206
+ await this.recoveryManager.retryOperation(() => this.jobStatusApi.markJobCompleted(apiJobId, {
207
+ exitCode: result.exitCode || (result.success ? 0 : 1),
208
+ logs: result.logs || this.jobStatusApi.getCurrentLogs(apiJobId),
209
+ artifactUrls: result.artifactUrls,
210
+ actualDuration,
211
+ errorMessage: result.errorMessage
212
+ }), {}, `mark job ${job.externalId} as COMPLETED`);
213
+ logger.info(`Job completed: ${job.externalId} (${jobResult.status})`);
214
+ return jobResult;
215
+ }
216
+ catch (error) {
217
+ logger.error(`Job execution failed: ${job.externalId}`, error);
218
+ const completedAt = new Date();
219
+ const actualDuration = Math.floor((completedAt.getTime() - startTime.getTime()) / 1000);
220
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
221
+ // Report job failure via REST API with retry (MVP.4.2.2 + MVP.4.3.2)
222
+ try {
223
+ await this.recoveryManager.retryOperation(() => this.jobStatusApi.markJobFailed(apiJobId, errorMessage, this.jobStatusApi.getCurrentLogs(apiJobId)), {}, `mark job ${job.externalId} as FAILED`);
224
+ }
225
+ catch (apiError) {
226
+ logger.error('Failed to report job failure to server after retries', apiError);
227
+ }
228
+ return {
229
+ jobId: job.externalId,
230
+ status: 'FAILED',
231
+ errorMessage,
232
+ actualDuration,
233
+ startedAt: startTime,
234
+ completedAt
235
+ };
236
+ }
237
+ finally {
238
+ // Remove from active jobs
239
+ this.activeJobs.delete(job.externalId);
240
+ // Update status back to online if no more jobs
241
+ if (this.activeJobs.size === 0) {
242
+ await this.websocketClient.updateStatus('ONLINE');
243
+ }
244
+ }
245
+ }
246
+ /**
247
+ * Get current agent status
248
+ */
249
+ getStatus() {
250
+ return {
251
+ isRunning: this.isRunning,
252
+ activeJobs: this.activeJobs.size,
253
+ capabilities: this.capabilities,
254
+ uptime: this.isRunning ? Date.now() - this.startTime : 0
255
+ };
256
+ }
257
+ startTime = Date.now();
258
+ /**
259
+ * Initialize the EnhancedJobExecutor from config.
260
+ * Returns null if enhanced config sections are missing (backward compat).
261
+ */
262
+ initEnhancedExecutor(config) {
263
+ if (!config.acceptanceRules || !config.resourceGovernance || !config.cacheConfig) {
264
+ logger.info('Enhanced executor not initialized: missing config sections, using basic executor');
265
+ return null;
266
+ }
267
+ const recipeRegistry = new RecipeRegistry();
268
+ const cacheManager = new CacheManager({
269
+ directory: config.cacheConfig.directory,
270
+ maxSizeGB: config.cacheConfig.maxSizeGB,
271
+ strategy: config.cacheConfig.strategy,
272
+ volumes: config.cacheConfig.volumes,
273
+ });
274
+ const acceptanceChecker = new AcceptanceChecker(config.acceptanceRules);
275
+ const resourceGovernor = new ResourceGovernor(config.resourceGovernance, config.maxConcurrentJobs);
276
+ const executorConfig = {
277
+ executionMode: config.executionConfig?.defaultMode ?? 'docker',
278
+ dockerAvailable: true,
279
+ };
280
+ const snapshotProvider = () => ({
281
+ cpuPercent: 10,
282
+ memoryPercent: 30,
283
+ diskFreeGB: 50,
284
+ activeJobs: this.activeJobs.size,
285
+ });
286
+ logger.info('Enhanced job executor initialized with recipe detection and caching');
287
+ return new EnhancedJobExecutor(recipeRegistry, cacheManager, acceptanceChecker, resourceGovernor, executorConfig, snapshotProvider);
288
+ }
289
+ /**
290
+ * Convert a JobSubmissionRequest to an EnhancedJobRequest
291
+ */
292
+ toEnhancedRequest(job, workDir) {
293
+ return {
294
+ id: job.externalId,
295
+ repository: job.repository,
296
+ buildCommand: job.buildCommand,
297
+ dockerImage: job.dockerImage,
298
+ environment: job.environment,
299
+ workDir,
300
+ artifacts: job.artifacts,
301
+ };
302
+ }
303
+ /**
304
+ * Set up event handlers for WebSocket client
305
+ */
306
+ setupEventHandlers() {
307
+ // Handle job assignments
308
+ // Server sends nested structure: { jobId, agentId, job: { externalId, ... }, assignedAt }
309
+ // We unwrap to get the actual job data and the database jobId for status reporting
310
+ this.websocketClient.onJobAssigned(async (jobData) => {
311
+ // Server sends nested structure: { jobId, agentId, job: { externalId, ... } }
312
+ const rawData = jobData;
313
+ const job = rawData.job || rawData;
314
+ const dbJobId = rawData.jobId || job.id;
315
+ const externalId = job.externalId || dbJobId;
316
+ logger.info(`Received job assignment: ${externalId} (dbId: ${dbJobId})`);
317
+ try {
318
+ const result = await this.executeJob({
319
+ ...job,
320
+ jobId: dbJobId,
321
+ });
322
+ // Send job completion notification
323
+ await this.websocketClient.sendJobResult({
324
+ ...result,
325
+ jobId: dbJobId,
326
+ });
327
+ }
328
+ catch (error) {
329
+ logger.error(`Failed to execute assigned job: ${externalId}`, error);
330
+ // Send job failure notification
331
+ await this.websocketClient.sendJobResult({
332
+ jobId: dbJobId,
333
+ status: 'FAILED',
334
+ errorMessage: error instanceof Error ? error.message : 'Unknown error',
335
+ startedAt: new Date(),
336
+ completedAt: new Date()
337
+ });
338
+ }
339
+ });
340
+ // Handle connection status changes
341
+ this.websocketClient.onConnectionChange((connected) => {
342
+ if (connected) {
343
+ logger.info('Connected to BuildHive platform');
344
+ }
345
+ else {
346
+ logger.warn('Disconnected from BuildHive platform');
347
+ }
348
+ });
349
+ // Handle reconnection
350
+ this.websocketClient.onReconnected(() => {
351
+ logger.info('Reconnected to BuildHive platform');
352
+ // Re-register agent capabilities
353
+ this.websocketClient.registerAgent();
354
+ });
355
+ }
356
+ /**
357
+ * Start heartbeat mechanism
358
+ */
359
+ consecutiveHeartbeatFailures = 0;
360
+ static MAX_HEARTBEAT_FAILURES = 5;
361
+ startHeartbeat() {
362
+ this.heartbeatInterval = setInterval(async () => {
363
+ try {
364
+ const metrics = await this.metricsCollector.getCurrentMetrics();
365
+ await this.websocketClient.sendHeartbeat({
366
+ currentLoad: this.calculateCurrentLoad(),
367
+ activeJobs: this.activeJobs.size,
368
+ metrics: {
369
+ cpuUsage: metrics.cpuUsage,
370
+ memoryUsage: metrics.memoryUsage,
371
+ diskUsage: metrics.diskUsage
372
+ }
373
+ });
374
+ this.consecutiveHeartbeatFailures = 0;
375
+ }
376
+ catch (error) {
377
+ this.consecutiveHeartbeatFailures++;
378
+ logger.error(`Heartbeat failed (${this.consecutiveHeartbeatFailures}/${BuildHiveAgent.MAX_HEARTBEAT_FAILURES}):`, error);
379
+ if (this.consecutiveHeartbeatFailures >= BuildHiveAgent.MAX_HEARTBEAT_FAILURES) {
380
+ logger.warn('Too many consecutive heartbeat failures — forcing WebSocket reconnect');
381
+ this.consecutiveHeartbeatFailures = 0;
382
+ try {
383
+ await this.websocketClient.disconnect();
384
+ await this.websocketClient.connect();
385
+ }
386
+ catch (reconnectError) {
387
+ logger.error('Heartbeat-triggered reconnect failed:', reconnectError);
388
+ }
389
+ }
390
+ }
391
+ }, this.config.heartbeatInterval * 1000);
392
+ }
393
+ /**
394
+ * Start metrics reporting
395
+ */
396
+ startMetricsReporting() {
397
+ if (!this.config.enableMetrics) {
398
+ return;
399
+ }
400
+ this.metricsInterval = setInterval(async () => {
401
+ try {
402
+ const metrics = await this.metricsCollector.getCurrentMetrics();
403
+ await this.websocketClient.sendMetrics(metrics);
404
+ }
405
+ catch (error) {
406
+ logger.error('Failed to send metrics:', error);
407
+ }
408
+ }, 60000); // Send metrics every minute
409
+ }
410
+ /**
411
+ * Start Docker health monitoring (MVP.4.3.2)
412
+ *
413
+ * Continuously monitors Docker daemon health and attempts recovery on failure
414
+ */
415
+ startDockerHealthMonitoring() {
416
+ // Initial health check
417
+ this.recoveryManager.checkDockerHealth().then(isHealthy => {
418
+ if (!isHealthy) {
419
+ logger.warn('Initial Docker health check failed, attempting recovery');
420
+ this.recoveryManager.recoverDockerConnection();
421
+ }
422
+ });
423
+ // Start continuous monitoring
424
+ this.dockerHealthMonitor = this.recoveryManager.startDockerHealthMonitoring(60000, // Check every minute
425
+ () => {
426
+ // Callback when Docker becomes unhealthy and recovery fails
427
+ logger.error('Docker daemon is unhealthy and recovery failed');
428
+ logger.error('Agent may not be able to execute new jobs until Docker is restored');
429
+ // Update agent status to reflect Docker issue
430
+ this.websocketClient.updateStatus('OFFLINE').catch(err => {
431
+ logger.error('Failed to update agent status:', err);
432
+ });
433
+ });
434
+ logger.debug('Docker health monitoring interval started');
435
+ }
436
+ /**
437
+ * Calculate current load based on active jobs and system metrics
438
+ */
439
+ calculateCurrentLoad() {
440
+ const jobLoad = this.activeJobs.size / this.config.maxConcurrentJobs;
441
+ return Math.min(jobLoad * 100, 100);
442
+ }
443
+ /**
444
+ * Clean up resources
445
+ */
446
+ async cleanup() {
447
+ // Stop intervals
448
+ if (this.heartbeatInterval) {
449
+ clearInterval(this.heartbeatInterval);
450
+ this.heartbeatInterval = null;
451
+ }
452
+ if (this.metricsInterval) {
453
+ clearInterval(this.metricsInterval);
454
+ this.metricsInterval = null;
455
+ }
456
+ if (this.dockerHealthMonitor) {
457
+ clearInterval(this.dockerHealthMonitor);
458
+ this.dockerHealthMonitor = null;
459
+ }
460
+ // Disconnect WebSocket
461
+ try {
462
+ await this.websocketClient.disconnect();
463
+ }
464
+ catch (error) {
465
+ logger.error('Error disconnecting WebSocket:', error);
466
+ }
467
+ // Stop metrics collector
468
+ try {
469
+ await this.metricsCollector.stop();
470
+ }
471
+ catch (error) {
472
+ logger.error('Error stopping metrics collector:', error);
473
+ }
474
+ // Clean up job executor
475
+ try {
476
+ await this.jobExecutor.cleanup();
477
+ }
478
+ catch (error) {
479
+ logger.error('Error cleaning up job executor:', error);
480
+ }
481
+ // Clean up job status API
482
+ try {
483
+ this.jobStatusApi.cleanup();
484
+ }
485
+ catch (error) {
486
+ logger.error('Error cleaning up job status API:', error);
487
+ }
488
+ }
489
+ }
490
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}