webscout 8.2.3__py3-none-any.whl → 8.2.5__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 (122) hide show
  1. webscout/AIutel.py +226 -14
  2. webscout/Bard.py +579 -206
  3. webscout/DWEBS.py +78 -35
  4. webscout/Extra/gguf.py +2 -0
  5. webscout/Extra/tempmail/base.py +1 -1
  6. webscout/Provider/AISEARCH/hika_search.py +4 -0
  7. webscout/Provider/AISEARCH/scira_search.py +2 -5
  8. webscout/Provider/Aitopia.py +75 -51
  9. webscout/Provider/AllenAI.py +181 -147
  10. webscout/Provider/ChatGPTClone.py +97 -86
  11. webscout/Provider/ChatSandbox.py +342 -0
  12. webscout/Provider/Cloudflare.py +79 -32
  13. webscout/Provider/Deepinfra.py +135 -94
  14. webscout/Provider/ElectronHub.py +103 -39
  15. webscout/Provider/ExaChat.py +36 -20
  16. webscout/Provider/GPTWeb.py +103 -47
  17. webscout/Provider/GithubChat.py +52 -49
  18. webscout/Provider/GizAI.py +283 -0
  19. webscout/Provider/Glider.py +39 -28
  20. webscout/Provider/Groq.py +222 -91
  21. webscout/Provider/HeckAI.py +93 -69
  22. webscout/Provider/HuggingFaceChat.py +113 -106
  23. webscout/Provider/Hunyuan.py +94 -83
  24. webscout/Provider/Jadve.py +104 -79
  25. webscout/Provider/LambdaChat.py +142 -123
  26. webscout/Provider/Llama3.py +94 -39
  27. webscout/Provider/MCPCore.py +315 -0
  28. webscout/Provider/Marcus.py +95 -37
  29. webscout/Provider/Netwrck.py +94 -52
  30. webscout/Provider/OPENAI/__init__.py +4 -1
  31. webscout/Provider/OPENAI/ai4chat.py +286 -0
  32. webscout/Provider/OPENAI/chatgptclone.py +35 -14
  33. webscout/Provider/OPENAI/deepinfra.py +37 -0
  34. webscout/Provider/OPENAI/exachat.py +4 -0
  35. webscout/Provider/OPENAI/groq.py +354 -0
  36. webscout/Provider/OPENAI/heckai.py +6 -2
  37. webscout/Provider/OPENAI/mcpcore.py +376 -0
  38. webscout/Provider/OPENAI/multichat.py +368 -0
  39. webscout/Provider/OPENAI/netwrck.py +3 -1
  40. webscout/Provider/OPENAI/scirachat.py +2 -4
  41. webscout/Provider/OPENAI/textpollinations.py +20 -22
  42. webscout/Provider/OPENAI/toolbaz.py +1 -0
  43. webscout/Provider/OpenGPT.py +48 -38
  44. webscout/Provider/PI.py +178 -93
  45. webscout/Provider/PizzaGPT.py +66 -36
  46. webscout/Provider/StandardInput.py +42 -30
  47. webscout/Provider/TeachAnything.py +95 -52
  48. webscout/Provider/TextPollinationsAI.py +138 -78
  49. webscout/Provider/TwoAI.py +162 -81
  50. webscout/Provider/TypliAI.py +305 -0
  51. webscout/Provider/Venice.py +97 -58
  52. webscout/Provider/VercelAI.py +33 -14
  53. webscout/Provider/WiseCat.py +65 -28
  54. webscout/Provider/Writecream.py +37 -11
  55. webscout/Provider/WritingMate.py +135 -63
  56. webscout/Provider/__init__.py +9 -27
  57. webscout/Provider/ai4chat.py +6 -7
  58. webscout/Provider/asksteve.py +53 -44
  59. webscout/Provider/cerebras.py +77 -31
  60. webscout/Provider/chatglm.py +47 -37
  61. webscout/Provider/copilot.py +0 -3
  62. webscout/Provider/elmo.py +109 -60
  63. webscout/Provider/granite.py +102 -54
  64. webscout/Provider/hermes.py +95 -48
  65. webscout/Provider/koala.py +1 -1
  66. webscout/Provider/learnfastai.py +113 -54
  67. webscout/Provider/llama3mitril.py +86 -51
  68. webscout/Provider/llmchat.py +88 -46
  69. webscout/Provider/llmchatco.py +110 -115
  70. webscout/Provider/meta.py +41 -37
  71. webscout/Provider/multichat.py +67 -28
  72. webscout/Provider/scira_chat.py +49 -30
  73. webscout/Provider/scnet.py +106 -53
  74. webscout/Provider/searchchat.py +87 -88
  75. webscout/Provider/sonus.py +113 -63
  76. webscout/Provider/toolbaz.py +115 -82
  77. webscout/Provider/turboseek.py +90 -43
  78. webscout/Provider/tutorai.py +82 -64
  79. webscout/Provider/typefully.py +85 -35
  80. webscout/Provider/typegpt.py +118 -61
  81. webscout/Provider/uncovr.py +132 -76
  82. webscout/Provider/x0gpt.py +69 -26
  83. webscout/Provider/yep.py +79 -66
  84. webscout/cli.py +256 -0
  85. webscout/conversation.py +34 -22
  86. webscout/exceptions.py +23 -0
  87. webscout/prompt_manager.py +56 -42
  88. webscout/version.py +1 -1
  89. webscout/webscout_search.py +65 -47
  90. webscout/webscout_search_async.py +81 -126
  91. webscout/yep_search.py +93 -43
  92. {webscout-8.2.3.dist-info → webscout-8.2.5.dist-info}/METADATA +183 -50
  93. {webscout-8.2.3.dist-info → webscout-8.2.5.dist-info}/RECORD +97 -113
  94. {webscout-8.2.3.dist-info → webscout-8.2.5.dist-info}/WHEEL +1 -1
  95. webscout-8.2.5.dist-info/entry_points.txt +3 -0
  96. {webscout-8.2.3.dist-info → webscout-8.2.5.dist-info}/top_level.txt +0 -1
  97. inferno/__init__.py +0 -6
  98. inferno/__main__.py +0 -9
  99. inferno/cli.py +0 -6
  100. webscout/Local/__init__.py +0 -12
  101. webscout/Local/__main__.py +0 -9
  102. webscout/Local/api.py +0 -576
  103. webscout/Local/cli.py +0 -516
  104. webscout/Local/config.py +0 -75
  105. webscout/Local/llm.py +0 -287
  106. webscout/Local/model_manager.py +0 -253
  107. webscout/Local/server.py +0 -721
  108. webscout/Local/utils.py +0 -93
  109. webscout/Provider/C4ai.py +0 -432
  110. webscout/Provider/ChatGPTES.py +0 -237
  111. webscout/Provider/Chatify.py +0 -175
  112. webscout/Provider/DeepSeek.py +0 -196
  113. webscout/Provider/Llama.py +0 -200
  114. webscout/Provider/Phind.py +0 -535
  115. webscout/Provider/WebSim.py +0 -228
  116. webscout/Provider/askmyai.py +0 -158
  117. webscout/Provider/gaurish.py +0 -244
  118. webscout/Provider/labyrinth.py +0 -340
  119. webscout/Provider/lepton.py +0 -194
  120. webscout/Provider/llamatutor.py +0 -192
  121. webscout-8.2.3.dist-info/entry_points.txt +0 -5
  122. {webscout-8.2.3.dist-info → webscout-8.2.5.dist-info/licenses}/LICENSE.md +0 -0
webscout/AIutel.py CHANGED
@@ -1,28 +1,240 @@
1
1
  import json
2
2
  import platform
3
3
  import subprocess
4
- from typing import Union
4
+ from typing import Union, Optional, Dict, Any, Iterable, Generator, List, Callable
5
+ import io # Import io for type checking
6
+ # Removed logging import and configuration
5
7
 
8
+ # Helper function to process a single chunk
9
+ def _process_chunk(
10
+ chunk: str,
11
+ intro_value: str,
12
+ to_json: bool,
13
+ skip_markers: List[str],
14
+ strip_chars: Optional[str],
15
+ yield_raw_on_error: bool,
16
+ ) -> Union[str, Dict[str, Any], None]:
17
+ """Internal helper to sanitize and potentially parse a single chunk."""
18
+ if not isinstance(chunk, str):
19
+ # Silently skip non-strings when processing an iterable
20
+ return None
6
21
 
22
+ sanitized_chunk = chunk
23
+
24
+ # 1. Remove the prefix
25
+ if intro_value and sanitized_chunk.startswith(intro_value):
26
+ sanitized_chunk = sanitized_chunk[len(intro_value):]
27
+
28
+ # 2. Strip characters/whitespace
29
+ if strip_chars is not None:
30
+ # Strip specified chars from both ends
31
+ sanitized_chunk = sanitized_chunk.strip(strip_chars)
32
+ else:
33
+ # Default: strip only leading whitespace *after* prefix removal
34
+ sanitized_chunk = sanitized_chunk.lstrip()
35
+
36
+ # 3. Skip if empty or a marker (checked *after* stripping)
37
+ if not sanitized_chunk or sanitized_chunk in skip_markers:
38
+ return None
39
+
40
+ # 4. Attempt JSON parsing if requested
41
+ if to_json:
42
+ try:
43
+ return json.loads(sanitized_chunk)
44
+ except json.JSONDecodeError:
45
+ return sanitized_chunk if yield_raw_on_error else None
46
+ except Exception: # Catch other potential JSON errors
47
+ return sanitized_chunk if yield_raw_on_error else None
48
+ else:
49
+ # 5. Return sanitized string if no JSON parsing needed
50
+ return sanitized_chunk
51
+
52
+ # Helper generator to decode bytes and split lines
53
+ def _decode_byte_stream(byte_iterator: Iterable[bytes]) -> Generator[str, None, None]:
54
+ """Decodes bytes from an iterator, handles line splitting, and yields strings."""
55
+ buffer = b""
56
+ decoder = io.TextIOWrapper(io.BytesIO(buffer), encoding='utf-8', errors='ignore') # Use TextIOWrapper for robust decoding
57
+
58
+ for chunk_bytes in byte_iterator:
59
+ if not chunk_bytes:
60
+ continue
61
+
62
+ # Append new bytes to the buffer
63
+ current_pos = decoder.tell()
64
+ decoder.seek(0, io.SEEK_END)
65
+ decoder.buffer.write(chunk_bytes) # type: ignore # Write bytes to underlying buffer
66
+ decoder.seek(current_pos) # Reset position
67
+
68
+ # Read lines
69
+ line = decoder.readline()
70
+ while line:
71
+ if line.endswith('\n'):
72
+ yield line.rstrip('\r\n') # Yield complete line without newline chars
73
+ else:
74
+ # Incomplete line, put it back by adjusting the read position
75
+ decoder.seek(current_pos) # Go back to where we started reading this potential line
76
+ break # Stop reading lines for now, wait for more bytes
77
+ current_pos = decoder.tell() # Update position for next potential line read
78
+ line = decoder.readline()
79
+
80
+ # Yield any remaining data in the buffer after the loop finishes
81
+ remaining = decoder.read()
82
+ if remaining:
83
+ yield remaining.rstrip('\r\n')
7
84
 
8
85
  def sanitize_stream(
9
- chunk: str, intro_value: str = "data:", to_json: bool = True
10
- ) -> Union[str, dict]:
11
- """Remove streaming flags
86
+ data: Union[str, Iterable[str], Iterable[bytes]],
87
+ intro_value: str = "data:",
88
+ to_json: bool = True,
89
+ skip_markers: Optional[List[str]] = None,
90
+ strip_chars: Optional[str] = None,
91
+ start_marker: Optional[str] = None,
92
+ end_marker: Optional[str] = None,
93
+ content_extractor: Optional[Callable[[Union[str, Dict[str, Any]]], Optional[Any]]] = None,
94
+ yield_raw_on_error: bool = True,
95
+ ) -> Generator[Any, None, None]:
96
+ """
97
+ Processes a single string chunk or an iterable stream of text chunks (like SSE).
98
+ Removes prefixes, strips characters, skips markers, optionally parses as JSON,
99
+ and yields the results.
100
+
101
+ This function always returns a generator, even for single string input
102
+ (yielding 0 or 1 item). It can automatically handle byte streams
103
+ (like response.iter_content) and decode them. It can also attempt
104
+ to parse a single input string as JSON if `to_json` is True.
12
105
 
13
106
  Args:
14
- chunk (str): Streamig chunk.
15
- intro_value (str, optional): streaming flag. Defaults to "data:".
16
- to_json (bool, optional). Return chunk as dictionary. Defaults to True.
107
+ data (Union[str, Iterable[str], Iterable[bytes]]):
108
+ A single string chunk, an iterable yielding string chunks,
109
+ or an iterable yielding bytes (like response.iter_content()).
110
+ intro_value (str, optional): The prefix to remove from each chunk/line.
111
+ Set to None or "" to disable prefix removal.
112
+ Defaults to "data:".
113
+ to_json (bool, optional): If True, attempt to parse the sanitized chunk as JSON.
114
+ If False, yield the sanitized string. Defaults to True.
115
+ skip_markers (Optional[List[str]], optional): A list of exact string values
116
+ (after prefix removal and stripping)
117
+ to skip yielding. E.g., ["[DONE]"].
118
+ Defaults to None.
119
+ strip_chars (Optional[str], optional): Characters to strip from the beginning
120
+ and end of the sanitized chunk *before*
121
+ JSON parsing or marker checking. If None (default),
122
+ only leading whitespace is stripped *after*
123
+ prefix removal.
124
+ start_marker (Optional[str], optional): If provided, processing and yielding will
125
+ only begin *after* this exact marker string
126
+ is encountered in the raw input. Defaults to None.
127
+ end_marker (Optional[str], optional): If provided, processing and yielding will
128
+ stop *before* this exact marker string is encountered.
129
+ content_extractor (Optional[Callable]): A function that takes the processed chunk
130
+ (string or dict) and returns the final item
131
+ to yield. If None, the processed chunk is yielded.
132
+ yield_raw_on_error (bool, optional): If True and to_json is True, yield the raw
133
+ sanitized string chunk if JSON parsing fails.
134
+ If False, skip chunks that fail parsing.
135
+ Defaults to True.
17
136
 
18
- Returns:
19
- str: Sanitized streaming value.
137
+ Yields:
138
+ Generator[Any, None, None]: # Yields result of extractor or processed chunk
139
+ Processed chunks (string or dictionary).
140
+ Skips empty chunks, chunks matching skip_markers,
141
+ or chunks failing JSON parse if yield_raw_on_error is False.
142
+
143
+ Raises:
144
+ TypeError: If the input `data` is neither a string nor a valid iterable.
20
145
  """
146
+ effective_skip_markers = skip_markers or []
147
+ processing_active = start_marker is None # Start processing immediately if no start_marker
148
+
149
+ if isinstance(data, str):
150
+ # --- Handle single string input (potentially non-streaming JSON or text) ---
151
+ processed_item = None
152
+ if to_json:
153
+ try:
154
+ # Try parsing the whole string as JSON first
155
+ json_obj = json.loads(data)
156
+ # If successful, treat this as the single item to process
157
+ processed_item = json_obj
158
+ except json.JSONDecodeError:
159
+ # If not JSON, fall back to processing as a single text line
160
+ pass # processed_item remains None
161
+
162
+ if processed_item is None:
163
+ # Process as a single text line (respecting start/end markers if relevant for single line)
164
+ if not processing_active and data == start_marker:
165
+ processing_active = True # Activate processing but don't yield marker
166
+ elif processing_active and end_marker is not None and data == end_marker:
167
+ processing_active = False # Deactivate processing
168
+
169
+ if processing_active:
170
+ # Apply standard chunk processing (prefix, strip, skip markers)
171
+ processed_item = _process_chunk(
172
+ data, intro_value, to_json, effective_skip_markers, strip_chars, yield_raw_on_error
173
+ )
174
+
175
+ # Apply content extractor if an item was processed
176
+ if processed_item is not None:
177
+ if content_extractor:
178
+ try:
179
+ final_content = content_extractor(processed_item)
180
+ if final_content is not None: # Yield whatever the extractor returns if not None
181
+ yield final_content
182
+ except Exception:
183
+ pass # Skip if extractor fails
184
+ else: # Yield directly if no extractor
185
+ yield processed_item
186
+
187
+ elif hasattr(data, '__iter__') or hasattr(data, '__aiter__'): # Check for iterables (sync/async)
188
+ # --- Handle Streaming Input (Bytes or Strings) ---
189
+ data_iter = iter(data) # Get iterator
190
+ try:
191
+ first_item = next(data_iter)
192
+ except StopIteration:
193
+ return # Empty iterable
194
+
195
+ # Reconstruct the iterable including the first item
196
+ from itertools import chain
197
+ reconstructed_iter = chain([first_item], data_iter)
198
+
199
+ # --- Choose processing path based on type ---
200
+ if isinstance(first_item, bytes):
201
+ # Process byte stream
202
+ line_iterator = _decode_byte_stream(reconstructed_iter) # type: ignore
203
+ elif isinstance(first_item, str):
204
+ # Process string stream directly
205
+ line_iterator = reconstructed_iter # type: ignore
206
+ else:
207
+ raise TypeError(f"Iterable must yield strings or bytes, not {type(first_item).__name__}")
21
208
 
22
- if chunk.startswith(intro_value):
23
- chunk = chunk[len(intro_value) :]
209
+ # --- Process the line iterator (now guaranteed to yield strings) ---
210
+ for line in line_iterator:
211
+ # Check start marker if not already active
212
+ if not processing_active and start_marker is not None and line == start_marker:
213
+ processing_active = True
214
+ continue # Skip the marker itself
215
+ # Check end marker if active
216
+ if processing_active and end_marker is not None and line == end_marker:
217
+ processing_active = False
218
+ continue # Skip the marker itself
219
+ # Process and yield if active
220
+ if processing_active:
221
+ processed = _process_chunk(
222
+ line, intro_value, to_json, effective_skip_markers, strip_chars, yield_raw_on_error
223
+ )
224
+ if processed is not None:
225
+ # Apply content extractor
226
+ if content_extractor:
227
+ try:
228
+ final_content = content_extractor(processed)
229
+ if final_content is not None: # Yield whatever the extractor returns if not None
230
+ yield final_content
231
+ except Exception:
232
+ pass # Skip if extractor fails
233
+ else: # Yield directly if no extractor
234
+ yield processed
235
+ else:
236
+ raise TypeError(f"Input must be a string or an iterable, not {type(data).__name__}")
24
237
 
25
- return json.loads(chunk) if to_json else chunk
26
238
 
27
239
  def run_system_command(
28
240
  command: str,
@@ -54,7 +266,7 @@ def run_system_command(
54
266
  if exit_on_error:
55
267
  raise Exception(f"Command failed with exit code {e.returncode}") from e
56
268
  else:
57
- return (False, e)
269
+ return (False, e)
58
270
 
59
271
  class Updates:
60
272
  """Webscout latest release info"""
@@ -129,4 +341,4 @@ from .optimizers import Optimizers
129
341
 
130
342
  from .Extra.autocoder import AutoCoder
131
343
 
132
- from .prompt_manager import AwesomePrompts
344
+ from .prompt_manager import AwesomePrompts