mcli-framework 7.0.3__py3-none-any.whl → 7.0.5__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.

@@ -137,8 +137,12 @@ LAZY_COMMAND_COMPLETIONS = {
137
137
  "subcommands": [
138
138
  "download",
139
139
  "list",
140
- "remove",
141
- "info"
140
+ "start",
141
+ "stop",
142
+ "pull",
143
+ "delete",
144
+ "recommend",
145
+ "status"
142
146
  ]
143
147
  },
144
148
  "cron-test": {
mcli/app/model_cmd.py CHANGED
@@ -7,6 +7,7 @@ from pathlib import Path
7
7
  from typing import Optional
8
8
 
9
9
  import click
10
+ import psutil
10
11
 
11
12
  from mcli.lib.logger.logger import get_logger
12
13
  from mcli.workflow.model_service.lightweight_model_server import (
@@ -223,5 +224,106 @@ def status(port: int):
223
224
  click.echo(f"❌ Error checking server: {e}")
224
225
 
225
226
 
227
+ @model.command()
228
+ @click.option("--port", "-p", default=8080, help="Port where server is running")
229
+ def stop(port: int):
230
+ """Stop the lightweight model server."""
231
+ import requests
232
+ import psutil
233
+
234
+ try:
235
+ # First check if server is running
236
+ try:
237
+ response = requests.get(f"http://localhost:{port}/health", timeout=2)
238
+ if response.status_code != 200:
239
+ click.echo(f"❌ No server running on port {port}")
240
+ return
241
+ except requests.exceptions.ConnectionError:
242
+ click.echo(f"❌ No server running on port {port}")
243
+ return
244
+
245
+ # Find and kill the process using the port
246
+ for proc in psutil.process_iter(["pid", "name", "connections"]):
247
+ try:
248
+ connections = proc.info.get("connections")
249
+ if connections:
250
+ for conn in connections:
251
+ if hasattr(conn, "laddr") and conn.laddr.port == port:
252
+ click.echo(f"🛑 Stopping server (PID: {proc.pid})...")
253
+ proc.terminate()
254
+ proc.wait(timeout=5)
255
+ click.echo("✅ Server stopped successfully")
256
+ return
257
+ except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.TimeoutExpired):
258
+ continue
259
+
260
+ click.echo("⚠️ Could not find server process")
261
+
262
+ except Exception as e:
263
+ click.echo(f"❌ Error stopping server: {e}")
264
+
265
+
266
+ @model.command()
267
+ @click.argument("model_name")
268
+ def pull(model_name: str):
269
+ """Pull (download) a specific lightweight model."""
270
+ if model_name not in LIGHTWEIGHT_MODELS:
271
+ click.echo(f"❌ Model '{model_name}' not found.")
272
+ click.echo("Available models:")
273
+ for key in LIGHTWEIGHT_MODELS.keys():
274
+ click.echo(f" • {key}")
275
+ sys.exit(1)
276
+
277
+ server = LightweightModelServer()
278
+
279
+ click.echo(f"Pulling model: {model_name}")
280
+ success = server.download_and_load_model(model_name)
281
+
282
+ if success:
283
+ click.echo(f"✅ Successfully pulled {model_name}")
284
+ else:
285
+ click.echo(f"❌ Failed to pull {model_name}")
286
+ sys.exit(1)
287
+
288
+
289
+ @model.command()
290
+ @click.argument("model_name")
291
+ @click.option("--force", "-f", is_flag=True, help="Force deletion without confirmation")
292
+ def delete(model_name: str, force: bool):
293
+ """Delete a downloaded lightweight model."""
294
+ server = LightweightModelServer()
295
+ downloaded_models = server.downloader.get_downloaded_models()
296
+
297
+ if model_name not in downloaded_models:
298
+ click.echo(f"❌ Model '{model_name}' not found.")
299
+ click.echo("Downloaded models:")
300
+ if downloaded_models:
301
+ for model in downloaded_models:
302
+ click.echo(f" • {model}")
303
+ else:
304
+ click.echo(" (none)")
305
+ sys.exit(1)
306
+
307
+ # Confirm deletion unless --force is used
308
+ if not force:
309
+ model_info = LIGHTWEIGHT_MODELS.get(model_name, {})
310
+ name = model_info.get("name", model_name)
311
+ size = model_info.get("size_mb", "unknown")
312
+ click.echo(f"⚠️ About to delete:")
313
+ click.echo(f" Model: {name}")
314
+ click.echo(f" Size: {size} MB")
315
+ if not click.confirm("Are you sure you want to delete this model?"):
316
+ click.echo("❌ Deletion cancelled")
317
+ return
318
+
319
+ success = server.delete_model(model_name)
320
+
321
+ if success:
322
+ click.echo(f"✅ Successfully deleted {model_name}")
323
+ else:
324
+ click.echo(f"❌ Failed to delete {model_name}")
325
+ sys.exit(1)
326
+
327
+
226
328
  if __name__ == "__main__":
227
329
  model()
mcli/self/self_cmd.py CHANGED
@@ -774,18 +774,15 @@ def logs(type: str, lines: int, follow: bool, date: str, grep: str, level: str):
774
774
  from datetime import datetime
775
775
  from pathlib import Path
776
776
 
777
- # Find the logs directory
778
- current_file = Path(__file__)
779
- # Go up 5 levels: file -> self -> mcli -> src -> repo_root
780
- project_root = current_file.parents[4]
781
- logs_dir = project_root / "logs"
777
+ # Import get_logs_dir to get the correct logs directory
778
+ from mcli.lib.paths import get_logs_dir
782
779
 
783
- # Alternative: try current working directory first
784
- if not logs_dir.exists():
785
- logs_dir = Path.cwd() / "logs"
780
+ # Get the logs directory (creates it if it doesn't exist)
781
+ logs_dir = get_logs_dir()
786
782
 
787
783
  if not logs_dir.exists():
788
784
  click.echo("❌ Logs directory not found", err=True)
785
+ click.echo(f"Expected location: {logs_dir}", err=True)
789
786
  return
790
787
 
791
788
  # Determine which log files to read
@@ -566,6 +566,43 @@ class LightweightModelServer:
566
566
  else:
567
567
  return "distilbert-base-uncased" # Standard small model
568
568
 
569
+ def stop_server(self) -> bool:
570
+ """Stop the lightweight server"""
571
+ if not self.running:
572
+ print("⚠️ Server is not running")
573
+ return False
574
+
575
+ try:
576
+ self.running = False
577
+ print("🛑 Server stopped")
578
+ return True
579
+ except Exception as e:
580
+ print(f"❌ Error stopping server: {e}")
581
+ return False
582
+
583
+ def delete_model(self, model_key: str) -> bool:
584
+ """Delete a downloaded model"""
585
+ try:
586
+ model_dir = self.models_dir / model_key
587
+
588
+ if not model_dir.exists():
589
+ print(f"⚠️ Model '{model_key}' not found")
590
+ return False
591
+
592
+ # Remove from loaded models if present
593
+ if model_key in self.loaded_models:
594
+ del self.loaded_models[model_key]
595
+ print(f"✅ Unloaded model: {model_key}")
596
+
597
+ # Delete the model directory
598
+ shutil.rmtree(model_dir)
599
+ print(f"✅ Deleted model: {model_key}")
600
+ return True
601
+
602
+ except Exception as e:
603
+ print(f"❌ Error deleting model {model_key}: {e}")
604
+ return False
605
+
569
606
 
570
607
  def create_simple_client():
571
608
  """Create a simple client script for testing"""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcli-framework
3
- Version: 7.0.3
3
+ Version: 7.0.5
4
4
  Summary: 🚀 High-performance CLI framework with Rust extensions, AI chat, and stunning visuals
5
5
  Author-email: Luis Fernandez de la Vara <luis@lefv.io>
6
6
  Maintainer-email: Luis Fernandez de la Vara <luis@lefv.io>
@@ -6,11 +6,11 @@ mcli/app/__init__.py,sha256=Qy_ttkXt_XKuSQKgQx3H7NqVy8c7otSFtBVZaatCdZc,816
6
6
  mcli/app/chat_cmd.py,sha256=OJK91iX-f-CL5-m3ECG4IlcbLbsWQpPp7XWuGnb0cVQ,1552
7
7
  mcli/app/commands_cmd.py,sha256=5MccxYKNkzIisDeBPJj6K4ZwWeZFB2a4P8AS9B1_EDs,8441
8
8
  mcli/app/completion_cmd.py,sha256=8gtYDddviBCD6Gk57lkLKOpim5QAMMcugYPmwfraBeo,7862
9
- mcli/app/completion_helpers.py,sha256=GJvkxJ5lU_Gh4K35Q275QW1fN39poasyYjDO5-5kxM0,8809
9
+ mcli/app/completion_helpers.py,sha256=PR66qgVNC5_st-CBiD4uuGfO3Zs7Y3QmJ2GJjpx5N6g,8897
10
10
  mcli/app/cron_test_cmd.py,sha256=Ai4Smg2WxULeiMD5s2m_S_fXdMAAQsKHpSc4iJGSnwI,26156
11
11
  mcli/app/logs_cmd.py,sha256=xkGjUiuV1a1-2j8rkffp0OwnG9nS39-i2jpCnKUn9f0,13777
12
12
  mcli/app/main.py,sha256=iA9HdqhBaOnOJ2--edLPD7iAatAzhIl5NAcNhw9qJAw,19010
13
- mcli/app/model_cmd.py,sha256=wRs2xfDbWrdzmVH1hbHr8jypucNUKpXvNdYJAlvk5xc,8153
13
+ mcli/app/model_cmd.py,sha256=xJqD4xBLFqi3sBsgAeyXIC8n5SR3czl8wIWx8za31vA,11756
14
14
  mcli/app/redis_cmd.py,sha256=Cl0LQ3Mqt27gLeb542_xw6bJBbIE-CBmWyMmaUTSk8c,9426
15
15
  mcli/app/visual_cmd.py,sha256=jXighahHxeM9HANQ2Brk6nKFgi2ZuQBOBH7PE5xhebk,9428
16
16
  mcli/app/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -159,7 +159,7 @@ mcli/public/public.py,sha256=t9BkO1XV7s3YcoH0bbIpyjZ05UX_vBjaKtKkuDX7wZ0,114
159
159
  mcli/public/commands/__init__.py,sha256=0WGm1i4t1uifkC_5FmbQ2r03q53yrZ3KnoWOd2M7dEA,103
160
160
  mcli/public/oi/oi.py,sha256=SQabQWQ1pE67pWYEHwIDc3R93DARJfB6VHk7qxWx9xo,308
161
161
  mcli/self/__init__.py,sha256=7hCrgaRb4oAgAf-kcyzqhJ5LFpW19jwF5bxowR4LwjY,41
162
- mcli/self/self_cmd.py,sha256=FM7LqGi3ZXRZCjFBhxIMRce_--8L7GT2UjH3sgKP3UI,47491
162
+ mcli/self/self_cmd.py,sha256=KbgavTt9uXVGKbuX1o4aD4Ll0Ssz96qDHy6WSP7nf88,47419
163
163
  mcli/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
164
164
  mcli/workflow/lsh_integration.py,sha256=khwmMPsdYdkmmLxlZi_UqUo2p0Nf-6GF6PPbtOrmoYQ,13290
165
165
  mcli/workflow/workflow.py,sha256=t58OVXmU9uQCJnyXuIbMAm8lihSzJ_jI10vXPNpZspk,928
@@ -191,7 +191,7 @@ mcli/workflow/interview/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
191
191
  mcli/workflow/model_service/client.py,sha256=wWYde_zR6_o6SP6oePwkHKmEVBtELrP8uKyZNTBWwVc,20888
192
192
  mcli/workflow/model_service/download_and_run_efficient_models.py,sha256=UlKs_Oq_1Vn5qFP28ALCF6CVMTqcRT8hG5quHeGHLIc,9898
193
193
  mcli/workflow/model_service/lightweight_embedder.py,sha256=82B0tYOYVTB3rdC-7XYEMnkw4Q_K0-p3LeyvdaP6ro8,14165
194
- mcli/workflow/model_service/lightweight_model_server.py,sha256=NYhIBDBSa1UwnsF6cEwDuNrcOLYcEIntw19GeMGVF5U,29883
194
+ mcli/workflow/model_service/lightweight_model_server.py,sha256=VyBrUba1maPHNDzO_o7FhLPgN_ncz5EOqrHorzDV5rc,31063
195
195
  mcli/workflow/model_service/lightweight_test.py,sha256=J1--5Q8YvJT3Wzhqf0ElDAostRVA2yDs1LkVwkDMf5M,7330
196
196
  mcli/workflow/model_service/model_service.py,sha256=pAxxHw4tShkrnWWFBnzsrGGKEFa8ZEv4Mza_C8clK38,69729
197
197
  mcli/workflow/model_service/ollama_efficient_runner.py,sha256=fFZLoIfmgbQnMLwnXuH2ya5o_Tu6ww3ERtXg58HbamE,14340
@@ -236,9 +236,9 @@ mcli/workflow/videos/__init__.py,sha256=aV3DEoO7qdKJY4odWKoQbOKDQq4ludTeCLnZcupO
236
236
  mcli/workflow/videos/videos.py,sha256=C47ViVv6qqqkSKQz6YXjzhok4UrqFbya8w5k_x7hToM,8360
237
237
  mcli/workflow/wakatime/__init__.py,sha256=wKG8cVIHVtMPhNRFGFtX43bRnocHqOMMkFMkmW-M6pU,2626
238
238
  mcli/workflow/wakatime/wakatime.py,sha256=sEjsUKa3-XyE8Ni6sAb_D3GAY5jDcA30KknW9YTbLTA,142
239
- mcli_framework-7.0.3.dist-info/licenses/LICENSE,sha256=sahwAMfrJv2-V66HNPTp7A9UmMjxtyejwTZZoWQvEcI,1075
240
- mcli_framework-7.0.3.dist-info/METADATA,sha256=T2hlb-nQrSmCvzSNg6QcRYrpEGJYyGjW6LUHvL6JbIs,14307
241
- mcli_framework-7.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
242
- mcli_framework-7.0.3.dist-info/entry_points.txt,sha256=dYrZbDIm-KUPsl1wfv600Kx_8sMy89phMkCihbDRgP8,261
243
- mcli_framework-7.0.3.dist-info/top_level.txt,sha256=_bnO8J2EUkliWivey_1le0UrnocFKmyVMQjbQ8iVXjc,5
244
- mcli_framework-7.0.3.dist-info/RECORD,,
239
+ mcli_framework-7.0.5.dist-info/licenses/LICENSE,sha256=sahwAMfrJv2-V66HNPTp7A9UmMjxtyejwTZZoWQvEcI,1075
240
+ mcli_framework-7.0.5.dist-info/METADATA,sha256=qds7VDa4wmRAfUlfVpr3y9bwS1gHHKD5uQ193Ol89qA,14307
241
+ mcli_framework-7.0.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
242
+ mcli_framework-7.0.5.dist-info/entry_points.txt,sha256=dYrZbDIm-KUPsl1wfv600Kx_8sMy89phMkCihbDRgP8,261
243
+ mcli_framework-7.0.5.dist-info/top_level.txt,sha256=_bnO8J2EUkliWivey_1le0UrnocFKmyVMQjbQ8iVXjc,5
244
+ mcli_framework-7.0.5.dist-info/RECORD,,