webscout 8.2.8__py3-none-any.whl → 8.2.9__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.
- webscout/AIauto.py +32 -14
- webscout/AIbase.py +96 -37
- webscout/AIutel.py +491 -87
- webscout/Bard.py +441 -323
- webscout/Extra/GitToolkit/__init__.py +10 -10
- webscout/Extra/YTToolkit/ytapi/video.py +232 -232
- webscout/Litlogger/README.md +10 -0
- webscout/Litlogger/__init__.py +7 -59
- webscout/Litlogger/formats.py +4 -0
- webscout/Litlogger/handlers.py +103 -0
- webscout/Litlogger/levels.py +13 -0
- webscout/Litlogger/logger.py +92 -0
- webscout/Provider/AISEARCH/Perplexity.py +332 -358
- webscout/Provider/AISEARCH/felo_search.py +9 -35
- webscout/Provider/AISEARCH/genspark_search.py +30 -56
- webscout/Provider/AISEARCH/hika_search.py +4 -16
- webscout/Provider/AISEARCH/iask_search.py +410 -436
- webscout/Provider/AISEARCH/monica_search.py +4 -30
- webscout/Provider/AISEARCH/scira_search.py +6 -32
- webscout/Provider/AISEARCH/webpilotai_search.py +38 -64
- webscout/Provider/Blackboxai.py +153 -35
- webscout/Provider/Deepinfra.py +339 -339
- webscout/Provider/ExaChat.py +358 -358
- webscout/Provider/Gemini.py +169 -169
- webscout/Provider/GithubChat.py +1 -2
- webscout/Provider/Glider.py +3 -3
- webscout/Provider/HeckAI.py +171 -81
- webscout/Provider/OPENAI/BLACKBOXAI.py +766 -735
- webscout/Provider/OPENAI/Cloudflare.py +7 -7
- webscout/Provider/OPENAI/FreeGemini.py +6 -5
- webscout/Provider/OPENAI/NEMOTRON.py +8 -20
- webscout/Provider/OPENAI/Qwen3.py +283 -0
- webscout/Provider/OPENAI/README.md +952 -1253
- webscout/Provider/OPENAI/TwoAI.py +357 -0
- webscout/Provider/OPENAI/__init__.py +5 -1
- webscout/Provider/OPENAI/ai4chat.py +40 -40
- webscout/Provider/OPENAI/api.py +808 -649
- webscout/Provider/OPENAI/c4ai.py +3 -3
- webscout/Provider/OPENAI/chatgpt.py +555 -555
- webscout/Provider/OPENAI/chatgptclone.py +493 -487
- webscout/Provider/OPENAI/chatsandbox.py +4 -3
- webscout/Provider/OPENAI/copilot.py +242 -0
- webscout/Provider/OPENAI/deepinfra.py +5 -2
- webscout/Provider/OPENAI/e2b.py +63 -5
- webscout/Provider/OPENAI/exaai.py +416 -410
- webscout/Provider/OPENAI/exachat.py +444 -443
- webscout/Provider/OPENAI/freeaichat.py +2 -2
- webscout/Provider/OPENAI/glider.py +5 -2
- webscout/Provider/OPENAI/groq.py +5 -2
- webscout/Provider/OPENAI/heckai.py +308 -307
- webscout/Provider/OPENAI/mcpcore.py +8 -2
- webscout/Provider/OPENAI/multichat.py +4 -4
- webscout/Provider/OPENAI/netwrck.py +6 -5
- webscout/Provider/OPENAI/oivscode.py +287 -0
- webscout/Provider/OPENAI/opkfc.py +496 -496
- webscout/Provider/OPENAI/pydantic_imports.py +172 -0
- webscout/Provider/OPENAI/scirachat.py +15 -9
- webscout/Provider/OPENAI/sonus.py +304 -303
- webscout/Provider/OPENAI/standardinput.py +433 -433
- webscout/Provider/OPENAI/textpollinations.py +4 -4
- webscout/Provider/OPENAI/toolbaz.py +413 -413
- webscout/Provider/OPENAI/typefully.py +3 -3
- webscout/Provider/OPENAI/typegpt.py +11 -5
- webscout/Provider/OPENAI/uncovrAI.py +463 -462
- webscout/Provider/OPENAI/utils.py +90 -79
- webscout/Provider/OPENAI/venice.py +431 -425
- webscout/Provider/OPENAI/wisecat.py +387 -381
- webscout/Provider/OPENAI/writecream.py +3 -3
- webscout/Provider/OPENAI/x0gpt.py +365 -378
- webscout/Provider/OPENAI/yep.py +39 -13
- webscout/Provider/TTI/README.md +55 -101
- webscout/Provider/TTI/__init__.py +4 -9
- webscout/Provider/TTI/aiarta.py +365 -0
- webscout/Provider/TTI/artbit.py +0 -0
- webscout/Provider/TTI/base.py +64 -0
- webscout/Provider/TTI/fastflux.py +200 -0
- webscout/Provider/TTI/magicstudio.py +201 -0
- webscout/Provider/TTI/piclumen.py +203 -0
- webscout/Provider/TTI/pixelmuse.py +225 -0
- webscout/Provider/TTI/pollinations.py +221 -0
- webscout/Provider/TTI/utils.py +11 -0
- webscout/Provider/TTS/__init__.py +2 -1
- webscout/Provider/TTS/base.py +159 -159
- webscout/Provider/TTS/openai_fm.py +129 -0
- webscout/Provider/TextPollinationsAI.py +308 -308
- webscout/Provider/TwoAI.py +239 -44
- webscout/Provider/UNFINISHED/Youchat.py +330 -330
- webscout/Provider/UNFINISHED/puterjs.py +635 -0
- webscout/Provider/UNFINISHED/test_lmarena.py +119 -119
- webscout/Provider/Writecream.py +246 -246
- webscout/Provider/__init__.py +2 -0
- webscout/Provider/ai4chat.py +33 -8
- webscout/Provider/koala.py +169 -169
- webscout/Provider/oivscode.py +309 -0
- webscout/Provider/samurai.py +3 -2
- webscout/Provider/typegpt.py +3 -3
- webscout/Provider/uncovr.py +368 -368
- webscout/client.py +70 -0
- webscout/litprinter/__init__.py +58 -58
- webscout/optimizers.py +419 -419
- webscout/scout/README.md +3 -1
- webscout/scout/core/crawler.py +134 -64
- webscout/scout/core/scout.py +148 -109
- webscout/scout/element.py +106 -88
- webscout/swiftcli/Readme.md +323 -323
- webscout/swiftcli/plugins/manager.py +9 -2
- webscout/version.py +1 -1
- webscout/zeroart/__init__.py +134 -134
- webscout/zeroart/effects.py +100 -100
- webscout/zeroart/fonts.py +1238 -1238
- {webscout-8.2.8.dist-info → webscout-8.2.9.dist-info}/METADATA +159 -35
- {webscout-8.2.8.dist-info → webscout-8.2.9.dist-info}/RECORD +116 -161
- {webscout-8.2.8.dist-info → webscout-8.2.9.dist-info}/WHEEL +1 -1
- {webscout-8.2.8.dist-info → webscout-8.2.9.dist-info}/entry_points.txt +1 -0
- webscout/Litlogger/Readme.md +0 -175
- webscout/Litlogger/core/__init__.py +0 -6
- webscout/Litlogger/core/level.py +0 -23
- webscout/Litlogger/core/logger.py +0 -165
- webscout/Litlogger/handlers/__init__.py +0 -12
- webscout/Litlogger/handlers/console.py +0 -33
- webscout/Litlogger/handlers/file.py +0 -143
- webscout/Litlogger/handlers/network.py +0 -173
- webscout/Litlogger/styles/__init__.py +0 -7
- webscout/Litlogger/styles/colors.py +0 -249
- webscout/Litlogger/styles/formats.py +0 -458
- webscout/Litlogger/styles/text.py +0 -87
- webscout/Litlogger/utils/__init__.py +0 -6
- webscout/Litlogger/utils/detectors.py +0 -153
- webscout/Litlogger/utils/formatters.py +0 -200
- webscout/Provider/TTI/AiForce/README.md +0 -159
- webscout/Provider/TTI/AiForce/__init__.py +0 -22
- webscout/Provider/TTI/AiForce/async_aiforce.py +0 -224
- webscout/Provider/TTI/AiForce/sync_aiforce.py +0 -245
- webscout/Provider/TTI/FreeAIPlayground/README.md +0 -99
- webscout/Provider/TTI/FreeAIPlayground/__init__.py +0 -9
- webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +0 -181
- webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +0 -180
- webscout/Provider/TTI/ImgSys/README.md +0 -174
- webscout/Provider/TTI/ImgSys/__init__.py +0 -23
- webscout/Provider/TTI/ImgSys/async_imgsys.py +0 -202
- webscout/Provider/TTI/ImgSys/sync_imgsys.py +0 -195
- webscout/Provider/TTI/MagicStudio/README.md +0 -101
- webscout/Provider/TTI/MagicStudio/__init__.py +0 -2
- webscout/Provider/TTI/MagicStudio/async_magicstudio.py +0 -111
- webscout/Provider/TTI/MagicStudio/sync_magicstudio.py +0 -109
- webscout/Provider/TTI/Nexra/README.md +0 -155
- webscout/Provider/TTI/Nexra/__init__.py +0 -22
- webscout/Provider/TTI/Nexra/async_nexra.py +0 -286
- webscout/Provider/TTI/Nexra/sync_nexra.py +0 -258
- webscout/Provider/TTI/PollinationsAI/README.md +0 -146
- webscout/Provider/TTI/PollinationsAI/__init__.py +0 -23
- webscout/Provider/TTI/PollinationsAI/async_pollinations.py +0 -311
- webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +0 -265
- webscout/Provider/TTI/aiarta/README.md +0 -134
- webscout/Provider/TTI/aiarta/__init__.py +0 -2
- webscout/Provider/TTI/aiarta/async_aiarta.py +0 -482
- webscout/Provider/TTI/aiarta/sync_aiarta.py +0 -440
- webscout/Provider/TTI/artbit/README.md +0 -100
- webscout/Provider/TTI/artbit/__init__.py +0 -22
- webscout/Provider/TTI/artbit/async_artbit.py +0 -155
- webscout/Provider/TTI/artbit/sync_artbit.py +0 -148
- webscout/Provider/TTI/fastflux/README.md +0 -129
- webscout/Provider/TTI/fastflux/__init__.py +0 -22
- webscout/Provider/TTI/fastflux/async_fastflux.py +0 -261
- webscout/Provider/TTI/fastflux/sync_fastflux.py +0 -252
- webscout/Provider/TTI/huggingface/README.md +0 -114
- webscout/Provider/TTI/huggingface/__init__.py +0 -22
- webscout/Provider/TTI/huggingface/async_huggingface.py +0 -199
- webscout/Provider/TTI/huggingface/sync_huggingface.py +0 -195
- webscout/Provider/TTI/piclumen/README.md +0 -161
- webscout/Provider/TTI/piclumen/__init__.py +0 -23
- webscout/Provider/TTI/piclumen/async_piclumen.py +0 -268
- webscout/Provider/TTI/piclumen/sync_piclumen.py +0 -233
- webscout/Provider/TTI/pixelmuse/README.md +0 -79
- webscout/Provider/TTI/pixelmuse/__init__.py +0 -4
- webscout/Provider/TTI/pixelmuse/async_pixelmuse.py +0 -249
- webscout/Provider/TTI/pixelmuse/sync_pixelmuse.py +0 -182
- webscout/Provider/TTI/talkai/README.md +0 -139
- webscout/Provider/TTI/talkai/__init__.py +0 -4
- webscout/Provider/TTI/talkai/async_talkai.py +0 -229
- webscout/Provider/TTI/talkai/sync_talkai.py +0 -207
- webscout/Provider/UNFINISHED/oivscode.py +0 -351
- {webscout-8.2.8.dist-info → webscout-8.2.9.dist-info}/licenses/LICENSE.md +0 -0
- {webscout-8.2.8.dist-info → webscout-8.2.9.dist-info}/top_level.txt +0 -0
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import textwrap
|
|
2
|
-
from typing import Optional
|
|
3
|
-
|
|
4
|
-
class TextStyle:
|
|
5
|
-
@staticmethod
|
|
6
|
-
def wrap(text: str, width: int = 80, indent: str = "") -> str:
|
|
7
|
-
"""Wrap text to specified width with optional indentation."""
|
|
8
|
-
return textwrap.fill(text, width=width, initial_indent=indent,
|
|
9
|
-
subsequent_indent=indent)
|
|
10
|
-
|
|
11
|
-
@staticmethod
|
|
12
|
-
def truncate(text: str, max_length: int, suffix: str = "...") -> str:
|
|
13
|
-
"""Truncate text to maximum length with suffix."""
|
|
14
|
-
if len(text) <= max_length:
|
|
15
|
-
return text
|
|
16
|
-
return text[:max_length - len(suffix)] + suffix
|
|
17
|
-
|
|
18
|
-
@staticmethod
|
|
19
|
-
def pad(text: str, width: int, align: str = "left",
|
|
20
|
-
fill_char: str = " ") -> str:
|
|
21
|
-
"""Pad text to specified width with alignment."""
|
|
22
|
-
if align == "left":
|
|
23
|
-
return text.ljust(width, fill_char)
|
|
24
|
-
elif align == "right":
|
|
25
|
-
return text.rjust(width, fill_char)
|
|
26
|
-
elif align == "center":
|
|
27
|
-
return text.center(width, fill_char)
|
|
28
|
-
raise ValueError(f"Invalid alignment: {align}")
|
|
29
|
-
|
|
30
|
-
@staticmethod
|
|
31
|
-
def indent(text: str, prefix: str = " ", predicate: Optional[callable] = None) -> str:
|
|
32
|
-
"""Indent text lines with prefix based on optional predicate."""
|
|
33
|
-
lines = text.splitlines(True)
|
|
34
|
-
if predicate is None:
|
|
35
|
-
predicate = bool
|
|
36
|
-
|
|
37
|
-
def should_indent(line):
|
|
38
|
-
return predicate(line)
|
|
39
|
-
|
|
40
|
-
return "".join(prefix + line if should_indent(line) else line
|
|
41
|
-
for line in lines)
|
|
42
|
-
|
|
43
|
-
@staticmethod
|
|
44
|
-
def highlight(text: str, substring: str, color: str) -> str:
|
|
45
|
-
"""Highlight substring within text using ANSI color codes."""
|
|
46
|
-
from ..styles.colors import LogColors
|
|
47
|
-
if not substring:
|
|
48
|
-
return text
|
|
49
|
-
|
|
50
|
-
parts = text.split(substring)
|
|
51
|
-
highlighted = f"{color}{substring}{LogColors.RESET}"
|
|
52
|
-
return highlighted.join(parts)
|
|
53
|
-
|
|
54
|
-
@staticmethod
|
|
55
|
-
def table(headers: list, rows: list, padding: int = 1) -> str:
|
|
56
|
-
"""Create a formatted table with headers and rows."""
|
|
57
|
-
if not rows:
|
|
58
|
-
return ""
|
|
59
|
-
|
|
60
|
-
# Calculate column widths
|
|
61
|
-
widths = [max(len(str(row[i])) for row in [headers] + rows)
|
|
62
|
-
for i in range(len(headers))]
|
|
63
|
-
|
|
64
|
-
# Create separator line
|
|
65
|
-
separator = "+" + "+".join("-" * (w + 2 * padding) for w in widths) + "+"
|
|
66
|
-
|
|
67
|
-
# Format header
|
|
68
|
-
header = "|" + "|".join(
|
|
69
|
-
str(h).center(w + 2 * padding) for h, w in zip(headers, widths)
|
|
70
|
-
) + "|"
|
|
71
|
-
|
|
72
|
-
# Format rows
|
|
73
|
-
formatted_rows = []
|
|
74
|
-
for row in rows:
|
|
75
|
-
formatted_row = "|" + "|".join(
|
|
76
|
-
str(cell).ljust(w + 2 * padding) for cell, w in zip(row, widths)
|
|
77
|
-
) + "|"
|
|
78
|
-
formatted_rows.append(formatted_row)
|
|
79
|
-
|
|
80
|
-
# Combine all parts
|
|
81
|
-
return "\n".join([
|
|
82
|
-
separator,
|
|
83
|
-
header,
|
|
84
|
-
separator,
|
|
85
|
-
*formatted_rows,
|
|
86
|
-
separator
|
|
87
|
-
])
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import sys
|
|
3
|
-
from typing import Optional
|
|
4
|
-
from ..core.level import LogLevel
|
|
5
|
-
|
|
6
|
-
class LevelDetector:
|
|
7
|
-
"""Utility class for intelligent log level detection."""
|
|
8
|
-
|
|
9
|
-
# Common patterns indicating error conditions
|
|
10
|
-
ERROR_PATTERNS = [
|
|
11
|
-
r"error",
|
|
12
|
-
r"exception",
|
|
13
|
-
r"failed",
|
|
14
|
-
r"failure",
|
|
15
|
-
r"traceback",
|
|
16
|
-
r"crash",
|
|
17
|
-
r"fatal",
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
# Common patterns indicating warning conditions
|
|
21
|
-
WARNING_PATTERNS = [
|
|
22
|
-
r"warning",
|
|
23
|
-
r"warn",
|
|
24
|
-
r"deprecated",
|
|
25
|
-
r"might",
|
|
26
|
-
r"consider",
|
|
27
|
-
r"attention",
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
# Common patterns indicating debug information
|
|
31
|
-
DEBUG_PATTERNS = [
|
|
32
|
-
r"debug",
|
|
33
|
-
r"trace",
|
|
34
|
-
r"verbose",
|
|
35
|
-
r"detail",
|
|
36
|
-
]
|
|
37
|
-
|
|
38
|
-
@classmethod
|
|
39
|
-
def detect_level(cls, message: str, exception: Optional[Exception] = None) -> LogLevel:
|
|
40
|
-
"""
|
|
41
|
-
Detect appropriate log level from message content and context.
|
|
42
|
-
|
|
43
|
-
Args:
|
|
44
|
-
message: Log message to analyze
|
|
45
|
-
exception: Optional exception object
|
|
46
|
-
|
|
47
|
-
Returns:
|
|
48
|
-
Detected LogLevel
|
|
49
|
-
"""
|
|
50
|
-
# If there's an exception, it's at least ERROR
|
|
51
|
-
if exception is not None:
|
|
52
|
-
if isinstance(exception, (SystemExit, KeyboardInterrupt)):
|
|
53
|
-
return LogLevel.CRITICAL
|
|
54
|
-
return LogLevel.ERROR
|
|
55
|
-
|
|
56
|
-
# Convert to lowercase for pattern matching
|
|
57
|
-
message_lower = message.lower()
|
|
58
|
-
|
|
59
|
-
# Check for error patterns
|
|
60
|
-
for pattern in cls.ERROR_PATTERNS:
|
|
61
|
-
if re.search(pattern, message_lower):
|
|
62
|
-
return LogLevel.ERROR
|
|
63
|
-
|
|
64
|
-
# Check for warning patterns
|
|
65
|
-
for pattern in cls.WARNING_PATTERNS:
|
|
66
|
-
if re.search(pattern, message_lower):
|
|
67
|
-
return LogLevel.WARNING
|
|
68
|
-
|
|
69
|
-
# Check for debug patterns
|
|
70
|
-
for pattern in cls.DEBUG_PATTERNS:
|
|
71
|
-
if re.search(pattern, message_lower):
|
|
72
|
-
return LogLevel.DEBUG
|
|
73
|
-
|
|
74
|
-
# Default to INFO
|
|
75
|
-
return LogLevel.INFO
|
|
76
|
-
|
|
77
|
-
@classmethod
|
|
78
|
-
def detect_level_from_exception(cls, exc_type, exc_value, exc_tb) -> LogLevel:
|
|
79
|
-
"""
|
|
80
|
-
Detect log level from exception information.
|
|
81
|
-
|
|
82
|
-
Args:
|
|
83
|
-
exc_type: Exception type
|
|
84
|
-
exc_value: Exception value
|
|
85
|
-
exc_tb: Exception traceback
|
|
86
|
-
|
|
87
|
-
Returns:
|
|
88
|
-
Detected LogLevel
|
|
89
|
-
"""
|
|
90
|
-
# Critical errors that should terminate execution
|
|
91
|
-
if exc_type in (SystemExit, KeyboardInterrupt, MemoryError):
|
|
92
|
-
return LogLevel.CRITICAL
|
|
93
|
-
|
|
94
|
-
# Built-in exceptions that indicate programming errors
|
|
95
|
-
if exc_type in (
|
|
96
|
-
SyntaxError,
|
|
97
|
-
IndentationError,
|
|
98
|
-
NameError,
|
|
99
|
-
TypeError,
|
|
100
|
-
AttributeError
|
|
101
|
-
):
|
|
102
|
-
return LogLevel.ERROR
|
|
103
|
-
|
|
104
|
-
# Runtime errors that might be recoverable
|
|
105
|
-
if exc_type in (
|
|
106
|
-
ValueError,
|
|
107
|
-
KeyError,
|
|
108
|
-
IOError,
|
|
109
|
-
OSError,
|
|
110
|
-
ConnectionError
|
|
111
|
-
):
|
|
112
|
-
return LogLevel.WARNING
|
|
113
|
-
|
|
114
|
-
# Default to ERROR for unknown exception types
|
|
115
|
-
return LogLevel.ERROR
|
|
116
|
-
|
|
117
|
-
@classmethod
|
|
118
|
-
def detect_level_from_frame(cls, frame_depth: int = 1) -> LogLevel:
|
|
119
|
-
"""
|
|
120
|
-
Detect log level by analyzing the call stack.
|
|
121
|
-
|
|
122
|
-
Args:
|
|
123
|
-
frame_depth: How many frames up to look (1 = caller's frame)
|
|
124
|
-
|
|
125
|
-
Returns:
|
|
126
|
-
Detected LogLevel
|
|
127
|
-
"""
|
|
128
|
-
try:
|
|
129
|
-
frame = sys._getframe(frame_depth)
|
|
130
|
-
|
|
131
|
-
# Check function/method name
|
|
132
|
-
code = frame.f_code
|
|
133
|
-
func_name = code.co_name.lower()
|
|
134
|
-
|
|
135
|
-
if any(p in func_name for p in ["error", "fail", "crash"]):
|
|
136
|
-
return LogLevel.ERROR
|
|
137
|
-
if any(p in func_name for p in ["warn"]):
|
|
138
|
-
return LogLevel.WARNING
|
|
139
|
-
if any(p in func_name for p in ["debug", "trace"]):
|
|
140
|
-
return LogLevel.DEBUG
|
|
141
|
-
|
|
142
|
-
# Check local variables for exceptions
|
|
143
|
-
locals_dict = frame.f_locals
|
|
144
|
-
for value in locals_dict.values():
|
|
145
|
-
if isinstance(value, Exception):
|
|
146
|
-
return cls.detect_level_from_exception(
|
|
147
|
-
type(value), value, value.__traceback__
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
return LogLevel.INFO
|
|
151
|
-
|
|
152
|
-
except Exception:
|
|
153
|
-
return LogLevel.INFO # Default if detection fails
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import re
|
|
3
|
-
import traceback
|
|
4
|
-
from datetime import datetime
|
|
5
|
-
from typing import Any, Dict, Optional, Union
|
|
6
|
-
|
|
7
|
-
class MessageFormatter:
|
|
8
|
-
"""Utility class for formatting log messages."""
|
|
9
|
-
|
|
10
|
-
@staticmethod
|
|
11
|
-
def format_exception(exc_info: tuple) -> str:
|
|
12
|
-
"""
|
|
13
|
-
Format exception information into a readable string.
|
|
14
|
-
|
|
15
|
-
Args:
|
|
16
|
-
exc_info: Tuple of (type, value, traceback)
|
|
17
|
-
|
|
18
|
-
Returns:
|
|
19
|
-
Formatted exception string
|
|
20
|
-
"""
|
|
21
|
-
return "".join(traceback.format_exception(*exc_info))
|
|
22
|
-
|
|
23
|
-
@staticmethod
|
|
24
|
-
def format_dict(data: Dict[str, Any], indent: int = 2) -> str:
|
|
25
|
-
"""
|
|
26
|
-
Format dictionary into pretty-printed string.
|
|
27
|
-
|
|
28
|
-
Args:
|
|
29
|
-
data: Dictionary to format
|
|
30
|
-
indent: Number of spaces for indentation
|
|
31
|
-
|
|
32
|
-
Returns:
|
|
33
|
-
Formatted string representation
|
|
34
|
-
"""
|
|
35
|
-
return json.dumps(data, indent=indent, default=str, ensure_ascii=False)
|
|
36
|
-
|
|
37
|
-
@staticmethod
|
|
38
|
-
def format_object(obj: Any) -> str:
|
|
39
|
-
"""
|
|
40
|
-
Format any object into a string representation.
|
|
41
|
-
|
|
42
|
-
Args:
|
|
43
|
-
obj: Object to format
|
|
44
|
-
|
|
45
|
-
Returns:
|
|
46
|
-
String representation of object
|
|
47
|
-
"""
|
|
48
|
-
if hasattr(obj, "to_dict"):
|
|
49
|
-
return MessageFormatter.format_dict(obj.to_dict())
|
|
50
|
-
if hasattr(obj, "__dict__"):
|
|
51
|
-
return MessageFormatter.format_dict(obj.__dict__)
|
|
52
|
-
return str(obj)
|
|
53
|
-
|
|
54
|
-
@staticmethod
|
|
55
|
-
def truncate(message: str, max_length: int = 1000, suffix: str = "...") -> str:
|
|
56
|
-
"""
|
|
57
|
-
Truncate message to maximum length.
|
|
58
|
-
|
|
59
|
-
Args:
|
|
60
|
-
message: Message to truncate
|
|
61
|
-
max_length: Maximum length
|
|
62
|
-
suffix: String to append when truncated
|
|
63
|
-
|
|
64
|
-
Returns:
|
|
65
|
-
Truncated message
|
|
66
|
-
"""
|
|
67
|
-
if len(message) <= max_length:
|
|
68
|
-
return message
|
|
69
|
-
return message[:max_length - len(suffix)] + suffix
|
|
70
|
-
|
|
71
|
-
@staticmethod
|
|
72
|
-
def mask_sensitive(message: str, patterns: Dict[str, str]) -> str:
|
|
73
|
-
"""
|
|
74
|
-
Mask sensitive information in message.
|
|
75
|
-
|
|
76
|
-
Args:
|
|
77
|
-
message: Message to process
|
|
78
|
-
patterns: Dictionary of {pattern: mask}
|
|
79
|
-
|
|
80
|
-
Returns:
|
|
81
|
-
Message with sensitive info masked
|
|
82
|
-
"""
|
|
83
|
-
result = message
|
|
84
|
-
for pattern, mask in patterns.items():
|
|
85
|
-
result = re.sub(pattern, mask, result)
|
|
86
|
-
return result
|
|
87
|
-
|
|
88
|
-
@staticmethod
|
|
89
|
-
def format_context(context: Dict[str, Any]) -> str:
|
|
90
|
-
"""
|
|
91
|
-
Format context dictionary into readable string.
|
|
92
|
-
|
|
93
|
-
Args:
|
|
94
|
-
context: Context dictionary
|
|
95
|
-
|
|
96
|
-
Returns:
|
|
97
|
-
Formatted context string
|
|
98
|
-
"""
|
|
99
|
-
parts = []
|
|
100
|
-
for key, value in sorted(context.items()):
|
|
101
|
-
formatted_value = (
|
|
102
|
-
MessageFormatter.format_object(value)
|
|
103
|
-
if isinstance(value, (dict, list, tuple))
|
|
104
|
-
else str(value)
|
|
105
|
-
)
|
|
106
|
-
parts.append(f"{key}={formatted_value}")
|
|
107
|
-
return " ".join(parts)
|
|
108
|
-
|
|
109
|
-
@staticmethod
|
|
110
|
-
def format_metrics(metrics: Dict[str, Union[int, float]]) -> str:
|
|
111
|
-
"""
|
|
112
|
-
Format performance metrics into readable string.
|
|
113
|
-
|
|
114
|
-
Args:
|
|
115
|
-
metrics: Dictionary of metric names and values
|
|
116
|
-
|
|
117
|
-
Returns:
|
|
118
|
-
Formatted metrics string
|
|
119
|
-
"""
|
|
120
|
-
parts = []
|
|
121
|
-
for key, value in sorted(metrics.items()):
|
|
122
|
-
if isinstance(value, float):
|
|
123
|
-
formatted = f"{value:.3f}"
|
|
124
|
-
else:
|
|
125
|
-
formatted = str(value)
|
|
126
|
-
parts.append(f"{key}={formatted}")
|
|
127
|
-
return " ".join(parts)
|
|
128
|
-
|
|
129
|
-
@staticmethod
|
|
130
|
-
def format_timestamp(
|
|
131
|
-
timestamp: Optional[datetime] = None,
|
|
132
|
-
format: str = "%Y-%m-%d %H:%M:%S.%f"
|
|
133
|
-
) -> str:
|
|
134
|
-
"""
|
|
135
|
-
Format timestamp into string.
|
|
136
|
-
|
|
137
|
-
Args:
|
|
138
|
-
timestamp: Datetime object (uses current time if None)
|
|
139
|
-
format: strftime format string
|
|
140
|
-
|
|
141
|
-
Returns:
|
|
142
|
-
Formatted timestamp string
|
|
143
|
-
"""
|
|
144
|
-
if timestamp is None:
|
|
145
|
-
timestamp = datetime.now()
|
|
146
|
-
return timestamp.strftime(format)
|
|
147
|
-
|
|
148
|
-
@classmethod
|
|
149
|
-
def format_message(
|
|
150
|
-
cls,
|
|
151
|
-
message: str,
|
|
152
|
-
context: Optional[Dict[str, Any]] = None,
|
|
153
|
-
metrics: Optional[Dict[str, Union[int, float]]] = None,
|
|
154
|
-
max_length: Optional[int] = None,
|
|
155
|
-
mask_patterns: Optional[Dict[str, str]] = None,
|
|
156
|
-
timestamp_format: Optional[str] = None
|
|
157
|
-
) -> str:
|
|
158
|
-
"""
|
|
159
|
-
Format complete log message with all options.
|
|
160
|
-
|
|
161
|
-
Args:
|
|
162
|
-
message: Base message
|
|
163
|
-
context: Optional context dictionary
|
|
164
|
-
metrics: Optional performance metrics
|
|
165
|
-
max_length: Optional maximum length
|
|
166
|
-
mask_patterns: Optional sensitive data patterns
|
|
167
|
-
timestamp_format: Optional timestamp format
|
|
168
|
-
|
|
169
|
-
Returns:
|
|
170
|
-
Formatted complete message
|
|
171
|
-
"""
|
|
172
|
-
parts = []
|
|
173
|
-
|
|
174
|
-
# Add timestamp
|
|
175
|
-
if timestamp_format:
|
|
176
|
-
parts.append(cls.format_timestamp(format=timestamp_format))
|
|
177
|
-
|
|
178
|
-
# Add main message
|
|
179
|
-
parts.append(message)
|
|
180
|
-
|
|
181
|
-
# Add context if present
|
|
182
|
-
if context:
|
|
183
|
-
parts.append(cls.format_context(context))
|
|
184
|
-
|
|
185
|
-
# Add metrics if present
|
|
186
|
-
if metrics:
|
|
187
|
-
parts.append(cls.format_metrics(metrics))
|
|
188
|
-
|
|
189
|
-
# Join all parts
|
|
190
|
-
result = " ".join(parts)
|
|
191
|
-
|
|
192
|
-
# Apply masking if needed
|
|
193
|
-
if mask_patterns:
|
|
194
|
-
result = cls.mask_sensitive(result, mask_patterns)
|
|
195
|
-
|
|
196
|
-
# Apply length limit if needed
|
|
197
|
-
if max_length:
|
|
198
|
-
result = cls.truncate(result, max_length)
|
|
199
|
-
|
|
200
|
-
return result
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
# AiForce Provider 🔥
|
|
2
|
-
|
|
3
|
-
Yo fam! This is the AiForce provider for generating some fire images! Part of the HelpingAI squad! 👑
|
|
4
|
-
|
|
5
|
-
## Features 💪
|
|
6
|
-
|
|
7
|
-
- Both sync and async support ⚡
|
|
8
|
-
- 12 fire models to choose from 🎨
|
|
9
|
-
- Smart retry mechanism 🔄
|
|
10
|
-
- Custom image sizes 📐
|
|
11
|
-
- Save with custom names 💾
|
|
12
|
-
- Fire logging with cyberpunk theme 🌟
|
|
13
|
-
- Proxy support for stealth mode 🕵️♂️
|
|
14
|
-
|
|
15
|
-
## Quick Start 🚀
|
|
16
|
-
|
|
17
|
-
### Installation 📦
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
pip install webscout
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### Basic Usage 💫
|
|
24
|
-
|
|
25
|
-
```python
|
|
26
|
-
# Sync way
|
|
27
|
-
from webscout import AiForceimager
|
|
28
|
-
|
|
29
|
-
provider = AiForceimager()
|
|
30
|
-
images = provider.generate("Epic dragon")
|
|
31
|
-
paths = provider.save(images)
|
|
32
|
-
|
|
33
|
-
# Async way
|
|
34
|
-
from webscout import AsyncAiForceimager
|
|
35
|
-
import asyncio
|
|
36
|
-
|
|
37
|
-
async def generate():
|
|
38
|
-
provider = AsyncAiForceimager()
|
|
39
|
-
images = await provider.generate("Cool art")
|
|
40
|
-
paths = await provider.save(images)
|
|
41
|
-
|
|
42
|
-
asyncio.run(generate())
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Available Models 🎭
|
|
46
|
-
|
|
47
|
-
| Model | Description | Best For |
|
|
48
|
-
|-------|-------------|----------|
|
|
49
|
-
| `Flux-1.1-Pro` | Latest pro model (Default) | High quality general purpose |
|
|
50
|
-
| `stable-diffusion-xl-lightning` | Fast SDXL model | Quick generations |
|
|
51
|
-
| `stable-diffusion-xl-base` | Base SDXL model | High quality base |
|
|
52
|
-
| `ideogram` | Artistic model | Creative artwork |
|
|
53
|
-
| `flux` | Standard model | General purpose |
|
|
54
|
-
| `flux-realism` | Photorealistic model | Realistic images |
|
|
55
|
-
| `flux-anime` | Anime style | Anime/manga art |
|
|
56
|
-
| `flux-3d` | 3D rendering | 3D objects/scenes |
|
|
57
|
-
| `flux-disney` | Disney style | Disney-like art |
|
|
58
|
-
| `flux-pixel` | Pixel art | Retro/game art |
|
|
59
|
-
| `flux-4o` | 4k output | High resolution |
|
|
60
|
-
| `any-dark` | Dark theme | Gothic/dark art |
|
|
61
|
-
|
|
62
|
-
## Advanced Examples 🔥
|
|
63
|
-
|
|
64
|
-
### Custom Settings 🛠️
|
|
65
|
-
|
|
66
|
-
```python
|
|
67
|
-
provider = AiForceimager(
|
|
68
|
-
timeout=120, # Longer timeout
|
|
69
|
-
proxies={
|
|
70
|
-
'http': 'http://proxy.example.com:8080'
|
|
71
|
-
}
|
|
72
|
-
)
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### Multiple Images with Custom Size 📸
|
|
76
|
-
|
|
77
|
-
```python
|
|
78
|
-
images = provider.generate(
|
|
79
|
-
prompt="A shiny red sports car",
|
|
80
|
-
amount=3, # Generate 3 images
|
|
81
|
-
model="flux-realism", # Use realistic model
|
|
82
|
-
width=1024, # Custom width
|
|
83
|
-
height=768, # Custom height
|
|
84
|
-
seed=42 # For reproducible results
|
|
85
|
-
)
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Custom Save Options 💾
|
|
89
|
-
|
|
90
|
-
```python
|
|
91
|
-
paths = provider.save(
|
|
92
|
-
images,
|
|
93
|
-
name="sports_car", # Custom name
|
|
94
|
-
dir="my_images", # Custom directory
|
|
95
|
-
filenames_prefix="v1_" # Add prefix
|
|
96
|
-
)
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### Async with Error Handling ⚡
|
|
100
|
-
|
|
101
|
-
```python
|
|
102
|
-
async def generate_safely():
|
|
103
|
-
provider = AsyncAiForceimager()
|
|
104
|
-
try:
|
|
105
|
-
images = await provider.generate(
|
|
106
|
-
prompt="Epic dragon",
|
|
107
|
-
model="flux-3d",
|
|
108
|
-
amount=2
|
|
109
|
-
)
|
|
110
|
-
paths = await provider.save(images, dir="dragons")
|
|
111
|
-
print(f"Saved to: {paths}")
|
|
112
|
-
except Exception as e:
|
|
113
|
-
print(f"Oops! Something went wrong: {e}")
|
|
114
|
-
|
|
115
|
-
asyncio.run(generate_safely())
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## Tips & Tricks 💡
|
|
119
|
-
|
|
120
|
-
1. Use `flux-realism` for photorealistic images
|
|
121
|
-
2. Use `flux-3d` for product renders
|
|
122
|
-
3. Use `flux-anime` for anime style art
|
|
123
|
-
4. Set custom timeouts for large images
|
|
124
|
-
5. Use proxies for better reliability
|
|
125
|
-
6. Add seed for reproducible results
|
|
126
|
-
|
|
127
|
-
## Error Handling 🛡️
|
|
128
|
-
|
|
129
|
-
The provider handles common errors:
|
|
130
|
-
|
|
131
|
-
- Network issues
|
|
132
|
-
- API timeouts
|
|
133
|
-
- Invalid inputs
|
|
134
|
-
- File saving errors
|
|
135
|
-
|
|
136
|
-
Example with retry:
|
|
137
|
-
|
|
138
|
-
```python
|
|
139
|
-
provider = AiForceimager()
|
|
140
|
-
try:
|
|
141
|
-
images = provider.generate(
|
|
142
|
-
"Epic scene",
|
|
143
|
-
max_retries=5, # More retries
|
|
144
|
-
retry_delay=10 # Longer delay
|
|
145
|
-
)
|
|
146
|
-
except Exception as e:
|
|
147
|
-
print(f"Generation failed: {e}")
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## Contributing 🤝
|
|
151
|
-
|
|
152
|
-
Pull up to the squad! We're always looking for improvements:
|
|
153
|
-
|
|
154
|
-
1. Fork it
|
|
155
|
-
2. Create your feature branch
|
|
156
|
-
3. Push your changes
|
|
157
|
-
4. Hit us with that pull request
|
|
158
|
-
|
|
159
|
-
Made with 💖 by the HelpingAI Team
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
AiForce - Your go-to provider for generating fire images! 🔥
|
|
3
|
-
|
|
4
|
-
Examples:
|
|
5
|
-
>>> # Sync Usage
|
|
6
|
-
>>> from webscout import AiForceimager
|
|
7
|
-
>>> provider = AiForceimager()
|
|
8
|
-
>>> images = provider.generate("Cool art")
|
|
9
|
-
>>> paths = provider.save(images)
|
|
10
|
-
>>>
|
|
11
|
-
>>> # Async Usage
|
|
12
|
-
>>> from webscout import AsyncAiForceimager
|
|
13
|
-
>>> async def example():
|
|
14
|
-
... provider = AsyncAiForceimager()
|
|
15
|
-
... images = await provider.generate("Epic dragon")
|
|
16
|
-
... paths = await provider.save(images)
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
from .sync_aiforce import AiForceimager
|
|
20
|
-
from .async_aiforce import AsyncAiForceimager
|
|
21
|
-
|
|
22
|
-
__all__ = ["AiForceimager", "AsyncAiForceimager"]
|