webscout 8.2.3__py3-none-any.whl → 8.2.4__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.
- inferno/lol.py +589 -0
- webscout/AIutel.py +226 -14
- webscout/Bard.py +579 -206
- webscout/DWEBS.py +78 -35
- webscout/Extra/tempmail/base.py +1 -1
- webscout/Provider/AISEARCH/hika_search.py +4 -0
- webscout/Provider/AllenAI.py +163 -126
- webscout/Provider/ChatGPTClone.py +96 -84
- webscout/Provider/Deepinfra.py +95 -67
- webscout/Provider/ElectronHub.py +55 -0
- webscout/Provider/GPTWeb.py +96 -46
- webscout/Provider/Groq.py +194 -91
- webscout/Provider/HeckAI.py +89 -47
- webscout/Provider/HuggingFaceChat.py +113 -106
- webscout/Provider/Hunyuan.py +94 -83
- webscout/Provider/Jadve.py +107 -75
- webscout/Provider/LambdaChat.py +106 -64
- webscout/Provider/Llama3.py +94 -39
- webscout/Provider/MCPCore.py +318 -0
- webscout/Provider/Marcus.py +85 -36
- webscout/Provider/Netwrck.py +76 -43
- webscout/Provider/OPENAI/__init__.py +4 -1
- webscout/Provider/OPENAI/ai4chat.py +286 -0
- webscout/Provider/OPENAI/chatgptclone.py +35 -14
- webscout/Provider/OPENAI/deepinfra.py +37 -0
- webscout/Provider/OPENAI/groq.py +354 -0
- webscout/Provider/OPENAI/heckai.py +6 -2
- webscout/Provider/OPENAI/mcpcore.py +376 -0
- webscout/Provider/OPENAI/multichat.py +368 -0
- webscout/Provider/OPENAI/netwrck.py +3 -1
- webscout/Provider/OpenGPT.py +48 -38
- webscout/Provider/PI.py +168 -92
- webscout/Provider/PizzaGPT.py +66 -36
- webscout/Provider/TeachAnything.py +85 -51
- webscout/Provider/TextPollinationsAI.py +109 -51
- webscout/Provider/TwoAI.py +109 -60
- webscout/Provider/Venice.py +93 -56
- webscout/Provider/VercelAI.py +2 -2
- webscout/Provider/WiseCat.py +65 -28
- webscout/Provider/Writecream.py +37 -11
- webscout/Provider/WritingMate.py +135 -63
- webscout/Provider/__init__.py +3 -21
- webscout/Provider/ai4chat.py +6 -7
- webscout/Provider/copilot.py +0 -3
- webscout/Provider/elmo.py +101 -58
- webscout/Provider/granite.py +91 -46
- webscout/Provider/hermes.py +87 -47
- webscout/Provider/koala.py +1 -1
- webscout/Provider/learnfastai.py +104 -50
- webscout/Provider/llama3mitril.py +86 -51
- webscout/Provider/llmchat.py +88 -46
- webscout/Provider/llmchatco.py +74 -49
- webscout/Provider/meta.py +41 -37
- webscout/Provider/multichat.py +54 -25
- webscout/Provider/scnet.py +93 -43
- webscout/Provider/searchchat.py +82 -75
- webscout/Provider/sonus.py +103 -51
- webscout/Provider/toolbaz.py +132 -77
- webscout/Provider/turboseek.py +92 -41
- webscout/Provider/tutorai.py +82 -64
- webscout/Provider/typefully.py +75 -33
- webscout/Provider/typegpt.py +96 -35
- webscout/Provider/uncovr.py +112 -62
- webscout/Provider/x0gpt.py +69 -26
- webscout/Provider/yep.py +79 -66
- webscout/conversation.py +35 -21
- webscout/exceptions.py +20 -0
- webscout/prompt_manager.py +56 -42
- webscout/version.py +1 -1
- webscout/webscout_search.py +65 -47
- webscout/webscout_search_async.py +81 -126
- webscout/yep_search.py +93 -43
- {webscout-8.2.3.dist-info → webscout-8.2.4.dist-info}/METADATA +22 -10
- {webscout-8.2.3.dist-info → webscout-8.2.4.dist-info}/RECORD +78 -81
- {webscout-8.2.3.dist-info → webscout-8.2.4.dist-info}/WHEEL +1 -1
- webscout/Provider/C4ai.py +0 -432
- webscout/Provider/ChatGPTES.py +0 -237
- webscout/Provider/DeepSeek.py +0 -196
- webscout/Provider/Llama.py +0 -200
- webscout/Provider/Phind.py +0 -535
- webscout/Provider/WebSim.py +0 -228
- webscout/Provider/labyrinth.py +0 -340
- webscout/Provider/lepton.py +0 -194
- webscout/Provider/llamatutor.py +0 -192
- {webscout-8.2.3.dist-info → webscout-8.2.4.dist-info}/entry_points.txt +0 -0
- {webscout-8.2.3.dist-info → webscout-8.2.4.dist-info/licenses}/LICENSE.md +0 -0
- {webscout-8.2.3.dist-info → webscout-8.2.4.dist-info}/top_level.txt +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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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
|
-
|
|
23
|
-
|
|
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
|