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,433 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import time
|
|
3
|
-
import uuid
|
|
4
|
-
import re
|
|
5
|
-
import cloudscraper
|
|
6
|
-
from datetime import datetime
|
|
7
|
-
from typing import List, Dict, Optional, Union, Generator, Any
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
# Import base classes and utility structures
|
|
11
|
-
from .base import OpenAICompatibleProvider, BaseChat, BaseCompletions
|
|
12
|
-
from .utils import (
|
|
13
|
-
ChatCompletionChunk, ChatCompletion, Choice, ChoiceDelta,
|
|
14
|
-
ChatCompletionMessage, CompletionUsage,
|
|
15
|
-
format_prompt, get_system_prompt, get_last_user_message, count_tokens
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
# Import LitAgent for browser fingerprinting
|
|
19
|
-
try:
|
|
20
|
-
from webscout.litagent import LitAgent
|
|
21
|
-
except ImportError:
|
|
22
|
-
# Define a dummy LitAgent if webscout is not installed or accessible
|
|
23
|
-
class LitAgent:
|
|
24
|
-
def generate_fingerprint(self, browser: str = "chrome") -> Dict[str, Any]:
|
|
25
|
-
# Return minimal default headers if LitAgent is unavailable
|
|
26
|
-
print("Warning: LitAgent not found. Using default minimal headers.")
|
|
27
|
-
return {
|
|
28
|
-
"accept": "*/*",
|
|
29
|
-
"accept_language": "en-US,en;q=0.9",
|
|
30
|
-
"platform": "Windows",
|
|
31
|
-
"sec_ch_ua": '"Not/A)Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
|
|
32
|
-
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
|
|
33
|
-
"browser_type": browser,
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
# --- StandardInput Client ---
|
|
37
|
-
|
|
38
|
-
class Completions(BaseCompletions):
|
|
39
|
-
def __init__(self, client: 'StandardInput'):
|
|
40
|
-
self._client = client
|
|
41
|
-
|
|
42
|
-
def create(
|
|
43
|
-
self,
|
|
44
|
-
*,
|
|
45
|
-
model: str,
|
|
46
|
-
messages: List[Dict[str, str]],
|
|
47
|
-
max_tokens: Optional[int] = None,
|
|
48
|
-
stream: bool = False,
|
|
49
|
-
temperature: Optional[float] = None,
|
|
50
|
-
top_p: Optional[float] = None,
|
|
51
|
-
**kwargs: Any
|
|
52
|
-
) -> Union[ChatCompletion, Generator[ChatCompletionChunk, None, None]]:
|
|
53
|
-
"""Create a chat completion."""
|
|
54
|
-
# Validate model
|
|
55
|
-
if model not in self._client.AVAILABLE_MODELS and model not in self._client.MODEL_MAPPING.values():
|
|
56
|
-
raise ValueError(f"Model {model} not supported. Choose from: {list(self._client.AVAILABLE_MODELS)}")
|
|
57
|
-
|
|
58
|
-
# Map model name if needed
|
|
59
|
-
internal_model = self._client.MODEL_MAPPING.get(model, model)
|
|
60
|
-
|
|
61
|
-
# Extract reasoning flag from kwargs
|
|
62
|
-
enable_reasoning = kwargs.get("enable_reasoning", False)
|
|
63
|
-
|
|
64
|
-
# Prepare request
|
|
65
|
-
request_id = str(uuid.uuid4())
|
|
66
|
-
created_time = int(time.time())
|
|
67
|
-
|
|
68
|
-
# Extract system message and user message using utility functions
|
|
69
|
-
system_content = get_system_prompt(messages)
|
|
70
|
-
# Format the prompt for debugging purposes
|
|
71
|
-
formatted_prompt = format_prompt(messages, add_special_tokens=True, do_continue=True)
|
|
72
|
-
# Uncomment the line below for debugging
|
|
73
|
-
# print(f"Formatted prompt:\n{formatted_prompt}")
|
|
74
|
-
|
|
75
|
-
# Prepare the request payload
|
|
76
|
-
payload = {
|
|
77
|
-
"id": request_id,
|
|
78
|
-
"messages": [
|
|
79
|
-
{"role": "system", "content": system_content},
|
|
80
|
-
{"role": "user", "content": formatted_prompt, "parts": [{"type": "text", "text": formatted_prompt}]}
|
|
81
|
-
],
|
|
82
|
-
"modelId": internal_model,
|
|
83
|
-
"enabledFeatures": ["reasoning"] if enable_reasoning or "reasoning" in internal_model else []
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
# Handle streaming vs non-streaming
|
|
87
|
-
if stream:
|
|
88
|
-
return self._stream_request(request_id, created_time, model, payload)
|
|
89
|
-
else:
|
|
90
|
-
return self._non_stream_request(request_id, created_time, model, payload)
|
|
91
|
-
|
|
92
|
-
def _non_stream_request(
|
|
93
|
-
self,
|
|
94
|
-
request_id: str,
|
|
95
|
-
created_time: int,
|
|
96
|
-
model: str,
|
|
97
|
-
payload: Dict[str, Any]
|
|
98
|
-
) -> ChatCompletion:
|
|
99
|
-
"""Handle non-streaming request."""
|
|
100
|
-
try:
|
|
101
|
-
# Make the request
|
|
102
|
-
response = self._client.session.post(
|
|
103
|
-
self._client.api_endpoint,
|
|
104
|
-
cookies=self._client.cookies,
|
|
105
|
-
json=payload,
|
|
106
|
-
timeout=self._client.timeout
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
# Check for errors
|
|
110
|
-
if response.status_code != 200:
|
|
111
|
-
# Try to get response content for better error messages
|
|
112
|
-
try:
|
|
113
|
-
error_content = response.text
|
|
114
|
-
except:
|
|
115
|
-
error_content = "<could not read response content>"
|
|
116
|
-
|
|
117
|
-
if response.status_code in [403, 429]:
|
|
118
|
-
print(f"Received status code {response.status_code}, refreshing identity...")
|
|
119
|
-
self._client._refresh_identity()
|
|
120
|
-
response = self._client.session.post(
|
|
121
|
-
self._client.api_endpoint,
|
|
122
|
-
cookies=self._client.cookies,
|
|
123
|
-
json=payload,
|
|
124
|
-
timeout=self._client.timeout
|
|
125
|
-
)
|
|
126
|
-
if not response.ok:
|
|
127
|
-
raise IOError(f"Failed to generate response after identity refresh - ({response.status_code}, {response.reason}) - {error_content}")
|
|
128
|
-
print("Identity refreshed successfully.")
|
|
129
|
-
else:
|
|
130
|
-
raise IOError(f"Request failed with status code {response.status_code}. Response: {error_content}")
|
|
131
|
-
|
|
132
|
-
# Process the response
|
|
133
|
-
full_response = ""
|
|
134
|
-
|
|
135
|
-
# Process the streaming response to get the full text
|
|
136
|
-
for line in response.iter_lines(decode_unicode=True):
|
|
137
|
-
if line:
|
|
138
|
-
try:
|
|
139
|
-
# Extract content from the response
|
|
140
|
-
match = re.search(r'0:"(.*?)"', line)
|
|
141
|
-
if match:
|
|
142
|
-
content = match.group(1)
|
|
143
|
-
# Format the content to handle escape sequences
|
|
144
|
-
content = self._client.format_text(content)
|
|
145
|
-
full_response += content
|
|
146
|
-
except:
|
|
147
|
-
pass
|
|
148
|
-
|
|
149
|
-
# Create the response objects
|
|
150
|
-
message = ChatCompletionMessage(
|
|
151
|
-
role="assistant",
|
|
152
|
-
content=full_response
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
choice = Choice(
|
|
156
|
-
index=0,
|
|
157
|
-
message=message,
|
|
158
|
-
finish_reason="stop"
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
# Estimate token usage (very rough estimate)
|
|
162
|
-
prompt_tokens = count_tokens(str(payload))
|
|
163
|
-
completion_tokens = count_tokens(full_response)
|
|
164
|
-
total_tokens = prompt_tokens + completion_tokens
|
|
165
|
-
|
|
166
|
-
usage = CompletionUsage(
|
|
167
|
-
prompt_tokens=prompt_tokens,
|
|
168
|
-
completion_tokens=completion_tokens,
|
|
169
|
-
total_tokens=total_tokens
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
# Create the completion object
|
|
173
|
-
completion = ChatCompletion(
|
|
174
|
-
id=request_id,
|
|
175
|
-
choices=[choice],
|
|
176
|
-
created=created_time,
|
|
177
|
-
model=model,
|
|
178
|
-
usage=usage,
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
return completion
|
|
182
|
-
|
|
183
|
-
except Exception as e:
|
|
184
|
-
print(f"Error during StandardInput non-stream request: {e}")
|
|
185
|
-
raise IOError(f"StandardInput request failed: {e}") from e
|
|
186
|
-
|
|
187
|
-
def _stream_request(
|
|
188
|
-
self,
|
|
189
|
-
request_id: str,
|
|
190
|
-
created_time: int,
|
|
191
|
-
model: str,
|
|
192
|
-
payload: Dict[str, Any]
|
|
193
|
-
) -> Generator[ChatCompletionChunk, None, None]:
|
|
194
|
-
"""Handle streaming request."""
|
|
195
|
-
try:
|
|
196
|
-
# Make the request
|
|
197
|
-
response = self._client.session.post(
|
|
198
|
-
self._client.api_endpoint,
|
|
199
|
-
cookies=self._client.cookies,
|
|
200
|
-
json=payload,
|
|
201
|
-
stream=True,
|
|
202
|
-
timeout=self._client.timeout
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
# Check for errors
|
|
206
|
-
if response.status_code != 200:
|
|
207
|
-
# Try to get response content for better error messages
|
|
208
|
-
try:
|
|
209
|
-
error_content = response.text
|
|
210
|
-
except:
|
|
211
|
-
error_content = "<could not read response content>"
|
|
212
|
-
|
|
213
|
-
if response.status_code in [403, 429]:
|
|
214
|
-
print(f"Received status code {response.status_code}, refreshing identity...")
|
|
215
|
-
self._client._refresh_identity()
|
|
216
|
-
response = self._client.session.post(
|
|
217
|
-
self._client.api_endpoint,
|
|
218
|
-
cookies=self._client.cookies,
|
|
219
|
-
json=payload,
|
|
220
|
-
stream=True,
|
|
221
|
-
timeout=self._client.timeout
|
|
222
|
-
)
|
|
223
|
-
if not response.ok:
|
|
224
|
-
raise IOError(f"Failed to generate response after identity refresh - ({response.status_code}, {response.reason}) - {error_content}")
|
|
225
|
-
print("Identity refreshed successfully.")
|
|
226
|
-
else:
|
|
227
|
-
raise IOError(f"Request failed with status code {response.status_code}. Response: {error_content}")
|
|
228
|
-
|
|
229
|
-
# Process the streaming response
|
|
230
|
-
for line in response.iter_lines(decode_unicode=True):
|
|
231
|
-
if line:
|
|
232
|
-
try:
|
|
233
|
-
# Extract content from the response
|
|
234
|
-
match = re.search(r'0:"(.*?)"', line)
|
|
235
|
-
if match:
|
|
236
|
-
content = match.group(1)
|
|
237
|
-
|
|
238
|
-
# Format the content to handle escape sequences
|
|
239
|
-
content = self._client.format_text(content)
|
|
240
|
-
|
|
241
|
-
# Create the delta object
|
|
242
|
-
delta = ChoiceDelta(content=content)
|
|
243
|
-
|
|
244
|
-
# Create the choice object
|
|
245
|
-
choice = Choice(
|
|
246
|
-
index=0,
|
|
247
|
-
delta=delta,
|
|
248
|
-
finish_reason=None
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
# Create the chunk object
|
|
252
|
-
chunk = ChatCompletionChunk(
|
|
253
|
-
id=request_id,
|
|
254
|
-
choices=[choice],
|
|
255
|
-
created=created_time,
|
|
256
|
-
model=model
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
yield chunk
|
|
260
|
-
except:
|
|
261
|
-
pass
|
|
262
|
-
|
|
263
|
-
# Send the final chunk with finish_reason
|
|
264
|
-
final_choice = Choice(
|
|
265
|
-
index=0,
|
|
266
|
-
delta=ChoiceDelta(content=None),
|
|
267
|
-
finish_reason="stop"
|
|
268
|
-
)
|
|
269
|
-
|
|
270
|
-
final_chunk = ChatCompletionChunk(
|
|
271
|
-
id=request_id,
|
|
272
|
-
choices=[final_choice],
|
|
273
|
-
created=created_time,
|
|
274
|
-
model=model
|
|
275
|
-
)
|
|
276
|
-
|
|
277
|
-
yield final_chunk
|
|
278
|
-
|
|
279
|
-
except Exception as e:
|
|
280
|
-
print(f"Error during StandardInput stream request: {e}")
|
|
281
|
-
raise IOError(f"StandardInput request failed: {e}") from e
|
|
282
|
-
|
|
283
|
-
class Chat(BaseChat):
|
|
284
|
-
def __init__(self, client: 'StandardInput'):
|
|
285
|
-
self.completions = Completions(client)
|
|
286
|
-
|
|
287
|
-
class StandardInput(OpenAICompatibleProvider):
|
|
288
|
-
"""
|
|
289
|
-
OpenAI-compatible client for StandardInput API.
|
|
290
|
-
|
|
291
|
-
Usage:
|
|
292
|
-
client = StandardInput()
|
|
293
|
-
response = client.chat.completions.create(
|
|
294
|
-
model="standard-quick",
|
|
295
|
-
messages=[{"role": "user", "content": "Hello!"}]
|
|
296
|
-
)
|
|
297
|
-
print(response.choices[0].message.content)
|
|
298
|
-
"""
|
|
299
|
-
|
|
300
|
-
AVAILABLE_MODELS = [
|
|
301
|
-
"standard-quick",
|
|
302
|
-
"standard-reasoning",
|
|
303
|
-
]
|
|
304
|
-
|
|
305
|
-
# Map external model names to internal model IDs
|
|
306
|
-
MODEL_MAPPING = {
|
|
307
|
-
"standard-quick": "quick",
|
|
308
|
-
"standard-reasoning": "quick", # Same model but with reasoning enabled
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
def __init__(
|
|
312
|
-
self,
|
|
313
|
-
timeout: int = 30,
|
|
314
|
-
browser: str = "chrome"
|
|
315
|
-
):
|
|
316
|
-
"""
|
|
317
|
-
Initialize the StandardInput client.
|
|
318
|
-
|
|
319
|
-
Args:
|
|
320
|
-
timeout: Request timeout in seconds.
|
|
321
|
-
browser: Browser name for LitAgent to generate User-Agent.
|
|
322
|
-
"""
|
|
323
|
-
self.timeout = timeout
|
|
324
|
-
self.api_endpoint = "https://chat.standard-input.com/api/chat"
|
|
325
|
-
|
|
326
|
-
# Initialize LitAgent for user agent generation
|
|
327
|
-
self.agent = LitAgent()
|
|
328
|
-
# Use fingerprinting to create a consistent browser identity
|
|
329
|
-
self.fingerprint = self.agent.generate_fingerprint(browser)
|
|
330
|
-
|
|
331
|
-
# Use the fingerprint for headers
|
|
332
|
-
self.headers = {
|
|
333
|
-
"accept": "*/*",
|
|
334
|
-
"accept-encoding": "gzip, deflate, br, zstd",
|
|
335
|
-
"accept-language": self.fingerprint["accept_language"],
|
|
336
|
-
"content-type": "application/json",
|
|
337
|
-
"dnt": "1",
|
|
338
|
-
"origin": "https://chat.standard-input.com",
|
|
339
|
-
"referer": "https://chat.standard-input.com/",
|
|
340
|
-
"sec-ch-ua": self.fingerprint["sec_ch_ua"] or '"Microsoft Edge";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
|
|
341
|
-
"sec-ch-ua-mobile": "?0",
|
|
342
|
-
"sec-ch-ua-platform": f'"{self.fingerprint["platform"]}"',
|
|
343
|
-
"sec-fetch-dest": "empty",
|
|
344
|
-
"sec-fetch-mode": "cors",
|
|
345
|
-
"sec-fetch-site": "same-origin",
|
|
346
|
-
"sec-gpc": "1",
|
|
347
|
-
"user-agent": self.fingerprint["user_agent"],
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
# Default cookies - these should be updated for production use
|
|
351
|
-
self.cookies = {
|
|
352
|
-
"auth-chat": '''%7B%22user%22%3A%7B%22id%22%3A%2243a26ebd-7691-4a5a-8321-12aff017af86%22%2C%22email%22%3A%22iu511inmev%40illubd.com%22%2C%22accountId%22%3A%22057d78c9-06db-48eb-aeaa-0efdbaeb9446%22%2C%22provider%22%3A%22password%22%7D%2C%22tokens%22%3A%7B%22access%22%3A%22eyJhbGciOiJFUzI1NiIsImtpZCI6Ijg1NDhmZWY1LTk5MjYtNDk2Yi1hMjI2LTQ5OTExYjllYzU2NSIsInR5cCI6IkpXVCJ9.eyJtb2RlIjoiYWNjZXNzIiwidHlwZSI6InVzZXIiLCJwcm9wZXJ0aWVzIjp7ImlkIjoiNDNhMjZlYmQtNzY5MS00YTVhLTgzMzEtMTJhZmYwMTdhZjg2IiwiZW1haWwiOiJpdTUxMWlubWV2QGlsbHViZC5jb20iLCJhY2NvdW50SWQiOiIwNTdkNzhjOS0wNmRiLTQ4ZWItYWVhYS0wZWZkYmFlYjk0NDYiLCJwcm92aWRlciI6InBhc3N3b3JkIn0sImF1ZCI6InN0YW5kYXJkLWlucHV0LWlvcyIsImlzcyI6Imh0dHBzOi8vYXV0aC5zdGFuZGFyZC1pbnB1dC5jb20iLCJzdWIiOiJ1c2VyOjRmYWMzMTllZjA4MDRiZmMiLCJleHAiOjE3NDU0MDU5MDN9.d3VsEq-UCNsQWkiPlTVw7caS0wTXfCYe6yeFLeb4Ce6ZYTIFFn685SF-aKvLOxaYaq7Pyk4D2qr24riPVhxUWQ%22%2C%22refresh%22%3A%22user%3A4fac319ef0804bfc%3A3a757177-5507-4a36-9356-492f5ed06105%22%7D%7D''',
|
|
353
|
-
"auth": '''%7B%22user%22%3A%7B%22id%22%3A%22c51e291f-8f44-439d-a38b-9ea147581a13%22%2C%22email%22%3A%22r6cigexlsb%40mrotzis.com%22%2C%22accountId%22%3A%22599fd4ce-04a2-40f6-a78f-d33d0059b77f%22%2C%22provider%22%3A%22password%22%7D%2C%22tokens%22%3A%7B%22access%22%3A%22eyJhbGciOiJFUzI1NiIsImtpZCI6Ijg1NDhmZWY1LTk5MjYtNDk2Yi1hMjI2LTQ5OTExYjllYzU2NSIsInR5cCI6IkpXVCJ9.eyJtb2RlIjoiYWNjZXNzIiwidHlwZSI6InVzZXIiLCJwcm9wZXJ0aWVzIjp7ImlkIjoiYzUxZTI5MWYtOGY0NC00MzlkLWEzOGItOWVhMTQ3NTgxYTEzIiwiZW1haWwiOiJyNmNpZ2V4bHNiQG1yb3R6aXMuY29tIiwiYWNjb3VudElkIjoiNTk5ZmQ0Y2UtMDRhMi00MGY2LWE3OGYtZDMzZDAwNTliNzdmIiwicHJvdmlkZXIiOiJwYXNzd29yZCJ9LCJhdWQiOiJzdGFuZGFyZC1pbnB1dC1pb3MiLCJpc3MiOiJodHRwczovL2F1dGguc3RhbmRhcmQtaW5wdXQuY29tIiwic3ViIjoidXNlcjo4Y2FmMjRkYzUxNDc4MmNkIiwiZXhwIjoxNzQ2NzI0MTU3fQ.a3970nBJkd8JoU-khRA2JlRMuYeJ7378QS4ZL446kOkDi35uTwuC4qGrWH9efk9GkFaVcWPtYeOJjRb7f2SeJA%22%2C%22refresh%22%3A%22user%3A8caf24dc514782cd%3A14e24386-8443-4df0-ae25-234ad59218ef%22%7D%7D''',
|
|
354
|
-
"sidebar:state": "true",
|
|
355
|
-
"ph_phc_f3wUUyCfmKlKtkc2pfT7OsdcW2mBEVGN2A87yEYbG3c_posthog": '''%7B%22distinct_id%22%3A%220195c7cc-ac8f-79ff-b901-e14a78fc2a67%22%2C%22%24sesid%22%3A%5B1744688627860%2C%220196377f-9f12-77e6-a9ea-0e9669423803%22%2C1744687832850%5D%2C%22%24initial_person_info%22%3A%7B%22r%22%3A%22%24direct%22%2C%22u%22%3A%22https%3A%2F%2Fstandard-input.com%2F%22%7D%7D'''
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
# Initialize session with cloudscraper for better handling of Cloudflare protection
|
|
359
|
-
self.session = cloudscraper.create_scraper()
|
|
360
|
-
self.session.headers.update(self.headers)
|
|
361
|
-
|
|
362
|
-
# Initialize chat interface
|
|
363
|
-
self.chat = Chat(self)
|
|
364
|
-
|
|
365
|
-
def _refresh_identity(self, browser: str = None):
|
|
366
|
-
"""
|
|
367
|
-
Refreshes the browser identity fingerprint.
|
|
368
|
-
|
|
369
|
-
Args:
|
|
370
|
-
browser: Specific browser to use for the new fingerprint
|
|
371
|
-
"""
|
|
372
|
-
browser = browser or self.fingerprint.get("browser_type", "chrome")
|
|
373
|
-
self.fingerprint = self.agent.generate_fingerprint(browser)
|
|
374
|
-
|
|
375
|
-
# Update headers with new fingerprint
|
|
376
|
-
self.headers.update({
|
|
377
|
-
"Accept-Language": self.fingerprint["accept_language"],
|
|
378
|
-
"Sec-CH-UA": self.fingerprint["sec_ch_ua"] or self.headers["sec-ch-ua"],
|
|
379
|
-
"Sec-CH-UA-Platform": f'"{self.fingerprint["platform"]}"',
|
|
380
|
-
"User-Agent": self.fingerprint["user_agent"],
|
|
381
|
-
})
|
|
382
|
-
|
|
383
|
-
# Update session headers
|
|
384
|
-
for header, value in self.headers.items():
|
|
385
|
-
self.session.headers[header] = value
|
|
386
|
-
|
|
387
|
-
return self.fingerprint
|
|
388
|
-
|
|
389
|
-
def format_text(self, text: str) -> str:
|
|
390
|
-
"""
|
|
391
|
-
Format text by replacing escaped newlines with actual newlines.
|
|
392
|
-
|
|
393
|
-
Args:
|
|
394
|
-
text: Text to format
|
|
395
|
-
|
|
396
|
-
Returns:
|
|
397
|
-
Formatted text
|
|
398
|
-
"""
|
|
399
|
-
# Use a more comprehensive approach to handle all escape sequences
|
|
400
|
-
try:
|
|
401
|
-
# First handle double backslashes to avoid issues
|
|
402
|
-
text = text.replace('\\\\', '\\')
|
|
403
|
-
|
|
404
|
-
# Handle common escape sequences
|
|
405
|
-
text = text.replace('\\n', '\n')
|
|
406
|
-
text = text.replace('\\r', '\r')
|
|
407
|
-
text = text.replace('\\t', '\t')
|
|
408
|
-
text = text.replace('\\"', '"')
|
|
409
|
-
text = text.replace("\\'", "'")
|
|
410
|
-
|
|
411
|
-
# Handle any remaining escape sequences using JSON decoding
|
|
412
|
-
# This is a fallback in case there are other escape sequences
|
|
413
|
-
try:
|
|
414
|
-
# Add quotes to make it a valid JSON string
|
|
415
|
-
json_str = f'"{text}"'
|
|
416
|
-
# Use json module to decode all escape sequences
|
|
417
|
-
decoded = json.loads(json_str)
|
|
418
|
-
return decoded
|
|
419
|
-
except json.JSONDecodeError:
|
|
420
|
-
# If JSON decoding fails, return the text with the replacements we've already done
|
|
421
|
-
return text
|
|
422
|
-
except Exception as e:
|
|
423
|
-
# If any error occurs, return the original text
|
|
424
|
-
print(f"Warning: Error formatting text: {e}")
|
|
425
|
-
return text
|
|
426
|
-
|
|
427
|
-
@property
|
|
428
|
-
def models(self):
|
|
429
|
-
class _ModelList:
|
|
430
|
-
def list(inner_self):
|
|
431
|
-
return type(self).AVAILABLE_MODELS
|
|
432
|
-
return _ModelList()
|
|
433
|
-
|