Update app.py
Browse files
app.py
CHANGED
|
@@ -652,23 +652,29 @@ def execute_staged_tool(tool_name: str, args: dict) -> str:
|
|
| 652 |
# placeholder message since they can't be meaningfully injected as text.
|
| 653 |
# =============================================================================
|
| 654 |
|
|
|
|
|
|
|
|
|
|
| 655 |
TEXT_EXTENSIONS = {
|
| 656 |
-
|
| 657 |
-
'.
|
| 658 |
-
|
| 659 |
-
'.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 660 |
}
|
| 661 |
|
| 662 |
|
| 663 |
-
def process_uploaded_file(file) -> str:
|
| 664 |
-
"""Read an uploaded file and format it for conversation context.
|
| 665 |
|
| 666 |
-
|
| 667 |
-
|
| 668 |
|
| 669 |
-
|
| 670 |
-
|
| 671 |
-
|
|
|
|
| 672 |
"""
|
| 673 |
if file is None:
|
| 674 |
return ""
|
|
@@ -677,18 +683,41 @@ def process_uploaded_file(file) -> str:
|
|
| 677 |
file_name = os.path.basename(file_path)
|
| 678 |
suffix = os.path.splitext(file_name)[1].lower()
|
| 679 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 680 |
if suffix in TEXT_EXTENSIONS or suffix == '':
|
| 681 |
try:
|
| 682 |
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
| 683 |
content = f.read()
|
| 684 |
-
# Cap at 50KB to avoid overwhelming context
|
| 685 |
if len(content) > 50000:
|
| 686 |
-
content = content[:50000] + f"\n\n... (
|
| 687 |
return f"π **Uploaded: {file_name}**\n```\n{content}\n```"
|
| 688 |
except Exception as e:
|
| 689 |
-
return f"π **Uploaded: {file_name}** (
|
| 690 |
-
|
| 691 |
-
|
|
|
|
| 692 |
|
| 693 |
|
| 694 |
# =============================================================================
|
|
@@ -1085,13 +1114,14 @@ with gr.Blocks(
|
|
| 1085 |
gr.Markdown("---")
|
| 1086 |
gr.Markdown("### π Upload Context")
|
| 1087 |
file_input = gr.File(
|
| 1088 |
-
|
| 1089 |
-
|
| 1090 |
-
|
| 1091 |
-
|
| 1092 |
-
|
| 1093 |
-
|
| 1094 |
-
|
|
|
|
| 1095 |
gr.Markdown(
|
| 1096 |
"*Upload code, configs, or docs to include in your message.*"
|
| 1097 |
)
|
|
|
|
| 652 |
# placeholder message since they can't be meaningfully injected as text.
|
| 653 |
# =============================================================================
|
| 654 |
|
| 655 |
+
# CHANGELOG [2026-02-01 - Clawdbot]
|
| 656 |
+
# WHY: Expanded to cover the full spectrum of E-T Systems and modern dev environments.
|
| 657 |
+
|
| 658 |
TEXT_EXTENSIONS = {
|
| 659 |
+
# Core Logic & Scripts
|
| 660 |
+
'.py', '.js', '.ts', '.jsx', '.tsx', '.go', '.rs', '.c', '.cpp', '.h', '.hpp', '.java', '.php', '.rb',
|
| 661 |
+
# Config & Data
|
| 662 |
+
'.json', '.yaml', '.yml', '.toml', '.xml', '.sql', '.csv', '.env', '.ini', '.conf', '.cfg',
|
| 663 |
+
# Infrastructure & Web
|
| 664 |
+
'.dockerfile', '.Dockerfile', '.sh', '.bash', '.html', '.css', '.scss', '.less',
|
| 665 |
+
# Documentation & Workspace
|
| 666 |
+
'.md', '.txt', '.rst', '.gitignore', '.dockerignore', '.mjs', '.cjs', '.lock'
|
| 667 |
}
|
| 668 |
|
| 669 |
|
|
|
|
|
|
|
| 670 |
|
| 671 |
+
import zipfile
|
| 672 |
+
import io
|
| 673 |
|
| 674 |
+
def process_uploaded_file(file) -> str:
|
| 675 |
+
"""
|
| 676 |
+
WHY: Ingests archives or individual files to anchor the recursive memory
|
| 677 |
+
in current ground truth, preventing model drift.
|
| 678 |
"""
|
| 679 |
if file is None:
|
| 680 |
return ""
|
|
|
|
| 683 |
file_name = os.path.basename(file_path)
|
| 684 |
suffix = os.path.splitext(file_name)[1].lower()
|
| 685 |
|
| 686 |
+
# --- ZIP ARCHIVE HANDLING ---
|
| 687 |
+
if suffix == '.zip':
|
| 688 |
+
zip_output = [f"π¦ **Archive Extracted: {file_name}**"]
|
| 689 |
+
try:
|
| 690 |
+
with zipfile.ZipFile(file_path, 'r') as z:
|
| 691 |
+
for z_info in z.infolist():
|
| 692 |
+
# Skip directories and hidden metadata
|
| 693 |
+
if z_info.is_dir() or any(p.startswith('.') for p in z_info.filename.split('/')):
|
| 694 |
+
continue
|
| 695 |
+
|
| 696 |
+
z_suffix = os.path.splitext(z_info.filename)[1].lower()
|
| 697 |
+
if z_suffix in TEXT_EXTENSIONS:
|
| 698 |
+
with z.open(z_info) as f:
|
| 699 |
+
content = f.read().decode('utf-8', errors='ignore')
|
| 700 |
+
# Truncate large files to save Kimi's context tokens
|
| 701 |
+
if len(content) > 15000:
|
| 702 |
+
content = content[:15000] + "\n... (File Truncated)"
|
| 703 |
+
zip_output.append(f"π `{z_info.filename}`\n```\n{content}\n```")
|
| 704 |
+
return "\n\n".join(zip_output)
|
| 705 |
+
except Exception as e:
|
| 706 |
+
return f"β Error extracting ZIP {file_name}: {e}"
|
| 707 |
+
|
| 708 |
+
# --- INDIVIDUAL FILE HANDLING ---
|
| 709 |
if suffix in TEXT_EXTENSIONS or suffix == '':
|
| 710 |
try:
|
| 711 |
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
| 712 |
content = f.read()
|
|
|
|
| 713 |
if len(content) > 50000:
|
| 714 |
+
content = content[:50000] + f"\n\n... (Large File Truncated)"
|
| 715 |
return f"π **Uploaded: {file_name}**\n```\n{content}\n```"
|
| 716 |
except Exception as e:
|
| 717 |
+
return f"π **Uploaded: {file_name}** (Read Error: {e})"
|
| 718 |
+
|
| 719 |
+
return f"π **Uploaded: {file_name}** (Binary/Unsupported Format)"
|
| 720 |
+
|
| 721 |
|
| 722 |
|
| 723 |
# =============================================================================
|
|
|
|
| 1114 |
gr.Markdown("---")
|
| 1115 |
gr.Markdown("### π Upload Context")
|
| 1116 |
file_input = gr.File(
|
| 1117 |
+
label="Drop files or ZIPs here",
|
| 1118 |
+
file_types=[
|
| 1119 |
+
'.py', '.js', '.ts', '.tsx', '.json', '.md', '.txt',
|
| 1120 |
+
'.yaml', '.yml', '.html', '.css', '.sh', '.zip',
|
| 1121 |
+
'.toml', '.sql', '.dockerfile', '.env'
|
| 1122 |
+
],
|
| 1123 |
+
file_count="multiple" # Allows selecting multiple files at once
|
| 1124 |
+
)
|
| 1125 |
gr.Markdown(
|
| 1126 |
"*Upload code, configs, or docs to include in your message.*"
|
| 1127 |
)
|