webscout 8.3.6__py3-none-any.whl → 2025.10.11__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.
- webscout/AIauto.py +250 -250
- webscout/AIbase.py +379 -379
- webscout/AIutel.py +60 -58
- webscout/Bard.py +1012 -1012
- webscout/Bing_search.py +417 -417
- webscout/DWEBS.py +529 -529
- webscout/Extra/Act.md +309 -309
- webscout/Extra/GitToolkit/__init__.py +10 -10
- webscout/Extra/GitToolkit/gitapi/README.md +110 -110
- webscout/Extra/GitToolkit/gitapi/__init__.py +11 -11
- webscout/Extra/GitToolkit/gitapi/repository.py +195 -195
- webscout/Extra/GitToolkit/gitapi/user.py +96 -96
- webscout/Extra/GitToolkit/gitapi/utils.py +61 -61
- webscout/Extra/YTToolkit/README.md +375 -375
- webscout/Extra/YTToolkit/YTdownloader.py +956 -956
- webscout/Extra/YTToolkit/__init__.py +2 -2
- webscout/Extra/YTToolkit/transcriber.py +475 -475
- webscout/Extra/YTToolkit/ytapi/README.md +44 -44
- webscout/Extra/YTToolkit/ytapi/__init__.py +6 -6
- webscout/Extra/YTToolkit/ytapi/channel.py +307 -307
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -13
- webscout/Extra/YTToolkit/ytapi/extras.py +118 -118
- webscout/Extra/YTToolkit/ytapi/https.py +88 -88
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -61
- webscout/Extra/YTToolkit/ytapi/playlist.py +58 -58
- webscout/Extra/YTToolkit/ytapi/pool.py +7 -7
- webscout/Extra/YTToolkit/ytapi/query.py +39 -39
- webscout/Extra/YTToolkit/ytapi/stream.py +62 -62
- webscout/Extra/YTToolkit/ytapi/utils.py +62 -62
- webscout/Extra/YTToolkit/ytapi/video.py +232 -232
- webscout/Extra/autocoder/__init__.py +9 -9
- webscout/Extra/autocoder/autocoder.py +1105 -1105
- webscout/Extra/autocoder/autocoder_utiles.py +332 -332
- webscout/Extra/gguf.md +429 -429
- webscout/Extra/gguf.py +1213 -1213
- webscout/Extra/tempmail/README.md +487 -487
- webscout/Extra/tempmail/__init__.py +27 -27
- webscout/Extra/tempmail/async_utils.py +140 -140
- webscout/Extra/tempmail/base.py +160 -160
- webscout/Extra/tempmail/cli.py +186 -186
- webscout/Extra/tempmail/emailnator.py +84 -84
- webscout/Extra/tempmail/mail_tm.py +360 -360
- webscout/Extra/tempmail/temp_mail_io.py +291 -291
- webscout/Extra/weather.md +281 -281
- webscout/Extra/weather.py +193 -193
- webscout/Litlogger/README.md +10 -10
- webscout/Litlogger/__init__.py +15 -15
- webscout/Litlogger/formats.py +13 -13
- webscout/Litlogger/handlers.py +121 -121
- webscout/Litlogger/levels.py +13 -13
- webscout/Litlogger/logger.py +134 -134
- webscout/Provider/AISEARCH/Perplexity.py +332 -332
- webscout/Provider/AISEARCH/README.md +279 -279
- webscout/Provider/AISEARCH/__init__.py +33 -11
- webscout/Provider/AISEARCH/felo_search.py +206 -206
- webscout/Provider/AISEARCH/genspark_search.py +323 -323
- webscout/Provider/AISEARCH/hika_search.py +185 -185
- webscout/Provider/AISEARCH/iask_search.py +410 -410
- webscout/Provider/AISEARCH/monica_search.py +219 -219
- webscout/Provider/AISEARCH/scira_search.py +316 -314
- webscout/Provider/AISEARCH/stellar_search.py +177 -177
- webscout/Provider/AISEARCH/webpilotai_search.py +255 -255
- webscout/Provider/Aitopia.py +314 -315
- webscout/Provider/Andi.py +3 -3
- webscout/Provider/Apriel.py +306 -0
- webscout/Provider/ChatGPTClone.py +236 -236
- webscout/Provider/ChatSandbox.py +343 -342
- webscout/Provider/Cloudflare.py +324 -324
- webscout/Provider/Cohere.py +208 -207
- webscout/Provider/Deepinfra.py +370 -369
- webscout/Provider/ExaAI.py +260 -260
- webscout/Provider/ExaChat.py +308 -387
- webscout/Provider/Flowith.py +221 -221
- webscout/Provider/GMI.py +293 -0
- webscout/Provider/Gemini.py +164 -162
- webscout/Provider/GeminiProxy.py +167 -166
- webscout/Provider/GithubChat.py +371 -370
- webscout/Provider/Groq.py +800 -800
- webscout/Provider/HeckAI.py +383 -379
- webscout/Provider/Jadve.py +282 -297
- webscout/Provider/K2Think.py +308 -0
- webscout/Provider/Koboldai.py +206 -384
- webscout/Provider/LambdaChat.py +423 -425
- webscout/Provider/Nemotron.py +244 -245
- webscout/Provider/Netwrck.py +248 -247
- webscout/Provider/OLLAMA.py +395 -394
- webscout/Provider/OPENAI/Cloudflare.py +394 -395
- webscout/Provider/OPENAI/FalconH1.py +452 -457
- webscout/Provider/OPENAI/FreeGemini.py +297 -299
- webscout/Provider/OPENAI/{monochat.py → K2Think.py} +432 -329
- webscout/Provider/OPENAI/NEMOTRON.py +241 -244
- webscout/Provider/OPENAI/PI.py +428 -427
- webscout/Provider/OPENAI/README.md +959 -959
- webscout/Provider/OPENAI/TogetherAI.py +345 -345
- webscout/Provider/OPENAI/TwoAI.py +466 -467
- webscout/Provider/OPENAI/__init__.py +33 -59
- webscout/Provider/OPENAI/ai4chat.py +313 -303
- webscout/Provider/OPENAI/base.py +249 -269
- webscout/Provider/OPENAI/chatglm.py +528 -0
- webscout/Provider/OPENAI/chatgpt.py +593 -588
- webscout/Provider/OPENAI/chatgptclone.py +521 -524
- webscout/Provider/OPENAI/chatsandbox.py +202 -177
- webscout/Provider/OPENAI/deepinfra.py +319 -315
- webscout/Provider/OPENAI/e2b.py +1665 -1665
- webscout/Provider/OPENAI/exaai.py +420 -420
- webscout/Provider/OPENAI/exachat.py +452 -452
- webscout/Provider/OPENAI/friendli.py +232 -232
- webscout/Provider/OPENAI/{refact.py → gmi.py} +324 -274
- webscout/Provider/OPENAI/groq.py +364 -364
- webscout/Provider/OPENAI/heckai.py +314 -311
- webscout/Provider/OPENAI/llmchatco.py +337 -337
- webscout/Provider/OPENAI/netwrck.py +355 -354
- webscout/Provider/OPENAI/oivscode.py +290 -290
- webscout/Provider/OPENAI/opkfc.py +518 -518
- webscout/Provider/OPENAI/pydantic_imports.py +1 -1
- webscout/Provider/OPENAI/scirachat.py +535 -529
- webscout/Provider/OPENAI/sonus.py +308 -308
- webscout/Provider/OPENAI/standardinput.py +442 -442
- webscout/Provider/OPENAI/textpollinations.py +340 -348
- webscout/Provider/OPENAI/toolbaz.py +419 -413
- webscout/Provider/OPENAI/typefully.py +362 -362
- webscout/Provider/OPENAI/utils.py +295 -295
- webscout/Provider/OPENAI/venice.py +436 -436
- webscout/Provider/OPENAI/wisecat.py +387 -387
- webscout/Provider/OPENAI/writecream.py +166 -166
- webscout/Provider/OPENAI/x0gpt.py +378 -378
- webscout/Provider/OPENAI/yep.py +389 -389
- webscout/Provider/OpenGPT.py +230 -230
- webscout/Provider/Openai.py +244 -496
- webscout/Provider/PI.py +405 -404
- webscout/Provider/Perplexitylabs.py +430 -431
- webscout/Provider/QwenLM.py +272 -254
- webscout/Provider/STT/__init__.py +32 -2
- webscout/Provider/{Llama3.py → Sambanova.py} +257 -258
- webscout/Provider/StandardInput.py +309 -309
- webscout/Provider/TTI/README.md +82 -82
- webscout/Provider/TTI/__init__.py +33 -12
- webscout/Provider/TTI/aiarta.py +413 -413
- webscout/Provider/TTI/base.py +136 -136
- webscout/Provider/TTI/bing.py +243 -243
- webscout/Provider/TTI/gpt1image.py +149 -149
- webscout/Provider/TTI/imagen.py +196 -196
- webscout/Provider/TTI/infip.py +211 -211
- webscout/Provider/TTI/magicstudio.py +232 -232
- webscout/Provider/TTI/monochat.py +219 -219
- webscout/Provider/TTI/piclumen.py +214 -214
- webscout/Provider/TTI/pixelmuse.py +232 -232
- webscout/Provider/TTI/pollinations.py +232 -232
- webscout/Provider/TTI/together.py +288 -288
- webscout/Provider/TTI/utils.py +12 -12
- webscout/Provider/TTI/venice.py +367 -367
- webscout/Provider/TTS/README.md +192 -192
- webscout/Provider/TTS/__init__.py +33 -10
- webscout/Provider/TTS/parler.py +110 -110
- webscout/Provider/TTS/streamElements.py +333 -333
- webscout/Provider/TTS/utils.py +280 -280
- webscout/Provider/TeachAnything.py +237 -236
- webscout/Provider/TextPollinationsAI.py +311 -318
- webscout/Provider/TogetherAI.py +356 -357
- webscout/Provider/TwoAI.py +313 -569
- webscout/Provider/TypliAI.py +312 -311
- webscout/Provider/UNFINISHED/ChatHub.py +208 -208
- webscout/Provider/UNFINISHED/ChutesAI.py +313 -313
- webscout/Provider/{GizAI.py → UNFINISHED/GizAI.py} +294 -294
- webscout/Provider/{Marcus.py → UNFINISHED/Marcus.py} +198 -198
- webscout/Provider/{Qodo.py → UNFINISHED/Qodo.py} +477 -477
- webscout/Provider/UNFINISHED/VercelAIGateway.py +338 -338
- webscout/Provider/{XenAI.py → UNFINISHED/XenAI.py} +324 -324
- webscout/Provider/UNFINISHED/Youchat.py +330 -330
- webscout/Provider/UNFINISHED/liner.py +334 -0
- webscout/Provider/UNFINISHED/liner_api_request.py +262 -262
- webscout/Provider/UNFINISHED/puterjs.py +634 -634
- webscout/Provider/UNFINISHED/samurai.py +223 -223
- webscout/Provider/UNFINISHED/test_lmarena.py +119 -119
- webscout/Provider/Venice.py +251 -250
- webscout/Provider/VercelAI.py +256 -255
- webscout/Provider/WiseCat.py +232 -231
- webscout/Provider/WrDoChat.py +367 -366
- webscout/Provider/__init__.py +33 -86
- webscout/Provider/ai4chat.py +174 -174
- webscout/Provider/akashgpt.py +331 -334
- webscout/Provider/cerebras.py +446 -340
- webscout/Provider/chatglm.py +394 -214
- webscout/Provider/cleeai.py +211 -212
- webscout/Provider/deepseek_assistant.py +1 -1
- webscout/Provider/elmo.py +282 -282
- webscout/Provider/geminiapi.py +208 -208
- webscout/Provider/granite.py +261 -261
- webscout/Provider/hermes.py +263 -265
- webscout/Provider/julius.py +223 -222
- webscout/Provider/learnfastai.py +309 -309
- webscout/Provider/llama3mitril.py +214 -214
- webscout/Provider/llmchat.py +243 -243
- webscout/Provider/llmchatco.py +290 -290
- webscout/Provider/meta.py +801 -801
- webscout/Provider/oivscode.py +309 -309
- webscout/Provider/scira_chat.py +384 -457
- webscout/Provider/searchchat.py +292 -291
- webscout/Provider/sonus.py +258 -258
- webscout/Provider/toolbaz.py +370 -364
- webscout/Provider/turboseek.py +274 -265
- webscout/Provider/typefully.py +208 -207
- webscout/Provider/x0gpt.py +1 -0
- webscout/Provider/yep.py +372 -371
- webscout/__init__.py +30 -31
- webscout/__main__.py +5 -5
- webscout/auth/api_key_manager.py +189 -189
- webscout/auth/config.py +175 -175
- webscout/auth/models.py +185 -185
- webscout/auth/routes.py +664 -664
- webscout/auth/simple_logger.py +236 -236
- webscout/cli.py +523 -523
- webscout/conversation.py +438 -438
- webscout/exceptions.py +361 -361
- webscout/litagent/Readme.md +298 -298
- webscout/litagent/__init__.py +28 -28
- webscout/litagent/agent.py +581 -581
- webscout/litagent/constants.py +59 -59
- webscout/litprinter/__init__.py +58 -58
- webscout/models.py +181 -181
- webscout/optimizers.py +419 -419
- webscout/prompt_manager.py +288 -288
- webscout/sanitize.py +1078 -1078
- webscout/scout/README.md +401 -401
- webscout/scout/__init__.py +8 -8
- webscout/scout/core/__init__.py +6 -6
- webscout/scout/core/crawler.py +297 -297
- webscout/scout/core/scout.py +706 -706
- webscout/scout/core/search_result.py +95 -95
- webscout/scout/core/text_analyzer.py +62 -62
- webscout/scout/core/text_utils.py +277 -277
- webscout/scout/core/web_analyzer.py +51 -51
- webscout/scout/element.py +599 -599
- webscout/scout/parsers/__init__.py +69 -69
- webscout/scout/parsers/html5lib_parser.py +172 -172
- webscout/scout/parsers/html_parser.py +236 -236
- webscout/scout/parsers/lxml_parser.py +178 -178
- webscout/scout/utils.py +37 -37
- webscout/swiftcli/Readme.md +323 -323
- webscout/swiftcli/__init__.py +95 -95
- webscout/swiftcli/core/__init__.py +7 -7
- webscout/swiftcli/core/cli.py +308 -308
- webscout/swiftcli/core/context.py +104 -104
- webscout/swiftcli/core/group.py +241 -241
- webscout/swiftcli/decorators/__init__.py +28 -28
- webscout/swiftcli/decorators/command.py +221 -221
- webscout/swiftcli/decorators/options.py +220 -220
- webscout/swiftcli/decorators/output.py +302 -302
- webscout/swiftcli/exceptions.py +21 -21
- webscout/swiftcli/plugins/__init__.py +9 -9
- webscout/swiftcli/plugins/base.py +135 -135
- webscout/swiftcli/plugins/manager.py +269 -269
- webscout/swiftcli/utils/__init__.py +59 -59
- webscout/swiftcli/utils/formatting.py +252 -252
- webscout/swiftcli/utils/parsing.py +267 -267
- webscout/update_checker.py +117 -117
- webscout/version.py +1 -1
- webscout/webscout_search.py +1183 -1183
- webscout/webscout_search_async.py +649 -649
- webscout/yep_search.py +346 -346
- webscout/zeroart/README.md +89 -89
- webscout/zeroart/__init__.py +134 -134
- webscout/zeroart/base.py +66 -66
- webscout/zeroart/effects.py +100 -100
- webscout/zeroart/fonts.py +1238 -1238
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/METADATA +937 -936
- webscout-2025.10.11.dist-info/RECORD +300 -0
- webscout/Provider/AISEARCH/DeepFind.py +0 -254
- webscout/Provider/AllenAI.py +0 -440
- webscout/Provider/Blackboxai.py +0 -793
- webscout/Provider/FreeGemini.py +0 -250
- webscout/Provider/GptOss.py +0 -207
- webscout/Provider/Hunyuan.py +0 -283
- webscout/Provider/Kimi.py +0 -445
- webscout/Provider/MCPCore.py +0 -322
- webscout/Provider/MiniMax.py +0 -207
- webscout/Provider/OPENAI/BLACKBOXAI.py +0 -1045
- webscout/Provider/OPENAI/MiniMax.py +0 -298
- webscout/Provider/OPENAI/Qwen3.py +0 -304
- webscout/Provider/OPENAI/autoproxy.py +0 -1067
- webscout/Provider/OPENAI/copilot.py +0 -321
- webscout/Provider/OPENAI/gptoss.py +0 -288
- webscout/Provider/OPENAI/kimi.py +0 -469
- webscout/Provider/OPENAI/mcpcore.py +0 -431
- webscout/Provider/OPENAI/multichat.py +0 -378
- webscout/Provider/OPENAI/qodo.py +0 -630
- webscout/Provider/OPENAI/xenai.py +0 -514
- webscout/Provider/Reka.py +0 -214
- webscout/Provider/UNFINISHED/fetch_together_models.py +0 -90
- webscout/Provider/asksteve.py +0 -220
- webscout/Provider/copilot.py +0 -441
- webscout/Provider/freeaichat.py +0 -294
- webscout/Provider/koala.py +0 -182
- webscout/Provider/lmarena.py +0 -198
- webscout/Provider/monochat.py +0 -275
- webscout/Provider/multichat.py +0 -375
- webscout/Provider/scnet.py +0 -244
- webscout/Provider/talkai.py +0 -194
- webscout/tempid.py +0 -128
- webscout-8.3.6.dist-info/RECORD +0 -327
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/WHEEL +0 -0
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/entry_points.txt +0 -0
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/licenses/LICENSE.md +0 -0
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/top_level.txt +0 -0
webscout/auth/config.py
CHANGED
|
@@ -1,175 +1,175 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Configuration management for the Webscout API server.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import os
|
|
6
|
-
from typing import List, Dict, Optional, Any
|
|
7
|
-
from webscout.Litlogger import Logger, LogLevel, LogFormat, ConsoleHandler
|
|
8
|
-
import sys
|
|
9
|
-
|
|
10
|
-
# Configuration constants
|
|
11
|
-
DEFAULT_PORT = 8000
|
|
12
|
-
DEFAULT_HOST = "0.0.0.0"
|
|
13
|
-
|
|
14
|
-
# Setup logger
|
|
15
|
-
logger = Logger(
|
|
16
|
-
name="webscout.api",
|
|
17
|
-
level=LogLevel.INFO,
|
|
18
|
-
handlers=[ConsoleHandler(stream=sys.stdout)],
|
|
19
|
-
fmt=LogFormat.DEFAULT
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def _get_supabase_url() -> Optional[str]:
|
|
24
|
-
"""Get Supabase URL from environment variables or GitHub secrets."""
|
|
25
|
-
# Try environment variable first
|
|
26
|
-
url = os.getenv("SUPABASE_URL")
|
|
27
|
-
if url:
|
|
28
|
-
logger.info("📍 Using SUPABASE_URL from environment")
|
|
29
|
-
return url
|
|
30
|
-
|
|
31
|
-
# Try to get from GitHub secrets (if running in GitHub Actions)
|
|
32
|
-
github_url = os.getenv("GITHUB_SUPABASE_URL") # GitHub Actions secret
|
|
33
|
-
if github_url:
|
|
34
|
-
logger.info("📍 Using SUPABASE_URL from GitHub secrets")
|
|
35
|
-
return github_url
|
|
36
|
-
|
|
37
|
-
# Don't log error during import - only when actually needed
|
|
38
|
-
return None
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def _get_supabase_anon_key() -> Optional[str]:
|
|
42
|
-
"""Get Supabase anon key from environment variables or GitHub secrets."""
|
|
43
|
-
# Try environment variable first
|
|
44
|
-
key = os.getenv("SUPABASE_ANON_KEY")
|
|
45
|
-
if key:
|
|
46
|
-
logger.info("🔑 Using SUPABASE_ANON_KEY from environment")
|
|
47
|
-
return key
|
|
48
|
-
|
|
49
|
-
# Try to get from GitHub secrets (if running in GitHub Actions)
|
|
50
|
-
github_key = os.getenv("GITHUB_SUPABASE_ANON_KEY") # GitHub Actions secret
|
|
51
|
-
if github_key:
|
|
52
|
-
logger.info("🔑 Using SUPABASE_ANON_KEY from GitHub secrets")
|
|
53
|
-
return github_key
|
|
54
|
-
|
|
55
|
-
# Don't log error during import - only when actually needed
|
|
56
|
-
return None
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class ServerConfig:
|
|
60
|
-
"""Centralized configuration management for the API server."""
|
|
61
|
-
|
|
62
|
-
def __init__(self):
|
|
63
|
-
self.api_key: Optional[str] = None
|
|
64
|
-
self.provider_map: Dict[str, Any] = {}
|
|
65
|
-
self.default_provider: str = "ChatGPT"
|
|
66
|
-
self.base_url: Optional[str] = None
|
|
67
|
-
self.host: str = DEFAULT_HOST
|
|
68
|
-
self.port: int = DEFAULT_PORT
|
|
69
|
-
self.debug: bool = False
|
|
70
|
-
self.cors_origins: List[str] = ["*"]
|
|
71
|
-
self.max_request_size: int = 10 * 1024 * 1024 # 10MB
|
|
72
|
-
self.request_timeout: int = 300 # 5 minutes
|
|
73
|
-
self.auth_required: bool = os.getenv("WEBSCOUT_AUTH_REQUIRED", "false").lower() == "true" # Default to no auth
|
|
74
|
-
self.rate_limit_enabled: bool = os.getenv("WEBSCOUT_RATE_LIMIT_ENABLED", "false").lower() == "true" # Default to no rate limit
|
|
75
|
-
self.default_rate_limit: int = 60 # Default rate limit for no-auth mode
|
|
76
|
-
self.request_logging_enabled: bool = os.getenv("WEBSCOUT_REQUEST_LOGGING", "true").lower() == "true" # Enable request logging by default
|
|
77
|
-
|
|
78
|
-
# Database configuration - lazy initialization
|
|
79
|
-
self._supabase_url: Optional[str] = None
|
|
80
|
-
self._supabase_anon_key: Optional[str] = None
|
|
81
|
-
self._supabase_url_checked: bool = False
|
|
82
|
-
self._supabase_anon_key_checked: bool = False
|
|
83
|
-
self.mongodb_url: Optional[str] = os.getenv("MONGODB_URL")
|
|
84
|
-
|
|
85
|
-
@property
|
|
86
|
-
def supabase_url(self) -> Optional[str]:
|
|
87
|
-
"""Get Supabase URL with lazy initialization."""
|
|
88
|
-
if not self._supabase_url_checked:
|
|
89
|
-
self._supabase_url = _get_supabase_url()
|
|
90
|
-
self._supabase_url_checked = True
|
|
91
|
-
return self._supabase_url
|
|
92
|
-
|
|
93
|
-
@property
|
|
94
|
-
def supabase_anon_key(self) -> Optional[str]:
|
|
95
|
-
"""Get Supabase anon key with lazy initialization."""
|
|
96
|
-
if not self._supabase_anon_key_checked:
|
|
97
|
-
self._supabase_anon_key = _get_supabase_anon_key()
|
|
98
|
-
self._supabase_anon_key_checked = True
|
|
99
|
-
return self._supabase_anon_key
|
|
100
|
-
|
|
101
|
-
def update(self, **kwargs) -> None:
|
|
102
|
-
"""Update configuration with provided values."""
|
|
103
|
-
for key, value in kwargs.items():
|
|
104
|
-
if hasattr(self, key) and value is not None:
|
|
105
|
-
setattr(self, key, value)
|
|
106
|
-
logger.info(f"Config updated: {key} = {value}")
|
|
107
|
-
|
|
108
|
-
def validate(self) -> None:
|
|
109
|
-
"""Validate configuration settings."""
|
|
110
|
-
if self.port < 1 or self.port > 65535:
|
|
111
|
-
raise ValueError(f"Invalid port number: {self.port}")
|
|
112
|
-
|
|
113
|
-
if self.default_provider not in self.provider_map and self.provider_map:
|
|
114
|
-
available_providers = list(set(v.__name__ for v in self.provider_map.values()))
|
|
115
|
-
logger.warning(f"Default provider '{self.default_provider}' not found. Available: {available_providers}")
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
class AppConfig:
|
|
119
|
-
"""Legacy configuration class for backward compatibility."""
|
|
120
|
-
api_key: Optional[str] = None
|
|
121
|
-
provider_map = {}
|
|
122
|
-
tti_provider_map = {} # Add TTI provider map
|
|
123
|
-
default_provider = "ChatGPT"
|
|
124
|
-
default_tti_provider = "PollinationsAI" # Add default TTI provider
|
|
125
|
-
base_url: Optional[str] = None
|
|
126
|
-
auth_required: bool = os.getenv("WEBSCOUT_AUTH_REQUIRED", "false").lower() == "true" # Default to no auth
|
|
127
|
-
rate_limit_enabled: bool = os.getenv("WEBSCOUT_RATE_LIMIT_ENABLED", "false").lower() == "true" # Default to no rate limit
|
|
128
|
-
default_rate_limit: int = 60 # Default rate limit for no-auth mode
|
|
129
|
-
request_logging_enabled: bool = os.getenv("WEBSCOUT_REQUEST_LOGGING", "true").lower() == "true" # Enable request logging by default
|
|
130
|
-
|
|
131
|
-
# Database configuration - lazy initialization
|
|
132
|
-
_supabase_url: Optional[str] = None
|
|
133
|
-
_supabase_anon_key: Optional[str] = None
|
|
134
|
-
_supabase_url_checked: bool = False
|
|
135
|
-
_supabase_anon_key_checked: bool = False
|
|
136
|
-
mongodb_url: Optional[str] = os.getenv("MONGODB_URL")
|
|
137
|
-
|
|
138
|
-
@classmethod
|
|
139
|
-
def get_supabase_url(cls) -> Optional[str]:
|
|
140
|
-
"""Get Supabase URL with lazy initialization."""
|
|
141
|
-
if not cls._supabase_url_checked:
|
|
142
|
-
cls._supabase_url = _get_supabase_url()
|
|
143
|
-
cls._supabase_url_checked = True
|
|
144
|
-
return cls._supabase_url
|
|
145
|
-
|
|
146
|
-
@classmethod
|
|
147
|
-
def get_supabase_anon_key(cls) -> Optional[str]:
|
|
148
|
-
"""Get Supabase anon key with lazy initialization."""
|
|
149
|
-
if not cls._supabase_anon_key_checked:
|
|
150
|
-
cls._supabase_anon_key = _get_supabase_anon_key()
|
|
151
|
-
cls._supabase_anon_key_checked = True
|
|
152
|
-
return cls._supabase_anon_key
|
|
153
|
-
|
|
154
|
-
# For backward compatibility, provide properties that call the methods
|
|
155
|
-
@property
|
|
156
|
-
def supabase_url(self) -> Optional[str]:
|
|
157
|
-
return self.__class__.get_supabase_url()
|
|
158
|
-
|
|
159
|
-
@property
|
|
160
|
-
def supabase_anon_key(self) -> Optional[str]:
|
|
161
|
-
return self.__class__.get_supabase_anon_key()
|
|
162
|
-
|
|
163
|
-
@classmethod
|
|
164
|
-
def set_config(cls, **data):
|
|
165
|
-
"""Set configuration values."""
|
|
166
|
-
for key, value in data.items():
|
|
167
|
-
setattr(cls, key, value)
|
|
168
|
-
# Sync with new config system
|
|
169
|
-
try:
|
|
170
|
-
from .server import get_config
|
|
171
|
-
config = get_config()
|
|
172
|
-
config.update(**data)
|
|
173
|
-
except ImportError:
|
|
174
|
-
# Handle case where server module is not available
|
|
175
|
-
pass
|
|
1
|
+
"""
|
|
2
|
+
Configuration management for the Webscout API server.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from typing import List, Dict, Optional, Any
|
|
7
|
+
from webscout.Litlogger import Logger, LogLevel, LogFormat, ConsoleHandler
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
# Configuration constants
|
|
11
|
+
DEFAULT_PORT = 8000
|
|
12
|
+
DEFAULT_HOST = "0.0.0.0"
|
|
13
|
+
|
|
14
|
+
# Setup logger
|
|
15
|
+
logger = Logger(
|
|
16
|
+
name="webscout.api",
|
|
17
|
+
level=LogLevel.INFO,
|
|
18
|
+
handlers=[ConsoleHandler(stream=sys.stdout)],
|
|
19
|
+
fmt=LogFormat.DEFAULT
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _get_supabase_url() -> Optional[str]:
|
|
24
|
+
"""Get Supabase URL from environment variables or GitHub secrets."""
|
|
25
|
+
# Try environment variable first
|
|
26
|
+
url = os.getenv("SUPABASE_URL")
|
|
27
|
+
if url:
|
|
28
|
+
logger.info("📍 Using SUPABASE_URL from environment")
|
|
29
|
+
return url
|
|
30
|
+
|
|
31
|
+
# Try to get from GitHub secrets (if running in GitHub Actions)
|
|
32
|
+
github_url = os.getenv("GITHUB_SUPABASE_URL") # GitHub Actions secret
|
|
33
|
+
if github_url:
|
|
34
|
+
logger.info("📍 Using SUPABASE_URL from GitHub secrets")
|
|
35
|
+
return github_url
|
|
36
|
+
|
|
37
|
+
# Don't log error during import - only when actually needed
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _get_supabase_anon_key() -> Optional[str]:
|
|
42
|
+
"""Get Supabase anon key from environment variables or GitHub secrets."""
|
|
43
|
+
# Try environment variable first
|
|
44
|
+
key = os.getenv("SUPABASE_ANON_KEY")
|
|
45
|
+
if key:
|
|
46
|
+
logger.info("🔑 Using SUPABASE_ANON_KEY from environment")
|
|
47
|
+
return key
|
|
48
|
+
|
|
49
|
+
# Try to get from GitHub secrets (if running in GitHub Actions)
|
|
50
|
+
github_key = os.getenv("GITHUB_SUPABASE_ANON_KEY") # GitHub Actions secret
|
|
51
|
+
if github_key:
|
|
52
|
+
logger.info("🔑 Using SUPABASE_ANON_KEY from GitHub secrets")
|
|
53
|
+
return github_key
|
|
54
|
+
|
|
55
|
+
# Don't log error during import - only when actually needed
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ServerConfig:
|
|
60
|
+
"""Centralized configuration management for the API server."""
|
|
61
|
+
|
|
62
|
+
def __init__(self):
|
|
63
|
+
self.api_key: Optional[str] = None
|
|
64
|
+
self.provider_map: Dict[str, Any] = {}
|
|
65
|
+
self.default_provider: str = "ChatGPT"
|
|
66
|
+
self.base_url: Optional[str] = None
|
|
67
|
+
self.host: str = DEFAULT_HOST
|
|
68
|
+
self.port: int = DEFAULT_PORT
|
|
69
|
+
self.debug: bool = False
|
|
70
|
+
self.cors_origins: List[str] = ["*"]
|
|
71
|
+
self.max_request_size: int = 10 * 1024 * 1024 # 10MB
|
|
72
|
+
self.request_timeout: int = 300 # 5 minutes
|
|
73
|
+
self.auth_required: bool = os.getenv("WEBSCOUT_AUTH_REQUIRED", "false").lower() == "true" # Default to no auth
|
|
74
|
+
self.rate_limit_enabled: bool = os.getenv("WEBSCOUT_RATE_LIMIT_ENABLED", "false").lower() == "true" # Default to no rate limit
|
|
75
|
+
self.default_rate_limit: int = 60 # Default rate limit for no-auth mode
|
|
76
|
+
self.request_logging_enabled: bool = os.getenv("WEBSCOUT_REQUEST_LOGGING", "true").lower() == "true" # Enable request logging by default
|
|
77
|
+
|
|
78
|
+
# Database configuration - lazy initialization
|
|
79
|
+
self._supabase_url: Optional[str] = None
|
|
80
|
+
self._supabase_anon_key: Optional[str] = None
|
|
81
|
+
self._supabase_url_checked: bool = False
|
|
82
|
+
self._supabase_anon_key_checked: bool = False
|
|
83
|
+
self.mongodb_url: Optional[str] = os.getenv("MONGODB_URL")
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def supabase_url(self) -> Optional[str]:
|
|
87
|
+
"""Get Supabase URL with lazy initialization."""
|
|
88
|
+
if not self._supabase_url_checked:
|
|
89
|
+
self._supabase_url = _get_supabase_url()
|
|
90
|
+
self._supabase_url_checked = True
|
|
91
|
+
return self._supabase_url
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def supabase_anon_key(self) -> Optional[str]:
|
|
95
|
+
"""Get Supabase anon key with lazy initialization."""
|
|
96
|
+
if not self._supabase_anon_key_checked:
|
|
97
|
+
self._supabase_anon_key = _get_supabase_anon_key()
|
|
98
|
+
self._supabase_anon_key_checked = True
|
|
99
|
+
return self._supabase_anon_key
|
|
100
|
+
|
|
101
|
+
def update(self, **kwargs) -> None:
|
|
102
|
+
"""Update configuration with provided values."""
|
|
103
|
+
for key, value in kwargs.items():
|
|
104
|
+
if hasattr(self, key) and value is not None:
|
|
105
|
+
setattr(self, key, value)
|
|
106
|
+
logger.info(f"Config updated: {key} = {value}")
|
|
107
|
+
|
|
108
|
+
def validate(self) -> None:
|
|
109
|
+
"""Validate configuration settings."""
|
|
110
|
+
if self.port < 1 or self.port > 65535:
|
|
111
|
+
raise ValueError(f"Invalid port number: {self.port}")
|
|
112
|
+
|
|
113
|
+
if self.default_provider not in self.provider_map and self.provider_map:
|
|
114
|
+
available_providers = list(set(v.__name__ for v in self.provider_map.values()))
|
|
115
|
+
logger.warning(f"Default provider '{self.default_provider}' not found. Available: {available_providers}")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class AppConfig:
|
|
119
|
+
"""Legacy configuration class for backward compatibility."""
|
|
120
|
+
api_key: Optional[str] = None
|
|
121
|
+
provider_map = {}
|
|
122
|
+
tti_provider_map = {} # Add TTI provider map
|
|
123
|
+
default_provider = "ChatGPT"
|
|
124
|
+
default_tti_provider = "PollinationsAI" # Add default TTI provider
|
|
125
|
+
base_url: Optional[str] = None
|
|
126
|
+
auth_required: bool = os.getenv("WEBSCOUT_AUTH_REQUIRED", "false").lower() == "true" # Default to no auth
|
|
127
|
+
rate_limit_enabled: bool = os.getenv("WEBSCOUT_RATE_LIMIT_ENABLED", "false").lower() == "true" # Default to no rate limit
|
|
128
|
+
default_rate_limit: int = 60 # Default rate limit for no-auth mode
|
|
129
|
+
request_logging_enabled: bool = os.getenv("WEBSCOUT_REQUEST_LOGGING", "true").lower() == "true" # Enable request logging by default
|
|
130
|
+
|
|
131
|
+
# Database configuration - lazy initialization
|
|
132
|
+
_supabase_url: Optional[str] = None
|
|
133
|
+
_supabase_anon_key: Optional[str] = None
|
|
134
|
+
_supabase_url_checked: bool = False
|
|
135
|
+
_supabase_anon_key_checked: bool = False
|
|
136
|
+
mongodb_url: Optional[str] = os.getenv("MONGODB_URL")
|
|
137
|
+
|
|
138
|
+
@classmethod
|
|
139
|
+
def get_supabase_url(cls) -> Optional[str]:
|
|
140
|
+
"""Get Supabase URL with lazy initialization."""
|
|
141
|
+
if not cls._supabase_url_checked:
|
|
142
|
+
cls._supabase_url = _get_supabase_url()
|
|
143
|
+
cls._supabase_url_checked = True
|
|
144
|
+
return cls._supabase_url
|
|
145
|
+
|
|
146
|
+
@classmethod
|
|
147
|
+
def get_supabase_anon_key(cls) -> Optional[str]:
|
|
148
|
+
"""Get Supabase anon key with lazy initialization."""
|
|
149
|
+
if not cls._supabase_anon_key_checked:
|
|
150
|
+
cls._supabase_anon_key = _get_supabase_anon_key()
|
|
151
|
+
cls._supabase_anon_key_checked = True
|
|
152
|
+
return cls._supabase_anon_key
|
|
153
|
+
|
|
154
|
+
# For backward compatibility, provide properties that call the methods
|
|
155
|
+
@property
|
|
156
|
+
def supabase_url(self) -> Optional[str]:
|
|
157
|
+
return self.__class__.get_supabase_url()
|
|
158
|
+
|
|
159
|
+
@property
|
|
160
|
+
def supabase_anon_key(self) -> Optional[str]:
|
|
161
|
+
return self.__class__.get_supabase_anon_key()
|
|
162
|
+
|
|
163
|
+
@classmethod
|
|
164
|
+
def set_config(cls, **data):
|
|
165
|
+
"""Set configuration values."""
|
|
166
|
+
for key, value in data.items():
|
|
167
|
+
setattr(cls, key, value)
|
|
168
|
+
# Sync with new config system
|
|
169
|
+
try:
|
|
170
|
+
from .server import get_config
|
|
171
|
+
config = get_config()
|
|
172
|
+
config.update(**data)
|
|
173
|
+
except ImportError:
|
|
174
|
+
# Handle case where server module is not available
|
|
175
|
+
pass
|