src — doctor

Module: src-doctor Cohesion: 0.80 Members: 0

src — doctor

The src/doctor module is the diagnostic and self-healing component of the application. Its primary purpose is to inspect the current environment, system dependencies, and application configuration to identify potential issues that might hinder functionality. It provides a structured way to report these issues and, for many of them, offers automated fixes.

This module is crucial for ensuring a smooth user experience by proactively identifying and resolving common setup problems, making the application more robust and user-friendly.

Core Concepts

The module operates around two key interfaces:

DoctorCheck

Represents the result of a single diagnostic check.

export interface DoctorCheck {
  name: string;      class="hl-cmt">// A human-readable name for the check (e.g., "Node.js version")
  status: 'ok' | 'warn' | 'error'; class="hl-cmt">// The severity of the check result
  message: string;   class="hl-cmt">// A detailed message explaining the status
  fixable?: boolean; class="hl-cmt">// True if an automated fix is available
  fix?: () => Promise<FixResult>; class="hl-cmt">// An optional async function to apply the fix
}

FixResult

Represents the outcome of an attempted fix operation.

export interface FixResult {
  success: boolean; class="hl-cmt">// True if the fix was applied successfully
  message: string;  class="hl-cmt">// A message describing the outcome of the fix
  action: string;   class="hl-cmt">// A short identifier for the action performed (e.g., "create-codebuddy-dir")
}

How it Works: The Doctor Process

The diagnostic process involves two main stages, exposed through the module's public API:

  1. Running Checks: The runDoctorChecks function orchestrates all individual diagnostic checks. It gathers their results into an array of DoctorCheck objects.
  2. Applying Fixes: The runFixes function takes an array of DoctorCheck results (typically from runDoctorChecks) and iterates through them. For any check marked as fixable with an associated fix function, it attempts to execute that fix.
graph TD
    A[CLI Command] --> B{runDoctorChecks(cwd)}
    B --> C(checkNodeVersion)
    B --> D(checkDependencies)
    B --> E(checkApiKeys)
    B --> F(checkConfigFiles)
    B --> G(checkStaleLockFiles)
    B --> H(checkTtsProviders)
    B --> I(checkDiskSpace)
    B --> J(checkGit)
    B -- Returns DoctorCheck[] --> K{Display Checks to User}
    K -- User chooses to fix --> L{runFixes(DoctorCheck[])}
    L --> M{For each fixable check}
    M --> N(Call check.fix())
    N -- Returns FixResult --> O{Display Fix Results}

Key Checks Explained

The module performs a comprehensive set of checks, categorized below:

System Environment Checks

These functions verify the presence and version of external tools and system resources.

Helper:

Configuration Checks

These functions validate the application's internal configuration and directory structure.

Helpers:

Runtime State Checks

These functions look for artifacts from previous runs that might indicate an issue.

Helper:

Fixing Issues

For many identified problems, the doctor module provides automated fix functions. These functions are designed to be idempotent where possible and log their actions using the logger.

Module Architecture and Dependencies

The src/doctor/index.ts module is a self-contained unit for diagnostics and fixes.

Usage

Developers can integrate the doctor module into various parts of the application, typically for pre-flight checks or maintenance tasks.

import { runDoctorChecks, runFixes, DoctorCheck, FixResult } from &#39;./src/doctor/index.js&#39;;

async function performDiagnosticsAndFixes() {
  console.log(&#39;Running diagnostic checks...&#39;);
  const checks: DoctorCheck[] = await runDoctorChecks();

  console.log(&#39;\n--- Doctor Report ---&#39;);
  checks.forEach(check => {
    console.log(`[${check.status.toUpperCase()}] ${check.name}: ${check.message}`);
  });

  const fixableChecks = checks.filter(check => check.fixable && check.status !== &#39;ok&#39;);

  if (fixableChecks.length > 0) {
    console.log(`\nFound ${fixableChecks.length} fixable issues. Attempting to fix...`);
    const fixResults: FixResult[] = await runFixes(fixableChecks);

    console.log(&#39;\n--- Fix Results ---&#39;);
    fixResults.forEach(result => {
      console.log(`[${result.success ? &#39;SUCCESS&#39; : &#39;FAILURE&#39;}] ${result.action}: ${result.message}`);
    });
  } else {
    console.log(&#39;\nNo fixable issues found.&#39;);
  }
}

performDiagnosticsAndFixes();

Contributing

To add a new diagnostic check or fix:

  1. Implement a check* function:

  1. Implement a fix* function (if applicable):

  1. Integrate into runDoctorChecks:

  1. Test: Write unit tests to cover both the diagnostic check and the fix logic, ensuring it correctly identifies issues and applies fixes as expected.