webscout 7.5__py3-none-any.whl → 7.7__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 (132) 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/__init__.py +9 -9
  9. webscout/Extra/autocoder/autocoder_utiles.py +193 -199
  10. webscout/Extra/autocoder/rawdog.py +789 -677
  11. webscout/Extra/gguf.py +682 -428
  12. webscout/Extra/weather.py +178 -156
  13. webscout/Extra/weather_ascii.py +70 -17
  14. webscout/Litlogger/core/logger.py +1 -2
  15. webscout/Litlogger/handlers/file.py +1 -1
  16. webscout/Litlogger/styles/formats.py +0 -2
  17. webscout/Litlogger/utils/detectors.py +0 -1
  18. webscout/Provider/AISEARCH/DeepFind.py +0 -1
  19. webscout/Provider/AISEARCH/ISou.py +1 -22
  20. webscout/Provider/AISEARCH/felo_search.py +0 -1
  21. webscout/Provider/AllenAI.py +28 -30
  22. webscout/Provider/C4ai.py +29 -11
  23. webscout/Provider/ChatGPTClone.py +226 -0
  24. webscout/Provider/ChatGPTGratis.py +24 -56
  25. webscout/Provider/DeepSeek.py +25 -17
  26. webscout/Provider/Deepinfra.py +115 -48
  27. webscout/Provider/Gemini.py +1 -1
  28. webscout/Provider/Glider.py +33 -12
  29. webscout/Provider/HF_space/qwen_qwen2.py +2 -2
  30. webscout/Provider/HeckAI.py +23 -7
  31. webscout/Provider/Hunyuan.py +272 -0
  32. webscout/Provider/Jadve.py +20 -5
  33. webscout/Provider/LambdaChat.py +391 -0
  34. webscout/Provider/Netwrck.py +42 -19
  35. webscout/Provider/OLLAMA.py +256 -32
  36. webscout/Provider/PI.py +4 -2
  37. webscout/Provider/Perplexitylabs.py +26 -6
  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 +179 -206
  43. webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +180 -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/async_aiarta.py +14 -14
  51. webscout/Provider/TTI/aiarta/sync_aiarta.py +52 -21
  52. webscout/Provider/TTI/artbit/async_artbit.py +3 -32
  53. webscout/Provider/TTI/artbit/sync_artbit.py +3 -31
  54. webscout/Provider/TTI/fastflux/__init__.py +22 -0
  55. webscout/Provider/TTI/fastflux/async_fastflux.py +261 -0
  56. webscout/Provider/TTI/fastflux/sync_fastflux.py +252 -0
  57. webscout/Provider/TTI/piclumen/__init__.py +22 -22
  58. webscout/Provider/TTI/piclumen/sync_piclumen.py +232 -232
  59. webscout/Provider/TTS/__init__.py +2 -2
  60. webscout/Provider/TTS/deepgram.py +12 -39
  61. webscout/Provider/TTS/elevenlabs.py +14 -40
  62. webscout/Provider/TTS/gesserit.py +11 -35
  63. webscout/Provider/TTS/murfai.py +13 -39
  64. webscout/Provider/TTS/parler.py +17 -40
  65. webscout/Provider/TTS/speechma.py +180 -0
  66. webscout/Provider/TTS/streamElements.py +17 -44
  67. webscout/Provider/TextPollinationsAI.py +39 -59
  68. webscout/Provider/Venice.py +25 -8
  69. webscout/Provider/WebSim.py +227 -0
  70. webscout/Provider/WiseCat.py +27 -5
  71. webscout/Provider/Youchat.py +64 -37
  72. webscout/Provider/__init__.py +12 -7
  73. webscout/Provider/akashgpt.py +20 -5
  74. webscout/Provider/flowith.py +33 -7
  75. webscout/Provider/freeaichat.py +32 -45
  76. webscout/Provider/koala.py +20 -5
  77. webscout/Provider/labyrinth.py +239 -0
  78. webscout/Provider/learnfastai.py +28 -15
  79. webscout/Provider/llamatutor.py +1 -1
  80. webscout/Provider/llmchat.py +30 -8
  81. webscout/Provider/multichat.py +65 -9
  82. webscout/Provider/sonus.py +208 -0
  83. webscout/Provider/talkai.py +1 -0
  84. webscout/Provider/turboseek.py +3 -0
  85. webscout/Provider/tutorai.py +2 -0
  86. webscout/Provider/typegpt.py +155 -65
  87. webscout/Provider/uncovr.py +297 -0
  88. webscout/Provider/x0gpt.py +3 -1
  89. webscout/Provider/yep.py +102 -20
  90. webscout/__init__.py +3 -0
  91. webscout/cli.py +53 -40
  92. webscout/conversation.py +1 -10
  93. webscout/litagent/__init__.py +2 -2
  94. webscout/litagent/agent.py +356 -20
  95. webscout/litagent/constants.py +34 -5
  96. webscout/litprinter/__init__.py +0 -3
  97. webscout/models.py +181 -0
  98. webscout/optimizers.py +1 -1
  99. webscout/prompt_manager.py +2 -8
  100. webscout/scout/core/scout.py +1 -4
  101. webscout/scout/core/search_result.py +1 -1
  102. webscout/scout/core/text_utils.py +1 -1
  103. webscout/scout/core.py +2 -5
  104. webscout/scout/element.py +1 -1
  105. webscout/scout/parsers/html_parser.py +1 -1
  106. webscout/scout/utils.py +0 -1
  107. webscout/swiftcli/__init__.py +1 -3
  108. webscout/tempid.py +1 -1
  109. webscout/update_checker.py +1 -3
  110. webscout/version.py +1 -1
  111. webscout/webscout_search_async.py +1 -2
  112. webscout/yep_search.py +297 -297
  113. {webscout-7.5.dist-info → webscout-7.7.dist-info}/LICENSE.md +4 -4
  114. {webscout-7.5.dist-info → webscout-7.7.dist-info}/METADATA +127 -405
  115. {webscout-7.5.dist-info → webscout-7.7.dist-info}/RECORD +118 -117
  116. webscout/Extra/autollama.py +0 -231
  117. webscout/Provider/Amigo.py +0 -274
  118. webscout/Provider/Bing.py +0 -243
  119. webscout/Provider/DiscordRocks.py +0 -253
  120. webscout/Provider/TTI/blackbox/__init__.py +0 -4
  121. webscout/Provider/TTI/blackbox/async_blackbox.py +0 -212
  122. webscout/Provider/TTI/blackbox/sync_blackbox.py +0 -199
  123. webscout/Provider/TTI/deepinfra/__init__.py +0 -4
  124. webscout/Provider/TTI/deepinfra/async_deepinfra.py +0 -227
  125. webscout/Provider/TTI/deepinfra/sync_deepinfra.py +0 -199
  126. webscout/Provider/TTI/imgninza/__init__.py +0 -4
  127. webscout/Provider/TTI/imgninza/async_ninza.py +0 -214
  128. webscout/Provider/TTI/imgninza/sync_ninza.py +0 -209
  129. webscout/Provider/TTS/voicepod.py +0 -117
  130. {webscout-7.5.dist-info → webscout-7.7.dist-info}/WHEEL +0 -0
  131. {webscout-7.5.dist-info → webscout-7.7.dist-info}/entry_points.txt +0 -0
  132. {webscout-7.5.dist-info → webscout-7.7.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
@@ -65,7 +65,6 @@ class Isou(AISearch):
65
65
  timeout: int = 120,
66
66
  proxies: Optional[dict] = None,
67
67
  model: str = "siliconflow:deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
68
- logging: bool = False
69
68
  ):
70
69
  """Initialize the Isou API client.
71
70
 
@@ -73,7 +72,6 @@ class Isou(AISearch):
73
72
  timeout (int, optional): Request timeout in seconds. Defaults to 120.
74
73
  proxies (dict, optional): Proxy configuration for requests. Defaults to None.
75
74
  model (str, optional): Model to use for search. Defaults to DeepSeek-R1.
76
- logging (bool, optional): Enable logging. Defaults to False.
77
75
  """
78
76
  self.available_models = [
79
77
  "siliconflow:deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
@@ -115,24 +113,6 @@ class Isou(AISearch):
115
113
  self.session.headers.update(self.headers)
116
114
  self.proxies = proxies
117
115
 
118
- # Initialize logger if enabled
119
- if logging:
120
- from webscout.Litlogger import Logger, LogFormat, ConsoleHandler
121
- from webscout.Litlogger.core.level import LogLevel
122
-
123
- console_handler = ConsoleHandler(
124
- level=LogLevel.DEBUG,
125
- )
126
-
127
- self.logger = Logger(
128
- name="Isou",
129
- level=LogLevel.DEBUG,
130
- handlers=[console_handler]
131
- )
132
- self.logger.info("Isou initialized successfully ✨")
133
- else:
134
- self.logger = None
135
-
136
116
  def search(
137
117
  self,
138
118
  prompt: str,
@@ -268,7 +248,6 @@ if __name__ == "__main__":
268
248
  # Initialize with specific model and logging
269
249
  ai = Isou(
270
250
  model="siliconflow:deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
271
- logging=False
272
251
  )
273
252
 
274
253
  response = ai.search(input(">>> "), stream=True, raw=False)
@@ -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
 
@@ -37,7 +37,7 @@ class AllenAI(Provider):
37
37
  history_offset: int = 10250,
38
38
  act: str = None,
39
39
  model: str = "tulu3-405b",
40
- system_prompt: str = "You are a helpful AI assistant.",
40
+
41
41
  ):
42
42
  """Initializes the AllenAI API client."""
43
43
  if model not in self.AVAILABLE_MODELS:
@@ -68,7 +68,6 @@ class AllenAI(Provider):
68
68
  self.session.headers.update(self.headers)
69
69
  self.session.proxies.update(proxies)
70
70
  self.model = model
71
- self.system_prompt = system_prompt
72
71
  self.is_conversation = is_conversation
73
72
  self.max_tokens_to_sample = max_tokens
74
73
  self.timeout = timeout
@@ -95,19 +94,6 @@ class AllenAI(Provider):
95
94
  )
96
95
  self.conversation.history_offset = history_offset
97
96
 
98
- def format_prompt(self, messages):
99
- """Format messages into a prompt string"""
100
- formatted = []
101
- for msg in messages:
102
- role = msg.get("role", "")
103
- content = msg.get("content", "")
104
- if role == "system":
105
- formatted.append(f"System: {content}")
106
- elif role == "user":
107
- formatted.append(f"User: {content}")
108
- elif role == "assistant":
109
- formatted.append(f"Assistant: {content}")
110
- return "\n".join(formatted)
111
97
 
112
98
  def ask(
113
99
  self,
@@ -139,11 +125,8 @@ class AllenAI(Provider):
139
125
  "x-anonymous-user-id": self.x_anonymous_user_id
140
126
  })
141
127
 
142
- # Format messages for AllenAI
143
- messages = [
144
- {"role": "system", "content": self.system_prompt},
145
- {"role": "user", "content": conversation_prompt}
146
- ]
128
+
129
+ messages = conversation_prompt
147
130
 
148
131
  # Build multipart form data
149
132
  form_data = [
@@ -154,7 +137,7 @@ class AllenAI(Provider):
154
137
  f'Content-Disposition: form-data; name="host"\r\n\r\n{host}\r\n',
155
138
 
156
139
  f'--{boundary}\r\n'
157
- f'Content-Disposition: form-data; name="content"\r\n\r\n{self.format_prompt(messages)}\r\n',
140
+ f'Content-Disposition: form-data; name="content"\r\n\r\n{messages}\r\n',
158
141
 
159
142
  f'--{boundary}\r\n'
160
143
  f'Content-Disposition: form-data; name="private"\r\n\r\n{str(private).lower()}\r\n'
@@ -275,8 +258,23 @@ class AllenAI(Provider):
275
258
  return response["text"]
276
259
 
277
260
  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)
261
+ print("-" * 80)
262
+ print(f"{'Model':<50} {'Status':<10} {'Response'}")
263
+ print("-" * 80)
264
+
265
+ for model in AllenAI.AVAILABLE_MODELS:
266
+ try:
267
+ test_ai = AllenAI(model=model, timeout=60)
268
+ response = test_ai.chat("Say 'Hello' in one word")
269
+ response_text = response
270
+
271
+ if response_text and len(response_text.strip()) > 0:
272
+ status = "✓"
273
+ # Truncate response if too long
274
+ display_text = response_text.strip()[:50] + "..." if len(response_text.strip()) > 50 else response_text.strip()
275
+ else:
276
+ status = "✗"
277
+ display_text = "Empty or invalid response"
278
+ print(f"{model:<50} {status:<10} {display_text}")
279
+ except Exception as e:
280
+ print(f"{model:<50} {'✗':<10} {str(e)}")