akashcli 4.3.0__tar.gz → 4.3.2__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 (31) hide show
  1. {akashcli-4.3.0 → akashcli-4.3.2}/PKG-INFO +1 -1
  2. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/cli.py +95 -16
  3. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli.egg-info/PKG-INFO +1 -1
  4. {akashcli-4.3.0 → akashcli-4.3.2}/pyproject.toml +1 -1
  5. {akashcli-4.3.0 → akashcli-4.3.2}/README.md +0 -0
  6. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/__init__.py +0 -0
  7. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/auth.py +0 -0
  8. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/client.py +0 -0
  9. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/config.py +0 -0
  10. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/crypto.py +0 -0
  11. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/env_manager.py +0 -0
  12. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/exceptions.py +0 -0
  13. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/exec.py +0 -0
  14. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/integrity.py +0 -0
  15. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/logger.py +0 -0
  16. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/models.py +0 -0
  17. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/p2p.py +0 -0
  18. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/packages.py +0 -0
  19. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/relay.py +0 -0
  20. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/restore.py +0 -0
  21. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/snapshot_crypto.py +0 -0
  22. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/storage.py +0 -0
  23. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/terminal.py +0 -0
  24. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/uploader.py +0 -0
  25. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/utils.py +0 -0
  26. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli.egg-info/SOURCES.txt +0 -0
  27. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli.egg-info/dependency_links.txt +0 -0
  28. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli.egg-info/entry_points.txt +0 -0
  29. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli.egg-info/requires.txt +0 -0
  30. {akashcli-4.3.0 → akashcli-4.3.2}/akashcli.egg-info/top_level.txt +0 -0
  31. {akashcli-4.3.0 → akashcli-4.3.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: akashcli
3
- Version: 4.3.0
3
+ Version: 4.3.2
4
4
  Summary: Akash CLI — secure remote shell relay, file vault, and device management
5
5
  License: MIT
6
6
  Keywords: akash,cli,relay,remote-shell,vault
@@ -74,6 +74,40 @@ class _Spin:
74
74
  sys.stdout.flush()
75
75
 
76
76
 
77
+ def _resolve_client(url_override: str = None, require_key: bool = False):
78
+ """
79
+ Return (api_key_or_None, base_url).
80
+
81
+ require_key=True — hard-fail with a clear message if no key found
82
+ (used by serve/devices which cannot work without server auth).
83
+ require_key=False — return None for api_key if missing; caller shows warning
84
+ and can offer a local/offline fallback.
85
+ """
86
+ import os as _os
87
+ config = ConfigManager.load()
88
+ base = (
89
+ url_override
90
+ or _os.getenv("AKASH_API_URL")
91
+ or config.get("api_url", "https://jstore.2bd.net")
92
+ ).rstrip("/")
93
+
94
+ api_key = _os.getenv("AKASH_API_KEY") or config.get("api_key") or None
95
+
96
+ if not api_key and require_key:
97
+ print(f" {_Y}!{_RS} No API key found.")
98
+ print(f" {_DM}Run {_C}akash login{_RS}{_DM} to save your key, or set {_C}AKASH_API_KEY{_RS}{_DM}.{_RS}")
99
+ raise typer.Exit(1)
100
+
101
+ return api_key, base
102
+
103
+
104
+ _GUEST_WARNING = (
105
+ f" {_Y}⚠{_RS} {_Y}Running as guest{_RS} — not logged in.\n"
106
+ f" {_DM}Features are limited and your data won't be saved to the cloud.\n"
107
+ f" Run {_RS}{_C}akash login{_RS}{_DM} to unlock full access.{_RS}"
108
+ )
109
+
110
+
77
111
  def _progress_bar(done: int, total: int, width: int = 28) -> str:
78
112
  """Return a plain ASCII progress bar string."""
79
113
  if not total:
@@ -904,8 +938,13 @@ def run(
904
938
  from .exec import acquire_exec_token, run_command, _clear_cached_token
905
939
 
906
940
  try:
907
- client = AkashClient()
908
- base = (url or client.base_url).rstrip("/")
941
+ api_key, base = _resolve_client(url)
942
+
943
+ # ── No key + device flag → relay needs auth ───────────────────────
944
+ if device is not None and not api_key:
945
+ print(_GUEST_WARNING)
946
+ _err("relay requires an API key. Run `akash login` first.")
947
+ raise typer.Exit(1)
909
948
 
910
949
  # ── Device relay path ─────────────────────────────────────────────
911
950
  if device is not None:
@@ -914,7 +953,7 @@ def run(
914
953
  _p()
915
954
  with _Spin("connecting to relay…"):
916
955
  pass
917
- exit_code = connect_run(client.api_key, base, command, target=device or None)
956
+ exit_code = connect_run(api_key, base, command, target=device or None)
918
957
  _p()
919
958
  if exit_code == 0:
920
959
  _info("exited 0")
@@ -923,12 +962,28 @@ def run(
923
962
  raise typer.Exit(exit_code)
924
963
  return
925
964
 
965
+ # ── No key → local execution fallback ────────────────────────────
966
+ if not api_key:
967
+ print(_GUEST_WARNING)
968
+ _p()
969
+ _info(f"running locally: {command}")
970
+ _p()
971
+ import subprocess as _sp
972
+ result = _sp.run(command, shell=True)
973
+ _p()
974
+ if result.returncode == 0:
975
+ _info("exited 0")
976
+ else:
977
+ _warn(f"exited {result.returncode}")
978
+ raise typer.Exit(result.returncode)
979
+ return
980
+
926
981
  if reauth:
927
982
  _clear_cached_token()
928
983
  _info("cleared cached token — re-authenticating…")
929
984
 
930
985
  with _Spin("authenticating…"):
931
- token = acquire_exec_token(client.api_key, base)
986
+ token = acquire_exec_token(api_key, base)
932
987
 
933
988
  _info(f"running: {command}")
934
989
  _p()
@@ -1048,8 +1103,13 @@ def shell(
1048
1103
  from .exec import acquire_exec_token, run_shell, _clear_cached_token
1049
1104
 
1050
1105
  try:
1051
- client = AkashClient()
1052
- base = (url or client.base_url).rstrip("/")
1106
+ api_key, base = _resolve_client(url)
1107
+
1108
+ # ── No key + device flag → relay needs auth ───────────────────────
1109
+ if device is not None and not api_key:
1110
+ print(_GUEST_WARNING)
1111
+ _err("relay requires an API key. Run `akash login` first.")
1112
+ raise typer.Exit(1)
1053
1113
 
1054
1114
  # ── Device relay path ─────────────────────────────────────────────
1055
1115
  if device is not None:
@@ -1057,7 +1117,7 @@ def shell(
1057
1117
  label = device.strip() if device.strip() else None
1058
1118
  _info(f"connecting to device {_cy(label or 'auto')}…")
1059
1119
  try:
1060
- exit_code = connect_shell(client.api_key, base, target=label)
1120
+ exit_code = connect_shell(api_key, base, target=label)
1061
1121
  except RuntimeError as e:
1062
1122
  _err(str(e))
1063
1123
  raise typer.Exit(1)
@@ -1067,12 +1127,26 @@ def shell(
1067
1127
  raise typer.Exit(exit_code)
1068
1128
  return
1069
1129
 
1130
+ # ── No key → local PTY shell fallback ────────────────────────────
1131
+ if not api_key:
1132
+ import shutil as _sh
1133
+ print(_GUEST_WARNING)
1134
+ _p()
1135
+ shell_bin = os.environ.get("SHELL") or _sh.which("bash") or _sh.which("sh") or "/bin/sh"
1136
+ _info(f"opening local shell {_dim(shell_bin)}")
1137
+ _p()
1138
+ import subprocess as _sp
1139
+ result = _sp.run([shell_bin])
1140
+ _p()
1141
+ _info("session closed")
1142
+ raise typer.Exit(result.returncode)
1143
+
1070
1144
  if reauth:
1071
1145
  _clear_cached_token()
1072
1146
  _info("cleared cached token — re-authenticating…")
1073
1147
 
1074
1148
  with _Spin("authenticating…"):
1075
- token = acquire_exec_token(client.api_key, base)
1149
+ token = acquire_exec_token(api_key, base)
1076
1150
 
1077
1151
  exit_code = run_shell(token, base)
1078
1152
 
@@ -1108,17 +1182,21 @@ def devices(
1108
1182
  akash devices --revoke laptop remove a device
1109
1183
  """
1110
1184
  try:
1111
- client = AkashClient()
1185
+ api_key, base = _resolve_client(require_key=True)
1186
+ except typer.Exit:
1187
+ raise
1112
1188
  except Exception as e:
1113
1189
  _err(str(e))
1114
1190
  raise typer.Exit(1)
1115
1191
 
1192
+ _hdrs = {"x-api-key": api_key, "Origin": "https://akash.cli"}
1193
+
1116
1194
  if revoke:
1117
1195
  try:
1118
1196
  import httpx as _hx
1119
1197
  resp = _hx.delete(
1120
- f"{client.base_url}/api/exec/devices/{revoke}",
1121
- headers=client._get_headers(), timeout=10,
1198
+ f"{base}/api/exec/devices/{revoke}",
1199
+ headers=_hdrs, timeout=10,
1122
1200
  )
1123
1201
  resp.raise_for_status()
1124
1202
  _ok(f"revoked {_ye(revoke)}")
@@ -1130,8 +1208,8 @@ def devices(
1130
1208
  try:
1131
1209
  import httpx as _hx
1132
1210
  resp = _hx.get(
1133
- f"{client.base_url}/api/exec/devices",
1134
- headers=client._get_headers(), timeout=10,
1211
+ f"{base}/api/exec/devices",
1212
+ headers=_hdrs, timeout=10,
1135
1213
  )
1136
1214
  resp.raise_for_status()
1137
1215
  data = resp.json()
@@ -1210,8 +1288,9 @@ def serve(
1210
1288
  return
1211
1289
 
1212
1290
  try:
1213
- client = AkashClient()
1214
- base = (url or client.base_url).rstrip("/")
1291
+ api_key, base = _resolve_client(url, require_key=True)
1292
+ except typer.Exit:
1293
+ raise
1215
1294
  except Exception as e:
1216
1295
  _err(str(e))
1217
1296
  raise typer.Exit(1)
@@ -1221,7 +1300,7 @@ def serve(
1221
1300
  resolved_label = (label or _cfg_label() or "default").strip()
1222
1301
 
1223
1302
  try:
1224
- _serve(client.api_key, base, resolved_label, daemon=daemon)
1303
+ _serve(api_key, base, resolved_label, daemon=daemon)
1225
1304
  except Exception as e:
1226
1305
  _err(f"serve failed: {e}")
1227
1306
  raise typer.Exit(1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: akashcli
3
- Version: 4.3.0
3
+ Version: 4.3.2
4
4
  Summary: Akash CLI — secure remote shell relay, file vault, and device management
5
5
  License: MIT
6
6
  Keywords: akash,cli,relay,remote-shell,vault
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "akashcli"
3
- version = "4.3.0"
3
+ version = "4.3.2"
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