mirror of
https://github.com/ktds-dg0501/kt-event-marketing-fe.git
synced 2025-12-06 06:56:24 +00:00
- eventApi에 getAiRecommendations 메서드 추가 - Job COMPLETED 시 Event Service의 공개 API로 추천 결과 조회 - AI Service Internal API 대신 Event Service API 사용 - 타입 정의 통합 및 중복 제거 - 환경변수 포트 설정 수정 (AI_HOST: 8083) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
110 lines
3.0 KiB
TypeScript
110 lines
3.0 KiB
TypeScript
import axios, { AxiosInstance } from 'axios';
|
|
|
|
// AI Service API 클라이언트
|
|
const AI_API_BASE_URL = process.env.NEXT_PUBLIC_AI_HOST || 'http://localhost:8083';
|
|
const API_VERSION = process.env.NEXT_PUBLIC_API_VERSION || 'v1';
|
|
|
|
export const aiApiClient: AxiosInstance = axios.create({
|
|
baseURL: `${AI_API_BASE_URL}/api/${API_VERSION}`,
|
|
timeout: 300000, // AI 생성은 최대 5분
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
withCredentials: false, // CORS 설정
|
|
});
|
|
|
|
// Request interceptor
|
|
aiApiClient.interceptors.request.use(
|
|
(config) => {
|
|
console.log('🤖 AI API Request:', {
|
|
method: config.method?.toUpperCase(),
|
|
url: config.url,
|
|
baseURL: config.baseURL,
|
|
data: config.data,
|
|
});
|
|
|
|
const token = localStorage.getItem('accessToken');
|
|
if (token && config.headers) {
|
|
config.headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
return config;
|
|
},
|
|
(error) => {
|
|
console.error('❌ AI API Request Error:', error);
|
|
return Promise.reject(error);
|
|
}
|
|
);
|
|
|
|
// Response interceptor
|
|
aiApiClient.interceptors.response.use(
|
|
(response) => {
|
|
console.log('✅ AI API Response:', {
|
|
status: response.status,
|
|
url: response.config.url,
|
|
data: response.data,
|
|
});
|
|
return response;
|
|
},
|
|
(error) => {
|
|
console.error('❌ AI API Error:', {
|
|
message: error.message,
|
|
status: error.response?.status,
|
|
url: error.config?.url,
|
|
data: error.response?.data,
|
|
});
|
|
return Promise.reject(error);
|
|
}
|
|
);
|
|
|
|
// Types (eventApi.ts로 이동됨 - import해서 사용)
|
|
|
|
export interface JobStatusResponse {
|
|
jobId: string;
|
|
status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED';
|
|
progress: number;
|
|
message: string;
|
|
eventId?: string;
|
|
createdAt: string;
|
|
startedAt?: string;
|
|
completedAt?: string;
|
|
failedAt?: string;
|
|
errorMessage?: string;
|
|
retryCount?: number;
|
|
processingTimeMs?: number;
|
|
}
|
|
|
|
export interface HealthCheckResponse {
|
|
status: 'UP' | 'DOWN' | 'DEGRADED';
|
|
timestamp: string;
|
|
services: {
|
|
kafka: 'UP' | 'DOWN';
|
|
redis: 'UP' | 'DOWN';
|
|
claude_api: 'UP' | 'DOWN' | 'CIRCUIT_OPEN';
|
|
gpt4_api?: 'UP' | 'DOWN' | 'CIRCUIT_OPEN';
|
|
circuit_breaker: 'CLOSED' | 'OPEN' | 'HALF_OPEN';
|
|
};
|
|
}
|
|
|
|
// API Functions
|
|
export const aiApi = {
|
|
// 헬스체크
|
|
healthCheck: async (): Promise<HealthCheckResponse> => {
|
|
const response = await aiApiClient.get<HealthCheckResponse>('/health');
|
|
return response.data;
|
|
},
|
|
|
|
// Job 상태 조회 (Internal API)
|
|
getJobStatus: async (jobId: string): Promise<JobStatusResponse> => {
|
|
const response = await aiApiClient.get<JobStatusResponse>(`/internal/jobs/${jobId}/status`);
|
|
return response.data;
|
|
},
|
|
|
|
// AI 추천 결과 조회 (Internal API) - Deprecated: eventApi.getAiRecommendations 사용
|
|
// getRecommendations: async (eventId: string): Promise<AiRecommendationResult> => {
|
|
// const response = await aiApiClient.get<AiRecommendationResult>(`/internal/recommendations/${eventId}`);
|
|
// return response.data;
|
|
// },
|
|
};
|
|
|
|
export default aiApi;
|