- {Object.entries(data).map(([key, value]) => (
-
- {key}: {parseQueueData(value, indent + 1)}
-
- ))}
-
- );
- }
- return data.toString();
-}
diff --git a/frontend/python/compare.py b/frontend/python/compare.py
deleted file mode 100644
index c2ecaf25f7..0000000000
--- a/frontend/python/compare.py
+++ /dev/null
@@ -1,314 +0,0 @@
-import os
-import hashlib
-import filecmp
-from pathlib import Path
-from datetime import datetime
-import difflib
-
-
-def get_file_hash(filepath):
- """Calculate MD5 hash of a file."""
- md5_hash = hashlib.md5()
- try:
- with open(filepath, "rb") as f:
- for chunk in iter(lambda: f.read(4096), b""):
- md5_hash.update(chunk)
- return md5_hash.hexdigest()
- except Exception:
- return "Error calculating hash"
-
-
-def format_size(size_bytes):
- """Format file size nicely."""
- if size_bytes < 1000:
- return f"{size_bytes}B"
- elif size_bytes < 1000000:
- return f"{size_bytes / 1000:.1f}KB"
- else:
- return f"{size_bytes / 1000000:.1f}MB"
-
-
-def count_lines(filepath):
- """Count lines in a file safely."""
- try:
- with open(filepath, "rb") as f:
- return sum(1 for _ in f)
- except Exception:
- return 0
-
-
-def calculate_diff_ratio(file1, file2):
- """Calculate how different two files are using difflib."""
- try:
- with (
- open(file1, "r", errors="replace") as f1,
- open(file2, "r", errors="replace") as f2,
- ):
- text1 = f1.readlines()
- text2 = f2.readlines()
- matcher = difflib.SequenceMatcher(None, text1, text2)
- return 1.0 - matcher.ratio() # Higher value means more different
- except Exception:
- return 1.0 # If we can't compare, assume completely different
-
-
-def get_relative_path(file_path, base_path):
- """Get relative path from base directory."""
- return str(Path(file_path).relative_to(base_path))
-
-
-def collect_files_recursive(folder_path):
- """Recursively collect all files in a folder."""
- folder_path = Path(folder_path)
- file_dict = {}
-
- for path in folder_path.rglob("*"):
- if path.is_file():
- rel_path = get_relative_path(path, folder_path)
- file_dict[rel_path] = path
-
- return file_dict
-
-
-def compare_folders_recursive(folder1, folder2, output_file=None):
- """Compare two folders recursively and generate a detailed report."""
- # Automatically generate output filename if not specified
- if output_file is None:
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
- output_file = f"folder_comparison_{timestamp}.md"
-
- # Get folder paths
- folder1_path = Path(folder1)
- folder2_path = Path(folder2)
-
- # Get shorthand names for display
- folder1_name = folder1_path.name
- folder2_name = folder2_path.name
-
- # Get all files recursively
- print(f"Collecting files from {folder1_name}...")
- files1 = collect_files_recursive(folder1_path)
- print(f"Collecting files from {folder2_name}...")
- files2 = collect_files_recursive(folder2_path)
-
- # All unique file paths across both folders
- all_files = sorted(set(files1.keys()) | set(files2.keys()))
-
- # Calculate column widths for alignment
- max_filepath_len = max(len(file) for file in all_files) + 2
- hash_col_width = 10 # For hash comparison
- size_col_width = 20 # For size and line count
- diff_col_width = 30 # For difference description
-
- # Initialize report
- report = [
- f"# Recursive Folder Comparison Report: {folder1_name} vs {folder2_name}\n",
- f"Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n",
- "## File Comparison Table\n",
- f"| {'File Path'.ljust(max_filepath_len)} | {'Status'.ljust(hash_col_width)} | {folder1_name.ljust(size_col_width)} | {folder2_name.ljust(size_col_width)} | {'Difference'.ljust(diff_col_width)} |",
- f"|{'-' * max_filepath_len}|{'-' * hash_col_width}|{'-' * size_col_width}|{'-' * size_col_width}|{'-' * diff_col_width}|",
- ]
-
- # Track file categories
- identical_files = []
- different_files = []
- only_in_folder1 = []
- only_in_folder2 = []
-
- # Store detailed file comparisons for sorting later
- file_comparisons = []
-
- # Compare each file
- print(f"Comparing {len(all_files)} unique files...")
- for rel_path in all_files:
- in_folder1 = rel_path in files1
- in_folder2 = rel_path in files2
-
- # Default values
- status = "—"
- size1_str = "—"
- size2_str = "—"
- diff_str = "—"
- diff_ratio = 0
-
- # Get details for folder1
- if in_folder1:
- file1 = files1[rel_path]
- size1 = file1.stat().st_size
- lines1 = count_lines(file1)
- hash1 = get_file_hash(file1)
- size1_str = f"{format_size(size1)} ({lines1} lines)"
- else:
- hash1 = "—"
- size1 = 0
- lines1 = 0
-
- # Get details for folder2
- if in_folder2:
- file2 = files2[rel_path]
- size2 = file2.stat().st_size
- lines2 = count_lines(file2)
- hash2 = get_file_hash(file2)
- size2_str = f"{format_size(size2)} ({lines2} lines)"
- else:
- hash2 = "—"
- size2 = 0
- lines2 = 0
-
- # Calculate difference and determine status
- if not in_folder1:
- status = "MISSING"
- diff_str = f"Only in {folder2_name}"
- only_in_folder2.append(rel_path)
- diff_ratio = 1.0 # Completely different (missing)
- elif not in_folder2:
- status = "MISSING"
- diff_str = f"Only in {folder1_name}"
- only_in_folder1.append(rel_path)
- diff_ratio = 1.0 # Completely different (missing)
- else:
- # Both files exist, compare them
- if hash1 == hash2 and hash1 != "Error calculating hash":
- status = "IDENTICAL"
- diff_str = "Identical content"
- identical_files.append(rel_path)
- diff_ratio = 0.0
- else:
- status = "DIFFERENT"
- size_diff = size2 - size1
- lines_diff = lines2 - lines1
- sign = "+" if size_diff > 0 else ""
- sign_lines = "+" if lines_diff > 0 else ""
-
- # Calculate how different the files are
- diff_ratio = calculate_diff_ratio(file1, file2)
- different_files.append((rel_path, diff_ratio))
-
- # Format difference description
- diff_pct = int(diff_ratio * 100)
- diff_str = f"{sign}{format_size(size_diff)} ({sign_lines}{lines_diff} lines) {diff_pct}% different"
-
- # Store comparison for sorting later
- file_comparisons.append(
- {
- "rel_path": rel_path,
- "status": status,
- "size1_str": size1_str,
- "size2_str": size2_str,
- "diff_str": diff_str,
- "diff_ratio": diff_ratio,
- "in_folder1": in_folder1,
- "in_folder2": in_folder2,
- "hash1": hash1[:8] if len(hash1) > 8 else hash1,
- "hash2": hash2[:8] if len(hash2) > 8 else hash2,
- }
- )
-
- # Sort files by difference ratio (most different first)
- file_comparisons.sort(key=lambda x: x["diff_ratio"], reverse=True)
-
- # Generate the sorted table
- for comp in file_comparisons:
- hash_display = (
- f"{comp['hash1']}:{comp['hash2']}"
- if comp["status"] == "DIFFERENT"
- else comp["status"]
- )
- report.append(
- f"| {comp['rel_path'].ljust(max_filepath_len)} | "
- f"{hash_display.ljust(hash_col_width)} | "
- f"{comp['size1_str'].ljust(size_col_width)} | "
- f"{comp['size2_str'].ljust(size_col_width)} | "
- f"{comp['diff_str'].ljust(diff_col_width)} |"
- )
-
- # Sort different files by difference ratio for the detailed section
- different_files.sort(key=lambda x: x[1], reverse=True)
-
- # Add Files Missing From Each Folder sections
- report.append("\n## Files Present in One Folder But Missing in the Other\n")
-
- if only_in_folder1:
- report.append(
- f"\n### Files Only in {folder1_name} ({len(only_in_folder1)} files)"
- )
- for rel_path in sorted(only_in_folder1):
- file1 = files1[rel_path]
- size1 = file1.stat().st_size
- lines1 = count_lines(file1)
- hash1 = get_file_hash(file1)[:8]
- report.append(
- f"- `{rel_path}` ({format_size(size1)}, {lines1} lines, hash: {hash1})"
- )
-
- if only_in_folder2:
- report.append(
- f"\n### Files Only in {folder2_name} ({len(only_in_folder2)} files)"
- )
- for rel_path in sorted(only_in_folder2):
- file2 = files2[rel_path]
- size2 = file2.stat().st_size
- lines2 = count_lines(file2)
- hash2 = get_file_hash(file2)[:8]
- report.append(
- f"- `{rel_path}` ({format_size(size2)}, {lines2} lines, hash: {hash2})"
- )
-
- # Add detailed section for different files
- if different_files:
- report.append(f"\n## Files with Differences (Sorted by Most Different First)\n")
- for rel_path, diff_ratio in different_files:
- file1 = files1[rel_path]
- file2 = files2[rel_path]
- size1 = file1.stat().st_size
- size2 = file2.stat().st_size
- lines1 = count_lines(file1)
- lines2 = count_lines(file2)
- hash1 = get_file_hash(file1)[:8]
- hash2 = get_file_hash(file2)[:8]
- size_diff = size2 - size1
- lines_diff = lines2 - lines1
- diff_pct = int(diff_ratio * 100)
-
- report.append(f"### `{rel_path}` ({diff_pct}% different)")
- report.append(
- f"- {folder1_name}: {format_size(size1)}, {lines1} lines, hash: {hash1}"
- )
- report.append(
- f"- {folder2_name}: {format_size(size2)}, {lines2} lines, hash: {hash2}"
- )
- report.append(
- f"- Difference: {size_diff:+d} bytes, {lines_diff:+d} lines\n"
- )
-
- # Add summary section
- report.extend(
- [
- "\n## Summary",
- f"- **Total Unique Files**: {len(all_files)}",
- f"- **Files in {folder1_name}**: {len(files1)}",
- f"- **Files in {folder2_name}**: {len(files2)}",
- f"- **Identical Files**: {len(identical_files)}",
- f"- **Different Files**: {len(different_files)}",
- f"- **Files Only in {folder1_name}**: {len(only_in_folder1)}",
- f"- **Files Only in {folder2_name}**: {len(only_in_folder2)}",
- f"\n## Path Information",
- f"- {folder1_name}: `{folder1}`",
- f"- {folder2_name}: `{folder2}`",
- ]
- )
-
- # Write report to file
- with open(output_file, "w") as f:
- f.write("\n".join(report))
-
- print(f"Recursive comparison report written to {output_file}")
- return "\n".join(report)
-
-
-# Execute the comparison
-if __name__ == "__main__":
- folder1 = "/Users/michaelchung/storyteller-rust/frontend/apps/editor2d/src/Classes/"
- folder2 = "/Users/michaelchung/storyteller-rust/frontend/apps/editor3d/app/Classes/"
-
- report = compare_folders_recursive(folder1, folder2)
diff --git a/frontend/python/folder_comparison_20250416_133319.md b/frontend/python/folder_comparison_20250416_133319.md
deleted file mode 100644
index f9fcbe754b..0000000000
--- a/frontend/python/folder_comparison_20250416_133319.md
+++ /dev/null
@@ -1,165 +0,0 @@
-# Recursive Folder Comparison Report: Classes vs Classes
-
-Generated on: 2025-04-16 13:33:19
-
-## File Comparison Table
-
-| File Path | Status | Classes | Classes | Difference |
-|------------------------------------|----------|--------------------|--------------------|------------------------------|
-| ApiHelpers.ts | MISSING | — | 637B (17 lines) | Only in Classes |
-| ApiManager/SegmentationApi.ts | MISSING | 1.9KB (84 lines) | — | Only in Classes |
-| ApiManager/StudioGen2Api.ts | MISSING | — | 1.6KB (61 lines) | Only in Classes |
-| EnvironmentVariables.ts | MISSING | — | 263B (10 lines) | Only in Classes |
-| GetFrontendEnvironment.ts | MISSING | — | 1.9KB (65 lines) | Only in Classes |
-| ApiManager/MediaUploadApi.ts | 707d2bf2:06a93d8c | 10.3KB (349 lines) | 10.0KB (339 lines) | -255B (-10 lines) 72% different |
-| ApiManager/EngineApi.ts | c4850e80:85e20a81 | 1.0KB (39 lines) | 5.5KB (213 lines) | +4.5KB (+174 lines) 69% different |
-| ApiManager/JobsApi.ts | f7eb8e22:2aa03349 | 2.0KB (77 lines) | 1.9KB (74 lines) | -56B (-3 lines) 28% different |
-| ApiManager/ApiManager.ts | 44db0b07:67a3a046 | 5.5KB (235 lines) | 5.3KB (211 lines) | -200B (-24 lines) 14% different |
-| ApiManager/BillingApi.ts | 20051893:f5b7af84 | 1.0KB (33 lines) | 1.0KB (33 lines) | -8B (0 lines) 6% different |
-| ApiManager/VoiceDesignerApi.ts | e4d874c3:3635ba42 | 2.0KB (77 lines) | 2.1KB (78 lines) | +94B (+1 lines) 5% different |
-| ApiManager/MediaFilesApi.ts | be67aab2:44342e0f | 10.6KB (364 lines) | 10.6KB (369 lines) | +56B (+5 lines) 5% different |
-| ApiManager/PromptsApi.ts | d73d329a:c4824d2e | 648B (25 lines) | 657B (25 lines) | +9B (0 lines) 4% different |
-| ApiManager/MiscApi.ts | 298f5d93:187ad676 | 799B (26 lines) | 799B (26 lines) | 0B (0 lines) 3% different |
-| ApiManager/TtsApi.ts | 5feb5cad:6228b278 | 1.7KB (64 lines) | 1.7KB (64 lines) | +2B (0 lines) 3% different |
-| ApiManager/index.ts | 55a9094b:1fe59701 | 564B (18 lines) | 597B (19 lines) | +33B (+1 lines) 2% different |
-| ApiManager/UserBookmarksApi.ts | e3e4cb19:fd3afc78 | 5.4KB (201 lines) | 5.5KB (202 lines) | +56B (+1 lines) 2% different |
-| ApiManager/WeightsApi.ts | c12a98df:8a7dbb68 | 7.8KB (295 lines) | 7.9KB (296 lines) | +39B (+1 lines) 2% different |
-| ApiManager/VideoApi.ts | a9947328:cb947c07 | 1.9KB (70 lines) | 1.9KB (70 lines) | -11B (0 lines) 1% different |
-| ApiManager/BetaKeysApi.ts | 8d4ec6f1:33f1e4b3 | 4.3KB (167 lines) | 4.3KB (167 lines) | -3B (0 lines) 1% different |
-| ApiManager/UsersApi.ts | 65121217:72db0eae | 3.9KB (161 lines) | 3.9KB (161 lines) | -6B (0 lines) 0% different |
-| ApiManager/AnalyticsApi.ts | IDENTICAL | 944B (38 lines) | 944B (38 lines) | Identical content |
-| ApiManager/CommentsApi.ts | IDENTICAL | 2.3KB (91 lines) | 2.3KB (91 lines) | Identical content |
-| ApiManager/FeaturedItemsApi.ts | IDENTICAL | 2.3KB (96 lines) | 2.3KB (96 lines) | Identical content |
-| ApiManager/ModerationApi.ts | IDENTICAL | 960B (42 lines) | 960B (42 lines) | Identical content |
-| ApiManager/UserRatingsApi.ts | IDENTICAL | 2.4KB (92 lines) | 2.4KB (92 lines) | Identical content |
-| ApiManager/VoiceConversionApi.ts | IDENTICAL | 1.4KB (53 lines) | 1.4KB (53 lines) | Identical content |
-
-## Files Present in One Folder But Missing in the Other
-
-
-### Files Only in Classes (23 files)
-- `ApiManager/SegmentationApi.ts` (1.9KB, 84 lines, hash: bb14fbf6)
-- `ApiManager/enums/Api.ts` (254B, 7 lines, hash: ea867d98)
-- `ApiManager/enums/Billing.ts` (242B, 11 lines, hash: e47c3eaa)
-- `ApiManager/enums/Job.ts` (433B, 16 lines, hash: d148fd64)
-- `ApiManager/enums/MediaFileClass.ts` (524B, 26 lines, hash: c90ce542)
-- `ApiManager/enums/MediaFileType.ts` (1.7KB, 58 lines, hash: a2374fec)
-- `ApiManager/enums/QueryFilters.ts` (579B, 29 lines, hash: 6d10a292)
-- `ApiManager/enums/Tts.ts` (205B, 7 lines, hash: f6393d2e)
-- `ApiManager/enums/UserFeatures.ts` (167B, 6 lines, hash: 05d49e51)
-- `ApiManager/enums/Visibility.ts` (92B, 5 lines, hash: 297d031b)
-- `ApiManager/enums/WeightCategory.ts` (180B, 8 lines, hash: f9be3d32)
-- `ApiManager/enums/WeightType.ts` (208B, 11 lines, hash: 80436726)
-- `ApiManager/models/BetaKeys.ts` (502B, 26 lines, hash: 7c718ac6)
-- `ApiManager/models/Billing.tsx` (416B, 17 lines, hash: 8db6eb3b)
-- `ApiManager/models/Dataset.ts` (588B, 23 lines, hash: 6af860ff)
-- `ApiManager/models/Job.ts` (1.8KB, 72 lines, hash: 9d7b385a)
-- `ApiManager/models/MediaFile.ts` (1.8KB, 59 lines, hash: 41778349)
-- `ApiManager/models/Pagination.ts` (200B, 9 lines, hash: 837b24d3)
-- `ApiManager/models/Prompts.ts` (424B, 16 lines, hash: 8ef1f366)
-- `ApiManager/models/StatusAlert.ts` (175B, 9 lines, hash: fcee4684)
-- `ApiManager/models/UserBookmark.ts` (1.6KB, 75 lines, hash: 8f70d1b1)
-- `ApiManager/models/Users.ts` (1.3KB, 50 lines, hash: 5ed82bbd)
-- `ApiManager/models/Weight.ts` (767B, 40 lines, hash: 3f9cccdb)
-
-### Files Only in Classes (4 files)
-- `ApiHelpers.ts` (637B, 17 lines, hash: 9b638c6c)
-- `ApiManager/StudioGen2Api.ts` (1.6KB, 61 lines, hash: b2707195)
-- `EnvironmentVariables.ts` (263B, 10 lines, hash: 29c93666)
-- `GetFrontendEnvironment.ts` (1.9KB, 65 lines, hash: 7ee8b738)
-
-## Files with Differences (Sorted by Most Different First)
-
-### `ApiManager/MediaUploadApi.ts` (72% different)
-- Classes: 10.3KB, 349 lines, hash: 707d2bf2
-- Classes: 10.0KB, 339 lines, hash: 06a93d8c
-- Difference: -255 bytes, -10 lines
-
-### `ApiManager/EngineApi.ts` (69% different)
-- Classes: 1.0KB, 39 lines, hash: c4850e80
-- Classes: 5.5KB, 213 lines, hash: 85e20a81
-- Difference: +4469 bytes, +174 lines
-
-### `ApiManager/JobsApi.ts` (28% different)
-- Classes: 2.0KB, 77 lines, hash: f7eb8e22
-- Classes: 1.9KB, 74 lines, hash: 2aa03349
-- Difference: -56 bytes, -3 lines
-
-### `ApiManager/ApiManager.ts` (14% different)
-- Classes: 5.5KB, 235 lines, hash: 44db0b07
-- Classes: 5.3KB, 211 lines, hash: 67a3a046
-- Difference: -200 bytes, -24 lines
-
-### `ApiManager/BillingApi.ts` (6% different)
-- Classes: 1.0KB, 33 lines, hash: 20051893
-- Classes: 1.0KB, 33 lines, hash: f5b7af84
-- Difference: -8 bytes, +0 lines
-
-### `ApiManager/VoiceDesignerApi.ts` (5% different)
-- Classes: 2.0KB, 77 lines, hash: e4d874c3
-- Classes: 2.1KB, 78 lines, hash: 3635ba42
-- Difference: +94 bytes, +1 lines
-
-### `ApiManager/MediaFilesApi.ts` (5% different)
-- Classes: 10.6KB, 364 lines, hash: be67aab2
-- Classes: 10.6KB, 369 lines, hash: 44342e0f
-- Difference: +56 bytes, +5 lines
-
-### `ApiManager/PromptsApi.ts` (4% different)
-- Classes: 648B, 25 lines, hash: d73d329a
-- Classes: 657B, 25 lines, hash: c4824d2e
-- Difference: +9 bytes, +0 lines
-
-### `ApiManager/MiscApi.ts` (3% different)
-- Classes: 799B, 26 lines, hash: 298f5d93
-- Classes: 799B, 26 lines, hash: 187ad676
-- Difference: +0 bytes, +0 lines
-
-### `ApiManager/TtsApi.ts` (3% different)
-- Classes: 1.7KB, 64 lines, hash: 5feb5cad
-- Classes: 1.7KB, 64 lines, hash: 6228b278
-- Difference: +2 bytes, +0 lines
-
-### `ApiManager/index.ts` (2% different)
-- Classes: 564B, 18 lines, hash: 55a9094b
-- Classes: 597B, 19 lines, hash: 1fe59701
-- Difference: +33 bytes, +1 lines
-
-### `ApiManager/UserBookmarksApi.ts` (2% different)
-- Classes: 5.4KB, 201 lines, hash: e3e4cb19
-- Classes: 5.5KB, 202 lines, hash: fd3afc78
-- Difference: +56 bytes, +1 lines
-
-### `ApiManager/WeightsApi.ts` (2% different)
-- Classes: 7.8KB, 295 lines, hash: c12a98df
-- Classes: 7.9KB, 296 lines, hash: 8a7dbb68
-- Difference: +39 bytes, +1 lines
-
-### `ApiManager/VideoApi.ts` (1% different)
-- Classes: 1.9KB, 70 lines, hash: a9947328
-- Classes: 1.9KB, 70 lines, hash: cb947c07
-- Difference: -11 bytes, +0 lines
-
-### `ApiManager/BetaKeysApi.ts` (1% different)
-- Classes: 4.3KB, 167 lines, hash: 8d4ec6f1
-- Classes: 4.3KB, 167 lines, hash: 33f1e4b3
-- Difference: -3 bytes, +0 lines
-
-### `ApiManager/UsersApi.ts` (0% different)
-- Classes: 3.9KB, 161 lines, hash: 65121217
-- Classes: 3.9KB, 161 lines, hash: 72db0eae
-- Difference: -6 bytes, +0 lines
-
-
-## Summary
-- **Total Unique Files**: 49
-- **Files in Classes**: 45
-- **Files in Classes**: 26
-- **Identical Files**: 6
-- **Different Files**: 16
-- **Files Only in Classes**: 23
-- **Files Only in Classes**: 4
-
-## Path Information
-- Classes: `/Users/michaelchung/storyteller-rust/frontend/apps/editor2d/src/Classes/`
-- Classes: `/Users/michaelchung/storyteller-rust/frontend/apps/editor3d/app/Classes/`
\ No newline at end of file