src — services
src — services
The src/services module provides a collection of reusable, domain-specific functionalities that support the core operations of the agent. It abstracts away complex tasks such as codebase exploration, static code analysis, execution plan management, dynamic prompt construction, and unified file system interactions.
This module is designed to offer clear, focused APIs, allowing other parts of the codebase (e.g., agents, command handlers) to consume these capabilities without needing to understand their intricate internal workings.
Module Overview
The src/services module is structured into several distinct components:
- Code Analysis: Services for static analysis of code files and execution plans.
- Codebase Exploration: Tools for scanning and understanding project structure.
- Execution Planning: Services for creating, managing, and analyzing multi-step execution plans.
- Prompt Engineering: Components for dynamically building comprehensive system prompts for LLMs.
- Virtual File System (VFS): A unified interface for file operations, supporting physical and virtual file systems with security features.
Core Services
1. Code Analyzer (src/services/analysis/code-analyzer.ts)
The CodeAnalyzer service performs static analysis on individual code files to extract various metrics and detect potential issues. It's designed to provide a quick, high-level understanding of a file's characteristics without requiring a full AST parser.
Key Capabilities:
analyzeFileContent(filePath: string, content: string): FileAnalysis: The primary entry point, taking a file path and its content to produce aFileAnalysisobject.detectLanguage(filePath: string): string: Infers the programming language based on the file extension.extractDependencies(content: string, language: string): FileDependency[]: Identifiesimportandrequirestatements for JavaScript/TypeScript, andimportstatements for Python.extractExports(content: string, language: string): string[]: Detects named and default exports in JavaScript/TypeScript files.detectIssues(content: string, filePath: string, language: string): CodeIssue[]: Scans for:- Security Patterns: Hardcoded secrets, dangerous functions (
eval,innerHTML), and potential SQL injection patterns. - Maintainability:
TODO/FIXMEcomments,console.logstatements, andanytype usage in TypeScript. - Style: Overly long lines.
estimateComplexity(content: string): number: Provides a simple heuristic for code complexity based on control flow structures (if, for, while, switch, try/catch, ternary operators, logical operators).generateFileSummary(content: string, _language: string): string: Creates a concise summary including line count, function count, class count, and interface count.
Output:
The analysis results are encapsulated in the FileAnalysis interface, defined in src/services/analysis/types.ts.
Usage Example:
import { CodeAnalyzer } from 39;./services/analysis/code-analyzer.js39;;
const analyzer = new CodeAnalyzer();
const filePath = 39;src/my-module.ts39;;
const fileContent = `
import { someUtil } from 39;./utils39;;
const API_KEY = "sk-1234567890abcdefghijklmnopqrstuvwxyz"; class="hl-cmt">// Hardcoded secret
function doSomething(data: any) {
console.log("Processing data:", data);
if (data.length > 100) {
class="hl-cmt">// TODO: Optimize this loop
for (let i = 0; i < data.length; i++) {
class="hl-cmt">// ...
}
}
}
export default doSomething;
`;
const analysis = analyzer.analyzeFileContent(filePath, fileContent);
console.log(`Language: ${analysis.language}`); class="hl-cmt">// typescript
console.log(`Issues:`, analysis.issues);
class="hl-cmt">// [
class="hl-cmt">// { type: 39;security39;, severity: 39;critical39;, message: 39;Problème de sécurité détecté: hardcodedSecrets39;, ... },
class="hl-cmt">// { type: 39;maintainability39;, severity: 39;warning39;, message: 39;TODO/FIXME non résolu39;, ... },
class="hl-cmt">// { type: 39;maintainability39;, severity: 39;warning39;, message: 39;console.log détecté (à supprimer en production)39;, ... },
class="hl-cmt">// { type: 39;maintainability39;, severity: 39;warning39;, message: 39;Type "any" utilisé39;, ... }
class="hl-cmt">// ]
2. Plan Analyzer (src/services/analysis/plan-analysis.ts)
The PlanAnalyzer service is responsible for performing various analytical computations on an ExecutionPlan. It enhances the plan with insights into its structure, risks, and execution characteristics.
Key Capabilities:
static analyze(plan: ExecutionPlan): void: The main method that updates theanalysisproperty of anExecutionPlanin-place. It calculates:totalSteps,totalFiles,estimatedComplexity.riskAssessment: The highest risk level among all steps.criticalPath: The longest sequence of dependent steps, indicating the minimum time required for execution.parallelizableGroups: Identifies groups of steps that can be executed concurrently.rollbackPoints: Suggests steps that are suitable as rollback points in case of failure.static calculateCriticalPath(plan: ExecutionPlan): string[]: Uses a memoized depth-first search to find the longest dependency chain.static findParallelGroups(plan: ExecutionPlan): string[][]: Determines groups of steps that can run in parallel by calculating their dependency depth.static detectCycles(plan: ExecutionPlan): string[]: Identifies circular dependencies within the plan's steps, which would prevent execution.
Connections:
This service is primarily used by the PlanGenerator to keep the plan's analysis up-to-date after modifications.
3. Codebase Explorer (src/services/codebase-explorer.ts)
The CodebaseExplorer service provides comprehensive capabilities for scanning, analyzing, and reporting on a project's file system structure and content. It's designed to give a holistic view of a codebase.
Key Classes & Interfaces:
CodebaseExplorer: The main class for performing exploration.FileInfo: Detailed information about a single file.DirectoryInfo: Information about a directory.ProjectInfo: Detected project type and metadata (e.g., Node.js, Python).CodebaseStats: Aggregated statistics for the entire codebase.ExplorationOptions: Configuration for the exploration process (e.g.,maxDepth,excludePatterns).
Key Capabilities:
constructor(rootPath: string, options: Partial: Initializes the explorer for a given root directory.) async explore(): Promise: Initiates the recursive scan of the codebase, populating internal data structures.private async scanDirectory(dirPath: string, depth: number): Promise: Recursively traverses directories, respectingmaxDepthandexcludePatterns.private async analyzeFile(fullPath: string, relativePath: string): Promise: Gathers detailed information for each file, including language, category, size, and line count.private detectLanguage(ext: string): string: Maps file extensions to programming languages.private categorizeFile(relativePath: string, name: string, ext: string): FileCategory: Assigns files to categories likesource,test,config,documentation, etc.private async detectProject(): Promise: Identifies the project type (e.g.,nodejs,python) by looking for common configuration files (package.json,setup.py,go.mod, etc.).private calculateStats(): CodebaseStats: Aggregates data from all scanned files and directories to produce overall statistics.- Reporting & Utilities:
generateTree(maxDepth = 3): Promise: Creates a textual tree view of the codebase.generateReport(): string: Produces a detailed summary report including project info, statistics, language distribution, and lists of largest/recently modified files.getFiles(),getDirectories(),getProjectInfo(): Accessors for collected data.findFiles(pattern: string),findByLanguage(language: string),findByCategory(category: FileCategory): Search functionalities.getImportantFiles(): FileInfo[]: Identifies key files like entry points and configuration files.
Helper Functions:
createCodebaseExplorer(rootPath: string, options?: Partial: Factory function.): CodebaseExplorer exploreCodebase(rootPath: string, options?: Partial: A convenience function for a quick, comprehensive exploration.): Promise<{ stats: CodebaseStats; project: ProjectInfo | null; tree: string; report: string; }>
Usage Example:
import { exploreCodebase } from 39;./services/codebase-explorer.js39;;
async function runExploration() {
const { stats, project, tree, report } = await exploreCodebase(process.cwd(), {
maxDepth: 5,
excludePatterns: [39;node_modules39;, 39;.git39;],
});
console.log(39;Project Info:39;, project);
console.log(39;Codebase Stats:39;, stats);
console.log(39;\nCodebase Tree:\n39;, tree);
console.log(39;\nCodebase Report:\n39;, report);
}
runExploration();
4. Plan Generator (src/services/plan-generator.ts)
The PlanGenerator service provides a structured way to create, manage, and track the execution of complex, multi-step tasks. It implements a phased workflow, allowing for detailed planning, analysis, and progress tracking.
Key Classes & Interfaces:
PlanGenerator: The main class for managing execution plans.ExecutionPlan: The central data structure representing a complete plan.PlanStep: A single, atomic unit of work within anExecutionPlan.PlanPhase: Defines the current stage of the plan (e.g.,analysis,strategy,execution,completed).PlanGeneratorOptions: Configuration for plan generation (e.g.,maxSteps,includeTests).
Key Capabilities:
constructor(options: Partial: Initializes the generator with specific options.) createPlan(title: string, goal: string, description: string): ExecutionPlan: Starts a new execution plan.addStep(step: Omit: Adds a new step to the current plan.): PlanStep addSteps(steps: Omit: Adds multiple steps.[]): PlanStep[] removeStep(stepId: string): boolean: Removes a step and its dependencies.reorderSteps(stepIds: string[]): boolean: Changes the order of steps.transitionPhase(newPhase: PlanPhase): boolean: Moves the plan through its lifecycle phases.updateStepStatus(stepId: string, status: PlanStep["status"], notes?: string): boolean: Updates the status of individual steps (pending,in_progress,completed,failed).getNextStep(): PlanStep | null: Returns the next pending step whose dependencies are met.getParallelSteps(): PlanStep[]: Returns all pending steps whose dependencies are met, allowing for parallel execution.validate(): { valid: boolean; issues: string[] }: Checks the plan for structural issues like circular dependencies or missing dependencies.- Persistence:
loadPlan(json: string): ExecutionPlan: Loads a plan from a JSON string.exportPlan(): string: Exports the current plan to a JSON string.async savePlan(filePath: string): Promise: Saves the plan to a file.async loadPlanFromFile(filePath: string): Promise: Loads a plan from a file.- Reporting:
generateSummary(): string: Creates a human-readable text summary of the plan.generateMarkdown(): string: Generates a Markdown representation of the plan.private updateAnalysis(): void: Internally callsPlanAnalyzer.analyzeto keep the plan's analysis up-to-date.
Singleton Pattern:
The plan-generator.ts module also provides getPlanGenerator() and resetPlanGenerator() functions to manage a singleton instance of the PlanGenerator, ensuring a consistent view of the active plan across the application.
Connections:
- Relies heavily on
PlanAnalyzerfor plan analysis and validation. - Uses
fs/promisesfor file persistence. - The
ExecutionPlanandPlanSteptypes are defined insrc/services/plan-types.ts.
5. Prompt Builder (src/services/prompt-builder.ts)
The PromptBuilder service is a critical component responsible for dynamically constructing the comprehensive system prompt provided to the LLM agent. It aggregates information from various sources to create a rich and context-aware prompt.
Key Class:
PromptBuilder: The main class for prompt construction.
Key Capabilities:
constructor(config: PromptBuilderConfig, promptCacheManager: PromptCacheManager, memory?: EnhancedMemory, moltbotHooksManager?: MoltbotHooksManager, persistentMemory?: PersistentMemoryManager): Initializes the builder with configuration and optional context managers.async buildSystemPrompt(systemPromptId: string | undefined, modelName: string, customInstructions: string | null): Promise: The core method that orchestrates the prompt building process. It integrates:- Moltbot Intro Hooks: Content from
intro_hook.txtfor role/personality injection. - Memory Context: Information from
EnhancedMemory(project context, preferences, recent summaries) andPersistentMemoryManager. - Prompt Management: Uses
getPromptManager()to load specific prompts by ID orautoSelectPromptId()based on the model. - Bootstrap Context: Content from
BOOTSTRAP.md,AGENTS.md,SOUL.md. - Persona Instructions: Active persona definitions from
getPersonaManager(). - Knowledge Base: Context from
getKnowledgeManager(). - Documentation Summary: Architecture summary from
getDocsContextProvider(). - Modular Rules: Rules from
getRulesLoader(). - Skill Enhancements: Active skill prompts from
getSkillManager(). - Identity: Information from
getIdentityManager(). - Coding Style: Auto-detected conventions from
getCodingStyleAnalyzer(). - Workflow Rules: Orchestration rules from
getWorkflowRulesBlock(). - Prompt Variation: Applies variations (
varySystemPrompt) to prevent brittle model repetition. - Truncation: Ensures the prompt fits within the model's context window.
- Caching: Uses
PromptCacheManagerto cache generated prompts.
Connections:
The PromptBuilder has extensive outgoing calls to various managers and providers across the codebase, making it a central hub for prompt engineering and context injection. It's typically instantiated and used by the main agent loop.
6. System Prompt Override (src/services/system-prompt-override.ts)
The SystemPromptOverride service provides a mechanism to modify the system prompt using command-line interface (CLI) flags. It allows users to replace the entire prompt or append additional instructions.
Key Class:
SystemPromptOverride: The class handling prompt overrides.
Key Capabilities:
apply(basePrompt: string, options: OverrideOptions): string: Takes a base system prompt and applies overrides based on the providedOverrideOptions.- Replacement: If
systemPromptorsystemPromptFileis provided, thebasePromptis entirely replaced. - Appending: If
appendSystemPromptorappendSystemPromptFileis provided, their content is appended to thebasePrompt. - Validation: Prevents simultaneous use of replace and append options.
private readFile(filePath: string): string: Utility to read file content for file-based overrides.
Connections:
This service is typically used by the agent's initialization logic to incorporate user-defined prompt modifications after the PromptBuilder has generated the initial system prompt.
7. Unified VFS Router (src/services/vfs/unified-vfs-router.ts)
The UnifiedVfsRouter acts as the central gateway for all file system operations within the application. Its purpose is to prevent "Split Brain" scenarios by ensuring a single, consistent interface for file access, and to enable the use of virtual file systems.
Key Interfaces & Classes:
IVfsProvider: An interface defining the contract for any Virtual File System provider (e.g.,readFile,writeFile,exists).UnifiedVfsRouter: The singleton router class.
Key Capabilities:
static get Instance(): UnifiedVfsRouter: Provides a singleton instance of the router.mount(prefix: string, provider: IVfsProvider): void: Registers a VFS provider to handle paths starting with a specificprefix(e.g.,memory://). Mounts are sorted by prefix length for longest-prefix matching.unmount(prefix: string): boolean: Removes a mounted provider.private findMount(filePath: string): { provider: IVfsProvider; strippedPath: string } | null: Internal method to determine which provider (if any) should handle a given path.- Default Behavior: If no mounted provider matches, operations are delegated to the physical file system using
fs-extra. - Performance Tracking: All file operations are wrapped with
measureLatencyfor performance monitoring. - Security & Isolation:
resolvePath(filePath: string, baseDir: string): { valid: boolean; resolved: string; error?: string }: Validates paths against workspace boundaries, prevents path traversal, and detects symlink escapes usingWorkspaceIsolation.validateWithIsolation(filePath: string, operation?: string): PathValidationResult: Directly exposes the detailed validation result fromWorkspaceIsolation.
Architecture Diagram:
graph TD
A[Agent File Operations] --> B{UnifiedVfsRouter.Instance};
B -- "filePath.startsWith('memory://')" --> C[MemoryVfsProvider];
B -- "Default (physical FS)" --> D[fs-extra (Physical File System)];
C -- "Stores in .codebuddy/agent-memory" --> E[Disk];
D -- "Accesses project files" --> E;
B -- "Path Validation" --> F[WorkspaceIsolation];
Connections:
- All file system interactions within the agent should ideally go through
UnifiedVfsRouter.Instance. - It integrates with
WorkspaceIsolationfor robust security checks. - It uses
fs-extrafor physical file system operations.
8. Memory VFS Provider (src/services/vfs/memory-vfs-provider.ts)
The MemoryVfsProvider is an implementation of the IVfsProvider interface, designed for ephemeral file storage with a Time-To-Live (TTL) mechanism. It stores files in a dedicated directory (.codebuddy/agent-memory/) and automatically cleans up expired entries.
Key Class:
MemoryVfsProvider: The VFS provider for memory-backed files.
Key Capabilities:
constructor(config: Partial: Initializes the provider with a base directory, default TTL, and cleanup interval.) readFile,writeFile,exists,stat,readdir,remove,rename,ensureDir: Implements allIVfsProvidermethods, routing them tofs-extrawithin its designatedbaseDir.- TTL Management:
setTtl(filePath: string, ttlMs: number): void: Sets a custom TTL for a specific file.isExpired(filePath: string): boolean: Checks if a file has passed its TTL.async cleanupExpired(): Promise: Manually removes all expired files.private startCleanup(): void: Initiates a periodic cleanup process.- Path Resolution: Ensures that all file operations are confined to its
baseDirto prevent path traversal. dispose(): void: Stops the periodic cleanup timer and releases resources.
Connections:
- This provider is designed to be mounted by the
UnifiedVfsRouterat a specific prefix (e.g.,memory://). - It uses
fs-extrafor underlying file system operations.
9. Analysis Types (src/services/analysis/types.ts) & Plan Types (src/services/plan-types.ts)
These files define the core data structures and enumerations used by the analysis and planning services. They ensure type safety, clarity, and consistency across the module.
Key Types in analysis/types.ts:
CodeGuardianMode,IssueSeverity,IssueTypeCodeIssue,FileDependency,FileAnalysisCodeAnalysis,RefactorSuggestion,PatchStep,PatchPlan,PatchDiff
Key Types in plan-types.ts:
PlanPhase,PriorityLevel,RiskLevel,ActionTypePlanAction,PlanStep,PlanAnalysis,PlanMetadata,ExecutionPlan
Interactions and Dependencies
The src/services module is a collection of loosely coupled services, but they interact in specific ways:
PlanGeneratorrelies onPlanAnalyzerfor plan validation and analysis updates.UnifiedVfsRoutercan mountMemoryVfsProvider(and potentially other VFS providers) to handle specific file paths.UnifiedVfsRouterintegrates withWorkspaceIsolation(fromsrc/workspace) for security.PromptBuilderhas extensive dependencies on various context providers and managers (e.g.,EnhancedMemory,MoltbotHooksManager,PromptManager,KnowledgeManager,DocsContextProvider,RulesLoader,SkillManager,IdentityManager,CodingStyleAnalyzer,WorkflowRules) from other modules to construct a comprehensive system prompt.- The agent's core logic (e.g.,
src/agent/codebuddy-agent.ts) instantiates and utilizesPromptBuilder,CodebaseExplorer, andPlanGenerator. SystemPromptOverridemodifies the output ofPromptBuilder.
Usage Patterns
Developers interacting with this module will typically:
- Explore a Codebase: Use
CodebaseExplorerto get an overview of a project, find specific files, or generate reports. - Analyze Code: Use
CodeAnalyzerfor static checks on individual files, often as part of a larger analysis pipeline. - Manage Execution Plans: Use
PlanGeneratorto define, modify, track, and persist multi-step tasks, leveragingPlanAnalyzerfor insights. - Build Agent Prompts: The
PromptBuilderis a core internal service for the agent, dynamically assembling the LLM's system prompt from many sources. Developers might extend it by adding new context providers. - Interact with the File System: All file operations should ideally go through
UnifiedVfsRouter.Instanceto ensure consistency, security, and support for virtual file systems. This allows for flexible environments like sandboxed execution or in-memory workspaces.