mcli-framework 7.0.0__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 mcli-framework might be problematic. Click here for more details.

Files changed (186) hide show
  1. mcli/app/chat_cmd.py +42 -0
  2. mcli/app/commands_cmd.py +226 -0
  3. mcli/app/completion_cmd.py +216 -0
  4. mcli/app/completion_helpers.py +288 -0
  5. mcli/app/cron_test_cmd.py +697 -0
  6. mcli/app/logs_cmd.py +419 -0
  7. mcli/app/main.py +492 -0
  8. mcli/app/model/model.py +1060 -0
  9. mcli/app/model_cmd.py +227 -0
  10. mcli/app/redis_cmd.py +269 -0
  11. mcli/app/video/video.py +1114 -0
  12. mcli/app/visual_cmd.py +303 -0
  13. mcli/chat/chat.py +2409 -0
  14. mcli/chat/command_rag.py +514 -0
  15. mcli/chat/enhanced_chat.py +652 -0
  16. mcli/chat/system_controller.py +1010 -0
  17. mcli/chat/system_integration.py +1016 -0
  18. mcli/cli.py +25 -0
  19. mcli/config.toml +20 -0
  20. mcli/lib/api/api.py +586 -0
  21. mcli/lib/api/daemon_client.py +203 -0
  22. mcli/lib/api/daemon_client_local.py +44 -0
  23. mcli/lib/api/daemon_decorator.py +217 -0
  24. mcli/lib/api/mcli_decorators.py +1032 -0
  25. mcli/lib/auth/auth.py +85 -0
  26. mcli/lib/auth/aws_manager.py +85 -0
  27. mcli/lib/auth/azure_manager.py +91 -0
  28. mcli/lib/auth/credential_manager.py +192 -0
  29. mcli/lib/auth/gcp_manager.py +93 -0
  30. mcli/lib/auth/key_manager.py +117 -0
  31. mcli/lib/auth/mcli_manager.py +93 -0
  32. mcli/lib/auth/token_manager.py +75 -0
  33. mcli/lib/auth/token_util.py +1011 -0
  34. mcli/lib/config/config.py +47 -0
  35. mcli/lib/discovery/__init__.py +1 -0
  36. mcli/lib/discovery/command_discovery.py +274 -0
  37. mcli/lib/erd/erd.py +1345 -0
  38. mcli/lib/erd/generate_graph.py +453 -0
  39. mcli/lib/files/files.py +76 -0
  40. mcli/lib/fs/fs.py +109 -0
  41. mcli/lib/lib.py +29 -0
  42. mcli/lib/logger/logger.py +611 -0
  43. mcli/lib/performance/optimizer.py +409 -0
  44. mcli/lib/performance/rust_bridge.py +502 -0
  45. mcli/lib/performance/uvloop_config.py +154 -0
  46. mcli/lib/pickles/pickles.py +50 -0
  47. mcli/lib/search/cached_vectorizer.py +479 -0
  48. mcli/lib/services/data_pipeline.py +460 -0
  49. mcli/lib/services/lsh_client.py +441 -0
  50. mcli/lib/services/redis_service.py +387 -0
  51. mcli/lib/shell/shell.py +137 -0
  52. mcli/lib/toml/toml.py +33 -0
  53. mcli/lib/ui/styling.py +47 -0
  54. mcli/lib/ui/visual_effects.py +634 -0
  55. mcli/lib/watcher/watcher.py +185 -0
  56. mcli/ml/api/app.py +215 -0
  57. mcli/ml/api/middleware.py +224 -0
  58. mcli/ml/api/routers/admin_router.py +12 -0
  59. mcli/ml/api/routers/auth_router.py +244 -0
  60. mcli/ml/api/routers/backtest_router.py +12 -0
  61. mcli/ml/api/routers/data_router.py +12 -0
  62. mcli/ml/api/routers/model_router.py +302 -0
  63. mcli/ml/api/routers/monitoring_router.py +12 -0
  64. mcli/ml/api/routers/portfolio_router.py +12 -0
  65. mcli/ml/api/routers/prediction_router.py +267 -0
  66. mcli/ml/api/routers/trade_router.py +12 -0
  67. mcli/ml/api/routers/websocket_router.py +76 -0
  68. mcli/ml/api/schemas.py +64 -0
  69. mcli/ml/auth/auth_manager.py +425 -0
  70. mcli/ml/auth/models.py +154 -0
  71. mcli/ml/auth/permissions.py +302 -0
  72. mcli/ml/backtesting/backtest_engine.py +502 -0
  73. mcli/ml/backtesting/performance_metrics.py +393 -0
  74. mcli/ml/cache.py +400 -0
  75. mcli/ml/cli/main.py +398 -0
  76. mcli/ml/config/settings.py +394 -0
  77. mcli/ml/configs/dvc_config.py +230 -0
  78. mcli/ml/configs/mlflow_config.py +131 -0
  79. mcli/ml/configs/mlops_manager.py +293 -0
  80. mcli/ml/dashboard/app.py +532 -0
  81. mcli/ml/dashboard/app_integrated.py +738 -0
  82. mcli/ml/dashboard/app_supabase.py +560 -0
  83. mcli/ml/dashboard/app_training.py +615 -0
  84. mcli/ml/dashboard/cli.py +51 -0
  85. mcli/ml/data_ingestion/api_connectors.py +501 -0
  86. mcli/ml/data_ingestion/data_pipeline.py +567 -0
  87. mcli/ml/data_ingestion/stream_processor.py +512 -0
  88. mcli/ml/database/migrations/env.py +94 -0
  89. mcli/ml/database/models.py +667 -0
  90. mcli/ml/database/session.py +200 -0
  91. mcli/ml/experimentation/ab_testing.py +845 -0
  92. mcli/ml/features/ensemble_features.py +607 -0
  93. mcli/ml/features/political_features.py +676 -0
  94. mcli/ml/features/recommendation_engine.py +809 -0
  95. mcli/ml/features/stock_features.py +573 -0
  96. mcli/ml/features/test_feature_engineering.py +346 -0
  97. mcli/ml/logging.py +85 -0
  98. mcli/ml/mlops/data_versioning.py +518 -0
  99. mcli/ml/mlops/experiment_tracker.py +377 -0
  100. mcli/ml/mlops/model_serving.py +481 -0
  101. mcli/ml/mlops/pipeline_orchestrator.py +614 -0
  102. mcli/ml/models/base_models.py +324 -0
  103. mcli/ml/models/ensemble_models.py +675 -0
  104. mcli/ml/models/recommendation_models.py +474 -0
  105. mcli/ml/models/test_models.py +487 -0
  106. mcli/ml/monitoring/drift_detection.py +676 -0
  107. mcli/ml/monitoring/metrics.py +45 -0
  108. mcli/ml/optimization/portfolio_optimizer.py +834 -0
  109. mcli/ml/preprocessing/data_cleaners.py +451 -0
  110. mcli/ml/preprocessing/feature_extractors.py +491 -0
  111. mcli/ml/preprocessing/ml_pipeline.py +382 -0
  112. mcli/ml/preprocessing/politician_trading_preprocessor.py +569 -0
  113. mcli/ml/preprocessing/test_preprocessing.py +294 -0
  114. mcli/ml/scripts/populate_sample_data.py +200 -0
  115. mcli/ml/tasks.py +400 -0
  116. mcli/ml/tests/test_integration.py +429 -0
  117. mcli/ml/tests/test_training_dashboard.py +387 -0
  118. mcli/public/oi/oi.py +15 -0
  119. mcli/public/public.py +4 -0
  120. mcli/self/self_cmd.py +1246 -0
  121. mcli/workflow/daemon/api_daemon.py +800 -0
  122. mcli/workflow/daemon/async_command_database.py +681 -0
  123. mcli/workflow/daemon/async_process_manager.py +591 -0
  124. mcli/workflow/daemon/client.py +530 -0
  125. mcli/workflow/daemon/commands.py +1196 -0
  126. mcli/workflow/daemon/daemon.py +905 -0
  127. mcli/workflow/daemon/daemon_api.py +59 -0
  128. mcli/workflow/daemon/enhanced_daemon.py +571 -0
  129. mcli/workflow/daemon/process_cli.py +244 -0
  130. mcli/workflow/daemon/process_manager.py +439 -0
  131. mcli/workflow/daemon/test_daemon.py +275 -0
  132. mcli/workflow/dashboard/dashboard_cmd.py +113 -0
  133. mcli/workflow/docker/docker.py +0 -0
  134. mcli/workflow/file/file.py +100 -0
  135. mcli/workflow/gcloud/config.toml +21 -0
  136. mcli/workflow/gcloud/gcloud.py +58 -0
  137. mcli/workflow/git_commit/ai_service.py +328 -0
  138. mcli/workflow/git_commit/commands.py +430 -0
  139. mcli/workflow/lsh_integration.py +355 -0
  140. mcli/workflow/model_service/client.py +594 -0
  141. mcli/workflow/model_service/download_and_run_efficient_models.py +288 -0
  142. mcli/workflow/model_service/lightweight_embedder.py +397 -0
  143. mcli/workflow/model_service/lightweight_model_server.py +714 -0
  144. mcli/workflow/model_service/lightweight_test.py +241 -0
  145. mcli/workflow/model_service/model_service.py +1955 -0
  146. mcli/workflow/model_service/ollama_efficient_runner.py +425 -0
  147. mcli/workflow/model_service/pdf_processor.py +386 -0
  148. mcli/workflow/model_service/test_efficient_runner.py +234 -0
  149. mcli/workflow/model_service/test_example.py +315 -0
  150. mcli/workflow/model_service/test_integration.py +131 -0
  151. mcli/workflow/model_service/test_new_features.py +149 -0
  152. mcli/workflow/openai/openai.py +99 -0
  153. mcli/workflow/politician_trading/commands.py +1790 -0
  154. mcli/workflow/politician_trading/config.py +134 -0
  155. mcli/workflow/politician_trading/connectivity.py +490 -0
  156. mcli/workflow/politician_trading/data_sources.py +395 -0
  157. mcli/workflow/politician_trading/database.py +410 -0
  158. mcli/workflow/politician_trading/demo.py +248 -0
  159. mcli/workflow/politician_trading/models.py +165 -0
  160. mcli/workflow/politician_trading/monitoring.py +413 -0
  161. mcli/workflow/politician_trading/scrapers.py +966 -0
  162. mcli/workflow/politician_trading/scrapers_california.py +412 -0
  163. mcli/workflow/politician_trading/scrapers_eu.py +377 -0
  164. mcli/workflow/politician_trading/scrapers_uk.py +350 -0
  165. mcli/workflow/politician_trading/scrapers_us_states.py +438 -0
  166. mcli/workflow/politician_trading/supabase_functions.py +354 -0
  167. mcli/workflow/politician_trading/workflow.py +852 -0
  168. mcli/workflow/registry/registry.py +180 -0
  169. mcli/workflow/repo/repo.py +223 -0
  170. mcli/workflow/scheduler/commands.py +493 -0
  171. mcli/workflow/scheduler/cron_parser.py +238 -0
  172. mcli/workflow/scheduler/job.py +182 -0
  173. mcli/workflow/scheduler/monitor.py +139 -0
  174. mcli/workflow/scheduler/persistence.py +324 -0
  175. mcli/workflow/scheduler/scheduler.py +679 -0
  176. mcli/workflow/sync/sync_cmd.py +437 -0
  177. mcli/workflow/sync/test_cmd.py +314 -0
  178. mcli/workflow/videos/videos.py +242 -0
  179. mcli/workflow/wakatime/wakatime.py +11 -0
  180. mcli/workflow/workflow.py +37 -0
  181. mcli_framework-7.0.0.dist-info/METADATA +479 -0
  182. mcli_framework-7.0.0.dist-info/RECORD +186 -0
  183. mcli_framework-7.0.0.dist-info/WHEEL +5 -0
  184. mcli_framework-7.0.0.dist-info/entry_points.txt +7 -0
  185. mcli_framework-7.0.0.dist-info/licenses/LICENSE +21 -0
  186. mcli_framework-7.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1016 @@
1
+ """
2
+ System Integration for MCLI Chat
3
+ Provides system control capabilities directly within chat conversations
4
+ """
5
+
6
+ import json
7
+ from typing import Any, Dict, List
8
+
9
+ from mcli.lib.logger.logger import get_logger
10
+
11
+ from .system_controller import (
12
+ change_directory,
13
+ clean_simulator_data,
14
+ control_app,
15
+ execute_shell_command,
16
+ execute_system_command,
17
+ get_current_directory,
18
+ list_directory,
19
+ open_file_or_url,
20
+ open_textedit_and_write,
21
+ system_controller,
22
+ take_screenshot,
23
+ )
24
+
25
+ logger = get_logger(__name__)
26
+
27
+
28
+ class ChatSystemIntegration:
29
+ """Integration layer between chat and system control"""
30
+
31
+ def __init__(self):
32
+ self.system_controller = system_controller
33
+ self.enabled = True
34
+
35
+ # Define available system functions
36
+ self.system_functions = {
37
+ "open_textedit_and_write": {
38
+ "function": open_textedit_and_write,
39
+ "description": "Open TextEdit and write specified text",
40
+ "parameters": {
41
+ "text": "Text to write in TextEdit",
42
+ "filename": "Optional filename to save (will save to Desktop)",
43
+ },
44
+ "examples": [
45
+ "Open TextEdit and write 'Hello, World!'",
46
+ "Write 'My notes' in TextEdit and save as 'notes.txt'",
47
+ ],
48
+ },
49
+ "control_application": {
50
+ "function": control_app,
51
+ "description": "Control system applications (open, close, interact)",
52
+ "parameters": {
53
+ "app_name": "Name of the application (e.g., 'TextEdit', 'Calculator')",
54
+ "action": "Action to perform (open, close, new_document, write_text)",
55
+ "**kwargs": "Additional parameters like text, filename",
56
+ },
57
+ "examples": ["Open Calculator", "Close TextEdit", "Open new document in TextEdit"],
58
+ },
59
+ "execute_command": {
60
+ "function": execute_system_command,
61
+ "description": "Execute shell/terminal commands",
62
+ "parameters": {
63
+ "command": "Shell command to execute",
64
+ "description": "Optional description of what the command does",
65
+ },
66
+ "examples": [
67
+ "List files in current directory",
68
+ "Check system uptime",
69
+ "Create a new folder",
70
+ ],
71
+ },
72
+ "take_screenshot": {
73
+ "function": take_screenshot,
74
+ "description": "Take a screenshot and save to Desktop",
75
+ "parameters": {
76
+ "filename": "Optional filename (will auto-generate if not provided)"
77
+ },
78
+ "examples": ["Take a screenshot", "Take screenshot and save as 'my_screen.png'"],
79
+ },
80
+ "open_file_or_url": {
81
+ "function": open_file_or_url,
82
+ "description": "Open files or URLs with default system application",
83
+ "parameters": {"path_or_url": "File path or URL to open"},
84
+ "examples": [
85
+ "Open https://google.com",
86
+ "Open ~/Documents/file.txt",
87
+ "Open current directory in Finder",
88
+ ],
89
+ },
90
+ "get_system_info": {
91
+ "function": self.system_controller.get_system_info,
92
+ "description": "Get comprehensive system information (CPU, memory, disk, etc.)",
93
+ "parameters": {},
94
+ "examples": [
95
+ "What is my system information?",
96
+ "Show system specs",
97
+ "How much RAM do I have?",
98
+ ],
99
+ },
100
+ "get_system_time": {
101
+ "function": self.system_controller.get_system_time,
102
+ "description": "Get current system time and date",
103
+ "parameters": {},
104
+ "examples": [
105
+ "What time is it?",
106
+ "What is the current time?",
107
+ "Show me the date and time",
108
+ ],
109
+ },
110
+ "get_memory_usage": {
111
+ "function": self.system_controller.get_memory_usage,
112
+ "description": "Get detailed memory usage information",
113
+ "parameters": {},
114
+ "examples": ["How much memory am I using?", "Show memory usage", "Check RAM usage"],
115
+ },
116
+ "get_disk_usage": {
117
+ "function": self.system_controller.get_disk_usage,
118
+ "description": "Get disk space and usage information",
119
+ "parameters": {},
120
+ "examples": [
121
+ "How much disk space do I have?",
122
+ "Show disk usage",
123
+ "Check storage space",
124
+ ],
125
+ },
126
+ "clear_system_caches": {
127
+ "function": self.system_controller.clear_system_caches,
128
+ "description": "Clear system caches and temporary files",
129
+ "parameters": {},
130
+ "examples": ["Clear system caches", "Clean up temporary files", "Free up space"],
131
+ },
132
+ "change_directory": {
133
+ "function": change_directory,
134
+ "description": "Navigate to a directory",
135
+ "parameters": {"path": "Directory path to navigate to"},
136
+ "examples": [
137
+ "Navigate to /System/Volumes/Data",
138
+ "Go to ~/Documents",
139
+ "Change to /tmp",
140
+ ],
141
+ },
142
+ "list_directory": {
143
+ "function": list_directory,
144
+ "description": "List contents of a directory",
145
+ "parameters": {
146
+ "path": "Directory path to list (optional, defaults to current)",
147
+ "show_hidden": "Show hidden files (optional)",
148
+ "detailed": "Show detailed file information (optional)",
149
+ },
150
+ "examples": [
151
+ "List current directory",
152
+ "Show files in /System/Volumes/Data",
153
+ "List all files including hidden ones",
154
+ ],
155
+ },
156
+ "clean_simulator_data": {
157
+ "function": clean_simulator_data,
158
+ "description": "Clean iOS/watchOS simulator cache and temporary data",
159
+ "parameters": {},
160
+ "examples": [
161
+ "Clean simulator data",
162
+ "Remove iOS simulator caches",
163
+ "Free up simulator storage",
164
+ ],
165
+ },
166
+ "execute_shell_command": {
167
+ "function": execute_shell_command,
168
+ "description": "Execute shell commands with full terminal access",
169
+ "parameters": {
170
+ "command": "Shell command to execute",
171
+ "working_directory": "Directory to run command in (optional)",
172
+ },
173
+ "examples": ["Run ls -la", "Execute find command", "Run custom shell scripts"],
174
+ },
175
+ "get_current_directory": {
176
+ "function": get_current_directory,
177
+ "description": "Get current working directory",
178
+ "parameters": {},
179
+ "examples": ["Where am I?", "Show current directory", "What's my current path?"],
180
+ },
181
+ }
182
+
183
+ def handle_system_request(self, request: str) -> Dict[str, Any]:
184
+ """
185
+ Analyze user request and execute appropriate system function
186
+ This is the main entry point for chat system integration
187
+ """
188
+
189
+ if not self.enabled:
190
+ return {
191
+ "success": False,
192
+ "error": "System control is disabled",
193
+ "suggestion": "Enable system control to use this feature",
194
+ }
195
+
196
+ # Parse the request and determine action
197
+ request_lower = request.lower()
198
+
199
+ # System information requests
200
+ if any(
201
+ phrase in request_lower
202
+ for phrase in ["what time", "current time", "system time", "what is the time"]
203
+ ):
204
+ return self._handle_system_time_request(request)
205
+
206
+ elif any(
207
+ phrase in request_lower
208
+ for phrase in ["system info", "system information", "system specs", "hardware info"]
209
+ ):
210
+ return self._handle_system_info_request(request)
211
+
212
+ # Hardware devices requests
213
+ elif any(
214
+ phrase in request_lower
215
+ for phrase in [
216
+ "hardware devices",
217
+ "connected devices",
218
+ "list hardware",
219
+ "show devices",
220
+ "connected hardware",
221
+ ]
222
+ ):
223
+ return self._handle_hardware_devices_request(request)
224
+
225
+ elif any(
226
+ phrase in request_lower
227
+ for phrase in [
228
+ "memory usage",
229
+ "ram usage",
230
+ "how much memory",
231
+ "how much ram",
232
+ "memory info",
233
+ ]
234
+ ):
235
+ return self._handle_memory_request(request)
236
+
237
+ elif any(
238
+ phrase in request_lower
239
+ for phrase in [
240
+ "disk usage",
241
+ "disk space",
242
+ "storage space",
243
+ "how much space",
244
+ "free space",
245
+ ]
246
+ ):
247
+ return self._handle_disk_request(request)
248
+
249
+ elif any(
250
+ phrase in request_lower
251
+ for phrase in [
252
+ "clear cache",
253
+ "clean cache",
254
+ "clear temp",
255
+ "free up space",
256
+ "clean system",
257
+ "clear system cache",
258
+ ]
259
+ ):
260
+ return self._handle_cache_clear_request(request)
261
+
262
+ # Navigation requests
263
+ elif any(
264
+ phrase in request_lower
265
+ for phrase in ["navigate to", "go to", "change to", "cd to", "move to"]
266
+ ):
267
+ return self._handle_navigation_request(request)
268
+
269
+ # Directory listing requests (more specific to avoid false positives)
270
+ elif any(
271
+ phrase in request_lower
272
+ for phrase in ["list files", "list directory", "show files", "ls", "dir", "what's in"]
273
+ ):
274
+ return self._handle_directory_listing_request(request)
275
+
276
+ # Simulator cleanup requests
277
+ elif any(
278
+ phrase in request_lower
279
+ for phrase in ["clean simulator", "simulator data", "clean ios", "clean watchos"]
280
+ ):
281
+ return self._handle_simulator_cleanup_request(request)
282
+
283
+ # Shell command requests
284
+ elif any(
285
+ phrase in request_lower for phrase in ["run command", "execute", "shell", "terminal"]
286
+ ):
287
+ return self._handle_shell_command_request(request)
288
+
289
+ # Current directory requests
290
+ elif any(
291
+ phrase in request_lower
292
+ for phrase in ["where am i", "current directory", "pwd", "current path"]
293
+ ):
294
+ return self._handle_current_directory_request(request)
295
+
296
+ # TextEdit operations
297
+ elif "textedit" in request_lower and ("write" in request_lower or "type" in request_lower):
298
+ return self._handle_textedit_request(request)
299
+
300
+ # Application control
301
+ elif any(word in request_lower for word in ["open", "close", "launch", "quit"]):
302
+ return self._handle_app_control_request(request)
303
+
304
+ # Screenshot
305
+ elif "screenshot" in request_lower or "screen capture" in request_lower:
306
+ return self._handle_screenshot_request(request)
307
+
308
+ # File/URL opening
309
+ elif "open" in request_lower and (
310
+ "file" in request_lower or "url" in request_lower or "http" in request_lower
311
+ ):
312
+ return self._handle_open_request(request)
313
+
314
+ # Command execution
315
+ elif any(word in request_lower for word in ["run", "execute", "command", "terminal"]):
316
+ return self._handle_command_request(request)
317
+
318
+ else:
319
+ return {
320
+ "success": False,
321
+ "error": "Could not understand system request",
322
+ "available_functions": list(self.system_functions.keys()),
323
+ "suggestion": "Try: 'Open TextEdit and write Hello World' or 'Take a screenshot'",
324
+ }
325
+
326
+ def _handle_textedit_request(self, request: str) -> Dict[str, Any]:
327
+ """Handle TextEdit-specific requests"""
328
+ try:
329
+ # Extract text to write
330
+ text = "Hello, World!" # default
331
+ filename = None
332
+
333
+ # Simple text extraction patterns
334
+ if '"' in request:
335
+ # Extract text in quotes
336
+ parts = request.split('"')
337
+ if len(parts) >= 2:
338
+ text = parts[1]
339
+ elif "write " in request.lower():
340
+ # Extract text after "write"
341
+ parts = request.lower().split("write ")
342
+ if len(parts) > 1:
343
+ text_part = parts[1]
344
+ # Remove common words
345
+ for word in ["in textedit", "to textedit", "and save", "then save"]:
346
+ text_part = text_part.replace(word, "")
347
+ text = text_part.strip()
348
+
349
+ # Extract filename if mentioned
350
+ if "save as" in request.lower():
351
+ parts = request.lower().split("save as")
352
+ if len(parts) > 1:
353
+ filename_part = parts[1].strip()
354
+ # Extract filename (remove quotes and common words)
355
+ filename = filename_part.replace('"', "").replace("'", "").split()[0]
356
+ if not filename.endswith(".txt"):
357
+ filename += ".txt"
358
+
359
+ result = open_textedit_and_write(text, filename)
360
+
361
+ if result["success"]:
362
+ message = f"โœ… Opened TextEdit and wrote: '{text}'"
363
+ if filename:
364
+ message += f" (saved as {filename})"
365
+ result["message"] = message
366
+
367
+ return result
368
+
369
+ except Exception as e:
370
+ return {
371
+ "success": False,
372
+ "error": f"Error handling TextEdit request: {e}",
373
+ "request": request,
374
+ }
375
+
376
+ def _handle_app_control_request(self, request: str) -> Dict[str, Any]:
377
+ """Handle application control requests"""
378
+ try:
379
+ request_lower = request.lower()
380
+
381
+ # Determine action
382
+ if "open" in request_lower or "launch" in request_lower:
383
+ action = "open"
384
+ elif "close" in request_lower or "quit" in request_lower:
385
+ action = "close"
386
+ elif "new document" in request_lower:
387
+ action = "new_document"
388
+ else:
389
+ action = "open" # default
390
+
391
+ # Extract app name
392
+ app_name = "TextEdit" # default
393
+
394
+ common_apps = {
395
+ "textedit": "TextEdit",
396
+ "calculator": "Calculator",
397
+ "finder": "Finder",
398
+ "safari": "Safari",
399
+ "chrome": "Google Chrome",
400
+ "firefox": "Firefox",
401
+ "terminal": "Terminal",
402
+ "preview": "Preview",
403
+ "notes": "Notes",
404
+ "mail": "Mail",
405
+ }
406
+
407
+ for app_key, app_value in common_apps.items():
408
+ if app_key in request_lower:
409
+ app_name = app_value
410
+ break
411
+
412
+ result = control_app(app_name, action)
413
+
414
+ if result["success"]:
415
+ result["message"] = f"โœ… {action.title()} {app_name}"
416
+
417
+ return result
418
+
419
+ except Exception as e:
420
+ return {
421
+ "success": False,
422
+ "error": f"Error handling app control request: {e}",
423
+ "request": request,
424
+ }
425
+
426
+ def _handle_screenshot_request(self, request: str) -> Dict[str, Any]:
427
+ """Handle screenshot requests"""
428
+ try:
429
+ filename = None
430
+
431
+ # Extract filename if specified
432
+ if "save as" in request.lower() or "name" in request.lower():
433
+ # Simple filename extraction
434
+ words = request.split()
435
+ for i, word in enumerate(words):
436
+ if word.lower() in ["as", "name"] and i < len(words) - 1:
437
+ filename = words[i + 1].replace('"', "").replace("'", "")
438
+ if not filename.endswith(".png"):
439
+ filename += ".png"
440
+ break
441
+
442
+ result = take_screenshot(filename)
443
+
444
+ if result["success"]:
445
+ path = result.get("screenshot_path", "Desktop")
446
+ result["message"] = f"โœ… Screenshot saved to: {path}"
447
+
448
+ return result
449
+
450
+ except Exception as e:
451
+ return {"success": False, "error": f"Error taking screenshot: {e}", "request": request}
452
+
453
+ def _handle_open_request(self, request: str) -> Dict[str, Any]:
454
+ """Handle file/URL opening requests"""
455
+ try:
456
+ # Extract URL or file path
457
+ words = request.split()
458
+ path_or_url = None
459
+
460
+ for word in words:
461
+ if word.startswith("http") or word.startswith("www.") or "/" in word:
462
+ path_or_url = word
463
+ break
464
+
465
+ if not path_or_url:
466
+ # Look for common patterns
467
+ if "google" in request.lower():
468
+ path_or_url = "https://google.com"
469
+ elif "current directory" in request.lower() or "this folder" in request.lower():
470
+ path_or_url = "."
471
+ else:
472
+ return {
473
+ "success": False,
474
+ "error": "Could not determine what to open",
475
+ "suggestion": "Specify a URL (like https://google.com) or file path",
476
+ }
477
+
478
+ result = open_file_or_url(path_or_url)
479
+
480
+ if result["success"]:
481
+ result["message"] = f"โœ… Opened: {path_or_url}"
482
+
483
+ return result
484
+
485
+ except Exception as e:
486
+ return {"success": False, "error": f"Error opening file/URL: {e}", "request": request}
487
+
488
+ def _handle_command_request(self, request: str) -> Dict[str, Any]:
489
+ """Handle command execution requests"""
490
+ try:
491
+ # Extract command (this is simplified - in practice you'd want more security)
492
+ command = None
493
+
494
+ if "run " in request.lower():
495
+ parts = request.lower().split("run ")
496
+ if len(parts) > 1:
497
+ command = parts[1].strip()
498
+ elif "execute " in request.lower():
499
+ parts = request.lower().split("execute ")
500
+ if len(parts) > 1:
501
+ command = parts[1].strip()
502
+
503
+ if not command:
504
+ return {
505
+ "success": False,
506
+ "error": "Could not extract command to execute",
507
+ "suggestion": "Try: 'Run ls' or 'Execute date'",
508
+ }
509
+
510
+ # Basic security check (you'd want more comprehensive checks)
511
+ dangerous_commands = ["rm -rf", "sudo", "format", "del /", "> /dev"]
512
+ if any(dangerous in command.lower() for dangerous in dangerous_commands):
513
+ return {
514
+ "success": False,
515
+ "error": "Command blocked for security reasons",
516
+ "command": command,
517
+ }
518
+
519
+ result = execute_system_command(command, f"User requested: {command}")
520
+
521
+ if result["success"]:
522
+ result["message"] = f"โœ… Executed: {command}"
523
+
524
+ return result
525
+
526
+ except Exception as e:
527
+ return {"success": False, "error": f"Error executing command: {e}", "request": request}
528
+
529
+ def _handle_system_time_request(self, request: str) -> Dict[str, Any]:
530
+ """Handle system time requests"""
531
+ try:
532
+ result = self.system_controller.get_system_time()
533
+
534
+ if result["success"]:
535
+ time_data = result["data"]
536
+ result["message"] = (
537
+ f"โฐ Current time: {time_data['current_time']} ({time_data['timezone'][0]})"
538
+ )
539
+
540
+ return result
541
+
542
+ except Exception as e:
543
+ return {
544
+ "success": False,
545
+ "error": f"Error getting system time: {e}",
546
+ "request": request,
547
+ }
548
+
549
+ def _handle_system_info_request(self, request: str) -> Dict[str, Any]:
550
+ """Handle system information requests"""
551
+ try:
552
+ result = self.system_controller.get_system_info()
553
+
554
+ if result["success"]:
555
+ info_data = result["data"]
556
+ summary = [
557
+ f"๐Ÿ’ป System: {info_data['system']} {info_data['machine']}",
558
+ f"๐Ÿง  CPU: {info_data['cpu']['logical_cores']} cores, {info_data['cpu']['cpu_usage_percent']}% usage",
559
+ f"๐Ÿ’พ RAM: {info_data['memory']['used_gb']:.1f}GB used / {info_data['memory']['total_gb']:.1f}GB total ({info_data['memory']['usage_percent']}%)",
560
+ f"โฐ Uptime: {info_data['uptime_hours']:.1f} hours",
561
+ ]
562
+ result["message"] = "\n".join(summary)
563
+
564
+ return result
565
+
566
+ except Exception as e:
567
+ return {
568
+ "success": False,
569
+ "error": f"Error getting system information: {e}",
570
+ "request": request,
571
+ }
572
+
573
+ def _handle_hardware_devices_request(self, request: str) -> Dict[str, Any]:
574
+ """Handle hardware devices listing requests"""
575
+ try:
576
+ # Use shell command to get hardware information
577
+ import subprocess
578
+
579
+ summary = ["๐Ÿ”Œ Connected Hardware Devices:"]
580
+
581
+ try:
582
+ # Get USB devices
583
+ result = subprocess.run(
584
+ ["system_profiler", "SPUSBDataType"], capture_output=True, text=True, timeout=10
585
+ )
586
+
587
+ if result.returncode == 0:
588
+ usb_lines = result.stdout.split("\n")
589
+ usb_devices = []
590
+ for line in usb_lines:
591
+ line = line.strip()
592
+ if ":" in line and not line.startswith("USB") and len(line) < 100:
593
+ if any(
594
+ keyword in line.lower()
595
+ for keyword in [
596
+ "mouse",
597
+ "keyboard",
598
+ "disk",
599
+ "camera",
600
+ "audio",
601
+ "hub",
602
+ ]
603
+ ):
604
+ device_name = line.split(":")[0].strip()
605
+ if device_name and len(device_name) > 3:
606
+ usb_devices.append(device_name)
607
+
608
+ if usb_devices:
609
+ summary.append("๐Ÿ’พ USB Devices:")
610
+ for device in usb_devices[:8]: # Limit to 8 devices
611
+ summary.append(f" โ€ข {device}")
612
+
613
+ except Exception:
614
+ pass
615
+
616
+ try:
617
+ # Get network interfaces
618
+ result = subprocess.run(
619
+ ["ifconfig", "-a"], capture_output=True, text=True, timeout=5
620
+ )
621
+
622
+ if result.returncode == 0:
623
+ interfaces = []
624
+ for line in result.stdout.split("\n"):
625
+ if line and not line.startswith("\t") and not line.startswith(" "):
626
+ interface_name = line.split(":")[0].strip()
627
+ if interface_name and interface_name not in ["lo0", "gif0", "stf0"]:
628
+ interfaces.append(interface_name)
629
+
630
+ if interfaces:
631
+ summary.append("๐ŸŒ Network Interfaces:")
632
+ for interface in interfaces[:6]: # Limit to 6 interfaces
633
+ summary.append(f" โ€ข {interface}")
634
+
635
+ except Exception:
636
+ pass
637
+
638
+ try:
639
+ # Get audio devices
640
+ result = subprocess.run(
641
+ ["system_profiler", "SPAudioDataType"],
642
+ capture_output=True,
643
+ text=True,
644
+ timeout=5,
645
+ )
646
+
647
+ if result.returncode == 0:
648
+ audio_devices = []
649
+ for line in result.stdout.split("\n"):
650
+ line = line.strip()
651
+ if ":" in line and (
652
+ "Built-in" in line or "USB" in line or "Bluetooth" in line
653
+ ):
654
+ device_name = line.split(":")[0].strip()
655
+ if device_name and len(device_name) > 3:
656
+ audio_devices.append(device_name)
657
+
658
+ if audio_devices:
659
+ summary.append("๐Ÿ”Š Audio Devices:")
660
+ for device in audio_devices[:4]: # Limit to 4 devices
661
+ summary.append(f" โ€ข {device}")
662
+
663
+ except Exception:
664
+ pass
665
+
666
+ if len(summary) == 1: # Only has header
667
+ summary.append("โ„น๏ธ No specific hardware devices detected via system profiler")
668
+ summary.append("๐Ÿ’ก Try: 'system info' for general hardware information")
669
+
670
+ return {
671
+ "success": True,
672
+ "message": "\n".join(summary),
673
+ "description": "List connected hardware devices",
674
+ }
675
+
676
+ except Exception as e:
677
+ return {
678
+ "success": False,
679
+ "error": f"Error getting hardware devices: {e}",
680
+ "suggestion": "Try 'system info' for general hardware information",
681
+ "request": request,
682
+ }
683
+
684
+ def _handle_memory_request(self, request: str) -> Dict[str, Any]:
685
+ """Handle memory usage requests"""
686
+ try:
687
+ result = self.system_controller.get_memory_usage()
688
+
689
+ if result["success"]:
690
+ memory_data = result["data"]
691
+ vm = memory_data["virtual_memory"]
692
+ swap = memory_data["swap_memory"]
693
+
694
+ summary = [
695
+ f"๐Ÿ’พ Memory Usage:",
696
+ f" RAM: {vm['used_gb']:.1f}GB used / {vm['total_gb']:.1f}GB total ({vm['usage_percent']}%)",
697
+ f" Available: {vm['available_gb']:.1f}GB",
698
+ f" Swap: {swap['used_gb']:.1f}GB used / {swap['total_gb']:.1f}GB total ({swap['usage_percent']}%)",
699
+ ]
700
+
701
+ # Add recommendations if any
702
+ if memory_data["recommendations"]:
703
+ summary.append("๐Ÿ“‹ Recommendations:")
704
+ for rec in memory_data["recommendations"]:
705
+ summary.append(f" โ€ข {rec}")
706
+
707
+ result["message"] = "\n".join(summary)
708
+
709
+ return result
710
+
711
+ except Exception as e:
712
+ return {
713
+ "success": False,
714
+ "error": f"Error getting memory usage: {e}",
715
+ "request": request,
716
+ }
717
+
718
+ def _handle_disk_request(self, request: str) -> Dict[str, Any]:
719
+ """Handle disk usage requests"""
720
+ try:
721
+ result = self.system_controller.get_disk_usage()
722
+
723
+ if result["success"]:
724
+ disk_data = result["data"]
725
+
726
+ summary = [f"๐Ÿ’ฝ Disk Usage:"]
727
+
728
+ # Show main disk first
729
+ if disk_data["total_disk_gb"] > 0:
730
+ usage_pct = (disk_data["total_used_gb"] / disk_data["total_disk_gb"]) * 100
731
+ summary.append(
732
+ f" Main: {disk_data['total_used_gb']:.1f}GB used / {disk_data['total_disk_gb']:.1f}GB total ({usage_pct:.1f}%)"
733
+ )
734
+ summary.append(f" Free: {disk_data['total_free_gb']:.1f}GB available")
735
+
736
+ # Show other partitions
737
+ if len(disk_data["partitions"]) > 1:
738
+ summary.append(" Other partitions:")
739
+ for partition in disk_data["partitions"]:
740
+ if partition["mountpoint"] not in ["/", "C:\\"]:
741
+ summary.append(
742
+ f" {partition['mountpoint']}: {partition['used_gb']:.1f}GB / {partition['total_gb']:.1f}GB ({partition['usage_percent']}%)"
743
+ )
744
+
745
+ # Add recommendations if any
746
+ if disk_data["recommendations"]:
747
+ summary.append("๐Ÿ“‹ Recommendations:")
748
+ for rec in disk_data["recommendations"]:
749
+ summary.append(f" โ€ข {rec}")
750
+
751
+ result["message"] = "\n".join(summary)
752
+
753
+ return result
754
+
755
+ except Exception as e:
756
+ return {"success": False, "error": f"Error getting disk usage: {e}", "request": request}
757
+
758
+ def _handle_cache_clear_request(self, request: str) -> Dict[str, Any]:
759
+ """Handle cache clearing requests"""
760
+ try:
761
+ result = self.system_controller.clear_system_caches()
762
+
763
+ if result["success"]:
764
+ cache_data = result["data"]
765
+
766
+ summary = [f"๐Ÿงน Cache Cleanup Results:"]
767
+
768
+ if cache_data["cleared_items"]:
769
+ for item in cache_data["cleared_items"]:
770
+ summary.append(f" โœ… {item}")
771
+ else:
772
+ summary.append(" โ„น๏ธ No cache items found to clear")
773
+
774
+ if cache_data["total_freed_mb"] > 0:
775
+ summary.append(f"๐Ÿ’พ Total space freed: {cache_data['total_freed_mb']:.1f} MB")
776
+
777
+ result["message"] = "\n".join(summary)
778
+
779
+ return result
780
+
781
+ except Exception as e:
782
+ return {"success": False, "error": f"Error clearing caches: {e}", "request": request}
783
+
784
+ def _handle_navigation_request(self, request: str) -> Dict[str, Any]:
785
+ """Handle directory navigation requests"""
786
+ try:
787
+ # Extract path from request
788
+ request_lower = request.lower()
789
+ path = None
790
+
791
+ # Common patterns to extract path
792
+ if "navigate to " in request_lower:
793
+ path = request[request_lower.find("navigate to ") + 12 :].strip()
794
+ elif "go to " in request_lower:
795
+ path = request[request_lower.find("go to ") + 6 :].strip()
796
+ elif "change to " in request_lower:
797
+ path = request[request_lower.find("change to ") + 10 :].strip()
798
+ elif "cd to " in request_lower:
799
+ path = request[request_lower.find("cd to ") + 6 :].strip()
800
+ elif "move to " in request_lower:
801
+ path = request[request_lower.find("move to ") + 8 :].strip()
802
+
803
+ if not path:
804
+ return {
805
+ "success": False,
806
+ "error": "Could not extract directory path from request",
807
+ "suggestion": "Try: 'navigate to /path/to/directory' or 'cd to ~/Documents'",
808
+ }
809
+
810
+ # Clean up path (remove quotes, extra text)
811
+ path = path.replace('"', "").replace("'", "")
812
+ if ":" in path and not path.startswith("/"):
813
+ # Handle "navigate to /path:" format
814
+ path = path.split(":")[0]
815
+
816
+ result = change_directory(path)
817
+
818
+ if result["success"]:
819
+ # Also list the directory contents after navigation
820
+ list_result = list_directory()
821
+ if list_result["success"]:
822
+ entries = list_result["entries"]
823
+ entry_summary = []
824
+ dirs = [e for e in entries if e["type"] == "directory"]
825
+ files = [e for e in entries if e["type"] == "file"]
826
+
827
+ if dirs:
828
+ entry_summary.append(f"{len(dirs)} directories")
829
+ if files:
830
+ entry_summary.append(f"{len(files)} files")
831
+
832
+ result["message"] = (
833
+ f"โœ… {result['message']}\n๐Ÿ“ Contains: {', '.join(entry_summary)}"
834
+ )
835
+ result["directory_contents"] = entries[:10] # Show first 10 items
836
+
837
+ return result
838
+
839
+ except Exception as e:
840
+ return {"success": False, "error": f"Navigation error: {e}", "request": request}
841
+
842
+ def _handle_directory_listing_request(self, request: str) -> Dict[str, Any]:
843
+ """Handle directory listing requests"""
844
+ try:
845
+ request_lower = request.lower()
846
+
847
+ # Extract path if specified
848
+ path = None
849
+ show_hidden = False
850
+ detailed = False
851
+
852
+ if "list " in request_lower:
853
+ after_list = request[request_lower.find("list ") + 5 :].strip()
854
+ if after_list and not after_list.startswith(("current", "this", "files")):
855
+ path = after_list
856
+ elif "show files in " in request_lower:
857
+ path = request[request_lower.find("show files in ") + 14 :].strip()
858
+ elif "what's in " in request_lower:
859
+ path = request[request_lower.find("what's in ") + 10 :].strip()
860
+
861
+ if "hidden" in request_lower or "all files" in request_lower:
862
+ show_hidden = True
863
+ if "detailed" in request_lower or "details" in request_lower:
864
+ detailed = True
865
+
866
+ # Clean up path
867
+ if path:
868
+ path = path.replace('"', "").replace("'", "")
869
+ if path.endswith(":"):
870
+ path = path[:-1]
871
+
872
+ result = list_directory(path, show_hidden, detailed)
873
+
874
+ if result["success"]:
875
+ entries = result["entries"]
876
+ dirs = [e for e in entries if e["type"] == "directory"]
877
+ files = [e for e in entries if e["type"] == "file"]
878
+
879
+ summary = []
880
+ if dirs:
881
+ summary.append(f"๐Ÿ“ {len(dirs)} directories")
882
+ if files:
883
+ summary.append(f"๐Ÿ“„ {len(files)} files")
884
+
885
+ result["message"] = f"๐Ÿ“‚ {result['path']}\n{', '.join(summary)}"
886
+
887
+ # Format entries for display
888
+ display_entries = []
889
+ for entry in entries[:20]: # Show first 20
890
+ if entry["type"] == "directory":
891
+ display_entries.append(f"๐Ÿ“ {entry['name']}/")
892
+ else:
893
+ size_str = ""
894
+ if entry.get("size") is not None:
895
+ size_kb = entry["size"] / 1024
896
+ if size_kb < 1024:
897
+ size_str = f" ({size_kb:.1f} KB)"
898
+ else:
899
+ size_str = f" ({size_kb/1024:.1f} MB)"
900
+ display_entries.append(f"๐Ÿ“„ {entry['name']}{size_str}")
901
+
902
+ if display_entries:
903
+ result["display_entries"] = display_entries
904
+ if len(entries) > 20:
905
+ result["message"] += f"\n(showing first 20 of {len(entries)} items)"
906
+
907
+ return result
908
+
909
+ except Exception as e:
910
+ return {"success": False, "error": f"Directory listing error: {e}", "request": request}
911
+
912
+ def _handle_simulator_cleanup_request(self, request: str) -> Dict[str, Any]:
913
+ """Handle iOS/watchOS simulator cleanup requests"""
914
+ try:
915
+ result = clean_simulator_data()
916
+
917
+ if result["success"]:
918
+ data = result["data"]
919
+ result["message"] = (
920
+ f"๐Ÿงน Simulator cleanup completed!\n๐Ÿ’พ Freed {data['total_freed_mb']} MB of storage"
921
+ )
922
+
923
+ if data["cleaned_items"]:
924
+ result["cleaned_summary"] = data["cleaned_items"][:5] # Show first 5 items
925
+
926
+ return result
927
+
928
+ except Exception as e:
929
+ return {"success": False, "error": f"Simulator cleanup error: {e}", "request": request}
930
+
931
+ def _handle_shell_command_request(self, request: str) -> Dict[str, Any]:
932
+ """Handle shell command execution requests"""
933
+ try:
934
+ request_lower = request.lower()
935
+
936
+ # Extract command
937
+ command = None
938
+ if "run command " in request_lower:
939
+ command = request[request_lower.find("run command ") + 12 :].strip()
940
+ elif "execute " in request_lower:
941
+ command = request[request_lower.find("execute ") + 8 :].strip()
942
+ elif "shell " in request_lower:
943
+ command = request[request_lower.find("shell ") + 6 :].strip()
944
+ elif "terminal " in request_lower:
945
+ command = request[request_lower.find("terminal ") + 9 :].strip()
946
+
947
+ if not command:
948
+ return {
949
+ "success": False,
950
+ "error": "Could not extract command from request",
951
+ "suggestion": "Try: 'run command ls -la' or 'execute find /path -name pattern'",
952
+ }
953
+
954
+ # Basic security check
955
+ dangerous_commands = ["rm -rf /", "sudo rm", "format", "mkfs", "> /dev/null"]
956
+ if any(dangerous in command.lower() for dangerous in dangerous_commands):
957
+ return {
958
+ "success": False,
959
+ "error": "Command blocked for security reasons",
960
+ "command": command,
961
+ }
962
+
963
+ result = execute_shell_command(command)
964
+
965
+ if result["success"]:
966
+ result["message"] = f"โœ… Executed: {command}"
967
+ if result.get("output"):
968
+ # Truncate long output
969
+ output = result["output"]
970
+ if len(output) > 2000:
971
+ result["output"] = output[:2000] + "\n... (output truncated)"
972
+
973
+ return result
974
+
975
+ except Exception as e:
976
+ return {"success": False, "error": f"Shell command error: {e}", "request": request}
977
+
978
+ def _handle_current_directory_request(self, request: str) -> Dict[str, Any]:
979
+ """Handle current directory requests"""
980
+ try:
981
+ current_dir = get_current_directory()
982
+
983
+ return {
984
+ "success": True,
985
+ "current_directory": current_dir,
986
+ "message": f"๐Ÿ“ Current directory: {current_dir}",
987
+ "description": "Get current directory",
988
+ }
989
+
990
+ except Exception as e:
991
+ return {"success": False, "error": f"Current directory error: {e}", "request": request}
992
+
993
+ def get_capabilities(self) -> Dict[str, Any]:
994
+ """Get information about available system capabilities"""
995
+ return {
996
+ "enabled": self.enabled,
997
+ "system": self.system_controller.system,
998
+ "functions": {
999
+ name: {"description": info["description"], "examples": info["examples"]}
1000
+ for name, info in self.system_functions.items()
1001
+ },
1002
+ }
1003
+
1004
+
1005
+ # Global instance for use in chat
1006
+ chat_system_integration = ChatSystemIntegration()
1007
+
1008
+
1009
+ def handle_system_request(request: str) -> Dict[str, Any]:
1010
+ """Main function for handling system requests from chat"""
1011
+ return chat_system_integration.handle_system_request(request)
1012
+
1013
+
1014
+ def get_system_capabilities() -> Dict[str, Any]:
1015
+ """Get available system capabilities"""
1016
+ return chat_system_integration.get_capabilities()