Update README.md
Browse files
README.md
CHANGED
@@ -1,10 +1,422 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Bihar AgMCP - Agricultural Weather Alert System Documentation
|
2 |
+
Table of Contents
|
3 |
+
System Overview
|
4 |
+
Architecture
|
5 |
+
Installation & Setup
|
6 |
+
Core Components
|
7 |
+
Server-side
|
8 |
+
Client-side
|
9 |
+
API Reference
|
10 |
+
Data Models
|
11 |
+
Configuration
|
12 |
+
Deployment
|
13 |
+
Troubleshooting
|
14 |
+
Contributing
|
15 |
+
|
16 |
+
System Overview
|
17 |
+
Purpose
|
18 |
+
The Bihar AgMCP (Agricultural Model Control Protocol) is an AI-powered weather alert system designed to provide personalized agricultural advisories to farmers in Bihar, India. The system generates location-specific weather alerts with crop-specific recommendations.
|
19 |
+
Key Features
|
20 |
+
AI-Enhanced Weather Alerts: OpenAI-powered intelligent alert generation
|
21 |
+
Multi-Channel Communication: SMS, WhatsApp, USSD, IVR, and Telegram support
|
22 |
+
Regional Crop Intelligence: District-specific crop recommendations based on seasons
|
23 |
+
Real-time Weather Data: Integration with multiple weather APIs
|
24 |
+
Geographic Intelligence: Village-level weather data and coordinates
|
25 |
+
Web Interface: User-friendly Gradio interface for easy access
|
26 |
+
CSV Export: Data export functionality for analysis
|
27 |
+
Target Users
|
28 |
+
Agricultural extension workers
|
29 |
+
Farmers and farmer organizations
|
30 |
+
Government agricultural departments
|
31 |
+
Research institutions
|
32 |
+
NGOs working in agriculture
|
33 |
+
|
34 |
+
Architecture
|
35 |
+
System Architecture Diagram
|
36 |
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
37 |
+
│ Weather APIs │ │ OpenAI API │ │ Geographic APIs │
|
38 |
+
│ │ │ │ │ │
|
39 |
+
│ • Open-Meteo │ │ • GPT Models │ │ • Geocoding │
|
40 |
+
│ • Tomorrow.io │ │ • Alert Gen │ │ • Village Data │
|
41 |
+
│ • OpenWeather │ │ │ │ │
|
42 |
+
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
43 |
+
│ │ │
|
44 |
+
└───────────────────────┼───────────────────────┘
|
45 |
+
│
|
46 |
+
┌─────────────────┐
|
47 |
+
│ FastAPI Core │
|
48 |
+
│ │
|
49 |
+
│ • Alert Engine │
|
50 |
+
│ • Crop Calendar │
|
51 |
+
│ • Workflow Mgmt │
|
52 |
+
└─────────────────┘
|
53 |
+
│
|
54 |
+
┌───────────────────────┼───────────────────────┐
|
55 |
+
│ │ │
|
56 |
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
57 |
+
│ A2A Agents │ │ Web Interface │ │ API Clients │
|
58 |
+
│ │ │ │ │ │
|
59 |
+
│ • SMS Agent │ │ • Gradio UI │ │ • MCP Protocol │
|
60 |
+
│ • WhatsApp │ │ • CSV Export │ │ • REST API │
|
61 |
+
│ • USSD/IVR │ │ • District Sel │ │ • JSON-RPC │
|
62 |
+
│ • Telegram │ │ │ │ │
|
63 |
+
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
64 |
+
Technology Stack
|
65 |
+
Backend: FastAPI (Python 3.8+)
|
66 |
+
AI: OpenAI GPT
|
67 |
+
Weather Data: Open-Meteo, Tomorrow.io, OpenWeatherMap
|
68 |
+
Frontend: Gradio
|
69 |
+
Data Processing: Pandas, CSV
|
70 |
+
Async Operations: asyncio
|
71 |
+
Configuration: dotenv
|
72 |
+
Logging: Python logging
|
73 |
+
|
74 |
+
Installation & Setup
|
75 |
+
Prerequisites
|
76 |
+
Python 3.8 or higher
|
77 |
+
pip package manager
|
78 |
+
Internet connection for API access
|
79 |
+
Environment Setup
|
80 |
+
Clone the repository
|
81 |
+
git clone <repository-url>
|
82 |
+
cd bihar-agmcp
|
83 |
+
Install dependencies
|
84 |
+
pip install fastapi uvicorn gradio pandas python-dotenv pydantic
|
85 |
+
Create environment file Create a .env file in the root directory:
|
86 |
+
# Required
|
87 |
+
OPENAI_API_KEY=your_openai_api_key_here
|
88 |
+
|
89 |
+
# Optional Weather APIs
|
90 |
+
TOMORROW_IO_API_KEY=your_tomorrow_io_key
|
91 |
+
GOOGLE_WEATHER_API_KEY=your_google_weather_key
|
92 |
+
OPENWEATHERMAP_API_KEY=your_openweathermap_key
|
93 |
+
ACCUWEATHER_API_KEY=your_accuweather_key
|
94 |
+
|
95 |
+
# Logging
|
96 |
+
LOG_LEVEL=INFO
|
97 |
+
Tool dependencies Ensure the following modules are available:
|
98 |
+
tools/ - Weather and geographic tools
|
99 |
+
a2a_agents/ - Communication agents
|
100 |
+
utils/ - Utility functions
|
101 |
+
Quick Start
|
102 |
+
python main.py
|
103 |
+
|
104 |
+
Core Components
|
105 |
+
1. Server-side
|
106 |
+
Alert Generation Engine
|
107 |
+
Primary Function: generate_dynamic_alert(district, state)
|
108 |
+
Generates comprehensive weather alerts for specific districts.
|
109 |
+
Process Flow:
|
110 |
+
Village Selection: Randomly selects a village from the district
|
111 |
+
Coordinate Resolution: Gets GPS coordinates for location
|
112 |
+
Crop Intelligence: Selects appropriate crop based on:
|
113 |
+
Current season (Kharif/Rabi/Zaid)
|
114 |
+
District crop preferences
|
115 |
+
Regional agricultural patterns
|
116 |
+
Weather Data Collection: Fetches weather data from APIs
|
117 |
+
Alert Generation: Creates weather-based alerts
|
118 |
+
AI Enhancement: Applies OpenAI analysis (if available)
|
119 |
+
Example Usage:
|
120 |
+
alert_data = await generate_dynamic_alert("Patna", "Bihar")
|
121 |
+
b. Crop Calendar System
|
122 |
+
Crop Definitions
|
123 |
+
The system includes detailed crop calendars for major Bihar crops:
|
124 |
+
Rice (Kharif): June-July planting, October-November harvest
|
125 |
+
Wheat (Rabi): November-December planting, March-April harvest
|
126 |
+
Maize (Kharif/Zaid): Dual season crop
|
127 |
+
Sugarcane (Annual): February-March planting
|
128 |
+
Mustard (Rabi): October-November planting
|
129 |
+
District Crop Mapping
|
130 |
+
Each district has specific crop preferences:
|
131 |
+
DISTRICT_CROPS = {
|
132 |
+
'patna': {
|
133 |
+
'primary': ['rice', 'wheat', 'potato'],
|
134 |
+
'secondary': ['mustard', 'gram'],
|
135 |
+
'specialty': ['sugarcane']
|
136 |
+
},
|
137 |
+
# ... other districts
|
138 |
+
}
|
139 |
+
c. Weather Integration
|
140 |
+
Supported Weather APIs
|
141 |
+
Open-Meteo (Primary): Free, reliable weather data
|
142 |
+
Tomorrow.io: Professional weather services
|
143 |
+
OpenWeatherMap: Popular weather API
|
144 |
+
AccuWeather: Commercial weather data
|
145 |
+
Google Weather: Google's weather services
|
146 |
+
Weather Alert Types
|
147 |
+
Heavy Rain Warning: >25mm rainfall expected
|
148 |
+
Moderate Rain Warning: 10-25mm rainfall expected
|
149 |
+
Heat/Drought Warning: High temperature + low rainfall
|
150 |
+
Cold Warning: Temperature <10°C
|
151 |
+
High Wind Warning: Wind speed >30 km/h
|
152 |
+
Weather Update: Normal conditions
|
153 |
+
2. Client-side
|
154 |
+
A2A Communication Agents
|
155 |
+
SMS Agent
|
156 |
+
Creates concise SMS messages (160 characters max):
|
157 |
+
def create_sms_message(alert_data):
|
158 |
+
return f"BIHAR ALERT: {crop} in {location} - {weather_summary}"
|
159 |
+
WhatsApp Agent
|
160 |
+
Generates rich WhatsApp messages with emojis and formatting:
|
161 |
+
def create_whatsapp_message(alert_data):
|
162 |
+
return {
|
163 |
+
"text": formatted_message,
|
164 |
+
"buttons": action_buttons
|
165 |
+
}
|
166 |
+
USSD Agent
|
167 |
+
Creates interactive USSD menu structures:
|
168 |
+
def create_ussd_menu(alert_data):
|
169 |
+
return {
|
170 |
+
"menu": "CON Weather Alert...\n1. Details\n2. Actions"
|
171 |
+
}
|
172 |
+
IVR Agent
|
173 |
+
Generates voice script for phone systems:
|
174 |
+
def create_ivr_script(alert_data):
|
175 |
+
return {
|
176 |
+
"script": "Welcome to Bihar weather alert...",
|
177 |
+
"menu_options": [...]
|
178 |
+
}
|
179 |
+
Telegram Agent
|
180 |
+
Creates Telegram messages with inline keyboards:
|
181 |
+
def create_telegram_message(alert_data):
|
182 |
+
return {
|
183 |
+
"text": message,
|
184 |
+
"reply_markup": inline_keyboard
|
185 |
+
}
|
186 |
+
|
187 |
+
API Reference
|
188 |
+
Core Endpoints
|
189 |
+
1. Workflow Execution
|
190 |
+
POST /api/run-workflow
|
191 |
+
Request Body:
|
192 |
+
{
|
193 |
+
"state": "bihar",
|
194 |
+
"district": "patna"
|
195 |
+
}
|
196 |
+
Response:
|
197 |
+
{
|
198 |
+
"message": "workflow_results",
|
199 |
+
"status": "success",
|
200 |
+
"csv": "csv_data",
|
201 |
+
"raw_data": {
|
202 |
+
"alert_data": {...},
|
203 |
+
"agent_responses": {...}
|
204 |
+
}
|
205 |
+
}
|
206 |
+
2. Health Check
|
207 |
+
GET /api/health
|
208 |
+
Response:
|
209 |
+
{
|
210 |
+
"status": "healthy",
|
211 |
+
"openai_available": true,
|
212 |
+
"timestamp": "2025-08-13T10:30:00"
|
213 |
+
}
|
214 |
+
3. MCP Tool Execution
|
215 |
+
POST /mcp
|
216 |
+
Request Body:
|
217 |
+
{
|
218 |
+
"tool": "get_current_weather",
|
219 |
+
"parameters": {
|
220 |
+
"latitude": 25.5941,
|
221 |
+
"longitude": 85.1376
|
222 |
+
}
|
223 |
+
}
|
224 |
+
4. Geographic Data
|
225 |
+
GET /api/districts/{state}
|
226 |
+
GET /api/villages/{state}/{district}
|
227 |
+
5. Weather Data
|
228 |
+
GET /api/weather/{latitude}/{longitude}
|
229 |
+
A2A Agent Endpoints
|
230 |
+
SMS
|
231 |
+
POST /a2a/sms
|
232 |
+
WhatsApp
|
233 |
+
POST /a2a/whatsapp
|
234 |
+
USSD
|
235 |
+
POST /a2a/ussd
|
236 |
+
IVR
|
237 |
+
POST /a2a/ivr
|
238 |
+
Telegram
|
239 |
+
POST /a2a/telegram
|
240 |
+
|
241 |
+
Data Models
|
242 |
+
AlertRequest
|
243 |
+
class AlertRequest(BaseModel):
|
244 |
+
alert_json: dict
|
245 |
+
WorkflowRequest
|
246 |
+
class WorkflowRequest(BaseModel):
|
247 |
+
state: str
|
248 |
+
district: str
|
249 |
+
MCPRequest
|
250 |
+
class MCPRequest(BaseModel):
|
251 |
+
tool: str
|
252 |
+
parameters: dict
|
253 |
+
Alert Data Structure
|
254 |
+
{
|
255 |
+
"alert_id": "BH_PAT_VIL_20250813_103000",
|
256 |
+
"timestamp": "2025-08-13T10:30:00Z",
|
257 |
+
"location": {
|
258 |
+
"village": "Danapur",
|
259 |
+
"district": "Patna",
|
260 |
+
"state": "Bihar",
|
261 |
+
"coordinates": [25.5941, 85.1376],
|
262 |
+
"coordinates_source": "village_danapur"
|
263 |
+
},
|
264 |
+
"crop": {
|
265 |
+
"name": "rice",
|
266 |
+
"stage": "Tillering",
|
267 |
+
"season": "kharif",
|
268 |
+
"planted_estimate": "2025-06-15"
|
269 |
+
},
|
270 |
+
"alert": {
|
271 |
+
"type": "heavy_rain_warning",
|
272 |
+
"urgency": "high",
|
273 |
+
"message": "Heavy rainfall expected...",
|
274 |
+
"action_items": ["delay_fertilizer", "check_drainage"],
|
275 |
+
"ai_generated": true
|
276 |
+
},
|
277 |
+
"weather": {
|
278 |
+
"temperature": "28.5°C",
|
279 |
+
"expected_rainfall": "35.2mm",
|
280 |
+
"wind_speed": "15.3 km/h",
|
281 |
+
"rain_probability": "85%"
|
282 |
+
}
|
283 |
+
}
|
284 |
+
|
285 |
+
Configuration
|
286 |
+
Environment Variables
|
287 |
+
Required
|
288 |
+
OPENAI_API_KEY: OpenAI API key for AI features
|
289 |
+
Optional
|
290 |
+
TOMORROW_IO_API_KEY: Tomorrow.io weather API
|
291 |
+
GOOGLE_WEATHER_API_KEY: Google Weather API
|
292 |
+
OPENWEATHERMAP_API_KEY: OpenWeatherMap API
|
293 |
+
ACCUWEATHER_API_KEY: AccuWeather API
|
294 |
+
LOG_LEVEL: Logging level (DEBUG, INFO, WARNING, ERROR)
|
295 |
+
CORS Configuration
|
296 |
+
app.add_middleware(
|
297 |
+
CORSMiddleware,
|
298 |
+
allow_origins=["https://mcp-ui.vercel.app", "*"],
|
299 |
+
allow_credentials=True,
|
300 |
+
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
301 |
+
allow_headers=["*"]
|
302 |
+
)
|
303 |
+
Bihar Districts Configuration
|
304 |
+
The system supports 39 Bihar districts:
|
305 |
+
Patna, Gaya, Bhagalpur, Muzaffarpur, Darbhanga
|
306 |
+
Siwan, Begusarai, Katihar, Nalanda, Rohtas
|
307 |
+
And 29 others...
|
308 |
+
|
309 |
+
Deployment
|
310 |
+
Local Development
|
311 |
+
python main.py
|
312 |
+
FastAPI server: http://localhost:8000
|
313 |
+
Gradio interface: http://localhost:7860
|
314 |
+
Production Deployment
|
315 |
+
Docker Deployment
|
316 |
+
FROM python:3.9-slim
|
317 |
+
|
318 |
+
WORKDIR /app
|
319 |
+
COPY requirements.txt .
|
320 |
+
RUN pip install -r requirements.txt
|
321 |
+
|
322 |
+
COPY . .
|
323 |
+
EXPOSE 8000 7860
|
324 |
+
|
325 |
+
CMD ["python", "main.py"]
|
326 |
+
HuggingFace Spaces
|
327 |
+
The application automatically detects HuggingFace Spaces environment and configures accordingly:
|
328 |
+
if os.getenv("SPACE_ID") or os.getenv("GRADIO_SERVER_NAME"):
|
329 |
+
# HuggingFace Spaces mode
|
330 |
+
fastapi_thread = threading.Thread(target=run_fastapi, daemon=True)
|
331 |
+
fastapi_thread.start()
|
332 |
+
demo.launch(server_name="0.0.0.0", server_port=7860)
|
333 |
+
|
334 |
+
|
335 |
+
|
336 |
+
Troubleshooting
|
337 |
+
Common Issues
|
338 |
+
1. OpenAI API Key Missing
|
339 |
+
Error: OpenAI API key not found - AI features will be limited Solution: Add OPENAI_API_KEY to .env file
|
340 |
+
2. Weather API Failures
|
341 |
+
Error: Failed to get weather data Solutions:
|
342 |
+
Check internet connectivity
|
343 |
+
Verify API keys in .env
|
344 |
+
Check API quotas and limits
|
345 |
+
3. Geographic Data Issues
|
346 |
+
Error: District 'xyz' not found in Bihar Solutions:
|
347 |
+
Use correct district spelling
|
348 |
+
Check district name in BIHAR_DISTRICTS list
|
349 |
+
Verify state parameter is "bihar"
|
350 |
+
4. Import Errors
|
351 |
+
Error: ModuleNotFoundError: No module named 'tools' Solution: Ensure all required modules are in the project directory:
|
352 |
+
tools/
|
353 |
+
a2a_agents/
|
354 |
+
utils/
|
355 |
+
Logging and Debugging
|
356 |
+
Enable Debug Logging
|
357 |
+
export LOG_LEVEL=DEBUG
|
358 |
+
python main.py
|
359 |
+
Check Log Output
|
360 |
+
logger.info(f"Selected village: {village}")
|
361 |
+
logger.error(f"Weather API error: {error}")
|
362 |
+
Performance Optimization
|
363 |
+
1. API Response Caching
|
364 |
+
Consider implementing Redis caching for weather data:
|
365 |
+
# Pseudo-code
|
366 |
+
@cache.cached(timeout=300) # 5 minute cache
|
367 |
+
async def get_weather_data(lat, lon):
|
368 |
+
return await weather_api.fetch(lat, lon)
|
369 |
+
2. Database Integration
|
370 |
+
For production, consider using PostgreSQL/MongoDB:
|
371 |
+
# Store alert history
|
372 |
+
await db.alerts.insert_one(alert_data)
|
373 |
+
|
374 |
+
Contributing
|
375 |
+
Development Guidelines
|
376 |
+
1. Code Style
|
377 |
+
Follow PEP 8 Python style guide
|
378 |
+
Use type hints for function parameters
|
379 |
+
Add docstrings for all functions
|
380 |
+
Maximum line length: 100 characters
|
381 |
+
2. Testing
|
382 |
+
import pytest
|
383 |
+
|
384 |
+
def test_crop_selection():
|
385 |
+
crop = select_regional_crop("patna", "bihar")
|
386 |
+
assert crop in ["rice", "wheat", "potato"]
|
387 |
+
|
388 |
+
async def test_weather_api():
|
389 |
+
result = await open_meteo.get_current_weather(25.5941, 85.1376)
|
390 |
+
assert "temperature" in result
|
391 |
+
3. Documentation
|
392 |
+
Update this documentation for new features
|
393 |
+
Add inline comments for complex logic
|
394 |
+
Create examples for new API endpoints
|
395 |
+
4. Version Control
|
396 |
+
git checkout -b feature/new-weather-provider
|
397 |
+
git commit -m "Add new weather API integration"
|
398 |
+
git push origin feature/new-weather-provider
|
399 |
+
Adding New Features
|
400 |
+
1. New Weather Provider
|
401 |
+
# tools/new_weather_api.py
|
402 |
+
async def get_current_weather(latitude, longitude, api_key):
|
403 |
+
# Implementation
|
404 |
+
return weather_data
|
405 |
+
2. New Communication Channel
|
406 |
+
# a2a_agents/slack_agent.py
|
407 |
+
def create_slack_message(alert_data):
|
408 |
+
return {
|
409 |
+
"text": message,
|
410 |
+
"attachments": []
|
411 |
+
}
|
412 |
+
3. New Crop Types
|
413 |
+
CROP_CALENDAR["new_crop"] = {
|
414 |
+
"season": "Rabi",
|
415 |
+
"planting": "December",
|
416 |
+
"harvesting": "May",
|
417 |
+
"duration_days": 150,
|
418 |
+
"stages": ["Sowing", "Growth", "Harvest"]
|
419 |
+
}
|
420 |
+
|
421 |
+
|
422 |
+
Last Updated: August 13, 2025.
|