webscout 8.2.2__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 (483) hide show
  1. webscout/AIauto.py +524 -143
  2. webscout/AIbase.py +247 -123
  3. webscout/AIutel.py +68 -132
  4. webscout/Bard.py +1072 -535
  5. webscout/Extra/GitToolkit/__init__.py +2 -2
  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 -0
  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 -0
  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 -45
  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 +189 -18
  35. webscout/Extra/__init__.py +2 -3
  36. webscout/Extra/gguf.py +1298 -682
  37. webscout/Extra/tempmail/README.md +488 -0
  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 +237 -304
  49. webscout/Provider/AISEARCH/README.md +106 -0
  50. webscout/Provider/AISEARCH/__init__.py +16 -10
  51. webscout/Provider/AISEARCH/brave_search.py +298 -0
  52. webscout/Provider/AISEARCH/iask_search.py +130 -209
  53. webscout/Provider/AISEARCH/monica_search.py +200 -246
  54. webscout/Provider/AISEARCH/webpilotai_search.py +242 -281
  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 -0
  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 +343 -173
  64. webscout/Provider/EssentialAI.py +217 -0
  65. webscout/Provider/ExaAI.py +274 -261
  66. webscout/Provider/Gemini.py +60 -54
  67. webscout/Provider/GithubChat.py +385 -367
  68. webscout/Provider/Gradient.py +286 -0
  69. webscout/Provider/Groq.py +556 -670
  70. webscout/Provider/HadadXYZ.py +323 -0
  71. webscout/Provider/HeckAI.py +392 -233
  72. webscout/Provider/HuggingFace.py +387 -0
  73. webscout/Provider/IBM.py +340 -0
  74. webscout/Provider/Jadve.py +317 -266
  75. webscout/Provider/K2Think.py +306 -0
  76. webscout/Provider/Koboldai.py +221 -381
  77. webscout/Provider/Netwrck.py +273 -228
  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 -0
  83. webscout/Provider/OPENAI/TogetherAI.py +405 -0
  84. webscout/Provider/OPENAI/TwoAI.py +255 -0
  85. webscout/Provider/OPENAI/__init__.py +148 -25
  86. webscout/Provider/OPENAI/ai4chat.py +348 -0
  87. webscout/Provider/OPENAI/akashgpt.py +436 -0
  88. webscout/Provider/OPENAI/algion.py +303 -0
  89. webscout/Provider/OPENAI/ayle.py +365 -0
  90. webscout/Provider/OPENAI/base.py +253 -46
  91. webscout/Provider/OPENAI/cerebras.py +296 -0
  92. webscout/Provider/OPENAI/chatgpt.py +514 -193
  93. webscout/Provider/OPENAI/chatsandbox.py +233 -0
  94. webscout/Provider/OPENAI/deepinfra.py +403 -272
  95. webscout/Provider/OPENAI/e2b.py +2370 -1350
  96. webscout/Provider/OPENAI/elmo.py +278 -0
  97. webscout/Provider/OPENAI/exaai.py +186 -138
  98. webscout/Provider/OPENAI/freeassist.py +446 -0
  99. webscout/Provider/OPENAI/gradient.py +448 -0
  100. webscout/Provider/OPENAI/groq.py +380 -0
  101. webscout/Provider/OPENAI/hadadxyz.py +292 -0
  102. webscout/Provider/OPENAI/heckai.py +100 -104
  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 -327
  107. webscout/Provider/OPENAI/meta.py +541 -0
  108. webscout/Provider/OPENAI/netwrck.py +110 -84
  109. webscout/Provider/OPENAI/nvidia.py +317 -0
  110. webscout/Provider/OPENAI/oivscode.py +348 -0
  111. webscout/Provider/OPENAI/openrouter.py +328 -0
  112. webscout/Provider/OPENAI/pydantic_imports.py +1 -0
  113. webscout/Provider/OPENAI/sambanova.py +397 -0
  114. webscout/Provider/OPENAI/sonus.py +126 -115
  115. webscout/Provider/OPENAI/textpollinations.py +218 -133
  116. webscout/Provider/OPENAI/toolbaz.py +136 -166
  117. webscout/Provider/OPENAI/typefully.py +419 -0
  118. webscout/Provider/OPENAI/typliai.py +279 -0
  119. webscout/Provider/OPENAI/utils.py +314 -211
  120. webscout/Provider/OPENAI/wisecat.py +103 -125
  121. webscout/Provider/OPENAI/writecream.py +185 -156
  122. webscout/Provider/OPENAI/x0gpt.py +227 -136
  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 -344
  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 -0
  133. webscout/Provider/TTI/__init__.py +37 -12
  134. webscout/Provider/TTI/base.py +147 -0
  135. webscout/Provider/TTI/claudeonline.py +393 -0
  136. webscout/Provider/TTI/magicstudio.py +292 -0
  137. webscout/Provider/TTI/miragic.py +180 -0
  138. webscout/Provider/TTI/pollinations.py +331 -0
  139. webscout/Provider/TTI/together.py +334 -0
  140. webscout/Provider/TTI/utils.py +14 -0
  141. webscout/Provider/TTS/README.md +186 -0
  142. webscout/Provider/TTS/__init__.py +43 -7
  143. webscout/Provider/TTS/base.py +523 -0
  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 -0
  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 -180
  153. webscout/Provider/TTS/streamElements.py +275 -333
  154. webscout/Provider/TTS/utils.py +280 -280
  155. webscout/Provider/TextPollinationsAI.py +221 -121
  156. webscout/Provider/TogetherAI.py +450 -0
  157. webscout/Provider/TwoAI.py +309 -199
  158. webscout/Provider/TypliAI.py +311 -0
  159. webscout/Provider/UNFINISHED/ChatHub.py +219 -0
  160. webscout/Provider/{OPENAI/glider.py → UNFINISHED/ChutesAI.py} +160 -145
  161. webscout/Provider/UNFINISHED/GizAI.py +300 -0
  162. webscout/Provider/UNFINISHED/Marcus.py +218 -0
  163. webscout/Provider/UNFINISHED/Qodo.py +481 -0
  164. webscout/Provider/UNFINISHED/XenAI.py +330 -0
  165. webscout/Provider/{Youchat.py → UNFINISHED/Youchat.py} +64 -47
  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 -0
  170. webscout/Provider/UNFINISHED/samurai.py +231 -0
  171. webscout/Provider/WiseCat.py +256 -196
  172. webscout/Provider/WrDoChat.py +390 -0
  173. webscout/Provider/__init__.py +115 -198
  174. webscout/Provider/ai4chat.py +181 -202
  175. webscout/Provider/akashgpt.py +330 -342
  176. webscout/Provider/cerebras.py +397 -242
  177. webscout/Provider/cleeai.py +236 -213
  178. webscout/Provider/elmo.py +291 -234
  179. webscout/Provider/geminiapi.py +343 -208
  180. webscout/Provider/julius.py +245 -223
  181. webscout/Provider/learnfastai.py +333 -266
  182. webscout/Provider/llama3mitril.py +230 -180
  183. webscout/Provider/llmchat.py +308 -213
  184. webscout/Provider/llmchatco.py +321 -311
  185. webscout/Provider/meta.py +996 -794
  186. webscout/Provider/oivscode.py +332 -0
  187. webscout/Provider/searchchat.py +316 -293
  188. webscout/Provider/sonus.py +264 -208
  189. webscout/Provider/toolbaz.py +359 -320
  190. webscout/Provider/turboseek.py +332 -219
  191. webscout/Provider/typefully.py +262 -280
  192. webscout/Provider/x0gpt.py +332 -256
  193. webscout/__init__.py +31 -38
  194. webscout/__main__.py +5 -5
  195. webscout/cli.py +585 -293
  196. webscout/client.py +1497 -0
  197. webscout/conversation.py +140 -565
  198. webscout/exceptions.py +383 -339
  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 +32 -378
  204. webscout/prompt_manager.py +376 -274
  205. webscout/sanitize.py +1514 -0
  206. webscout/scout/README.md +452 -0
  207. webscout/scout/__init__.py +8 -8
  208. webscout/scout/core/__init__.py +7 -7
  209. webscout/scout/core/crawler.py +330 -140
  210. webscout/scout/core/scout.py +800 -568
  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 -460
  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 -809
  284. webscout/swiftcli/core/__init__.py +7 -0
  285. webscout/swiftcli/core/cli.py +574 -0
  286. webscout/swiftcli/core/context.py +98 -0
  287. webscout/swiftcli/core/group.py +268 -0
  288. webscout/swiftcli/decorators/__init__.py +28 -0
  289. webscout/swiftcli/decorators/command.py +243 -0
  290. webscout/swiftcli/decorators/options.py +247 -0
  291. webscout/swiftcli/decorators/output.py +392 -0
  292. webscout/swiftcli/exceptions.py +21 -0
  293. webscout/swiftcli/plugins/__init__.py +9 -0
  294. webscout/swiftcli/plugins/base.py +134 -0
  295. webscout/swiftcli/plugins/manager.py +269 -0
  296. webscout/swiftcli/utils/__init__.py +58 -0
  297. webscout/swiftcli/utils/formatting.py +251 -0
  298. webscout/swiftcli/utils/parsing.py +368 -0
  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 -55
  304. webscout/zeroart/base.py +70 -60
  305. webscout/zeroart/effects.py +155 -99
  306. webscout/zeroart/fonts.py +1799 -816
  307. webscout-2026.1.19.dist-info/METADATA +638 -0
  308. webscout-2026.1.19.dist-info/RECORD +312 -0
  309. {webscout-8.2.2.dist-info → webscout-2026.1.19.dist-info}/WHEEL +1 -1
  310. webscout-2026.1.19.dist-info/entry_points.txt +4 -0
  311. webscout-2026.1.19.dist-info/top_level.txt +1 -0
  312. inferno/__init__.py +0 -6
  313. inferno/__main__.py +0 -9
  314. inferno/cli.py +0 -6
  315. webscout/DWEBS.py +0 -477
  316. webscout/Extra/autocoder/__init__.py +0 -9
  317. webscout/Extra/autocoder/autocoder.py +0 -849
  318. webscout/Extra/autocoder/autocoder_utiles.py +0 -332
  319. webscout/LLM.py +0 -442
  320. webscout/Litlogger/__init__.py +0 -67
  321. webscout/Litlogger/core/__init__.py +0 -6
  322. webscout/Litlogger/core/level.py +0 -23
  323. webscout/Litlogger/core/logger.py +0 -165
  324. webscout/Litlogger/handlers/__init__.py +0 -12
  325. webscout/Litlogger/handlers/console.py +0 -33
  326. webscout/Litlogger/handlers/file.py +0 -143
  327. webscout/Litlogger/handlers/network.py +0 -173
  328. webscout/Litlogger/styles/__init__.py +0 -7
  329. webscout/Litlogger/styles/colors.py +0 -249
  330. webscout/Litlogger/styles/formats.py +0 -458
  331. webscout/Litlogger/styles/text.py +0 -87
  332. webscout/Litlogger/utils/__init__.py +0 -6
  333. webscout/Litlogger/utils/detectors.py +0 -153
  334. webscout/Litlogger/utils/formatters.py +0 -200
  335. webscout/Local/__init__.py +0 -12
  336. webscout/Local/__main__.py +0 -9
  337. webscout/Local/api.py +0 -576
  338. webscout/Local/cli.py +0 -516
  339. webscout/Local/config.py +0 -75
  340. webscout/Local/llm.py +0 -287
  341. webscout/Local/model_manager.py +0 -253
  342. webscout/Local/server.py +0 -721
  343. webscout/Local/utils.py +0 -93
  344. webscout/Provider/AI21.py +0 -177
  345. webscout/Provider/AISEARCH/DeepFind.py +0 -250
  346. webscout/Provider/AISEARCH/ISou.py +0 -256
  347. webscout/Provider/AISEARCH/felo_search.py +0 -228
  348. webscout/Provider/AISEARCH/genspark_search.py +0 -208
  349. webscout/Provider/AISEARCH/hika_search.py +0 -194
  350. webscout/Provider/AISEARCH/scira_search.py +0 -324
  351. webscout/Provider/Aitopia.py +0 -292
  352. webscout/Provider/AllenAI.py +0 -413
  353. webscout/Provider/Blackboxai.py +0 -229
  354. webscout/Provider/C4ai.py +0 -432
  355. webscout/Provider/ChatGPTClone.py +0 -226
  356. webscout/Provider/ChatGPTES.py +0 -237
  357. webscout/Provider/ChatGPTGratis.py +0 -194
  358. webscout/Provider/Chatify.py +0 -175
  359. webscout/Provider/Cloudflare.py +0 -273
  360. webscout/Provider/DeepSeek.py +0 -196
  361. webscout/Provider/ElectronHub.py +0 -709
  362. webscout/Provider/ExaChat.py +0 -342
  363. webscout/Provider/Free2GPT.py +0 -241
  364. webscout/Provider/GPTWeb.py +0 -193
  365. webscout/Provider/Glider.py +0 -211
  366. webscout/Provider/HF_space/__init__.py +0 -0
  367. webscout/Provider/HF_space/qwen_qwen2.py +0 -206
  368. webscout/Provider/HuggingFaceChat.py +0 -462
  369. webscout/Provider/Hunyuan.py +0 -272
  370. webscout/Provider/LambdaChat.py +0 -392
  371. webscout/Provider/Llama.py +0 -200
  372. webscout/Provider/Llama3.py +0 -204
  373. webscout/Provider/Marcus.py +0 -148
  374. webscout/Provider/OLLAMA.py +0 -396
  375. webscout/Provider/OPENAI/c4ai.py +0 -367
  376. webscout/Provider/OPENAI/chatgptclone.py +0 -460
  377. webscout/Provider/OPENAI/exachat.py +0 -433
  378. webscout/Provider/OPENAI/freeaichat.py +0 -352
  379. webscout/Provider/OPENAI/opkfc.py +0 -488
  380. webscout/Provider/OPENAI/scirachat.py +0 -463
  381. webscout/Provider/OPENAI/standardinput.py +0 -425
  382. webscout/Provider/OPENAI/typegpt.py +0 -346
  383. webscout/Provider/OPENAI/uncovrAI.py +0 -455
  384. webscout/Provider/OPENAI/venice.py +0 -413
  385. webscout/Provider/OPENAI/yep.py +0 -327
  386. webscout/Provider/OpenGPT.py +0 -199
  387. webscout/Provider/Perplexitylabs.py +0 -415
  388. webscout/Provider/Phind.py +0 -535
  389. webscout/Provider/PizzaGPT.py +0 -198
  390. webscout/Provider/Reka.py +0 -214
  391. webscout/Provider/StandardInput.py +0 -278
  392. webscout/Provider/TTI/AiForce/__init__.py +0 -22
  393. webscout/Provider/TTI/AiForce/async_aiforce.py +0 -224
  394. webscout/Provider/TTI/AiForce/sync_aiforce.py +0 -245
  395. webscout/Provider/TTI/FreeAIPlayground/__init__.py +0 -9
  396. webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +0 -181
  397. webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +0 -180
  398. webscout/Provider/TTI/ImgSys/__init__.py +0 -23
  399. webscout/Provider/TTI/ImgSys/async_imgsys.py +0 -202
  400. webscout/Provider/TTI/ImgSys/sync_imgsys.py +0 -195
  401. webscout/Provider/TTI/MagicStudio/__init__.py +0 -2
  402. webscout/Provider/TTI/MagicStudio/async_magicstudio.py +0 -111
  403. webscout/Provider/TTI/MagicStudio/sync_magicstudio.py +0 -109
  404. webscout/Provider/TTI/Nexra/__init__.py +0 -22
  405. webscout/Provider/TTI/Nexra/async_nexra.py +0 -286
  406. webscout/Provider/TTI/Nexra/sync_nexra.py +0 -258
  407. webscout/Provider/TTI/PollinationsAI/__init__.py +0 -23
  408. webscout/Provider/TTI/PollinationsAI/async_pollinations.py +0 -311
  409. webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +0 -265
  410. webscout/Provider/TTI/aiarta/__init__.py +0 -2
  411. webscout/Provider/TTI/aiarta/async_aiarta.py +0 -482
  412. webscout/Provider/TTI/aiarta/sync_aiarta.py +0 -440
  413. webscout/Provider/TTI/artbit/__init__.py +0 -22
  414. webscout/Provider/TTI/artbit/async_artbit.py +0 -155
  415. webscout/Provider/TTI/artbit/sync_artbit.py +0 -148
  416. webscout/Provider/TTI/fastflux/__init__.py +0 -22
  417. webscout/Provider/TTI/fastflux/async_fastflux.py +0 -261
  418. webscout/Provider/TTI/fastflux/sync_fastflux.py +0 -252
  419. webscout/Provider/TTI/huggingface/__init__.py +0 -22
  420. webscout/Provider/TTI/huggingface/async_huggingface.py +0 -199
  421. webscout/Provider/TTI/huggingface/sync_huggingface.py +0 -195
  422. webscout/Provider/TTI/piclumen/__init__.py +0 -23
  423. webscout/Provider/TTI/piclumen/async_piclumen.py +0 -268
  424. webscout/Provider/TTI/piclumen/sync_piclumen.py +0 -233
  425. webscout/Provider/TTI/pixelmuse/__init__.py +0 -4
  426. webscout/Provider/TTI/pixelmuse/async_pixelmuse.py +0 -249
  427. webscout/Provider/TTI/pixelmuse/sync_pixelmuse.py +0 -182
  428. webscout/Provider/TTI/talkai/__init__.py +0 -4
  429. webscout/Provider/TTI/talkai/async_talkai.py +0 -229
  430. webscout/Provider/TTI/talkai/sync_talkai.py +0 -207
  431. webscout/Provider/TTS/gesserit.py +0 -127
  432. webscout/Provider/TeachAnything.py +0 -187
  433. webscout/Provider/Venice.py +0 -219
  434. webscout/Provider/VercelAI.py +0 -234
  435. webscout/Provider/WebSim.py +0 -228
  436. webscout/Provider/Writecream.py +0 -211
  437. webscout/Provider/WritingMate.py +0 -197
  438. webscout/Provider/aimathgpt.py +0 -189
  439. webscout/Provider/askmyai.py +0 -158
  440. webscout/Provider/asksteve.py +0 -203
  441. webscout/Provider/bagoodex.py +0 -145
  442. webscout/Provider/chatglm.py +0 -205
  443. webscout/Provider/copilot.py +0 -428
  444. webscout/Provider/freeaichat.py +0 -271
  445. webscout/Provider/gaurish.py +0 -244
  446. webscout/Provider/geminiprorealtime.py +0 -160
  447. webscout/Provider/granite.py +0 -187
  448. webscout/Provider/hermes.py +0 -219
  449. webscout/Provider/koala.py +0 -268
  450. webscout/Provider/labyrinth.py +0 -340
  451. webscout/Provider/lepton.py +0 -194
  452. webscout/Provider/llamatutor.py +0 -192
  453. webscout/Provider/multichat.py +0 -325
  454. webscout/Provider/promptrefine.py +0 -193
  455. webscout/Provider/scira_chat.py +0 -277
  456. webscout/Provider/scnet.py +0 -187
  457. webscout/Provider/talkai.py +0 -194
  458. webscout/Provider/tutorai.py +0 -252
  459. webscout/Provider/typegpt.py +0 -232
  460. webscout/Provider/uncovr.py +0 -312
  461. webscout/Provider/yep.py +0 -376
  462. webscout/litprinter/__init__.py +0 -59
  463. webscout/scout/core.py +0 -881
  464. webscout/tempid.py +0 -128
  465. webscout/webscout_search.py +0 -1346
  466. webscout/webscout_search_async.py +0 -877
  467. webscout/yep_search.py +0 -297
  468. webscout-8.2.2.dist-info/METADATA +0 -734
  469. webscout-8.2.2.dist-info/RECORD +0 -309
  470. webscout-8.2.2.dist-info/entry_points.txt +0 -5
  471. webscout-8.2.2.dist-info/top_level.txt +0 -3
  472. webstoken/__init__.py +0 -30
  473. webstoken/classifier.py +0 -189
  474. webstoken/keywords.py +0 -216
  475. webstoken/language.py +0 -128
  476. webstoken/ner.py +0 -164
  477. webstoken/normalizer.py +0 -35
  478. webstoken/processor.py +0 -77
  479. webstoken/sentiment.py +0 -206
  480. webstoken/stemmer.py +0 -73
  481. webstoken/tagger.py +0 -60
  482. webstoken/tokenizer.py +0 -158
  483. {webscout-8.2.2.dist-info → webscout-2026.1.19.dist-info/licenses}/LICENSE.md +0 -0
@@ -0,0 +1,134 @@
1
+ """Base plugin system for SwiftCLI."""
2
+
3
+ from typing import Any, Dict, List, Optional
4
+
5
+
6
+ class Plugin:
7
+ """
8
+ Base class for SwiftCLI plugins.
9
+
10
+ Plugins can extend the CLI functionality by hooking into various stages
11
+ of command execution. Subclass this class and override the methods
12
+ you want to hook into.
13
+
14
+ Attributes:
15
+ app: The CLI application instance
16
+ enabled: Whether the plugin is enabled
17
+ config: Plugin configuration dictionary
18
+
19
+ Example:
20
+ class LoggingPlugin(Plugin):
21
+ def before_command(self, command, args):
22
+ print(f"[LOG] Running command: {command}")
23
+
24
+ def after_command(self, command, args, result):
25
+ print(f"[LOG] Command completed: {result}")
26
+ """
27
+
28
+ def __init__(self):
29
+ self.app = None # Set by plugin manager
30
+ self.enabled: bool = True
31
+ self.config: Dict[str, Any] = {}
32
+
33
+ def init_app(self, app: Any) -> None:
34
+ """
35
+ Initialize plugin with CLI app instance.
36
+
37
+ Args:
38
+ app: The CLI application instance
39
+ """
40
+ self.app = app
41
+
42
+ def before_command(self, command: str, args: List[str]) -> Optional[bool]:
43
+ """
44
+ Called before command execution.
45
+
46
+ Args:
47
+ command: Command name
48
+ args: Command arguments
49
+
50
+ Returns:
51
+ Optional[bool]: Return False to prevent command execution
52
+ """
53
+ pass
54
+
55
+ def after_command(self, command: str, args: List[str], result: Any) -> None:
56
+ """
57
+ Called after command execution.
58
+
59
+ Args:
60
+ command: Command name
61
+ args: Command arguments
62
+ result: Command result
63
+ """
64
+ pass
65
+
66
+ def on_error(self, command: str, error: Exception) -> None:
67
+ """
68
+ Called when command raises an error.
69
+
70
+ Args:
71
+ command: Command name
72
+ error: The exception that was raised
73
+ """
74
+ pass
75
+
76
+ def on_help(self, command: str) -> Optional[str]:
77
+ """
78
+ Called when help is requested for a command.
79
+
80
+ Args:
81
+ command: Command name
82
+
83
+ Returns:
84
+ Optional[str]: Additional help text to display
85
+ """
86
+ pass
87
+
88
+ def on_completion(self, command: str, incomplete: str) -> List[str]:
89
+ """
90
+ Called when shell completion is requested.
91
+
92
+ Args:
93
+ command: Command name
94
+ incomplete: Incomplete text to complete
95
+
96
+ Returns:
97
+ List[str]: Possible completions
98
+ """
99
+ return []
100
+
101
+ def configure(self, config: Dict[str, Any]) -> None:
102
+ """
103
+ Configure the plugin.
104
+
105
+ Args:
106
+ config: Configuration dictionary
107
+ """
108
+ self.config.update(config)
109
+
110
+ def validate_config(self) -> None:
111
+ """
112
+ Validate plugin configuration.
113
+
114
+ Raises:
115
+ PluginError: If configuration is invalid
116
+ """
117
+ pass
118
+
119
+ def enable(self) -> None:
120
+ """Enable the plugin."""
121
+ self.enabled = True
122
+
123
+ def disable(self) -> None:
124
+ """Disable the plugin."""
125
+ self.enabled = False
126
+
127
+ @property
128
+ def name(self) -> str:
129
+ """Get plugin name."""
130
+ return self.__class__.__name__
131
+
132
+ def __repr__(self) -> str:
133
+ status = "enabled" if self.enabled else "disabled"
134
+ return f"<{self.name} [{status}]>"
@@ -0,0 +1,269 @@
1
+ """Plugin manager for SwiftCLI."""
2
+
3
+ import importlib
4
+ import os
5
+ import sys
6
+ import tempfile
7
+ from pathlib import Path
8
+ from typing import Any, Dict, List, Optional
9
+
10
+ from rich.console import Console
11
+
12
+ from ..exceptions import PluginError
13
+ from .base import Plugin
14
+
15
+ console = Console()
16
+
17
+ class PluginManager:
18
+ """
19
+ Manages SwiftCLI plugins.
20
+
21
+ The plugin manager handles plugin registration, loading, and execution.
22
+ It provides hooks for plugins to extend CLI functionality at various points
23
+ during command execution.
24
+
25
+ Attributes:
26
+ plugins: List of registered plugins
27
+ plugin_dir: Directory where plugins are stored
28
+
29
+ Example:
30
+ # Register a plugin
31
+ plugin_manager = PluginManager()
32
+ plugin_manager.register(LoggingPlugin())
33
+
34
+ # Load plugins from directory
35
+ plugin_manager.load_plugins()
36
+ """
37
+
38
+ def __init__(self, plugin_dir: Optional[str] = None):
39
+ """
40
+ Initialize plugin manager.
41
+
42
+ Args:
43
+ plugin_dir: Optional custom plugin directory path
44
+ """
45
+ self.plugins: List[Plugin] = []
46
+ # Use temporary directory instead of ~/.swiftcli/plugins
47
+ if plugin_dir:
48
+ self.plugin_dir = plugin_dir
49
+ os.makedirs(self.plugin_dir, exist_ok=True)
50
+ else:
51
+ # Create a temporary directory that will be cleaned up when the process exits
52
+ self.temp_dir = tempfile.TemporaryDirectory(prefix="swiftcli_")
53
+ self.plugin_dir = self.temp_dir.name
54
+
55
+ # Add plugin directory to Python path
56
+ if self.plugin_dir not in sys.path:
57
+ sys.path.append(self.plugin_dir)
58
+
59
+ def register(self, plugin: Plugin) -> None:
60
+ """
61
+ Register a new plugin.
62
+
63
+ Args:
64
+ plugin: Plugin instance to register
65
+
66
+ Raises:
67
+ PluginError: If plugin is invalid or already registered
68
+ """
69
+ if not isinstance(plugin, Plugin):
70
+ raise PluginError(f"Invalid plugin type: {type(plugin)}")
71
+
72
+ if self._get_plugin(plugin.name):
73
+ raise PluginError(f"Plugin already registered: {plugin.name}")
74
+
75
+ try:
76
+ plugin.validate_config()
77
+ except Exception as e:
78
+ raise PluginError(f"Plugin configuration invalid: {str(e)}")
79
+
80
+ self.plugins.append(plugin)
81
+
82
+ def unregister(self, plugin_name: str) -> None:
83
+ """
84
+ Unregister a plugin.
85
+
86
+ Args:
87
+ plugin_name: Name of plugin to unregister
88
+
89
+ Raises:
90
+ PluginError: If plugin not found
91
+ """
92
+ plugin = self._get_plugin(plugin_name)
93
+ if not plugin:
94
+ raise PluginError(f"Plugin not found: {plugin_name}")
95
+
96
+ self.plugins.remove(plugin)
97
+
98
+ def load_plugins(self) -> None:
99
+ """
100
+ Load all plugins from plugin directory.
101
+
102
+ This method searches for Python files in the plugin directory and
103
+ attempts to load any Plugin subclasses defined in them.
104
+ """
105
+ for file in Path(self.plugin_dir).glob("*.py"):
106
+ if file.name.startswith("_"):
107
+ continue
108
+
109
+ try:
110
+ module = importlib.import_module(file.stem)
111
+
112
+ # Find Plugin subclasses in module
113
+ for attr_name in dir(module):
114
+ attr = getattr(module, attr_name)
115
+ if (isinstance(attr, type) and
116
+ issubclass(attr, Plugin) and
117
+ attr is not Plugin):
118
+ plugin = attr()
119
+ self.register(plugin)
120
+
121
+ except Exception as e:
122
+ console.print(f"[red]Error loading plugin {file.name}: {e}[/red]")
123
+
124
+ def init_plugins(self, app: Any) -> None:
125
+ """
126
+ Initialize all plugins with the CLI application instance.
127
+
128
+ Args:
129
+ app: The CLI application instance
130
+ """
131
+ for plugin in self.plugins:
132
+ plugin.init_app(app)
133
+
134
+ def configure_plugins(self, config: Dict[str, Dict[str, Any]]) -> None:
135
+ """
136
+ Configure plugins with provided configuration.
137
+
138
+ Args:
139
+ config: Dictionary of plugin configurations
140
+ """
141
+ for plugin in self.plugins:
142
+ if plugin.name in config:
143
+ plugin.configure(config[plugin.name])
144
+
145
+ def before_command(self, command: str, args: List[str]) -> bool:
146
+ """
147
+ Run before_command hooks for all plugins.
148
+
149
+ Args:
150
+ command: Command name
151
+ args: Command arguments
152
+
153
+ Returns:
154
+ bool: False if any plugin prevents command execution
155
+ """
156
+ for plugin in self.plugins:
157
+ if not plugin.enabled:
158
+ continue
159
+
160
+ try:
161
+ result = plugin.before_command(command, args)
162
+ if result is False:
163
+ return False
164
+ except Exception as e:
165
+ console.print(f"[red]Error in plugin {plugin.name}: {e}[/red]")
166
+ if plugin.app and getattr(plugin.app, 'debug', False):
167
+ import traceback
168
+ traceback.print_exc()
169
+
170
+ return True
171
+
172
+ def after_command(self, command: str, args: List[str], result: Any) -> None:
173
+ """
174
+ Run after_command hooks for all plugins.
175
+
176
+ Args:
177
+ command: Command name
178
+ args: Command arguments
179
+ result: Command result
180
+ """
181
+ for plugin in self.plugins:
182
+ if not plugin.enabled:
183
+ continue
184
+
185
+ try:
186
+ plugin.after_command(command, args, result)
187
+ except Exception as e:
188
+ console.print(f"[red]Error in plugin {plugin.name}: {e}[/red]")
189
+ if plugin.app and getattr(plugin.app, 'debug', False):
190
+ import traceback
191
+ traceback.print_exc()
192
+
193
+ def on_error(self, command: str, error: Exception) -> None:
194
+ """
195
+ Run error hooks for all plugins.
196
+
197
+ Args:
198
+ command: Command name
199
+ error: The exception that was raised
200
+ """
201
+ for plugin in self.plugins:
202
+ if not plugin.enabled:
203
+ continue
204
+
205
+ try:
206
+ plugin.on_error(command, error)
207
+ except Exception as e:
208
+ console.print(f"[red]Error in plugin {plugin.name}: {e}[/red]")
209
+ if plugin.app and getattr(plugin.app, 'debug', False):
210
+ import traceback
211
+ traceback.print_exc()
212
+
213
+ def get_help_text(self, command: str) -> List[str]:
214
+ """
215
+ Get additional help text from plugins.
216
+
217
+ Args:
218
+ command: Command name
219
+
220
+ Returns:
221
+ List[str]: List of help text strings from plugins
222
+ """
223
+ help_texts = []
224
+ for plugin in self.plugins:
225
+ if not plugin.enabled:
226
+ continue
227
+
228
+ try:
229
+ help_text = plugin.on_help(command)
230
+ if help_text:
231
+ help_texts.append(help_text)
232
+ except Exception as e:
233
+ console.print(f"[red]Error in plugin {plugin.name}: {e}[/red]")
234
+
235
+ return help_texts
236
+
237
+ def get_completions(self, command: str, incomplete: str) -> List[str]:
238
+ """
239
+ Get command completions from plugins.
240
+
241
+ Args:
242
+ command: Command name
243
+ incomplete: Incomplete text to complete
244
+
245
+ Returns:
246
+ List[str]: Combined list of completions from all plugins
247
+ """
248
+ completions = []
249
+ for plugin in self.plugins:
250
+ if not plugin.enabled:
251
+ continue
252
+
253
+ try:
254
+ plugin_completions = plugin.on_completion(command, incomplete)
255
+ completions.extend(plugin_completions)
256
+ except Exception as e:
257
+ console.print(f"[red]Error in plugin {plugin.name}: {e}[/red]")
258
+
259
+ return list(set(completions)) # Remove duplicates
260
+
261
+ def _get_plugin(self, name: str) -> Optional[Plugin]:
262
+ """Get plugin by name."""
263
+ for plugin in self.plugins:
264
+ if plugin.name == name:
265
+ return plugin
266
+ return None
267
+
268
+ def __repr__(self) -> str:
269
+ return f"<PluginManager plugins={len(self.plugins)}>"
@@ -0,0 +1,58 @@
1
+ """Utility functions for SwiftCLI."""
2
+
3
+ from .formatting import (
4
+ clear_screen,
5
+ create_padding,
6
+ create_table,
7
+ format_dict,
8
+ format_error,
9
+ format_info,
10
+ format_list,
11
+ format_success,
12
+ format_warning,
13
+ get_terminal_size,
14
+ strip_ansi,
15
+ style_text,
16
+ truncate_text,
17
+ wrap_text,
18
+ )
19
+ from .parsing import (
20
+ convert_type,
21
+ get_env_var,
22
+ load_config_file,
23
+ parse_args,
24
+ parse_dict,
25
+ parse_key_value,
26
+ parse_list,
27
+ validate_choice,
28
+ validate_required,
29
+ )
30
+
31
+ __all__ = [
32
+ # Formatting utilities
33
+ 'style_text',
34
+ 'format_error',
35
+ 'format_warning',
36
+ 'format_success',
37
+ 'format_info',
38
+ 'create_table',
39
+ 'truncate_text',
40
+ 'wrap_text',
41
+ 'format_dict',
42
+ 'format_list',
43
+ 'strip_ansi',
44
+ 'get_terminal_size',
45
+ 'clear_screen',
46
+ 'create_padding',
47
+
48
+ # Parsing utilities
49
+ 'parse_args',
50
+ 'validate_required',
51
+ 'convert_type',
52
+ 'validate_choice',
53
+ 'load_config_file',
54
+ 'parse_key_value',
55
+ 'parse_list',
56
+ 'parse_dict',
57
+ 'get_env_var'
58
+ ]
@@ -0,0 +1,251 @@
1
+ """Utility functions for text formatting and styling."""
2
+
3
+ import re
4
+ from typing import Any, Dict, List, Optional, Union
5
+
6
+ from rich.console import Console
7
+ from rich.padding import Padding
8
+ from rich.table import Table
9
+ from rich.text import Text
10
+
11
+ console = Console()
12
+
13
+ def style_text(
14
+ text: str,
15
+ color: Optional[str] = None,
16
+ bold: bool = False,
17
+ italic: bool = False,
18
+ underline: bool = False
19
+ ) -> Text:
20
+ """
21
+ Apply styling to text.
22
+
23
+ Args:
24
+ text: Text to style
25
+ color: Text color
26
+ bold: Bold text
27
+ italic: Italic text
28
+ underline: Underline text
29
+
30
+ Returns:
31
+ Rich Text object with applied styling
32
+ """
33
+ style = []
34
+ if color:
35
+ style.append(color)
36
+ if bold:
37
+ style.append("bold")
38
+ if italic:
39
+ style.append("italic")
40
+ if underline:
41
+ style.append("underline")
42
+
43
+ return Text(text, style=" ".join(style))
44
+
45
+ def format_error(message: str, title: str = "Error") -> None:
46
+ """
47
+ Format and display error message.
48
+
49
+ Args:
50
+ message: Error message
51
+ title: Error title
52
+ """
53
+ console.print(f"[bold red]{title}:[/] {message}")
54
+
55
+ def format_warning(message: str, title: str = "Warning") -> None:
56
+ """
57
+ Format and display warning message.
58
+
59
+ Args:
60
+ message: Warning message
61
+ title: Warning title
62
+ """
63
+ console.print(f"[bold yellow]{title}:[/] {message}")
64
+
65
+ def format_success(message: str, title: str = "Success") -> None:
66
+ """
67
+ Format and display success message.
68
+
69
+ Args:
70
+ message: Success message
71
+ title: Success title
72
+ """
73
+ console.print(f"[bold green]{title}:[/] {message}")
74
+
75
+ def format_info(message: str, title: str = "Info") -> None:
76
+ """
77
+ Format and display info message.
78
+
79
+ Args:
80
+ message: Info message
81
+ title: Info title
82
+ """
83
+ console.print(f"[bold blue]{title}:[/] {message}")
84
+
85
+ def create_table(
86
+ headers: List[str],
87
+ rows: List[List[Any]],
88
+ title: Optional[str] = None,
89
+ style: str = "default",
90
+ show_lines: bool = False
91
+ ) -> Table:
92
+ """
93
+ Create a formatted table.
94
+
95
+ Args:
96
+ headers: Column headers
97
+ rows: Table rows
98
+ title: Table title
99
+ style: Table style
100
+ show_lines: Show row/column lines
101
+
102
+ Returns:
103
+ Rich Table object
104
+ """
105
+ table = Table(
106
+ title=title,
107
+ show_header=True,
108
+ header_style="bold blue",
109
+ show_lines=show_lines
110
+ )
111
+
112
+ # Add columns
113
+ for header in headers:
114
+ table.add_column(header)
115
+
116
+ # Add rows
117
+ for row in rows:
118
+ table.add_row(*[str(cell) for cell in row])
119
+
120
+ return table
121
+
122
+ def truncate_text(
123
+ text: str,
124
+ max_length: int,
125
+ suffix: str = "..."
126
+ ) -> str:
127
+ """
128
+ Truncate text to specified length.
129
+
130
+ Args:
131
+ text: Text to truncate
132
+ max_length: Maximum length
133
+ suffix: Truncation suffix
134
+
135
+ Returns:
136
+ Truncated text
137
+ """
138
+ if len(text) <= max_length:
139
+ return text
140
+ return text[:max_length - len(suffix)] + suffix
141
+
142
+ def wrap_text(
143
+ text: str,
144
+ width: int,
145
+ indent: str = "",
146
+ initial_indent: str = ""
147
+ ) -> str:
148
+ """
149
+ Wrap text to specified width.
150
+
151
+ Args:
152
+ text: Text to wrap
153
+ width: Maximum line width
154
+ indent: Indentation for wrapped lines
155
+ initial_indent: Indentation for first line
156
+
157
+ Returns:
158
+ Wrapped text
159
+ """
160
+ import textwrap
161
+ return textwrap.fill(
162
+ text,
163
+ width=width,
164
+ initial_indent=initial_indent,
165
+ subsequent_indent=indent
166
+ )
167
+
168
+ def format_dict(
169
+ data: Dict[str, Any],
170
+ indent: int = 2,
171
+ sort_keys: bool = True
172
+ ) -> str:
173
+ """
174
+ Format dictionary for display.
175
+
176
+ Args:
177
+ data: Dictionary to format
178
+ indent: Indentation level
179
+ sort_keys: Sort dictionary keys
180
+
181
+ Returns:
182
+ Formatted string
183
+ """
184
+ import json
185
+ return json.dumps(
186
+ data,
187
+ indent=indent,
188
+ sort_keys=sort_keys,
189
+ default=str
190
+ )
191
+
192
+ def format_list(
193
+ items: List[Any],
194
+ bullet: str = "•",
195
+ indent: int = 2
196
+ ) -> str:
197
+ """
198
+ Format list for display.
199
+
200
+ Args:
201
+ items: List to format
202
+ bullet: Bullet point character
203
+ indent: Indentation level
204
+
205
+ Returns:
206
+ Formatted string
207
+ """
208
+ indent_str = " " * indent
209
+ return "\n".join(f"{indent_str}{bullet} {item}" for item in items)
210
+
211
+ def strip_ansi(text: str) -> str:
212
+ """
213
+ Remove ANSI escape sequences from text.
214
+
215
+ Args:
216
+ text: Text containing ANSI sequences
217
+
218
+ Returns:
219
+ Clean text
220
+ """
221
+ ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
222
+ return ansi_escape.sub('', text)
223
+
224
+ def get_terminal_size() -> tuple:
225
+ """
226
+ Get terminal size.
227
+
228
+ Returns:
229
+ Tuple of (width, height)
230
+ """
231
+ return console.size
232
+
233
+ def clear_screen() -> None:
234
+ """Clear the terminal screen."""
235
+ console.clear()
236
+
237
+ def create_padding(
238
+ renderable: Any,
239
+ pad: Union[int, tuple] = 1
240
+ ) -> Padding:
241
+ """
242
+ Add padding around content.
243
+
244
+ Args:
245
+ renderable: Content to pad
246
+ pad: Padding amount
247
+
248
+ Returns:
249
+ Padded content
250
+ """
251
+ return Padding(renderable, pad)