skylos 1.0.11__py3-none-any.whl → 1.1.11__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 skylos might be problematic. Click here for more details.

@@ -1,608 +0,0 @@
1
- import gradio as gr
2
- import os
3
- import concurrent.futures
4
- import types
5
-
6
- def get_files_by_folder(root_dir, max_depth=3):
7
- files_by_folder = {}
8
- if not os.path.exists(root_dir) or not os.path.isdir(root_dir):
9
- return files_by_folder
10
-
11
- def scan_directory(current_dir, current_depth=0):
12
- if current_depth > max_depth:
13
- return
14
- try:
15
- items = sorted(os.listdir(current_dir))
16
- except PermissionError:
17
- return
18
- for item in items:
19
- if item.startswith('.') or item in ['__pycache__', 'node_modules', '.git']:
20
- continue
21
- item_path = os.path.join(current_dir, item)
22
- if os.path.isfile(item_path):
23
- if not item.endswith(('.pyc', '.pyo')):
24
- folder = os.path.relpath(os.path.dirname(item_path), root_dir)
25
- if folder == '.':
26
- folder = 'Root Directory'
27
- if folder not in files_by_folder:
28
- files_by_folder[folder] = []
29
- files_by_folder[folder].append((item, item_path))
30
- elif os.path.isdir(item_path):
31
- scan_directory(item_path, current_depth + 1)
32
-
33
- scan_directory(root_dir)
34
- return files_by_folder
35
-
36
- def process_chunks(strategy, num_chunks, max_chunk_size, output_dir, selected_files):
37
- try:
38
-
39
- if not selected_files:
40
- return "❌ No files selected. Please select files using the checkboxes."
41
-
42
- try:
43
- from pykomodo.multi_dirs_chunker import ParallelChunker
44
- except ImportError as e:
45
- return f"❌ Error: Could not import ParallelChunker. Make sure pykomodo is installed.\nError: {e}"
46
-
47
- if not output_dir.strip():
48
- return "❌ Please provide an output directory."
49
-
50
- output_dir = output_dir.strip()
51
- os.makedirs(output_dir, exist_ok=True)
52
-
53
- if strategy == "Equal Chunks":
54
- if not num_chunks or num_chunks <= 0:
55
- return "❌ Please provide a positive number of chunks."
56
- chunker = ParallelChunker(equal_chunks=int(num_chunks), output_dir=output_dir)
57
- elif strategy == "Max Chunk Size":
58
- if not max_chunk_size or max_chunk_size <= 0:
59
- return "❌ Please provide a positive max chunk size."
60
- chunker = ParallelChunker(max_chunk_size=int(max_chunk_size), output_dir=output_dir)
61
- else:
62
- return "❌ Invalid chunking strategy selected."
63
-
64
- if not hasattr(chunker, 'process_files'):
65
- def process_files(self, file_paths):
66
- self.loaded_files.clear()
67
- valid_files = [fp for fp in file_paths if os.path.isfile(fp)]
68
- if not valid_files:
69
- raise ValueError("No valid files found to process")
70
-
71
- with concurrent.futures.ThreadPoolExecutor(max_workers=getattr(self, 'num_threads', 4)) as ex:
72
- future_map = {ex.submit(self._load_file_data, p): p for p in valid_files}
73
- for fut in concurrent.futures.as_completed(future_map):
74
- try:
75
- path, content, priority = fut.result()
76
- if content is not None and not self.is_binary_file(path):
77
- self.loaded_files.append((path, content, priority))
78
- except Exception as e:
79
- print(f"Error processing file: {e}")
80
-
81
- if not self.loaded_files:
82
- raise ValueError("No files could be processed")
83
-
84
- self.loaded_files.sort(key=lambda x: (-x[2], x[0]))
85
- self._process_chunks()
86
-
87
- chunker.process_files = types.MethodType(process_files, chunker)
88
-
89
- chunker.process_files(selected_files)
90
-
91
- output_files = []
92
- if os.path.exists(output_dir):
93
- output_files = [f for f in os.listdir(output_dir) if f.endswith('.txt')]
94
-
95
- return f"✅ Chunking completed successfully!\n📁 Output directory: {output_dir}\n📄 Files processed: {len(selected_files)}\n📦 Chunks created: {len(output_files)}"
96
-
97
- except Exception as e:
98
- import traceback
99
- traceback.print_exc()
100
- return f"❌ Error during processing: {str(e)}"
101
-
102
- def launch_dashboard():
103
-
104
- custom_css = """
105
- .gradio-container {
106
- max-width: 1200px !important;
107
- margin: 0 auto !important;
108
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
109
- }
110
-
111
- .header {
112
- text-align: center;
113
- padding: 30px 0;
114
- border-bottom: 2px solid #e5e7eb;
115
- margin-bottom: 30px;
116
- }
117
-
118
- .header h1 {
119
- font-size: 2.5rem;
120
- font-weight: 700;
121
- color: #1f2937;
122
- margin: 0;
123
- }
124
-
125
- .header p {
126
- font-size: 1.1rem;
127
- color: #6b7280;
128
- margin: 10px 0 0 0;
129
- }
130
-
131
- .step-section {
132
- background: white;
133
- border: 1px solid #e5e7eb;
134
- border-radius: 8px;
135
- padding: 24px;
136
- margin-bottom: 24px;
137
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
138
- }
139
-
140
- .step-header {
141
- display: flex;
142
- align-items: center;
143
- margin-bottom: 20px;
144
- padding-bottom: 16px;
145
- border-bottom: 1px solid #f3f4f6;
146
- }
147
-
148
- .step-number {
149
- background: #1f2937;
150
- color: white;
151
- width: 32px;
152
- height: 32px;
153
- border-radius: 50%;
154
- display: flex;
155
- align-items: center;
156
- justify-content: center;
157
- font-weight: 600;
158
- margin-right: 16px;
159
- font-size: 14px;
160
- }
161
-
162
- .step-title {
163
- font-size: 1.25rem;
164
- font-weight: 600;
165
- color: #1f2937;
166
- margin: 0;
167
- }
168
-
169
- .instructions {
170
- background: #f8fafc;
171
- border: 1px solid #e2e8f0;
172
- border-radius: 6px;
173
- padding: 16px;
174
- margin-bottom: 24px;
175
- }
176
-
177
- .instructions h3 {
178
- margin: 0 0 12px 0;
179
- color: #1e293b;
180
- font-size: 1rem;
181
- font-weight: 600;
182
- }
183
-
184
- .instructions ol {
185
- margin: 0;
186
- padding-left: 20px;
187
- color: #475569;
188
- }
189
-
190
- .instructions li {
191
- margin-bottom: 4px;
192
- }
193
-
194
- .config-panel {
195
- background: #fafafa;
196
- border: 1px solid #e5e7eb;
197
- border-radius: 8px;
198
- padding: 24px;
199
- }
200
-
201
- .config-header {
202
- text-align: center;
203
- margin-bottom: 20px;
204
- padding-bottom: 16px;
205
- border-bottom: 1px solid #e5e7eb;
206
- }
207
-
208
- .config-header h2 {
209
- margin: 0;
210
- color: #1f2937;
211
- font-size: 1.5rem;
212
- font-weight: 600;
213
- }
214
-
215
- .gr-button {
216
- border-radius: 6px !important;
217
- font-weight: 500 !important;
218
- font-size: 14px !important;
219
- }
220
-
221
- .gr-button-primary {
222
- background: #1f2937 !important;
223
- border: 1px solid #1f2937 !important;
224
- }
225
-
226
- .gr-button-primary:hover {
227
- background: #111827 !important;
228
- border: 1px solid #111827 !important;
229
- }
230
-
231
- .gr-button-secondary {
232
- background: white !important;
233
- border: 1px solid #d1d5db !important;
234
- color: #374151 !important;
235
- }
236
-
237
- .gr-button-secondary:hover {
238
- background: #f9fafb !important;
239
- border: 1px solid #9ca3af !important;
240
- }
241
-
242
- .gr-textbox, .gr-dropdown {
243
- border-radius: 6px !important;
244
- border: 1px solid #d1d5db !important;
245
- }
246
-
247
- .gr-textbox:focus, .gr-dropdown:focus {
248
- border-color: #1f2937 !important;
249
- box-shadow: 0 0 0 3px rgba(31, 41, 55, 0.1) !important;
250
- }
251
-
252
- .status-display {
253
- background: white;
254
- border: 1px solid #e5e7eb;
255
- border-radius: 6px;
256
- padding: 16px;
257
- font-family: 'SF Mono', Monaco, monospace;
258
- font-size: 13px;
259
- line-height: 1.5;
260
- }
261
-
262
- .file-selection {
263
- background: white;
264
- border: 1px solid #e5e7eb;
265
- border-radius: 6px;
266
- padding: 16px;
267
- min-height: 200px;
268
- }
269
-
270
- .selection-summary {
271
- background: #f9fafb;
272
- border: 1px solid #d1d5db;
273
- border-radius: 6px;
274
- padding: 16px;
275
- margin-top: 16px;
276
- }
277
-
278
- .selection-summary h4 {
279
- margin: 0 0 8px 0;
280
- color: #374151;
281
- font-size: 14px;
282
- font-weight: 600;
283
- }
284
- """
285
-
286
- with gr.Blocks(
287
- theme=gr.themes.Default(),
288
- css=custom_css,
289
- title="Komodo Chunking Tool"
290
- ) as demo:
291
-
292
- gr.HTML("""
293
- <div class="header">
294
- <h1>Komodo Chunking Tool</h1>
295
- <p>Professional code file processing and chunking</p>
296
- </div>
297
- """)
298
-
299
- gr.HTML("""
300
- <div class="instructions">
301
- <h3>How to use this tool:</h3>
302
- <ol>
303
- <li>Enter your repository path and click "Load Repository"</li>
304
- <li>Select a folder from the dropdown to view its files</li>
305
- <li>Check the files you want to process</li>
306
- <li>Configure chunking settings and click "Process Files"</li>
307
- </ol>
308
- </div>
309
- """)
310
-
311
- current_folder = gr.State(value="")
312
- all_files_data = gr.State(value={})
313
- all_selected_files = gr.State(value=[])
314
-
315
- with gr.Row():
316
-
317
- with gr.Column(scale=2):
318
-
319
- gr.HTML("""
320
- <div class="step-section">
321
- <div class="step-header">
322
- <div class="step-number">1</div>
323
- <h3 class="step-title">Load Repository</h3>
324
- </div>
325
- """)
326
-
327
- repo_path = gr.Textbox(
328
- label="Repository Path",
329
- placeholder="Enter path to your code repository (e.g., /Users/yourname/project or .)",
330
- value=".",
331
- info="Path to the directory containing your code files"
332
- )
333
-
334
- load_btn = gr.Button("Load Repository", variant="primary", size="lg")
335
-
336
- load_status = gr.Textbox(
337
- label="Status",
338
- interactive=False,
339
- value="Enter repository path and click 'Load Repository' to begin",
340
- elem_classes="status-display"
341
- )
342
-
343
- gr.HTML("</div>")
344
-
345
- ## step2 -> select folder
346
- gr.HTML("""
347
- <div class="step-section">
348
- <div class="step-header">
349
- <div class="step-number">2</div>
350
- <h3 class="step-title">Select Folder</h3>
351
- </div>
352
- """)
353
-
354
- folder_dropdown = gr.Dropdown(
355
- label="Choose folder to explore",
356
- choices=[],
357
- value="",
358
- info="Select a folder to view its files"
359
- )
360
-
361
- gr.HTML("</div>")
362
-
363
- # step3 -> file select
364
- gr.HTML("""
365
- <div class="step-section">
366
- <div class="step-header">
367
- <div class="step-number">3</div>
368
- <h3 class="step-title">Select Files</h3>
369
- </div>
370
- """)
371
-
372
- file_checkboxes = gr.CheckboxGroup(
373
- label="Files in selected folder",
374
- choices=[],
375
- value=[],
376
- info="Check the files you want to process",
377
- elem_classes="file-selection"
378
- )
379
-
380
- with gr.Row():
381
- select_all_btn = gr.Button("Select All", size="sm", variant="secondary")
382
- clear_selection_btn = gr.Button("Clear Selection", size="sm", variant="secondary")
383
-
384
- gr.HTML("</div>")
385
-
386
- gr.HTML("""
387
- <div class="selection-summary">
388
- <h4>Selected Files Summary</h4>
389
- """)
390
-
391
- selected_display = gr.Textbox(
392
- label="Currently selected files",
393
- interactive=False,
394
- lines=4,
395
- value="No files selected",
396
- show_label=False
397
- )
398
-
399
- gr.HTML("</div>")
400
-
401
- with gr.Column(scale=1):
402
-
403
- gr.HTML("""
404
- <div class="config-panel">
405
- <div class="config-header">
406
- <h2>Configuration</h2>
407
- </div>
408
- """)
409
-
410
- strategy = gr.Dropdown(
411
- label="Chunking Strategy",
412
- choices=["Equal Chunks", "Max Chunk Size"],
413
- value="Equal Chunks",
414
- info="How to split your files"
415
- )
416
-
417
- num_chunks = gr.Number(
418
- label="Number of Chunks",
419
- value=5,
420
- minimum=1,
421
- step=1,
422
- visible=True,
423
- info="Split files into this many equal parts"
424
- )
425
-
426
- max_chunk_size = gr.Number(
427
- label="Max Chunk Size (tokens)",
428
- value=1000,
429
- minimum=100,
430
- step=100,
431
- visible=False,
432
- info="Maximum size for each chunk"
433
- )
434
-
435
- output_dir = gr.Textbox(
436
- label="Output Directory",
437
- value="chunks",
438
- placeholder="Directory to save chunks",
439
- info="Where to save the processed files"
440
- )
441
-
442
- process_btn = gr.Button("Process Files", variant="primary", size="lg")
443
-
444
- status = gr.Textbox(
445
- label="Processing Status",
446
- interactive=False,
447
- lines=6,
448
- value="Ready to process files",
449
- elem_classes="status-display"
450
- )
451
-
452
- gr.HTML("</div>")
453
-
454
- def load_files(repo_path):
455
- try:
456
- if not repo_path or not repo_path.strip():
457
- return (gr.update(choices=[], value=""),
458
- gr.update(choices=[], value=[]),
459
- {}, [], "No files selected",
460
- "❌ Please enter a repository path")
461
-
462
- repo_path = repo_path.strip()
463
-
464
- if not os.path.exists(repo_path):
465
- return (gr.update(choices=[], value=""),
466
- gr.update(choices=[], value=[]),
467
- {}, [], "No files selected",
468
- f"❌ Path does not exist: {repo_path}")
469
-
470
- if not os.path.isdir(repo_path):
471
- return (gr.update(choices=[], value=""),
472
- gr.update(choices=[], value=[]),
473
- {}, [], "No files selected",
474
- f"❌ Path is not a directory: {repo_path}")
475
-
476
- files_by_folder = get_files_by_folder(repo_path)
477
-
478
- if not files_by_folder:
479
- return (gr.update(choices=[], value=""),
480
- gr.update(choices=[], value=[]),
481
- {}, [], "No files selected",
482
- "❌ No files found in directory")
483
-
484
- total_files = sum(len(files) for files in files_by_folder.values())
485
-
486
- folder_choices = []
487
- for folder, files in sorted(files_by_folder.items()):
488
- folder_choices.append(f"📁 {folder} ({len(files)} files)")
489
-
490
- first_folder = folder_choices[0] if folder_choices else ""
491
- first_folder_files = []
492
- if first_folder:
493
- actual_folder = first_folder.split("📁 ")[1].split(" (")[0]
494
- if actual_folder in files_by_folder:
495
- first_folder_files = [(f"📄 {filename}", filepath)
496
- for filename, filepath in files_by_folder[actual_folder]]
497
-
498
- status_msg = f"✅ Found {total_files} files in {len(files_by_folder)} folders"
499
-
500
- return (gr.update(choices=folder_choices, value=first_folder),
501
- gr.update(choices=first_folder_files, value=[]),
502
- files_by_folder, [], "No files selected", status_msg)
503
-
504
- except Exception as e:
505
- return (gr.update(choices=[], value=""),
506
- gr.update(choices=[], value=[]),
507
- {}, [], "No files selected", f"❌ Error: {str(e)}")
508
-
509
- def update_files_for_folder(selected_folder, files_data, current_selected):
510
- if not selected_folder or not files_data:
511
- return gr.update(choices=[], value=[]), current_selected, "No files selected"
512
-
513
- folder_name = selected_folder.split("📁 ")[1].split(" (")[0]
514
-
515
- if folder_name not in files_data:
516
- return gr.update(choices=[], value=[]), current_selected, "No files selected"
517
-
518
- file_choices = [(f"📄 {filename}", filepath)
519
- for filename, filepath in files_data[folder_name]]
520
-
521
- current_folder_files = [filepath for filename, filepath in files_data[folder_name]]
522
- kept_selections = [f for f in current_selected if f in current_folder_files]
523
-
524
- if current_selected:
525
- display_text = f"Selected {len(current_selected)} files:\n" + "\n".join([
526
- os.path.basename(f) for f in current_selected
527
- ])
528
- else:
529
- display_text = "No files selected"
530
-
531
- return gr.update(choices=file_choices, value=kept_selections), current_selected, display_text
532
-
533
- def update_selected_files(folder_selections, current_all_selected):
534
- if not folder_selections:
535
- return current_all_selected, "No files selected"
536
-
537
- new_all_selected = list(set(current_all_selected + folder_selections))
538
-
539
- if new_all_selected:
540
- display_text = f"Selected {len(new_all_selected)} files:\n" + "\n".join([
541
- os.path.basename(f) for f in new_all_selected
542
- ])
543
- else:
544
- display_text = "No files selected"
545
-
546
- return new_all_selected, display_text
547
-
548
- def select_all_in_folder(folder_selections):
549
- return folder_selections if folder_selections else []
550
-
551
- def clear_all_selections():
552
- return [], [], "No files selected"
553
-
554
- def update_visibility(strategy):
555
- if strategy == "Equal Chunks":
556
- return gr.update(visible=True), gr.update(visible=False)
557
- else:
558
- return gr.update(visible=False), gr.update(visible=True)
559
-
560
- def process_files_handler(strategy, num_chunks, max_chunk_size, output_dir, selected_files):
561
- return process_chunks(strategy, num_chunks, max_chunk_size, output_dir, selected_files)
562
-
563
- load_btn.click(
564
- load_files,
565
- inputs=[repo_path],
566
- outputs=[folder_dropdown, file_checkboxes, all_files_data, all_selected_files, selected_display, load_status]
567
- )
568
-
569
- folder_dropdown.change(
570
- update_files_for_folder,
571
- inputs=[folder_dropdown, all_files_data, all_selected_files],
572
- outputs=[file_checkboxes, all_selected_files, selected_display]
573
- )
574
-
575
- file_checkboxes.change(
576
- update_selected_files,
577
- inputs=[file_checkboxes, all_selected_files],
578
- outputs=[all_selected_files, selected_display]
579
- )
580
-
581
- select_all_btn.click(
582
- lambda choices: choices,
583
- inputs=[file_checkboxes],
584
- outputs=[file_checkboxes]
585
- )
586
-
587
- clear_selection_btn.click(
588
- clear_all_selections,
589
- outputs=[all_selected_files, file_checkboxes, selected_display]
590
- )
591
-
592
- strategy.change(
593
- update_visibility,
594
- inputs=[strategy],
595
- outputs=[num_chunks, max_chunk_size]
596
- )
597
-
598
- process_btn.click(
599
- process_files_handler,
600
- inputs=[strategy, num_chunks, max_chunk_size, output_dir, all_selected_files],
601
- outputs=[status]
602
- )
603
-
604
- return demo
605
-
606
- if __name__ == "__main__":
607
- demo = launch_dashboard()
608
- demo.launch(debug=False)