webscout 8.2.6__py3-none-any.whl → 8.2.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of webscout might be problematic. Click here for more details.

Files changed (292) hide show
  1. webscout/AIutel.py +97 -87
  2. webscout/version.py +1 -1
  3. {webscout-8.2.6.dist-info → webscout-8.2.7.dist-info}/METADATA +2 -15
  4. webscout-8.2.7.dist-info/RECORD +26 -0
  5. {webscout-8.2.6.dist-info → webscout-8.2.7.dist-info}/WHEEL +1 -1
  6. webscout-8.2.7.dist-info/entry_points.txt +3 -0
  7. webscout-8.2.7.dist-info/top_level.txt +1 -0
  8. webscout/Extra/GitToolkit/__init__.py +0 -10
  9. webscout/Extra/GitToolkit/gitapi/__init__.py +0 -12
  10. webscout/Extra/GitToolkit/gitapi/repository.py +0 -195
  11. webscout/Extra/GitToolkit/gitapi/user.py +0 -96
  12. webscout/Extra/GitToolkit/gitapi/utils.py +0 -62
  13. webscout/Extra/YTToolkit/YTdownloader.py +0 -957
  14. webscout/Extra/YTToolkit/__init__.py +0 -3
  15. webscout/Extra/YTToolkit/transcriber.py +0 -476
  16. webscout/Extra/YTToolkit/ytapi/__init__.py +0 -6
  17. webscout/Extra/YTToolkit/ytapi/channel.py +0 -307
  18. webscout/Extra/YTToolkit/ytapi/errors.py +0 -13
  19. webscout/Extra/YTToolkit/ytapi/extras.py +0 -45
  20. webscout/Extra/YTToolkit/ytapi/https.py +0 -88
  21. webscout/Extra/YTToolkit/ytapi/patterns.py +0 -61
  22. webscout/Extra/YTToolkit/ytapi/playlist.py +0 -59
  23. webscout/Extra/YTToolkit/ytapi/pool.py +0 -8
  24. webscout/Extra/YTToolkit/ytapi/query.py +0 -40
  25. webscout/Extra/YTToolkit/ytapi/stream.py +0 -63
  26. webscout/Extra/YTToolkit/ytapi/utils.py +0 -62
  27. webscout/Extra/YTToolkit/ytapi/video.py +0 -232
  28. webscout/Extra/__init__.py +0 -7
  29. webscout/Extra/autocoder/__init__.py +0 -9
  30. webscout/Extra/autocoder/autocoder.py +0 -910
  31. webscout/Extra/autocoder/autocoder_utiles.py +0 -332
  32. webscout/Extra/gguf.py +0 -684
  33. webscout/Extra/tempmail/__init__.py +0 -28
  34. webscout/Extra/tempmail/async_utils.py +0 -141
  35. webscout/Extra/tempmail/base.py +0 -161
  36. webscout/Extra/tempmail/cli.py +0 -187
  37. webscout/Extra/tempmail/emailnator.py +0 -84
  38. webscout/Extra/tempmail/mail_tm.py +0 -361
  39. webscout/Extra/tempmail/temp_mail_io.py +0 -292
  40. webscout/Extra/weather.py +0 -194
  41. webscout/Extra/weather_ascii.py +0 -76
  42. webscout/Litlogger/__init__.py +0 -67
  43. webscout/Litlogger/core/__init__.py +0 -6
  44. webscout/Litlogger/core/level.py +0 -23
  45. webscout/Litlogger/core/logger.py +0 -165
  46. webscout/Litlogger/handlers/__init__.py +0 -12
  47. webscout/Litlogger/handlers/console.py +0 -33
  48. webscout/Litlogger/handlers/file.py +0 -143
  49. webscout/Litlogger/handlers/network.py +0 -173
  50. webscout/Litlogger/styles/__init__.py +0 -7
  51. webscout/Litlogger/styles/colors.py +0 -249
  52. webscout/Litlogger/styles/formats.py +0 -458
  53. webscout/Litlogger/styles/text.py +0 -87
  54. webscout/Litlogger/utils/__init__.py +0 -6
  55. webscout/Litlogger/utils/detectors.py +0 -153
  56. webscout/Litlogger/utils/formatters.py +0 -200
  57. webscout/Provider/AI21.py +0 -177
  58. webscout/Provider/AISEARCH/DeepFind.py +0 -250
  59. webscout/Provider/AISEARCH/ISou.py +0 -256
  60. webscout/Provider/AISEARCH/Perplexity.py +0 -359
  61. webscout/Provider/AISEARCH/__init__.py +0 -10
  62. webscout/Provider/AISEARCH/felo_search.py +0 -228
  63. webscout/Provider/AISEARCH/genspark_search.py +0 -208
  64. webscout/Provider/AISEARCH/hika_search.py +0 -198
  65. webscout/Provider/AISEARCH/iask_search.py +0 -436
  66. webscout/Provider/AISEARCH/monica_search.py +0 -246
  67. webscout/Provider/AISEARCH/scira_search.py +0 -322
  68. webscout/Provider/AISEARCH/webpilotai_search.py +0 -281
  69. webscout/Provider/Aitopia.py +0 -316
  70. webscout/Provider/AllenAI.py +0 -447
  71. webscout/Provider/Andi.py +0 -228
  72. webscout/Provider/Blackboxai.py +0 -229
  73. webscout/Provider/ChatGPTClone.py +0 -237
  74. webscout/Provider/ChatGPTGratis.py +0 -194
  75. webscout/Provider/ChatSandbox.py +0 -342
  76. webscout/Provider/Cloudflare.py +0 -325
  77. webscout/Provider/Cohere.py +0 -208
  78. webscout/Provider/Deepinfra.py +0 -338
  79. webscout/Provider/ElectronHub.py +0 -773
  80. webscout/Provider/ExaAI.py +0 -261
  81. webscout/Provider/ExaChat.py +0 -358
  82. webscout/Provider/Free2GPT.py +0 -241
  83. webscout/Provider/GPTWeb.py +0 -249
  84. webscout/Provider/Gemini.py +0 -169
  85. webscout/Provider/GithubChat.py +0 -370
  86. webscout/Provider/GizAI.py +0 -285
  87. webscout/Provider/Glider.py +0 -222
  88. webscout/Provider/Groq.py +0 -801
  89. webscout/Provider/HF_space/__init__.py +0 -0
  90. webscout/Provider/HF_space/qwen_qwen2.py +0 -206
  91. webscout/Provider/HeckAI.py +0 -257
  92. webscout/Provider/HuggingFaceChat.py +0 -469
  93. webscout/Provider/Hunyuan.py +0 -283
  94. webscout/Provider/Jadve.py +0 -291
  95. webscout/Provider/Koboldai.py +0 -381
  96. webscout/Provider/LambdaChat.py +0 -411
  97. webscout/Provider/Llama3.py +0 -259
  98. webscout/Provider/MCPCore.py +0 -315
  99. webscout/Provider/Marcus.py +0 -206
  100. webscout/Provider/Nemotron.py +0 -218
  101. webscout/Provider/Netwrck.py +0 -270
  102. webscout/Provider/OLLAMA.py +0 -396
  103. webscout/Provider/OPENAI/__init__.py +0 -28
  104. webscout/Provider/OPENAI/ai4chat.py +0 -286
  105. webscout/Provider/OPENAI/base.py +0 -46
  106. webscout/Provider/OPENAI/c4ai.py +0 -367
  107. webscout/Provider/OPENAI/chatgpt.py +0 -549
  108. webscout/Provider/OPENAI/chatgptclone.py +0 -481
  109. webscout/Provider/OPENAI/deepinfra.py +0 -309
  110. webscout/Provider/OPENAI/e2b.py +0 -1350
  111. webscout/Provider/OPENAI/exaai.py +0 -404
  112. webscout/Provider/OPENAI/exachat.py +0 -437
  113. webscout/Provider/OPENAI/freeaichat.py +0 -352
  114. webscout/Provider/OPENAI/glider.py +0 -316
  115. webscout/Provider/OPENAI/groq.py +0 -354
  116. webscout/Provider/OPENAI/heckai.py +0 -341
  117. webscout/Provider/OPENAI/llmchatco.py +0 -327
  118. webscout/Provider/OPENAI/mcpcore.py +0 -376
  119. webscout/Provider/OPENAI/multichat.py +0 -368
  120. webscout/Provider/OPENAI/netwrck.py +0 -350
  121. webscout/Provider/OPENAI/opkfc.py +0 -488
  122. webscout/Provider/OPENAI/scirachat.py +0 -462
  123. webscout/Provider/OPENAI/sonus.py +0 -294
  124. webscout/Provider/OPENAI/standardinput.py +0 -425
  125. webscout/Provider/OPENAI/textpollinations.py +0 -329
  126. webscout/Provider/OPENAI/toolbaz.py +0 -406
  127. webscout/Provider/OPENAI/typegpt.py +0 -346
  128. webscout/Provider/OPENAI/uncovrAI.py +0 -455
  129. webscout/Provider/OPENAI/utils.py +0 -211
  130. webscout/Provider/OPENAI/venice.py +0 -413
  131. webscout/Provider/OPENAI/wisecat.py +0 -381
  132. webscout/Provider/OPENAI/writecream.py +0 -156
  133. webscout/Provider/OPENAI/x0gpt.py +0 -371
  134. webscout/Provider/OPENAI/yep.py +0 -327
  135. webscout/Provider/OpenGPT.py +0 -209
  136. webscout/Provider/Openai.py +0 -496
  137. webscout/Provider/PI.py +0 -429
  138. webscout/Provider/Perplexitylabs.py +0 -415
  139. webscout/Provider/QwenLM.py +0 -254
  140. webscout/Provider/Reka.py +0 -214
  141. webscout/Provider/StandardInput.py +0 -290
  142. webscout/Provider/TTI/AiForce/__init__.py +0 -22
  143. webscout/Provider/TTI/AiForce/async_aiforce.py +0 -224
  144. webscout/Provider/TTI/AiForce/sync_aiforce.py +0 -245
  145. webscout/Provider/TTI/FreeAIPlayground/__init__.py +0 -9
  146. webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +0 -181
  147. webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +0 -180
  148. webscout/Provider/TTI/ImgSys/__init__.py +0 -23
  149. webscout/Provider/TTI/ImgSys/async_imgsys.py +0 -202
  150. webscout/Provider/TTI/ImgSys/sync_imgsys.py +0 -195
  151. webscout/Provider/TTI/MagicStudio/__init__.py +0 -2
  152. webscout/Provider/TTI/MagicStudio/async_magicstudio.py +0 -111
  153. webscout/Provider/TTI/MagicStudio/sync_magicstudio.py +0 -109
  154. webscout/Provider/TTI/Nexra/__init__.py +0 -22
  155. webscout/Provider/TTI/Nexra/async_nexra.py +0 -286
  156. webscout/Provider/TTI/Nexra/sync_nexra.py +0 -258
  157. webscout/Provider/TTI/PollinationsAI/__init__.py +0 -23
  158. webscout/Provider/TTI/PollinationsAI/async_pollinations.py +0 -311
  159. webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +0 -265
  160. webscout/Provider/TTI/__init__.py +0 -12
  161. webscout/Provider/TTI/aiarta/__init__.py +0 -2
  162. webscout/Provider/TTI/aiarta/async_aiarta.py +0 -482
  163. webscout/Provider/TTI/aiarta/sync_aiarta.py +0 -440
  164. webscout/Provider/TTI/artbit/__init__.py +0 -22
  165. webscout/Provider/TTI/artbit/async_artbit.py +0 -155
  166. webscout/Provider/TTI/artbit/sync_artbit.py +0 -148
  167. webscout/Provider/TTI/fastflux/__init__.py +0 -22
  168. webscout/Provider/TTI/fastflux/async_fastflux.py +0 -261
  169. webscout/Provider/TTI/fastflux/sync_fastflux.py +0 -252
  170. webscout/Provider/TTI/huggingface/__init__.py +0 -22
  171. webscout/Provider/TTI/huggingface/async_huggingface.py +0 -199
  172. webscout/Provider/TTI/huggingface/sync_huggingface.py +0 -195
  173. webscout/Provider/TTI/piclumen/__init__.py +0 -23
  174. webscout/Provider/TTI/piclumen/async_piclumen.py +0 -268
  175. webscout/Provider/TTI/piclumen/sync_piclumen.py +0 -233
  176. webscout/Provider/TTI/pixelmuse/__init__.py +0 -4
  177. webscout/Provider/TTI/pixelmuse/async_pixelmuse.py +0 -249
  178. webscout/Provider/TTI/pixelmuse/sync_pixelmuse.py +0 -182
  179. webscout/Provider/TTI/talkai/__init__.py +0 -4
  180. webscout/Provider/TTI/talkai/async_talkai.py +0 -229
  181. webscout/Provider/TTI/talkai/sync_talkai.py +0 -207
  182. webscout/Provider/TTS/__init__.py +0 -8
  183. webscout/Provider/TTS/base.py +0 -159
  184. webscout/Provider/TTS/deepgram.py +0 -156
  185. webscout/Provider/TTS/elevenlabs.py +0 -111
  186. webscout/Provider/TTS/gesserit.py +0 -128
  187. webscout/Provider/TTS/murfai.py +0 -113
  188. webscout/Provider/TTS/parler.py +0 -111
  189. webscout/Provider/TTS/speechma.py +0 -180
  190. webscout/Provider/TTS/streamElements.py +0 -333
  191. webscout/Provider/TTS/utils.py +0 -280
  192. webscout/Provider/TeachAnything.py +0 -233
  193. webscout/Provider/TextPollinationsAI.py +0 -306
  194. webscout/Provider/TwoAI.py +0 -280
  195. webscout/Provider/TypliAI.py +0 -305
  196. webscout/Provider/Venice.py +0 -258
  197. webscout/Provider/VercelAI.py +0 -253
  198. webscout/Provider/WiseCat.py +0 -233
  199. webscout/Provider/WrDoChat.py +0 -370
  200. webscout/Provider/Writecream.py +0 -237
  201. webscout/Provider/WritingMate.py +0 -269
  202. webscout/Provider/Youchat.py +0 -330
  203. webscout/Provider/__init__.py +0 -178
  204. webscout/Provider/ai4chat.py +0 -203
  205. webscout/Provider/aimathgpt.py +0 -189
  206. webscout/Provider/akashgpt.py +0 -335
  207. webscout/Provider/asksteve.py +0 -212
  208. webscout/Provider/bagoodex.py +0 -145
  209. webscout/Provider/cerebras.py +0 -288
  210. webscout/Provider/chatglm.py +0 -215
  211. webscout/Provider/cleeai.py +0 -213
  212. webscout/Provider/copilot.py +0 -425
  213. webscout/Provider/elmo.py +0 -283
  214. webscout/Provider/freeaichat.py +0 -285
  215. webscout/Provider/geminiapi.py +0 -208
  216. webscout/Provider/geminiprorealtime.py +0 -160
  217. webscout/Provider/granite.py +0 -235
  218. webscout/Provider/hermes.py +0 -266
  219. webscout/Provider/julius.py +0 -223
  220. webscout/Provider/koala.py +0 -268
  221. webscout/Provider/learnfastai.py +0 -325
  222. webscout/Provider/llama3mitril.py +0 -215
  223. webscout/Provider/llmchat.py +0 -255
  224. webscout/Provider/llmchatco.py +0 -306
  225. webscout/Provider/meta.py +0 -798
  226. webscout/Provider/multichat.py +0 -364
  227. webscout/Provider/scira_chat.py +0 -297
  228. webscout/Provider/scnet.py +0 -243
  229. webscout/Provider/searchchat.py +0 -292
  230. webscout/Provider/sonus.py +0 -258
  231. webscout/Provider/talkai.py +0 -194
  232. webscout/Provider/toolbaz.py +0 -353
  233. webscout/Provider/turboseek.py +0 -266
  234. webscout/Provider/typefully.py +0 -330
  235. webscout/Provider/typegpt.py +0 -289
  236. webscout/Provider/uncovr.py +0 -368
  237. webscout/Provider/x0gpt.py +0 -299
  238. webscout/Provider/yep.py +0 -389
  239. webscout/litagent/__init__.py +0 -29
  240. webscout/litagent/agent.py +0 -455
  241. webscout/litagent/constants.py +0 -60
  242. webscout/litprinter/__init__.py +0 -59
  243. webscout/scout/__init__.py +0 -8
  244. webscout/scout/core/__init__.py +0 -7
  245. webscout/scout/core/crawler.py +0 -140
  246. webscout/scout/core/scout.py +0 -568
  247. webscout/scout/core/search_result.py +0 -96
  248. webscout/scout/core/text_analyzer.py +0 -63
  249. webscout/scout/core/text_utils.py +0 -277
  250. webscout/scout/core/web_analyzer.py +0 -52
  251. webscout/scout/core.py +0 -881
  252. webscout/scout/element.py +0 -460
  253. webscout/scout/parsers/__init__.py +0 -69
  254. webscout/scout/parsers/html5lib_parser.py +0 -172
  255. webscout/scout/parsers/html_parser.py +0 -236
  256. webscout/scout/parsers/lxml_parser.py +0 -178
  257. webscout/scout/utils.py +0 -37
  258. webscout/swiftcli/__init__.py +0 -95
  259. webscout/swiftcli/core/__init__.py +0 -7
  260. webscout/swiftcli/core/cli.py +0 -297
  261. webscout/swiftcli/core/context.py +0 -104
  262. webscout/swiftcli/core/group.py +0 -241
  263. webscout/swiftcli/decorators/__init__.py +0 -28
  264. webscout/swiftcli/decorators/command.py +0 -221
  265. webscout/swiftcli/decorators/options.py +0 -220
  266. webscout/swiftcli/decorators/output.py +0 -252
  267. webscout/swiftcli/exceptions.py +0 -21
  268. webscout/swiftcli/plugins/__init__.py +0 -9
  269. webscout/swiftcli/plugins/base.py +0 -135
  270. webscout/swiftcli/plugins/manager.py +0 -262
  271. webscout/swiftcli/utils/__init__.py +0 -59
  272. webscout/swiftcli/utils/formatting.py +0 -252
  273. webscout/swiftcli/utils/parsing.py +0 -267
  274. webscout/zeroart/__init__.py +0 -55
  275. webscout/zeroart/base.py +0 -60
  276. webscout/zeroart/effects.py +0 -99
  277. webscout/zeroart/fonts.py +0 -816
  278. webscout-8.2.6.dist-info/RECORD +0 -307
  279. webscout-8.2.6.dist-info/entry_points.txt +0 -3
  280. webscout-8.2.6.dist-info/top_level.txt +0 -2
  281. webstoken/__init__.py +0 -30
  282. webstoken/classifier.py +0 -189
  283. webstoken/keywords.py +0 -216
  284. webstoken/language.py +0 -128
  285. webstoken/ner.py +0 -164
  286. webstoken/normalizer.py +0 -35
  287. webstoken/processor.py +0 -77
  288. webstoken/sentiment.py +0 -206
  289. webstoken/stemmer.py +0 -73
  290. webstoken/tagger.py +0 -60
  291. webstoken/tokenizer.py +0 -158
  292. {webscout-8.2.6.dist-info → webscout-8.2.7.dist-info}/licenses/LICENSE.md +0 -0
@@ -1,910 +0,0 @@
1
- """RawDog module for generating and auto-executing Python scripts in the CLI."""
2
-
3
- import os
4
- import re
5
- import sys
6
- import queue
7
- import tempfile
8
- import threading
9
- import subprocess
10
- from typing import Optional, Generator, List, Tuple, Dict, Any, NamedTuple
11
- from rich.panel import Panel
12
- from rich.syntax import Syntax
13
- from rich.console import Console
14
- from rich.markdown import Markdown
15
- from rich.table import Table
16
- from rich.theme import Theme
17
- from rich.live import Live
18
- from rich.box import ROUNDED
19
- from .autocoder_utiles import get_intro_prompt
20
- # Initialize LitLogger with custom format and colors
21
- default_path = tempfile.mkdtemp(prefix="webscout_autocoder")
22
-
23
- # Custom theme for consistent styling
24
- CUSTOM_THEME = Theme({
25
- "info": "cyan",
26
- "warning": "yellow",
27
- "error": "red bold",
28
- "success": "green",
29
- "code": "blue",
30
- "output": "white",
31
- })
32
-
33
- console = Console(theme=CUSTOM_THEME)
34
- class CommandResult(NamedTuple):
35
- """Result of a system command execution."""
36
- success: bool
37
- stdout: str
38
- stderr: str
39
-
40
- def run_system_command(
41
- command: str,
42
- exit_on_error: bool = False,
43
- stdout_error: bool = False,
44
- help: Optional[str] = None
45
- ) -> Tuple[bool, CommandResult]:
46
- """Execute a system command and return the result.
47
-
48
- Args:
49
- command (str): Command to execute
50
- exit_on_error (bool): Whether to exit on error. Defaults to False.
51
- stdout_error (bool): Whether to include stdout in error messages. Defaults to False.
52
- help (str, optional): Help message for errors. Defaults to None.
53
-
54
- Returns:
55
- Tuple[bool, CommandResult]: Success status and command result containing stdout/stderr
56
- """
57
- try:
58
- # Execute command and capture output
59
- process = subprocess.Popen(
60
- command,
61
- stdout=subprocess.PIPE,
62
- stderr=subprocess.PIPE,
63
- shell=True,
64
- text=True
65
- )
66
-
67
- # Get stdout and stderr
68
- stdout, stderr = process.communicate()
69
- success = process.returncode == 0
70
-
71
- # Create result object
72
- result = CommandResult(
73
- success=success,
74
- stdout=stdout.strip() if stdout else "",
75
- stderr=stderr.strip() if stderr else ""
76
- )
77
-
78
- # Handle errors if needed
79
- if not success and exit_on_error:
80
- error_msg = stderr if stderr else stdout if stdout_error else "Command failed"
81
- if help:
82
- error_msg += f"\n{help}"
83
- sys.exit(error_msg)
84
-
85
- return success, result
86
-
87
- except Exception as e:
88
- # Handle execution errors
89
- error_msg = str(e)
90
- if help:
91
- error_msg += f"\n{help}"
92
-
93
- if exit_on_error:
94
- sys.exit(error_msg)
95
-
96
- return False, CommandResult(success=False, stdout="", stderr=error_msg)
97
-
98
-
99
- class AutoCoder:
100
- """Generate and auto-execute Python scripts in the CLI with advanced error handling and retry logic.
101
-
102
- This class provides:
103
- - Automatic code generation
104
- - Script execution with safety checks
105
- - Advanced error handling and retries
106
- - Beautiful logging with rich console
107
- - Execution result capture and display
108
-
109
- Examples:
110
- >>> coder = AutoCoder()
111
- >>> coder.execute("Get system info")
112
- Generating system info script...
113
- Script executed successfully!
114
- """
115
-
116
- def __init__(
117
- self,
118
- quiet: bool = False,
119
- internal_exec: bool = False,
120
- confirm_script: bool = False,
121
- interpreter: str = "python",
122
- prettify: bool = True,
123
- path_to_script: str = "",
124
- max_retries: int = 3,
125
- ai_instance = None
126
- ):
127
- """Initialize AutoCoder instance.
128
-
129
- Args:
130
- quiet (bool): Flag to control logging. Defaults to False.
131
- internal_exec (bool): Execute scripts with exec function. Defaults to False.
132
- confirm_script (bool): Give consent to scripts prior to execution. Defaults to False.
133
- interpreter (str): Python's interpreter name. Defaults to "python".
134
- prettify (bool): Prettify the code on stdout. Defaults to True.
135
- path_to_script (str): Path to save generated scripts. Defaults to "".
136
- max_retries (int): Maximum number of retry attempts. Defaults to 3.
137
- ai_instance: AI instance for error correction. Defaults to None.
138
- """
139
- self.internal_exec = internal_exec
140
- self.confirm_script = confirm_script
141
- self.quiet = quiet
142
- self.interpreter = interpreter
143
- self.prettify = prettify
144
- self.path_to_script = path_to_script or os.path.join(default_path, "execute_this.py")
145
- self.max_retries = max_retries
146
- self.tried_solutions = set()
147
- self.ai_instance = ai_instance
148
- self.last_execution_result = ""
149
-
150
- # Get Python version with enhanced logging
151
- if self.internal_exec:
152
- self.python_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
153
- else:
154
- version_output = run_system_command(
155
- f"{self.interpreter} --version",
156
- exit_on_error=True,
157
- stdout_error=True,
158
- help="If you're using Webscout-cli, use the flag '--internal-exec'"
159
- )[1].stdout
160
- self.python_version = version_output.split(" ")[1]
161
-
162
-
163
-
164
- def _extract_code_blocks(self, response: str) -> List[Tuple[str, str]]:
165
- """Extract code blocks from a response string.
166
-
167
- Args:
168
- response (str): Response string containing code blocks
169
-
170
- Returns:
171
- List[Tuple[str, str]]: List of (code_type, code) tuples
172
- """
173
- blocks = []
174
-
175
- # First try to find code blocks with explicit language tags
176
- pattern = r"```(\w+)\n(.*?)```"
177
- matches = re.finditer(pattern, response, re.DOTALL)
178
-
179
- for match in matches:
180
- code_type = match.group(1).lower()
181
- code = match.group(2).strip()
182
- blocks.append((code_type, code))
183
-
184
- # If no explicit code blocks found with language tags, try generic code blocks
185
- if not blocks:
186
- pattern = r"```(.*?)```"
187
- matches = re.finditer(pattern, response, re.DOTALL)
188
- for match in matches:
189
- code = match.group(1).strip()
190
- blocks.append(('python', code))
191
-
192
- # If still no code blocks found, treat as raw Python code
193
- if not blocks:
194
- lines = [line.strip() for line in response.split('\n') if line.strip()]
195
- if lines:
196
- blocks.append(('python', '\n'.join(lines)))
197
-
198
- return blocks
199
-
200
- def _execute_code_block(self, code_type: str, code: str, ai_instance=None) -> Tuple[bool, str]:
201
- """Execute a code block.
202
-
203
- Args:
204
- code_type (str): Type of code block ('python')
205
- code (str): Code to execute
206
- ai_instance: Optional AI instance for error correction
207
-
208
- Returns:
209
- Tuple[bool, str]: (Success status, Error message or execution result)
210
- """
211
- try:
212
- result = self._execute_with_retry(code, ai_instance)
213
- if result is None:
214
- return True, self.last_execution_result
215
- return False, result
216
- except Exception as e:
217
- return False, str(e)
218
-
219
- def _format_output_panel(self, code: str, output_lines: list) -> Panel:
220
- """Format code and output into a single panel.
221
-
222
- Args:
223
- code (str): The code that was executed
224
- output_lines (list): List of output lines
225
-
226
- Returns:
227
- Panel: Formatted panel with code and output
228
- """
229
- # Format output
230
- output_text = "\n".join(output_lines) if output_lines else "Running..."
231
-
232
- # Create panel with Jupyter-like styling
233
- panel = Panel(
234
- output_text,
235
- title="[bold red]Out [1]:[/bold red]",
236
- border_style="red",
237
- expand=True,
238
- padding=(0, 1),
239
- box=ROUNDED
240
- )
241
-
242
- return panel
243
-
244
- def _format_result_panel(self, output: str) -> Panel:
245
- """Format execution result into a panel.
246
-
247
- Args:
248
- output (str): Execution output text
249
-
250
- Returns:
251
- Panel: Formatted panel with execution result
252
- """
253
- # Create panel with Jupyter-like styling
254
- panel = Panel(
255
- output,
256
- title="[bold red]Out [1]:[/bold red]",
257
- border_style="red",
258
- expand=True,
259
- padding=(0, 1),
260
- box=ROUNDED
261
- )
262
-
263
- return panel
264
-
265
- def _stream_output(self, process: subprocess.Popen) -> Generator[str, None, None]:
266
- """Stream output from a subprocess in realtime.
267
-
268
- Args:
269
- process: Subprocess to stream output from
270
-
271
- Yields:
272
- str: Lines of output
273
- """
274
- # Stream stdout
275
- output_lines = []
276
- for line in process.stdout:
277
- decoded_line = line.decode('utf-8').strip() if isinstance(line, bytes) else line.strip()
278
- if decoded_line:
279
- output_lines.append(decoded_line)
280
- yield decoded_line
281
-
282
- # Check stderr
283
- error = process.stderr.read() if process.stderr else None
284
- if error:
285
- error_str = error.decode('utf-8').strip() if isinstance(error, bytes) else error.strip()
286
- if error_str:
287
- yield f"Error: {error_str}"
288
- output_lines.append(f"Error: {error_str}")
289
-
290
- # Store the full execution result
291
- self.last_execution_result = "\n".join(output_lines)
292
-
293
- def _execute_with_retry(self, code: str, ai_instance=None) -> Optional[str]:
294
- """Execute code with retry logic and error correction.
295
-
296
- Args:
297
- code (str): Code to execute
298
- ai_instance: Optional AI instance for error correction
299
-
300
- Returns:
301
- Optional[str]: Error message if execution failed, None if successful
302
- """
303
- last_error = None
304
- retries = 0
305
-
306
- # Add the solution to tried solutions
307
- self.tried_solutions.add(code)
308
-
309
- # Print the code first
310
- if self.prettify:
311
- syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
312
- console.print(Panel(
313
- syntax,
314
- title="[bold blue]In [1]:[/bold blue]",
315
- border_style="blue",
316
- expand=True,
317
- box=ROUNDED
318
- ))
319
-
320
- while retries < self.max_retries:
321
- try:
322
- if self.path_to_script:
323
- script_dir = os.path.dirname(self.path_to_script)
324
- if script_dir:
325
- os.makedirs(script_dir, exist_ok=True)
326
- with open(self.path_to_script, "w", encoding="utf-8") as f:
327
- f.write(code)
328
-
329
- if self.internal_exec:
330
- # Create StringIO for output capture
331
- import io
332
- import sys
333
- stdout = io.StringIO()
334
- stderr = io.StringIO()
335
-
336
- # Create a queue for realtime output
337
- output_queue = queue.Queue()
338
- output_lines = []
339
-
340
- def execute_code():
341
- try:
342
- # Create a local namespace
343
- local_namespace: Dict[str, Any] = {}
344
-
345
- # Redirect stdout/stderr
346
- sys.stdout = stdout
347
- sys.stderr = stderr
348
-
349
- # Execute the code
350
- exec(code, globals(), local_namespace)
351
-
352
- # Get any output
353
- output = stdout.getvalue()
354
- error = stderr.getvalue()
355
-
356
- if error:
357
- output_queue.put(("error", error))
358
- if output:
359
- output_queue.put(("output", output))
360
-
361
- except Exception as e:
362
- output_queue.put(("error", str(e)))
363
- finally:
364
- # Restore stdout/stderr
365
- sys.stdout = sys.__stdout__
366
- sys.stderr = sys.__stderr__
367
-
368
- # Create and start execution thread
369
- thread = threading.Thread(target=execute_code)
370
- thread.daemon = True # Make thread daemon to avoid hanging
371
- thread.start()
372
-
373
- # Display output in realtime
374
- with Live(auto_refresh=True) as live:
375
- timeout_counter = 0
376
- while thread.is_alive() or not output_queue.empty():
377
- try:
378
- msg_type, content = output_queue.get(timeout=0.1)
379
- if content:
380
- new_lines = content.splitlines()
381
- output_lines.extend(new_lines)
382
- live.update(self._format_output_panel(code, output_lines))
383
- live.refresh()
384
- output_queue.task_done()
385
- except queue.Empty:
386
- timeout_counter += 1
387
- # Refresh the display to show it's still running
388
- if timeout_counter % 10 == 0: # Refresh every ~1 second
389
- live.update(self._format_output_panel(code, output_lines))
390
- live.refresh()
391
- if timeout_counter > 100 and thread.is_alive(): # ~10 seconds
392
- output_lines.append("Warning: Execution taking longer than expected...")
393
- live.update(self._format_output_panel(code, output_lines))
394
- live.refresh()
395
- continue
396
-
397
- # Wait for thread to complete with timeout
398
- thread.join(timeout=30) # 30 second timeout
399
- if thread.is_alive():
400
- output_lines.append("Error: Execution timed out after 30 seconds")
401
- raise TimeoutError("Execution timed out after 30 seconds")
402
-
403
- # Check for any final errors
404
- error = stderr.getvalue()
405
- if error:
406
- raise Exception(error)
407
-
408
- # Store the full execution result
409
- self.last_execution_result = stdout.getvalue()
410
-
411
- else:
412
- try:
413
- process = subprocess.Popen(
414
- [self.interpreter, self.path_to_script],
415
- stdout=subprocess.PIPE,
416
- stderr=subprocess.PIPE,
417
- text=True, # Use text mode to avoid encoding issues
418
- bufsize=1,
419
- )
420
-
421
- output_lines = []
422
- # Stream output in realtime
423
- with Live(auto_refresh=True) as live:
424
- for line in self._stream_output(process):
425
- output_lines.append(line)
426
- live.update(self._format_output_panel(code, output_lines))
427
- live.refresh()
428
-
429
- process.wait(timeout=30) # 30 second timeout
430
-
431
- if process.returncode != 0:
432
- # Try to read more detailed error information
433
- if process.stderr:
434
- error = process.stderr.read()
435
- error_str = error.strip() if error else ""
436
- if error_str:
437
- raise Exception(error_str)
438
- raise Exception(f"Process exited with code {process.returncode}")
439
-
440
- # Store the full execution result
441
- self.last_execution_result = "\n".join(output_lines)
442
-
443
- except subprocess.TimeoutExpired:
444
- # Handle the case where the process times out
445
- if process:
446
- process.kill()
447
- raise TimeoutError("Execution timed out after 30 seconds")
448
-
449
- return None
450
-
451
- except Exception as e:
452
- last_error = e
453
- if retries < self.max_retries - 1 and ai_instance:
454
- try:
455
- # First try to handle import errors
456
- if isinstance(e, ImportError):
457
- fixed_code = self._handle_import_error(e, code)
458
- if fixed_code:
459
- code = fixed_code
460
- retries += 1
461
- continue
462
-
463
- # Get error context and try to fix the specific error
464
- error_context = self._get_error_context(e, code)
465
- fixed_response = ai_instance.chat(error_context)
466
- fixed_code = self._extract_code_from_response(fixed_response)
467
-
468
- if not fixed_code:
469
- # If no code found, try a more general approach
470
- general_context = f"""
471
- The code failed with error: {str(e)}
472
-
473
- Original Code:
474
- ```python
475
- {code}
476
- ```
477
-
478
- Please provide a complete, corrected version of the code that handles this error. The code should:
479
- 1. Handle any potential encoding issues
480
- 2. Include proper error handling
481
- 3. Use appropriate libraries and imports
482
- 4. Be compatible with the current Python environment
483
- 5. Fix the specific error: {str(e)}
484
-
485
- Provide only the corrected code without any explanation.
486
- """
487
- fixed_response = ai_instance.chat(general_context)
488
- fixed_code = self._extract_code_from_response(fixed_response)
489
-
490
- if not fixed_code:
491
- break
492
-
493
- if self._is_similar_solution(fixed_code):
494
- # If solution is too similar, try a different approach
495
- different_context = f"""
496
- Previous solutions were not successful. The code failed with error: {str(e)}
497
-
498
- Original Code:
499
- ```python
500
- {code}
501
- ```
502
-
503
- Please provide a significantly different approach to solve this problem. Consider:
504
- 1. Using alternative libraries or methods
505
- 2. Implementing a different algorithm
506
- 3. Adding more robust error handling
507
- 4. Using a different encoding or data handling approach
508
- 5. Specifically address the error: {str(e)}
509
-
510
- Provide only the corrected code without any explanation.
511
- """
512
- fixed_response = ai_instance.chat(different_context)
513
- fixed_code = self._extract_code_from_response(fixed_response)
514
-
515
- if self._is_similar_solution(fixed_code):
516
- break
517
-
518
- # Update code and continue with retry
519
- code = fixed_code
520
- self.tried_solutions.add(code)
521
- retries += 1
522
- continue
523
-
524
- except Exception as ai_error:
525
- console.print(f"Error during AI correction: {str(ai_error)}", style="error")
526
- break
527
- break
528
-
529
- return str(last_error) if last_error else "Unknown error occurred"
530
-
531
- def execute(self, prompt: str, ai_instance=None) -> bool:
532
- """Execute the given prompt using the appropriate executor.
533
-
534
- Args:
535
- prompt (str): Prompt to execute
536
- ai_instance: Optional AI instance for error correction
537
-
538
- Returns:
539
- bool: True if execution was successful, False otherwise
540
- """
541
- try:
542
- # Extract code blocks
543
- code_blocks = self._extract_code_blocks(prompt)
544
- if not code_blocks:
545
- console.print("No executable code found in the prompt", style="warning")
546
- return False
547
-
548
- # Execute each code block
549
- overall_success = True
550
- for code_type, code in code_blocks:
551
- success, result = self._execute_code_block(code_type, code, ai_instance)
552
-
553
- if not success:
554
- console.print(f"Execution failed: {result}", style="error")
555
- overall_success = False
556
-
557
- return overall_success
558
-
559
- except Exception as e:
560
- console.print(f"Error in execution: {str(e)}", style="error")
561
- return False
562
-
563
- def _extract_code_from_response(self, response: str) -> str:
564
- """Extract code from AI response.
565
-
566
- Args:
567
- response (str): AI response containing code blocks
568
-
569
- Returns:
570
- str: Extracted code from the first code block
571
- """
572
- if not response:
573
- return ""
574
-
575
- # First try to find code blocks with explicit language tags
576
- code_blocks = self._extract_code_blocks(response)
577
- if code_blocks:
578
- # Return the content of the first code block
579
- return code_blocks[0][1]
580
-
581
- # If no code blocks found, try to find raw Python code
582
- lines = []
583
- in_code = False
584
- for line in response.split('\n'):
585
- line = line.strip()
586
- if not line:
587
- continue
588
-
589
- # Skip markdown headers and other non-code lines
590
- if line.startswith(('#', '```', '---', '===', '>>>')):
591
- continue
592
-
593
- # Skip common non-code lines
594
- if any(line.startswith(prefix) for prefix in ['Please', 'Here', 'The', 'This', 'You']):
595
- continue
596
-
597
- lines.append(line)
598
-
599
- if lines:
600
- return '\n'.join(lines)
601
-
602
- return ""
603
-
604
- def _get_error_context(self, error: Exception, code: str) -> str:
605
- """Create context about the error for AI correction.
606
-
607
- Args:
608
- error (Exception): The caught exception
609
- code (str): The code that caused the error
610
-
611
- Returns:
612
- str: Formatted error context for AI
613
- """
614
- error_type = type(error).__name__
615
- error_msg = str(error)
616
-
617
- # Get Python version and environment info
618
- python_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
619
- platform = sys.platform
620
-
621
- # Get the line number where the error occurred if available
622
- import traceback
623
- tb = traceback.extract_tb(error.__traceback__)
624
- line_info = ""
625
- if tb:
626
- line_info = f"\nError occurred at line {tb[-1].lineno}"
627
-
628
- return f"""
629
- The code failed with error:
630
- Error Type: {error_type}
631
- Error Message: {error_msg}{line_info}
632
-
633
- Environment:
634
- Python Version: {python_version}
635
- Platform: {platform}
636
-
637
- Original Code:
638
- ```python
639
- {code}
640
- ```
641
-
642
- Please fix the code to handle this error. The solution should:
643
- 1. Address the specific error: {error_msg}
644
- 2. Be compatible with Python {python_version}
645
- 3. Work on {platform}
646
- 4. Include proper error handling
647
- 5. Use appropriate libraries and imports
648
-
649
- Provide only the corrected code without any explanation.
650
- """
651
-
652
- def _handle_import_error(self, error: ImportError, code: str) -> Optional[str]:
653
- """Handle missing package errors by attempting to install them.
654
-
655
- Args:
656
- error (ImportError): The import error
657
- code (str): The code that caused the error
658
-
659
- Returns:
660
- Optional[str]: Fixed code or None if installation failed
661
- """
662
- try:
663
- missing_package = str(error).split("'")[1] if "'" in str(error) else str(error).split("No module named")[1].strip()
664
- missing_package = missing_package.replace("'", "").strip()
665
-
666
- console.print(f"Installing missing package: {missing_package}", style="info")
667
- result = subprocess.run(
668
- [sys.executable, "-m", "pip", "install", missing_package],
669
- capture_output=True,
670
- text=True
671
- )
672
- if result.returncode == 0:
673
- console.print(f"Successfully installed {missing_package}", style="success")
674
- return code # Retry with same code after installing package
675
- else:
676
- raise Exception(f"Failed to install {missing_package}: {result.stderr}")
677
- except Exception as e:
678
- console.print(f"Error installing package: {str(e)}", style="error")
679
- return None
680
-
681
- def _is_similar_solution(self, new_code: str, threshold: float = 0.8) -> bool:
682
- """Check if the new solution is too similar to previously tried ones.
683
-
684
- Args:
685
- new_code (str): New solution to check
686
- threshold (float): Similarity threshold (0-1). Defaults to 0.8.
687
-
688
- Returns:
689
- bool: True if solution is too similar to previous attempts
690
- """
691
- import difflib
692
-
693
- def normalize_code(code: str) -> str:
694
- lines = [line.split('#')[0].strip() for line in code.split('\n')]
695
- return '\n'.join(line for line in lines if line)
696
-
697
- new_code_norm = normalize_code(new_code)
698
-
699
- for tried_code in self.tried_solutions:
700
- tried_code_norm = normalize_code(tried_code)
701
- similarity = difflib.SequenceMatcher(None, new_code_norm, tried_code_norm).ratio()
702
- if similarity > threshold:
703
- return True
704
- return False
705
-
706
- def main(self, response: str) -> Optional[str]:
707
- """Execute code with error correction.
708
-
709
- Args:
710
- response (str): AI response containing code
711
-
712
- Returns:
713
- Optional[str]: Error message if execution failed, None if successful
714
- """
715
- if not response:
716
- return "No response provided"
717
-
718
- code = self._extract_code_from_response(response)
719
- if not code:
720
- return "No executable code found in the response"
721
-
722
- ai_instance = self.ai_instance or globals().get('ai')
723
-
724
- if not ai_instance:
725
- console.print("AI instance not found, error correction disabled", style="warning")
726
- try:
727
- if self.path_to_script:
728
- script_dir = os.path.dirname(self.path_to_script)
729
- if script_dir:
730
- os.makedirs(script_dir, exist_ok=True)
731
- with open(self.path_to_script, "w", encoding="utf-8") as f:
732
- f.write(code)
733
-
734
- if self.internal_exec:
735
- console.print("[INFO] Executing code internally", style="info")
736
- # Create a local namespace
737
- local_namespace: Dict[str, Any] = {}
738
-
739
- # Capture stdout
740
- import io
741
- old_stdout = sys.stdout
742
- captured_output = io.StringIO()
743
- sys.stdout = captured_output
744
-
745
- # Execute the code
746
- try:
747
- exec(code, globals(), local_namespace)
748
- # Capture the result
749
- self.last_execution_result = captured_output.getvalue()
750
- finally:
751
- # Restore stdout
752
- sys.stdout = old_stdout
753
- else:
754
- console.print("[INFO] Executing code as external process", style="info")
755
- result = subprocess.run(
756
- [self.interpreter, self.path_to_script],
757
- capture_output=True,
758
- text=True
759
- )
760
- self.last_execution_result = result.stdout
761
-
762
- if result.returncode != 0:
763
- raise Exception(result.stderr or result.stdout)
764
-
765
- return None
766
- except Exception as e:
767
- error_msg = f"Execution error: {str(e)}"
768
- console.print(error_msg, style="error")
769
- return error_msg
770
-
771
- result = self._execute_with_retry(code, ai_instance)
772
- return result
773
-
774
- @property
775
- def intro_prompt(self) -> str:
776
- """Get the introduction prompt.
777
-
778
- Returns:
779
- str: Introduction prompt
780
- """
781
- return get_intro_prompt()
782
-
783
- def log(self, message: str, category: str = "info"):
784
- """RawDog logger
785
-
786
- Args:
787
- message (str): Log message
788
- category (str, optional): Log level. Defaults to 'info'.
789
- """
790
- if self.quiet:
791
- return
792
-
793
- message = "[Webscout] - " + message
794
- if category == "error":
795
- console.print(f"[ERROR] {message}", style="error")
796
- else:
797
- console.print(message, style=category)
798
-
799
- def stdout(self, message: str, style: str = "info") -> None:
800
- """Enhanced stdout with Rich formatting.
801
-
802
- Args:
803
- message (str): Text to be printed
804
- style (str, optional): Style to apply. Defaults to "info".
805
- """
806
- if not self.prettify:
807
- print(message)
808
- return
809
-
810
- if message.startswith("```") and message.endswith("```"):
811
- # Handle code blocks
812
- code = message.strip("`").strip()
813
- syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
814
- console.print(Panel(syntax, title="Code", border_style="blue"))
815
- elif "```python" in message:
816
- # Handle markdown code blocks
817
- md = Markdown(message)
818
- console.print(md)
819
- else:
820
- # Handle regular text with optional styling
821
- console.print(message, style=style)
822
-
823
- def print_code(self, code: str, title: str = "Generated Code") -> None:
824
- """Print code with syntax highlighting and panel.
825
-
826
- Args:
827
- code (str): Code to print
828
- title (str, optional): Panel title. Defaults to "Generated Code".
829
- """
830
- if self.prettify:
831
- syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
832
- console.print(Panel(
833
- syntax,
834
- title=f"[bold blue]In [1]:[/bold blue]",
835
- border_style="blue",
836
- expand=True,
837
- box=ROUNDED
838
- ))
839
- else:
840
- print(f"\n{title}:")
841
- print(code)
842
-
843
- def print_output(self, output: str, style: str = "output") -> None:
844
- """Print command output with optional styling.
845
-
846
- Args:
847
- output (str): Output to print
848
- style (str, optional): Style to apply. Defaults to "output".
849
- """
850
- if self.prettify:
851
- # Try to detect if output is Python code
852
- try:
853
- # If it looks like Python code, syntax highlight it
854
- compile(output, '<string>', 'exec')
855
- syntax = Syntax(output, "python", theme="monokai", line_numbers=False)
856
- formatted_output = syntax
857
- except SyntaxError:
858
- # If not Python code, treat as plain text
859
- formatted_output = output
860
-
861
- console.print(Panel(
862
- formatted_output,
863
- title="[bold red]Out [1]:[/bold red]",
864
- border_style="red",
865
- expand=True,
866
- padding=(0, 1),
867
- box=ROUNDED
868
- ))
869
- else:
870
- print("\nOutput:")
871
- print(output)
872
-
873
- def print_error(self, error: str) -> None:
874
- """Print error message with styling.
875
-
876
- Args:
877
- error (str): Error message to print
878
- """
879
- if self.prettify:
880
- console.print(f"\n Error:", style="error bold")
881
- console.print(error, style="error")
882
- else:
883
- print("\nError:")
884
- print(error)
885
-
886
- def print_table(self, headers: list, rows: list) -> None:
887
- """Print data in a formatted table.
888
-
889
- Args:
890
- headers (list): Table headers
891
- rows (list): Table rows
892
- """
893
- if not self.prettify:
894
- # Simple ASCII table
895
- print("\n" + "-" * 80)
896
- print("| " + " | ".join(headers) + " |")
897
- print("-" * 80)
898
- for row in rows:
899
- print("| " + " | ".join(str(cell) for cell in row) + " |")
900
- print("-" * 80)
901
- return
902
-
903
- table = Table(show_header=True, header_style="bold cyan")
904
- for header in headers:
905
- table.add_column(header)
906
-
907
- for row in rows:
908
- table.add_row(*[str(cell) for cell in row])
909
-
910
- console.print(table)