refactor: extract common bandwidth formatting utilities
- Add BandwidthInfo interface to types.ts (single source of truth) - Create formatters.ts with formatTB() and formatTrafficInfo() - Display CDN hit rate and gross/origin traffic in recommendations - Fix floating point formatting (consistent decimal places) - Fix undefined handling in toLocaleString() calls - Unify overage detection logic (overage_tb > 0 && cost > 0) - Add CDN hit rate range validation (0-100%) - Extract CDN_CACHE_HIT_RATES constants Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,9 +9,10 @@
|
||||
* - Brave Search / Context7 도구로 최신 트렌드 반영
|
||||
*/
|
||||
|
||||
import type { Env, ServerSession } from './types';
|
||||
import type { Env, ServerSession, BandwidthInfo } from './types';
|
||||
import { createLogger } from './utils/logger';
|
||||
import { executeSearchWeb, executeLookupDocs } from './tools/search-tool';
|
||||
import { formatTrafficInfo } from './utils/formatters';
|
||||
|
||||
const logger = createLogger('server-agent');
|
||||
|
||||
@@ -215,11 +216,7 @@ interface RecommendResponse {
|
||||
estimated_capacity?: {
|
||||
max_concurrent_users?: number;
|
||||
};
|
||||
bandwidth_analysis?: {
|
||||
estimated_monthly_tb?: number;
|
||||
overage_tb?: number;
|
||||
overage_cost_krw?: number;
|
||||
};
|
||||
bandwidth_info?: BandwidthInfo;
|
||||
}>;
|
||||
}
|
||||
|
||||
@@ -561,12 +558,32 @@ export async function processServerConsultation(
|
||||
plan: selected.plan_name
|
||||
});
|
||||
|
||||
// 트래픽 정보 포맷팅
|
||||
let trafficInfo = '';
|
||||
if (selected.price.estimated_monthly_tb !== undefined) {
|
||||
const bandwidthInfo: BandwidthInfo = {
|
||||
included_transfer_tb: selected.price.bandwidth_tb,
|
||||
overage_cost_per_gb: 0,
|
||||
overage_cost_per_tb: 0,
|
||||
estimated_monthly_tb: selected.price.estimated_monthly_tb,
|
||||
estimated_overage_tb: selected.price.overage_tb || 0,
|
||||
estimated_overage_cost: selected.price.overage_cost_krw || 0,
|
||||
total_estimated_cost: selected.price.monthly_krw + (selected.price.overage_cost_krw || 0),
|
||||
currency: 'KRW',
|
||||
gross_monthly_tb: selected.price.gross_monthly_tb,
|
||||
cdn_cache_hit_rate: selected.price.cdn_cache_hit_rate,
|
||||
};
|
||||
trafficInfo = `• ${formatTrafficInfo(bandwidthInfo, 'KRW')}\n`;
|
||||
}
|
||||
|
||||
return `🖥️ ${selected.plan_name} 신청 확인\n\n` +
|
||||
`• 제공사: ${selected.provider}\n` +
|
||||
`• 스펙: ${selected.specs.vcpu}vCPU / ${selected.specs.ram_gb}GB / ${selected.specs.storage_gb}GB\n` +
|
||||
`• 스펙: ${selected.specs.vcpu}vCPU / ${selected.specs.ram_gb}GB RAM / ${selected.specs.storage_gb}GB SSD\n` +
|
||||
`• 리전: ${selected.region.name} (${selected.region.code})\n` +
|
||||
`• 가격: ₩${selected.price.monthly_krw.toLocaleString()}/월\n\n` +
|
||||
`신청하시겠습니까?\n\n` +
|
||||
`• 가격: ₩${selected.price.monthly_krw.toLocaleString()}/월\n` +
|
||||
`• 대역폭: ${selected.price.bandwidth_tb}TB 포함\n` +
|
||||
trafficInfo +
|
||||
`\n신청하시겠습니까?\n\n` +
|
||||
`__KEYBOARD__${keyboardData}__END__`;
|
||||
} else {
|
||||
return `번호를 다시 확인해주세요. 1번부터 ${session.lastRecommendation.recommendations.length}번 중에서 선택해주세요.`;
|
||||
@@ -646,7 +663,12 @@ export async function processServerConsultation(
|
||||
},
|
||||
price: {
|
||||
monthly_krw: Math.round(rec.server.monthly_price),
|
||||
bandwidth_tb: rec.server.transfer_tb
|
||||
bandwidth_tb: rec.server.transfer_tb,
|
||||
estimated_monthly_tb: rec.bandwidth_info?.estimated_monthly_tb,
|
||||
gross_monthly_tb: rec.bandwidth_info?.gross_monthly_tb,
|
||||
cdn_cache_hit_rate: rec.bandwidth_info?.cdn_cache_hit_rate,
|
||||
overage_tb: rec.bandwidth_info?.estimated_overage_tb,
|
||||
overage_cost_krw: rec.bandwidth_info?.estimated_overage_cost
|
||||
},
|
||||
score: rec.score,
|
||||
max_users: rec.estimated_capacity?.max_concurrent_users || 0
|
||||
|
||||
Reference in New Issue
Block a user