webscout 7.4__py3-none-any.whl → 7.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of webscout might be problematic. Click here for more details.

Files changed (137) hide show
  1. webscout/AIauto.py +5 -53
  2. webscout/AIutel.py +8 -318
  3. webscout/DWEBS.py +460 -489
  4. webscout/Extra/YTToolkit/YTdownloader.py +14 -53
  5. webscout/Extra/YTToolkit/transcriber.py +12 -13
  6. webscout/Extra/YTToolkit/ytapi/video.py +0 -1
  7. webscout/Extra/__init__.py +0 -1
  8. webscout/Extra/autocoder/autocoder_utiles.py +0 -4
  9. webscout/Extra/autocoder/rawdog.py +13 -41
  10. webscout/Extra/gguf.py +652 -428
  11. webscout/Extra/weather.py +178 -156
  12. webscout/Extra/weather_ascii.py +70 -17
  13. webscout/Litlogger/core/logger.py +1 -2
  14. webscout/Litlogger/handlers/file.py +1 -1
  15. webscout/Litlogger/styles/formats.py +0 -2
  16. webscout/Litlogger/utils/detectors.py +0 -1
  17. webscout/Provider/AISEARCH/DeepFind.py +0 -1
  18. webscout/Provider/AISEARCH/ISou.py +1 -1
  19. webscout/Provider/AISEARCH/felo_search.py +0 -1
  20. webscout/Provider/AllenAI.py +24 -9
  21. webscout/Provider/C4ai.py +432 -0
  22. webscout/Provider/ChatGPTGratis.py +24 -56
  23. webscout/Provider/Cloudflare.py +18 -21
  24. webscout/Provider/DeepSeek.py +27 -48
  25. webscout/Provider/Deepinfra.py +129 -53
  26. webscout/Provider/Gemini.py +1 -1
  27. webscout/Provider/GithubChat.py +362 -0
  28. webscout/Provider/Glider.py +25 -8
  29. webscout/Provider/HF_space/qwen_qwen2.py +2 -2
  30. webscout/Provider/HeckAI.py +38 -5
  31. webscout/Provider/HuggingFaceChat.py +462 -0
  32. webscout/Provider/Jadve.py +20 -5
  33. webscout/Provider/Marcus.py +7 -50
  34. webscout/Provider/Netwrck.py +43 -67
  35. webscout/Provider/PI.py +4 -2
  36. webscout/Provider/Perplexitylabs.py +26 -6
  37. webscout/Provider/Phind.py +29 -3
  38. webscout/Provider/PizzaGPT.py +10 -51
  39. webscout/Provider/TTI/AiForce/async_aiforce.py +4 -37
  40. webscout/Provider/TTI/AiForce/sync_aiforce.py +41 -38
  41. webscout/Provider/TTI/FreeAIPlayground/__init__.py +9 -9
  42. webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +206 -206
  43. webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +192 -192
  44. webscout/Provider/TTI/MagicStudio/__init__.py +2 -0
  45. webscout/Provider/TTI/MagicStudio/async_magicstudio.py +111 -0
  46. webscout/Provider/TTI/MagicStudio/sync_magicstudio.py +109 -0
  47. webscout/Provider/TTI/PollinationsAI/async_pollinations.py +5 -24
  48. webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +2 -22
  49. webscout/Provider/TTI/__init__.py +2 -3
  50. webscout/Provider/TTI/aiarta/__init__.py +2 -0
  51. webscout/Provider/TTI/aiarta/async_aiarta.py +482 -0
  52. webscout/Provider/TTI/aiarta/sync_aiarta.py +440 -0
  53. webscout/Provider/TTI/fastflux/__init__.py +22 -0
  54. webscout/Provider/TTI/fastflux/async_fastflux.py +257 -0
  55. webscout/Provider/TTI/fastflux/sync_fastflux.py +247 -0
  56. webscout/Provider/TTS/__init__.py +2 -2
  57. webscout/Provider/TTS/deepgram.py +12 -39
  58. webscout/Provider/TTS/elevenlabs.py +14 -40
  59. webscout/Provider/TTS/gesserit.py +11 -35
  60. webscout/Provider/TTS/murfai.py +13 -39
  61. webscout/Provider/TTS/parler.py +17 -40
  62. webscout/Provider/TTS/speechma.py +180 -0
  63. webscout/Provider/TTS/streamElements.py +17 -44
  64. webscout/Provider/TextPollinationsAI.py +39 -59
  65. webscout/Provider/Venice.py +217 -200
  66. webscout/Provider/WiseCat.py +27 -5
  67. webscout/Provider/Youchat.py +63 -36
  68. webscout/Provider/__init__.py +13 -8
  69. webscout/Provider/akashgpt.py +28 -10
  70. webscout/Provider/copilot.py +416 -0
  71. webscout/Provider/flowith.py +196 -0
  72. webscout/Provider/freeaichat.py +32 -45
  73. webscout/Provider/granite.py +17 -53
  74. webscout/Provider/koala.py +20 -5
  75. webscout/Provider/llamatutor.py +7 -47
  76. webscout/Provider/llmchat.py +36 -53
  77. webscout/Provider/multichat.py +92 -98
  78. webscout/Provider/talkai.py +1 -0
  79. webscout/Provider/turboseek.py +3 -0
  80. webscout/Provider/tutorai.py +2 -0
  81. webscout/Provider/typegpt.py +154 -64
  82. webscout/Provider/x0gpt.py +3 -1
  83. webscout/Provider/yep.py +102 -20
  84. webscout/__init__.py +3 -0
  85. webscout/cli.py +4 -40
  86. webscout/conversation.py +1 -10
  87. webscout/exceptions.py +19 -9
  88. webscout/litagent/__init__.py +2 -2
  89. webscout/litagent/agent.py +351 -20
  90. webscout/litagent/constants.py +34 -5
  91. webscout/litprinter/__init__.py +0 -3
  92. webscout/models.py +181 -0
  93. webscout/optimizers.py +1 -1
  94. webscout/prompt_manager.py +2 -8
  95. webscout/scout/core/scout.py +1 -4
  96. webscout/scout/core/search_result.py +1 -1
  97. webscout/scout/core/text_utils.py +1 -1
  98. webscout/scout/core.py +2 -5
  99. webscout/scout/element.py +1 -1
  100. webscout/scout/parsers/html_parser.py +1 -1
  101. webscout/scout/utils.py +0 -1
  102. webscout/swiftcli/__init__.py +1 -3
  103. webscout/tempid.py +1 -1
  104. webscout/update_checker.py +55 -95
  105. webscout/version.py +1 -1
  106. webscout/webscout_search_async.py +1 -2
  107. webscout/yep_search.py +297 -297
  108. webscout-7.6.dist-info/LICENSE.md +146 -0
  109. {webscout-7.4.dist-info → webscout-7.6.dist-info}/METADATA +104 -514
  110. {webscout-7.4.dist-info → webscout-7.6.dist-info}/RECORD +113 -120
  111. webscout/Extra/autollama.py +0 -231
  112. webscout/Local/__init__.py +0 -10
  113. webscout/Local/_version.py +0 -3
  114. webscout/Local/formats.py +0 -747
  115. webscout/Local/model.py +0 -1368
  116. webscout/Local/samplers.py +0 -125
  117. webscout/Local/thread.py +0 -539
  118. webscout/Local/ui.py +0 -401
  119. webscout/Local/utils.py +0 -388
  120. webscout/Provider/Amigo.py +0 -274
  121. webscout/Provider/Bing.py +0 -243
  122. webscout/Provider/DiscordRocks.py +0 -253
  123. webscout/Provider/TTI/blackbox/__init__.py +0 -4
  124. webscout/Provider/TTI/blackbox/async_blackbox.py +0 -212
  125. webscout/Provider/TTI/blackbox/sync_blackbox.py +0 -199
  126. webscout/Provider/TTI/deepinfra/__init__.py +0 -4
  127. webscout/Provider/TTI/deepinfra/async_deepinfra.py +0 -227
  128. webscout/Provider/TTI/deepinfra/sync_deepinfra.py +0 -199
  129. webscout/Provider/TTI/imgninza/__init__.py +0 -4
  130. webscout/Provider/TTI/imgninza/async_ninza.py +0 -214
  131. webscout/Provider/TTI/imgninza/sync_ninza.py +0 -209
  132. webscout/Provider/TTS/voicepod.py +0 -117
  133. webscout/Provider/dgaf.py +0 -214
  134. webscout-7.4.dist-info/LICENSE.md +0 -211
  135. {webscout-7.4.dist-info → webscout-7.6.dist-info}/WHEEL +0 -0
  136. {webscout-7.4.dist-info → webscout-7.6.dist-info}/entry_points.txt +0 -0
  137. {webscout-7.4.dist-info → webscout-7.6.dist-info}/top_level.txt +0 -0
webscout/Extra/weather.py CHANGED
@@ -1,172 +1,194 @@
1
+ """
2
+ Weather information module with a clean, strongly-typed API structure.
3
+
4
+ This module provides a simple client for fetching weather data
5
+ from the wttr.in service with proper typing and a consistent interface.
6
+ """
7
+
1
8
  import requests
2
- import json
3
9
  from datetime import datetime
4
- from rich.console import Console
5
- from rich.table import Table
6
- from rich.panel import Panel
7
- from rich.layout import Layout
8
- from rich.align import Align
9
- from rich import box
10
- from rich.live import Live
11
- from rich.progress import Progress, SpinnerColumn, TextColumn
12
- from rich.style import Style
13
- from rich.text import Text
14
- from rich.columns import Columns
15
-
16
- # Initialize Rich console with force terminal
17
- console = Console(force_terminal=True)
18
-
19
- def get_emoji(condition: str) -> str:
20
- """Get appropriate emoji for weather condition"""
21
- conditions = {
22
- 'sunny': '*', 'clear': '*',
23
- 'partly cloudy': '~', 'cloudy': '=',
24
- 'rain': 'v', 'light rain': '.',
25
- 'heavy rain': 'V', 'thunderstorm': 'V',
26
- 'snow': '*', 'light snow': '*',
27
- 'mist': '-', 'fog': '-',
28
- 'overcast': '='
29
- }
30
- condition = condition.lower()
31
- for key, symbol in conditions.items():
32
- if key in condition:
33
- return symbol
34
- return '~'
35
-
36
- def get_wind_arrow(degrees: int) -> str:
37
- """Convert wind degrees to arrow"""
38
- arrows = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']
39
- index = round(degrees / 45) % 8
40
- return arrows[index]
41
-
42
- def format_temp(temp: str, scale='C') -> Text:
43
- """Format temperature with color based on value"""
44
- try:
45
- value = float(temp)
46
- if scale == 'C':
47
- if value <= 0:
48
- return Text(f"{temp}°{scale}", style="bold blue")
49
- elif value >= 30:
50
- return Text(f"{temp}°{scale}", style="bold red")
51
- else:
52
- return Text(f"{temp}°{scale}", style="bold green")
53
- except ValueError:
54
- pass
55
- return Text(f"{temp}°{scale}")
56
-
57
- def create_current_weather_panel(data):
58
- """Create panel for current weather"""
59
- current = data['current_condition'][0]
60
- location = data['nearest_area'][0]
61
- location_name = f"{location['areaName'][0]['value']}, {location['country'][0]['value']}"
62
-
63
- weather_desc = current['weatherDesc'][0]['value']
64
- symbol = get_emoji(weather_desc)
10
+ from typing import List, Dict, Any, Optional
11
+
12
+
13
+ class CurrentCondition:
14
+ """Current weather conditions with strongly typed properties."""
65
15
 
66
- # Create weather info table
67
- table = Table(show_header=False, box=box.ROUNDED, expand=True)
68
- table.add_column("Label", style="cyan")
69
- table.add_column("Value", justify="right")
16
+ def __init__(self, data: Dict[str, Any]) -> None:
17
+ """Initialize with current condition data.
18
+
19
+ Args:
20
+ data: Current condition data dictionary from wttr.in
21
+ """
22
+ self.temp_c: Optional[str] = data.get('temp_C')
23
+ self.temp_f: Optional[str] = data.get('temp_F')
24
+ self.feels_like_c: Optional[str] = data.get('FeelsLikeC')
25
+ self.feels_like_f: Optional[str] = data.get('FeelsLikeF')
26
+ self.weather_desc: str = data.get('weatherDesc', [{}])[0].get('value', '')
27
+ self.weather_code: Optional[str] = data.get('weatherCode')
28
+ self.humidity: Optional[str] = data.get('humidity')
29
+ self.visibility: Optional[str] = data.get('visibility')
30
+ self.pressure: Optional[str] = data.get('pressure')
31
+ self.wind_speed_kmph: Optional[str] = data.get('windspeedKmph')
32
+ self.wind_direction: Optional[str] = data.get('winddir16Point')
33
+ self.wind_degree: Optional[str] = data.get('winddirDegree')
34
+
35
+
36
+ class Location:
37
+ """Location information with strongly typed properties."""
70
38
 
71
- table.add_row("Location", f"@ {location_name}")
72
- table.add_row("Condition", f"{symbol} {weather_desc}")
73
- table.add_row("Temperature",
74
- f"{format_temp(current['temp_C'])} / {format_temp(current['temp_F'], 'F')}")
75
- table.add_row("Feels Like",
76
- f"{format_temp(current['FeelsLikeC'])} / {format_temp(current['FeelsLikeF'], 'F')}")
77
- table.add_row("Humidity", f"~ {current['humidity']}%")
39
+ def __init__(self, data: Dict[str, Any]) -> None:
40
+ """Initialize with location data.
41
+
42
+ Args:
43
+ data: Location data dictionary from wttr.in
44
+ """
45
+ self.name: str = data.get('areaName', [{}])[0].get('value', '')
46
+ self.country: str = data.get('country', [{}])[0].get('value', '')
47
+ self.region: str = data.get('region', [{}])[0].get('value', '')
48
+ self.latitude: Optional[str] = data.get('latitude')
49
+ self.longitude: Optional[str] = data.get('longitude')
50
+
51
+
52
+ class HourlyForecast:
53
+ """Hourly forecast information with strongly typed properties."""
78
54
 
79
- wind_dir = get_wind_arrow(int(current['winddirDegree']))
80
- table.add_row("Wind",
81
- f"> {current['windspeedKmph']} km/h {wind_dir} ({current['winddir16Point']})")
82
- table.add_row("Visibility", f"O {current['visibility']} km")
83
- table.add_row("Pressure", f"# {current['pressure']} mb")
55
+ def __init__(self, data: Dict[str, Any]) -> None:
56
+ """Initialize with hourly forecast data.
57
+
58
+ Args:
59
+ data: Hourly forecast data dictionary from wttr.in
60
+ """
61
+ self.time: Optional[str] = data.get('time')
62
+ self.temp_c: Optional[str] = data.get('tempC')
63
+ self.temp_f: Optional[str] = data.get('tempF')
64
+ self.weather_desc: str = data.get('weatherDesc', [{}])[0].get('value', '')
65
+ self.weather_code: Optional[str] = data.get('weatherCode')
66
+ self.wind_speed_kmph: Optional[str] = data.get('windspeedKmph')
67
+ self.wind_direction: Optional[str] = data.get('winddir16Point')
68
+ self.feels_like_c: Optional[str] = data.get('FeelsLikeC')
69
+ self.feels_like_f: Optional[str] = data.get('FeelsLikeF')
70
+ self.chance_of_rain: Optional[str] = data.get('chanceofrain')
71
+ self.chance_of_snow: Optional[str] = data.get('chanceofsnow')
72
+
73
+
74
+ class DayForecast:
75
+ """Daily forecast information with strongly typed properties."""
84
76
 
85
- return Panel(table, title="[bold]Current Weather[/]", border_style="blue")
86
-
87
- def create_forecast_panel(data):
88
- """Create panel for weather forecast"""
89
- table = Table(show_header=True, box=box.ROUNDED, expand=True)
90
- table.add_column("Date", style="cyan")
91
- table.add_column("Condition")
92
- table.add_column("Temp (°C)")
93
- table.add_column("Rain")
94
- table.add_column("Wind")
77
+ def __init__(self, data: Dict[str, Any]) -> None:
78
+ """Initialize with daily forecast data.
79
+
80
+ Args:
81
+ data: Daily forecast data dictionary from wttr.in
82
+ """
83
+ self.date: Optional[str] = data.get('date')
84
+ self.date_formatted: Optional[str] = None
85
+ if self.date:
86
+ try:
87
+ self.date_formatted = datetime.strptime(self.date, '%Y-%m-%d').strftime('%a, %b %d')
88
+ except ValueError:
89
+ pass
90
+
91
+ self.max_temp_c: Optional[str] = data.get('maxtempC')
92
+ self.max_temp_f: Optional[str] = data.get('maxtempF')
93
+ self.min_temp_c: Optional[str] = data.get('mintempC')
94
+ self.min_temp_f: Optional[str] = data.get('mintempF')
95
+ self.avg_temp_c: Optional[str] = data.get('avgtempC')
96
+ self.avg_temp_f: Optional[str] = data.get('avgtempF')
97
+ self.sun_hour: Optional[str] = data.get('sunHour')
98
+
99
+ # Parse astronomy data (simplified)
100
+ if data.get('astronomy') and len(data.get('astronomy', [])) > 0:
101
+ astro = data.get('astronomy', [{}])[0]
102
+ self.sunrise: Optional[str] = astro.get('sunrise')
103
+ self.sunset: Optional[str] = astro.get('sunset')
104
+ self.moon_phase: Optional[str] = astro.get('moon_phase')
105
+ else:
106
+ self.sunrise = self.sunset = self.moon_phase = None
107
+
108
+ # Parse hourly forecasts
109
+ self.hourly: List[HourlyForecast] = []
110
+ for hour_data in data.get('hourly', []):
111
+ self.hourly.append(HourlyForecast(hour_data))
112
+
113
+
114
+ class Weather:
115
+ """Weather response object with strongly typed properties."""
95
116
 
96
- for day in data['weather'][:3]:
97
- date = datetime.strptime(day['date'], '%Y-%m-%d').strftime('%a, %b %d')
98
- # Get mid-day conditions (noon)
99
- noon = day['hourly'][4]
100
- condition = noon['weatherDesc'][0]['value']
101
- symbol = get_emoji(condition)
102
- temp_range = f"{day['mintempC']}° - {day['maxtempC']}°"
103
- rain_chance = f"v {noon['chanceofrain']}%"
104
- wind = f"> {noon['windspeedKmph']} km/h"
117
+ def __init__(self, data: Optional[Dict[str, Any]] = None) -> None:
118
+ """Initialize with weather data.
105
119
 
106
- table.add_row(
107
- date,
108
- f"{symbol} {condition}",
109
- temp_range,
110
- rain_chance,
111
- wind
112
- )
120
+ Args:
121
+ data: Weather data dictionary from wttr.in
122
+ """
123
+ if not data:
124
+ self.current_condition = None
125
+ self.location = None
126
+ self.forecast_days = []
127
+ return
128
+
129
+ # Parse current condition
130
+ self.current_condition: Optional[CurrentCondition] = None
131
+ if data.get('current_condition') and len(data.get('current_condition', [])) > 0:
132
+ self.current_condition = CurrentCondition(data.get('current_condition', [{}])[0])
133
+
134
+ # Parse location
135
+ self.location: Optional[Location] = None
136
+ if data.get('nearest_area') and len(data.get('nearest_area', [])) > 0:
137
+ self.location = Location(data.get('nearest_area', [{}])[0])
138
+
139
+ # Parse forecast days
140
+ self.forecast_days: List[DayForecast] = []
141
+ for day_data in data.get('weather', []):
142
+ self.forecast_days.append(DayForecast(day_data))
143
+
144
+ @property
145
+ def today(self) -> Optional[DayForecast]:
146
+ """Get today's forecast."""
147
+ return self.forecast_days[0] if self.forecast_days else None
148
+
149
+ @property
150
+ def tomorrow(self) -> Optional[DayForecast]:
151
+ """Get tomorrow's forecast."""
152
+ return self.forecast_days[1] if len(self.forecast_days) > 1 else None
153
+
154
+ @property
155
+ def summary(self) -> str:
156
+ """Get a simple text summary of current weather."""
157
+ if not self.current_condition or not self.location:
158
+ return "Weather data not available"
159
+
160
+ return f"{self.location.name}, {self.location.country}: {self.current_condition.weather_desc}, {self.current_condition.temp_c}°C ({self.current_condition.temp_f}°F)"
161
+
162
+
163
+ class WeatherClient:
164
+ """Client for fetching weather information."""
113
165
 
114
- return Panel(table, title="[bold]3-Day Forecast[/]", border_style="blue")
115
-
116
- def get(location: str):
117
- """Get weather data with progress indicator"""
118
- with Progress(
119
- SpinnerColumn(),
120
- TextColumn("[progress.description]{task.description}"),
121
- console=console,
122
- ) as progress:
123
- progress.add_task(description="Fetching weather data...", total=None)
166
+ def get_weather(self, location: str) -> Weather:
167
+ """Get weather for the specified location.
168
+
169
+ Args:
170
+ location: Location to get weather for (city name, zip code, etc.)
171
+
172
+ Returns:
173
+ Weather object containing all weather data
174
+ """
124
175
  try:
125
176
  response = requests.get(f"https://wttr.in/{location}?format=j1", timeout=10)
126
177
  response.raise_for_status()
127
- return response.json()
178
+ return Weather(response.json())
128
179
  except Exception as e:
129
- console.print(f"[red]Error fetching weather data: {str(e)}[/]")
130
- return None
180
+ print(f"Error fetching weather data: {str(e)}")
181
+ return Weather()
131
182
 
132
- def display_weather(data):
133
- """Display weather information in a beautiful layout"""
134
- if not data:
135
- return
136
-
137
- # Create layout
138
- layout = Layout()
139
- layout.split_column(
140
- Layout(name="current", size=15),
141
- Layout(name="forecast", size=10)
142
- )
143
-
144
- # Update layout sections
145
- layout["current"].update(create_current_weather_panel(data))
146
- layout["forecast"].update(create_forecast_panel(data))
183
+
184
+ def get(location: str) -> Weather:
185
+ """Convenience function to get weather for a location.
147
186
 
148
- # Print layout with a title
149
- console.print("\n")
150
- console.print(Align.center("[bold blue]Weather Report[/]"))
151
- console.print("\n")
152
- console.print(layout)
153
- console.print("\n")
154
-
155
- def main():
156
- """Main function to run the weather app"""
157
- try:
158
- console.clear()
159
- console.print("\n[bold cyan]* Weather Information[/]\n")
160
- location = console.input("[cyan]Enter location: [/]")
187
+ Args:
188
+ location: Location to get weather for
161
189
 
162
- weather_data = get(location)
163
- if weather_data:
164
- display_weather(weather_data)
165
-
166
- except KeyboardInterrupt:
167
- console.print("\n[yellow]Operation cancelled by user[/]")
168
- except Exception as e:
169
- console.print(f"\n[bold red]Unexpected error:[/] {str(e)}")
170
-
171
- if __name__ == "__main__":
172
- main()
190
+ Returns:
191
+ Weather object containing all weather data
192
+ """
193
+ client = WeatherClient()
194
+ return client.get_weather(location)
@@ -1,23 +1,76 @@
1
+ """
2
+ Weather ASCII art visualization module with a simple, strongly-typed API.
3
+
4
+ This module provides a clean interface for fetching weather information
5
+ in ASCII art format using the wttr.in service.
6
+ """
7
+
1
8
  import requests
2
- from rich.console import Console
3
- from webscout.zeroart import figlet_format
9
+ from typing import Dict, Optional, Any
4
10
 
5
- console = Console()
6
- def get(location):
7
- """Fetches ASCII art weather data for the given location.
8
- Args:
9
- location (str): The location for which to fetch weather data.
10
11
 
12
+ class WeatherAscii:
13
+ """Container for ASCII weather data with a simple API."""
14
+
15
+ def __init__(self, content: str) -> None:
16
+ """Initialize with ASCII weather content.
17
+
18
+ Args:
19
+ content: ASCII weather data or error message
20
+ """
21
+ self._content = content
22
+
23
+ @property
24
+ def content(self) -> str:
25
+ """Get the ASCII content, similar to choices.message.content in OpenAI API."""
26
+ return self._content
27
+
28
+ def __str__(self) -> str:
29
+ """String representation of ASCII weather."""
30
+ return self.content
31
+
32
+
33
+ class WeatherAsciiClient:
34
+ """Client for fetching weather information in ASCII art."""
35
+
36
+ def get_weather(self, location: str, params: Optional[Dict[str, Any]] = None) -> WeatherAscii:
37
+ """Get ASCII weather for a location.
38
+
39
+ Args:
40
+ location: The location for which to fetch weather data
41
+ params: Additional parameters for the request
42
+
43
+ Returns:
44
+ WeatherAscii object containing ASCII art weather data
45
+ """
46
+ url = f"https://wttr.in/{location}"
47
+ headers = {'User-Agent': 'curl'}
48
+
49
+ try:
50
+ response = requests.get(url, headers=headers, params=params, timeout=10)
51
+ response.raise_for_status()
52
+
53
+ if response.status_code == 200:
54
+ # Remove the footer line from wttr.in
55
+ ascii_weather = "\n".join(response.text.splitlines()[:-1])
56
+ return WeatherAscii(ascii_weather)
57
+ else:
58
+ error_msg = f"Error: Unable to fetch weather data. Status code: {response.status_code}"
59
+ return WeatherAscii(error_msg)
60
+ except requests.exceptions.RequestException as e:
61
+ return WeatherAscii(f"Error: {str(e)}")
62
+
63
+
64
+ def get(location: str, params: Optional[Dict[str, Any]] = None) -> WeatherAscii:
65
+ """Convenience function to get ASCII weather for a location.
66
+
67
+ Args:
68
+ location: Location to get weather for
69
+ params: Additional parameters for the request
70
+
11
71
  Returns:
12
- str: ASCII art weather report if the request is successful,
13
- otherwise an error message.
72
+ WeatherAscii object containing ASCII art weather data
14
73
  """
15
- console.print(f"[bold green]{figlet_format('Weather')}")
16
- url = f"https://wttr.in/{location}"
17
- response = requests.get(url, headers={'User-Agent': 'curl'})
18
-
19
- if response.status_code == 200:
20
- return "\n".join(response.text.splitlines()[:-1])
21
- else:
22
- return f"Error: Unable to fetch weather data. Status code: {response.status_code}"
74
+ client = WeatherAsciiClient()
75
+ return client.get_weather(location, params)
23
76
 
@@ -4,11 +4,10 @@ import sys
4
4
  import threading
5
5
  import traceback
6
6
  from datetime import datetime
7
- from typing import Any, Dict, List, Optional, Union
7
+ from typing import List, Union
8
8
 
9
9
  from ..core.level import LogLevel
10
10
  from ..styles.formats import LogFormat
11
- from ..styles.colors import LogColors
12
11
 
13
12
  class Logger:
14
13
  # Emoji mappings for different log levels
@@ -2,7 +2,7 @@ import os
2
2
  import time
3
3
  from datetime import datetime
4
4
  from pathlib import Path
5
- from typing import Optional, Union
5
+ from typing import Union
6
6
  from ..core.level import LogLevel
7
7
 
8
8
  class FileHandler:
@@ -1,5 +1,3 @@
1
- from enum import Enum
2
- from typing import Dict
3
1
 
4
2
  class LogFormat:
5
3
  # Basic formats with improved styling
@@ -1,6 +1,5 @@
1
1
  import re
2
2
  import sys
3
- import traceback
4
3
  from typing import Optional
5
4
  from ..core.level import LogLevel
6
5
 
@@ -1,6 +1,5 @@
1
1
  from uuid import uuid4
2
2
  import requests
3
- import json
4
3
  import re
5
4
  from typing import Any, Dict, Generator, Optional
6
5
 
@@ -1,7 +1,7 @@
1
1
  import requests
2
2
  import json
3
3
  import re
4
- from typing import Dict, Optional, Generator, Union, Any
4
+ from typing import Dict, Optional, Generator, Any
5
5
  from webscout import LitAgent
6
6
  from webscout import exceptions
7
7
  from webscout.AIbase import AISearch
@@ -1,4 +1,3 @@
1
- import re
2
1
  import requests
3
2
  from uuid import uuid4
4
3
  import json
@@ -18,10 +18,10 @@ class AllenAI(Provider):
18
18
 
19
19
  AVAILABLE_MODELS = [
20
20
  'tulu3-405b',
21
- 'OLMo-2-1124-13B-Instruct',
22
- 'tulu-3-1-8b',
23
- 'Llama-3-1-Tulu-3-70B',
24
- 'olmoe-0125'
21
+ # 'OLMo-2-1124-13B-Instruct',
22
+ # 'tulu-3-1-8b',
23
+ # 'Llama-3-1-Tulu-3-70B',
24
+ # 'olmoe-0125'
25
25
  ]
26
26
 
27
27
 
@@ -275,8 +275,23 @@ class AllenAI(Provider):
275
275
  return response["text"]
276
276
 
277
277
  if __name__ == "__main__":
278
- from rich import print
279
- ai = AllenAI(timeout=5000)
280
- response = ai.chat("write a poem about AI", stream=True)
281
- for chunk in response:
282
- print(chunk, end="", flush=True)
278
+ print("-" * 80)
279
+ print(f"{'Model':<50} {'Status':<10} {'Response'}")
280
+ print("-" * 80)
281
+
282
+ for model in AllenAI.AVAILABLE_MODELS:
283
+ try:
284
+ test_ai = AllenAI(model=model, timeout=60)
285
+ response = test_ai.chat("Say 'Hello' in one word")
286
+ response_text = response
287
+
288
+ if response_text and len(response_text.strip()) > 0:
289
+ status = "✓"
290
+ # Truncate response if too long
291
+ display_text = response_text.strip()[:50] + "..." if len(response_text.strip()) > 50 else response_text.strip()
292
+ else:
293
+ status = "✗"
294
+ display_text = "Empty or invalid response"
295
+ print(f"{model:<50} {status:<10} {display_text}")
296
+ except Exception as e:
297
+ print(f"{model:<50} {'✗':<10} {str(e)}")