// Weather Tool - wttr.in integration import type { Env } from '../types'; import { retryWithBackoff } from '../utils/retry'; import { ERROR_MESSAGES } from '../constants/messages'; import { createLogger } from '../utils/logger'; const logger = createLogger('weather'); // wttr.in API 응답 타입 정의 interface WttrCurrentCondition { temp_C: string; FeelsLikeC: string; weatherDesc: Array<{ value: string }>; humidity: string; windspeedKmph: string; winddir16Point: string; uvIndex: string; visibility: string; } interface WttrWeatherDay { date: string; maxtempC: string; mintempC: string; hourly: Array<{ time: string; tempC: string; weatherDesc: Array<{ value: string }>; chanceofrain: string; }>; } interface WttrResponse { current_condition: WttrCurrentCondition[]; weather: WttrWeatherDay[]; nearest_area: Array<{ areaName: Array<{ value: string }>; country: Array<{ value: string }>; }>; } export const weatherTool = { type: 'function', function: { name: 'get_weather', description: '특정 도시의 현재 날씨 정보를 가져옵니다', parameters: { type: 'object', properties: { city: { type: 'string', description: '도시 이름 (예: Seoul, Tokyo, New York)', }, }, required: ['city'], }, }, }; export async function executeWeather(args: { city: string }, env?: Env): Promise { const city = args.city || 'Seoul'; try { const wttrUrl = env?.WTTR_IN_URL || 'https://wttr.in'; const response = await retryWithBackoff( () => fetch(`${wttrUrl}/${encodeURIComponent(city)}?format=j1`), { maxRetries: 2, initialDelayMs: 500 } ); if (!response.ok) { throw new Error(`API 응답 실패: ${response.status}`); } const data = await response.json() as WttrResponse; // 안전한 접근 - 데이터 유효성 확인 if (!data.current_condition?.[0]) { return `${ERROR_MESSAGES.WEATHER_SERVICE_UNAVAILABLE}: ${city}`; } const current = data.current_condition[0]; // weatherDesc 배열 존재 확인 if (!current.weatherDesc?.[0]?.value) { return `날씨 정보가 불완전합니다: ${city}`; } return `🌤 ${city} 날씨 온도: ${current.temp_C}°C (체감 ${current.FeelsLikeC}°C) 상태: ${current.weatherDesc[0].value} 습도: ${current.humidity}% 풍속: ${current.windspeedKmph} km/h`; } catch (error) { logger.error('날씨 조회 실패', error as Error, { city }); return `${ERROR_MESSAGES.WEATHER_SERVICE_UNAVAILABLE}: ${city}`; } }