format.tsβ’7.92 kB
/**
* Format utilities for hi-cloud output
*/
export interface LogEntry {
timestamp: string;
severity: string;
message: string;
resource?: string;
labels?: Record<string, string>;
}
/**
* Get severity emoji
*/
export function getSeverityEmoji(severity: string): string {
switch (severity.toUpperCase()) {
case 'EMERGENCY':
case 'ALERT':
case 'CRITICAL':
case 'ERROR':
return 'π΄';
case 'WARNING':
return 'π‘';
case 'NOTICE':
case 'INFO':
return 'π΅';
case 'DEBUG':
return 'βͺ';
default:
return 'β«';
}
}
/**
* Format log entries for display
*/
export function formatLogEntries(logs: LogEntry[]): string {
if (logs.length === 0) {
return 'λ‘κ·Έκ° μμ΅λλ€.';
}
const lines = logs.map((log) => {
const emoji = getSeverityEmoji(log.severity);
const time = formatTimestamp(log.timestamp);
const severity = log.severity.padEnd(8);
const message = log.message.substring(0, 200); // Truncate long messages
return `${emoji} [${time}] ${severity} ${message}`;
});
return lines.join('\n');
}
/**
* Format timestamp for display
*/
export function formatTimestamp(timestamp: string): string {
try {
const date = new Date(timestamp);
return date.toLocaleString('ko-KR', {
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
});
} catch {
return timestamp;
}
}
/**
* Format Cloud Run service status
*/
export function formatRunStatus(service: any): string {
const lines: string[] = [];
lines.push(`π¦ μλΉμ€: ${service.name || 'Unknown'}`);
lines.push(`π URL: ${service.url || 'N/A'}`);
lines.push(`π 리μ : ${service.region || 'N/A'}`);
lines.push(`π 리λΉμ : ${service.revision || 'N/A'}`);
if (service.status) {
const statusEmoji = service.status === 'Ready' ? 'β
' : 'β';
lines.push(`${statusEmoji} μν: ${service.status}`);
}
if (service.traffic) {
lines.push(`\nπ νΈλν½ λΆλ°°:`);
service.traffic.forEach((t: any) => {
lines.push(` - ${t.revisionName}: ${t.percent}%`);
});
}
if (service.lastDeployed) {
lines.push(`\nπ λ§μ§λ§ λ°°ν¬: ${formatTimestamp(service.lastDeployed)}`);
}
return lines.join('\n');
}
/**
* Format storage bucket/object list
*/
export function formatStorageList(items: any[], isBucketList: boolean): string {
if (items.length === 0) {
return isBucketList ? 'λ²ν·μ΄ μμ΅λλ€.' : 'κ°μ²΄κ° μμ΅λλ€.';
}
const lines: string[] = [];
if (isBucketList) {
lines.push('π¦ λ²ν· λͺ©λ‘:');
items.forEach((bucket) => {
lines.push(` π ${bucket.name}`);
if (bucket.location) {
lines.push(` β μμΉ: ${bucket.location}`);
}
});
} else {
lines.push('π κ°μ²΄ λͺ©λ‘:');
items.forEach((obj) => {
const size = formatFileSize(obj.size);
lines.push(` π ${obj.name} (${size})`);
});
}
return lines.join('\n');
}
/**
* Format file size
*/
export function formatFileSize(bytes: number): string {
if (bytes === 0) return '0 B';
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(1024));
const size = (bytes / Math.pow(1024, i)).toFixed(2);
return `${size} ${units[i]}`;
}
/**
* Format SQL query result
*/
export function formatSqlResult(rows: any[], columns: string[]): string {
if (rows.length === 0) {
return 'κ²°κ³Όκ° μμ΅λλ€.';
}
const lines: string[] = [];
lines.push(`π κ²°κ³Ό: ${rows.length}ν`);
lines.push('');
// Simple table format
lines.push('| ' + columns.join(' | ') + ' |');
lines.push('|' + columns.map(() => '---').join('|') + '|');
rows.slice(0, 100).forEach((row) => {
const values = columns.map((col) => String(row[col] ?? 'NULL').substring(0, 50));
lines.push('| ' + values.join(' | ') + ' |');
});
if (rows.length > 100) {
lines.push(`\n... μΈ ${rows.length - 100}κ° ν μλ΅`);
}
return lines.join('\n');
}
/**
* Format error message for user
*/
export function formatError(error: any): string {
if (error.type && error.suggestion) {
return `β ${error.message}\n\nπ‘ ${error.suggestion}`;
}
return `β μ€λ₯: ${error.message || error}`;
}
/**
* Create summary report for hi-ai integration
*/
export function createErrorReport(logs: LogEntry[]): {
summary: string;
errors: LogEntry[];
hasErrors: boolean;
hiAiHint?: string;
} {
const errors = logs.filter((log) =>
['ERROR', 'CRITICAL', 'ALERT', 'EMERGENCY'].includes(log.severity.toUpperCase())
);
let summary: string;
let hiAiHint: string | undefined;
if (errors.length > 0) {
summary = `π΄ ${errors.length}κ°μ μλ¬κ° λ°κ²¬λμμ΅λλ€.`;
// hi-ai ν΅ν© ννΈ - LLMμ΄ μμ°μ€λ½κ² hi-ai λꡬλ₯Ό νΈμΆνλλ‘ μ λ
hiAiHint = getHiAiIntegrationHint('error_analysis', {
errorCount: errors.length,
errorTypes: [...new Set(errors.map(e => e.severity))],
});
} else {
summary = 'β
μλ¬κ° μμ΅λλ€.';
}
return {
summary,
errors,
hasErrors: errors.length > 0,
hiAiHint,
};
}
/**
* hi-ai ν΅ν© ννΈ μμ±
* hi-ai MCPκ° μ€μΉλμ΄ μμ κ²½μ° LLMμ΄ μμ°μ€λ½κ² νΈμΆν μ μλλ‘ ννΈ μ 곡
*/
export function getHiAiIntegrationHint(
context: 'error_analysis' | 'deployment_failure' | 'performance_issue' | 'cost_alert',
data?: Record<string, any>
): string {
const hints: Record<string, string> = {
error_analysis: `
π‘ hi-ai μ°λ κ°λ₯: μλ¬ λΆμμ΄ νμνλ©΄ analyze_problem λκ΅¬λ‘ μμΈμ λΆμνκ³ ,
κ΄λ ¨ μ½λλ₯Ό μ°Ύμ μμ λ°©μμ μ μν μ μμ΅λλ€.
λ©λͺ¨λ¦¬μ μ μ₯νλ©΄ κ°μ μλ¬ μ¬λ° μ λΉ λ₯΄κ² ν΄κ²°ν μ μμ΅λλ€.`,
deployment_failure: `
π‘ hi-ai μ°λ κ°λ₯: λ°°ν¬ μ€ν¨ μμΈμ step_by_step_analysisλ‘ λ¨κ³λ³ λΆμνκ³ ,
μ½λ μμ μ΄ νμνλ©΄ suggest_improvementsλ‘ κ°μ μμ λ°μ μ μμ΅λλ€.`,
performance_issue: `
π‘ hi-ai μ°λ κ°λ₯: μ±λ₯ λ¬Έμ λ₯Ό analyze_complexityλ‘ λΆμνκ³ ,
λ³λͺ© μ§μ μ μ°Ύμ μ΅μ ν λ°©μμ μ μν μ μμ΅λλ€.`,
cost_alert: `
π‘ hi-ai μ°λ κ°λ₯: λΉμ© μ¦κ° μμΈμ break_down_problemμΌλ‘ λΆμνκ³ ,
λΉμ© μ κ° λ°©μμ 체κ³μ μΌλ‘ μ 리ν μ μμ΅λλ€.`,
};
return hints[context] || '';
}
/**
* μλ¬ λ‘κ·Έμ λν μμΈ λΆμ 리ν¬νΈ μμ± (hi-ai μ°λμ©)
*/
export function createDetailedErrorReport(logs: LogEntry[]): string {
const report = createErrorReport(logs);
if (!report.hasErrors) {
return report.summary;
}
const lines: string[] = [report.summary, ''];
// μλ¬ μ νλ³ κ·Έλ£Ήν
const errorsByType = new Map<string, LogEntry[]>();
report.errors.forEach(error => {
const type = error.severity.toUpperCase();
if (!errorsByType.has(type)) {
errorsByType.set(type, []);
}
errorsByType.get(type)!.push(error);
});
// μ νλ³ μμ½
lines.push('π μλ¬ μμ½:');
errorsByType.forEach((errors, type) => {
lines.push(` ${getSeverityEmoji(type)} ${type}: ${errors.length}건`);
});
lines.push('');
// μ΅κ·Ό μλ¬ μμΈ (μ΅λ 5κ°)
lines.push('π μ΅κ·Ό μλ¬ μμΈ:');
report.errors.slice(0, 5).forEach((error, idx) => {
lines.push(` ${idx + 1}. [${formatTimestamp(error.timestamp)}] ${error.message.substring(0, 150)}`);
if (error.resource) {
lines.push(` β 리μμ€: ${error.resource}`);
}
});
if (report.errors.length > 5) {
lines.push(` ... μΈ ${report.errors.length - 5}건`);
}
// hi-ai ννΈ μΆκ°
if (report.hiAiHint) {
lines.push('');
lines.push(report.hiAiHint);
}
return lines.join('\n');
}