Code Improvements
The Robota library is continuously improving code quality and developer experience through ongoing enhancements. This document provides detailed information about refactoring and code improvement work.
Structural Improvements
Modularization and Separation
The codebase is logically separated as follows:
robota/
├── packages/ # Core packages
│ ├── core/ # Core functionality
│ │ ├── managers/ # Feature-specific manager classes
│ │ ├── services/ # Business logic services
│ │ ├── interfaces/ # Type definitions and interfaces
│ │ └── utils/ # Utility functions
│ ├── openai/ # OpenAI integration
│ ├── anthropic/ # Anthropic integration
│ ├── mcp/ # MCP implementation
│ ├── tools/ # Tool system
│ └── ...
└── apps/ # Applications
├── docs/ # Documentation application
└── examples/ # Example code
Introduction of Manager Pattern
Core functionality is organized into manager classes separated by responsibility:
export class Robota {
// Managers
private aiProviderManager: AIProviderManager;
private toolProviderManager: ToolProviderManager;
private systemMessageManager: SystemMessageManager;
private functionCallManager: FunctionCallManager;
private conversationService: ConversationService;
// Basic configuration
private memory: Memory;
private onToolCall?: (toolName: string, params: any, result: any) => void;
private logger: Logger;
private debug: boolean;
}
AIProviderManager
Handles registration, management, and selection of AI providers:
export class AIProviderManager {
addProvider(name: string, aiProvider: AIProvider): void;
setCurrentAI(providerName: string, model: string): void;
getAvailableAIs(): Record<string, string[]>;
getCurrentAI(): { provider?: string; model?: string };
isConfigured(): boolean;
}
ToolProviderManager
Manages tool providers and tool calls:
export class ToolProviderManager {
addProviders(providers: ToolProvider[]): void;
callTool(toolName: string, parameters: Record<string, any>): Promise<any>;
getAvailableTools(): any[];
setAllowedFunctions(functions: string[]): void;
}
SystemMessageManager
Manages system prompts and system messages:
export class SystemMessageManager {
setSystemPrompt(prompt: string): void;
setSystemMessages(messages: Message[]): void;
addSystemMessage(content: string): void;
getSystemPrompt(): string | undefined;
getSystemMessages(): Message[] | undefined;
}
FunctionCallManager
Manages function call configuration and modes:
export class FunctionCallManager {
setFunctionCallMode(mode: FunctionCallMode): void;
configure(config: FunctionCallConfig): void;
getDefaultMode(): FunctionCallMode;
isFunctionAllowed(functionName: string): boolean;
}
Introduction of Service Layer
Business logic is separated into service classes:
ConversationService
Handles conversation processing with AI:
export class ConversationService {
prepareContext(memory: Memory, systemPrompt?: string, systemMessages?: Message[], options?: RunOptions): Context;
generateResponse(aiProvider: AIProvider, model: string, context: Context, options: RunOptions, availableTools: any[], onToolCall?: Function): Promise<ModelResponse>;
generateStream(aiProvider: AIProvider, model: string, context: Context, options: RunOptions, availableTools: any[]): Promise<AsyncIterable<StreamingResponseChunk>>;
}
This modularization provides the following benefits:
- Single Responsibility Principle: Each class has clear responsibilities
- Code Reusability: Common functionality is properly separated, reducing code duplication
- Maintainability: Changes in one module have minimal impact on other modules
- Testability: Independent modules are easy to unit test
- Bundle Size Optimization: Users can import only the modules they need to optimize bundle size
Interface Improvements
Core interfaces have been improved as follows:
- AIProvider: Provides a standardized, extensible interface for communication with AI models
- Memory: Defines clear contracts for conversation history management
- Tool: Extensible interface for tool definition and execution
Build System Improvements
Test File Separation
The build system has been improved so that test files are excluded from production builds:
// tsconfig.json - For production build
{
"exclude": [
"src/**/*.test.ts",
"src/**/*.test.tsx",
"src/**/*.spec.ts",
"src/**/*.spec.tsx"
]
}
// tsconfig.test.json - For testing
{
"extends": "./tsconfig.json",
"compilerOptions": {
"types": ["vitest/globals", "node"]
},
"include": ["src/**/*"],
"exclude": []
}
Type System Cleanup
Type definitions have been moved to appropriate locations, resolving circular dependency issues:
// Located in managers/function-call-manager.ts
export type FunctionCallMode = 'auto' | 'force' | 'disabled';
export interface FunctionCallConfig {
defaultMode?: FunctionCallMode;
maxCalls?: number;
timeout?: number;
allowedFunctions?: string[];
}
Type System Improvements
Introduction of Generic Types
// Before:
interface Tool {
name: string;
description?: string;
execute: (...args: any[]) => Promise<any>;
}
// Improved:
interface Tool<TInput = any, TOutput = any> {
name: string;
description?: string;
parameters?: ToolParameter[];
execute: (input: TInput) => Promise<ToolResult<TOutput>>;
}
Added Explicit Type Checking
// Function parameter validation
registerFunction(schema: FunctionSchema, fn: Function): void {
if (!schema || !schema.name) {
throw new Error('Valid function schema is required.');
}
if (typeof fn !== 'function') {
throw new Error('Second argument must be a function.');
}
// Implementation...
}
Code Readability Improvements
Comments and Documentation
JSDoc comments are included for all major classes, methods, and properties:
export class FunctionCallManager {
setFunctionCallMode(mode: FunctionCallMode): void {
this.config.defaultMode = mode;
}
}
Consistent Method Grouping
Related methods are grouped logically to clarify code structure:
class Robota {
// ============================================================
// AI Provider Management (delegation)
// ============================================================
addAIProvider() { /* ... */ }
setCurrentAI() { /* ... */ }
getAvailableAIs() { /* ... */ }
// ============================================================
// System Message Management (delegation)
// ============================================================
setSystemPrompt() { /* ... */ }
setSystemMessages() { /* ... */ }
addSystemMessage() { /* ... */ }
// ============================================================
// Function Call Management (delegation)
// ============================================================
setFunctionCallMode() { /* ... */ }
configureFunctionCall() { /* ... */ }
// ============================================================
// Execution Methods
// ============================================================
run() { /* ... */ }
chat() { /* ... */ }
runStream() { /* ... */ }
// ============================================================
// Internal Helper Methods
// ============================================================
private generateResponse() { /* ... */ }
private generateStream() { /* ... */ }
}
Error Handling Improvements
Error handling has been improved to provide more specific and useful feedback in various situations:
async generateResponse(context: any, options: RunOptions = {}): Promise<ModelResponse> {
if (!this.aiProviderManager.isConfigured()) {
throw new Error('Current AI provider and model are not configured. Use setCurrentAI() method to configure.');
}
try {
// Response generation...
} catch (error) {
logger.error('Error occurred during AI client call:', error);
throw new Error(`Error during AI client call: ${error instanceof Error ? error.message : String(error)}`);
}
}
Test Improvements
Test Location and Structure
Test files are placed alongside their corresponding implementation files for easier management:
packages/core/src/
├── memory.ts
├── memory.test.ts // Tests for memory.ts
├── robota.ts
└── robota.test.ts // Tests for robota.ts
Expanded Test Coverage
Test coverage has been improved in the following areas:
- Edge Cases: Tests for abnormal inputs and boundary conditions
- Error Situations: Verification that exceptions are handled properly
- Integration Tests: Test scenarios where multiple components work together
Tests for Refactored Structure
Test code has been updated to match the new manager-based structure:
describe('Robota', () => {
let mockProvider: MockProvider;
let robota: Robota;
beforeEach(() => {
mockProvider = new MockProvider();
robota = new Robota({
aiProviders: { mock: mockProvider },
currentProvider: 'mock',
currentModel: 'mock-model'
});
});
it('should initialize with function call configuration', () => {
const customRobota = new Robota({
aiProviders: { mock: mockProvider },
currentProvider: 'mock',
currentModel: 'mock-model',
functionCallConfig
});
expect(customRobota['functionCallManager'].getDefaultMode()).toBe('auto');
expect(customRobota['functionCallManager'].getMaxCalls()).toBe(5);
expect(customRobota['functionCallManager'].getAllowedFunctions()).toEqual(['getWeather']);
});
});
API Design Improvements
Consistent Naming Conventions
All APIs follow consistent naming conventions:
- Classes: PascalCase (e.g.,
AIProviderManager
,FunctionCallManager
) - Methods: camelCase (e.g.,
registerFunction
,setSystemPrompt
) - Constants: UPPER_SNAKE_CASE (e.g.,
DEFAULT_TIMEOUT
,MAX_TOKENS
) - Types/Interfaces: PascalCase (e.g.,
ToolResult
,FunctionSchema
)
Dependency Injection and Delegation Pattern
The Robota class is configured with managers through dependency injection, and public APIs are implemented by delegating to appropriate managers:
export class Robota {
constructor(options: RobotaOptions) {
// Initialize managers
this.aiProviderManager = new AIProviderManager();
this.toolProviderManager = new ToolProviderManager(this.logger, options.functionCallConfig?.allowedFunctions);
this.systemMessageManager = new SystemMessageManager();
this.functionCallManager = new FunctionCallManager(options.functionCallConfig);
this.conversationService = new ConversationService(options.temperature, options.maxTokens, this.logger, this.debug);
}
// Delegate AI Provider management to AIProviderManager
addAIProvider(name: string, aiProvider: AIProvider): void {
this.aiProviderManager.addProvider(name, aiProvider);
}
// Delegate system message management to SystemMessageManager
setSystemPrompt(prompt: string): void {
this.systemMessageManager.setSystemPrompt(prompt);
}
}
Method Chaining Support
// Before:
toolRegistry.register(tool1);
toolRegistry.register(tool2);
// Improved:
toolRegistry
.register(tool1)
.register(tool2);
Performance Improvements
Memory Optimization
The memory management system has been improved to efficiently store and retrieve conversation history:
class SimpleMemory implements Memory {
private messages: Message[] = [];
private maxMessages: number;
constructor(options?: { maxMessages?: number }) {
this.maxMessages = options?.maxMessages || 0;
}
addMessage(message: Message): void {
this.messages.push(message);
// Apply maximum message limit
if (this.maxMessages > 0 && this.messages.length > this.maxMessages) {
// Always keep system messages
const systemMessages = this.messages.filter(m => m.role === 'system');
const nonSystemMessages = this.messages.filter(m => m.role !== 'system');
// Trim only non-system messages
const remainingCount = this.maxMessages - systemMessages.length;
const trimmedNonSystemMessages = nonSystemMessages.slice(-remainingCount);
// Combine system messages and trimmed non-system messages
this.messages = [...systemMessages, ...trimmedNonSystemMessages];
}
}
}
Code Comment Improvements
Korean JSDoc Comments Converted to English
All JSDoc comments in the library codebase have been changed from Korean to English. This is an important improvement for international usability and standard development practices.
Changed Files
Core Package:
index.ts
: Main class and manager export commentsrobota.ts
: All Robota class and method commentsmanagers/
: All manager class commentsfunction.ts
: Function creation utility commentsinterfaces/
: Interface definition commentsutils.ts
: Utility function commentsproviders/
: Provider implementation comments
OpenAI Package:
index.ts
,types.ts
: Provider options and interface commentsprovider.ts
: OpenAI Provider implementation comments
Anthropic Package:
index.ts
,types.ts
,provider.ts
: All package comments
Tools Package:
types.d.ts
,index.ts
: Tool system related commentstool-provider.ts
,mcp-tool-provider.ts
: Tool provider comments
Comment Change Examples
// Before (Korean)
/**
* 메인 Robota 클래스
* 에이전트 초기화 및 실행을 위한 인터페이스 제공
*/
// After (English)
/**
* Main Robota class
* Provides an interface for initializing and running agents
*/
Standardized JSDoc Format
All comments have been improved to follow standard JSDoc format:
/**
* Function description
*
* @param paramName - Parameter description
* @returns Return value description
*
* @example
* ```ts
* const result = functionCall(param);
* ```
*/
Future Comment Writing Principles
All new code going forward should follow these principles:
- Write in English: All JSDoc comments and inline comments must be written in English
- Standard Format: Follow JSDoc standard rules
- Complete Documentation: Include parameters, return values, examples
- Clear Descriptions: Clearly describe the purpose and usage of functions or classes
Conclusion
Through these code improvements, the Robota library provides the following benefits:
- Better Developer Experience: Intuitive APIs and clear documentation
- Enhanced Type Safety: Catch errors at compile time
- Higher Code Quality: Consistent style and design principles
- Extensibility: Easy to add new features and integrations
- Maintainability: Clear module boundaries and separation of responsibilities
- Testability: Each manager and service can be tested independently
- Build Optimization: Test files are excluded from production builds for bundle size optimization
- International Standards: English comments make it easy for international developers to understand
Future development plans include additional optimizations, support for more providers, and implementation of advanced features.