All files / agent/src/registration index.ts

0% Statements 0/145
0% Branches 0/1
0% Functions 0/1
0% Lines 0/145

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146                                                                                                                                                                                                                                                                                                   
/**
 * Agent Registration Module
 *
 * Orchestrates the agent registration process including machine ID generation,
 * capability detection, API registration, and configuration persistence.
 *
 * Requirements: MVP.4.1.2
 */

import { AgentConfig, DEFAULT_CONFIG } from '../config/types.js';
import { MachineIdManager } from './machineId.js';
import { BuildHiveApiClient } from './apiClient.js';
import { detectCapabilities } from '../utils/capabilities.js';
import { scanInstalledSDKs, generateTagsFromSDKs } from '../utils/sdkScanner.js';
import { saveConfig } from '../config/index.js';
import { createLogger } from '../utils/logger.js';
import { join } from 'path';
import os from 'os';

const logger = createLogger('registration');

export interface RegistrationOptions {
  platformUrl: string;
  name?: string;
  tags?: string[];
  maxConcurrentJobs?: number;
  configPath?: string;
}

export class AgentRegistration {
  private machineIdManager: MachineIdManager;
  private apiClient: BuildHiveApiClient;

  constructor(platformUrl: string) {
    this.machineIdManager = new MachineIdManager();
    this.apiClient = new BuildHiveApiClient(platformUrl);
  }

  /**
   * Register agent with the BuildHive platform
   */
  async registerAgent(options: RegistrationOptions): Promise<AgentConfig> {
    logger.info('Starting agent registration process');

    // Test connection to platform
    logger.info(`Testing connection to ${options.platformUrl}`);
    const connected = await this.apiClient.testConnection();
    if (!connected) {
      throw new Error(
        `Cannot connect to BuildHive platform at ${options.platformUrl}. Please check the URL and your network connection.`
      );
    }

    // Get or generate machine ID
    const machineId = await this.machineIdManager.getMachineId();
    logger.info(`Machine ID: ${machineId}`);

    // Detect system capabilities
    logger.info('Detecting system capabilities...');
    const capabilities = await detectCapabilities();
    logger.info('Detected system capabilities:', capabilities);

    // Scan installed SDKs and generate capability tags
    logger.info('Scanning installed SDKs...');
    const sdkCapabilities = await scanInstalledSDKs();
    const sdkTags = generateTagsFromSDKs(sdkCapabilities);
    logger.info(`SDK scan generated ${sdkTags.length} tags: ${sdkTags.join(', ')}`);

    // Merge user-provided tags with SDK-detected tags (user tags take precedence)
    const userTags = options.tags || [];
    const mergedTags = [...new Set([...userTags, ...sdkTags])];
    logger.info(`Merged tags (${mergedTags.length}): ${mergedTags.join(', ')}`);

    // Generate agent name if not provided
    const agentName =
      options.name ||
      `buildhive-agent-${os.hostname()}-${machineId.substring(0, 8)}`;

    // Register with platform
    logger.info(`Registering agent "${agentName}" with platform...`);
    const response = await this.apiClient.register({
      name: agentName,
      machineId,
      version: '1.0.0', // Agent version
      capabilities,
      tags: mergedTags,
      maxConcurrentJobs: options.maxConcurrentJobs || 1,
      sdkCapabilities,
    });

    logger.info(`Agent registered successfully with ID: ${response.agentId}`);

    // Create full config with registration data and defaults
    const fullConfig: AgentConfig = {
      ...DEFAULT_CONFIG,
      platformUrl: options.platformUrl,
      agentId: response.agentId,
      apiKey: response.apiKey,
      name: agentName,
      tags: mergedTags,
      maxConcurrentJobs: options.maxConcurrentJobs || 1,
    } as AgentConfig;

    // Determine config file path
    const configPath =
      options.configPath ||
      join(os.homedir(), '.buildhive', 'buildhive-agent.json');

    // Save config to file
    await saveConfig(fullConfig, configPath);
    logger.info(`Configuration saved to ${configPath}`);

    logger.info('Agent registration completed successfully');

    return fullConfig;
  }

  /**
   * Check if agent is already registered
   */
  async isRegistered(): Promise<boolean> {
    return await this.machineIdManager.exists();
  }

  /**
   * Re-register agent (clears existing registration)
   */
  async reRegister(options: RegistrationOptions): Promise<AgentConfig> {
    logger.warn('Re-registering agent - clearing existing machine ID');
    await this.machineIdManager.clear();
    return await this.registerAgent(options);
  }

  /**
   * Get machine ID without registering
   */
  async getMachineId(): Promise<string> {
    return await this.machineIdManager.getMachineId();
  }
}

// Export convenience functions
export { MachineIdManager } from './machineId.js';
export { BuildHiveApiClient } from './apiClient.js';
export * from './types.js';