-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtask_planner.py
More file actions
227 lines (199 loc) · 10.9 KB
/
Copy pathtask_planner.py
File metadata and controls
227 lines (199 loc) · 10.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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
import re
import json
from nlp_engine import ArabicNLPEngine
from system_manager import SystemManager
class TaskPlanner:
"""
Task Planner & Executor (نظام تخطيط وتقسيم المهام المتسلسل):
Parses compound instructions, splits them into sequenceable subtasks,
executes them sequentially, and aggregates the responses.
"""
def __init__(self, nlp_engine=None, system_mgr=None):
self.nlp = nlp_engine if nlp_engine else ArabicNLPEngine()
self.system_mgr = system_mgr if system_mgr else SystemManager()
# Split markers for compound sentences (Arabic and English)
self.split_patterns = re.compile(
r'\s+(?:ثم|و|بعدين|بعدها|وكمان|وكذلك|and|then|afterwards)\s+|\s*,\s*|\s*;\s*',
re.IGNORECASE
)
def is_compound_query(self, query):
"""Determines if a query contains multiple sub-actions."""
# Clean query
parts = self.split_query(query)
valid_intents = 0
for part in parts:
if len(part.strip()) > 3:
analysis = self.nlp.parse(part)
if analysis.get("intent") != "UNKNOWN":
valid_intents += 1
return valid_intents > 1
def split_query(self, query):
"""Splits a query into sub-instructions using split markers."""
if not query:
return []
# Normalize and preprocess attached Arabic 'waw' (e.g. 'ونظف' -> 'و نظف') to prevent split failure
action_keywords = [
"افتح", "شغل", "نظف", "نضف", "شيك", "تفاصيل", "استهلاك",
"درجة", "حرارة", "احذف", "امسح", "سوي", "انشئ", "اصنع",
"اعمل", "عرض", "ابحث", "دور", "قفل", "سويلي", "اكتب"
]
normalized = query
for kw in action_keywords:
pattern = rf'\bو({kw})\b'
normalized = re.sub(pattern, r'و \1', normalized)
# Split and filter empty parts
parts = self.split_patterns.split(normalized)
return [p.strip() for p in parts if p.strip()]
def plan_tasks(self, query):
"""
Analyzes the query, splits it, and builds a structured execution plan.
Returns a list of dictionaries, each describing a subtask.
"""
sub_instructions = self.split_query(query)
plan = []
for idx, inst in enumerate(sub_instructions):
analysis = self.nlp.parse(inst)
intent = analysis.get("intent")
sub_intent = analysis.get("sub_intent")
params = analysis.get("parameters", {})
# Skip if unknown unless it's the only one
if intent == "UNKNOWN" and len(sub_instructions) > 1:
continue
plan.append({
"step": idx + 1,
"instruction": inst,
"intent": intent,
"sub_intent": sub_intent,
"parameters": params,
"status": "pending",
"result": None
})
return plan
def execute_plan(self, plan):
"""
Sequentially executes all subtasks in the plan and aggregates the final feedback.
Yields progress text for real-time streaming feedback in GUI.
"""
if not plan:
yield "عيني، ما لقيت أي مهام واضحة للتنفيذ بطلبك. شلون أقدر أساعدك؟"
return
yield "صار عيني! بدأت بتخطيط المهام وتقسيمها كالتالي:\n"
for task in plan:
yield f"• خطوة {task['step']}: {task['instruction']}\n"
yield "\nجاري التنفيذ هسة...\n\n"
results_summary = []
for task in plan:
step = task["step"]
inst = task["instruction"]
intent = task["intent"]
sub = task["sub_intent"]
params = task["parameters"]
yield f"**[جاري التنفيذ]** خطوة {step}: {inst}...\n"
# Simulate slight processing delay for clean GUI visuals
import time
time.sleep(0.5)
cmd_tag = ""
status_text = ""
try:
if intent == "SYSTEM_INFO":
if sub == "ram":
stats = self.system_mgr.get_ram_usage()
status_text = f"تم فحص الرامات: مستخدم {stats['percent']}% (متبقي {stats['free_gb']} GB)"
cmd_tag = "[RUN_COMMAND: CHECK_RAM]"
elif sub == "cpu":
usage = self.system_mgr.get_cpu_usage()
temp = self.system_mgr.get_cpu_temperature()
status_text = f"تم فحص المعالج: الاستهلاك {usage}%، درجة الحرارة {temp}°C"
cmd_tag = "[RUN_COMMAND: CHECK_CPU]"
elif sub == "temp":
temp = self.system_mgr.get_cpu_temperature()
status_text = f"درجة حرارة المعالج هسة {temp}°C"
cmd_tag = "[RUN_COMMAND: CHECK_TEMP]"
elif sub == "disk":
disks = self.system_mgr.get_all_disks()
parts = [f"{d}: {info['percent']}%" for d, info in disks.items()]
status_text = "تم فحص الأقراص: " + " | ".join(parts)
cmd_tag = "[RUN_COMMAND: CHECK_DISK]"
else:
status_text = "تم فحص مواصفات الجهاز بالكامل"
cmd_tag = "[RUN_COMMAND: CHECK_ALL]"
elif intent == "EXECUTE_CMD":
# Maps sub_intents to system manager calls
apps_map = {
"open_calc": ("الحاسبة", "calc"),
"open_notepad": ("المفكرة", "notepad"),
"open_browser": ("المتصفح", "browser"),
"open_store": ("متجر مايكروسوفت", "store"),
"open_settings": ("الإعدادات", "settings"),
"open_explorer": ("مستكشف الملفات", "explorer"),
"open_paint": ("الرسام", "paint"),
"open_taskmgr": ("مدير المهام", "taskmgr"),
"open_control": ("لوحة التحكم", "control"),
"open_cmd": ("موجه الأوامر", "cmd"),
"open_powershell": ("الباورشيل", "powershell")
}
if sub == "clean_temp":
res = self.system_mgr.clean_temp_files()
status_text = f"تم تنظيف المؤقتات بنجاح. المساحة المحذوفة {res['cleaned_mb']} MB"
cmd_tag = "[RUN_COMMAND: CLEAN_TEMP]"
elif sub == "lock_screen":
self.system_mgr.lock_screen()
status_text = "تم قفل الشاشة بنجاح"
cmd_tag = "[RUN_COMMAND: LOCK_SCREEN]"
elif sub in apps_map:
label, app_name = apps_map[sub]
res = self.system_mgr.open_app(app_name)
if res["status"] == "success":
status_text = f"تم فتح {label} بنجاح"
else:
status_text = f"فشل فتح {label}: {res.get('message')}"
cmd_tag = f"[RUN_COMMAND: OPEN_APP: {app_name}]"
else:
status_text = "تم تنفيذ أمر النظام بنجاح"
elif intent == "FILE_CREATE":
name = params.get("name", "جديد")
path = params.get("path", "")
is_folder = any(kw in inst for kw in ["فولدر", "مجلد", "folder"])
t_type = "folder" if is_folder else "file"
payload = json.dumps({"name": name, "type": t_type, "path": path}, ensure_ascii=False)
# We can call the system manager if path matches, or let UI run command.
# For compound execution safety, we let the backend try creating it
res = self.system_mgr.resolve_path(name) # resolved path
if t_type == "folder":
os.makedirs(res, exist_ok=True)
status_text = f"تم إنشاء المجلد بنجاح باسم {name}"
else:
with open(res, "w", encoding="utf-8") as f:
f.write("")
status_text = f"تم إنشاء الملف بنجاح باسم {name}"
cmd_tag = f"[RUN_COMMAND: FILE_CREATE: {payload}]"
elif intent == "FILE_DELETE":
name = params.get("name", "")
payload = json.dumps({"name": name}, ensure_ascii=False)
resolved = self.system_mgr.resolve_path(name)
if os.path.exists(resolved):
if os.path.isdir(resolved):
import shutil
shutil.rmtree(resolved)
else:
os.remove(resolved)
status_text = f"تم حذف {name} بنجاح"
else:
status_text = f"تعذر الحذف، الملف {name} غير موجود"
cmd_tag = f"[RUN_COMMAND: FILE_DELETE: {payload}]"
else:
status_text = "تمت معالجة الخطوة بنجاح"
task["status"] = "completed"
task["result"] = status_text
yield f"**[مكتمل]** خطوة {step}: {status_text}\n\n"
results_summary.append(f"الخطوة {step}: {status_text}")
except Exception as ex:
task["status"] = "failed"
task["result"] = str(ex)
yield f"**[فشل]** خطوة {step}: السبب {str(ex)}\n\n"
results_summary.append(f"الخطوة {step} (فشل): {str(ex)}")
# Final warm summary
yield "**ملخص تنفيذ المهام عيني:**\n"
for res in results_summary:
yield f"- {res}\n"
yield "\nكل الأوامر المطلوبة صارت جاهزة ومنفذة إلك! تدلل عيني."