tests — config
tests — config
The config module is central to how the application manages its operational parameters, user preferences, and external service connections. It provides a robust system for loading, resolving, validating, and dynamically updating configuration from various sources, including environment variables, user-defined profiles, project-specific rules, and CLI arguments.
This documentation describes the core components within the src/config directory, whose functionality is thoroughly tested by the tests/config module.
Core Configuration Principles
The config module adheres to several key principles:
- Layered Resolution: Configuration values are resolved from multiple sources, with a clear priority hierarchy.
- Validation: Environment variables and user settings are validated against defined schemas to ensure correctness and provide helpful feedback.
- Profile Management: Users can define and switch between different connection profiles for various LLM providers.
- Project-Specific Rules: Project-level
.codebuddyrulesfiles allow developers to define coding standards, security policies, and custom prompts. - Hot Reloading: Critical configuration changes can be detected and applied dynamically without requiring a full application restart.
- Model Abstraction: A registry and resolution logic abstract away the complexities of different LLM providers and their models, including pricing and capabilities.
Key Components
1. ConfigResolver (src/config/config-resolver.js)
The ConfigResolver is the primary mechanism for resolving connection-related configuration, such as API keys, base URLs, and default models. It implements a strict priority order to determine the effective configuration.
Purpose: To provide a single, consistent source for connection parameters, respecting user preferences and system defaults.
Key Features:
- Priority Resolution: Resolves configuration values in the following order (highest to lowest):
- CLI Arguments: Explicit values passed via command-line.
- Active Profile: Settings from the currently selected connection profile.
- Environment Variables: System-wide environment variables (e.g.,
GROK_API_KEY). - Built-in Defaults: Hardcoded fallback values.
- Profile Management:
getProfiles(): Retrieves all available connection profiles (built-in and user-defined).getActiveProfileId(),getActiveProfile(): Accesses the currently active profile.setActiveProfile(id): Switches the active profile.addProfile(profile),updateProfile(id, updates),removeProfile(id): Manages user-defined profiles.- Provider Detection:
detectProviderFromSettings()(used internally) infers the LLM provider based on thebaseURLor explicitprovidersetting. - Singleton Access:
getConfigResolver()provides a singleton instance, ensuring consistent configuration across the application.initConfigResolver()allows initial setup with custom config, andresetConfigResolver()for testing or re-initialization. - Events: Emits
profile-changedandprofile-addedevents, allowing other parts of the application to react to configuration updates.
Configuration Priority Flow:
graph TD
A[CLI Arguments] --> B(Highest Priority)
B --> C[Active Connection Profile]
C --> D[Environment Variables]
D --> E[Built-in Defaults]
E --> F(Lowest Priority)
2. EnvSchema (src/config/env-schema.js)
This module defines the schema for all recognized environment variables and provides utilities for their validation and summarization.
Purpose: To ensure environment variables are correctly formatted, provide defaults, and offer a clear overview of the current environment configuration.
Key Features:
ENV_SCHEMA: An array ofEnvVarDefobjects, each defining an environment variable's name, type, description, category, default value, validation rules (min/max, pattern), and sensitivity.validateEnv(env): Checks a given environment object againstENV_SCHEMA, returning aValidationResultwithvalidstatus,errors(for critical issues like missing required vars), andwarnings(for non-critical issues like invalid types or out-of-range values).getEnvSummary(env): Generates a human-readable, formatted string summarizing all environment variables, their values (masked for sensitive ones), defaults, and any validation issues.maskValue(value): Utility to mask sensitive string values (e.g., API keys) for display, showing only the first and last few characters.getEnvDef(name): Retrieves the schema definition for a specific environment variable.
3. CodeBuddyRulesManager (src/config/codebuddyrules.js)
The CodeBuddyRulesManager handles project-specific configuration defined in .codebuddyrules (YAML or JSON) files. These rules influence the agent's behavior, coding style, and security policies within a project.
Purpose: To allow developers to define project-specific guidelines and constraints for the AI agent.
Key Features:
- Rule Loading: Automatically discovers and loads
.codebuddyrulesfiles from the current directory and optionally from parent directories (inheritFromParent). - Rule Merging: Merges rules from multiple files, with child directory rules overriding parent rules.
- System Prompt Generation:
getSystemPromptAdditions()compiles relevant rules (description, languages, instructions, style, persona) into a natural language string to augment the AI's system prompt. - Security Policies:
isCommandAllowed(command): Checks if a command is permitted based onsecurity.allowedCommandsandsecurity.blockedCommands.isPathAllowed(path): Verifies if a file path is accessible, respectingsecurity.blockedPaths.- File Filtering:
getIgnorePatterns()andgetIncludePatterns()provide glob patterns for file filtering, useful for context management. - Custom Prompts:
getCustomPrompt(key)retrieves predefined custom prompts from the rules file. - Default Rules:
createDefaultRules(path)can generate a boilerplate.codebuddyrulesfile. - Singleton Access:
getCodeBuddyRulesManager()provides a singleton instance.initializeCodeBuddyRules(cwd)initializes it for a given working directory. - Events: Emits
initializedandrules:loadedevents.
4. HotReloadManager (src/config/hot-reload/index.js)
This module provides the infrastructure for detecting changes in configuration files and dynamically reloading affected application subsystems.
Purpose: To enable seamless updates to configuration without requiring a full application restart, improving developer experience and operational flexibility.
Key Features:
ConfigWatcher: Monitors specified file paths for changes, debouncing events to prevent excessive reloads.diffConfigs(oldSnap, newSnap): Compares two configuration snapshots and identifies specific changes (added, removed, or modified keys).getSubsystemForPath(path): Maps a configuration key path (e.g.,model,tools,policies) to a logicalSubsystemId.registerReloader(subsystem, handler): Allows different parts of the application to register aReloaderfunction for specific subsystems.reloadSubsystems(changes, options): Orchestrates the reload process:
- Identifies affected subsystems based on
changes. - Sorts subsystems by a predefined priority (
getReloadOrder) to ensure dependencies are reloaded correctly (e.g., security before models). - Executes the registered
Reloaderfor each affected subsystem. - Handles reload success/failure, with optional rollback.
createNoOpReloader(subsystem): A utility to create a reloader that simply logs the change without performing any action.createSimpleReloader(subsystem, handler): A utility to create a reloader that applies a new value to a specific part of the system.HotReloadManager: The main class that integrates the watcher, diffing, and reloading logic. It can be started and stopped, and allows adding/removing watched paths.
5. Migration Utilities (src/config/migration.js)
This module provides functions for migrating legacy user settings to the new profile-based ConnectionConfig structure, as well as utilities for managing profiles.
Purpose: To ensure backward compatibility with older configuration formats and provide tools for profile import/export.
Key Features:
needsMigration(settings): Determines if a givenLegacyUserSettingsobject requires migration.migrateSettings(legacySettings): Converts legacy settings into the modernConnectionConfigformat, creating a "migrated" profile if custom settings were present.createProfileFromLegacy(legacy, name): Helper to construct aConnectionProfilefrom legacy settings.detectProviderFromSettings(settings): Infers the LLM provider frombaseURLor explicitproviderin settings.mergeWithDefaults(config): Ensures that built-in default profiles are present in aConnectionConfig, adding them if missing and not duplicating existing ones.validateConnectionConfig(config): Cleans up and validates aConnectionConfig, ensuringprofilesis an array,activeProfileIdis valid, and default fields likeenabledandcreatedAtare set.- Profile Management Utilities:
cloneProfile(original, newId, newName): Creates a copy of an existing profile with a new ID and name.createCustomProfile(id, name, baseURL, apiKey): Creates a new custom profile, automatically detecting the provider.- Import/Export:
exportProfiles(profiles): Serializes a list of profiles to JSON, redacting sensitiveapiKeyvalues.importProfiles(json): Deserializes profiles from JSON, clearing redactedapiKeyfields.
6. Model Configuration
This group of modules provides a comprehensive system for managing LLM models, their capabilities, pricing, and resolution logic.
6.1. ModelRegistry (src/config/model-registry.js)
The ModelRegistry acts as a central repository for all known LLM models, their metadata, and pricing information.
Purpose: To provide a unified interface for querying model capabilities, pricing, and resolving aliases.
Key Features:
- Model Metadata: Stores information like
maxInputTokens,maxOutputTokens,supportsVision,supportsFunctionCallingfor various models. - Pricing Lookup:
getPricing(modelName)retrieves input and output token costs for a given model. It can derive pricing from built-in data or frominput_cost_per_token/output_cost_per_tokenfields in the model snapshot. - Alias Resolution:
resolveAlias(alias)converts common aliases (e.g., "sonnet", "gpt4") into their full model names. Supports environment variable overrides for aliases (e.g.,CODEBUDDY_ALIAS_SONNET). - Model Listing:
listModels(options)returns a list of available models, optionally filtered by provider. - Singleton Access:
getModelRegistry()provides a singleton instance.resetModelRegistry()is available for testing.
6.2. ModelDefaults (src/config/model-defaults.js)
This module defines default models for various providers and fallback options.
Purpose: To establish sensible default models for different LLM providers and a universal fallback.
Key Features:
MODEL_DEFAULTS: A map linkingProviderKey(e.g., 'xai', 'openai') to their default model names.FALLBACK_MODEL: The ultimate fallback model if no other model can be resolved (currentlygrok-code-fast-1).FALLBACK_PROVIDER: The provider associated with theFALLBACK_MODEL(currently 'xai').getProviderDefaultModel(provider): Returns the default model for a given provider, respecting provider-specific environment variables (e.g.,GROK_MODEL,OPENAI_MODEL).GEMINI_FALLBACK_CHAIN: A prioritized list of Gemini models for fallback scenarios.MODEL_ROLES: Defines models suitable for specific use cases (e.g.,fast,reasoning,architect).
6.3. ModelPricing (src/config/model-pricing.js)
Provides utility functions for retrieving model pricing in various formats.
Purpose: To offer convenient access to model pricing data, adapting it to different units (per 1K, per 1M tokens).
Key Features:
getModelPricing(modelName): Retrieves raw pricing (input/output per million tokens) from theModelRegistry.getPricingPer1k(modelName): Returns pricing converted to per 1,000 tokens.getPricingPer1M(modelName): Returns pricing as input/output per 1,000,000 tokens.getPricingForIndicator(modelName): Returns pricing in a specific format suitable for cost indicators, including the model name.
6.4. ResolveModel (src/config/resolve-model.js)
This module contains the core logic for determining the final model and its provider based on various inputs.
Purpose: To abstract the complexity of model selection, ensuring the correct model and provider are identified based on a priority hierarchy.
Key Features:
inferProvider(modelName): Attempts to determine the LLM provider based on common prefixes in themodelName(e.g., "gpt-" -> "openai", "claude-" -> "anthropic").resolveModel(options): The main resolution function. It takes an object of potential model sources (explicitModel,savedModel,providerhint) and applies the following priority:
explicitModel: A model explicitly requested (e.g., via CLI).savedModel: A model stored in user settings or an active profile.- Environment Variable: The provider's default model as overridden by an environment variable.
- Provider Default: The static default model for the specified
provider. FALLBACK_MODEL: The universal fallback model.
- Source Tagging: The returned
ResolvedModelobject includes asourcefield (e.g., 'explicit', 'saved', 'env', 'provider-default', 'fallback') indicating where the model was resolved from.
7. AgentDefaults (src/config/agent-defaults.js)
A simple module providing specific default values for agent-related configurations, currently focused on image generation.
Purpose: To centralize default settings for agent capabilities that might be configured via toml-config.js.
Key Features:
getImageGenerationModel(): Retrieves the default image generation model from the application's TOML configuration, returningundefinedif not configured or an error occurs.
Integration and Usage
These configuration modules work in concert to provide a robust and flexible configuration system:
- The
ConfigResolveris typically initialized early in the application lifecycle to establish the active connection profile. EnvSchemais used to validateprocess.envat startup and to generate diagnostic summaries.CodeBuddyRulesManageris initialized with the current working directory to load project-specific rules, which then inform the AI's behavior and security checks.- The
ModelRegistryandModelDefaultsprovide the foundational data forresolveModel, which is called whenever an LLM interaction needs to determine the specific model to use. - The
HotReloadManagercontinuously monitors configuration files, and upon detecting changes, uses thediffConfigsandreloadSubsystemsmechanisms to update relevant parts of the application dynamically. Migration Utilitiesare invoked once at startup if legacy settings are detected, ensuring a smooth transition to the new profile system.
By separating concerns into these distinct modules, the configuration system remains modular, testable, and adaptable to evolving requirements.