tryaii-mcp-server
Version:
TryAII MCP Server - 15+ AI models with comparison, cost tracking, and collective intelligence
164 lines • 6.71 kB
JavaScript
/**
* Centralized cost calculation utility to ensure consistency
* between McpProtocolHandler balance deduction and SessionManager database storage
*/
import { logger } from './logger.js';
/**
* Calculate actual total cost from tool execution result
* This is the authoritative cost calculation used by both:
* - McpProtocolHandler (for balance deduction)
* - SessionManager (for database session cost)
*/
export function calculateActualCost(result, toolName) {
const defaultResult = {
totalCost: 0,
modelCount: 0,
successfulModels: 0,
breakdown: []
};
try {
// Parse the result to extract actual model costs
if (!result || !result.content || !result.content[0] || !result.content[0].text) {
logger.warn('No result content to extract cost from - using fallback pricing', { toolName });
return getFallbackCost(toolName);
}
const resultData = JSON.parse(result.content[0].text);
// Handle brains response format - sum costs from 5 AI models
if (toolName === 'brains' && resultData.responses && Array.isArray(resultData.responses)) {
let totalCost = 0;
const breakdown = [];
let successfulModels = 0;
for (const response of resultData.responses) {
const modelCost = response.cost || 0;
const modelId = response.model?.id || response.modelId || 'unknown';
const success = response.status === 'success';
totalCost += modelCost;
if (success)
successfulModels++;
breakdown.push({
modelId,
cost: modelCost,
success
});
}
// If no cost data found, use fallback
if (totalCost === 0) {
logger.warn('Brains response has no cost data - using fallback', { responseCount: resultData.responses.length });
return getFallbackCost(toolName);
}
const result = {
totalCost,
modelCount: resultData.responses.length,
successfulModels,
breakdown
};
logger.info('Calculated actual cost from brains result', {
toolName,
...result
});
return result;
}
// Handle compare_models response format - sum costs from multiple models
else if (toolName === 'compare_models' && resultData.results && Array.isArray(resultData.results)) {
let totalCost = 0;
const breakdown = [];
let successfulModels = 0;
for (const modelResult of resultData.results) {
const modelCost = modelResult.cost || 0;
const modelId = modelResult.modelId || 'unknown';
const success = modelResult.success !== false;
totalCost += modelCost;
if (success)
successfulModels++;
breakdown.push({
modelId,
cost: modelCost,
success
});
}
// If no cost data found, use fallback
if (totalCost === 0) {
logger.warn('Compare response has no cost data - using fallback', { modelCount: resultData.results.length });
return getFallbackCost(toolName, resultData.results.length);
}
const result = {
totalCost,
modelCount: resultData.results.length,
successfulModels,
breakdown
};
logger.info('Calculated actual cost from compare result', {
toolName,
...result
});
return result;
}
// Handle chat_with_model response format - single model cost
else if (toolName === 'chat_with_model' && resultData.cost !== undefined) {
const cost = resultData.cost || 0;
// If no cost data found, use fallback
if (cost === 0) {
logger.warn('Chat response has no cost data - using fallback');
return getFallbackCost(toolName);
}
const result = {
totalCost: cost,
modelCount: 1,
successfulModels: 1,
breakdown: [{
modelId: resultData.modelId || 'unknown',
cost,
success: true
}]
};
logger.info('Calculated actual cost from chat result', { toolName, ...result });
return result;
}
// If we have response data but no recognizable cost format, use intelligent fallback
logger.warn('Response format not recognized - using intelligent fallback', {
toolName,
hasResponses: !!resultData.responses,
hasResults: !!resultData.results,
hasCost: !!resultData.cost
});
return getFallbackCost(toolName);
}
catch (parseError) {
logger.error('Failed to parse result for cost extraction - using fallback', {
toolName,
error: parseError instanceof Error ? parseError.message : parseError
});
return getFallbackCost(toolName);
}
}
/**
* Get fallback cost when actual cost cannot be determined
* Uses conservative pricing to ensure minimum revenue
*/
function getFallbackCost(toolName, modelCount) {
const fallbackCosts = {
'brains': 0.15, // 5 top models - increased from 0.10
'compare_models': 0.08, // Variable based on model count - increased from 0.06
'chat_with_model': 0.03, // Single model - increased from 0.02
'list_available_models': 0, // Free
'get_model_info': 0 // Free
};
let baseCost = fallbackCosts[toolName] || 0.02; // Default fallback cost
// Adjust costs based on parameters
if (toolName === 'compare_models' && modelCount) {
baseCost = Math.min(modelCount * 0.025, 0.25); // Cap at $0.25, increased rate
}
const result = {
totalCost: baseCost,
modelCount: toolName === 'brains' ? 5 : (modelCount || 1),
successfulModels: toolName === 'brains' ? 5 : (modelCount || 1),
breakdown: [{
modelId: 'fallback',
cost: baseCost,
success: true
}]
};
logger.warn('Using fallback cost calculation', { toolName, ...result });
return result;
}
//# sourceMappingURL=costCalculator.js.map