akashcli 4.7.8__tar.gz → 4.8.0__tar.gz

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.
Files changed (33) hide show
  1. {akashcli-4.7.8 → akashcli-4.8.0}/PKG-INFO +1 -1
  2. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/cli.py +59 -11
  3. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli.egg-info/PKG-INFO +1 -1
  4. {akashcli-4.7.8 → akashcli-4.8.0}/pyproject.toml +1 -1
  5. {akashcli-4.7.8 → akashcli-4.8.0}/README.md +0 -0
  6. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/__init__.py +0 -0
  7. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/_net.py +0 -0
  8. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/auth.py +0 -0
  9. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/client.py +0 -0
  10. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/config.py +0 -0
  11. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/crypto.py +0 -0
  12. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/env_manager.py +0 -0
  13. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/exceptions.py +0 -0
  14. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/exec.py +0 -0
  15. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/integrity.py +0 -0
  16. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/logger.py +0 -0
  17. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/models.py +0 -0
  18. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/p2p.py +0 -0
  19. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/packages.py +0 -0
  20. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/relay.py +0 -0
  21. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/restore.py +0 -0
  22. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/snapshot_crypto.py +0 -0
  23. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/storage.py +0 -0
  24. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/terminal.py +0 -0
  25. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/updater.py +0 -0
  26. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/uploader.py +0 -0
  27. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli/utils.py +0 -0
  28. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli.egg-info/SOURCES.txt +0 -0
  29. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli.egg-info/dependency_links.txt +0 -0
  30. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli.egg-info/entry_points.txt +0 -0
  31. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli.egg-info/requires.txt +0 -0
  32. {akashcli-4.7.8 → akashcli-4.8.0}/akashcli.egg-info/top_level.txt +0 -0
  33. {akashcli-4.7.8 → akashcli-4.8.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: akashcli
3
- Version: 4.7.8
3
+ Version: 4.8.0
4
4
  Summary: Akash CLI — secure remote shell relay, file vault, and device management
5
5
  License-Expression: MIT
6
6
  Keywords: akash,cli,relay,remote-shell,vault
@@ -19,7 +19,7 @@ from .config import ConfigManager, DEFAULT_STORAGE_URL
19
19
  from .exceptions import AkashError
20
20
  from .exec import _device_fingerprint
21
21
  from .uploader import VaultUploader
22
- from .updater import show_update_warning_if_available, check_for_updates, format_update_box, mark_update_printed
22
+ from .updater import show_update_warning_if_available, check_for_updates, format_update_box, mark_update_printed, is_newer_version
23
23
 
24
24
  atexit.register(show_update_warning_if_available)
25
25
 
@@ -361,23 +361,38 @@ def update():
361
361
 
362
362
  print(f" {_Y}⚡{_RS} New version available: {_DM}{__version__}{_RS} {_C}→{_RS} {_G}{latest}{_RS}")
363
363
  with _Spin(f"updating akashcli to v{latest}…"):
364
- cmd = [sys.executable, "-m", "pip", "install", "-U", "akashcli", "--break-system-packages"]
364
+ cmd = [sys.executable, "-m", "pip", "install", "-U", "--no-cache-dir", f"akashcli=={latest}", "--break-system-packages"]
365
365
  res = subprocess.run(cmd, capture_output=True, text=True)
366
366
  if res.returncode != 0:
367
- cmd = [sys.executable, "-m", "pip", "install", "-U", "akashcli"]
367
+ cmd = [sys.executable, "-m", "pip", "install", "-U", "--no-cache-dir", f"akashcli=={latest}"]
368
368
  res = subprocess.run(cmd, capture_output=True, text=True)
369
+ if res.returncode != 0:
370
+ # Fallback to general upgrade if pinned version is waiting on PyPI CDN propagation
371
+ cmd = [sys.executable, "-m", "pip", "install", "-U", "--no-cache-dir", "akashcli", "--break-system-packages"]
372
+ res = subprocess.run(cmd, capture_output=True, text=True)
373
+
374
+ # Verify what version is actually installed now in a fresh Python runtime
375
+ chk = subprocess.run(
376
+ [sys.executable, "-c", "import importlib.metadata; print(importlib.metadata.version('akashcli'))"],
377
+ capture_output=True,
378
+ text=True
379
+ )
380
+ curr = chk.stdout.strip() if chk.returncode == 0 else ""
369
381
 
370
- if res.returncode == 0:
371
- _ok(f"Successfully updated akashcli to {_G}v{latest}{_RS}!")
382
+ if curr == latest or (curr and not is_newer_version(latest, curr)):
383
+ _ok(f"Successfully updated akashcli to {_G}v{curr or latest}{_RS}!")
372
384
  try:
373
385
  from .integrity import seal
374
386
  seal()
375
387
  _ok("Integrity manifest re-sealed.")
376
388
  except Exception:
377
389
  pass
390
+ elif res.returncode == 0:
391
+ _warn(f"pip reported success, but installed version is still v{curr or __version__}.")
392
+ _info(f"PyPI CDN may take 1-2 minutes to replicate. Try: {_cy(f'pip install -U --no-cache-dir akashcli=={latest}')}")
378
393
  else:
379
394
  _err(f"Update failed: {res.stderr or res.stdout}")
380
- _info(f"Please run manually: {_cy('pip install -U akashcli')}")
395
+ _info(f"Please run manually: {_cy(f'pip install -U --no-cache-dir akashcli=={latest}')}")
381
396
  mark_update_printed()
382
397
  _p()
383
398
 
@@ -3205,18 +3220,39 @@ _LAST_UNDO_DIR = Path.home() / ".akash" / "undo_vault"
3205
3220
  def _save_undo_checkpoint():
3206
3221
  try:
3207
3222
  import tarfile
3223
+ cwd = Path.cwd().resolve()
3224
+ home = Path.home().resolve()
3225
+ # Never archive the full home directory or system root!
3226
+ if cwd == home or cwd == Path("/") or str(cwd).startswith(("/proc", "/sys", "/dev")):
3227
+ return
3208
3228
  _LAST_UNDO_DIR.mkdir(parents=True, exist_ok=True)
3209
3229
  undo_tar = _LAST_UNDO_DIR / "workspace_last.tar.gz"
3230
+ excluded = {".git", "venv", "__pycache__", ".akash", "storage", ".termux", "node_modules", ".cache", "build", "dist"}
3210
3231
  with tarfile.open(undo_tar, "w:gz") as tar:
3232
+ count = 0
3211
3233
  for item in os.listdir("."):
3212
- if item in (".git", "venv", "__pycache__", ".akash"):
3234
+ if item in excluded or item.startswith(".") or os.path.islink(item):
3235
+ continue
3236
+ p = Path(item)
3237
+ if not p.exists() or p.is_symlink():
3213
3238
  continue
3214
- if os.path.exists(item):
3215
- tar.add(item)
3239
+ try:
3240
+ if p.is_file() and p.stat().st_size > 5 * 1024 * 1024:
3241
+ continue
3242
+ except Exception:
3243
+ continue
3244
+ tar.add(item, recursive=True, filter=lambda ti: None if (ti.name in excluded or ti.issym()) else ti)
3245
+ count += 1
3246
+ if count > 100:
3247
+ break
3216
3248
  except Exception:
3217
3249
  pass
3218
3250
 
3219
3251
  def _restore_undo_checkpoint() -> tuple[bool, str]:
3252
+ cwd = Path.cwd().resolve()
3253
+ home = Path.home().resolve()
3254
+ if cwd == home or cwd == Path("/"):
3255
+ return False, "Undo snapshot is disabled when running in root or home directory for safety."
3220
3256
  undo_tar = _LAST_UNDO_DIR / "workspace_last.tar.gz"
3221
3257
  if not undo_tar.exists():
3222
3258
  return False, "No undo checkpoint available for this session."
@@ -3451,7 +3487,10 @@ def mcp_serve(
3451
3487
  ws.send(json.dumps({
3452
3488
  "type": "tool_response",
3453
3489
  "id": call_id,
3454
- "result": {"content": [{"type": "text", "text": f"⛔ {sec_reason}"}], "isError": True}
3490
+ "result": {
3491
+ "content": [{"type": "text", "text": f"⛔ Security Policy Block: {sec_reason}\nCommand: {cmd}"}],
3492
+ "isError": True
3493
+ }
3455
3494
  }))
3456
3495
  else:
3457
3496
  if any(k in cmd for k in ["touch", "mkdir", "mv", "cp", "sed", ">", ">>", "python", "npm", "pip"]):
@@ -3465,6 +3504,8 @@ def mcp_serve(
3465
3504
  exec_cmd += " -y"
3466
3505
  if re.search(r"\bdu\b", exec_cmd) and "-x" not in exec_cmd:
3467
3506
  exec_cmd = re.sub(r"\bdu\b", "du -x", exec_cmd)
3507
+ if re.search(r"\btermux-location\b", exec_cmd) and "-r" not in exec_cmd:
3508
+ exec_cmd = re.sub(r"\btermux-location\b", "termux-location -r once", exec_cmd)
3468
3509
 
3469
3510
  # Process-group-isolated runner: immune to pipe deadlocks & orphaned subshells
3470
3511
  import os, signal
@@ -3509,10 +3550,17 @@ def mcp_serve(
3509
3550
  ec_icon = f"{_G}✓{_RS}" if returncode == 0 else f"{_R}✗{_RS}"
3510
3551
  print(f"{ts_pfx} {ec_icon} {ec_color}exec:{_RS} {disp_cmd} {ec_color}[{returncode}]{_RS} {_dim(f'{elapsed_ms:.1f}ms')}")
3511
3552
 
3553
+ if returncode != 0:
3554
+ res_content = bounded_out or f"Command exited with status code {returncode} (no output)"
3555
+ if not res_content.startswith("⛔"):
3556
+ res_content = f"⛔ Command execution failed (exit code {returncode}):\n{res_content}"
3557
+ else:
3558
+ res_content = bounded_out or "(command completed successfully with no output)"
3559
+
3512
3560
  ws.send(json.dumps({
3513
3561
  "type": "tool_response",
3514
3562
  "id": call_id,
3515
- "result": {"content": [{"type": "text", "text": bounded_out or "(no output)"}], "isError": returncode != 0}
3563
+ "result": {"content": [{"type": "text", "text": res_content}], "isError": returncode != 0}
3516
3564
  }))
3517
3565
  elif t_name == "akash_undo":
3518
3566
  with _Spin("undo: reverting workspace to checkpoint", min_seconds=0.25, prefix=ts_pfx):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: akashcli
3
- Version: 4.7.8
3
+ Version: 4.8.0
4
4
  Summary: Akash CLI — secure remote shell relay, file vault, and device management
5
5
  License-Expression: MIT
6
6
  Keywords: akash,cli,relay,remote-shell,vault
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "akashcli"
3
- version = "4.7.8"
3
+ version = "4.8.0"
4
4
  description = "Akash CLI — secure remote shell relay, file vault, and device management"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes