webscout 8.2.6__py3-none-any.whl → 8.2.8__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 (150) hide show
  1. webscout/AIauto.py +1 -1
  2. webscout/AIutel.py +298 -239
  3. webscout/Extra/Act.md +309 -0
  4. webscout/Extra/GitToolkit/gitapi/README.md +110 -0
  5. webscout/Extra/YTToolkit/README.md +375 -0
  6. webscout/Extra/YTToolkit/ytapi/README.md +44 -0
  7. webscout/Extra/YTToolkit/ytapi/extras.py +92 -19
  8. webscout/Extra/autocoder/autocoder.py +309 -114
  9. webscout/Extra/autocoder/autocoder_utiles.py +15 -15
  10. webscout/Extra/gguf.md +430 -0
  11. webscout/Extra/tempmail/README.md +488 -0
  12. webscout/Extra/weather.md +281 -0
  13. webscout/Litlogger/Readme.md +175 -0
  14. webscout/Provider/AISEARCH/DeepFind.py +41 -37
  15. webscout/Provider/AISEARCH/README.md +279 -0
  16. webscout/Provider/AISEARCH/__init__.py +0 -1
  17. webscout/Provider/AISEARCH/genspark_search.py +228 -86
  18. webscout/Provider/AISEARCH/hika_search.py +11 -11
  19. webscout/Provider/AISEARCH/scira_search.py +324 -322
  20. webscout/Provider/AllenAI.py +7 -14
  21. webscout/Provider/Blackboxai.py +518 -74
  22. webscout/Provider/Cloudflare.py +0 -1
  23. webscout/Provider/Deepinfra.py +23 -21
  24. webscout/Provider/Flowith.py +217 -0
  25. webscout/Provider/FreeGemini.py +250 -0
  26. webscout/Provider/GizAI.py +15 -5
  27. webscout/Provider/Glider.py +11 -8
  28. webscout/Provider/HeckAI.py +80 -52
  29. webscout/Provider/Koboldai.py +7 -4
  30. webscout/Provider/LambdaChat.py +2 -2
  31. webscout/Provider/Marcus.py +10 -18
  32. webscout/Provider/OPENAI/BLACKBOXAI.py +735 -0
  33. webscout/Provider/OPENAI/Cloudflare.py +378 -0
  34. webscout/Provider/OPENAI/FreeGemini.py +282 -0
  35. webscout/Provider/OPENAI/NEMOTRON.py +244 -0
  36. webscout/Provider/OPENAI/README.md +1253 -0
  37. webscout/Provider/OPENAI/__init__.py +8 -0
  38. webscout/Provider/OPENAI/ai4chat.py +293 -286
  39. webscout/Provider/OPENAI/api.py +810 -0
  40. webscout/Provider/OPENAI/base.py +217 -14
  41. webscout/Provider/OPENAI/c4ai.py +373 -367
  42. webscout/Provider/OPENAI/chatgpt.py +7 -0
  43. webscout/Provider/OPENAI/chatgptclone.py +7 -0
  44. webscout/Provider/OPENAI/chatsandbox.py +172 -0
  45. webscout/Provider/OPENAI/deepinfra.py +30 -20
  46. webscout/Provider/OPENAI/e2b.py +6 -0
  47. webscout/Provider/OPENAI/exaai.py +7 -0
  48. webscout/Provider/OPENAI/exachat.py +6 -0
  49. webscout/Provider/OPENAI/flowith.py +162 -0
  50. webscout/Provider/OPENAI/freeaichat.py +359 -352
  51. webscout/Provider/OPENAI/glider.py +323 -316
  52. webscout/Provider/OPENAI/groq.py +361 -354
  53. webscout/Provider/OPENAI/heckai.py +30 -64
  54. webscout/Provider/OPENAI/llmchatco.py +8 -0
  55. webscout/Provider/OPENAI/mcpcore.py +7 -0
  56. webscout/Provider/OPENAI/multichat.py +8 -0
  57. webscout/Provider/OPENAI/netwrck.py +356 -350
  58. webscout/Provider/OPENAI/opkfc.py +8 -0
  59. webscout/Provider/OPENAI/scirachat.py +471 -462
  60. webscout/Provider/OPENAI/sonus.py +9 -0
  61. webscout/Provider/OPENAI/standardinput.py +9 -1
  62. webscout/Provider/OPENAI/textpollinations.py +339 -329
  63. webscout/Provider/OPENAI/toolbaz.py +7 -0
  64. webscout/Provider/OPENAI/typefully.py +355 -0
  65. webscout/Provider/OPENAI/typegpt.py +358 -346
  66. webscout/Provider/OPENAI/uncovrAI.py +7 -0
  67. webscout/Provider/OPENAI/utils.py +103 -7
  68. webscout/Provider/OPENAI/venice.py +12 -0
  69. webscout/Provider/OPENAI/wisecat.py +19 -19
  70. webscout/Provider/OPENAI/writecream.py +7 -0
  71. webscout/Provider/OPENAI/x0gpt.py +7 -0
  72. webscout/Provider/OPENAI/yep.py +50 -21
  73. webscout/Provider/OpenGPT.py +1 -1
  74. webscout/Provider/TTI/AiForce/README.md +159 -0
  75. webscout/Provider/TTI/FreeAIPlayground/README.md +99 -0
  76. webscout/Provider/TTI/ImgSys/README.md +174 -0
  77. webscout/Provider/TTI/MagicStudio/README.md +101 -0
  78. webscout/Provider/TTI/Nexra/README.md +155 -0
  79. webscout/Provider/TTI/PollinationsAI/README.md +146 -0
  80. webscout/Provider/TTI/README.md +128 -0
  81. webscout/Provider/TTI/aiarta/README.md +134 -0
  82. webscout/Provider/TTI/artbit/README.md +100 -0
  83. webscout/Provider/TTI/fastflux/README.md +129 -0
  84. webscout/Provider/TTI/huggingface/README.md +114 -0
  85. webscout/Provider/TTI/piclumen/README.md +161 -0
  86. webscout/Provider/TTI/pixelmuse/README.md +79 -0
  87. webscout/Provider/TTI/talkai/README.md +139 -0
  88. webscout/Provider/TTS/README.md +192 -0
  89. webscout/Provider/TTS/__init__.py +2 -1
  90. webscout/Provider/TTS/speechma.py +500 -100
  91. webscout/Provider/TTS/sthir.py +94 -0
  92. webscout/Provider/TeachAnything.py +3 -7
  93. webscout/Provider/TextPollinationsAI.py +4 -2
  94. webscout/Provider/{aimathgpt.py → UNFINISHED/ChatHub.py} +88 -68
  95. webscout/Provider/UNFINISHED/liner_api_request.py +263 -0
  96. webscout/Provider/UNFINISHED/oivscode.py +351 -0
  97. webscout/Provider/UNFINISHED/test_lmarena.py +119 -0
  98. webscout/Provider/Writecream.py +11 -2
  99. webscout/Provider/__init__.py +8 -14
  100. webscout/Provider/ai4chat.py +4 -58
  101. webscout/Provider/asksteve.py +17 -9
  102. webscout/Provider/cerebras.py +3 -1
  103. webscout/Provider/koala.py +170 -268
  104. webscout/Provider/llmchat.py +3 -0
  105. webscout/Provider/lmarena.py +198 -0
  106. webscout/Provider/meta.py +7 -4
  107. webscout/Provider/samurai.py +223 -0
  108. webscout/Provider/scira_chat.py +4 -2
  109. webscout/Provider/typefully.py +23 -151
  110. webscout/__init__.py +4 -2
  111. webscout/cli.py +3 -28
  112. webscout/conversation.py +35 -35
  113. webscout/litagent/Readme.md +276 -0
  114. webscout/scout/README.md +402 -0
  115. webscout/swiftcli/Readme.md +323 -0
  116. webscout/version.py +1 -1
  117. webscout/webscout_search.py +2 -182
  118. webscout/webscout_search_async.py +1 -179
  119. webscout/zeroart/README.md +89 -0
  120. webscout/zeroart/__init__.py +134 -54
  121. webscout/zeroart/base.py +19 -13
  122. webscout/zeroart/effects.py +101 -99
  123. webscout/zeroart/fonts.py +1239 -816
  124. {webscout-8.2.6.dist-info → webscout-8.2.8.dist-info}/METADATA +116 -74
  125. {webscout-8.2.6.dist-info → webscout-8.2.8.dist-info}/RECORD +130 -103
  126. {webscout-8.2.6.dist-info → webscout-8.2.8.dist-info}/WHEEL +1 -1
  127. webscout-8.2.8.dist-info/entry_points.txt +3 -0
  128. webscout-8.2.8.dist-info/top_level.txt +1 -0
  129. webscout/Provider/AISEARCH/ISou.py +0 -256
  130. webscout/Provider/ElectronHub.py +0 -773
  131. webscout/Provider/Free2GPT.py +0 -241
  132. webscout/Provider/GPTWeb.py +0 -249
  133. webscout/Provider/bagoodex.py +0 -145
  134. webscout/Provider/geminiprorealtime.py +0 -160
  135. webscout/scout/core.py +0 -881
  136. webscout-8.2.6.dist-info/entry_points.txt +0 -3
  137. webscout-8.2.6.dist-info/top_level.txt +0 -2
  138. webstoken/__init__.py +0 -30
  139. webstoken/classifier.py +0 -189
  140. webstoken/keywords.py +0 -216
  141. webstoken/language.py +0 -128
  142. webstoken/ner.py +0 -164
  143. webstoken/normalizer.py +0 -35
  144. webstoken/processor.py +0 -77
  145. webstoken/sentiment.py +0 -206
  146. webstoken/stemmer.py +0 -73
  147. webstoken/tagger.py +0 -60
  148. webstoken/tokenizer.py +0 -158
  149. /webscout/Provider/{Youchat.py → UNFINISHED/Youchat.py} +0 -0
  150. {webscout-8.2.6.dist-info → webscout-8.2.8.dist-info}/licenses/LICENSE.md +0 -0
@@ -2,7 +2,6 @@ from curl_cffi.requests import Session
2
2
  from curl_cffi import CurlError
3
3
  import json
4
4
  import uuid
5
- import sys
6
5
  from typing import Any, Dict, Optional, Generator, Union
7
6
 
8
7
  from webscout.AIutel import Optimizers
@@ -25,7 +24,6 @@ class HeckAI(Provider):
25
24
  "openai/gpt-4.1-mini",
26
25
  "x-ai/grok-3-mini-beta",
27
26
  "meta-llama/llama-4-scout"
28
-
29
27
  ]
30
28
 
31
29
  def __init__(
@@ -112,7 +110,8 @@ class HeckAI(Provider):
112
110
  "sessionId": self.session_id,
113
111
  "previousQuestion": self.previous_question,
114
112
  "previousAnswer": self.previous_answer,
115
- "imgUrls": []
113
+ "imgUrls": [],
114
+ "superSmartMode": False # Added based on API request data
116
115
  }
117
116
 
118
117
  # Store this message as previous for next request
@@ -120,7 +119,6 @@ class HeckAI(Provider):
120
119
 
121
120
  def for_stream():
122
121
  streaming_text = "" # Initialize outside try block
123
- # in_answer = False # No longer needed
124
122
  try:
125
123
  # Use curl_cffi session post with impersonate
126
124
  response = self.session.post(
@@ -134,15 +132,16 @@ class HeckAI(Provider):
134
132
  response.raise_for_status() # Check for HTTP errors
135
133
 
136
134
  # Use sanitize_stream to process the stream
137
- processed_stream = sanitize_stream(
138
- data=response.iter_content(chunk_size=None), # Pass byte iterator
139
- intro_value="data:", # Prefix to remove *from lines between markers*
140
- to_json=False, # Content is text
141
- start_marker="data: [ANSWER_START]", # Check against the raw line including prefix
142
- end_marker="data: [ANSWER_DONE]", # Check against the raw line including prefix
143
- skip_markers=["[RELATE_Q_START]", "[RELATE_Q_DONE]"], # Skip these if they appear within answer block
144
- yield_raw_on_error=True
145
- )
135
+ processed_stream = sanitize_stream(
136
+ data=response.iter_content(chunk_size=1024), # Pass byte iterator
137
+ intro_value="data: ", # Prefix to remove (note the space)
138
+ to_json=False, # Content is text
139
+ start_marker="data: [ANSWER_START]",
140
+ end_marker="data: [ANSWER_DONE]",
141
+ skip_markers=["data: [RELATE_Q_START]", "data: [RELATE_Q_DONE]", "data: [REASON_START]", "data: [REASON_DONE]"],
142
+ yield_raw_on_error=True,
143
+ strip_chars=" \n\r\t" # Strip whitespace characters from chunks
144
+ )
146
145
 
147
146
  for content_chunk in processed_stream:
148
147
  # content_chunk is the text between ANSWER_START and ANSWER_DONE
@@ -150,9 +149,21 @@ class HeckAI(Provider):
150
149
  streaming_text += content_chunk
151
150
  yield dict(text=content_chunk) if not raw else content_chunk
152
151
 
153
- # Update history and previous answer after stream finishes
154
- self.previous_answer = streaming_text
155
- self.conversation.update_chat_history(prompt, streaming_text)
152
+ # Only update history if we received a valid response
153
+ if streaming_text:
154
+ # Update history and previous answer after stream finishes
155
+ self.previous_answer = streaming_text
156
+ # Convert to simple text before updating conversation
157
+ try:
158
+ # Ensure content is valid before updating conversation
159
+ if streaming_text and isinstance(streaming_text, str):
160
+ # Sanitize the content to ensure it's valid
161
+ sanitized_text = streaming_text.strip()
162
+ if sanitized_text: # Only update if we have non-empty content
163
+ self.conversation.update_chat_history(prompt, sanitized_text)
164
+ except Exception as e:
165
+ # If conversation update fails, log but don't crash
166
+ print(f"Warning: Failed to update conversation history: {str(e)}")
156
167
 
157
168
  except CurlError as e: # Catch CurlError
158
169
  raise exceptions.FailedToGenerateResponseError(f"Request failed (CurlError): {str(e)}") from e
@@ -177,7 +188,6 @@ class HeckAI(Provider):
177
188
  if not full_text:
178
189
  raise exceptions.FailedToGenerateResponseError(f"Failed to get non-stream response: {str(e)}") from e
179
190
 
180
- # last_response and history are updated within for_stream
181
191
  # Return the final aggregated response dict or raw string
182
192
  self.last_response = {"text": full_text} # Update last_response here
183
193
  return full_text if raw else self.last_response
@@ -200,13 +210,13 @@ class HeckAI(Provider):
200
210
  return text
201
211
  return text
202
212
 
203
- def chat(
204
- self,
205
- prompt: str,
206
- stream: bool = False,
207
- optimizer: str = None,
208
- conversationally: bool = False,
209
- ) -> Union[str, Generator[str, None, None]]: # Corrected return type hint
213
+ def chat(
214
+ self,
215
+ prompt: str,
216
+ stream: bool = False,
217
+ optimizer: str = None,
218
+ conversationally: bool = False,
219
+ ) -> Union[str, Generator[str, None, None]]: # Corrected return type hint
210
220
  def for_stream_chat():
211
221
  # ask() yields dicts or strings when streaming
212
222
  gen = self.ask(
@@ -226,32 +236,50 @@ class HeckAI(Provider):
226
236
 
227
237
  return for_stream_chat() if stream else for_non_stream_chat()
228
238
 
229
- def get_message(self, response: dict) -> str:
230
- assert isinstance(response, dict), "Response should be of dict data-type only"
231
- return response["text"]
232
-
233
- if __name__ == "__main__":
234
- # Ensure curl_cffi is installed
235
- print("-" * 80)
236
- print(f"{'Model':<50} {'Status':<10} {'Response'}")
237
- print("-" * 80)
239
+ def get_message(self, response: dict) -> str:
240
+ # Validate response format
241
+ if not isinstance(response, dict):
242
+ raise TypeError(f"Expected dict response, got {type(response).__name__}")
243
+
244
+ # Handle missing text key gracefully
245
+ if "text" not in response:
246
+ return ""
247
+
248
+ # Ensure text is a string
249
+ text = response["text"]
250
+ if not isinstance(text, str):
251
+ return str(text)
252
+
253
+ return text
238
254
 
239
- for model in HeckAI.AVAILABLE_MODELS:
240
- try:
241
- test_ai = HeckAI(model=model, timeout=60)
242
- response = test_ai.chat("Say 'Hello' in one word", stream=True)
243
- response_text = ""
244
- for chunk in response:
245
- response_text += chunk
246
- print(f"\r{model:<50} {'Testing...':<10}", end="", flush=True)
247
-
248
- if response_text and len(response_text.strip()) > 0:
249
- status = "✓"
250
- # Truncate response if too long
251
- display_text = response_text.strip()[:50] + "..." if len(response_text.strip()) > 50 else response_text.strip()
252
- else:
253
- status = "✗"
254
- display_text = "Empty or invalid response"
255
- print(f"\r{model:<50} {status:<10} {display_text}")
256
- except Exception as e:
257
- print(f"\r{model:<50} {'✗':<10} {str(e)}")
255
+ if __name__ == "__main__":
256
+ # Ensure curl_cffi is installed
257
+ print("-" * 80)
258
+ print(f"{'Model':<50} {'Status':<10} {'Response'}")
259
+ print("-" * 80)
260
+
261
+ for model in HeckAI.AVAILABLE_MODELS:
262
+ try:
263
+ test_ai = HeckAI(model=model, timeout=60)
264
+ # Use non-streaming mode first to avoid potential streaming issues
265
+ try:
266
+ response_text = test_ai.chat("Say 'Hello' in one word", stream=False)
267
+ print(f"\r{model:<50} {'✓':<10} {response_text.strip()[:50]}")
268
+ except Exception as e1:
269
+ # Fall back to streaming if non-streaming fails
270
+ print(f"\r{model:<50} {'Testing stream...':<10}", end="", flush=True)
271
+ response = test_ai.chat("Say 'Hello' in one word", stream=True)
272
+ response_text = ""
273
+ for chunk in response:
274
+ if chunk and isinstance(chunk, str):
275
+ response_text += chunk
276
+
277
+ if response_text and len(response_text.strip()) > 0:
278
+ status = "✓"
279
+ # Truncate response if too long
280
+ display_text = response_text.strip()[:50] + "..." if len(response_text.strip()) > 50 else response_text.strip()
281
+ print(f"\r{model:<50} {status:<10} {display_text}")
282
+ else:
283
+ raise ValueError("Empty or invalid response")
284
+ except Exception as e:
285
+ print(f"\r{model:<50} {'✗':<10} {str(e)}")
@@ -125,6 +125,7 @@ class KOBOLDAI(Provider):
125
125
  )
126
126
 
127
127
  message_load = ""
128
+ final_resp = None
128
129
  for value in response.iter_lines(
129
130
  decode_unicode=True,
130
131
  delimiter="" if raw else "event: message\ndata:",
@@ -135,12 +136,14 @@ class KOBOLDAI(Provider):
135
136
  message_load += self.get_message(resp)
136
137
  resp["token"] = message_load
137
138
  self.last_response.update(resp)
138
- yield value if raw else resp
139
+ final_resp = resp # Always keep the latest
139
140
  except json.decoder.JSONDecodeError:
140
141
  pass
141
- self.conversation.update_chat_history(
142
- prompt, self.get_message(self.last_response)
143
- )
142
+ if final_resp:
143
+ yield final_resp if not raw else json.dumps(final_resp)
144
+ self.conversation.update_chat_history(
145
+ prompt, self.get_message(self.last_response)
146
+ )
144
147
 
145
148
  def for_non_stream():
146
149
  # let's make use of stream
@@ -191,8 +191,8 @@ class LambdaChat(Provider):
191
191
  reasoning_text = ""
192
192
  if chunk["type"] == "stream" and "token" in chunk:
193
193
  return chunk["token"].replace("\u0000", "")
194
- elif chunk["type"] == "finalAnswer":
195
- return chunk.get("text")
194
+ # elif chunk["type"] == "finalAnswer":
195
+ # return chunk.get("text")
196
196
  elif chunk["type"] == "reasoning" and chunk.get("subtype") == "stream" and "token" in chunk:
197
197
  # Prepend reasoning with <think> tags? Or handle separately? For now, just return token.
198
198
  return chunk["token"] # Or potentially format as f"<think>{chunk['token']}</think>"
@@ -173,24 +173,16 @@ class Marcus(Provider):
173
173
  conversationally: bool = False,
174
174
  ) -> Union[str, Generator[str, None, None]]:
175
175
  """Generates a response from the AskMarcus API."""
176
- def for_stream_chat():
177
- # ask() yields dicts or strings when streaming
178
- gen = self.ask(
179
- prompt, stream=True, raw=False, # Ensure ask yields dicts
180
- optimizer=optimizer, conversationally=conversationally
181
- )
182
- for response_dict in gen:
183
- yield self.get_message(response_dict) # get_message expects dict
184
-
185
- def for_non_stream_chat():
186
- # ask() returns dict or str when not streaming
187
- response_data = self.ask(
188
- prompt, stream=False, raw=False, # Ensure ask returns dict
189
- optimizer=optimizer, conversationally=conversationally
190
- )
191
- return self.get_message(response_data) # get_message expects dict
192
-
193
- return for_stream_chat() if stream else for_non_stream_chat()
176
+ response_data = self.ask(
177
+ prompt, stream=False, raw=False, # Always get the full response
178
+ optimizer=optimizer, conversationally=conversationally
179
+ )
180
+ if stream:
181
+ def stream_wrapper():
182
+ yield self.get_message(response_data)
183
+ return stream_wrapper()
184
+ else:
185
+ return self.get_message(response_data)
194
186
 
195
187
  def get_message(self, response: Dict[str, Any]) -> str:
196
188
  """Extracts the message from the API response."""