webscout 8.2.1__tar.gz → 8.2.3__tar.gz

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.

Files changed (319) hide show
  1. {webscout-8.2.1/webscout.egg-info → webscout-8.2.3}/PKG-INFO +1 -1
  2. webscout-8.2.3/webscout/AIbase.py +260 -0
  3. {webscout-8.2.1 → webscout-8.2.3}/webscout/Bard.py +5 -0
  4. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/tempmail/__init__.py +2 -0
  5. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/tempmail/base.py +6 -1
  6. webscout-8.2.3/webscout/Extra/tempmail/emailnator.py +84 -0
  7. webscout-8.2.3/webscout/Local/__init__.py +12 -0
  8. {webscout-8.2.1 → webscout-8.2.3}/webscout/Local/cli.py +178 -0
  9. {webscout-8.2.1 → webscout-8.2.3}/webscout/Local/llm.py +104 -5
  10. {webscout-8.2.1 → webscout-8.2.3}/webscout/Local/model_manager.py +48 -0
  11. webscout-8.2.3/webscout/Local/server.py +721 -0
  12. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Cloudflare.py +5 -0
  13. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Gemini.py +2 -0
  14. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/e2b.py +159 -1
  15. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/textpollinations.py +90 -44
  16. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/toolbaz.py +4 -4
  17. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTS/__init__.py +1 -0
  18. webscout-8.2.3/webscout/Provider/TTS/base.py +159 -0
  19. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTS/deepgram.py +16 -16
  20. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTS/elevenlabs.py +5 -5
  21. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTS/gesserit.py +6 -5
  22. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTS/murfai.py +7 -7
  23. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTS/parler.py +6 -6
  24. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTS/speechma.py +22 -22
  25. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTS/streamElements.py +7 -7
  26. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TextPollinationsAI.py +56 -41
  27. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/toolbaz.py +4 -4
  28. webscout-8.2.3/webscout/version.py +2 -0
  29. {webscout-8.2.1 → webscout-8.2.3/webscout.egg-info}/PKG-INFO +1 -1
  30. {webscout-8.2.1 → webscout-8.2.3}/webscout.egg-info/SOURCES.txt +2 -0
  31. webscout-8.2.1/webscout/AIbase.py +0 -123
  32. webscout-8.2.1/webscout/Local/__init__.py +0 -6
  33. webscout-8.2.1/webscout/Local/server.py +0 -187
  34. webscout-8.2.1/webscout/version.py +0 -2
  35. {webscout-8.2.1 → webscout-8.2.3}/LICENSE.md +0 -0
  36. {webscout-8.2.1 → webscout-8.2.3}/README.md +0 -0
  37. {webscout-8.2.1 → webscout-8.2.3}/inferno/__init__.py +0 -0
  38. {webscout-8.2.1 → webscout-8.2.3}/inferno/__main__.py +0 -0
  39. {webscout-8.2.1 → webscout-8.2.3}/inferno/cli.py +0 -0
  40. {webscout-8.2.1 → webscout-8.2.3}/setup.cfg +0 -0
  41. {webscout-8.2.1 → webscout-8.2.3}/setup.py +0 -0
  42. {webscout-8.2.1 → webscout-8.2.3}/webscout/AIauto.py +0 -0
  43. {webscout-8.2.1 → webscout-8.2.3}/webscout/AIutel.py +0 -0
  44. {webscout-8.2.1 → webscout-8.2.3}/webscout/DWEBS.py +0 -0
  45. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/GitToolkit/__init__.py +0 -0
  46. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/GitToolkit/gitapi/__init__.py +0 -0
  47. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/GitToolkit/gitapi/repository.py +0 -0
  48. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/GitToolkit/gitapi/user.py +0 -0
  49. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/GitToolkit/gitapi/utils.py +0 -0
  50. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/YTdownloader.py +0 -0
  51. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/__init__.py +0 -0
  52. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/transcriber.py +0 -0
  53. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/__init__.py +0 -0
  54. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/channel.py +0 -0
  55. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/errors.py +0 -0
  56. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/extras.py +0 -0
  57. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/https.py +0 -0
  58. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/patterns.py +0 -0
  59. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/playlist.py +0 -0
  60. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/pool.py +0 -0
  61. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/query.py +0 -0
  62. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/stream.py +0 -0
  63. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/utils.py +0 -0
  64. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/YTToolkit/ytapi/video.py +0 -0
  65. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/__init__.py +0 -0
  66. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/autocoder/__init__.py +0 -0
  67. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/autocoder/autocoder.py +0 -0
  68. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/autocoder/autocoder_utiles.py +0 -0
  69. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/gguf.py +0 -0
  70. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/tempmail/async_utils.py +0 -0
  71. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/tempmail/cli.py +0 -0
  72. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/tempmail/mail_tm.py +0 -0
  73. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/tempmail/temp_mail_io.py +0 -0
  74. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/weather.py +0 -0
  75. {webscout-8.2.1 → webscout-8.2.3}/webscout/Extra/weather_ascii.py +0 -0
  76. {webscout-8.2.1 → webscout-8.2.3}/webscout/LLM.py +0 -0
  77. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/__init__.py +0 -0
  78. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/core/__init__.py +0 -0
  79. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/core/level.py +0 -0
  80. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/core/logger.py +0 -0
  81. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/handlers/__init__.py +0 -0
  82. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/handlers/console.py +0 -0
  83. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/handlers/file.py +0 -0
  84. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/handlers/network.py +0 -0
  85. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/styles/__init__.py +0 -0
  86. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/styles/colors.py +0 -0
  87. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/styles/formats.py +0 -0
  88. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/styles/text.py +0 -0
  89. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/utils/__init__.py +0 -0
  90. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/utils/detectors.py +0 -0
  91. {webscout-8.2.1 → webscout-8.2.3}/webscout/Litlogger/utils/formatters.py +0 -0
  92. {webscout-8.2.1 → webscout-8.2.3}/webscout/Local/__main__.py +0 -0
  93. {webscout-8.2.1 → webscout-8.2.3}/webscout/Local/api.py +0 -0
  94. {webscout-8.2.1 → webscout-8.2.3}/webscout/Local/config.py +0 -0
  95. {webscout-8.2.1 → webscout-8.2.3}/webscout/Local/utils.py +0 -0
  96. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AI21.py +0 -0
  97. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AISEARCH/DeepFind.py +0 -0
  98. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AISEARCH/ISou.py +0 -0
  99. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AISEARCH/Perplexity.py +0 -0
  100. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AISEARCH/__init__.py +0 -0
  101. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AISEARCH/felo_search.py +0 -0
  102. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AISEARCH/genspark_search.py +0 -0
  103. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AISEARCH/hika_search.py +0 -0
  104. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AISEARCH/iask_search.py +0 -0
  105. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AISEARCH/monica_search.py +0 -0
  106. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AISEARCH/scira_search.py +0 -0
  107. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AISEARCH/webpilotai_search.py +0 -0
  108. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Aitopia.py +0 -0
  109. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/AllenAI.py +0 -0
  110. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Andi.py +0 -0
  111. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Blackboxai.py +0 -0
  112. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/C4ai.py +0 -0
  113. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/ChatGPTClone.py +0 -0
  114. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/ChatGPTES.py +0 -0
  115. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/ChatGPTGratis.py +0 -0
  116. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Chatify.py +0 -0
  117. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Cohere.py +0 -0
  118. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/DeepSeek.py +0 -0
  119. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Deepinfra.py +0 -0
  120. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/ElectronHub.py +0 -0
  121. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/ExaAI.py +0 -0
  122. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/ExaChat.py +0 -0
  123. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Free2GPT.py +0 -0
  124. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/GPTWeb.py +0 -0
  125. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/GithubChat.py +0 -0
  126. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Glider.py +0 -0
  127. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Groq.py +0 -0
  128. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/HF_space/__init__.py +0 -0
  129. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/HF_space/qwen_qwen2.py +0 -0
  130. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/HeckAI.py +0 -0
  131. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/HuggingFaceChat.py +0 -0
  132. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Hunyuan.py +0 -0
  133. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Jadve.py +0 -0
  134. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Koboldai.py +0 -0
  135. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/LambdaChat.py +0 -0
  136. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Llama.py +0 -0
  137. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Llama3.py +0 -0
  138. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Marcus.py +0 -0
  139. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Netwrck.py +0 -0
  140. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OLLAMA.py +0 -0
  141. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/__init__.py +0 -0
  142. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/base.py +0 -0
  143. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/c4ai.py +0 -0
  144. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/chatgpt.py +0 -0
  145. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/chatgptclone.py +0 -0
  146. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/deepinfra.py +0 -0
  147. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/exaai.py +0 -0
  148. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/exachat.py +0 -0
  149. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/freeaichat.py +0 -0
  150. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/glider.py +0 -0
  151. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/heckai.py +0 -0
  152. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/llmchatco.py +0 -0
  153. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/netwrck.py +0 -0
  154. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/opkfc.py +0 -0
  155. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/scirachat.py +0 -0
  156. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/sonus.py +0 -0
  157. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/standardinput.py +0 -0
  158. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/typegpt.py +0 -0
  159. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/uncovrAI.py +0 -0
  160. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/utils.py +0 -0
  161. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/venice.py +0 -0
  162. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/wisecat.py +0 -0
  163. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/writecream.py +0 -0
  164. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/x0gpt.py +0 -0
  165. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OPENAI/yep.py +0 -0
  166. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/OpenGPT.py +0 -0
  167. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Openai.py +0 -0
  168. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/PI.py +0 -0
  169. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Perplexitylabs.py +0 -0
  170. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Phind.py +0 -0
  171. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/PizzaGPT.py +0 -0
  172. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/QwenLM.py +0 -0
  173. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Reka.py +0 -0
  174. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/StandardInput.py +0 -0
  175. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/AiForce/__init__.py +0 -0
  176. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/AiForce/async_aiforce.py +0 -0
  177. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/AiForce/sync_aiforce.py +0 -0
  178. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/FreeAIPlayground/__init__.py +0 -0
  179. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +0 -0
  180. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +0 -0
  181. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/ImgSys/__init__.py +0 -0
  182. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/ImgSys/async_imgsys.py +0 -0
  183. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/ImgSys/sync_imgsys.py +0 -0
  184. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/MagicStudio/__init__.py +0 -0
  185. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/MagicStudio/async_magicstudio.py +0 -0
  186. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/MagicStudio/sync_magicstudio.py +0 -0
  187. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/Nexra/__init__.py +0 -0
  188. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/Nexra/async_nexra.py +0 -0
  189. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/Nexra/sync_nexra.py +0 -0
  190. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/PollinationsAI/__init__.py +0 -0
  191. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/PollinationsAI/async_pollinations.py +0 -0
  192. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +0 -0
  193. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/__init__.py +0 -0
  194. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/aiarta/__init__.py +0 -0
  195. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/aiarta/async_aiarta.py +0 -0
  196. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/aiarta/sync_aiarta.py +0 -0
  197. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/artbit/__init__.py +0 -0
  198. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/artbit/async_artbit.py +0 -0
  199. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/artbit/sync_artbit.py +0 -0
  200. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/fastflux/__init__.py +0 -0
  201. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/fastflux/async_fastflux.py +0 -0
  202. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/fastflux/sync_fastflux.py +0 -0
  203. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/huggingface/__init__.py +0 -0
  204. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/huggingface/async_huggingface.py +0 -0
  205. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/huggingface/sync_huggingface.py +0 -0
  206. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/piclumen/__init__.py +0 -0
  207. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/piclumen/async_piclumen.py +0 -0
  208. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/piclumen/sync_piclumen.py +0 -0
  209. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/pixelmuse/__init__.py +0 -0
  210. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/pixelmuse/async_pixelmuse.py +0 -0
  211. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/pixelmuse/sync_pixelmuse.py +0 -0
  212. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/talkai/__init__.py +0 -0
  213. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/talkai/async_talkai.py +0 -0
  214. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTI/talkai/sync_talkai.py +0 -0
  215. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TTS/utils.py +0 -0
  216. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TeachAnything.py +0 -0
  217. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/TwoAI.py +0 -0
  218. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Venice.py +0 -0
  219. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/VercelAI.py +0 -0
  220. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/WebSim.py +0 -0
  221. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/WiseCat.py +0 -0
  222. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Writecream.py +0 -0
  223. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/WritingMate.py +0 -0
  224. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/Youchat.py +0 -0
  225. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/__init__.py +0 -0
  226. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/ai4chat.py +0 -0
  227. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/aimathgpt.py +0 -0
  228. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/akashgpt.py +0 -0
  229. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/askmyai.py +0 -0
  230. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/asksteve.py +0 -0
  231. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/bagoodex.py +0 -0
  232. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/cerebras.py +0 -0
  233. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/chatglm.py +0 -0
  234. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/cleeai.py +0 -0
  235. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/copilot.py +0 -0
  236. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/elmo.py +0 -0
  237. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/freeaichat.py +0 -0
  238. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/gaurish.py +0 -0
  239. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/geminiapi.py +0 -0
  240. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/geminiprorealtime.py +0 -0
  241. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/granite.py +0 -0
  242. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/hermes.py +0 -0
  243. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/julius.py +0 -0
  244. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/koala.py +0 -0
  245. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/labyrinth.py +0 -0
  246. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/learnfastai.py +0 -0
  247. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/lepton.py +0 -0
  248. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/llama3mitril.py +0 -0
  249. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/llamatutor.py +0 -0
  250. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/llmchat.py +0 -0
  251. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/llmchatco.py +0 -0
  252. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/meta.py +0 -0
  253. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/multichat.py +0 -0
  254. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/promptrefine.py +0 -0
  255. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/scira_chat.py +0 -0
  256. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/scnet.py +0 -0
  257. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/searchchat.py +0 -0
  258. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/sonus.py +0 -0
  259. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/talkai.py +0 -0
  260. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/turboseek.py +0 -0
  261. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/tutorai.py +0 -0
  262. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/typefully.py +0 -0
  263. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/typegpt.py +0 -0
  264. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/uncovr.py +0 -0
  265. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/x0gpt.py +0 -0
  266. {webscout-8.2.1 → webscout-8.2.3}/webscout/Provider/yep.py +0 -0
  267. {webscout-8.2.1 → webscout-8.2.3}/webscout/__init__.py +0 -0
  268. {webscout-8.2.1 → webscout-8.2.3}/webscout/__main__.py +0 -0
  269. {webscout-8.2.1 → webscout-8.2.3}/webscout/cli.py +0 -0
  270. {webscout-8.2.1 → webscout-8.2.3}/webscout/conversation.py +0 -0
  271. {webscout-8.2.1 → webscout-8.2.3}/webscout/exceptions.py +0 -0
  272. {webscout-8.2.1 → webscout-8.2.3}/webscout/litagent/__init__.py +0 -0
  273. {webscout-8.2.1 → webscout-8.2.3}/webscout/litagent/agent.py +0 -0
  274. {webscout-8.2.1 → webscout-8.2.3}/webscout/litagent/constants.py +0 -0
  275. {webscout-8.2.1 → webscout-8.2.3}/webscout/litprinter/__init__.py +0 -0
  276. {webscout-8.2.1 → webscout-8.2.3}/webscout/models.py +0 -0
  277. {webscout-8.2.1 → webscout-8.2.3}/webscout/optimizers.py +0 -0
  278. {webscout-8.2.1 → webscout-8.2.3}/webscout/prompt_manager.py +0 -0
  279. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/__init__.py +0 -0
  280. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/core/__init__.py +0 -0
  281. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/core/crawler.py +0 -0
  282. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/core/scout.py +0 -0
  283. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/core/search_result.py +0 -0
  284. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/core/text_analyzer.py +0 -0
  285. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/core/text_utils.py +0 -0
  286. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/core/web_analyzer.py +0 -0
  287. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/core.py +0 -0
  288. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/element.py +0 -0
  289. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/parsers/__init__.py +0 -0
  290. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/parsers/html5lib_parser.py +0 -0
  291. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/parsers/html_parser.py +0 -0
  292. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/parsers/lxml_parser.py +0 -0
  293. {webscout-8.2.1 → webscout-8.2.3}/webscout/scout/utils.py +0 -0
  294. {webscout-8.2.1 → webscout-8.2.3}/webscout/swiftcli/__init__.py +0 -0
  295. {webscout-8.2.1 → webscout-8.2.3}/webscout/tempid.py +0 -0
  296. {webscout-8.2.1 → webscout-8.2.3}/webscout/update_checker.py +0 -0
  297. {webscout-8.2.1 → webscout-8.2.3}/webscout/utils.py +0 -0
  298. {webscout-8.2.1 → webscout-8.2.3}/webscout/webscout_search.py +0 -0
  299. {webscout-8.2.1 → webscout-8.2.3}/webscout/webscout_search_async.py +0 -0
  300. {webscout-8.2.1 → webscout-8.2.3}/webscout/yep_search.py +0 -0
  301. {webscout-8.2.1 → webscout-8.2.3}/webscout/zeroart/__init__.py +0 -0
  302. {webscout-8.2.1 → webscout-8.2.3}/webscout/zeroart/base.py +0 -0
  303. {webscout-8.2.1 → webscout-8.2.3}/webscout/zeroart/effects.py +0 -0
  304. {webscout-8.2.1 → webscout-8.2.3}/webscout/zeroart/fonts.py +0 -0
  305. {webscout-8.2.1 → webscout-8.2.3}/webscout.egg-info/dependency_links.txt +0 -0
  306. {webscout-8.2.1 → webscout-8.2.3}/webscout.egg-info/entry_points.txt +0 -0
  307. {webscout-8.2.1 → webscout-8.2.3}/webscout.egg-info/requires.txt +0 -0
  308. {webscout-8.2.1 → webscout-8.2.3}/webscout.egg-info/top_level.txt +0 -0
  309. {webscout-8.2.1 → webscout-8.2.3}/webstoken/__init__.py +0 -0
  310. {webscout-8.2.1 → webscout-8.2.3}/webstoken/classifier.py +0 -0
  311. {webscout-8.2.1 → webscout-8.2.3}/webstoken/keywords.py +0 -0
  312. {webscout-8.2.1 → webscout-8.2.3}/webstoken/language.py +0 -0
  313. {webscout-8.2.1 → webscout-8.2.3}/webstoken/ner.py +0 -0
  314. {webscout-8.2.1 → webscout-8.2.3}/webstoken/normalizer.py +0 -0
  315. {webscout-8.2.1 → webscout-8.2.3}/webstoken/processor.py +0 -0
  316. {webscout-8.2.1 → webscout-8.2.3}/webstoken/sentiment.py +0 -0
  317. {webscout-8.2.1 → webscout-8.2.3}/webstoken/stemmer.py +0 -0
  318. {webscout-8.2.1 → webscout-8.2.3}/webstoken/tagger.py +0 -0
  319. {webscout-8.2.1 → webscout-8.2.3}/webstoken/tokenizer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: webscout
3
- Version: 8.2.1
3
+ Version: 8.2.3
4
4
  Summary: Search for anything using Google, DuckDuckGo, phind.com, Contains AI models, can transcribe yt videos, temporary email and phone number generation, has TTS support, webai (terminal gpt and open interpreter) and offline LLMs and more
5
5
  Author: OEvortex
6
6
  Author-email: helpingai5@gmail.com
@@ -0,0 +1,260 @@
1
+ from abc import ABC, abstractmethod
2
+ from pathlib import Path
3
+ from typing import AsyncGenerator, List, Union, Generator, Optional
4
+ from typing_extensions import TypeAlias
5
+
6
+ # Type aliases for better readability
7
+ Response: TypeAlias = dict[str, Union[str, bool, None]]
8
+ ImageData: TypeAlias = Union[bytes, str, Generator[bytes, None, None]]
9
+ AsyncImageData: TypeAlias = Union[bytes, str, AsyncGenerator[bytes, None]]
10
+
11
+ class AIProviderError(Exception):
12
+ pass
13
+
14
+ class Provider(ABC):
15
+
16
+ @abstractmethod
17
+ def ask(
18
+ self,
19
+ prompt: str,
20
+ stream: bool = False,
21
+ raw: bool = False,
22
+ optimizer: Optional[str] = None,
23
+ conversationally: bool = False,
24
+ ) -> Response:
25
+ raise NotImplementedError("Method needs to be implemented in subclass")
26
+
27
+ @abstractmethod
28
+ def chat(
29
+ self,
30
+ prompt: str,
31
+ stream: bool = False,
32
+ optimizer: Optional[str] = None,
33
+ conversationally: bool = False,
34
+ ) -> str:
35
+ raise NotImplementedError("Method needs to be implemented in subclass")
36
+
37
+ @abstractmethod
38
+ def get_message(self, response: Response) -> str:
39
+ raise NotImplementedError("Method needs to be implemented in subclass")
40
+
41
+ class AsyncProvider(ABC):
42
+
43
+ @abstractmethod
44
+ async def ask(
45
+ self,
46
+ prompt: str,
47
+ stream: bool = False,
48
+ raw: bool = False,
49
+ optimizer: Optional[str] = None,
50
+ conversationally: bool = False,
51
+ ) -> Response:
52
+ raise NotImplementedError("Method needs to be implemented in subclass")
53
+
54
+ @abstractmethod
55
+ async def chat(
56
+ self,
57
+ prompt: str,
58
+ stream: bool = False,
59
+ optimizer: Optional[str] = None,
60
+ conversationally: bool = False,
61
+ ) -> str:
62
+ raise NotImplementedError("Method needs to be implemented in subclass")
63
+
64
+ @abstractmethod
65
+ async def get_message(self, response: Response) -> str:
66
+ raise NotImplementedError("Method needs to be implemented in subclass")
67
+
68
+ class TTSProvider(ABC):
69
+
70
+ @abstractmethod
71
+ def tts(self, text: str, voice: str = None, verbose: bool = False) -> str:
72
+ """Convert text to speech and save to a temporary file.
73
+
74
+ Args:
75
+ text (str): The text to convert to speech
76
+ voice (str, optional): The voice to use. Defaults to provider's default voice.
77
+ verbose (bool, optional): Whether to print debug information. Defaults to False.
78
+
79
+ Returns:
80
+ str: Path to the generated audio file
81
+ """
82
+ raise NotImplementedError("Method needs to be implemented in subclass")
83
+
84
+ def save_audio(self, audio_file: str, destination: str = None, verbose: bool = False) -> str:
85
+ """Save audio to a specific destination.
86
+
87
+ Args:
88
+ audio_file (str): Path to the source audio file
89
+ destination (str, optional): Destination path. Defaults to current directory with timestamp.
90
+ verbose (bool, optional): Whether to print debug information. Defaults to False.
91
+
92
+ Returns:
93
+ str: Path to the saved audio file
94
+ """
95
+ import shutil
96
+ import os
97
+ from pathlib import Path
98
+ import time
99
+
100
+ source_path = Path(audio_file)
101
+
102
+ if not source_path.exists():
103
+ raise FileNotFoundError(f"Audio file not found: {audio_file}")
104
+
105
+ if destination is None:
106
+ # Create a default destination with timestamp in current directory
107
+ timestamp = int(time.time())
108
+ destination = os.path.join(os.getcwd(), f"tts_audio_{timestamp}{source_path.suffix}")
109
+
110
+ # Ensure the destination directory exists
111
+ os.makedirs(os.path.dirname(os.path.abspath(destination)), exist_ok=True)
112
+
113
+ # Copy the file
114
+ shutil.copy2(source_path, destination)
115
+
116
+ if verbose:
117
+ print(f"[debug] Audio saved to {destination}")
118
+
119
+ return destination
120
+
121
+ def stream_audio(self, text: str, voice: str = None, chunk_size: int = 1024, verbose: bool = False) -> Generator[bytes, None, None]:
122
+ """Stream audio in chunks.
123
+
124
+ Args:
125
+ text (str): The text to convert to speech
126
+ voice (str, optional): The voice to use. Defaults to provider's default voice.
127
+ chunk_size (int, optional): Size of audio chunks to yield. Defaults to 1024.
128
+ verbose (bool, optional): Whether to print debug information. Defaults to False.
129
+
130
+ Yields:
131
+ Generator[bytes, None, None]: Audio data chunks
132
+ """
133
+ # Generate the audio file
134
+ audio_file = self.tts(text, voice=voice, verbose=verbose)
135
+
136
+ # Stream the file in chunks
137
+ with open(audio_file, 'rb') as f:
138
+ while chunk := f.read(chunk_size):
139
+ yield chunk
140
+
141
+ class AsyncTTSProvider(ABC):
142
+
143
+ @abstractmethod
144
+ async def tts(self, text: str, voice: str = None, verbose: bool = False) -> str:
145
+ """Convert text to speech and save to a temporary file asynchronously.
146
+
147
+ Args:
148
+ text (str): The text to convert to speech
149
+ voice (str, optional): The voice to use. Defaults to provider's default voice.
150
+ verbose (bool, optional): Whether to print debug information. Defaults to False.
151
+
152
+ Returns:
153
+ str: Path to the generated audio file
154
+ """
155
+ raise NotImplementedError("Method needs to be implemented in subclass")
156
+
157
+ async def save_audio(self, audio_file: str, destination: str = None, verbose: bool = False) -> str:
158
+ """Save audio to a specific destination asynchronously.
159
+
160
+ Args:
161
+ audio_file (str): Path to the source audio file
162
+ destination (str, optional): Destination path. Defaults to current directory with timestamp.
163
+ verbose (bool, optional): Whether to print debug information. Defaults to False.
164
+
165
+ Returns:
166
+ str: Path to the saved audio file
167
+ """
168
+ import shutil
169
+ import os
170
+ from pathlib import Path
171
+ import time
172
+ import asyncio
173
+
174
+ source_path = Path(audio_file)
175
+
176
+ if not source_path.exists():
177
+ raise FileNotFoundError(f"Audio file not found: {audio_file}")
178
+
179
+ if destination is None:
180
+ # Create a default destination with timestamp in current directory
181
+ timestamp = int(time.time())
182
+ destination = os.path.join(os.getcwd(), f"tts_audio_{timestamp}{source_path.suffix}")
183
+
184
+ # Ensure the destination directory exists
185
+ os.makedirs(os.path.dirname(os.path.abspath(destination)), exist_ok=True)
186
+
187
+ # Copy the file using asyncio to avoid blocking
188
+ await asyncio.to_thread(shutil.copy2, source_path, destination)
189
+
190
+ if verbose:
191
+ print(f"[debug] Audio saved to {destination}")
192
+
193
+ return destination
194
+
195
+ async def stream_audio(self, text: str, voice: str = None, chunk_size: int = 1024, verbose: bool = False) -> AsyncGenerator[bytes, None]:
196
+ """Stream audio in chunks asynchronously.
197
+
198
+ Args:
199
+ text (str): The text to convert to speech
200
+ voice (str, optional): The voice to use. Defaults to provider's default voice.
201
+ chunk_size (int, optional): Size of audio chunks to yield. Defaults to 1024.
202
+ verbose (bool, optional): Whether to print debug information. Defaults to False.
203
+
204
+ Yields:
205
+ AsyncGenerator[bytes, None]: Audio data chunks
206
+ """
207
+ import aiofiles
208
+
209
+ # Generate the audio file
210
+ audio_file = await self.tts(text, voice=voice, verbose=verbose)
211
+
212
+ # Stream the file in chunks
213
+ async with aiofiles.open(audio_file, 'rb') as f:
214
+ while chunk := await f.read(chunk_size):
215
+ yield chunk
216
+
217
+ class ImageProvider(ABC):
218
+
219
+ @abstractmethod
220
+ def generate(self, prompt: str, amount: int = 1) -> List[bytes]:
221
+ raise NotImplementedError("Method needs to be implemented in subclass")
222
+
223
+ @abstractmethod
224
+ def save(
225
+ self,
226
+ response: List[bytes],
227
+ name: Optional[str] = None,
228
+ dir: Optional[Union[str, Path]] = None
229
+ ) -> List[str]:
230
+ raise NotImplementedError("Method needs to be implemented in subclass")
231
+
232
+ class AsyncImageProvider(ABC):
233
+
234
+ @abstractmethod
235
+ async def generate(
236
+ self,
237
+ prompt: str,
238
+ amount: int = 1
239
+ ) -> Union[AsyncGenerator[bytes, None], List[bytes]]:
240
+ raise NotImplementedError("Method needs to be implemented in subclass")
241
+
242
+ @abstractmethod
243
+ async def save(
244
+ self,
245
+ response: Union[AsyncGenerator[bytes, None], List[bytes]],
246
+ name: Optional[str] = None,
247
+ dir: Optional[Union[str, Path]] = None
248
+ ) -> List[str]:
249
+ raise NotImplementedError("Method needs to be implemented in subclass")
250
+
251
+ class AISearch(ABC):
252
+
253
+ @abstractmethod
254
+ def search(
255
+ self,
256
+ prompt: str,
257
+ stream: bool = False,
258
+ raw: bool = False,
259
+ ) -> Response:
260
+ raise NotImplementedError("Method needs to be implemented in subclass")
@@ -76,6 +76,11 @@ class Model(Enum):
76
76
  {"x-goog-ext-525001261-jspb": '[null,null,null,null,"203e6bb81620bcfe"]'},
77
77
  True,
78
78
  )
79
+ G_2_5_FLASH = (
80
+ "gemini-2.5-flash",
81
+ {"x-goog-ext-525001261-jspb": '[1,null,null,null,"35609594dbe934d8"]'},
82
+ False,
83
+ )
79
84
 
80
85
  def __init__(self, name, header, advanced_only):
81
86
  self.model_name = name
@@ -12,6 +12,7 @@ from .base import (
12
12
  )
13
13
  from .mail_tm import MailTM, MailTMAsync
14
14
  from .temp_mail_io import TempMailIO, TempMailIOAsync
15
+ from .emailnator import EmailnatorProvider
15
16
 
16
17
  __all__ = [
17
18
  'TempMailProvider',
@@ -20,6 +21,7 @@ __all__ = [
20
21
  'MailTMAsync',
21
22
  'TempMailIO',
22
23
  'TempMailIOAsync',
24
+ 'EmailnatorProvider',
23
25
  'get_random_email',
24
26
  'get_disposable_email',
25
27
  'get_provider'
@@ -99,7 +99,7 @@ def get_provider(provider_name: str = "mailtm", async_provider: bool = False) ->
99
99
  Get a temporary email provider instance
100
100
 
101
101
  Args:
102
- provider_name: Name of the provider to use ("mailtm" or "tempmailio")
102
+ provider_name: Name of the provider to use ("mailtm", "tempmailio", or "emailnator")
103
103
  async_provider: Whether to return an async provider
104
104
 
105
105
  Returns:
@@ -109,6 +109,8 @@ def get_provider(provider_name: str = "mailtm", async_provider: bool = False) ->
109
109
  if provider_name.lower() == "tempmailio":
110
110
  from .temp_mail_io import TempMailIOAsync
111
111
  return TempMailIOAsync()
112
+ elif provider_name.lower() == "emailnator":
113
+ raise NotImplementedError("Emailnator async provider not implemented.")
112
114
  else:
113
115
  from .mail_tm import MailTMAsync
114
116
  return MailTMAsync()
@@ -116,6 +118,9 @@ def get_provider(provider_name: str = "mailtm", async_provider: bool = False) ->
116
118
  if provider_name.lower() == "tempmailio":
117
119
  from .temp_mail_io import TempMailIO
118
120
  return TempMailIO()
121
+ elif provider_name.lower() == "emailnator":
122
+ from .emailnator import EmailnatorProvider
123
+ return EmailnatorProvider()
119
124
  else:
120
125
  from .mail_tm import MailTM
121
126
  return MailTM()
@@ -0,0 +1,84 @@
1
+ """
2
+ Emailnator Provider Implementation
3
+ Synchronous provider for Emailnator.com
4
+ """
5
+
6
+ from typing import List, Dict
7
+ from time import sleep
8
+ from requests import Session
9
+ from webscout.litagent import LitAgent
10
+ from .base import TempMailProvider
11
+ from json import loads
12
+ from re import findall
13
+
14
+ class EmailnatorProvider(TempMailProvider):
15
+ def __init__(self):
16
+ self.client = Session()
17
+ self.client.get("https://www.emailnator.com/", timeout=6)
18
+ self.cookies = self.client.cookies.get_dict()
19
+ self.user_agent = LitAgent()
20
+ self.client.headers = {
21
+ "authority": "www.emailnator.com",
22
+ "origin": "https://www.emailnator.com",
23
+ "referer": "https://www.emailnator.com/",
24
+ "user-agent": self.user_agent.random(),
25
+ "x-xsrf-token": self.client.cookies.get("XSRF-TOKEN")[:-3] + "=",
26
+ }
27
+ self.email = None
28
+ self._messages = []
29
+ self._account_deleted = False
30
+
31
+ def create_account(self) -> bool:
32
+ response = self.client.post(
33
+ "https://www.emailnator.com/generate-email",
34
+ json={"email": ["plusGmail", "dotGmail"]},
35
+ )
36
+ self.email = loads(response.text)["email"][0]
37
+ return bool(self.email)
38
+
39
+ def get_messages(self) -> List[Dict]:
40
+ # Wait for at least one message
41
+ for _ in range(30): # Wait up to 60 seconds
42
+ sleep(2)
43
+ mail_token = self.client.post(
44
+ "https://www.emailnator.com/message-list", json={"email": self.email}
45
+ )
46
+ mail_token = loads(mail_token.text)["messageData"]
47
+ if len(mail_token) > 1:
48
+ break
49
+ else:
50
+ return []
51
+ # Get message details
52
+ messages = []
53
+ for msg in mail_token[1:]:
54
+ msg_id = msg["messageID"]
55
+ mail_context = self.client.post(
56
+ "https://www.emailnator.com/message-list",
57
+ json={"email": self.email, "messageID": msg_id},
58
+ )
59
+ # The response is HTML, so we just store it as body
60
+ messages.append({
61
+ "msg_id": msg_id,
62
+ "from": msg.get("from", ""),
63
+ "subject": msg.get("subject", ""),
64
+ "body": mail_context.text,
65
+ })
66
+ self._messages = messages
67
+ return messages
68
+
69
+ def check_new_messages(self) -> List[Dict]:
70
+ current = self.get_messages()
71
+ if not self._messages:
72
+ return current
73
+ # Return only new messages
74
+ old_ids = {m["msg_id"] for m in self._messages}
75
+ new_msgs = [m for m in current if m["msg_id"] not in old_ids]
76
+ return new_msgs
77
+
78
+ def delete_account(self) -> bool:
79
+ # Emailnator does not support explicit account deletion, so just mark as deleted
80
+ self._account_deleted = True
81
+ return True
82
+
83
+ def get_account_info(self) -> Dict:
84
+ return {"email": self.email, "deleted": self._account_deleted}
@@ -0,0 +1,12 @@
1
+ """
2
+ Webscout.Local - A llama-cpp-python based LLM serving tool with Ollama-compatible API
3
+ """
4
+ from webscout.version import __version__
5
+
6
+ # Import main components for easier access
7
+ from .llm import LLMInterface
8
+ from .model_manager import ModelManager
9
+ from .server import start_server
10
+
11
+ # Define what's available when using `from webscout.Local import *`
12
+ __all__ = ["LLMInterface", "ModelManager", "start_server"]
@@ -17,6 +17,16 @@ console: Console = Console()
17
17
 
18
18
  model_manager: ModelManager = ModelManager()
19
19
 
20
+ # RAM requirements for different model sizes
21
+ RAM_REQUIREMENTS = {
22
+ "1B": "2 GB",
23
+ "3B": "4 GB",
24
+ "7B": "8 GB",
25
+ "13B": "16 GB",
26
+ "33B": "32 GB",
27
+ "70B": "64 GB",
28
+ }
29
+
20
30
  @app.command("serve")
21
31
  def run_model(
22
32
  model_string: str = typer.Argument(..., help="Model to run (format: 'name', 'repo_id' or 'repo_id:filename')"),
@@ -55,6 +65,16 @@ def run_model(
55
65
  console.print(f"[bold red]Error downloading model: {str(e)}[/bold red]")
56
66
  return
57
67
 
68
+ # Check RAM requirements
69
+ ram_requirement = "Unknown"
70
+ for size, ram in RAM_REQUIREMENTS.items():
71
+ if size in model_name:
72
+ ram_requirement = ram
73
+ break
74
+
75
+ if ram_requirement != "Unknown":
76
+ console.print(f"[yellow]This model requires approximately {ram_requirement} of RAM[/yellow]")
77
+
58
78
  # Try to load the model to verify it works
59
79
  try:
60
80
  llm = LLMInterface(model_name)
@@ -96,12 +116,42 @@ def list_models() -> None:
96
116
  table.add_column("Name", style="cyan")
97
117
  table.add_column("Repository", style="green")
98
118
  table.add_column("Filename", style="blue")
119
+ table.add_column("Size", style="magenta")
120
+ table.add_column("Downloaded", style="yellow")
99
121
 
100
122
  for model in models:
123
+ # Get file size in human-readable format
124
+ file_path = model.get("path")
125
+ file_size = "Unknown"
126
+ if file_path:
127
+ try:
128
+ import os
129
+ size_bytes = os.path.getsize(file_path)
130
+ # Convert to human-readable format
131
+ for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
132
+ if size_bytes < 1024.0 or unit == 'TB':
133
+ file_size = f"{size_bytes:.2f} {unit}"
134
+ break
135
+ size_bytes /= 1024.0
136
+ except Exception:
137
+ pass
138
+
139
+ # Format downloaded date
140
+ downloaded_at = model.get("downloaded_at", "Unknown")
141
+ if downloaded_at != "Unknown":
142
+ try:
143
+ import datetime
144
+ dt = datetime.datetime.fromisoformat(downloaded_at)
145
+ downloaded_at = dt.strftime("%Y-%m-%d %H:%M")
146
+ except Exception:
147
+ pass
148
+
101
149
  table.add_row(
102
150
  model["name"],
103
151
  model.get("repo_id", "Unknown"),
104
152
  model.get("filename", "Unknown"),
153
+ file_size,
154
+ downloaded_at,
105
155
  )
106
156
 
107
157
  console.print(table)
@@ -181,6 +231,16 @@ def chat(
181
231
  console.print(f"[bold red]Error downloading model: {str(e)}[/bold red]")
182
232
  return
183
233
 
234
+ # Check RAM requirements
235
+ ram_requirement = "Unknown"
236
+ for size, ram in RAM_REQUIREMENTS.items():
237
+ if size in model_name:
238
+ ram_requirement = ram
239
+ break
240
+
241
+ if ram_requirement != "Unknown":
242
+ console.print(f"[yellow]This model requires approximately {ram_requirement} of RAM[/yellow]")
243
+
184
244
  # Load the model
185
245
  try:
186
246
  llm = LLMInterface(model_name)
@@ -325,6 +385,124 @@ def chat(
325
385
  # Add extra spacing after the response
326
386
  console.print("")
327
387
 
388
+ @app.command("copy")
389
+ def copy_model(
390
+ source: str = typer.Argument(..., help="Name of the source model"),
391
+ destination: str = typer.Argument(..., help="Name for the destination model"),
392
+ ) -> None:
393
+ """
394
+ Copy a model to a new name.
395
+ """
396
+ try:
397
+ if model_manager.copy_model(source, destination):
398
+ console.print(f"[bold green]Model {source} copied to {destination} successfully[/bold green]")
399
+ else:
400
+ console.print(f"[bold red]Failed to copy model {source} to {destination}[/bold red]")
401
+ except Exception as e:
402
+ console.print(f"[bold red]Error copying model: {str(e)}[/bold red]")
403
+
404
+ @app.command("show")
405
+ def show_model(
406
+ model_name: str = typer.Argument(..., help="Name of the model to show information for"),
407
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed information"),
408
+ ) -> None:
409
+ """
410
+ Show detailed information about a model.
411
+ """
412
+ model_info = model_manager.get_model_info(model_name)
413
+
414
+ if not model_info:
415
+ console.print(f"[yellow]Model {model_name} not found.[/yellow]")
416
+ return
417
+
418
+ # Create a table for basic information
419
+ table = Table(title=f"Model Information: {model_name}")
420
+ table.add_column("Property", style="cyan")
421
+ table.add_column("Value", style="green")
422
+
423
+ # Add basic properties
424
+ table.add_row("Name", model_info["name"])
425
+ table.add_row("Repository", model_info.get("repo_id", "Unknown"))
426
+ table.add_row("Filename", model_info.get("filename", "Unknown"))
427
+
428
+ # Get file size in human-readable format
429
+ file_path = model_info.get("path")
430
+ if file_path:
431
+ try:
432
+ import os
433
+ size_bytes = os.path.getsize(file_path)
434
+ # Convert to human-readable format
435
+ for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
436
+ if size_bytes < 1024.0 or unit == 'TB':
437
+ file_size = f"{size_bytes:.2f} {unit}"
438
+ break
439
+ size_bytes /= 1024.0
440
+ table.add_row("Size", file_size)
441
+ except Exception:
442
+ table.add_row("Size", "Unknown")
443
+
444
+ # Format downloaded date
445
+ downloaded_at = model_info.get("downloaded_at", "Unknown")
446
+ if downloaded_at != "Unknown":
447
+ try:
448
+ import datetime
449
+ dt = datetime.datetime.fromisoformat(downloaded_at)
450
+ downloaded_at = dt.strftime("%Y-%m-%d %H:%M")
451
+ except Exception:
452
+ pass
453
+ table.add_row("Downloaded", downloaded_at)
454
+
455
+ # Add copied information if available
456
+ if "copied_from" in model_info:
457
+ table.add_row("Copied From", model_info["copied_from"])
458
+ copied_at = model_info.get("copied_at", "Unknown")
459
+ if copied_at != "Unknown":
460
+ try:
461
+ import datetime
462
+ dt = datetime.datetime.fromisoformat(copied_at)
463
+ copied_at = dt.strftime("%Y-%m-%d %H:%M")
464
+ except Exception:
465
+ pass
466
+ table.add_row("Copied At", copied_at)
467
+
468
+ # Estimate RAM requirements based on model name
469
+ ram_requirement = "Unknown"
470
+ for size, ram in RAM_REQUIREMENTS.items():
471
+ if size in model_name:
472
+ ram_requirement = ram
473
+ break
474
+ table.add_row("Estimated RAM", ram_requirement)
475
+
476
+ # Print the table
477
+ console.print(table)
478
+
479
+ # If verbose, show all properties
480
+ if verbose:
481
+ console.print("\n[bold]Detailed Information:[/bold]")
482
+ for key, value in model_info.items():
483
+ if key not in ["name", "repo_id", "filename", "path", "downloaded_at", "copied_from", "copied_at"]:
484
+ console.print(f"[cyan]{key}:[/cyan] {value}")
485
+
486
+ @app.command("ps")
487
+ def list_running_models() -> None:
488
+ """
489
+ List running models.
490
+ """
491
+ from .server import loaded_models
492
+
493
+ if not loaded_models:
494
+ console.print("[yellow]No models currently running.[/yellow]")
495
+ return
496
+
497
+ table = Table(title="Running Models")
498
+ table.add_column("Name", style="cyan")
499
+ table.add_column("Status", style="green")
500
+
501
+ for name in loaded_models.keys():
502
+ table.add_row(name, "Running")
503
+
504
+ console.print(table)
505
+
328
506
  @app.command("version")
329
507
  def version() -> None:
330
508
  """