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.
Files changed (413) hide show
  1. webscout/AIauto.py +524 -251
  2. webscout/AIbase.py +247 -319
  3. webscout/AIutel.py +68 -703
  4. webscout/Bard.py +1072 -1026
  5. webscout/Extra/GitToolkit/__init__.py +10 -10
  6. webscout/Extra/GitToolkit/gitapi/__init__.py +20 -12
  7. webscout/Extra/GitToolkit/gitapi/gist.py +142 -0
  8. webscout/Extra/GitToolkit/gitapi/organization.py +91 -0
  9. webscout/Extra/GitToolkit/gitapi/repository.py +308 -195
  10. webscout/Extra/GitToolkit/gitapi/search.py +162 -0
  11. webscout/Extra/GitToolkit/gitapi/trending.py +236 -0
  12. webscout/Extra/GitToolkit/gitapi/user.py +128 -96
  13. webscout/Extra/GitToolkit/gitapi/utils.py +82 -62
  14. webscout/Extra/YTToolkit/README.md +443 -375
  15. webscout/Extra/YTToolkit/YTdownloader.py +953 -957
  16. webscout/Extra/YTToolkit/__init__.py +3 -3
  17. webscout/Extra/YTToolkit/transcriber.py +595 -476
  18. webscout/Extra/YTToolkit/ytapi/README.md +230 -44
  19. webscout/Extra/YTToolkit/ytapi/__init__.py +22 -6
  20. webscout/Extra/YTToolkit/ytapi/captions.py +190 -0
  21. webscout/Extra/YTToolkit/ytapi/channel.py +302 -307
  22. webscout/Extra/YTToolkit/ytapi/errors.py +13 -13
  23. webscout/Extra/YTToolkit/ytapi/extras.py +178 -118
  24. webscout/Extra/YTToolkit/ytapi/hashtag.py +120 -0
  25. webscout/Extra/YTToolkit/ytapi/https.py +89 -88
  26. webscout/Extra/YTToolkit/ytapi/patterns.py +61 -61
  27. webscout/Extra/YTToolkit/ytapi/playlist.py +59 -59
  28. webscout/Extra/YTToolkit/ytapi/pool.py +8 -8
  29. webscout/Extra/YTToolkit/ytapi/query.py +143 -40
  30. webscout/Extra/YTToolkit/ytapi/shorts.py +122 -0
  31. webscout/Extra/YTToolkit/ytapi/stream.py +68 -63
  32. webscout/Extra/YTToolkit/ytapi/suggestions.py +97 -0
  33. webscout/Extra/YTToolkit/ytapi/utils.py +66 -62
  34. webscout/Extra/YTToolkit/ytapi/video.py +403 -232
  35. webscout/Extra/__init__.py +2 -3
  36. webscout/Extra/gguf.py +1298 -684
  37. webscout/Extra/tempmail/README.md +487 -487
  38. webscout/Extra/tempmail/__init__.py +28 -28
  39. webscout/Extra/tempmail/async_utils.py +143 -141
  40. webscout/Extra/tempmail/base.py +172 -161
  41. webscout/Extra/tempmail/cli.py +191 -187
  42. webscout/Extra/tempmail/emailnator.py +88 -84
  43. webscout/Extra/tempmail/mail_tm.py +378 -361
  44. webscout/Extra/tempmail/temp_mail_io.py +304 -292
  45. webscout/Extra/weather.py +196 -194
  46. webscout/Extra/weather_ascii.py +17 -15
  47. webscout/Provider/AISEARCH/PERPLEXED_search.py +175 -0
  48. webscout/Provider/AISEARCH/Perplexity.py +292 -333
  49. webscout/Provider/AISEARCH/README.md +106 -279
  50. webscout/Provider/AISEARCH/__init__.py +16 -9
  51. webscout/Provider/AISEARCH/brave_search.py +298 -0
  52. webscout/Provider/AISEARCH/iask_search.py +357 -410
  53. webscout/Provider/AISEARCH/monica_search.py +200 -220
  54. webscout/Provider/AISEARCH/webpilotai_search.py +242 -255
  55. webscout/Provider/Algion.py +413 -0
  56. webscout/Provider/Andi.py +74 -69
  57. webscout/Provider/Apriel.py +313 -0
  58. webscout/Provider/Ayle.py +323 -0
  59. webscout/Provider/ChatSandbox.py +329 -342
  60. webscout/Provider/ClaudeOnline.py +365 -0
  61. webscout/Provider/Cohere.py +232 -208
  62. webscout/Provider/DeepAI.py +367 -0
  63. webscout/Provider/Deepinfra.py +467 -340
  64. webscout/Provider/EssentialAI.py +217 -0
  65. webscout/Provider/ExaAI.py +274 -261
  66. webscout/Provider/Gemini.py +175 -169
  67. webscout/Provider/GithubChat.py +385 -369
  68. webscout/Provider/Gradient.py +286 -0
  69. webscout/Provider/Groq.py +556 -801
  70. webscout/Provider/HadadXYZ.py +323 -0
  71. webscout/Provider/HeckAI.py +392 -375
  72. webscout/Provider/HuggingFace.py +387 -0
  73. webscout/Provider/IBM.py +340 -0
  74. webscout/Provider/Jadve.py +317 -291
  75. webscout/Provider/K2Think.py +306 -0
  76. webscout/Provider/Koboldai.py +221 -384
  77. webscout/Provider/Netwrck.py +273 -270
  78. webscout/Provider/Nvidia.py +310 -0
  79. webscout/Provider/OPENAI/DeepAI.py +489 -0
  80. webscout/Provider/OPENAI/K2Think.py +423 -0
  81. webscout/Provider/OPENAI/PI.py +463 -0
  82. webscout/Provider/OPENAI/README.md +890 -952
  83. webscout/Provider/OPENAI/TogetherAI.py +405 -0
  84. webscout/Provider/OPENAI/TwoAI.py +255 -357
  85. webscout/Provider/OPENAI/__init__.py +148 -40
  86. webscout/Provider/OPENAI/ai4chat.py +348 -293
  87. webscout/Provider/OPENAI/akashgpt.py +436 -0
  88. webscout/Provider/OPENAI/algion.py +303 -0
  89. webscout/Provider/OPENAI/{exachat.py → ayle.py} +365 -444
  90. webscout/Provider/OPENAI/base.py +253 -249
  91. webscout/Provider/OPENAI/cerebras.py +296 -0
  92. webscout/Provider/OPENAI/chatgpt.py +870 -556
  93. webscout/Provider/OPENAI/chatsandbox.py +233 -173
  94. webscout/Provider/OPENAI/deepinfra.py +403 -322
  95. webscout/Provider/OPENAI/e2b.py +2370 -1414
  96. webscout/Provider/OPENAI/elmo.py +278 -0
  97. webscout/Provider/OPENAI/exaai.py +452 -417
  98. webscout/Provider/OPENAI/freeassist.py +446 -0
  99. webscout/Provider/OPENAI/gradient.py +448 -0
  100. webscout/Provider/OPENAI/groq.py +380 -364
  101. webscout/Provider/OPENAI/hadadxyz.py +292 -0
  102. webscout/Provider/OPENAI/heckai.py +333 -308
  103. webscout/Provider/OPENAI/huggingface.py +321 -0
  104. webscout/Provider/OPENAI/ibm.py +425 -0
  105. webscout/Provider/OPENAI/llmchat.py +253 -0
  106. webscout/Provider/OPENAI/llmchatco.py +378 -335
  107. webscout/Provider/OPENAI/meta.py +541 -0
  108. webscout/Provider/OPENAI/netwrck.py +374 -357
  109. webscout/Provider/OPENAI/nvidia.py +317 -0
  110. webscout/Provider/OPENAI/oivscode.py +348 -287
  111. webscout/Provider/OPENAI/openrouter.py +328 -0
  112. webscout/Provider/OPENAI/pydantic_imports.py +1 -172
  113. webscout/Provider/OPENAI/sambanova.py +397 -0
  114. webscout/Provider/OPENAI/sonus.py +305 -304
  115. webscout/Provider/OPENAI/textpollinations.py +370 -339
  116. webscout/Provider/OPENAI/toolbaz.py +375 -413
  117. webscout/Provider/OPENAI/typefully.py +419 -355
  118. webscout/Provider/OPENAI/typliai.py +279 -0
  119. webscout/Provider/OPENAI/utils.py +314 -318
  120. webscout/Provider/OPENAI/wisecat.py +359 -387
  121. webscout/Provider/OPENAI/writecream.py +185 -163
  122. webscout/Provider/OPENAI/x0gpt.py +462 -365
  123. webscout/Provider/OPENAI/zenmux.py +380 -0
  124. webscout/Provider/OpenRouter.py +386 -0
  125. webscout/Provider/Openai.py +337 -496
  126. webscout/Provider/PI.py +443 -429
  127. webscout/Provider/QwenLM.py +346 -254
  128. webscout/Provider/STT/__init__.py +28 -0
  129. webscout/Provider/STT/base.py +303 -0
  130. webscout/Provider/STT/elevenlabs.py +264 -0
  131. webscout/Provider/Sambanova.py +317 -0
  132. webscout/Provider/TTI/README.md +69 -82
  133. webscout/Provider/TTI/__init__.py +37 -7
  134. webscout/Provider/TTI/base.py +147 -64
  135. webscout/Provider/TTI/claudeonline.py +393 -0
  136. webscout/Provider/TTI/magicstudio.py +292 -201
  137. webscout/Provider/TTI/miragic.py +180 -0
  138. webscout/Provider/TTI/pollinations.py +331 -221
  139. webscout/Provider/TTI/together.py +334 -0
  140. webscout/Provider/TTI/utils.py +14 -11
  141. webscout/Provider/TTS/README.md +186 -192
  142. webscout/Provider/TTS/__init__.py +43 -10
  143. webscout/Provider/TTS/base.py +523 -159
  144. webscout/Provider/TTS/deepgram.py +286 -156
  145. webscout/Provider/TTS/elevenlabs.py +189 -111
  146. webscout/Provider/TTS/freetts.py +218 -0
  147. webscout/Provider/TTS/murfai.py +288 -113
  148. webscout/Provider/TTS/openai_fm.py +364 -129
  149. webscout/Provider/TTS/parler.py +203 -111
  150. webscout/Provider/TTS/qwen.py +334 -0
  151. webscout/Provider/TTS/sherpa.py +286 -0
  152. webscout/Provider/TTS/speechma.py +693 -580
  153. webscout/Provider/TTS/streamElements.py +275 -333
  154. webscout/Provider/TTS/utils.py +280 -280
  155. webscout/Provider/TextPollinationsAI.py +331 -308
  156. webscout/Provider/TogetherAI.py +450 -0
  157. webscout/Provider/TwoAI.py +309 -475
  158. webscout/Provider/TypliAI.py +311 -305
  159. webscout/Provider/UNFINISHED/ChatHub.py +219 -209
  160. webscout/Provider/{OPENAI/glider.py → UNFINISHED/ChutesAI.py} +331 -326
  161. webscout/Provider/{GizAI.py → UNFINISHED/GizAI.py} +300 -295
  162. webscout/Provider/{Marcus.py → UNFINISHED/Marcus.py} +218 -198
  163. webscout/Provider/UNFINISHED/Qodo.py +481 -0
  164. webscout/Provider/{MCPCore.py → UNFINISHED/XenAI.py} +330 -315
  165. webscout/Provider/UNFINISHED/Youchat.py +347 -330
  166. webscout/Provider/UNFINISHED/aihumanizer.py +41 -0
  167. webscout/Provider/UNFINISHED/grammerchecker.py +37 -0
  168. webscout/Provider/UNFINISHED/liner.py +342 -0
  169. webscout/Provider/UNFINISHED/liner_api_request.py +246 -263
  170. webscout/Provider/{samurai.py → UNFINISHED/samurai.py} +231 -224
  171. webscout/Provider/WiseCat.py +256 -233
  172. webscout/Provider/WrDoChat.py +390 -370
  173. webscout/Provider/__init__.py +115 -174
  174. webscout/Provider/ai4chat.py +181 -174
  175. webscout/Provider/akashgpt.py +330 -335
  176. webscout/Provider/cerebras.py +397 -290
  177. webscout/Provider/cleeai.py +236 -213
  178. webscout/Provider/elmo.py +291 -283
  179. webscout/Provider/geminiapi.py +343 -208
  180. webscout/Provider/julius.py +245 -223
  181. webscout/Provider/learnfastai.py +333 -325
  182. webscout/Provider/llama3mitril.py +230 -215
  183. webscout/Provider/llmchat.py +308 -258
  184. webscout/Provider/llmchatco.py +321 -306
  185. webscout/Provider/meta.py +996 -801
  186. webscout/Provider/oivscode.py +332 -309
  187. webscout/Provider/searchchat.py +316 -292
  188. webscout/Provider/sonus.py +264 -258
  189. webscout/Provider/toolbaz.py +359 -353
  190. webscout/Provider/turboseek.py +332 -266
  191. webscout/Provider/typefully.py +262 -202
  192. webscout/Provider/x0gpt.py +332 -299
  193. webscout/__init__.py +31 -39
  194. webscout/__main__.py +5 -5
  195. webscout/cli.py +585 -524
  196. webscout/client.py +1497 -70
  197. webscout/conversation.py +140 -436
  198. webscout/exceptions.py +383 -362
  199. webscout/litagent/__init__.py +29 -29
  200. webscout/litagent/agent.py +492 -455
  201. webscout/litagent/constants.py +60 -60
  202. webscout/models.py +505 -181
  203. webscout/optimizers.py +74 -420
  204. webscout/prompt_manager.py +376 -288
  205. webscout/sanitize.py +1514 -0
  206. webscout/scout/README.md +452 -404
  207. webscout/scout/__init__.py +8 -8
  208. webscout/scout/core/__init__.py +7 -7
  209. webscout/scout/core/crawler.py +330 -210
  210. webscout/scout/core/scout.py +800 -607
  211. webscout/scout/core/search_result.py +51 -96
  212. webscout/scout/core/text_analyzer.py +64 -63
  213. webscout/scout/core/text_utils.py +412 -277
  214. webscout/scout/core/web_analyzer.py +54 -52
  215. webscout/scout/element.py +872 -478
  216. webscout/scout/parsers/__init__.py +70 -69
  217. webscout/scout/parsers/html5lib_parser.py +182 -172
  218. webscout/scout/parsers/html_parser.py +238 -236
  219. webscout/scout/parsers/lxml_parser.py +203 -178
  220. webscout/scout/utils.py +38 -37
  221. webscout/search/__init__.py +47 -0
  222. webscout/search/base.py +201 -0
  223. webscout/search/bing_main.py +45 -0
  224. webscout/search/brave_main.py +92 -0
  225. webscout/search/duckduckgo_main.py +57 -0
  226. webscout/search/engines/__init__.py +127 -0
  227. webscout/search/engines/bing/__init__.py +15 -0
  228. webscout/search/engines/bing/base.py +35 -0
  229. webscout/search/engines/bing/images.py +114 -0
  230. webscout/search/engines/bing/news.py +96 -0
  231. webscout/search/engines/bing/suggestions.py +36 -0
  232. webscout/search/engines/bing/text.py +109 -0
  233. webscout/search/engines/brave/__init__.py +19 -0
  234. webscout/search/engines/brave/base.py +47 -0
  235. webscout/search/engines/brave/images.py +213 -0
  236. webscout/search/engines/brave/news.py +353 -0
  237. webscout/search/engines/brave/suggestions.py +318 -0
  238. webscout/search/engines/brave/text.py +167 -0
  239. webscout/search/engines/brave/videos.py +364 -0
  240. webscout/search/engines/duckduckgo/__init__.py +25 -0
  241. webscout/search/engines/duckduckgo/answers.py +80 -0
  242. webscout/search/engines/duckduckgo/base.py +189 -0
  243. webscout/search/engines/duckduckgo/images.py +100 -0
  244. webscout/search/engines/duckduckgo/maps.py +183 -0
  245. webscout/search/engines/duckduckgo/news.py +70 -0
  246. webscout/search/engines/duckduckgo/suggestions.py +22 -0
  247. webscout/search/engines/duckduckgo/text.py +221 -0
  248. webscout/search/engines/duckduckgo/translate.py +48 -0
  249. webscout/search/engines/duckduckgo/videos.py +80 -0
  250. webscout/search/engines/duckduckgo/weather.py +84 -0
  251. webscout/search/engines/mojeek.py +61 -0
  252. webscout/search/engines/wikipedia.py +77 -0
  253. webscout/search/engines/yahoo/__init__.py +41 -0
  254. webscout/search/engines/yahoo/answers.py +19 -0
  255. webscout/search/engines/yahoo/base.py +34 -0
  256. webscout/search/engines/yahoo/images.py +323 -0
  257. webscout/search/engines/yahoo/maps.py +19 -0
  258. webscout/search/engines/yahoo/news.py +258 -0
  259. webscout/search/engines/yahoo/suggestions.py +140 -0
  260. webscout/search/engines/yahoo/text.py +273 -0
  261. webscout/search/engines/yahoo/translate.py +19 -0
  262. webscout/search/engines/yahoo/videos.py +302 -0
  263. webscout/search/engines/yahoo/weather.py +220 -0
  264. webscout/search/engines/yandex.py +67 -0
  265. webscout/search/engines/yep/__init__.py +13 -0
  266. webscout/search/engines/yep/base.py +34 -0
  267. webscout/search/engines/yep/images.py +101 -0
  268. webscout/search/engines/yep/suggestions.py +38 -0
  269. webscout/search/engines/yep/text.py +99 -0
  270. webscout/search/http_client.py +172 -0
  271. webscout/search/results.py +141 -0
  272. webscout/search/yahoo_main.py +57 -0
  273. webscout/search/yep_main.py +48 -0
  274. webscout/server/__init__.py +48 -0
  275. webscout/server/config.py +78 -0
  276. webscout/server/exceptions.py +69 -0
  277. webscout/server/providers.py +286 -0
  278. webscout/server/request_models.py +131 -0
  279. webscout/server/request_processing.py +404 -0
  280. webscout/server/routes.py +642 -0
  281. webscout/server/server.py +351 -0
  282. webscout/server/ui_templates.py +1171 -0
  283. webscout/swiftcli/__init__.py +79 -95
  284. webscout/swiftcli/core/__init__.py +7 -7
  285. webscout/swiftcli/core/cli.py +574 -297
  286. webscout/swiftcli/core/context.py +98 -104
  287. webscout/swiftcli/core/group.py +268 -241
  288. webscout/swiftcli/decorators/__init__.py +28 -28
  289. webscout/swiftcli/decorators/command.py +243 -221
  290. webscout/swiftcli/decorators/options.py +247 -220
  291. webscout/swiftcli/decorators/output.py +392 -252
  292. webscout/swiftcli/exceptions.py +21 -21
  293. webscout/swiftcli/plugins/__init__.py +9 -9
  294. webscout/swiftcli/plugins/base.py +134 -135
  295. webscout/swiftcli/plugins/manager.py +269 -269
  296. webscout/swiftcli/utils/__init__.py +58 -59
  297. webscout/swiftcli/utils/formatting.py +251 -252
  298. webscout/swiftcli/utils/parsing.py +368 -267
  299. webscout/update_checker.py +280 -136
  300. webscout/utils.py +28 -14
  301. webscout/version.py +2 -1
  302. webscout/version.py.bak +3 -0
  303. webscout/zeroart/__init__.py +218 -135
  304. webscout/zeroart/base.py +70 -66
  305. webscout/zeroart/effects.py +155 -101
  306. webscout/zeroart/fonts.py +1799 -1239
  307. webscout-2026.1.19.dist-info/METADATA +638 -0
  308. webscout-2026.1.19.dist-info/RECORD +312 -0
  309. {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/WHEEL +1 -1
  310. {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/entry_points.txt +1 -1
  311. webscout/DWEBS.py +0 -520
  312. webscout/Extra/Act.md +0 -309
  313. webscout/Extra/GitToolkit/gitapi/README.md +0 -110
  314. webscout/Extra/autocoder/__init__.py +0 -9
  315. webscout/Extra/autocoder/autocoder.py +0 -1105
  316. webscout/Extra/autocoder/autocoder_utiles.py +0 -332
  317. webscout/Extra/gguf.md +0 -430
  318. webscout/Extra/weather.md +0 -281
  319. webscout/Litlogger/README.md +0 -10
  320. webscout/Litlogger/__init__.py +0 -15
  321. webscout/Litlogger/formats.py +0 -4
  322. webscout/Litlogger/handlers.py +0 -103
  323. webscout/Litlogger/levels.py +0 -13
  324. webscout/Litlogger/logger.py +0 -92
  325. webscout/Provider/AI21.py +0 -177
  326. webscout/Provider/AISEARCH/DeepFind.py +0 -254
  327. webscout/Provider/AISEARCH/felo_search.py +0 -202
  328. webscout/Provider/AISEARCH/genspark_search.py +0 -324
  329. webscout/Provider/AISEARCH/hika_search.py +0 -186
  330. webscout/Provider/AISEARCH/scira_search.py +0 -298
  331. webscout/Provider/Aitopia.py +0 -316
  332. webscout/Provider/AllenAI.py +0 -440
  333. webscout/Provider/Blackboxai.py +0 -791
  334. webscout/Provider/ChatGPTClone.py +0 -237
  335. webscout/Provider/ChatGPTGratis.py +0 -194
  336. webscout/Provider/Cloudflare.py +0 -324
  337. webscout/Provider/ExaChat.py +0 -358
  338. webscout/Provider/Flowith.py +0 -217
  339. webscout/Provider/FreeGemini.py +0 -250
  340. webscout/Provider/Glider.py +0 -225
  341. webscout/Provider/HF_space/__init__.py +0 -0
  342. webscout/Provider/HF_space/qwen_qwen2.py +0 -206
  343. webscout/Provider/HuggingFaceChat.py +0 -469
  344. webscout/Provider/Hunyuan.py +0 -283
  345. webscout/Provider/LambdaChat.py +0 -411
  346. webscout/Provider/Llama3.py +0 -259
  347. webscout/Provider/Nemotron.py +0 -218
  348. webscout/Provider/OLLAMA.py +0 -396
  349. webscout/Provider/OPENAI/BLACKBOXAI.py +0 -766
  350. webscout/Provider/OPENAI/Cloudflare.py +0 -378
  351. webscout/Provider/OPENAI/FreeGemini.py +0 -283
  352. webscout/Provider/OPENAI/NEMOTRON.py +0 -232
  353. webscout/Provider/OPENAI/Qwen3.py +0 -283
  354. webscout/Provider/OPENAI/api.py +0 -969
  355. webscout/Provider/OPENAI/c4ai.py +0 -373
  356. webscout/Provider/OPENAI/chatgptclone.py +0 -494
  357. webscout/Provider/OPENAI/copilot.py +0 -242
  358. webscout/Provider/OPENAI/flowith.py +0 -162
  359. webscout/Provider/OPENAI/freeaichat.py +0 -359
  360. webscout/Provider/OPENAI/mcpcore.py +0 -389
  361. webscout/Provider/OPENAI/multichat.py +0 -376
  362. webscout/Provider/OPENAI/opkfc.py +0 -496
  363. webscout/Provider/OPENAI/scirachat.py +0 -477
  364. webscout/Provider/OPENAI/standardinput.py +0 -433
  365. webscout/Provider/OPENAI/typegpt.py +0 -364
  366. webscout/Provider/OPENAI/uncovrAI.py +0 -463
  367. webscout/Provider/OPENAI/venice.py +0 -431
  368. webscout/Provider/OPENAI/yep.py +0 -382
  369. webscout/Provider/OpenGPT.py +0 -209
  370. webscout/Provider/Perplexitylabs.py +0 -415
  371. webscout/Provider/Reka.py +0 -214
  372. webscout/Provider/StandardInput.py +0 -290
  373. webscout/Provider/TTI/aiarta.py +0 -365
  374. webscout/Provider/TTI/artbit.py +0 -0
  375. webscout/Provider/TTI/fastflux.py +0 -200
  376. webscout/Provider/TTI/piclumen.py +0 -203
  377. webscout/Provider/TTI/pixelmuse.py +0 -225
  378. webscout/Provider/TTS/gesserit.py +0 -128
  379. webscout/Provider/TTS/sthir.py +0 -94
  380. webscout/Provider/TeachAnything.py +0 -229
  381. webscout/Provider/UNFINISHED/puterjs.py +0 -635
  382. webscout/Provider/UNFINISHED/test_lmarena.py +0 -119
  383. webscout/Provider/Venice.py +0 -258
  384. webscout/Provider/VercelAI.py +0 -253
  385. webscout/Provider/Writecream.py +0 -246
  386. webscout/Provider/WritingMate.py +0 -269
  387. webscout/Provider/asksteve.py +0 -220
  388. webscout/Provider/chatglm.py +0 -215
  389. webscout/Provider/copilot.py +0 -425
  390. webscout/Provider/freeaichat.py +0 -285
  391. webscout/Provider/granite.py +0 -235
  392. webscout/Provider/hermes.py +0 -266
  393. webscout/Provider/koala.py +0 -170
  394. webscout/Provider/lmarena.py +0 -198
  395. webscout/Provider/multichat.py +0 -364
  396. webscout/Provider/scira_chat.py +0 -299
  397. webscout/Provider/scnet.py +0 -243
  398. webscout/Provider/talkai.py +0 -194
  399. webscout/Provider/typegpt.py +0 -289
  400. webscout/Provider/uncovr.py +0 -368
  401. webscout/Provider/yep.py +0 -389
  402. webscout/litagent/Readme.md +0 -276
  403. webscout/litprinter/__init__.py +0 -59
  404. webscout/swiftcli/Readme.md +0 -323
  405. webscout/tempid.py +0 -128
  406. webscout/webscout_search.py +0 -1184
  407. webscout/webscout_search_async.py +0 -654
  408. webscout/yep_search.py +0 -347
  409. webscout/zeroart/README.md +0 -89
  410. webscout-8.2.9.dist-info/METADATA +0 -1033
  411. webscout-8.2.9.dist-info/RECORD +0 -289
  412. {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/licenses/LICENSE.md +0 -0
  413. {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/top_level.txt +0 -0
@@ -1,1105 +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
-
183
- # Check if this is a shell command (starts with !)
184
- if code_type == 'bash' or code_type == 'shell' or code.startswith('!'):
185
- blocks.append(('shell', code))
186
- else:
187
- blocks.append((code_type, code))
188
-
189
- # If no explicit code blocks found with language tags, try generic code blocks
190
- if not blocks:
191
- pattern = r"```(.*?)```"
192
- matches = re.finditer(pattern, response, re.DOTALL)
193
- for match in matches:
194
- code = match.group(1).strip()
195
-
196
- # Check if this is a shell command (starts with !)
197
- if code.startswith('!'):
198
- blocks.append(('shell', code))
199
- else:
200
- blocks.append(('python', code))
201
-
202
- # If still no code blocks found, treat as raw Python code
203
- if not blocks:
204
- lines = [line.strip() for line in response.split('\n') if line.strip()]
205
- if lines:
206
- # Check if this is a shell command (starts with !)
207
- if lines[0].startswith('!'):
208
- blocks.append(('shell', '\n'.join(lines)))
209
- else:
210
- blocks.append(('python', '\n'.join(lines)))
211
-
212
- return blocks
213
-
214
- def _execute_code_block(self, code_type: str, code: str, ai_instance=None) -> Tuple[bool, str]:
215
- """Execute a code block.
216
-
217
- Args:
218
- code_type (str): Type of code block ('python' or 'shell')
219
- code (str): Code to execute
220
- ai_instance: Optional AI instance for error correction
221
-
222
- Returns:
223
- Tuple[bool, str]: (Success status, Error message or execution result)
224
- """
225
- try:
226
- # Handle shell commands (starting with !)
227
- if code_type == 'shell':
228
- # Remove the leading '!' from each line
229
- shell_commands = []
230
- for line in code.split('\n'):
231
- if line.startswith('!'):
232
- shell_commands.append(line[1:].strip()) # Remove the '!' and any leading whitespace
233
- else:
234
- shell_commands.append(line.strip())
235
-
236
- # Execute each shell command
237
- overall_success = True
238
- overall_result = []
239
-
240
- # Display the shell command in Jupyter-style UI
241
- if self.prettify:
242
- # Format the command for display
243
- cmd_display = '\n'.join([f"!{cmd}" for cmd in shell_commands if cmd])
244
- syntax = Syntax(cmd_display, "bash", theme="monokai", line_numbers=True)
245
- console.print(Panel(
246
- syntax,
247
- title="[bold blue]In [1]:[/bold blue]",
248
- border_style="blue",
249
- expand=True,
250
- box=ROUNDED
251
- ))
252
-
253
- for cmd in shell_commands:
254
- if not cmd: # Skip empty commands
255
- continue
256
-
257
- success, result = run_system_command(cmd)
258
-
259
- if success:
260
- if result.stdout:
261
- overall_result.append(result.stdout)
262
-
263
- # Display the output in Jupyter-style UI
264
- if self.prettify:
265
- console.print(Panel(
266
- result.stdout,
267
- title="[bold red]Out [1]:[/bold red]",
268
- border_style="red",
269
- expand=True,
270
- padding=(0, 1),
271
- box=ROUNDED
272
- ))
273
-
274
- self.last_execution_result = '\n'.join(overall_result)
275
- else:
276
- error_msg = result.stderr if result.stderr else f"Command failed: {cmd}"
277
-
278
- # Display the error in Jupyter-style UI
279
- if self.prettify:
280
- console.print(Panel(
281
- f"Error: {error_msg}",
282
- title="[bold red]Out [1]:[/bold red]",
283
- border_style="red",
284
- expand=True,
285
- padding=(0, 1),
286
- box=ROUNDED
287
- ))
288
-
289
- return False, error_msg
290
-
291
- return True, self.last_execution_result
292
- else:
293
- # Handle Python code
294
- result = self._execute_with_retry(code, ai_instance)
295
- if result is None:
296
- return True, self.last_execution_result
297
- return False, result
298
- except Exception as e:
299
- return False, str(e)
300
-
301
- def _format_output_panel(self, code: str, output_lines: list) -> Panel:
302
- """Format code and output into a single panel.
303
-
304
- Args:
305
- code (str): The code that was executed
306
- output_lines (list): List of output lines
307
-
308
- Returns:
309
- Panel: Formatted panel with code and output
310
- """
311
- # Format output
312
- output_text = "\n".join(output_lines) if output_lines else "Running..."
313
-
314
- # Create panel with Jupyter-like styling
315
- panel = Panel(
316
- output_text,
317
- title="[bold red]Out [1]:[/bold red]",
318
- border_style="red",
319
- expand=True,
320
- padding=(0, 1),
321
- box=ROUNDED
322
- )
323
-
324
- return panel
325
-
326
- def _format_result_panel(self, output: str) -> Panel:
327
- """Format execution result into a panel.
328
-
329
- Args:
330
- output (str): Execution output text
331
-
332
- Returns:
333
- Panel: Formatted panel with execution result
334
- """
335
- # Create panel with Jupyter-like styling
336
- panel = Panel(
337
- output,
338
- title="[bold red]Out [1]:[/bold red]",
339
- border_style="red",
340
- expand=True,
341
- padding=(0, 1),
342
- box=ROUNDED
343
- )
344
-
345
- return panel
346
-
347
- def _stream_output(self, process: subprocess.Popen) -> Generator[str, None, None]:
348
- """Stream output from a subprocess in realtime.
349
-
350
- Args:
351
- process: Subprocess to stream output from
352
-
353
- Yields:
354
- str: Lines of output
355
- """
356
- # Stream stdout
357
- output_lines = []
358
- for line in process.stdout:
359
- decoded_line = line.decode('utf-8').strip() if isinstance(line, bytes) else line.strip()
360
- if decoded_line:
361
- output_lines.append(decoded_line)
362
- yield decoded_line
363
-
364
- # Check stderr
365
- error = process.stderr.read() if process.stderr else None
366
- if error:
367
- error_str = error.decode('utf-8').strip() if isinstance(error, bytes) else error.strip()
368
- if error_str:
369
- yield f"Error: {error_str}"
370
- output_lines.append(f"Error: {error_str}")
371
-
372
- # Store the full execution result
373
- self.last_execution_result = "\n".join(output_lines)
374
-
375
- def _execute_with_retry(self, code: str, ai_instance=None) -> Optional[str]:
376
- """Execute code with retry logic and error correction.
377
-
378
- Args:
379
- code (str): Code to execute
380
- ai_instance: Optional AI instance for error correction
381
-
382
- Returns:
383
- Optional[str]: Error message if execution failed, None if successful
384
- """
385
- last_error = None
386
- retries = 0
387
-
388
- # Add the solution to tried solutions
389
- self.tried_solutions.add(code)
390
-
391
- # Print the code first
392
- if self.prettify:
393
- syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
394
- console.print(Panel(
395
- syntax,
396
- title="[bold blue]In [1]:[/bold blue]",
397
- border_style="blue",
398
- expand=True,
399
- box=ROUNDED
400
- ))
401
-
402
- while retries < self.max_retries:
403
- try:
404
- if self.path_to_script:
405
- script_dir = os.path.dirname(self.path_to_script)
406
- if script_dir:
407
- os.makedirs(script_dir, exist_ok=True)
408
- with open(self.path_to_script, "w", encoding="utf-8") as f:
409
- f.write(code)
410
-
411
- if self.internal_exec:
412
- # Create StringIO for output capture
413
- import io
414
- import sys
415
- stdout = io.StringIO()
416
- stderr = io.StringIO()
417
-
418
- # Create a queue for realtime output
419
- output_queue = queue.Queue()
420
- output_lines = []
421
-
422
- def execute_code():
423
- try:
424
- # Create a local namespace
425
- local_namespace: Dict[str, Any] = {}
426
-
427
- # Redirect stdout/stderr
428
- sys.stdout = stdout
429
- sys.stderr = stderr
430
-
431
- # Execute the code
432
- exec(code, globals(), local_namespace)
433
-
434
- # Get any output
435
- output = stdout.getvalue()
436
- error = stderr.getvalue()
437
-
438
- if error:
439
- output_queue.put(("error", error))
440
- if output:
441
- output_queue.put(("output", output))
442
-
443
- except Exception as e:
444
- output_queue.put(("error", str(e)))
445
- finally:
446
- # Restore stdout/stderr
447
- sys.stdout = sys.__stdout__
448
- sys.stderr = sys.__stderr__
449
-
450
- # Create and start execution thread
451
- thread = threading.Thread(target=execute_code)
452
- thread.daemon = True # Make thread daemon to avoid hanging
453
- thread.start()
454
-
455
- # Display output in realtime
456
- with Live(auto_refresh=True) as live:
457
- timeout_counter = 0
458
- while thread.is_alive() or not output_queue.empty():
459
- try:
460
- msg_type, content = output_queue.get(timeout=0.1)
461
- if content:
462
- new_lines = content.splitlines()
463
- output_lines.extend(new_lines)
464
- live.update(self._format_output_panel(code, output_lines))
465
- live.refresh()
466
- output_queue.task_done()
467
- except queue.Empty:
468
- timeout_counter += 1
469
- # Refresh the display to show it's still running
470
- if timeout_counter % 10 == 0: # Refresh every ~1 second
471
- live.update(self._format_output_panel(code, output_lines))
472
- live.refresh()
473
- if timeout_counter > 100 and thread.is_alive(): # ~10 seconds
474
- output_lines.append("Warning: Execution taking longer than expected...")
475
- live.update(self._format_output_panel(code, output_lines))
476
- live.refresh()
477
- continue
478
-
479
- # Wait for thread to complete with timeout
480
- thread.join(timeout=30) # 30 second timeout
481
- if thread.is_alive():
482
- output_lines.append("Error: Execution timed out after 30 seconds")
483
- raise TimeoutError("Execution timed out after 30 seconds")
484
-
485
- # Check for any final errors
486
- error = stderr.getvalue()
487
- if error:
488
- raise Exception(error)
489
-
490
- # Store the full execution result
491
- self.last_execution_result = stdout.getvalue()
492
-
493
- else:
494
- try:
495
- process = subprocess.Popen(
496
- [self.interpreter, self.path_to_script],
497
- stdout=subprocess.PIPE,
498
- stderr=subprocess.PIPE,
499
- text=True, # Use text mode to avoid encoding issues
500
- bufsize=1,
501
- )
502
-
503
- output_lines = []
504
- # Stream output in realtime
505
- with Live(auto_refresh=True) as live:
506
- for line in self._stream_output(process):
507
- output_lines.append(line)
508
- live.update(self._format_output_panel(code, output_lines))
509
- live.refresh()
510
-
511
- process.wait(timeout=30) # 30 second timeout
512
-
513
- if process.returncode != 0:
514
- # Try to read more detailed error information
515
- if process.stderr:
516
- error = process.stderr.read()
517
- error_str = error.strip() if error else ""
518
- if error_str:
519
- raise Exception(error_str)
520
- raise Exception(f"Process exited with code {process.returncode}")
521
-
522
- # Store the full execution result
523
- self.last_execution_result = "\n".join(output_lines)
524
-
525
- except subprocess.TimeoutExpired:
526
- # Handle the case where the process times out
527
- if process:
528
- process.kill()
529
- raise TimeoutError("Execution timed out after 30 seconds")
530
-
531
- return None
532
-
533
- except Exception as e:
534
- last_error = e
535
- if retries < self.max_retries - 1 and ai_instance:
536
- try:
537
- # First try to handle import errors
538
- if isinstance(e, ImportError):
539
- fixed_code = self._handle_import_error(e, code)
540
- if fixed_code:
541
- code = fixed_code
542
- retries += 1
543
- continue
544
-
545
- # Get error context and try to fix the specific error
546
- error_context = self._get_error_context(e, code)
547
- fixed_response = ai_instance.chat(error_context)
548
- fixed_code = self._extract_code_from_response(fixed_response)
549
-
550
- if not fixed_code:
551
- # If no code found, try a more general approach
552
- general_context = f"""
553
- The code failed with error: {str(e)}
554
-
555
- Original Code:
556
- ```python
557
- {code}
558
- ```
559
-
560
- Please provide a complete, corrected version of the code that handles this error. The code should:
561
- 1. Handle any potential encoding issues
562
- 2. Include proper error handling
563
- 3. Use appropriate libraries and imports
564
- 4. Be compatible with the current Python environment
565
- 5. Fix the specific error: {str(e)}
566
-
567
- Provide only the corrected code without any explanation.
568
- """
569
- fixed_response = ai_instance.chat(general_context)
570
- fixed_code = self._extract_code_from_response(fixed_response)
571
-
572
- if not fixed_code:
573
- break
574
-
575
- if self._is_similar_solution(fixed_code):
576
- # If solution is too similar, try a different approach
577
- different_context = f"""
578
- Previous solutions were not successful. The code failed with error: {str(e)}
579
-
580
- Original Code:
581
- ```python
582
- {code}
583
- ```
584
-
585
- Please provide a significantly different approach to solve this problem. Consider:
586
- 1. Using alternative libraries or methods
587
- 2. Implementing a different algorithm
588
- 3. Adding more robust error handling
589
- 4. Using a different encoding or data handling approach
590
- 5. Specifically address the error: {str(e)}
591
-
592
- Provide only the corrected code without any explanation.
593
- """
594
- fixed_response = ai_instance.chat(different_context)
595
- fixed_code = self._extract_code_from_response(fixed_response)
596
-
597
- if self._is_similar_solution(fixed_code):
598
- break
599
-
600
- # Update code and continue with retry
601
- code = fixed_code
602
- self.tried_solutions.add(code)
603
- retries += 1
604
- continue
605
-
606
- except Exception as ai_error:
607
- console.print(f"Error during AI correction: {str(ai_error)}", style="error")
608
- break
609
- break
610
-
611
- return str(last_error) if last_error else "Unknown error occurred"
612
-
613
- def execute(self, prompt: str, ai_instance=None) -> bool:
614
- """Execute the given prompt using the appropriate executor.
615
-
616
- Args:
617
- prompt (str): Prompt to execute
618
- ai_instance: Optional AI instance for error correction
619
-
620
- Returns:
621
- bool: True if execution was successful, False otherwise
622
- """
623
- try:
624
- # Check if this is a direct shell command (starts with !)
625
- if prompt.strip().startswith('!'):
626
- # Handle shell command
627
- cmd = prompt.strip()[1:].strip() # Remove the '!' and any leading whitespace
628
-
629
- # Display the shell command in Jupyter-style UI
630
- if self.prettify:
631
- syntax = Syntax(f"!{cmd}", "bash", theme="monokai", line_numbers=True)
632
- console.print(Panel(
633
- syntax,
634
- title="[bold blue]In [1]:[/bold blue]",
635
- border_style="blue",
636
- expand=True,
637
- box=ROUNDED
638
- ))
639
-
640
- success, result = run_system_command(cmd)
641
-
642
- if success:
643
- if result.stdout:
644
- # Display the output in Jupyter-style UI
645
- if self.prettify:
646
- console.print(Panel(
647
- result.stdout,
648
- title="[bold red]Out [1]:[/bold red]",
649
- border_style="red",
650
- expand=True,
651
- padding=(0, 1),
652
- box=ROUNDED
653
- ))
654
- else:
655
- console.print(result.stdout, style="output")
656
- self.last_execution_result = result.stdout
657
- return True
658
- else:
659
- error_msg = result.stderr if result.stderr else f"Command failed: {cmd}"
660
- # Display the error in Jupyter-style UI
661
- if self.prettify:
662
- console.print(Panel(
663
- f"Error: {error_msg}",
664
- title="[bold red]Out [1]:[/bold red]",
665
- border_style="red",
666
- expand=True,
667
- padding=(0, 1),
668
- box=ROUNDED
669
- ))
670
- else:
671
- console.print(error_msg, style="error")
672
- return False
673
-
674
- # Extract code blocks
675
- code_blocks = self._extract_code_blocks(prompt)
676
- if not code_blocks:
677
- console.print("No executable code found in the prompt", style="warning")
678
- return False
679
-
680
- # Execute each code block
681
- overall_success = True
682
- for code_type, code in code_blocks:
683
- success, result = self._execute_code_block(code_type, code, ai_instance)
684
-
685
- if not success:
686
- console.print(f"Execution failed: {result}", style="error")
687
- overall_success = False
688
-
689
- return overall_success
690
-
691
- except Exception as e:
692
- console.print(f"Error in execution: {str(e)}", style="error")
693
- return False
694
-
695
- def _extract_code_from_response(self, response: str) -> str:
696
- """Extract code from AI response.
697
-
698
- Args:
699
- response (str): AI response containing code blocks
700
-
701
- Returns:
702
- str: Extracted code from the first code block
703
- """
704
- if not response:
705
- return ""
706
-
707
- # First try to find code blocks with explicit language tags
708
- code_blocks = self._extract_code_blocks(response)
709
- if code_blocks:
710
- # Return the content of the first code block
711
- return code_blocks[0][1]
712
-
713
- # If no code blocks found, try to find raw Python code or shell commands
714
- lines = []
715
- for line in response.split('\n'):
716
- line = line.strip()
717
- if not line:
718
- continue
719
-
720
- # Skip markdown headers and other non-code lines
721
- if line.startswith(('#', '```', '---', '===', '>>>')):
722
- continue
723
-
724
- # Skip common non-code lines
725
- if any(line.startswith(prefix) for prefix in ['Please', 'Here', 'The', 'This', 'You']):
726
- continue
727
-
728
- lines.append(line)
729
-
730
- if lines:
731
- return '\n'.join(lines)
732
-
733
- return ""
734
-
735
- def _get_error_context(self, error: Exception, code: str) -> str:
736
- """Create context about the error for AI correction.
737
-
738
- Args:
739
- error (Exception): The caught exception
740
- code (str): The code that caused the error
741
-
742
- Returns:
743
- str: Formatted error context for AI
744
- """
745
- error_type = type(error).__name__
746
- error_msg = str(error)
747
-
748
- # Get Python version and environment info
749
- python_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
750
- platform = sys.platform
751
-
752
- # Get the line number where the error occurred if available
753
- import traceback
754
- tb = traceback.extract_tb(error.__traceback__)
755
- line_info = ""
756
- if tb:
757
- line_info = f"\nError occurred at line {tb[-1].lineno}"
758
-
759
- return f"""
760
- The code failed with error:
761
- Error Type: {error_type}
762
- Error Message: {error_msg}{line_info}
763
-
764
- Environment:
765
- Python Version: {python_version}
766
- Platform: {platform}
767
-
768
- Original Code:
769
- ```python
770
- {code}
771
- ```
772
-
773
- Please fix the code to handle this error. The solution should:
774
- 1. Address the specific error: {error_msg}
775
- 2. Be compatible with Python {python_version}
776
- 3. Work on {platform}
777
- 4. Include proper error handling
778
- 5. Use appropriate libraries and imports
779
-
780
- Provide only the corrected code without any explanation.
781
- """
782
-
783
- def _handle_import_error(self, error: ImportError, code: str) -> Optional[str]:
784
- """Handle missing package errors by attempting to install them.
785
-
786
- Args:
787
- error (ImportError): The import error
788
- code (str): The code that caused the error
789
-
790
- Returns:
791
- Optional[str]: Fixed code or None if installation failed
792
- """
793
- try:
794
- missing_package = str(error).split("'")[1] if "'" in str(error) else str(error).split("No module named")[1].strip()
795
- missing_package = missing_package.replace("'", "").strip()
796
-
797
- console.print(f"Installing missing package: {missing_package}", style="info")
798
- result = subprocess.run(
799
- [sys.executable, "-m", "pip", "install", missing_package],
800
- capture_output=True,
801
- text=True
802
- )
803
- if result.returncode == 0:
804
- console.print(f"Successfully installed {missing_package}", style="success")
805
- return code # Retry with same code after installing package
806
- else:
807
- raise Exception(f"Failed to install {missing_package}: {result.stderr}")
808
- except Exception as e:
809
- console.print(f"Error installing package: {str(e)}", style="error")
810
- return None
811
-
812
- def _is_similar_solution(self, new_code: str, threshold: float = 0.8) -> bool:
813
- """Check if the new solution is too similar to previously tried ones.
814
-
815
- Args:
816
- new_code (str): New solution to check
817
- threshold (float): Similarity threshold (0-1). Defaults to 0.8.
818
-
819
- Returns:
820
- bool: True if solution is too similar to previous attempts
821
- """
822
- import difflib
823
-
824
- def normalize_code(code: str) -> str:
825
- lines = [line.split('#')[0].strip() for line in code.split('\n')]
826
- return '\n'.join(line for line in lines if line)
827
-
828
- new_code_norm = normalize_code(new_code)
829
-
830
- for tried_code in self.tried_solutions:
831
- tried_code_norm = normalize_code(tried_code)
832
- similarity = difflib.SequenceMatcher(None, new_code_norm, tried_code_norm).ratio()
833
- if similarity > threshold:
834
- return True
835
- return False
836
-
837
- def main(self, response: str) -> Optional[str]:
838
- """Execute code with error correction.
839
-
840
- Args:
841
- response (str): AI response containing code
842
-
843
- Returns:
844
- Optional[str]: Error message if execution failed, None if successful
845
- """
846
- if not response:
847
- return "No response provided"
848
-
849
- # Check if this is a shell command (starts with !)
850
- if response.strip().startswith('!'):
851
- # Handle shell command
852
- cmd = response.strip()[1:].strip() # Remove the '!' and any leading whitespace
853
-
854
- # Display the shell command in Jupyter-style UI
855
- if self.prettify:
856
- syntax = Syntax(f"!{cmd}", "bash", theme="monokai", line_numbers=True)
857
- console.print(Panel(
858
- syntax,
859
- title="[bold blue]In [1]:[/bold blue]",
860
- border_style="blue",
861
- expand=True,
862
- box=ROUNDED
863
- ))
864
-
865
- success, result = run_system_command(cmd)
866
-
867
- if success:
868
- if result.stdout:
869
- # Display the output in Jupyter-style UI
870
- if self.prettify:
871
- console.print(Panel(
872
- result.stdout,
873
- title="[bold red]Out [1]:[/bold red]",
874
- border_style="red",
875
- expand=True,
876
- padding=(0, 1),
877
- box=ROUNDED
878
- ))
879
- self.last_execution_result = result.stdout
880
- return None
881
- else:
882
- error_msg = result.stderr if result.stderr else f"Command failed: {cmd}"
883
- # Display the error in Jupyter-style UI
884
- if self.prettify:
885
- console.print(Panel(
886
- f"Error: {error_msg}",
887
- title="[bold red]Out [1]:[/bold red]",
888
- border_style="red",
889
- expand=True,
890
- padding=(0, 1),
891
- box=ROUNDED
892
- ))
893
- else:
894
- console.print(error_msg, style="error")
895
- return error_msg
896
-
897
- # Extract code blocks
898
- code_blocks = self._extract_code_blocks(response)
899
- if code_blocks:
900
- code_type, code = code_blocks[0]
901
-
902
- # Handle shell commands
903
- if code_type == 'shell':
904
- success, result = self._execute_code_block(code_type, code)
905
- if success:
906
- return None
907
- else:
908
- # Error is already displayed in _execute_code_block
909
- return result
910
-
911
- # Handle regular Python code
912
- code = self._extract_code_from_response(response)
913
- if not code:
914
- return "No executable code found in the response"
915
-
916
- ai_instance = self.ai_instance or globals().get('ai')
917
-
918
- if not ai_instance:
919
- console.print("AI instance not found, error correction disabled", style="warning")
920
- try:
921
- if self.path_to_script:
922
- script_dir = os.path.dirname(self.path_to_script)
923
- if script_dir:
924
- os.makedirs(script_dir, exist_ok=True)
925
- with open(self.path_to_script, "w", encoding="utf-8") as f:
926
- f.write(code)
927
-
928
- if self.internal_exec:
929
- console.print("[INFO] Executing code internally", style="info")
930
- # Create a local namespace
931
- local_namespace: Dict[str, Any] = {}
932
-
933
- # Capture stdout
934
- import io
935
- old_stdout = sys.stdout
936
- captured_output = io.StringIO()
937
- sys.stdout = captured_output
938
-
939
- # Execute the code
940
- try:
941
- exec(code, globals(), local_namespace)
942
- # Capture the result
943
- self.last_execution_result = captured_output.getvalue()
944
- finally:
945
- # Restore stdout
946
- sys.stdout = old_stdout
947
- else:
948
- console.print("[INFO] Executing code as external process", style="info")
949
- result = subprocess.run(
950
- [self.interpreter, self.path_to_script],
951
- capture_output=True,
952
- text=True
953
- )
954
- self.last_execution_result = result.stdout
955
-
956
- if result.returncode != 0:
957
- raise Exception(result.stderr or result.stdout)
958
-
959
- return None
960
- except Exception as e:
961
- error_msg = f"Execution error: {str(e)}"
962
- console.print(error_msg, style="error")
963
- return error_msg
964
-
965
- result = self._execute_with_retry(code, ai_instance)
966
- return result
967
-
968
- @property
969
- def intro_prompt(self) -> str:
970
- """Get the introduction prompt.
971
-
972
- Returns:
973
- str: Introduction prompt
974
- """
975
- return get_intro_prompt()
976
-
977
- def log(self, message: str, category: str = "info"):
978
- """RawDog logger
979
-
980
- Args:
981
- message (str): Log message
982
- category (str, optional): Log level. Defaults to 'info'.
983
- """
984
- if self.quiet:
985
- return
986
-
987
- message = "[Webscout] - " + message
988
- if category == "error":
989
- console.print(f"[ERROR] {message}", style="error")
990
- else:
991
- console.print(message, style=category)
992
-
993
- def stdout(self, message: str, style: str = "info") -> None:
994
- """Enhanced stdout with Rich formatting.
995
-
996
- Args:
997
- message (str): Text to be printed
998
- style (str, optional): Style to apply. Defaults to "info".
999
- """
1000
- if not self.prettify:
1001
- print(message)
1002
- return
1003
-
1004
- if message.startswith("```") and message.endswith("```"):
1005
- # Handle code blocks
1006
- code = message.strip("`").strip()
1007
- syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
1008
- console.print(Panel(syntax, title="Code", border_style="blue"))
1009
- elif "```python" in message:
1010
- # Handle markdown code blocks
1011
- md = Markdown(message)
1012
- console.print(md)
1013
- else:
1014
- # Handle regular text with optional styling
1015
- console.print(message, style=style)
1016
-
1017
- def print_code(self, code: str, title: str = "Generated Code") -> None:
1018
- """Print code with syntax highlighting and panel.
1019
-
1020
- Args:
1021
- code (str): Code to print
1022
- title (str, optional): Panel title. Defaults to "Generated Code".
1023
- """
1024
- if self.prettify:
1025
- syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
1026
- console.print(Panel(
1027
- syntax,
1028
- title=f"[bold blue]In [1]:[/bold blue]",
1029
- border_style="blue",
1030
- expand=True,
1031
- box=ROUNDED
1032
- ))
1033
- else:
1034
- print(f"\n{title}:")
1035
- print(code)
1036
-
1037
- def print_output(self, output: str, style: str = "output") -> None:
1038
- """Print command output with optional styling.
1039
-
1040
- Args:
1041
- output (str): Output to print
1042
- style (str, optional): Style to apply. Defaults to "output".
1043
- """
1044
- if self.prettify:
1045
- # Try to detect if output is Python code
1046
- try:
1047
- # If it looks like Python code, syntax highlight it
1048
- compile(output, '<string>', 'exec')
1049
- syntax = Syntax(output, "python", theme="monokai", line_numbers=False)
1050
- formatted_output = syntax
1051
- except SyntaxError:
1052
- # If not Python code, treat as plain text
1053
- formatted_output = output
1054
-
1055
- # Use the style parameter for the panel border
1056
- console.print(Panel(
1057
- formatted_output,
1058
- title="[bold red]Out [1]:[/bold red]",
1059
- border_style=style if style != "output" else "red",
1060
- expand=True,
1061
- padding=(0, 1),
1062
- box=ROUNDED
1063
- ))
1064
- else:
1065
- print("\nOutput:")
1066
- print(output)
1067
-
1068
- def print_error(self, error: str) -> None:
1069
- """Print error message with styling.
1070
-
1071
- Args:
1072
- error (str): Error message to print
1073
- """
1074
- if self.prettify:
1075
- console.print(f"\n Error:", style="error bold")
1076
- console.print(error, style="error")
1077
- else:
1078
- print("\nError:")
1079
- print(error)
1080
-
1081
- def print_table(self, headers: list, rows: list) -> None:
1082
- """Print data in a formatted table.
1083
-
1084
- Args:
1085
- headers (list): Table headers
1086
- rows (list): Table rows
1087
- """
1088
- if not self.prettify:
1089
- # Simple ASCII table
1090
- print("\n" + "-" * 80)
1091
- print("| " + " | ".join(headers) + " |")
1092
- print("-" * 80)
1093
- for row in rows:
1094
- print("| " + " | ".join(str(cell) for cell in row) + " |")
1095
- print("-" * 80)
1096
- return
1097
-
1098
- table = Table(show_header=True, header_style="bold cyan")
1099
- for header in headers:
1100
- table.add_column(header)
1101
-
1102
- for row in rows:
1103
- table.add_row(*[str(cell) for cell in row])
1104
-
1105
- console.print(table)