webscout 6.4__py3-none-any.whl → 6.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of webscout might be problematic. Click here for more details.
- webscout/AIutel.py +7 -54
- webscout/DWEBS.py +48 -26
- webscout/{YTdownloader.py → Extra/YTToolkit/YTdownloader.py} +990 -1103
- webscout/Extra/YTToolkit/__init__.py +3 -0
- webscout/{transcriber.py → Extra/YTToolkit/transcriber.py} +1 -1
- webscout/Extra/YTToolkit/ytapi/__init__.py +6 -0
- webscout/Extra/YTToolkit/ytapi/channel.py +307 -0
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -0
- webscout/Extra/YTToolkit/ytapi/extras.py +45 -0
- webscout/Extra/YTToolkit/ytapi/https.py +88 -0
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -0
- webscout/Extra/YTToolkit/ytapi/playlist.py +59 -0
- webscout/Extra/YTToolkit/ytapi/pool.py +8 -0
- webscout/Extra/YTToolkit/ytapi/query.py +37 -0
- webscout/Extra/YTToolkit/ytapi/stream.py +60 -0
- webscout/Extra/YTToolkit/ytapi/utils.py +62 -0
- webscout/Extra/YTToolkit/ytapi/video.py +102 -0
- webscout/Extra/__init__.py +2 -1
- webscout/Extra/autocoder/autocoder_utiles.py +119 -101
- webscout/Extra/autocoder/rawdog.py +679 -680
- webscout/Extra/gguf.py +441 -441
- webscout/Extra/markdownlite/__init__.py +862 -0
- webscout/Extra/weather_ascii.py +2 -2
- webscout/Provider/AISEARCH/__init__.py +2 -0
- webscout/Provider/AISEARCH/ooai.py +155 -0
- webscout/Provider/Amigo.py +70 -85
- webscout/Provider/{prefind.py → Jadve.py} +72 -70
- webscout/Provider/Netwrck.py +235 -0
- webscout/Provider/Openai.py +4 -3
- webscout/Provider/PI.py +292 -221
- webscout/Provider/PizzaGPT.py +3 -3
- webscout/Provider/Reka.py +0 -1
- webscout/Provider/TTS/__init__.py +5 -1
- webscout/Provider/TTS/deepgram.py +183 -0
- webscout/Provider/TTS/elevenlabs.py +137 -0
- webscout/Provider/TTS/gesserit.py +151 -0
- webscout/Provider/TTS/murfai.py +139 -0
- webscout/Provider/TTS/parler.py +134 -107
- webscout/Provider/TTS/streamElements.py +360 -275
- webscout/Provider/TTS/utils.py +280 -0
- webscout/Provider/TTS/voicepod.py +116 -116
- webscout/Provider/TeachAnything.py +15 -2
- webscout/Provider/Youchat.py +42 -8
- webscout/Provider/__init__.py +8 -21
- webscout/Provider/meta.py +794 -779
- webscout/Provider/multichat.py +230 -0
- webscout/Provider/promptrefine.py +2 -2
- webscout/Provider/talkai.py +10 -13
- webscout/Provider/turboseek.py +5 -4
- webscout/Provider/tutorai.py +8 -112
- webscout/Provider/typegpt.py +5 -7
- webscout/Provider/x0gpt.py +81 -9
- webscout/Provider/yep.py +123 -361
- webscout/__init__.py +33 -28
- webscout/conversation.py +24 -9
- webscout/exceptions.py +188 -20
- webscout/litprinter/__init__.py +719 -831
- webscout/litprinter/colors.py +54 -0
- webscout/optimizers.py +420 -270
- webscout/prompt_manager.py +279 -279
- webscout/scout/__init__.py +8 -0
- webscout/scout/core/__init__.py +7 -0
- webscout/scout/core/crawler.py +140 -0
- webscout/scout/core/scout.py +571 -0
- webscout/scout/core/search_result.py +96 -0
- webscout/scout/core/text_analyzer.py +63 -0
- webscout/scout/core/text_utils.py +277 -0
- webscout/scout/core/web_analyzer.py +52 -0
- webscout/scout/core.py +884 -0
- webscout/scout/element.py +460 -0
- webscout/scout/parsers/__init__.py +69 -0
- webscout/scout/parsers/html5lib_parser.py +172 -0
- webscout/scout/parsers/html_parser.py +236 -0
- webscout/scout/parsers/lxml_parser.py +178 -0
- webscout/scout/utils.py +38 -0
- webscout/update_checker.py +184 -125
- webscout/version.py +1 -1
- webscout/zeroart/__init__.py +55 -0
- webscout/zeroart/base.py +60 -0
- webscout/zeroart/effects.py +99 -0
- webscout/zeroart/fonts.py +816 -0
- webscout/zerodir/__init__.py +225 -0
- {webscout-6.4.dist-info → webscout-6.6.dist-info}/METADATA +18 -231
- webscout-6.6.dist-info/RECORD +197 -0
- webscout-6.6.dist-info/top_level.txt +2 -0
- webstoken/__init__.py +30 -0
- webstoken/classifier.py +189 -0
- webstoken/keywords.py +216 -0
- webstoken/language.py +128 -0
- webstoken/ner.py +164 -0
- webstoken/normalizer.py +35 -0
- webstoken/processor.py +77 -0
- webstoken/sentiment.py +206 -0
- webstoken/stemmer.py +73 -0
- webstoken/t.py +75 -0
- webstoken/tagger.py +60 -0
- webstoken/tokenizer.py +158 -0
- webscout/Agents/Onlinesearcher.py +0 -182
- webscout/Agents/__init__.py +0 -2
- webscout/Agents/functioncall.py +0 -248
- webscout/Bing_search.py +0 -251
- webscout/Provider/Perplexity.py +0 -599
- webscout/Provider/RoboCoders.py +0 -206
- webscout/Provider/genspark.py +0 -225
- webscout/Provider/perplexitylabs.py +0 -265
- webscout/Provider/twitterclone.py +0 -251
- webscout/Provider/upstage.py +0 -230
- webscout/gpt4free.py +0 -666
- webscout/requestsHTMLfix.py +0 -775
- webscout/webai.py +0 -2590
- webscout-6.4.dist-info/RECORD +0 -154
- webscout-6.4.dist-info/top_level.txt +0 -1
- /webscout/Provider/{felo_search.py → AISEARCH/felo_search.py} +0 -0
- {webscout-6.4.dist-info → webscout-6.6.dist-info}/LICENSE.md +0 -0
- {webscout-6.4.dist-info → webscout-6.6.dist-info}/WHEEL +0 -0
- {webscout-6.4.dist-info → webscout-6.6.dist-info}/entry_points.txt +0 -0
|
@@ -1,681 +1,680 @@
|
|
|
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
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
from rich import
|
|
14
|
-
from rich.
|
|
15
|
-
from rich.
|
|
16
|
-
from rich.
|
|
17
|
-
from rich.
|
|
18
|
-
from rich.
|
|
19
|
-
from rich.
|
|
20
|
-
from rich.
|
|
21
|
-
from rich.
|
|
22
|
-
from rich.
|
|
23
|
-
from
|
|
24
|
-
from
|
|
25
|
-
from webscout
|
|
26
|
-
from webscout import
|
|
27
|
-
from
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
>>> coder
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
self.
|
|
91
|
-
self.
|
|
92
|
-
self.
|
|
93
|
-
self.
|
|
94
|
-
self.
|
|
95
|
-
self.
|
|
96
|
-
self.
|
|
97
|
-
self.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
self.
|
|
110
|
-
|
|
111
|
-
self.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
)[1]
|
|
120
|
-
self.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
active_window
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
"""
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
error
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
retries
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
script_dir
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
import
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
sys.
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
sys.
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
thread
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
live.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
error
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
live.
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
process.
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
self.
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
Error
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
"""
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
similarity
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
script_dir
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
syntax =
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
md
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
print(
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
print(
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
console.print(
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
print(
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
print("
|
|
667
|
-
print("
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
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 threading
|
|
8
|
+
import platform
|
|
9
|
+
import datetime
|
|
10
|
+
import subprocess
|
|
11
|
+
import pygetwindow as gw
|
|
12
|
+
from rich import print as rprint
|
|
13
|
+
from rich.panel import Panel
|
|
14
|
+
from rich.syntax import Syntax
|
|
15
|
+
from rich.console import Console, Group
|
|
16
|
+
from rich.markdown import Markdown
|
|
17
|
+
from rich.table import Table
|
|
18
|
+
from rich.style import Style
|
|
19
|
+
from rich.theme import Theme
|
|
20
|
+
from rich.live import Live
|
|
21
|
+
from rich.status import Status
|
|
22
|
+
from rich.rule import Rule
|
|
23
|
+
from typing import Optional, Dict, Any, Generator, List, Tuple
|
|
24
|
+
from webscout.AIutel import run_system_command, default_path
|
|
25
|
+
from webscout import LitLogger, LogFormat, ColorScheme
|
|
26
|
+
from webscout.litprinter import LitPrinter
|
|
27
|
+
from .autocoder_utiles import EXAMPLES, get_intro_prompt
|
|
28
|
+
|
|
29
|
+
# Initialize LitLogger with custom format and colors
|
|
30
|
+
logger = LitLogger(
|
|
31
|
+
name="RawDog",
|
|
32
|
+
format=LogFormat.MODERN_EMOJI,
|
|
33
|
+
color_scheme=ColorScheme.CYBERPUNK
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Custom theme for consistent styling
|
|
37
|
+
CUSTOM_THEME = Theme({
|
|
38
|
+
"info": "cyan",
|
|
39
|
+
"warning": "yellow",
|
|
40
|
+
"error": "red bold",
|
|
41
|
+
"success": "green",
|
|
42
|
+
"code": "blue",
|
|
43
|
+
"output": "white",
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
console = Console(theme=CUSTOM_THEME)
|
|
47
|
+
|
|
48
|
+
class AutoCoder:
|
|
49
|
+
"""Generate and auto-execute Python scripts in the CLI with advanced error handling and retry logic.
|
|
50
|
+
|
|
51
|
+
This class provides:
|
|
52
|
+
- Automatic code generation
|
|
53
|
+
- Script execution with safety checks
|
|
54
|
+
- Advanced error handling and retries
|
|
55
|
+
- Beautiful logging with LitLogger
|
|
56
|
+
|
|
57
|
+
Examples:
|
|
58
|
+
>>> coder = AutoCoder()
|
|
59
|
+
>>> coder.execute("Get system info")
|
|
60
|
+
Generating system info script...
|
|
61
|
+
Script executed successfully!
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
examples = EXAMPLES
|
|
65
|
+
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
quiet: bool = False,
|
|
69
|
+
internal_exec: bool = False,
|
|
70
|
+
confirm_script: bool = False,
|
|
71
|
+
interpreter: str = "python",
|
|
72
|
+
prettify: bool = True,
|
|
73
|
+
path_to_script: str = "",
|
|
74
|
+
max_retries: int = 3,
|
|
75
|
+
ai_instance = None
|
|
76
|
+
):
|
|
77
|
+
"""Initialize AutoCoder instance.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
quiet (bool): Flag to control logging. Defaults to False.
|
|
81
|
+
internal_exec (bool): Execute scripts with exec function. Defaults to False.
|
|
82
|
+
confirm_script (bool): Give consent to scripts prior to execution. Defaults to False.
|
|
83
|
+
interpreter (str): Python's interpreter name. Defaults to "python".
|
|
84
|
+
prettify (bool): Prettify the code on stdout. Defaults to True.
|
|
85
|
+
path_to_script (str): Path to save generated scripts. Defaults to "".
|
|
86
|
+
max_retries (int): Maximum number of retry attempts. Defaults to 3.
|
|
87
|
+
ai_instance: AI instance for error correction. Defaults to None.
|
|
88
|
+
"""
|
|
89
|
+
self.internal_exec = internal_exec
|
|
90
|
+
self.confirm_script = confirm_script
|
|
91
|
+
self.quiet = quiet
|
|
92
|
+
self.interpreter = interpreter
|
|
93
|
+
self.prettify = prettify
|
|
94
|
+
self.path_to_script = path_to_script or os.path.join(default_path, "execute_this.py")
|
|
95
|
+
self.max_retries = max_retries
|
|
96
|
+
self.tried_solutions = set()
|
|
97
|
+
self.ai_instance = ai_instance
|
|
98
|
+
|
|
99
|
+
# Initialize logger with modern format and cyberpunk colors
|
|
100
|
+
self.logger = LitLogger(
|
|
101
|
+
name="AutoCoder",
|
|
102
|
+
format=LogFormat.MODERN_EMOJI,
|
|
103
|
+
color_scheme=ColorScheme.CYBERPUNK,
|
|
104
|
+
console_output=not quiet
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Get Python version with enhanced logging
|
|
108
|
+
self.logger.info("Initializing AutoCoder...")
|
|
109
|
+
if self.internal_exec:
|
|
110
|
+
self.python_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
111
|
+
self.logger.info(f"Using internal Python {self.python_version}")
|
|
112
|
+
else:
|
|
113
|
+
version_output = run_system_command(
|
|
114
|
+
f"{self.interpreter} --version",
|
|
115
|
+
exit_on_error=True,
|
|
116
|
+
stdout_error=True,
|
|
117
|
+
help="If you're using Webscout-cli, use the flag '--internal-exec'"
|
|
118
|
+
)[1].stdout
|
|
119
|
+
self.python_version = version_output.split(" ")[1]
|
|
120
|
+
self.logger.info(f"Using external Python {self.python_version}")
|
|
121
|
+
|
|
122
|
+
self.logger.success("AutoCoder initialized successfully!")
|
|
123
|
+
|
|
124
|
+
def get_current_app(self) -> str:
|
|
125
|
+
"""Get the name of the currently active application.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
str: Name of the active window or "Unknown"
|
|
129
|
+
"""
|
|
130
|
+
try:
|
|
131
|
+
active_window = gw.getActiveWindow()
|
|
132
|
+
if active_window:
|
|
133
|
+
return active_window.title
|
|
134
|
+
except Exception as e:
|
|
135
|
+
self.logger.error(f"Error getting active window: {e}")
|
|
136
|
+
return "Unknown"
|
|
137
|
+
|
|
138
|
+
def _extract_code_blocks(self, response: str) -> List[Tuple[str, str]]:
|
|
139
|
+
"""Extract code blocks from a response string.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
response (str): Response string containing code blocks
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
List[Tuple[str, str]]: List of (code_type, code) tuples
|
|
146
|
+
"""
|
|
147
|
+
blocks = []
|
|
148
|
+
|
|
149
|
+
# First try to find code blocks with explicit language tags
|
|
150
|
+
pattern = r"```(\w+)\n(.*?)```"
|
|
151
|
+
matches = re.finditer(pattern, response, re.DOTALL)
|
|
152
|
+
|
|
153
|
+
for match in matches:
|
|
154
|
+
code_type = match.group(1).lower()
|
|
155
|
+
code = match.group(2).strip()
|
|
156
|
+
blocks.append(('python', code))
|
|
157
|
+
|
|
158
|
+
# If no explicit code blocks found, treat as Python code
|
|
159
|
+
if not blocks:
|
|
160
|
+
lines = [line.strip() for line in response.split('\n') if line.strip()]
|
|
161
|
+
for line in lines:
|
|
162
|
+
blocks.append(('python', line))
|
|
163
|
+
|
|
164
|
+
return blocks
|
|
165
|
+
|
|
166
|
+
def _execute_code_block(self, code_type: str, code: str, ai_instance=None) -> Optional[str]:
|
|
167
|
+
"""Execute a code block.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
code_type (str): Type of code block ('python')
|
|
171
|
+
code (str): Code to execute
|
|
172
|
+
ai_instance: Optional AI instance for error correction
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
Optional[str]: Error message if execution failed, None if successful
|
|
176
|
+
"""
|
|
177
|
+
try:
|
|
178
|
+
return self._execute_with_retry(code, ai_instance)
|
|
179
|
+
except Exception as e:
|
|
180
|
+
return str(e)
|
|
181
|
+
|
|
182
|
+
def _format_output_panel(self, code: str, output_lines: list) -> Panel:
|
|
183
|
+
"""Format code and output into a single panel.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
code (str): The code that was executed
|
|
187
|
+
output_lines (list): List of output lines
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
Panel: Formatted panel with code and output
|
|
191
|
+
"""
|
|
192
|
+
code_syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
|
|
193
|
+
|
|
194
|
+
# Format output
|
|
195
|
+
output_text = "\n".join(output_lines) if output_lines else "Running..."
|
|
196
|
+
|
|
197
|
+
# Combine code and output with a separator
|
|
198
|
+
content = Group(
|
|
199
|
+
code_syntax,
|
|
200
|
+
Rule(style="bright_blue"),
|
|
201
|
+
output_text
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Create panel
|
|
205
|
+
panel = Panel(
|
|
206
|
+
content,
|
|
207
|
+
title="[bold blue]Code Execution[/bold blue]",
|
|
208
|
+
border_style="blue",
|
|
209
|
+
expand=True,
|
|
210
|
+
padding=(0, 1)
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
return panel
|
|
214
|
+
|
|
215
|
+
def _stream_output(self, process: subprocess.Popen) -> Generator[str, None, None]:
|
|
216
|
+
"""Stream output from a subprocess in realtime.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
process: Subprocess to stream output from
|
|
220
|
+
|
|
221
|
+
Yields:
|
|
222
|
+
str: Lines of output
|
|
223
|
+
"""
|
|
224
|
+
# Stream stdout
|
|
225
|
+
for line in process.stdout:
|
|
226
|
+
line = line.strip()
|
|
227
|
+
if line:
|
|
228
|
+
yield line
|
|
229
|
+
|
|
230
|
+
# Check stderr
|
|
231
|
+
error = process.stderr.read() if process.stderr else None
|
|
232
|
+
if error and error.strip():
|
|
233
|
+
yield f"Error: {error.strip()}"
|
|
234
|
+
|
|
235
|
+
def _execute_with_retry(self, code: str, ai_instance=None) -> Optional[str]:
|
|
236
|
+
"""Execute code with retry logic and error correction.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
code (str): Code to execute
|
|
240
|
+
ai_instance: Optional AI instance for error correction
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
Optional[str]: Error message if execution failed, None if successful
|
|
244
|
+
"""
|
|
245
|
+
last_error = None
|
|
246
|
+
retries = 0
|
|
247
|
+
while retries < self.max_retries:
|
|
248
|
+
try:
|
|
249
|
+
if self.path_to_script:
|
|
250
|
+
script_dir = os.path.dirname(self.path_to_script)
|
|
251
|
+
if script_dir:
|
|
252
|
+
os.makedirs(script_dir, exist_ok=True)
|
|
253
|
+
with open(self.path_to_script, "w", encoding="utf-8") as f:
|
|
254
|
+
f.write(code)
|
|
255
|
+
|
|
256
|
+
if self.internal_exec:
|
|
257
|
+
self.logger.info("Executing code internally")
|
|
258
|
+
# Create StringIO for output capture
|
|
259
|
+
import io
|
|
260
|
+
import sys
|
|
261
|
+
stdout = io.StringIO()
|
|
262
|
+
stderr = io.StringIO()
|
|
263
|
+
|
|
264
|
+
# Create a queue for realtime output
|
|
265
|
+
output_queue = queue.Queue()
|
|
266
|
+
output_lines = []
|
|
267
|
+
|
|
268
|
+
def execute_code():
|
|
269
|
+
try:
|
|
270
|
+
# Redirect stdout/stderr
|
|
271
|
+
sys.stdout = stdout
|
|
272
|
+
sys.stderr = stderr
|
|
273
|
+
|
|
274
|
+
# Execute the code
|
|
275
|
+
exec(code, globals())
|
|
276
|
+
|
|
277
|
+
# Get any output
|
|
278
|
+
output = stdout.getvalue()
|
|
279
|
+
error = stderr.getvalue()
|
|
280
|
+
|
|
281
|
+
if error:
|
|
282
|
+
output_queue.put(("error", error))
|
|
283
|
+
elif output:
|
|
284
|
+
output_queue.put(("output", output))
|
|
285
|
+
|
|
286
|
+
finally:
|
|
287
|
+
# Restore stdout/stderr
|
|
288
|
+
sys.stdout = sys.__stdout__
|
|
289
|
+
sys.stderr = sys.__stderr__
|
|
290
|
+
|
|
291
|
+
# Create and start execution thread
|
|
292
|
+
thread = threading.Thread(target=execute_code)
|
|
293
|
+
thread.start()
|
|
294
|
+
|
|
295
|
+
# Display output in realtime
|
|
296
|
+
with Live(auto_refresh=False, transient=True) as live:
|
|
297
|
+
while thread.is_alive() or not output_queue.empty():
|
|
298
|
+
try:
|
|
299
|
+
msg_type, content = output_queue.get_nowait()
|
|
300
|
+
if content:
|
|
301
|
+
output_lines.extend(content.splitlines())
|
|
302
|
+
live.update(self._format_output_panel(code, output_lines))
|
|
303
|
+
live.refresh()
|
|
304
|
+
except queue.Empty:
|
|
305
|
+
continue
|
|
306
|
+
|
|
307
|
+
thread.join()
|
|
308
|
+
|
|
309
|
+
# Check for any final errors
|
|
310
|
+
error = stderr.getvalue()
|
|
311
|
+
if error:
|
|
312
|
+
raise Exception(error)
|
|
313
|
+
|
|
314
|
+
else:
|
|
315
|
+
self.logger.info("Executing code as external process")
|
|
316
|
+
process = subprocess.Popen(
|
|
317
|
+
[self.interpreter, self.path_to_script],
|
|
318
|
+
stdout=subprocess.PIPE,
|
|
319
|
+
stderr=subprocess.PIPE,
|
|
320
|
+
text=True,
|
|
321
|
+
bufsize=1,
|
|
322
|
+
universal_newlines=True
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
output_lines = []
|
|
326
|
+
# Stream output in realtime
|
|
327
|
+
with Live(auto_refresh=False, transient=True) as live:
|
|
328
|
+
for line in self._stream_output(process):
|
|
329
|
+
output_lines.append(line)
|
|
330
|
+
live.update(self._format_output_panel(code, output_lines))
|
|
331
|
+
live.refresh()
|
|
332
|
+
|
|
333
|
+
process.wait()
|
|
334
|
+
error = process.stderr.read() if not isinstance(process.stderr, str) else process.stderr
|
|
335
|
+
if process.returncode != 0 and error:
|
|
336
|
+
raise Exception(error)
|
|
337
|
+
|
|
338
|
+
return None
|
|
339
|
+
|
|
340
|
+
except Exception as e:
|
|
341
|
+
last_error = e
|
|
342
|
+
if retries < self.max_retries - 1 and ai_instance:
|
|
343
|
+
error_context = self._get_error_context(e, code)
|
|
344
|
+
try:
|
|
345
|
+
self.logger.info(f"Attempting correction (retry {retries + 1}/{self.max_retries})")
|
|
346
|
+
fixed_response = ai_instance.chat(error_context)
|
|
347
|
+
fixed_code = self._extract_code_from_response(fixed_response)
|
|
348
|
+
|
|
349
|
+
if not fixed_code:
|
|
350
|
+
self.logger.error("AI provided empty response")
|
|
351
|
+
break
|
|
352
|
+
|
|
353
|
+
if self._is_similar_solution(fixed_code):
|
|
354
|
+
self.logger.warning("AI provided similar solution, requesting different approach")
|
|
355
|
+
error_context += "\nPrevious solutions were not successful. Please provide a significantly different approach."
|
|
356
|
+
fixed_response = ai_instance.chat(error_context)
|
|
357
|
+
fixed_code = self._extract_code_from_response(fixed_response)
|
|
358
|
+
|
|
359
|
+
if self._is_similar_solution(fixed_code):
|
|
360
|
+
self.logger.error("AI unable to provide sufficiently different solution")
|
|
361
|
+
break
|
|
362
|
+
|
|
363
|
+
code = fixed_code
|
|
364
|
+
retries += 1
|
|
365
|
+
continue
|
|
366
|
+
except Exception as ai_error:
|
|
367
|
+
self.logger.error(f"Error getting AI correction: {str(ai_error)}")
|
|
368
|
+
break
|
|
369
|
+
break
|
|
370
|
+
|
|
371
|
+
return str(last_error) if last_error else "Unknown error occurred"
|
|
372
|
+
|
|
373
|
+
def execute(self, prompt: str, ai_instance=None) -> bool:
|
|
374
|
+
"""Execute the given prompt using the appropriate executor.
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
prompt (str): Prompt to execute
|
|
378
|
+
ai_instance: Optional AI instance for error correction
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
bool: True if execution was successful, False otherwise
|
|
382
|
+
"""
|
|
383
|
+
try:
|
|
384
|
+
# Extract code blocks
|
|
385
|
+
code_blocks = self._extract_code_blocks(prompt)
|
|
386
|
+
if not code_blocks:
|
|
387
|
+
self.logger.warning("No code blocks found in prompt")
|
|
388
|
+
return False
|
|
389
|
+
|
|
390
|
+
# Execute each code block
|
|
391
|
+
for code_type, code in code_blocks:
|
|
392
|
+
self.logger.info(f"Executing {code_type} block")
|
|
393
|
+
error = self._execute_code_block(code_type, code, ai_instance)
|
|
394
|
+
|
|
395
|
+
if error:
|
|
396
|
+
self.logger.error(f"Execution failed: {error}")
|
|
397
|
+
return False
|
|
398
|
+
|
|
399
|
+
return True
|
|
400
|
+
|
|
401
|
+
except Exception as e:
|
|
402
|
+
self.logger.error(f"Execution error: {str(e)}")
|
|
403
|
+
return False
|
|
404
|
+
|
|
405
|
+
def _extract_code_from_response(self, response: str) -> str:
|
|
406
|
+
"""Extract code from AI response.
|
|
407
|
+
|
|
408
|
+
Args:
|
|
409
|
+
response (str): AI response containing code blocks
|
|
410
|
+
|
|
411
|
+
Returns:
|
|
412
|
+
str: Extracted code from the first code block
|
|
413
|
+
"""
|
|
414
|
+
code_blocks = self._extract_code_blocks(response)
|
|
415
|
+
if not code_blocks:
|
|
416
|
+
return ""
|
|
417
|
+
|
|
418
|
+
# Return the content of the first code block, regardless of type
|
|
419
|
+
return code_blocks[0][1]
|
|
420
|
+
|
|
421
|
+
def _get_error_context(self, error: Exception, code: str) -> str:
|
|
422
|
+
"""Create context about the error for AI correction.
|
|
423
|
+
|
|
424
|
+
Args:
|
|
425
|
+
error (Exception): The caught exception
|
|
426
|
+
code (str): The code that caused the error
|
|
427
|
+
|
|
428
|
+
Returns:
|
|
429
|
+
str: Formatted error context for AI
|
|
430
|
+
"""
|
|
431
|
+
error_type = type(error).__name__
|
|
432
|
+
error_msg = str(error)
|
|
433
|
+
|
|
434
|
+
return f"""
|
|
435
|
+
The code failed with error:
|
|
436
|
+
Error Type: {error_type}
|
|
437
|
+
Error Message: {error_msg}
|
|
438
|
+
|
|
439
|
+
Original Code:
|
|
440
|
+
```python
|
|
441
|
+
{code}
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
Please fix the code to handle this error. Provide only the corrected code without any explanation.
|
|
445
|
+
"""
|
|
446
|
+
|
|
447
|
+
def _handle_import_error(self, error: ImportError, code: str) -> Optional[str]:
|
|
448
|
+
"""Handle missing package errors by attempting to install them.
|
|
449
|
+
|
|
450
|
+
Args:
|
|
451
|
+
error (ImportError): The import error
|
|
452
|
+
code (str): The code that caused the error
|
|
453
|
+
|
|
454
|
+
Returns:
|
|
455
|
+
Optional[str]: Fixed code or None if installation failed
|
|
456
|
+
"""
|
|
457
|
+
missing_package = str(error).split("'")[1] if "'" in str(error) else str(error).split()[3]
|
|
458
|
+
try:
|
|
459
|
+
logger.info(f"Installing missing package: {missing_package}")
|
|
460
|
+
result = subprocess.run(
|
|
461
|
+
[sys.executable, "-m", "pip", "install", missing_package],
|
|
462
|
+
capture_output=True,
|
|
463
|
+
text=True
|
|
464
|
+
)
|
|
465
|
+
if result.returncode == 0:
|
|
466
|
+
logger.success(f"Successfully installed {missing_package}")
|
|
467
|
+
return code # Retry with same code after installing package
|
|
468
|
+
else:
|
|
469
|
+
raise Exception(f"Failed to install {missing_package}: {result.stderr}")
|
|
470
|
+
except Exception as e:
|
|
471
|
+
logger.error(f"Error installing package: {str(e)}")
|
|
472
|
+
return None
|
|
473
|
+
|
|
474
|
+
def _is_similar_solution(self, new_code: str, threshold: float = 0.8) -> bool:
|
|
475
|
+
"""Check if the new solution is too similar to previously tried ones.
|
|
476
|
+
|
|
477
|
+
Args:
|
|
478
|
+
new_code (str): New solution to check
|
|
479
|
+
threshold (float): Similarity threshold (0-1). Defaults to 0.8.
|
|
480
|
+
|
|
481
|
+
Returns:
|
|
482
|
+
bool: True if solution is too similar to previous attempts
|
|
483
|
+
"""
|
|
484
|
+
import difflib
|
|
485
|
+
|
|
486
|
+
def normalize_code(code: str) -> str:
|
|
487
|
+
lines = [line.split('#')[0].strip() for line in code.split('\n')]
|
|
488
|
+
return '\n'.join(line for line in lines if line)
|
|
489
|
+
|
|
490
|
+
new_code_norm = normalize_code(new_code)
|
|
491
|
+
|
|
492
|
+
for tried_code in self.tried_solutions:
|
|
493
|
+
tried_code_norm = normalize_code(tried_code)
|
|
494
|
+
similarity = difflib.SequenceMatcher(None, new_code_norm, tried_code_norm).ratio()
|
|
495
|
+
if similarity > threshold:
|
|
496
|
+
return True
|
|
497
|
+
return False
|
|
498
|
+
|
|
499
|
+
def main(self, response: str) -> Optional[str]:
|
|
500
|
+
"""Execute code with error correction.
|
|
501
|
+
|
|
502
|
+
Args:
|
|
503
|
+
response (str): AI response containing code
|
|
504
|
+
|
|
505
|
+
Returns:
|
|
506
|
+
Optional[str]: Error message if execution failed, None if successful
|
|
507
|
+
"""
|
|
508
|
+
if not response:
|
|
509
|
+
return None
|
|
510
|
+
|
|
511
|
+
code = self._extract_code_from_response(response)
|
|
512
|
+
|
|
513
|
+
# Print the generated code with syntax highlighting
|
|
514
|
+
self.print_code(code)
|
|
515
|
+
|
|
516
|
+
ai_instance = self.ai_instance or globals().get('ai')
|
|
517
|
+
|
|
518
|
+
if not ai_instance:
|
|
519
|
+
logger.warning("AI instance not found, error correction disabled")
|
|
520
|
+
try:
|
|
521
|
+
if self.path_to_script:
|
|
522
|
+
script_dir = os.path.dirname(self.path_to_script)
|
|
523
|
+
if script_dir:
|
|
524
|
+
os.makedirs(script_dir, exist_ok=True)
|
|
525
|
+
with open(self.path_to_script, "w", encoding="utf-8") as f:
|
|
526
|
+
f.write(code)
|
|
527
|
+
|
|
528
|
+
if self.internal_exec:
|
|
529
|
+
logger.info("Executing code internally")
|
|
530
|
+
exec(code, globals())
|
|
531
|
+
else:
|
|
532
|
+
logger.info("Executing code as external process")
|
|
533
|
+
result = subprocess.run(
|
|
534
|
+
[self.interpreter, self.path_to_script],
|
|
535
|
+
capture_output=True,
|
|
536
|
+
text=True
|
|
537
|
+
)
|
|
538
|
+
if result.returncode != 0:
|
|
539
|
+
raise Exception(result.stderr or result.stdout)
|
|
540
|
+
return None
|
|
541
|
+
except Exception as e:
|
|
542
|
+
return str(e)
|
|
543
|
+
|
|
544
|
+
return self._execute_with_retry(code, ai_instance)
|
|
545
|
+
|
|
546
|
+
@property
|
|
547
|
+
def intro_prompt(self) -> str:
|
|
548
|
+
"""Get the introduction prompt.
|
|
549
|
+
|
|
550
|
+
Returns:
|
|
551
|
+
str: Introduction prompt
|
|
552
|
+
"""
|
|
553
|
+
return get_intro_prompt()
|
|
554
|
+
|
|
555
|
+
def log(self, message: str, category: str = "info"):
|
|
556
|
+
"""RawDog logger
|
|
557
|
+
|
|
558
|
+
Args:
|
|
559
|
+
message (str): Log message
|
|
560
|
+
category (str, optional): Log level. Defaults to 'info'.
|
|
561
|
+
"""
|
|
562
|
+
if self.quiet:
|
|
563
|
+
return
|
|
564
|
+
|
|
565
|
+
message = "[Webscout] - " + message
|
|
566
|
+
if category == "error":
|
|
567
|
+
logger.error(message)
|
|
568
|
+
else:
|
|
569
|
+
logger.info(message)
|
|
570
|
+
|
|
571
|
+
def stdout(self, message: str, style: str = "info") -> None:
|
|
572
|
+
"""Enhanced stdout with Rich formatting.
|
|
573
|
+
|
|
574
|
+
Args:
|
|
575
|
+
message (str): Text to be printed
|
|
576
|
+
style (str, optional): Style to apply. Defaults to "info".
|
|
577
|
+
"""
|
|
578
|
+
if not self.prettify:
|
|
579
|
+
print(message)
|
|
580
|
+
return
|
|
581
|
+
|
|
582
|
+
if message.startswith("```") and message.endswith("```"):
|
|
583
|
+
# Handle code blocks
|
|
584
|
+
code = message.strip("`").strip()
|
|
585
|
+
syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
|
|
586
|
+
console.print(Panel(syntax, title="Code", border_style="blue"))
|
|
587
|
+
elif "```python" in message:
|
|
588
|
+
# Handle markdown code blocks
|
|
589
|
+
md = Markdown(message)
|
|
590
|
+
console.print(md)
|
|
591
|
+
else:
|
|
592
|
+
# Handle regular text with optional styling
|
|
593
|
+
console.print(message, style=style)
|
|
594
|
+
|
|
595
|
+
def print_code(self, code: str, title: str = "Generated Code") -> None:
|
|
596
|
+
"""Print code with syntax highlighting and panel.
|
|
597
|
+
|
|
598
|
+
Args:
|
|
599
|
+
code (str): Code to print
|
|
600
|
+
title (str, optional): Panel title. Defaults to "Generated Code".
|
|
601
|
+
"""
|
|
602
|
+
if self.prettify:
|
|
603
|
+
syntax = Syntax(code, "python", theme="monokai", line_numbers=True)
|
|
604
|
+
console.print(Panel(
|
|
605
|
+
syntax,
|
|
606
|
+
title=f"[bold blue]In [1]: {title}[/bold blue]",
|
|
607
|
+
border_style="blue",
|
|
608
|
+
expand=True
|
|
609
|
+
))
|
|
610
|
+
else:
|
|
611
|
+
print(f"\n{title}:")
|
|
612
|
+
print(code)
|
|
613
|
+
|
|
614
|
+
def print_output(self, output: str, style: str = "output") -> None:
|
|
615
|
+
"""Print command output with optional styling.
|
|
616
|
+
|
|
617
|
+
Args:
|
|
618
|
+
output (str): Output to print
|
|
619
|
+
style (str, optional): Style to apply. Defaults to "output".
|
|
620
|
+
"""
|
|
621
|
+
if self.prettify:
|
|
622
|
+
# Try to detect if output is Python code
|
|
623
|
+
try:
|
|
624
|
+
# If it looks like Python code, syntax highlight it
|
|
625
|
+
compile(output, '<string>', 'exec')
|
|
626
|
+
syntax = Syntax(output, "python", theme="monokai", line_numbers=False)
|
|
627
|
+
formatted_output = syntax
|
|
628
|
+
except SyntaxError:
|
|
629
|
+
# If not Python code, treat as plain text
|
|
630
|
+
formatted_output = output
|
|
631
|
+
|
|
632
|
+
console.print(Panel(
|
|
633
|
+
formatted_output,
|
|
634
|
+
title="[bold red]Out [1]:[/bold red]",
|
|
635
|
+
border_style="red",
|
|
636
|
+
expand=True,
|
|
637
|
+
padding=(0, 1)
|
|
638
|
+
))
|
|
639
|
+
else:
|
|
640
|
+
print("\nOutput:")
|
|
641
|
+
print(output)
|
|
642
|
+
|
|
643
|
+
def print_error(self, error: str) -> None:
|
|
644
|
+
"""Print error message with styling.
|
|
645
|
+
|
|
646
|
+
Args:
|
|
647
|
+
error (str): Error message to print
|
|
648
|
+
"""
|
|
649
|
+
if self.prettify:
|
|
650
|
+
console.print(f"\n Error:", style="error bold")
|
|
651
|
+
console.print(error, style="error")
|
|
652
|
+
else:
|
|
653
|
+
print("\nError:")
|
|
654
|
+
print(error)
|
|
655
|
+
|
|
656
|
+
def print_table(self, headers: list, rows: list) -> None:
|
|
657
|
+
"""Print data in a formatted table.
|
|
658
|
+
|
|
659
|
+
Args:
|
|
660
|
+
headers (list): Table headers
|
|
661
|
+
rows (list): Table rows
|
|
662
|
+
"""
|
|
663
|
+
if not self.prettify:
|
|
664
|
+
# Simple ASCII table
|
|
665
|
+
print("\n" + "-" * 80)
|
|
666
|
+
print("| " + " | ".join(headers) + " |")
|
|
667
|
+
print("-" * 80)
|
|
668
|
+
for row in rows:
|
|
669
|
+
print("| " + " | ".join(str(cell) for cell in row) + " |")
|
|
670
|
+
print("-" * 80)
|
|
671
|
+
return
|
|
672
|
+
|
|
673
|
+
table = Table(show_header=True, header_style="bold cyan")
|
|
674
|
+
for header in headers:
|
|
675
|
+
table.add_column(header)
|
|
676
|
+
|
|
677
|
+
for row in rows:
|
|
678
|
+
table.add_row(*[str(cell) for cell in row])
|
|
679
|
+
|
|
681
680
|
console.print(table)
|