Source code for mindroot.coreplugins.credits.models

from dataclasses import dataclass, field
from typing import Dict, Optional, Any, List
from datetime import datetime
from pathlib import Path
import json
import uuid

[docs] @dataclass class CreditTransaction: timestamp: datetime username: str amount: float # Positive for allocations, negative for usage balance: float # Running balance after this transaction type: str # 'allocation', 'usage', 'refund', 'expiration' source: str # 'purchase', 'admin_grant', 'usage_deduction', etc. reference_id: str # Links to usage event or purchase/admin action metadata: Dict[str, Any] = field(default_factory=dict) transaction_id: str = field(default_factory=lambda: str(uuid.uuid4()))
[docs] def to_dict(self) -> dict: return { 'timestamp': self.timestamp.isoformat(), 'username': self.username, 'amount': self.amount, 'balance': self.balance, 'type': self.type, 'source': self.source, 'reference_id': self.reference_id, 'metadata': self.metadata, 'transaction_id': self.transaction_id }
[docs] @classmethod def from_dict(cls, data: dict) -> 'CreditTransaction': data = data.copy() data['timestamp'] = datetime.fromisoformat(data['timestamp']) return cls(**data)
[docs] class CreditRatioConfig: """Manages the hierarchical credit ratio configuration""" def __init__(self, base_path: str): self.base_path = Path(base_path) / 'config' self.config_file = self.base_path / 'ratio_config.json' self.base_path.mkdir(parents=True, exist_ok=True) async def _load_config(self) -> Dict: """Load configuration from file""" try: with open(self.config_file, 'r') as f: return json.load(f) except (FileNotFoundError, json.JSONDecodeError): # Return default config if file doesn't exist or is invalid return { 'default_ratio': 100.0, # 1 cent = 100 credits by default 'plugins': {} } async def _save_config(self, config: Dict) -> None: """Save configuration to file""" with open(self.config_file, 'w') as f: json.dump(config, f, indent=2)
[docs] async def set_ratio(self, ratio: float, plugin_id: Optional[str] = None, cost_type_id: Optional[str] = None, model_id: Optional[str] = None) -> None: """Set a credit ratio at the specified level""" if ratio <= 0: raise ValueError("Ratio must be positive") config = await self._load_config() if not plugin_id: config['default_ratio'] = ratio await self._save_config(config) return if plugin_id not in config['plugins']: config['plugins'][plugin_id] = { 'default_ratio': None, 'cost_types': {}, 'models': {} } plugin_config = config['plugins'][plugin_id] if model_id: if model_id not in plugin_config['models']: plugin_config['models'][model_id] = { 'default_ratio': None, 'cost_types': {} } if cost_type_id: plugin_config['models'][model_id]['cost_types'][cost_type_id] = ratio else: plugin_config['models'][model_id]['default_ratio'] = ratio elif cost_type_id: plugin_config['cost_types'][cost_type_id] = ratio else: plugin_config['default_ratio'] = ratio await self._save_config(config)
[docs] async def get_ratio(self, plugin_id: str, cost_type_id: str, model_id: Optional[str] = None) -> float: """Get the appropriate credit ratio following the resolution order""" config = await self._load_config() plugin_config = config['plugins'].get(plugin_id, {}) # 1. Check model-specific cost type ratio if model_id and model_id in plugin_config.get('models', {}): model_config = plugin_config['models'][model_id] if cost_type_id in model_config.get('cost_types', {}): return model_config['cost_types'][cost_type_id] # 2. Check model default ratio if model_config.get('default_ratio') is not None: return model_config['default_ratio'] # 3. Check plugin cost type ratio if cost_type_id in plugin_config.get('cost_types', {}): return plugin_config['cost_types'][cost_type_id] # 4. Check plugin default ratio if plugin_config.get('default_ratio') is not None: return plugin_config['default_ratio'] # 5. Use global default ratio return config['default_ratio']
[docs] async def get_config(self) -> Dict: """Get the full configuration""" return await self._load_config()
[docs] async def set_config(self, config: Dict) -> None: """Set the full configuration""" # Basic validation if 'default_ratio' not in config: raise ValueError("Configuration must include default_ratio") if config['default_ratio'] <= 0: raise ValueError("Default ratio must be positive") await self._save_config(config)