#!/usr/bin/env node
// Complete test of all questions with detailed answers
const { spawn } = require('child_process');
class CompleteTester {
constructor() {
this.server = null;
this.requestId = 1;
this.responses = [];
}
async startServer() {
return new Promise((resolve, reject) => {
this.server = spawn('node', ['dist/index.js'], {
stdio: ['pipe', 'pipe', 'pipe'],
cwd: process.cwd()
});
this.server.stdout.on('data', (data) => {
const lines = data.toString().split('\n').filter(line => line.trim());
for (const line of lines) {
try {
const response = JSON.parse(line);
this.responses.push(response);
} catch (e) {}
}
});
this.server.on('error', reject);
setTimeout(resolve, 3000);
});
}
async sendRequest(method, params = {}) {
return new Promise((resolve) => {
const request = {
jsonrpc: "2.0",
id: this.requestId++,
method,
params
};
const startResponseCount = this.responses.length;
this.server.stdin.write(JSON.stringify(request) + '\n');
const checkForResponse = () => {
const newResponses = this.responses.slice(startResponseCount);
const matchingResponse = newResponses.find(r => r.id === request.id);
if (matchingResponse) {
resolve(matchingResponse);
} else if (Date.now() - startTime > 20000) {
resolve(null); // Timeout after 20s
} else {
setTimeout(checkForResponse, 200);
}
};
const startTime = Date.now();
setTimeout(checkForResponse, 200);
});
}
cleanup() {
if (this.server) {
this.server.kill();
}
}
}
async function runAllQuestions() {
console.log('π― COMPLETE TEST: ALL 12 QUESTIONS WITH DETAILED ANSWERS');
console.log('=' .repeat(80));
const client = new CompleteTester();
await client.startServer();
// Authenticate once
const authResponse = await client.sendRequest('tools/call', {
name: 'authenticate_user',
arguments: {
username: 'david+saola@umbrellacost.com',
password: 'Dsamsung1!'
}
});
if (!authResponse?.result?.content?.[0]?.text?.includes('Successfully authenticated')) {
console.log('β Authentication failed');
client.cleanup();
return;
}
console.log('β
Authentication successful\n');
const questions = [
{
num: 1,
text: "What was my total AWS cost for March 2025?",
params: {
name: 'api___invoices_caui',
arguments: {
startDate: "2025-03-01",
endDate: "2025-03-31",
cloud_context: "aws",
groupBy: "none"
}
},
expected: 104755.07
},
{
num: 2,
text: "What was my total unblended AWS cost for March 2025?",
params: {
name: 'api___invoices_caui',
arguments: {
startDate: "2025-03-01",
endDate: "2025-03-31",
cloud_context: "aws",
groupBy: "none",
isUnblended: "true"
}
},
expected: 104755.07
},
{
num: 3,
text: "What was my total amortized AWS cost for March 2025?",
params: {
name: 'api___invoices_caui',
arguments: {
startDate: "2025-03-01",
endDate: "2025-03-31",
cloud_context: "aws",
groupBy: "none",
isAmortized: "true"
}
},
expected: 108831.79
},
{
num: 4,
text: "What was my total net amortized AWS cost for March 2025?",
params: {
name: 'api___invoices_caui',
arguments: {
startDate: "2025-03-01",
endDate: "2025-03-31",
cloud_context: "aws",
groupBy: "none",
isNetAmortized: "true"
}
},
expected: 64730.56
},
{
num: 5,
text: "What are my top 5 AWS services by cost for March 2025?",
params: {
name: 'api___invoices_caui',
arguments: {
startDate: "2025-03-01",
endDate: "2025-03-31",
cloud_context: "aws",
groupBy: "service"
}
}
},
{
num: 6,
text: "Show me AWS costs grouped by account for March 2025",
params: {
name: 'api___invoices_caui',
arguments: {
startDate: "2025-03-01",
endDate: "2025-03-31",
cloud_context: "aws",
groupBy: "account"
}
}
},
{
num: 7,
text: "What was my daily AWS cost trend for March 2025?",
params: {
name: 'api___invoices_caui',
arguments: {
startDate: "2025-03-01",
endDate: "2025-03-31",
cloud_context: "aws",
groupBy: "none",
periodGranLevel: "day"
}
}
},
{
num: 8,
text: "Show me AWS region breakdown for March 2025",
params: {
name: 'api___invoices_caui',
arguments: {
startDate: "2025-03-01",
endDate: "2025-03-31",
cloud_context: "aws",
groupBy: "region"
}
}
},
{
num: 9,
text: "What are my AWS Reserved Instance recommendations?",
params: {
name: 'api___recommendations_v2',
arguments: {
cloud_context: "aws",
recommendation_type: "reserved_instance"
}
}
},
{
num: 10,
text: "What are my AWS EC2 rightsizing recommendations?",
params: {
name: 'api___recommendations_v2',
arguments: {
cloud_context: "aws",
recommendation_type: "rightsizing"
}
}
},
{
num: 11,
text: "Show me all AWS cost optimization recommendations",
params: {
name: 'api___recommendations_v2',
arguments: {
cloud_context: "aws"
}
}
},
{
num: 12,
text: "What are my top savings opportunities across all AWS services?",
params: {
name: 'api___recommendations_v2',
arguments: {
cloud_context: "aws",
recommendation_type: "all"
}
}
}
];
const results = [];
for (const q of questions) {
console.log(`π QUESTION ${q.num}: ${q.text}`);
console.log('-'.repeat(80));
const response = await client.sendRequest('tools/call', q.params);
if (response?.result?.content?.[0]?.text) {
const text = response.result.content[0].text;
if (q.num <= 8) {
// Cost questions - parse JSON data
const jsonMatch = text.match(/```json\n(.*?)\n```/s);
if (jsonMatch) {
try {
const data = JSON.parse(jsonMatch[1]);
const total = data.reduce((sum, item) => sum + (item.total_cost || 0), 0);
console.log(`π° ANSWER: $${total.toFixed(2)}`);
if (q.expected && Math.abs(total - q.expected) < 1) {
console.log(`β
CORRECT! Matches expected $${q.expected.toFixed(2)}`);
results.push(`β
Q${q.num}: $${total.toFixed(2)} (CORRECT)`);
} else if (q.expected) {
console.log(`β οΈ Expected $${q.expected.toFixed(2)}, got $${total.toFixed(2)}`);
results.push(`β οΈ Q${q.num}: $${total.toFixed(2)} (expected ${q.expected.toFixed(2)})`);
} else {
results.push(`π Q${q.num}: $${total.toFixed(2)}`);
}
if (q.num === 5 && data.length > 0) {
// Show top services
const serviceMap = {};
data.forEach(item => {
const serviceName = item.service_name || item.group_by || 'Unknown';
if (!serviceMap[serviceName]) serviceMap[serviceName] = 0;
serviceMap[serviceName] += (item.total_cost || 0);
});
const topServices = Object.entries(serviceMap)
.sort(([,a], [,b]) => b - a)
.slice(0, 5);
console.log('\nπ TOP 5 AWS SERVICES:');
topServices.forEach(([service, cost], index) => {
console.log(` ${index + 1}. ${service}: $${cost.toFixed(2)}`);
});
}
if (q.num === 6 && data.length > 0) {
// Show top accounts
const accountMap = {};
data.forEach(item => {
const accountName = item.account_name || item.group_by || 'Unknown';
if (!accountMap[accountName]) accountMap[accountName] = 0;
accountMap[accountName] += (item.total_cost || 0);
});
const topAccounts = Object.entries(accountMap)
.sort(([,a], [,b]) => b - a)
.slice(0, 3);
console.log('\nπ’ TOP ACCOUNTS:');
topAccounts.forEach(([account, cost], index) => {
console.log(` ${index + 1}. ${account}: $${cost.toFixed(2)}`);
});
}
} catch (e) {
console.log('β JSON parsing error');
results.push(`β Q${q.num}: JSON parsing error`);
}
} else {
console.log('β No JSON data found');
results.push(`β Q${q.num}: No JSON data found`);
}
} else {
// Recommendation questions
const recMatch = text.match(/(\d+)\s+recommendations/i);
const savingsMatch = text.match(/\$([0-9,]+(?:\.\d+)?)/);
if (recMatch && savingsMatch) {
console.log(`π― ANSWER: ${recMatch[1]} recommendations found`);
console.log(`π° SAVINGS: $${savingsMatch[1]} potential annual savings`);
results.push(`π― Q${q.num}: ${recMatch[1]} recommendations, $${savingsMatch[1]} savings`);
} else {
console.log('π Recommendations data available');
results.push(`π Q${q.num}: Recommendations available`);
}
// Show brief excerpt
const lines = text.split('\n').slice(0, 3);
console.log('π Summary:', lines.join(' ').substring(0, 100) + '...');
}
} else {
console.log('β No response received');
results.push(`β Q${q.num}: No response`);
}
console.log('');
await new Promise(resolve => setTimeout(resolve, 1000));
}
// Summary
console.log('\n' + '='.repeat(80));
console.log('π COMPLETE RESULTS SUMMARY:');
console.log('='.repeat(80));
results.forEach(result => console.log(result));
client.cleanup();
console.log('\nβ
All 12 questions completed successfully!');
}
runAllQuestions().catch(console.error);