webscout 8.2.9__py3-none-any.whl → 2026.1.19__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 +524 -251
- webscout/AIbase.py +247 -319
- webscout/AIutel.py +68 -703
- webscout/Bard.py +1072 -1026
- webscout/Extra/GitToolkit/__init__.py +10 -10
- webscout/Extra/GitToolkit/gitapi/__init__.py +20 -12
- webscout/Extra/GitToolkit/gitapi/gist.py +142 -0
- webscout/Extra/GitToolkit/gitapi/organization.py +91 -0
- webscout/Extra/GitToolkit/gitapi/repository.py +308 -195
- webscout/Extra/GitToolkit/gitapi/search.py +162 -0
- webscout/Extra/GitToolkit/gitapi/trending.py +236 -0
- webscout/Extra/GitToolkit/gitapi/user.py +128 -96
- webscout/Extra/GitToolkit/gitapi/utils.py +82 -62
- webscout/Extra/YTToolkit/README.md +443 -375
- webscout/Extra/YTToolkit/YTdownloader.py +953 -957
- webscout/Extra/YTToolkit/__init__.py +3 -3
- webscout/Extra/YTToolkit/transcriber.py +595 -476
- webscout/Extra/YTToolkit/ytapi/README.md +230 -44
- webscout/Extra/YTToolkit/ytapi/__init__.py +22 -6
- webscout/Extra/YTToolkit/ytapi/captions.py +190 -0
- webscout/Extra/YTToolkit/ytapi/channel.py +302 -307
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -13
- webscout/Extra/YTToolkit/ytapi/extras.py +178 -118
- webscout/Extra/YTToolkit/ytapi/hashtag.py +120 -0
- webscout/Extra/YTToolkit/ytapi/https.py +89 -88
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -61
- webscout/Extra/YTToolkit/ytapi/playlist.py +59 -59
- webscout/Extra/YTToolkit/ytapi/pool.py +8 -8
- webscout/Extra/YTToolkit/ytapi/query.py +143 -40
- webscout/Extra/YTToolkit/ytapi/shorts.py +122 -0
- webscout/Extra/YTToolkit/ytapi/stream.py +68 -63
- webscout/Extra/YTToolkit/ytapi/suggestions.py +97 -0
- webscout/Extra/YTToolkit/ytapi/utils.py +66 -62
- webscout/Extra/YTToolkit/ytapi/video.py +403 -232
- webscout/Extra/__init__.py +2 -3
- webscout/Extra/gguf.py +1298 -684
- webscout/Extra/tempmail/README.md +487 -487
- webscout/Extra/tempmail/__init__.py +28 -28
- webscout/Extra/tempmail/async_utils.py +143 -141
- webscout/Extra/tempmail/base.py +172 -161
- webscout/Extra/tempmail/cli.py +191 -187
- webscout/Extra/tempmail/emailnator.py +88 -84
- webscout/Extra/tempmail/mail_tm.py +378 -361
- webscout/Extra/tempmail/temp_mail_io.py +304 -292
- webscout/Extra/weather.py +196 -194
- webscout/Extra/weather_ascii.py +17 -15
- webscout/Provider/AISEARCH/PERPLEXED_search.py +175 -0
- webscout/Provider/AISEARCH/Perplexity.py +292 -333
- webscout/Provider/AISEARCH/README.md +106 -279
- webscout/Provider/AISEARCH/__init__.py +16 -9
- webscout/Provider/AISEARCH/brave_search.py +298 -0
- webscout/Provider/AISEARCH/iask_search.py +357 -410
- webscout/Provider/AISEARCH/monica_search.py +200 -220
- webscout/Provider/AISEARCH/webpilotai_search.py +242 -255
- webscout/Provider/Algion.py +413 -0
- webscout/Provider/Andi.py +74 -69
- webscout/Provider/Apriel.py +313 -0
- webscout/Provider/Ayle.py +323 -0
- webscout/Provider/ChatSandbox.py +329 -342
- webscout/Provider/ClaudeOnline.py +365 -0
- webscout/Provider/Cohere.py +232 -208
- webscout/Provider/DeepAI.py +367 -0
- webscout/Provider/Deepinfra.py +467 -340
- webscout/Provider/EssentialAI.py +217 -0
- webscout/Provider/ExaAI.py +274 -261
- webscout/Provider/Gemini.py +175 -169
- webscout/Provider/GithubChat.py +385 -369
- webscout/Provider/Gradient.py +286 -0
- webscout/Provider/Groq.py +556 -801
- webscout/Provider/HadadXYZ.py +323 -0
- webscout/Provider/HeckAI.py +392 -375
- webscout/Provider/HuggingFace.py +387 -0
- webscout/Provider/IBM.py +340 -0
- webscout/Provider/Jadve.py +317 -291
- webscout/Provider/K2Think.py +306 -0
- webscout/Provider/Koboldai.py +221 -384
- webscout/Provider/Netwrck.py +273 -270
- webscout/Provider/Nvidia.py +310 -0
- webscout/Provider/OPENAI/DeepAI.py +489 -0
- webscout/Provider/OPENAI/K2Think.py +423 -0
- webscout/Provider/OPENAI/PI.py +463 -0
- webscout/Provider/OPENAI/README.md +890 -952
- webscout/Provider/OPENAI/TogetherAI.py +405 -0
- webscout/Provider/OPENAI/TwoAI.py +255 -357
- webscout/Provider/OPENAI/__init__.py +148 -40
- webscout/Provider/OPENAI/ai4chat.py +348 -293
- webscout/Provider/OPENAI/akashgpt.py +436 -0
- webscout/Provider/OPENAI/algion.py +303 -0
- webscout/Provider/OPENAI/{exachat.py → ayle.py} +365 -444
- webscout/Provider/OPENAI/base.py +253 -249
- webscout/Provider/OPENAI/cerebras.py +296 -0
- webscout/Provider/OPENAI/chatgpt.py +870 -556
- webscout/Provider/OPENAI/chatsandbox.py +233 -173
- webscout/Provider/OPENAI/deepinfra.py +403 -322
- webscout/Provider/OPENAI/e2b.py +2370 -1414
- webscout/Provider/OPENAI/elmo.py +278 -0
- webscout/Provider/OPENAI/exaai.py +452 -417
- webscout/Provider/OPENAI/freeassist.py +446 -0
- webscout/Provider/OPENAI/gradient.py +448 -0
- webscout/Provider/OPENAI/groq.py +380 -364
- webscout/Provider/OPENAI/hadadxyz.py +292 -0
- webscout/Provider/OPENAI/heckai.py +333 -308
- webscout/Provider/OPENAI/huggingface.py +321 -0
- webscout/Provider/OPENAI/ibm.py +425 -0
- webscout/Provider/OPENAI/llmchat.py +253 -0
- webscout/Provider/OPENAI/llmchatco.py +378 -335
- webscout/Provider/OPENAI/meta.py +541 -0
- webscout/Provider/OPENAI/netwrck.py +374 -357
- webscout/Provider/OPENAI/nvidia.py +317 -0
- webscout/Provider/OPENAI/oivscode.py +348 -287
- webscout/Provider/OPENAI/openrouter.py +328 -0
- webscout/Provider/OPENAI/pydantic_imports.py +1 -172
- webscout/Provider/OPENAI/sambanova.py +397 -0
- webscout/Provider/OPENAI/sonus.py +305 -304
- webscout/Provider/OPENAI/textpollinations.py +370 -339
- webscout/Provider/OPENAI/toolbaz.py +375 -413
- webscout/Provider/OPENAI/typefully.py +419 -355
- webscout/Provider/OPENAI/typliai.py +279 -0
- webscout/Provider/OPENAI/utils.py +314 -318
- webscout/Provider/OPENAI/wisecat.py +359 -387
- webscout/Provider/OPENAI/writecream.py +185 -163
- webscout/Provider/OPENAI/x0gpt.py +462 -365
- webscout/Provider/OPENAI/zenmux.py +380 -0
- webscout/Provider/OpenRouter.py +386 -0
- webscout/Provider/Openai.py +337 -496
- webscout/Provider/PI.py +443 -429
- webscout/Provider/QwenLM.py +346 -254
- webscout/Provider/STT/__init__.py +28 -0
- webscout/Provider/STT/base.py +303 -0
- webscout/Provider/STT/elevenlabs.py +264 -0
- webscout/Provider/Sambanova.py +317 -0
- webscout/Provider/TTI/README.md +69 -82
- webscout/Provider/TTI/__init__.py +37 -7
- webscout/Provider/TTI/base.py +147 -64
- webscout/Provider/TTI/claudeonline.py +393 -0
- webscout/Provider/TTI/magicstudio.py +292 -201
- webscout/Provider/TTI/miragic.py +180 -0
- webscout/Provider/TTI/pollinations.py +331 -221
- webscout/Provider/TTI/together.py +334 -0
- webscout/Provider/TTI/utils.py +14 -11
- webscout/Provider/TTS/README.md +186 -192
- webscout/Provider/TTS/__init__.py +43 -10
- webscout/Provider/TTS/base.py +523 -159
- webscout/Provider/TTS/deepgram.py +286 -156
- webscout/Provider/TTS/elevenlabs.py +189 -111
- webscout/Provider/TTS/freetts.py +218 -0
- webscout/Provider/TTS/murfai.py +288 -113
- webscout/Provider/TTS/openai_fm.py +364 -129
- webscout/Provider/TTS/parler.py +203 -111
- webscout/Provider/TTS/qwen.py +334 -0
- webscout/Provider/TTS/sherpa.py +286 -0
- webscout/Provider/TTS/speechma.py +693 -580
- webscout/Provider/TTS/streamElements.py +275 -333
- webscout/Provider/TTS/utils.py +280 -280
- webscout/Provider/TextPollinationsAI.py +331 -308
- webscout/Provider/TogetherAI.py +450 -0
- webscout/Provider/TwoAI.py +309 -475
- webscout/Provider/TypliAI.py +311 -305
- webscout/Provider/UNFINISHED/ChatHub.py +219 -209
- webscout/Provider/{OPENAI/glider.py → UNFINISHED/ChutesAI.py} +331 -326
- webscout/Provider/{GizAI.py → UNFINISHED/GizAI.py} +300 -295
- webscout/Provider/{Marcus.py → UNFINISHED/Marcus.py} +218 -198
- webscout/Provider/UNFINISHED/Qodo.py +481 -0
- webscout/Provider/{MCPCore.py → UNFINISHED/XenAI.py} +330 -315
- webscout/Provider/UNFINISHED/Youchat.py +347 -330
- webscout/Provider/UNFINISHED/aihumanizer.py +41 -0
- webscout/Provider/UNFINISHED/grammerchecker.py +37 -0
- webscout/Provider/UNFINISHED/liner.py +342 -0
- webscout/Provider/UNFINISHED/liner_api_request.py +246 -263
- webscout/Provider/{samurai.py → UNFINISHED/samurai.py} +231 -224
- webscout/Provider/WiseCat.py +256 -233
- webscout/Provider/WrDoChat.py +390 -370
- webscout/Provider/__init__.py +115 -174
- webscout/Provider/ai4chat.py +181 -174
- webscout/Provider/akashgpt.py +330 -335
- webscout/Provider/cerebras.py +397 -290
- webscout/Provider/cleeai.py +236 -213
- webscout/Provider/elmo.py +291 -283
- webscout/Provider/geminiapi.py +343 -208
- webscout/Provider/julius.py +245 -223
- webscout/Provider/learnfastai.py +333 -325
- webscout/Provider/llama3mitril.py +230 -215
- webscout/Provider/llmchat.py +308 -258
- webscout/Provider/llmchatco.py +321 -306
- webscout/Provider/meta.py +996 -801
- webscout/Provider/oivscode.py +332 -309
- webscout/Provider/searchchat.py +316 -292
- webscout/Provider/sonus.py +264 -258
- webscout/Provider/toolbaz.py +359 -353
- webscout/Provider/turboseek.py +332 -266
- webscout/Provider/typefully.py +262 -202
- webscout/Provider/x0gpt.py +332 -299
- webscout/__init__.py +31 -39
- webscout/__main__.py +5 -5
- webscout/cli.py +585 -524
- webscout/client.py +1497 -70
- webscout/conversation.py +140 -436
- webscout/exceptions.py +383 -362
- webscout/litagent/__init__.py +29 -29
- webscout/litagent/agent.py +492 -455
- webscout/litagent/constants.py +60 -60
- webscout/models.py +505 -181
- webscout/optimizers.py +74 -420
- webscout/prompt_manager.py +376 -288
- webscout/sanitize.py +1514 -0
- webscout/scout/README.md +452 -404
- webscout/scout/__init__.py +8 -8
- webscout/scout/core/__init__.py +7 -7
- webscout/scout/core/crawler.py +330 -210
- webscout/scout/core/scout.py +800 -607
- webscout/scout/core/search_result.py +51 -96
- webscout/scout/core/text_analyzer.py +64 -63
- webscout/scout/core/text_utils.py +412 -277
- webscout/scout/core/web_analyzer.py +54 -52
- webscout/scout/element.py +872 -478
- webscout/scout/parsers/__init__.py +70 -69
- webscout/scout/parsers/html5lib_parser.py +182 -172
- webscout/scout/parsers/html_parser.py +238 -236
- webscout/scout/parsers/lxml_parser.py +203 -178
- webscout/scout/utils.py +38 -37
- webscout/search/__init__.py +47 -0
- webscout/search/base.py +201 -0
- webscout/search/bing_main.py +45 -0
- webscout/search/brave_main.py +92 -0
- webscout/search/duckduckgo_main.py +57 -0
- webscout/search/engines/__init__.py +127 -0
- webscout/search/engines/bing/__init__.py +15 -0
- webscout/search/engines/bing/base.py +35 -0
- webscout/search/engines/bing/images.py +114 -0
- webscout/search/engines/bing/news.py +96 -0
- webscout/search/engines/bing/suggestions.py +36 -0
- webscout/search/engines/bing/text.py +109 -0
- webscout/search/engines/brave/__init__.py +19 -0
- webscout/search/engines/brave/base.py +47 -0
- webscout/search/engines/brave/images.py +213 -0
- webscout/search/engines/brave/news.py +353 -0
- webscout/search/engines/brave/suggestions.py +318 -0
- webscout/search/engines/brave/text.py +167 -0
- webscout/search/engines/brave/videos.py +364 -0
- webscout/search/engines/duckduckgo/__init__.py +25 -0
- webscout/search/engines/duckduckgo/answers.py +80 -0
- webscout/search/engines/duckduckgo/base.py +189 -0
- webscout/search/engines/duckduckgo/images.py +100 -0
- webscout/search/engines/duckduckgo/maps.py +183 -0
- webscout/search/engines/duckduckgo/news.py +70 -0
- webscout/search/engines/duckduckgo/suggestions.py +22 -0
- webscout/search/engines/duckduckgo/text.py +221 -0
- webscout/search/engines/duckduckgo/translate.py +48 -0
- webscout/search/engines/duckduckgo/videos.py +80 -0
- webscout/search/engines/duckduckgo/weather.py +84 -0
- webscout/search/engines/mojeek.py +61 -0
- webscout/search/engines/wikipedia.py +77 -0
- webscout/search/engines/yahoo/__init__.py +41 -0
- webscout/search/engines/yahoo/answers.py +19 -0
- webscout/search/engines/yahoo/base.py +34 -0
- webscout/search/engines/yahoo/images.py +323 -0
- webscout/search/engines/yahoo/maps.py +19 -0
- webscout/search/engines/yahoo/news.py +258 -0
- webscout/search/engines/yahoo/suggestions.py +140 -0
- webscout/search/engines/yahoo/text.py +273 -0
- webscout/search/engines/yahoo/translate.py +19 -0
- webscout/search/engines/yahoo/videos.py +302 -0
- webscout/search/engines/yahoo/weather.py +220 -0
- webscout/search/engines/yandex.py +67 -0
- webscout/search/engines/yep/__init__.py +13 -0
- webscout/search/engines/yep/base.py +34 -0
- webscout/search/engines/yep/images.py +101 -0
- webscout/search/engines/yep/suggestions.py +38 -0
- webscout/search/engines/yep/text.py +99 -0
- webscout/search/http_client.py +172 -0
- webscout/search/results.py +141 -0
- webscout/search/yahoo_main.py +57 -0
- webscout/search/yep_main.py +48 -0
- webscout/server/__init__.py +48 -0
- webscout/server/config.py +78 -0
- webscout/server/exceptions.py +69 -0
- webscout/server/providers.py +286 -0
- webscout/server/request_models.py +131 -0
- webscout/server/request_processing.py +404 -0
- webscout/server/routes.py +642 -0
- webscout/server/server.py +351 -0
- webscout/server/ui_templates.py +1171 -0
- webscout/swiftcli/__init__.py +79 -95
- webscout/swiftcli/core/__init__.py +7 -7
- webscout/swiftcli/core/cli.py +574 -297
- webscout/swiftcli/core/context.py +98 -104
- webscout/swiftcli/core/group.py +268 -241
- webscout/swiftcli/decorators/__init__.py +28 -28
- webscout/swiftcli/decorators/command.py +243 -221
- webscout/swiftcli/decorators/options.py +247 -220
- webscout/swiftcli/decorators/output.py +392 -252
- webscout/swiftcli/exceptions.py +21 -21
- webscout/swiftcli/plugins/__init__.py +9 -9
- webscout/swiftcli/plugins/base.py +134 -135
- webscout/swiftcli/plugins/manager.py +269 -269
- webscout/swiftcli/utils/__init__.py +58 -59
- webscout/swiftcli/utils/formatting.py +251 -252
- webscout/swiftcli/utils/parsing.py +368 -267
- webscout/update_checker.py +280 -136
- webscout/utils.py +28 -14
- webscout/version.py +2 -1
- webscout/version.py.bak +3 -0
- webscout/zeroart/__init__.py +218 -135
- webscout/zeroart/base.py +70 -66
- webscout/zeroart/effects.py +155 -101
- webscout/zeroart/fonts.py +1799 -1239
- webscout-2026.1.19.dist-info/METADATA +638 -0
- webscout-2026.1.19.dist-info/RECORD +312 -0
- {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/WHEEL +1 -1
- {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/entry_points.txt +1 -1
- webscout/DWEBS.py +0 -520
- webscout/Extra/Act.md +0 -309
- webscout/Extra/GitToolkit/gitapi/README.md +0 -110
- webscout/Extra/autocoder/__init__.py +0 -9
- webscout/Extra/autocoder/autocoder.py +0 -1105
- webscout/Extra/autocoder/autocoder_utiles.py +0 -332
- webscout/Extra/gguf.md +0 -430
- webscout/Extra/weather.md +0 -281
- webscout/Litlogger/README.md +0 -10
- webscout/Litlogger/__init__.py +0 -15
- webscout/Litlogger/formats.py +0 -4
- webscout/Litlogger/handlers.py +0 -103
- webscout/Litlogger/levels.py +0 -13
- webscout/Litlogger/logger.py +0 -92
- webscout/Provider/AI21.py +0 -177
- webscout/Provider/AISEARCH/DeepFind.py +0 -254
- webscout/Provider/AISEARCH/felo_search.py +0 -202
- webscout/Provider/AISEARCH/genspark_search.py +0 -324
- webscout/Provider/AISEARCH/hika_search.py +0 -186
- webscout/Provider/AISEARCH/scira_search.py +0 -298
- webscout/Provider/Aitopia.py +0 -316
- webscout/Provider/AllenAI.py +0 -440
- webscout/Provider/Blackboxai.py +0 -791
- webscout/Provider/ChatGPTClone.py +0 -237
- webscout/Provider/ChatGPTGratis.py +0 -194
- webscout/Provider/Cloudflare.py +0 -324
- webscout/Provider/ExaChat.py +0 -358
- webscout/Provider/Flowith.py +0 -217
- webscout/Provider/FreeGemini.py +0 -250
- webscout/Provider/Glider.py +0 -225
- webscout/Provider/HF_space/__init__.py +0 -0
- webscout/Provider/HF_space/qwen_qwen2.py +0 -206
- webscout/Provider/HuggingFaceChat.py +0 -469
- webscout/Provider/Hunyuan.py +0 -283
- webscout/Provider/LambdaChat.py +0 -411
- webscout/Provider/Llama3.py +0 -259
- webscout/Provider/Nemotron.py +0 -218
- webscout/Provider/OLLAMA.py +0 -396
- webscout/Provider/OPENAI/BLACKBOXAI.py +0 -766
- webscout/Provider/OPENAI/Cloudflare.py +0 -378
- webscout/Provider/OPENAI/FreeGemini.py +0 -283
- webscout/Provider/OPENAI/NEMOTRON.py +0 -232
- webscout/Provider/OPENAI/Qwen3.py +0 -283
- webscout/Provider/OPENAI/api.py +0 -969
- webscout/Provider/OPENAI/c4ai.py +0 -373
- webscout/Provider/OPENAI/chatgptclone.py +0 -494
- webscout/Provider/OPENAI/copilot.py +0 -242
- webscout/Provider/OPENAI/flowith.py +0 -162
- webscout/Provider/OPENAI/freeaichat.py +0 -359
- webscout/Provider/OPENAI/mcpcore.py +0 -389
- webscout/Provider/OPENAI/multichat.py +0 -376
- webscout/Provider/OPENAI/opkfc.py +0 -496
- webscout/Provider/OPENAI/scirachat.py +0 -477
- webscout/Provider/OPENAI/standardinput.py +0 -433
- webscout/Provider/OPENAI/typegpt.py +0 -364
- webscout/Provider/OPENAI/uncovrAI.py +0 -463
- webscout/Provider/OPENAI/venice.py +0 -431
- webscout/Provider/OPENAI/yep.py +0 -382
- webscout/Provider/OpenGPT.py +0 -209
- webscout/Provider/Perplexitylabs.py +0 -415
- webscout/Provider/Reka.py +0 -214
- webscout/Provider/StandardInput.py +0 -290
- webscout/Provider/TTI/aiarta.py +0 -365
- webscout/Provider/TTI/artbit.py +0 -0
- webscout/Provider/TTI/fastflux.py +0 -200
- webscout/Provider/TTI/piclumen.py +0 -203
- webscout/Provider/TTI/pixelmuse.py +0 -225
- webscout/Provider/TTS/gesserit.py +0 -128
- webscout/Provider/TTS/sthir.py +0 -94
- webscout/Provider/TeachAnything.py +0 -229
- webscout/Provider/UNFINISHED/puterjs.py +0 -635
- webscout/Provider/UNFINISHED/test_lmarena.py +0 -119
- webscout/Provider/Venice.py +0 -258
- webscout/Provider/VercelAI.py +0 -253
- webscout/Provider/Writecream.py +0 -246
- webscout/Provider/WritingMate.py +0 -269
- webscout/Provider/asksteve.py +0 -220
- webscout/Provider/chatglm.py +0 -215
- webscout/Provider/copilot.py +0 -425
- webscout/Provider/freeaichat.py +0 -285
- webscout/Provider/granite.py +0 -235
- webscout/Provider/hermes.py +0 -266
- webscout/Provider/koala.py +0 -170
- webscout/Provider/lmarena.py +0 -198
- webscout/Provider/multichat.py +0 -364
- webscout/Provider/scira_chat.py +0 -299
- webscout/Provider/scnet.py +0 -243
- webscout/Provider/talkai.py +0 -194
- webscout/Provider/typegpt.py +0 -289
- webscout/Provider/uncovr.py +0 -368
- webscout/Provider/yep.py +0 -389
- webscout/litagent/Readme.md +0 -276
- webscout/litprinter/__init__.py +0 -59
- webscout/swiftcli/Readme.md +0 -323
- webscout/tempid.py +0 -128
- webscout/webscout_search.py +0 -1184
- webscout/webscout_search_async.py +0 -654
- webscout/yep_search.py +0 -347
- webscout/zeroart/README.md +0 -89
- webscout-8.2.9.dist-info/METADATA +0 -1033
- webscout-8.2.9.dist-info/RECORD +0 -289
- {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/licenses/LICENSE.md +0 -0
- {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/top_level.txt +0 -0
|
@@ -1,365 +1,462 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
from
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
from .base import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"""
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
1
|
+
import re
|
|
2
|
+
import time
|
|
3
|
+
import uuid
|
|
4
|
+
from typing import Any, Dict, Generator, List, Optional, Union
|
|
5
|
+
|
|
6
|
+
from curl_cffi.const import CurlHttpVersion
|
|
7
|
+
from curl_cffi.requests import Session
|
|
8
|
+
|
|
9
|
+
from webscout.Provider.OPENAI.base import (
|
|
10
|
+
BaseChat,
|
|
11
|
+
BaseCompletions,
|
|
12
|
+
OpenAICompatibleProvider,
|
|
13
|
+
SimpleModelList,
|
|
14
|
+
)
|
|
15
|
+
from webscout.Provider.OPENAI.utils import (
|
|
16
|
+
ChatCompletion,
|
|
17
|
+
ChatCompletionChunk,
|
|
18
|
+
ChatCompletionMessage,
|
|
19
|
+
Choice,
|
|
20
|
+
ChoiceDelta,
|
|
21
|
+
CompletionUsage,
|
|
22
|
+
count_tokens,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
from webscout.litagent import LitAgent
|
|
27
|
+
except ImportError:
|
|
28
|
+
LitAgent = None # type: ignore
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Completions(BaseCompletions):
|
|
32
|
+
"""Completions handler for X0GPT API."""
|
|
33
|
+
|
|
34
|
+
def __init__(self, client: "X0GPT") -> None:
|
|
35
|
+
"""Initialize Completions with X0GPT client."""
|
|
36
|
+
self._client = client
|
|
37
|
+
|
|
38
|
+
def create(
|
|
39
|
+
self,
|
|
40
|
+
*,
|
|
41
|
+
model: str,
|
|
42
|
+
messages: List[Dict[str, Any]],
|
|
43
|
+
max_tokens: Optional[int] = 2049,
|
|
44
|
+
stream: bool = False,
|
|
45
|
+
temperature: Optional[float] = None,
|
|
46
|
+
top_p: Optional[float] = None,
|
|
47
|
+
timeout: Optional[int] = None,
|
|
48
|
+
proxies: Optional[Dict[str, str]] = None,
|
|
49
|
+
**kwargs: Any,
|
|
50
|
+
) -> Union[ChatCompletion, Generator[ChatCompletionChunk, None, None]]:
|
|
51
|
+
"""Create a model response for the given chat conversation.
|
|
52
|
+
|
|
53
|
+
Mimics openai.chat.completions.create
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
model: Model name to use
|
|
57
|
+
messages: List of message dictionaries
|
|
58
|
+
max_tokens: Maximum tokens to generate
|
|
59
|
+
stream: Whether to stream the response
|
|
60
|
+
temperature: Sampling temperature
|
|
61
|
+
top_p: Nucleus sampling parameter
|
|
62
|
+
timeout: Request timeout in seconds
|
|
63
|
+
proxies: Proxy configuration
|
|
64
|
+
**kwargs: Additional parameters
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
ChatCompletion or generator of ChatCompletionChunk
|
|
68
|
+
"""
|
|
69
|
+
# Prepare the payload for X0GPT API
|
|
70
|
+
payload: Dict[str, Any] = {
|
|
71
|
+
"messages": messages,
|
|
72
|
+
"chatId": uuid.uuid4().hex,
|
|
73
|
+
"namespace": None,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
# Add optional parameters if provided
|
|
77
|
+
if max_tokens is not None and max_tokens > 0:
|
|
78
|
+
payload["max_tokens"] = max_tokens
|
|
79
|
+
|
|
80
|
+
if temperature is not None:
|
|
81
|
+
payload["temperature"] = temperature
|
|
82
|
+
|
|
83
|
+
if top_p is not None:
|
|
84
|
+
payload["top_p"] = top_p
|
|
85
|
+
|
|
86
|
+
# Add any additional parameters
|
|
87
|
+
payload.update(kwargs)
|
|
88
|
+
|
|
89
|
+
request_id = f"chatcmpl-{uuid.uuid4()}"
|
|
90
|
+
created_time = int(time.time())
|
|
91
|
+
|
|
92
|
+
if stream:
|
|
93
|
+
return self._create_stream(request_id, created_time, model, payload, timeout, proxies)
|
|
94
|
+
return self._create_non_stream(request_id, created_time, model, payload, timeout, proxies)
|
|
95
|
+
|
|
96
|
+
def _create_stream(
|
|
97
|
+
self,
|
|
98
|
+
request_id: str,
|
|
99
|
+
created_time: int,
|
|
100
|
+
model: str,
|
|
101
|
+
payload: Dict[str, Any],
|
|
102
|
+
timeout: Optional[int] = None,
|
|
103
|
+
proxies: Optional[Dict[str, str]] = None,
|
|
104
|
+
) -> Generator[ChatCompletionChunk, None, None]:
|
|
105
|
+
"""Create a streaming response from X0GPT API.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
request_id: Unique request identifier
|
|
109
|
+
created_time: Timestamp of request creation
|
|
110
|
+
model: Model name
|
|
111
|
+
payload: Request payload
|
|
112
|
+
timeout: Request timeout
|
|
113
|
+
proxies: Proxy configuration
|
|
114
|
+
|
|
115
|
+
Yields:
|
|
116
|
+
ChatCompletionChunk objects
|
|
117
|
+
|
|
118
|
+
Raises:
|
|
119
|
+
IOError: If request fails
|
|
120
|
+
"""
|
|
121
|
+
try:
|
|
122
|
+
response = self._client.session.post(
|
|
123
|
+
self._client.api_endpoint,
|
|
124
|
+
headers=self._client.headers,
|
|
125
|
+
json=payload,
|
|
126
|
+
stream=True,
|
|
127
|
+
timeout=timeout if timeout is not None else self._client.timeout,
|
|
128
|
+
proxies=proxies or getattr(self._client, "proxies", None),
|
|
129
|
+
impersonate="chrome120",
|
|
130
|
+
http_version=CurlHttpVersion.V1_1,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
# Handle non-200 responses
|
|
134
|
+
if response.status_code != 200:
|
|
135
|
+
raise IOError(
|
|
136
|
+
f"Failed to generate response - ({response.status_code}, "
|
|
137
|
+
f"{response.reason}) - {response.text}"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Track token usage across chunks
|
|
141
|
+
prompt_tokens = 0
|
|
142
|
+
completion_tokens = 0
|
|
143
|
+
|
|
144
|
+
# Estimate prompt tokens based on message length
|
|
145
|
+
for msg in payload.get("messages", []):
|
|
146
|
+
prompt_tokens += count_tokens(msg.get("content", ""))
|
|
147
|
+
|
|
148
|
+
for line in response.iter_lines():
|
|
149
|
+
if line:
|
|
150
|
+
# Handle both bytes and string responses
|
|
151
|
+
decoded_line = (
|
|
152
|
+
line.strip() if isinstance(line, str) else line.decode("utf-8").strip()
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# X0GPT uses a different format, extract the content
|
|
156
|
+
match = re.search(r'"([^"]*)"', decoded_line)
|
|
157
|
+
if match:
|
|
158
|
+
content = match.group(1)
|
|
159
|
+
|
|
160
|
+
# Format the content (replace escaped sequences)
|
|
161
|
+
content = self._client.format_text(content)
|
|
162
|
+
|
|
163
|
+
# Update token counts
|
|
164
|
+
completion_tokens += count_tokens(content)
|
|
165
|
+
|
|
166
|
+
# Create the delta object
|
|
167
|
+
delta = ChoiceDelta(
|
|
168
|
+
content=content,
|
|
169
|
+
role="assistant",
|
|
170
|
+
tool_calls=None,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# Create the choice object
|
|
174
|
+
choice = Choice(
|
|
175
|
+
index=0,
|
|
176
|
+
delta=delta,
|
|
177
|
+
finish_reason=None,
|
|
178
|
+
logprobs=None,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# Create the chunk object
|
|
182
|
+
chunk = ChatCompletionChunk(
|
|
183
|
+
id=request_id,
|
|
184
|
+
choices=[choice],
|
|
185
|
+
created=created_time,
|
|
186
|
+
model=model,
|
|
187
|
+
system_fingerprint=None,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Return the chunk object for internal processing
|
|
191
|
+
yield chunk
|
|
192
|
+
|
|
193
|
+
# Final chunk with finish_reason="stop"
|
|
194
|
+
delta = ChoiceDelta(
|
|
195
|
+
content=None,
|
|
196
|
+
role=None,
|
|
197
|
+
tool_calls=None,
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
choice = Choice(
|
|
201
|
+
index=0,
|
|
202
|
+
delta=delta,
|
|
203
|
+
finish_reason="stop",
|
|
204
|
+
logprobs=None,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
chunk = ChatCompletionChunk(
|
|
208
|
+
id=request_id,
|
|
209
|
+
choices=[choice],
|
|
210
|
+
created=created_time,
|
|
211
|
+
model=model,
|
|
212
|
+
system_fingerprint=None,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
yield chunk
|
|
216
|
+
|
|
217
|
+
except Exception as e:
|
|
218
|
+
raise IOError(f"X0GPT request failed: {e}") from e
|
|
219
|
+
|
|
220
|
+
def _create_non_stream(
|
|
221
|
+
self,
|
|
222
|
+
request_id: str,
|
|
223
|
+
created_time: int,
|
|
224
|
+
model: str,
|
|
225
|
+
payload: Dict[str, Any],
|
|
226
|
+
timeout: Optional[int] = None,
|
|
227
|
+
proxies: Optional[Dict[str, str]] = None,
|
|
228
|
+
) -> ChatCompletion:
|
|
229
|
+
"""Create a non-streaming response from X0GPT API.
|
|
230
|
+
|
|
231
|
+
Args:
|
|
232
|
+
request_id: Unique request identifier
|
|
233
|
+
created_time: Timestamp of request creation
|
|
234
|
+
model: Model name
|
|
235
|
+
payload: Request payload
|
|
236
|
+
timeout: Request timeout
|
|
237
|
+
proxies: Proxy configuration
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
ChatCompletion object
|
|
241
|
+
|
|
242
|
+
Raises:
|
|
243
|
+
IOError: If request fails
|
|
244
|
+
"""
|
|
245
|
+
try:
|
|
246
|
+
# For non-streaming, we still use streaming internally
|
|
247
|
+
response = self._client.session.post(
|
|
248
|
+
self._client.api_endpoint,
|
|
249
|
+
headers=self._client.headers,
|
|
250
|
+
json=payload,
|
|
251
|
+
stream=True,
|
|
252
|
+
timeout=timeout if timeout is not None else self._client.timeout,
|
|
253
|
+
proxies=proxies or getattr(self._client, "proxies", None),
|
|
254
|
+
impersonate="chrome120",
|
|
255
|
+
http_version=CurlHttpVersion.V1_1,
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
# Handle non-200 responses
|
|
259
|
+
if response.status_code != 200:
|
|
260
|
+
raise IOError(
|
|
261
|
+
f"Failed to generate response - ({response.status_code}, "
|
|
262
|
+
f"{response.reason}) - {response.text}"
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# Collect the full response
|
|
266
|
+
full_text = ""
|
|
267
|
+
for line in response.iter_lines():
|
|
268
|
+
if line:
|
|
269
|
+
# Handle both bytes and string responses
|
|
270
|
+
decoded_line = (
|
|
271
|
+
line.strip() if isinstance(line, str) else line.decode("utf-8").strip()
|
|
272
|
+
)
|
|
273
|
+
match = re.search(r'"([^"]*)"', decoded_line)
|
|
274
|
+
if match:
|
|
275
|
+
content = match.group(1)
|
|
276
|
+
full_text += content
|
|
277
|
+
|
|
278
|
+
# Format the text (replace escaped sequences)
|
|
279
|
+
full_text = self._client.format_text(full_text)
|
|
280
|
+
|
|
281
|
+
# Estimate token counts
|
|
282
|
+
prompt_tokens = 0
|
|
283
|
+
for msg in payload.get("messages", []):
|
|
284
|
+
prompt_tokens += count_tokens(msg.get("content", ""))
|
|
285
|
+
|
|
286
|
+
completion_tokens = count_tokens(full_text)
|
|
287
|
+
total_tokens = prompt_tokens + completion_tokens
|
|
288
|
+
|
|
289
|
+
# Create the message object
|
|
290
|
+
message = ChatCompletionMessage(role="assistant", content=full_text)
|
|
291
|
+
|
|
292
|
+
# Create the choice object
|
|
293
|
+
choice = Choice(index=0, message=message, finish_reason="stop")
|
|
294
|
+
|
|
295
|
+
# Create the usage object
|
|
296
|
+
usage = CompletionUsage(
|
|
297
|
+
prompt_tokens=prompt_tokens,
|
|
298
|
+
completion_tokens=completion_tokens,
|
|
299
|
+
total_tokens=total_tokens,
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
# Create the completion object
|
|
303
|
+
completion = ChatCompletion(
|
|
304
|
+
id=request_id,
|
|
305
|
+
choices=[choice],
|
|
306
|
+
created=created_time,
|
|
307
|
+
model=model,
|
|
308
|
+
usage=usage,
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
return completion
|
|
312
|
+
|
|
313
|
+
except Exception as e:
|
|
314
|
+
raise IOError(f"X0GPT request failed: {e}") from e
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
class Chat(BaseChat):
|
|
318
|
+
"""Chat handler for X0GPT API."""
|
|
319
|
+
|
|
320
|
+
def __init__(self, client: "X0GPT") -> None:
|
|
321
|
+
"""Initialize Chat with X0GPT client."""
|
|
322
|
+
self.completions = Completions(client)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
class X0GPT(OpenAICompatibleProvider):
|
|
326
|
+
"""OpenAI-compatible client for X0GPT API.
|
|
327
|
+
|
|
328
|
+
Usage:
|
|
329
|
+
client = X0GPT()
|
|
330
|
+
response = client.chat.completions.create(
|
|
331
|
+
model="X0GPT",
|
|
332
|
+
messages=[{"role": "user", "content": "Hello!"}]
|
|
333
|
+
)
|
|
334
|
+
"""
|
|
335
|
+
|
|
336
|
+
required_auth = False
|
|
337
|
+
AVAILABLE_MODELS = ["X0GPT"]
|
|
338
|
+
|
|
339
|
+
def __init__(self, timeout: Optional[int] = None, browser: str = "chrome") -> None:
|
|
340
|
+
"""Initialize the X0GPT client.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
timeout: Request timeout in seconds (None for no timeout)
|
|
344
|
+
browser: Browser to emulate in user agent
|
|
345
|
+
"""
|
|
346
|
+
self.timeout = timeout
|
|
347
|
+
self.api_endpoint = "https://x0-gpt.devwtf.in/api/stream/reply"
|
|
348
|
+
self.session: Session = Session()
|
|
349
|
+
|
|
350
|
+
# Initialize user agent
|
|
351
|
+
user_agent = self._get_user_agent(browser)
|
|
352
|
+
|
|
353
|
+
self.headers: Dict[str, str] = {
|
|
354
|
+
"authority": "x0-gpt.devwtf.in",
|
|
355
|
+
"method": "POST",
|
|
356
|
+
"path": "/api/stream/reply",
|
|
357
|
+
"scheme": "https",
|
|
358
|
+
"accept": "*/*",
|
|
359
|
+
"accept-encoding": "gzip, deflate, br, zstd",
|
|
360
|
+
"accept-language": "en-US,en;q=0.9,en-IN;q=0.8",
|
|
361
|
+
"content-type": "application/json",
|
|
362
|
+
"dnt": "1",
|
|
363
|
+
"origin": "https://x0-gpt.devwtf.in",
|
|
364
|
+
"referer": "https://x0-gpt.devwtf.in/chat",
|
|
365
|
+
"sec-ch-ua": ('"Not)A;Brand";v="99", "Microsoft Edge";v="127", "Chromium";v="127"'),
|
|
366
|
+
"sec-ch-ua-mobile": "?0",
|
|
367
|
+
"sec-ch-ua-platform": '"Windows"',
|
|
368
|
+
"user-agent": user_agent,
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
self.session.headers.update(self.headers)
|
|
372
|
+
|
|
373
|
+
# Initialize the chat interface
|
|
374
|
+
self.chat: Chat = Chat(self)
|
|
375
|
+
|
|
376
|
+
@staticmethod
|
|
377
|
+
def _get_user_agent(browser: str) -> str:
|
|
378
|
+
"""Get a user agent string, with fallback if LitAgent unavailable.
|
|
379
|
+
|
|
380
|
+
Args:
|
|
381
|
+
browser: Browser to emulate
|
|
382
|
+
|
|
383
|
+
Returns:
|
|
384
|
+
User agent string
|
|
385
|
+
"""
|
|
386
|
+
if LitAgent is not None:
|
|
387
|
+
try:
|
|
388
|
+
agent = LitAgent()
|
|
389
|
+
fingerprint = agent.generate_fingerprint(browser)
|
|
390
|
+
return fingerprint.get("user_agent", X0GPT._default_user_agent())
|
|
391
|
+
except Exception:
|
|
392
|
+
return X0GPT._default_user_agent()
|
|
393
|
+
return X0GPT._default_user_agent()
|
|
394
|
+
|
|
395
|
+
@staticmethod
|
|
396
|
+
def _default_user_agent() -> str:
|
|
397
|
+
"""Return a default user agent string.
|
|
398
|
+
|
|
399
|
+
Returns:
|
|
400
|
+
Default user agent
|
|
401
|
+
"""
|
|
402
|
+
return (
|
|
403
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
|
|
404
|
+
"(KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0"
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
def format_text(self, text: str) -> str:
|
|
408
|
+
"""Format text by replacing escaped sequences with actual characters.
|
|
409
|
+
|
|
410
|
+
Args:
|
|
411
|
+
text: Text to format
|
|
412
|
+
|
|
413
|
+
Returns:
|
|
414
|
+
Formatted text
|
|
415
|
+
"""
|
|
416
|
+
try:
|
|
417
|
+
# Replace common escape sequences
|
|
418
|
+
text = text.replace("\\n", "\n")
|
|
419
|
+
text = text.replace("\\r", "\r")
|
|
420
|
+
text = text.replace("\\t", "\t")
|
|
421
|
+
text = text.replace('\\"', '"')
|
|
422
|
+
text = text.replace("\\\\", "\\")
|
|
423
|
+
return text
|
|
424
|
+
except Exception:
|
|
425
|
+
# If any error occurs, return the original text
|
|
426
|
+
return text
|
|
427
|
+
|
|
428
|
+
def convert_model_name(self, model: str) -> str:
|
|
429
|
+
"""Convert model names to ones supported by X0GPT.
|
|
430
|
+
|
|
431
|
+
Args:
|
|
432
|
+
model: Model name to convert
|
|
433
|
+
|
|
434
|
+
Returns:
|
|
435
|
+
X0GPT model name
|
|
436
|
+
"""
|
|
437
|
+
# X0GPT doesn't use model names, but keep for compatibility
|
|
438
|
+
return model
|
|
439
|
+
|
|
440
|
+
@property
|
|
441
|
+
def models(self) -> SimpleModelList:
|
|
442
|
+
"""Get available models.
|
|
443
|
+
|
|
444
|
+
Returns:
|
|
445
|
+
SimpleModelList of available models
|
|
446
|
+
"""
|
|
447
|
+
return SimpleModelList(type(self).AVAILABLE_MODELS)
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
if __name__ == "__main__":
|
|
451
|
+
# Test the provider
|
|
452
|
+
client = X0GPT()
|
|
453
|
+
response = client.chat.completions.create(
|
|
454
|
+
model="X0GPT",
|
|
455
|
+
messages=[
|
|
456
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
457
|
+
{"role": "user", "content": "Hello! How are you today?"},
|
|
458
|
+
],
|
|
459
|
+
)
|
|
460
|
+
if not isinstance(response, Generator):
|
|
461
|
+
message = response.choices[0].message if response.choices else None
|
|
462
|
+
print(message.content if message else "")
|