All files / src/cli/setup discovery.ts

100% Statements 34/34
94.44% Branches 17/18
100% Functions 8/8
100% Lines 30/30

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          2x     2x 2x             6x   6x                           2x   6x 6x 6x 6x     6x     6x   6x                                       2x 5x   5x 1x   2x 2x     1x   4x     5x 1x     5x 3x 3x 1x 1x   2x       5x    
/**
 * Unified environment detection for the setup wizard.
 * Discovers installed MCP clients, Docker environment, and existing configurations.
 */
 
import { detectAllClients } from "../install/detector";
import { DiscoveryResult } from "./types";
import { DockerStatusResult } from "../docker/types";
import { getContainerRuntime } from "../docker/container-runtime";
import { getContainerInfo } from "../docker/docker-utils";
 
/**
 * Detect container runtime environment status.
 * Uses the shared container-runtime module for Docker/Podman detection.
 */
function detectDocker(): DockerStatusResult {
  const runtime = getContainerRuntime();
 
  return {
    dockerInstalled: runtime.runtimeVersion !== undefined,
    dockerRunning: runtime.runtimeAvailable,
    composeInstalled: runtime.composeCmd !== null,
    container: runtime.runtimeAvailable ? getContainerInfo() : undefined,
    instances: [],
    runtime,
  };
}
 
/**
 * Run full environment discovery.
 * Detects installed MCP clients, Docker status, and existing configurations.
 */
export function runDiscovery(): DiscoveryResult {
  // Detect MCP clients
  const allClients = detectAllClients();
  const detected = allClients.filter(r => r.detected);
  const configured = allClients.filter(r => r.alreadyConfigured);
  const unconfigured = detected.filter(r => !r.alreadyConfigured);
 
  // Detect Docker environment
  const docker = detectDocker();
 
  // Build summary
  const hasExistingSetup = configured.length > 0 || docker.container !== undefined;
 
  return {
    clients: {
      detected,
      configured,
      unconfigured,
    },
    docker,
    summary: {
      hasExistingSetup,
      clientCount: detected.length,
      configuredCount: configured.length,
      dockerRunning: docker.dockerRunning,
      containerExists: docker.container !== undefined,
    },
  };
}
 
/**
 * Format discovery summary for display
 */
export function formatDiscoverySummary(result: DiscoveryResult): string {
  const parts: string[] = [];
 
  if (result.summary.clientCount > 0) {
    const clientNames = result.clients.detected
      .map(c => {
        const configured = result.clients.configured.some(cc => cc.client === c.client);
        return configured ? `${c.client} ✓` : c.client;
      })
      .join(", ");
    parts.push(`Clients: ${clientNames}`);
  } else {
    parts.push("No MCP clients detected");
  }
 
  if (result.summary.configuredCount > 0) {
    parts.push(`Configured: ${result.summary.configuredCount} client(s)`);
  }
 
  if (result.docker.dockerInstalled) {
    const runtimeLabel = result.docker.runtime?.runtime === "podman" ? "Podman" : "Docker";
    if (result.docker.container) {
      const status = result.docker.container.status === "running" ? "running" : "stopped";
      parts.push(`${runtimeLabel}: container ${status}`);
    } else {
      parts.push(`${runtimeLabel}: installed, no container`);
    }
  }
 
  return parts.join(" | ");
}