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.
- {akashcli-4.3.0 → akashcli-4.3.2}/PKG-INFO +1 -1
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/cli.py +95 -16
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli.egg-info/PKG-INFO +1 -1
- {akashcli-4.3.0 → akashcli-4.3.2}/pyproject.toml +1 -1
- {akashcli-4.3.0 → akashcli-4.3.2}/README.md +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/__init__.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/auth.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/client.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/config.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/crypto.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/env_manager.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/exceptions.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/exec.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/integrity.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/logger.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/models.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/p2p.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/packages.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/relay.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/restore.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/snapshot_crypto.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/storage.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/terminal.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/uploader.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli/utils.py +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli.egg-info/SOURCES.txt +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli.egg-info/dependency_links.txt +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli.egg-info/entry_points.txt +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli.egg-info/requires.txt +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/akashcli.egg-info/top_level.txt +0 -0
- {akashcli-4.3.0 → akashcli-4.3.2}/setup.cfg +0 -0
|
@@ -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
|
-
|
|
908
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
1052
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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"{
|
|
1121
|
-
headers=
|
|
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"{
|
|
1134
|
-
headers=
|
|
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
|
-
|
|
1214
|
-
|
|
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(
|
|
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)
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|