1Egyb commited on
Commit
0c99645
·
verified ·
1 Parent(s): 81e0e45

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -70
app.py CHANGED
@@ -17,7 +17,7 @@ MAX_FILE_SIZE_BYTES = 200 * 1024
17
  MAX_TOTAL_FILES = 500
18
  MAX_EXTRACTED_BYTES = 20 * 1024 * 1024
19
  MODEL_ID = os.environ.get('HF_MODEL_ID', 'moonshotai/Kimi-K2-Instruct')
20
- HF_TOKEN = os.environ.get('HF_TOKEN') # تأكد من ضبط هذا المتغير
21
 
22
  # --------------------------- منطق Sandbox ---------------------------
23
  class Sandbox:
@@ -39,20 +39,21 @@ class Sandbox:
39
 
40
  self.cleanup()
41
  self.dir = tempfile.mkdtemp(prefix="dev_sandbox_")
42
- zip_path = zip_file.name
43
 
44
  try:
 
 
 
45
  with pyzipper.AESZipFile(zip_path, 'r') as zf:
46
  if password:
47
  zf.setpassword(password.encode('utf-8'))
48
 
49
- # استخراج آمن
50
  for info in zf.infolist():
51
  if info.filename.startswith('__MACOSX') or info.is_dir():
52
  continue
53
  dest_path = os.path.normpath(os.path.join(self.dir, info.filename))
54
  if not dest_path.startswith(os.path.normpath(self.dir) + os.sep):
55
- continue # تخطي الملفات المشبوهة
56
  zf.extract(info, path=self.dir)
57
 
58
  self.files_content = self.read_allowed_files(self.dir)
@@ -94,9 +95,9 @@ class Sandbox:
94
 
95
  def create_zip(self):
96
  if not self.dir: return None
97
- out_path = tempfile.mktemp()
98
- shutil.make_archive(out_path, 'zip', self.dir)
99
- return out_path + ".zip"
100
 
101
  sandbox = Sandbox()
102
  client = InferenceClient(api_key=HF_TOKEN) if HF_TOKEN else None
@@ -104,33 +105,24 @@ client = InferenceClient(api_key=HF_TOKEN) if HF_TOKEN else None
104
  # --------------------------- دوال الدردشة والمعالجة ---------------------------
105
 
106
  def handle_user_msg(message, history):
107
- # تحديث الواجهة فوراً برسالة المستخدم وتفريغ صندوق الإدخال
108
  return "", history + [{"role": "user", "content": message}]
109
 
110
  def handle_assistant_res(history):
111
  if not HF_TOKEN or not client:
112
- history.append({"role": "assistant", "content": "⚠️ خطأ: HF_TOKEN غير مضبوط. يرجى إضافة التوكن في الإعدادات."})
113
  yield history
114
  return
115
 
116
- # بناء السياق من الملفات المرفوعة
117
- context = "سياق الملفات الحالية في المشروع:\n"
118
- if not sandbox.files_content:
119
- context += "(لا توجد ملفات مرفوعة حالياً)\n"
120
- else:
121
- for name, content in sandbox.files_content.items():
122
- context += f"\n--- FILE: {name} ---\n{content[:2000]}\n" # نرسل أول 2000 حرف لتوفير التوكنز
123
 
124
- # إعداد الرسائل للنموذج
125
  system_instr = (
126
- "أنت مساعد برمجي خبير. عند طلب تعديل، أجب دائماً بالتنسيق التالي لكل ملف:\n"
127
  "[ملف: اسم_الملف_هنا]\n"
128
- "```language\n"
129
- "المحتوى الكامل للملف بعد التعديل\n"
130
- "```"
131
  )
132
 
133
- # استخراج آخر طلب للمستخدم
134
  user_query = history[-1]["content"]
135
  messages = [
136
  {"role": "system", "content": system_instr},
@@ -140,85 +132,62 @@ def handle_assistant_res(history):
140
  response = ""
141
  history.append({"role": "assistant", "content": ""})
142
 
143
- try:
 
144
  for chunk in client.chat_completion(model=MODEL_ID, messages=messages, max_tokens=2048, stream=True):
145
- # التأكد من أن القائمة ليست فارغة وأن هناك محتوى في الاختيار الأول
146
- if chunk.choices and len(chunk.choices) > 0:
147
  token = chunk.choices[0].delta.content
148
  if token:
149
  response += token
150
  history[-1]["content"] = response
151
  yield history
152
  except Exception as e:
153
- # إذا انقطع الات��ال بعد البدء، نحتفظ بما تم كتابته ونضيف الخطأ
154
- error_msg = f"\n\n❌ انقطع الاتصال: {str(e)}"
155
- history[-1]["content"] += error_msg
156
  yield history
157
 
158
-
159
  def run_apply_and_zip(history):
160
- if not history: return None, "لا توجد محادثة."
 
161
 
162
- last_bot_msg = history[-1]["content"]
163
- # Regex للبحث عن بلوكات الأكواد مع أسماء الملفات
164
  pattern = r"\[\s*(?:ملف|file)\s*:\s*(.*?)\s*\]\s*```.*?\n(.*?)```"
165
- matches = re.findall(pattern, last_bot_msg, re.DOTALL | re.IGNORECASE)
166
 
167
  if not matches:
168
- return None, "⚠️ لم يتم العثور على تعديلات بتنسيق [ملف: ...]"
169
 
170
  for name, code in matches:
171
  sandbox.update_file(name.strip(), code.strip())
172
 
173
- zip_result = sandbox.create_zip()
174
- return zip_result, f"✅ تم تحديث {len(matches)} ملف وحزم المشروع."
175
 
176
  # --------------------------- واجهة Gradio ---------------------------
177
- with gr.Blocks(theme=gr.themes.Soft(), title="Smart Dev Sandbox") as demo:
178
- gr.Markdown("# 🚀 Smart Dev Sandbox \n### التعديل الذكي على المشاريع (ZIP/DOCX/PDF)")
179
 
180
  with gr.Row():
181
  with gr.Column(scale=2):
182
- chatbot = gr.Chatbot(type="messages", label="المساعد المبرمج", height=500)
183
- msg_input = gr.Textbox(
184
- label="اطلب تعديلاً",
185
- placeholder="مثال: اجعل لون الخلفية في style.css داكناً...",
186
- show_label=False
187
- )
188
- with gr.Row():
189
- send_btn = gr.Button("إرسال الطلب", variant="primary")
190
- clear_btn = gr.Button("مسح الدردشة")
191
 
192
  with gr.Column(scale=1):
193
- with gr.Group():
194
- file_zip = gr.File(label="1. ارفع مشروعك (ZIP)")
195
- pwd = gr.Textbox(label="كلمة السر", type="password", placeholder="اتركه فارغاً إن لم يوجد")
196
- load_btn = gr.Button("تحليل الملفات 🔍")
197
-
198
  status = gr.Markdown("🟢 **الحالة:** جاهز")
199
-
200
- with gr.Group():
201
- apply_btn = gr.Button("2. تطبيق التعديلات وحفظ ZIP ✨", variant="stop")
202
- download = gr.File(label="3. تحميل المشروع المعدل")
203
-
204
- # ربط الأحداث (Logic flow)
205
- # عند الضغط على إرسال أو Enter
206
- msg_event = send_btn.click(
207
- handle_user_msg, [msg_input, chatbot], [msg_input, chatbot], queue=False
208
- ).then(
209
  handle_assistant_res, [chatbot], [chatbot]
210
  )
211
-
212
- msg_input.submit(
213
- handle_user_msg, [msg_input, chatbot], [msg_input, chatbot], queue=False
214
- ).then(
215
  handle_assistant_res, [chatbot], [chatbot]
216
  )
217
-
218
- # أزرار التحكم الأخرى
219
  load_btn.click(sandbox.reset, [file_zip, pwd], [status])
220
  apply_btn.click(run_apply_and_zip, [chatbot], [download, status])
221
- clear_btn.click(lambda: [], None, chatbot, queue=False)
222
 
223
  if __name__ == "__main__":
224
- demo.launch(debug=True)
 
17
  MAX_TOTAL_FILES = 500
18
  MAX_EXTRACTED_BYTES = 20 * 1024 * 1024
19
  MODEL_ID = os.environ.get('HF_MODEL_ID', 'moonshotai/Kimi-K2-Instruct')
20
+ HF_TOKEN = os.environ.get('HF_TOKEN')
21
 
22
  # --------------------------- منطق Sandbox ---------------------------
23
  class Sandbox:
 
39
 
40
  self.cleanup()
41
  self.dir = tempfile.mkdtemp(prefix="dev_sandbox_")
 
42
 
43
  try:
44
+ # استخدام getattr للتعامل مع كائنات Gradio المختلفة
45
+ zip_path = zip_file.name if hasattr(zip_file, 'name') else zip_file
46
+
47
  with pyzipper.AESZipFile(zip_path, 'r') as zf:
48
  if password:
49
  zf.setpassword(password.encode('utf-8'))
50
 
 
51
  for info in zf.infolist():
52
  if info.filename.startswith('__MACOSX') or info.is_dir():
53
  continue
54
  dest_path = os.path.normpath(os.path.join(self.dir, info.filename))
55
  if not dest_path.startswith(os.path.normpath(self.dir) + os.sep):
56
+ continue
57
  zf.extract(info, path=self.dir)
58
 
59
  self.files_content = self.read_allowed_files(self.dir)
 
95
 
96
  def create_zip(self):
97
  if not self.dir: return None
98
+ temp_zip_base = tempfile.mktemp()
99
+ shutil.make_archive(temp_zip_base, 'zip', self.dir)
100
+ return temp_zip_base + ".zip"
101
 
102
  sandbox = Sandbox()
103
  client = InferenceClient(api_key=HF_TOKEN) if HF_TOKEN else None
 
105
  # --------------------------- دوال الدردشة والمعالجة ---------------------------
106
 
107
  def handle_user_msg(message, history):
 
108
  return "", history + [{"role": "user", "content": message}]
109
 
110
  def handle_assistant_res(history):
111
  if not HF_TOKEN or not client:
112
+ history.append({"role": "assistant", "content": "⚠️ خطأ: HF_TOKEN غير مضبوط."})
113
  yield history
114
  return
115
 
116
+ context = "سياق المشروع:\n"
117
+ for name, content in sandbox.files_content.items():
118
+ context += f"\n--- FILE: {name} ---\n{content[:1500]}\n"
 
 
 
 
119
 
 
120
  system_instr = (
121
+ "أنت مساعد برمجي خبير. عند طلب تعديل، أجب دائماً بالتنسيق التالي:\n"
122
  "[ملف: اسم_الملف_هنا]\n"
123
+ "```language\nالمحتوى المحدث\n```"
 
 
124
  )
125
 
 
126
  user_query = history[-1]["content"]
127
  messages = [
128
  {"role": "system", "content": system_instr},
 
132
  response = ""
133
  history.append({"role": "assistant", "content": ""})
134
 
135
+ try:
136
+ # تصحيح منطق استلام الـ Chunks لتجنب خطأ Index out of range
137
  for chunk in client.chat_completion(model=MODEL_ID, messages=messages, max_tokens=2048, stream=True):
138
+ if hasattr(chunk, 'choices') and len(chunk.choices) > 0:
 
139
  token = chunk.choices[0].delta.content
140
  if token:
141
  response += token
142
  history[-1]["content"] = response
143
  yield history
144
  except Exception as e:
145
+ history[-1]["content"] += f"\n\n❌ خطأ أثناء البث: {str(e)}"
 
 
146
  yield history
147
 
 
148
  def run_apply_and_zip(history):
149
+ if not history or history[-1]["role"] != "assistant":
150
+ return None, "⚠️ لا يوجد رد من الوكيل لتطبيقه."
151
 
152
+ text = history[-1]["content"]
 
153
  pattern = r"\[\s*(?:ملف|file)\s*:\s*(.*?)\s*\]\s*```.*?\n(.*?)```"
154
+ matches = re.findall(pattern, text, re.DOTALL | re.IGNORECASE)
155
 
156
  if not matches:
157
+ return None, "⚠️ لم أجد أكواداً بتنسيق [ملف: ...]"
158
 
159
  for name, code in matches:
160
  sandbox.update_file(name.strip(), code.strip())
161
 
162
+ return sandbox.create_zip(), f"✅ تم تحديث {len(matches)} ملف."
 
163
 
164
  # --------------------------- واجهة Gradio ---------------------------
165
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
166
+ gr.Markdown("# 🚀 Smart Dev Sandbox PRO")
167
 
168
  with gr.Row():
169
  with gr.Column(scale=2):
170
+ chatbot = gr.Chatbot(type="messages", label="الدردشة البرمجية", height=450)
171
+ msg_input = gr.Textbox(placeholder="اطلب تعديلاً على الملفات المرفوعة...", show_label=False)
172
+ send_btn = gr.Button("إرسال الطلب ", variant="primary")
 
 
 
 
 
 
173
 
174
  with gr.Column(scale=1):
175
+ file_zip = gr.File(label="1. ارفع ملف ZIP")
176
+ pwd = gr.Textbox(label="كلمة السر (اختياري)", type="password")
177
+ load_btn = gr.Button("تحليل الملفات")
 
 
178
  status = gr.Markdown("🟢 **الحالة:** جاهز")
179
+ apply_btn = gr.Button("2. تطبيق وحفظ ZIP", variant="stop")
180
+ download = gr.File(label="تحميل المشروع")
181
+
182
+ # الأحداث
183
+ msg_input.submit(handle_user_msg, [msg_input, chatbot], [msg_input, chatbot]).then(
 
 
 
 
 
184
  handle_assistant_res, [chatbot], [chatbot]
185
  )
186
+ send_btn.click(handle_user_msg, [msg_input, chatbot], [msg_input, chatbot]).then(
 
 
 
187
  handle_assistant_res, [chatbot], [chatbot]
188
  )
 
 
189
  load_btn.click(sandbox.reset, [file_zip, pwd], [status])
190
  apply_btn.click(run_apply_and_zip, [chatbot], [download, status])
 
191
 
192
  if __name__ == "__main__":
193
+ demo.launch()