girish-hari's picture
checking-in the project source code
2358888
"""
Base simulator class for all service integrations.
All service-specific simulators inherit from this class.
"""
from abc import ABC, abstractmethod
from typing import Any, Dict, Optional
import json
class BaseSimulator(ABC):
"""Base class for all service simulators."""
def __init__(self, service_name: str):
self.service_name = service_name
self.mock_responses = {}
self.load_mock_responses()
@abstractmethod
def load_mock_responses(self):
"""Load mock responses for this service."""
pass
@abstractmethod
def get_required_permissions(self, action: str) -> set[str]:
"""Get required permissions for an action."""
pass
@abstractmethod
def validate_params(self, action: str, params: dict) -> tuple[bool, Optional[str]]:
"""
Validate parameters for an action.
Returns:
(is_valid, error_message)
"""
pass
@abstractmethod
def generate_mock_response(self, action: str, params: dict) -> dict:
"""Generate a realistic mock response for the action."""
pass
def execute(self, action: str, params: dict, mock: bool = True, credentials: Optional[dict] = None) -> dict:
"""
Execute an API action (mock or real).
Args:
action: The action to perform (e.g., 'get_pull_request')
params: Parameters for the action
mock: If True, return mock response. If False, call real API.
credentials: API credentials (required for real mode)
Returns:
Response dict with data or error
"""
# Validate parameters
is_valid, error_msg = self.validate_params(action, params)
if not is_valid:
return {
'success': False,
'error': 'INVALID_PARAMS',
'message': error_msg,
'service': self.service_name,
'action': action
}
if mock:
return self._execute_mock(action, params)
else:
if not credentials:
return {
'success': False,
'error': 'MISSING_CREDENTIALS',
'message': 'Credentials required for real API calls',
'service': self.service_name,
'action': action
}
return self._execute_real(action, params, credentials)
def _execute_mock(self, action: str, params: dict) -> dict:
"""Execute in mock mode."""
try:
response_data = self.generate_mock_response(action, params)
return {
'success': True,
'mode': 'mock',
'service': self.service_name,
'action': action,
'data': response_data,
'note': '⚡ This was a simulated response - no real API call made'
}
except Exception as e:
return {
'success': False,
'error': 'MOCK_GENERATION_ERROR',
'message': str(e),
'service': self.service_name,
'action': action
}
def _execute_real(self, action: str, params: dict, credentials: dict) -> dict:
"""
Execute real API call.
Subclasses should override this to implement real API calls.
"""
return {
'success': False,
'error': 'NOT_IMPLEMENTED',
'message': f'Real API mode not yet implemented for {self.service_name}.{action}',
'service': self.service_name,
'action': action,
'note': 'Override _execute_real() in your simulator to enable real API calls'
}
def estimate_tokens(self, response: dict) -> int:
"""
Estimate token count for a response.
Uses simple heuristic: ~4 characters per token for JSON.
Will be improved with tiktoken in later phases.
"""
response_str = json.dumps(response)
return len(response_str) // 4
def get_action_list(self) -> list[str]:
"""Get list of available actions for this service."""
return list(self.mock_responses.keys())