fetch_news
Fetch news from Arch Linux: get recent news, find critical updates requiring manual intervention, or retrieve news since the last system update.
Instructions
[DISCOVERY] Unified news fetching from Arch Linux. Actions: latest (get recent news), critical (find news requiring manual intervention), since_update (news since last system update). Works on any system for latest/critical, Arch only for since_update.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Type of news query | |
| limit | No | Maximum news items (for latest/critical). Default: 10 | |
| since_date | No | ISO date to filter from (for latest action) |
Implementation Reference
- src/arch_ops_server/news.py:290-316 (handler)The main handler function for fetch_news. Dispatches to get_latest_news, check_critical_news, or get_news_since_last_update based on the 'action' parameter.
async def fetch_news( action: str, limit: int = 10, since_date: Optional[str] = None ) -> Dict[str, Any]: """ Unified news fetching tool. Args: action: "latest", "critical", or "since_update" limit: Maximum number of news items since_date: ISO date string for filtering (for latest action) Returns: News results based on action """ if action == "latest": return await get_latest_news(limit=limit, since_date=since_date) elif action == "critical": return await check_critical_news(limit=limit) elif action == "since_update": return await get_news_since_last_update() else: return create_error_response( "InvalidAction", f"Unknown action: {action}. Use 'latest', 'critical', or 'since_update'" ) - Tool registration and input schema definition for fetch_news. Defines the Tool object with name, description, inputSchema (action enum, limit, since_date), and annotations.
Tool( name="fetch_news", description="[DISCOVERY] Unified news fetching from Arch Linux. Actions: latest (get recent news), critical (find news requiring manual intervention), since_update (news since last system update). Works on any system for latest/critical, Arch only for since_update.", inputSchema={ "type": "object", "properties": { "action": { "type": "string", "enum": ["latest", "critical", "since_update"], "description": "Type of news query" }, "limit": { "type": "integer", "description": "Maximum news items (for latest/critical). Default: 10", "default": 10 }, "since_date": { "type": "string", "description": "ISO date to filter from (for latest action)" } }, "required": ["action"] }, annotations=ToolAnnotations(readOnlyHint=True) ), - src/arch_ops_server/server.py:1223-1228 (registration)Call_tool dispatch for fetch_news. Extracts arguments (action, limit, since_date) and calls the fetch_news async function.
elif name == "fetch_news": action = arguments["action"] limit = arguments.get("limit", 10) since_date = arguments.get("since_date", None) result = await fetch_news(action, limit, since_date) return [TextContent(type="text", text=json.dumps(result, indent=2))] - src/arch_ops_server/news.py:39-143 (helper)get_latest_news - fetches Arch Linux RSS feed, parses XML, filters by date, and returns news items. Called by fetch_news when action='latest'.
async def get_latest_news( limit: int = 10, since_date: Optional[str] = None ) -> Dict[str, Any]: """ Fetch recent Arch Linux news from RSS feed. Args: limit: Maximum number of news items to return (default 10) since_date: Optional date in ISO format (YYYY-MM-DD) to filter news Returns: Dict with news items (title, date, summary, link) """ logger.info(f"Fetching latest Arch Linux news (limit={limit})") try: async with httpx.AsyncClient(timeout=10.0) as client: response = await client.get(ARCH_NEWS_URL) response.raise_for_status() # Parse RSS feed root = ET.fromstring(response.content) # Find all items (RSS 2.0 format) news_items = [] for item in root.findall('.//item')[:limit]: title_elem = item.find('title') link_elem = item.find('link') pub_date_elem = item.find('pubDate') description_elem = item.find('description') if title_elem is None or link_elem is None: continue title = title_elem.text link = link_elem.text pub_date = pub_date_elem.text if pub_date_elem is not None else "" # Parse description and strip HTML tags description = "" if description_elem is not None and description_elem.text: description = re.sub(r'<[^>]+>', '', description_elem.text) # Truncate to first 300 chars for summary description = description[:300] + "..." if len(description) > 300 else description # Parse date published_date = "" if pub_date: try: # Parse RFC 822 date format dt = datetime.strptime(pub_date, "%a, %d %b %Y %H:%M:%S %z") published_date = dt.isoformat() except ValueError: published_date = pub_date # Filter by date if requested if since_date and published_date: try: item_date = datetime.fromisoformat(published_date.replace('Z', '+00:00')) filter_date = datetime.fromisoformat(since_date + "T00:00:00+00:00") if item_date < filter_date: continue except ValueError as e: logger.warning(f"Failed to parse date for filtering: {e}") news_items.append({ "title": title, "link": link, "published": published_date, "summary": description.strip() }) logger.info(f"Successfully fetched {len(news_items)} news items") return { "count": len(news_items), "news": news_items } except httpx.HTTPStatusError as e: logger.error(f"HTTP error fetching news: {e}") return create_error_response( "HTTPError", f"Failed to fetch Arch news: HTTP {e.response.status_code}" ) except httpx.TimeoutException: logger.error("Timeout fetching Arch news") return create_error_response( "Timeout", "Request to Arch news feed timed out" ) except ET.ParseError as e: logger.error(f"Failed to parse RSS feed: {e}") return create_error_response( "ParseError", f"Failed to parse Arch news RSS feed: {str(e)}" ) except Exception as e: logger.error(f"Unexpected error fetching news: {e}") return create_error_response( "NewsError", f"Failed to fetch Arch news: {str(e)}" ) - ToolMetadata entry for fetch_news, defining its category (discovery), platform (any), permission (read), workflow (safety), and related tools.
"fetch_news": ToolMetadata( name="fetch_news", category="discovery", platform="any", permission="read", workflow="safety", related_tools=["check_updates_dry_run"], prerequisite_tools=[] ),