envloop-cli 1.27.0__tar.gz → 1.28.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.
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/PKG-INFO +4 -4
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/README.pypi.md +3 -3
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/_optional.py +3 -3
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/auth_cli.py +13 -11
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/lifecycle_cli.py +4 -4
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/resource_cli.py +28 -28
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/cli.py +14 -14
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/cli_output.py +2 -2
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/data_cli.py +10 -10
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/http.py +2 -2
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/navigation_resources.py +9 -9
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/resource_cli.py +18 -18
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/cli.py +16 -16
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/client.py +11 -11
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/decision.py +1 -1
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/http.py +9 -9
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/job_cost.py +2 -2
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/job_spec_cli.py +2 -2
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/resource_cli.py +5 -5
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/resources.py +2 -2
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/train.py +10 -10
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/train_runner_cli.py +1 -1
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/rsi-loop/envloop_rsi_loop/agent_runs.py +14 -19
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/rsi-loop/envloop_rsi_loop/cli.py +1 -1
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/rsi-loop/envloop_rsi_loop/cli_output.py +8 -8
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/pyproject.toml +1 -1
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/.gitignore +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/__init__.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/auth_login.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/auth_workspace.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/cli.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/cli_errors.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/cli_output.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/client.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/config.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/downloads.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/http.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/navigation_resources.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/profile_secrets.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/resources.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/terminal.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/utils/__init__.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/envloop/utils/logging.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/__init__.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/client.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/data.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/data_publications.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/data_upload.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/profile_updates.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/recipes.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/runner_packages.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/__init__.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/cli_output.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/inference.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/job_logs.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/navigation_resources.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/runtime_params.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/sandbox.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/train_log_cli.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/train_progress.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/experiment/envloop_experiment/training/__init__.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/rsi-loop/envloop_rsi_loop/__init__.py +0 -0
- {envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/rsi-loop/envloop_rsi_loop/rsi_cli.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: envloop-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.28.0
|
|
4
4
|
Summary: EnvLoop CLI and Python SDK for jobs, training, checkpoints and inference
|
|
5
5
|
Project-URL: Homepage, https://envloop.ai
|
|
6
6
|
Project-URL: Documentation, https://docs.envloop.ai
|
|
@@ -226,8 +226,8 @@ Choose a published Runner readable in your project. Save this request as `gpu-ru
|
|
|
226
226
|
{
|
|
227
227
|
"request_id": "gpu-run-001",
|
|
228
228
|
"trials": [
|
|
229
|
-
{"name": "first", "spec": {"runner": "envloop/bash@FULL_COMMIT", "resources": {"gpu_type": "H100", "gpus": 4}, "
|
|
230
|
-
{"name": "second", "spec": {"runner": "envloop/bash@FULL_COMMIT", "resources": {"gpu_type": "H100", "gpus": 4}, "
|
|
229
|
+
{"name": "first", "spec": {"runner": "envloop/bash@FULL_COMMIT", "resources": {"gpu_type": "H100", "gpus": 4}, "timeout_seconds": 600}},
|
|
230
|
+
{"name": "second", "spec": {"runner": "envloop/bash@FULL_COMMIT", "resources": {"gpu_type": "H100", "gpus": 4}, "timeout_seconds": 600}}
|
|
231
231
|
]
|
|
232
232
|
}
|
|
233
233
|
```
|
|
@@ -272,7 +272,7 @@ with Client.remote() as client:
|
|
|
272
272
|
```
|
|
273
273
|
|
|
274
274
|
Use the exact model returned by the Job. The SDK forwards the payload to the
|
|
275
|
-
Job's `/
|
|
275
|
+
Job's `/inference/decision` API; the approved plugin validates its business fields.
|
|
276
276
|
Availability requires matching platform support and approved content in your project.
|
|
277
277
|
|
|
278
278
|
## ANS data and verified downloads
|
|
@@ -209,8 +209,8 @@ Choose a published Runner readable in your project. Save this request as `gpu-ru
|
|
|
209
209
|
{
|
|
210
210
|
"request_id": "gpu-run-001",
|
|
211
211
|
"trials": [
|
|
212
|
-
{"name": "first", "spec": {"runner": "envloop/bash@FULL_COMMIT", "resources": {"gpu_type": "H100", "gpus": 4}, "
|
|
213
|
-
{"name": "second", "spec": {"runner": "envloop/bash@FULL_COMMIT", "resources": {"gpu_type": "H100", "gpus": 4}, "
|
|
212
|
+
{"name": "first", "spec": {"runner": "envloop/bash@FULL_COMMIT", "resources": {"gpu_type": "H100", "gpus": 4}, "timeout_seconds": 600}},
|
|
213
|
+
{"name": "second", "spec": {"runner": "envloop/bash@FULL_COMMIT", "resources": {"gpu_type": "H100", "gpus": 4}, "timeout_seconds": 600}}
|
|
214
214
|
]
|
|
215
215
|
}
|
|
216
216
|
```
|
|
@@ -255,7 +255,7 @@ with Client.remote() as client:
|
|
|
255
255
|
```
|
|
256
256
|
|
|
257
257
|
Use the exact model returned by the Job. The SDK forwards the payload to the
|
|
258
|
-
Job's `/
|
|
258
|
+
Job's `/inference/decision` API; the approved plugin validates its business fields.
|
|
259
259
|
Availability requires matching platform support and approved content in your project.
|
|
260
260
|
|
|
261
261
|
## ANS data and verified downloads
|
|
@@ -16,11 +16,11 @@ from typing import Any, override
|
|
|
16
16
|
FEATURES = {'data': 'envloop_data', 'experiment': 'envloop_experiment', 'rsi-loop': 'envloop_rsi_loop'}
|
|
17
17
|
FEATURE_COMMANDS = {
|
|
18
18
|
'data': {
|
|
19
|
-
'dataset': 'Discover
|
|
19
|
+
'dataset': 'Discover Datasets, revisions and tasks',
|
|
20
20
|
'data': 'Manage versioned Data resources and verified file downloads',
|
|
21
21
|
'runner': 'Discover available Runner revisions',
|
|
22
|
-
'checkpoint': 'List and download saved training
|
|
23
|
-
'profile': 'Manage platform runtime
|
|
22
|
+
'checkpoint': 'List and download saved training Checkpoints',
|
|
23
|
+
'profile': 'Manage platform runtime Profiles',
|
|
24
24
|
},
|
|
25
25
|
'experiment': {
|
|
26
26
|
'job': 'Submit and manage Agent, Sandbox, Train and Inference Jobs',
|
|
@@ -8,6 +8,8 @@ from typing import Any, cast
|
|
|
8
8
|
from .config import ConfigError, ConfigStore, normalize_url, validate_key
|
|
9
9
|
|
|
10
10
|
DEFAULT_BASE_URL = "https://api.envloop.ai"
|
|
11
|
+
CONFIG_FIELDS = ["base-url", "api-key", "workspace-id", "project-id"]
|
|
12
|
+
FIELD_HELP = "One of " + ", ".join(CONFIG_FIELDS)
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
def add_auth_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParser]") -> None:
|
|
@@ -23,29 +25,29 @@ def add_auth_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParse
|
|
|
23
25
|
actions = configure.add_subparsers(dest="config_action")
|
|
24
26
|
init = actions.add_parser("init", help="Configure interactively with masked API key input")
|
|
25
27
|
init.add_argument("--no-check", action="store_true", default=argparse.SUPPRESS, help="Save without API verification (offline)")
|
|
26
|
-
project = actions.add_parser("project", help="Select and verify a
|
|
27
|
-
project.add_argument("project_id", nargs="?", help="Project ID; omit for an interactive list with names and IDs")
|
|
28
|
-
project.add_argument("--stdin", action="store_true", help="Read the selected
|
|
28
|
+
project = actions.add_parser("project", help="Select and verify a Project with its own API key")
|
|
29
|
+
project.add_argument("project_id", metavar="PROJECT_ID", nargs="?", help="Project ID; omit for an interactive list with names and IDs")
|
|
30
|
+
project.add_argument("--stdin", action="store_true", help="Read the selected Project's API key from stdin")
|
|
29
31
|
setting = actions.add_parser("set", help="Save one field (API key is masked or read from stdin)")
|
|
30
|
-
setting.add_argument("field",
|
|
31
|
-
setting.add_argument("value", nargs="?", help=f"Base URL (default: {DEFAULT_BASE_URL}) or
|
|
32
|
+
setting.add_argument("field", metavar="FIELD", choices=CONFIG_FIELDS, help=FIELD_HELP)
|
|
33
|
+
setting.add_argument("value", metavar="VALUE", nargs="?", help=f"Base URL (default: {DEFAULT_BASE_URL}) or Workspace ID; API keys use masked input or --stdin")
|
|
32
34
|
setting.add_argument("--stdin", action="store_true", help="Read a single API key from stdin")
|
|
33
35
|
setting.add_argument("--no-check", action="store_true", default=argparse.SUPPRESS, help="Save API key without verification (offline)")
|
|
34
36
|
getting = actions.add_parser("get", help="Read saved configuration; never export an API key")
|
|
35
|
-
getting.add_argument("field",
|
|
37
|
+
getting.add_argument("field", metavar="FIELD", choices=CONFIG_FIELDS, help=FIELD_HELP)
|
|
36
38
|
actions.add_parser("path", help="Print configuration and credential file paths")
|
|
37
39
|
show = actions.add_parser("show", help="Show saved and effective settings without revealing keys")
|
|
38
40
|
show.add_argument("--json", action="store_true")
|
|
39
41
|
remove = actions.add_parser("unset", help="Delete a saved field; does not revoke the server key")
|
|
40
|
-
remove.add_argument("field",
|
|
42
|
+
remove.add_argument("field", metavar="FIELD", choices=CONFIG_FIELDS, help=FIELD_HELP)
|
|
41
43
|
status = commands.add_parser("status", help="Inspect local credentials; --check verifies read access")
|
|
42
44
|
status.add_argument("--check", action="store_true", help="Make a read-only request to the effective Base URL")
|
|
43
45
|
status.add_argument("--json", action="store_true")
|
|
44
46
|
commands.add_parser("logout", help="Remove the saved key for the stored default Base URL (local only)")
|
|
45
|
-
workspace = commands.add_parser("workspace", help="Select and verify the active
|
|
46
|
-
workspace.add_argument("workspace_id", nargs="?", help="Workspace ID; omit for an interactive list")
|
|
47
|
-
workspace.add_argument("--project-id", help="Project within the
|
|
48
|
-
workspace.add_argument("--stdin", action="store_true", help="Read the selected
|
|
47
|
+
workspace = commands.add_parser("workspace", help="Select and verify the active Workspace")
|
|
48
|
+
workspace.add_argument("workspace_id", metavar="WORKSPACE_ID", nargs="?", help="Workspace ID; omit for an interactive list")
|
|
49
|
+
workspace.add_argument("--project-id", help="Project within the Workspace; its own API key is required")
|
|
50
|
+
workspace.add_argument("--stdin", action="store_true", help="Read the selected Workspace's API key from stdin")
|
|
49
51
|
|
|
50
52
|
|
|
51
53
|
def _key_from_input(stdin: bool = False) -> str:
|
|
@@ -6,7 +6,7 @@ from typing import Any
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def wait_options(parser: argparse.ArgumentParser):
|
|
9
|
-
parser.add_argument('--wait', action='store_true', help='Wait for the persisted cleanup
|
|
9
|
+
parser.add_argument('--wait', action='store_true', help='Wait for the persisted cleanup Operation')
|
|
10
10
|
parser.add_argument('--timeout-seconds', type=float, default=600)
|
|
11
11
|
|
|
12
12
|
|
|
@@ -14,10 +14,10 @@ def add_management_commands(settings: "argparse._SubParsersAction[argparse.Argum
|
|
|
14
14
|
operations = settings.add_parser('operation', help='Inspect or retry persisted cleanup').add_subparsers(dest='operation_action', required=True)
|
|
15
15
|
for action in ('get', 'retry', 'wait'):
|
|
16
16
|
command = operations.add_parser(action)
|
|
17
|
-
command.add_argument('identifier')
|
|
17
|
+
command.add_argument('identifier', metavar='OPERATION_ID')
|
|
18
18
|
if action == 'wait':
|
|
19
19
|
command.add_argument('--timeout-seconds', type=float, default=600)
|
|
20
|
-
cleanup = settings.add_parser('cleanup', help='Clean an explicit set of
|
|
20
|
+
cleanup = settings.add_parser('cleanup', help='Clean an explicit set of Project resource IDs')
|
|
21
21
|
cleanup.add_argument('--file', type=Path, required=True, help='JSON array of resource kind and ID objects')
|
|
22
22
|
cleanup.add_argument('--request-id', required=True)
|
|
23
23
|
wait_options(cleanup)
|
|
@@ -27,7 +27,7 @@ def add_management_commands(settings: "argparse._SubParsersAction[argparse.Argum
|
|
|
27
27
|
create.add_argument('--request-id', required=True)
|
|
28
28
|
for action in ('get', 'cleanup', 'retain'):
|
|
29
29
|
command = scopes.add_parser(action)
|
|
30
|
-
command.add_argument('identifier')
|
|
30
|
+
command.add_argument('identifier', metavar='RESOURCE_SCOPE_ID')
|
|
31
31
|
if action == 'cleanup':
|
|
32
32
|
wait_options(command)
|
|
33
33
|
if action == 'retain':
|
|
@@ -17,10 +17,10 @@ def listing(commands: "argparse._SubParsersAction[argparse.ArgumentParser]", *,
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def add_resource_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParser]") -> None:
|
|
20
|
-
dashboard = groups.add_parser('dashboard', help='Inspect the current
|
|
21
|
-
dashboard.add_parser('get', help='Show
|
|
20
|
+
dashboard = groups.add_parser('dashboard', help='Inspect the current Project overview').add_subparsers(dest='action', required=True)
|
|
21
|
+
dashboard.add_parser('get', help='Show Project details and recent experiment pages')
|
|
22
22
|
|
|
23
|
-
billing = groups.add_parser('billing', help='Inspect
|
|
23
|
+
billing = groups.add_parser('billing', help='Inspect Project billing and recorded usage').add_subparsers(dest='resource', required=True)
|
|
24
24
|
for resource in ('account', 'usage', 'ledger', 'price'):
|
|
25
25
|
commands = billing.add_parser(resource, help=f'Inspect billing {resource}').add_subparsers(dest='action', required=True)
|
|
26
26
|
command = commands.add_parser('get', help='Show the billing account') if resource == 'account' else listing(commands, paged=False)
|
|
@@ -31,27 +31,27 @@ def add_resource_commands(groups: "argparse._SubParsersAction[argparse.ArgumentP
|
|
|
31
31
|
if resource == 'ledger':
|
|
32
32
|
command.add_argument('--limit', type=int, default=25)
|
|
33
33
|
|
|
34
|
-
limits = groups.add_parser('limit', help='Inspect
|
|
34
|
+
limits = groups.add_parser('limit', help='Inspect Project resource limits').add_subparsers(dest='action', required=True)
|
|
35
35
|
limits.add_parser('get', help='Read effective execution limits, compose Runner state and the registry credential '
|
|
36
36
|
'count (read-only)')
|
|
37
|
-
members = groups.add_parser('member', help='Manage
|
|
37
|
+
members = groups.add_parser('member', help='Manage Project members subject to server authorization').add_subparsers(dest='action', required=True)
|
|
38
38
|
listing(members, paged=False)
|
|
39
|
-
candidates = members.add_parser('candidate', help='Find eligible
|
|
40
|
-
listing(candidates, paged=False, help='List eligible
|
|
39
|
+
candidates = members.add_parser('candidate', help='Find eligible Project members').add_subparsers(dest='candidate_action', required=True)
|
|
40
|
+
listing(candidates, paged=False, help='List eligible Project members matching a query').add_argument('--query', required=True)
|
|
41
41
|
for action in ('add', 'update', 'remove'):
|
|
42
|
-
command = members.add_parser(action, help=f'{action.capitalize()} a
|
|
43
|
-
command.add_argument('user_id')
|
|
42
|
+
command = members.add_parser(action, help=f'{action.capitalize()} a Project membership (human-session authorization required)')
|
|
43
|
+
command.add_argument('user_id', metavar='USER_ID')
|
|
44
44
|
if action != 'remove':
|
|
45
45
|
command.add_argument('--role', choices=['viewer', 'developer', 'admin'], default='developer')
|
|
46
46
|
command.add_argument('--expected-version', required=True, type=int, help='Current membership version; use 0 for a new grant')
|
|
47
47
|
|
|
48
|
-
settings = groups.add_parser('setting', help='Inspect and update the current
|
|
49
|
-
settings.add_parser('get', help='Show current
|
|
50
|
-
update = settings.add_parser('update', help='Change
|
|
48
|
+
settings = groups.add_parser('setting', help='Inspect and update the current Project settings').add_subparsers(dest='action', required=True)
|
|
49
|
+
settings.add_parser('get', help='Show current Project settings')
|
|
50
|
+
update = settings.add_parser('update', help='Change Project fields (human-session authorization required)')
|
|
51
51
|
for field in ('name', 'slug', 'region'):
|
|
52
52
|
update.add_argument('--' + field)
|
|
53
53
|
update.add_argument('--expected-version', required=True, type=int)
|
|
54
|
-
archive = settings.add_parser('archive', help='Archive the
|
|
54
|
+
archive = settings.add_parser('archive', help='Archive the Project (human-session authorization required)')
|
|
55
55
|
archive.add_argument('--expected-version', required=True, type=int)
|
|
56
56
|
from .lifecycle_cli import add_management_commands
|
|
57
57
|
add_management_commands(settings)
|
|
@@ -89,40 +89,40 @@ def _revision(value: str) -> str:
|
|
|
89
89
|
|
|
90
90
|
def add_self_service_commands(settings: "argparse._SubParsersAction[argparse.ArgumentParser]") -> None:
|
|
91
91
|
"""Project Admin settings that also work with an API key whose ceiling includes them."""
|
|
92
|
-
registry = settings.add_parser('registry', help='Manage private registry credentials for this
|
|
92
|
+
registry = settings.add_parser('registry', help='Manage private registry credentials for this Project\'s images'
|
|
93
93
|
).add_subparsers(dest='registry_action', required=True)
|
|
94
94
|
listing(registry, paged=False, help='List registry credentials (metadata only; secrets are write-only)')
|
|
95
|
-
add = registry.add_parser('add', help='Register a write-only registry credential (
|
|
95
|
+
add = registry.add_parser('add', help='Register a write-only registry credential (Project Admin)')
|
|
96
96
|
add.add_argument('--registry', required=True, help='Registry host, for example ghcr.io')
|
|
97
97
|
add.add_argument('--repository-prefix', required=True, help='Repository prefix the credential covers, for example my-org')
|
|
98
98
|
add.add_argument('--username', required=True)
|
|
99
99
|
add.add_argument('--password-stdin', action='store_true',
|
|
100
100
|
help='Read the token or password from stdin; without it you are prompted (no echo)')
|
|
101
101
|
add.add_argument('--password', '--token', nargs='?', action=_RejectSecretArgument, help=argparse.SUPPRESS)
|
|
102
|
-
remove = registry.add_parser('remove', help='Remove a credential; later image pulls no longer receive it (
|
|
103
|
-
remove.add_argument('credential_id')
|
|
104
|
-
compose = settings.add_parser('compose', help='Compose Runner (multi-container Task) access for this
|
|
102
|
+
remove = registry.add_parser('remove', help='Remove a credential; later image pulls no longer receive it (Project Admin)')
|
|
103
|
+
remove.add_argument('credential_id', metavar='CREDENTIAL_ID')
|
|
104
|
+
compose = settings.add_parser('compose', help='Compose Runner (multi-container Task) access for this Project'
|
|
105
105
|
).add_subparsers(dest='compose_action', required=True)
|
|
106
106
|
compose.add_parser('get', help='Show the effective state, the reason and the platform bounds')
|
|
107
|
-
compose.add_parser('enable', help='Request compose Runners; the platform policy may need operator approval (
|
|
108
|
-
compose.add_parser('disable', help='Withdraw this
|
|
109
|
-
concurrency = settings.add_parser('concurrency', help='Concurrent Trial limit of this
|
|
107
|
+
compose.add_parser('enable', help='Request compose Runners; the platform policy may need operator approval (Project Admin)')
|
|
108
|
+
compose.add_parser('disable', help='Withdraw this Project\'s compose Runner request (Project Admin)')
|
|
109
|
+
concurrency = settings.add_parser('concurrency', help='Concurrent Trial limit of this Project'
|
|
110
110
|
).add_subparsers(dest='concurrency_action', required=True)
|
|
111
|
-
command = concurrency.add_parser('set', help='Lower the
|
|
112
|
-
'(
|
|
111
|
+
command = concurrency.add_parser('set', help='Lower the Project limit below the operator ceiling, or none to clear it '
|
|
112
|
+
'(Project Admin)')
|
|
113
113
|
command.add_argument('value', type=_concurrency, metavar='VALUE', help='1..10000 or none')
|
|
114
|
-
model = settings.add_parser('model-access', help='Metered model access for published Runners of this
|
|
114
|
+
model = settings.add_parser('model-access', help='Metered model access for published Runners of this Project'
|
|
115
115
|
).add_subparsers(dest='model_access_action', required=True)
|
|
116
116
|
listing(model, paged=False, help='List grants and whether the platform can deliver them now')
|
|
117
|
-
grant = model.add_parser('grant', help='Let one published Runner receive the
|
|
118
|
-
'Trials (
|
|
117
|
+
grant = model.add_parser('grant', help='Let one published Runner receive the Project\'s metered model key on Fly '
|
|
118
|
+
'Trials (Project Admin)')
|
|
119
119
|
grant.add_argument('runner', type=_runner_name, metavar='NAMESPACE/NAME', help='Published Runner name')
|
|
120
120
|
grant.add_argument('--protocol', dest='protocols', action='append', choices=['anthropic', 'openai'], required=True,
|
|
121
121
|
help='Model protocol to grant; repeat for both')
|
|
122
122
|
grant.add_argument('--revision', type=_revision, help='Limit the grant to one full commit Revision')
|
|
123
123
|
revoke = model.add_parser('revoke', help='Revoke a grant; Trials that have not started no longer get the key '
|
|
124
|
-
'(
|
|
125
|
-
revoke.add_argument('grant_id')
|
|
124
|
+
'(Project Admin)')
|
|
125
|
+
revoke.add_argument('grant_id', metavar='GRANT_ID')
|
|
126
126
|
|
|
127
127
|
|
|
128
128
|
def _read_secret(args: argparse.Namespace) -> str:
|
|
@@ -79,10 +79,10 @@ def secret_option(command: argparse.ArgumentParser) -> None:
|
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
def add_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParser]") -> None:
|
|
82
|
-
profiles = groups.add_parser("profile", help="Manage platform runtime
|
|
82
|
+
profiles = groups.add_parser("profile", help="Manage platform runtime Profiles").add_subparsers(dest="action", required=True)
|
|
83
83
|
put = profiles.add_parser("create", help="Create an immutable Profile version from TOML or JSON")
|
|
84
|
-
put.add_argument("name")
|
|
85
|
-
put.add_argument("version")
|
|
84
|
+
put.add_argument("name", metavar="NAME")
|
|
85
|
+
put.add_argument("version", metavar="VERSION")
|
|
86
86
|
put.add_argument("--file", type=Path, required=True, help="Profile TOML or JSON file")
|
|
87
87
|
put.add_argument("--runner", metavar="RUNNER", help="Bind a Runner revision to this version")
|
|
88
88
|
secret_input = put.add_mutually_exclusive_group()
|
|
@@ -90,8 +90,8 @@ def add_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParser]")
|
|
|
90
90
|
secret_input.add_argument("--model-api-key-stdin", action="store_true", help="Read the model API key from one line of standard input")
|
|
91
91
|
secret_option(put)
|
|
92
92
|
update = profiles.add_parser("update", help="Edit an existing Profile by publishing a new immutable version")
|
|
93
|
-
update.add_argument("name")
|
|
94
|
-
update.add_argument("version", help="New version; existing versions cannot be overwritten")
|
|
93
|
+
update.add_argument("name", metavar="NAME")
|
|
94
|
+
update.add_argument("version", metavar="VERSION", help="New version; existing versions cannot be overwritten")
|
|
95
95
|
update.add_argument("--from-version", help="Source version; omit to use default, then newest unarchived creation")
|
|
96
96
|
update.add_argument("--file", type=Path, required=True, help="TOML or JSON patch: merge params keys, replace supplied metadata; preserve omitted fields")
|
|
97
97
|
update.add_argument("--runner", metavar="RUNNER", help="Bind a Runner revision; v1 requires a full commit; omit to preserve the source binding")
|
|
@@ -100,13 +100,13 @@ def add_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParser]")
|
|
|
100
100
|
update_secret.add_argument("--model-api-key-stdin", action="store_true", help="Read an encrypted model connection key from one line of standard input")
|
|
101
101
|
secret_option(update)
|
|
102
102
|
fork = profiles.add_parser('fork', help='Fork an existing Profile into a new immutable identity')
|
|
103
|
-
fork.add_argument('source_name')
|
|
104
|
-
fork.add_argument('source_version')
|
|
105
|
-
fork.add_argument('name')
|
|
106
|
-
fork.add_argument('version')
|
|
103
|
+
fork.add_argument('source_name', metavar='SOURCE_NAME')
|
|
104
|
+
fork.add_argument('source_version', metavar='SOURCE_VERSION')
|
|
105
|
+
fork.add_argument('name', metavar='NAME')
|
|
106
|
+
fork.add_argument('version', metavar='VERSION')
|
|
107
107
|
secret_option(fork)
|
|
108
108
|
get = profiles.add_parser("get")
|
|
109
|
-
get.add_argument("name")
|
|
109
|
+
get.add_argument("name", metavar="NAME")
|
|
110
110
|
get.add_argument("--version")
|
|
111
111
|
listing = profiles.add_parser("list")
|
|
112
112
|
listing.add_argument("--name")
|
|
@@ -115,13 +115,13 @@ def add_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParser]")
|
|
|
115
115
|
listing.add_argument("--cursor")
|
|
116
116
|
listing.add_argument("--json", action="store_true", help="Output the complete response as JSON (default: table)")
|
|
117
117
|
default = profiles.add_parser("set-default")
|
|
118
|
-
default.add_argument("name")
|
|
119
|
-
default.add_argument("version")
|
|
118
|
+
default.add_argument("name", metavar="NAME")
|
|
119
|
+
default.add_argument("version", metavar="VERSION")
|
|
120
120
|
default.add_argument("--expected-version", help="Omit only when no default exists")
|
|
121
121
|
for command in ("archive", "export"):
|
|
122
122
|
item = profiles.add_parser(command)
|
|
123
|
-
item.add_argument("name")
|
|
124
|
-
item.add_argument("version")
|
|
123
|
+
item.add_argument("name", metavar="NAME")
|
|
124
|
+
item.add_argument("version", metavar="VERSION")
|
|
125
125
|
from envloop_data.resource_cli import add_resource_commands
|
|
126
126
|
add_resource_commands(groups)
|
|
127
127
|
|
|
@@ -38,9 +38,9 @@ def list_layout(items: list[dict[str, Any]], args: argparse.Namespace) -> tuple[
|
|
|
38
38
|
render = dataset_row
|
|
39
39
|
empty = 'No datasets found.'
|
|
40
40
|
elif args.group == 'checkpoint':
|
|
41
|
-
headers = ('CHECKPOINT ID', 'TYPE', 'MODEL', '
|
|
41
|
+
headers = ('CHECKPOINT ID', 'TYPE', 'MODEL', 'JOB ID', 'URI')
|
|
42
42
|
render = lambda item: (item.get('checkpoint_id'), item.get('checkpoint_type'), item.get('base_model'),
|
|
43
|
-
item.get('job_id')
|
|
43
|
+
item.get('job_id'), item.get('uri'))
|
|
44
44
|
empty = 'No checkpoints found.'
|
|
45
45
|
elif args.group == "profile" and args.name is None:
|
|
46
46
|
headers = ("NAME", "VERSIONS", "DEFAULT", "UPDATED AT")
|
|
@@ -18,14 +18,14 @@ from envloop_data.data_publications import (
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def add_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParser]", listing: Callable[[Any], argparse.ArgumentParser]):
|
|
21
|
-
data = groups.add_parser('data', help='Manage
|
|
21
|
+
data = groups.add_parser('data', help='Manage Project ANS resources and verified downloads').add_subparsers(dest='action', required=True)
|
|
22
22
|
command = listing(data)
|
|
23
23
|
command.add_argument('--type', required=True, choices=[*KINDS, 'artifact'])
|
|
24
24
|
for option in ('ref', 'job-id', 'trial-id'):
|
|
25
25
|
command.add_argument('--' + option)
|
|
26
26
|
for action in ('get', 'files'):
|
|
27
27
|
command = data.add_parser(action, help='Read a resource and its files' if action == 'get' else 'List one page of files')
|
|
28
|
-
command.add_argument('data_id')
|
|
28
|
+
command.add_argument('data_id', metavar='DATA_ID')
|
|
29
29
|
command.add_argument('--limit', type=int, default=25)
|
|
30
30
|
command.add_argument('--cursor')
|
|
31
31
|
command.add_argument('--json', action='store_true')
|
|
@@ -35,15 +35,15 @@ def add_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParser]",
|
|
|
35
35
|
command = data.add_parser(action, help='Register native content or HF metadata' if action == 'create' else 'Register a new immutable revision')
|
|
36
36
|
command.add_argument('--type', required=action == 'create', choices=KINDS)
|
|
37
37
|
if action == 'update':
|
|
38
|
-
command.add_argument('data_id')
|
|
38
|
+
command.add_argument('data_id', metavar='DATA_ID')
|
|
39
39
|
publication_arguments(command, source=True)
|
|
40
40
|
command.add_argument('--idempotency-key', help='Reuse for a resumable multipart retry of the same input')
|
|
41
|
-
command = data.add_parser('delete', help='Retire a
|
|
42
|
-
command.add_argument('data_id')
|
|
41
|
+
command = data.add_parser('delete', help='Retire a Project registration; retain immutable content')
|
|
42
|
+
command.add_argument('data_id', metavar='DATA_ID')
|
|
43
43
|
command.add_argument('--dry-run', action='store_true', help='Check authorization and preview without revoking')
|
|
44
44
|
command.add_argument('--json', action='store_true')
|
|
45
45
|
command = data.add_parser('download', help='Download and verify an ANS directory or one resource file')
|
|
46
|
-
command.add_argument('data_id')
|
|
46
|
+
command.add_argument('data_id', metavar='DATA_ID')
|
|
47
47
|
command.add_argument('--file', dest='file_id', help='Select one file by its resource file ID')
|
|
48
48
|
command.add_argument('--split', help='Select the complete Dataset split directory')
|
|
49
49
|
command.add_argument('--output', required=True, type=Path)
|
|
@@ -57,7 +57,7 @@ def add_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParser]",
|
|
|
57
57
|
command.add_argument('--parent-id', help='Existing publication when creating a new revision')
|
|
58
58
|
for action in ('get', 'part', 'complete', 'abort'):
|
|
59
59
|
command = uploads.add_parser(action, help=f'{action.capitalize()} a multipart upload')
|
|
60
|
-
command.add_argument('upload_id')
|
|
60
|
+
command.add_argument('upload_id', metavar='UPLOAD_ID')
|
|
61
61
|
command.add_argument('--json', action='store_true')
|
|
62
62
|
if action == 'part':
|
|
63
63
|
command.add_argument('--number', type=int, required=True)
|
|
@@ -65,7 +65,7 @@ def add_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParser]",
|
|
|
65
65
|
|
|
66
66
|
|
|
67
67
|
command = uploads.add_parser('harbor', help='Upload a private Harbor task directory or tar bundle; optionally register it for Jobs')
|
|
68
|
-
command.add_argument('source', type=Path)
|
|
68
|
+
command.add_argument('source', metavar='SOURCE', type=Path)
|
|
69
69
|
command.add_argument('--name', required=True, help='Dataset name as NAMESPACE/NAME')
|
|
70
70
|
command.add_argument('--version', required=True, help='Exact version from dataset.toml')
|
|
71
71
|
command.add_argument('--register', action='store_true', help='Register the uploaded snapshot with the selected Runner')
|
|
@@ -74,12 +74,12 @@ def add_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParser]",
|
|
|
74
74
|
command.add_argument('--idempotency-key', help='Stable upload key; identical input resumes by default')
|
|
75
75
|
command.add_argument('--json', action='store_true')
|
|
76
76
|
command = data.add_parser('register', help='Register an uploaded Harbor Dataset snapshot for Jobs')
|
|
77
|
-
command.add_argument('data_id')
|
|
77
|
+
command.add_argument('data_id', metavar='DATA_ID')
|
|
78
78
|
command.add_argument('--runner', required=True, help='Existing Runner NAME@REVISION')
|
|
79
79
|
command.add_argument('--wait', action='store_true', help='Wait until registration finishes (default: return after it starts)')
|
|
80
80
|
command.add_argument('--json', action='store_true')
|
|
81
81
|
command = data.add_parser('registration', help='Read and advance Harbor Dataset registration')
|
|
82
|
-
command.add_argument('data_id')
|
|
82
|
+
command.add_argument('data_id', metavar='DATA_ID')
|
|
83
83
|
command.add_argument('--json', action='store_true')
|
|
84
84
|
|
|
85
85
|
|
|
@@ -58,9 +58,9 @@ class Endpoints:
|
|
|
58
58
|
return {"kind": "dataset", **{key: matches[0][key] for key in ("name", "version", "manifest_sha256")}}
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
def open_checkpoint_archive(self,
|
|
61
|
+
def open_checkpoint_archive(self, job_id: str) -> Download:
|
|
62
62
|
"""Read a local mock checkpoint through its authenticated public API route."""
|
|
63
|
-
path = f"/v1/
|
|
63
|
+
path = f"/v1/jobs/{quote(job_id, safe='')}/checkpoint/download"
|
|
64
64
|
try:
|
|
65
65
|
return Download(self.opener.open(Request(self.base + path, headers=self.headers), timeout=self.timeout))
|
|
66
66
|
except HTTPError as error:
|
{envloop_cli-1.27.0 → envloop_cli-1.28.0}/packages/data/envloop_data/navigation_resources.py
RENAMED
|
@@ -61,10 +61,10 @@ class Datasets:
|
|
|
61
61
|
return self.transport.request('GET', query(path, limit=limit, cursor=cursor))
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
def _checkpoint_matches(
|
|
65
|
-
if
|
|
64
|
+
def _checkpoint_matches(checkpoint: str, item: dict[str, Any]) -> bool:
|
|
65
|
+
if checkpoint in {item.get('checkpoint_id'), item.get('uri'), item.get('model_uri')}:
|
|
66
66
|
return True
|
|
67
|
-
parsed = urlsplit(
|
|
67
|
+
parsed = urlsplit(checkpoint)
|
|
68
68
|
if parsed.scheme not in {'envloop', 'tinker'} or parsed.query or parsed.fragment:
|
|
69
69
|
return False
|
|
70
70
|
name = parsed.path.lstrip('/')
|
|
@@ -128,12 +128,12 @@ class Checkpoints:
|
|
|
128
128
|
def list(self, **filters: Any) -> Any:
|
|
129
129
|
if self.training is not None:
|
|
130
130
|
return self.training.checkpoints(**filters)
|
|
131
|
-
return self.transport.request('GET', '/v1/
|
|
131
|
+
return self.transport.request('GET', '/v1/checkpoints?' + urlencode({key: value for key, value in filters.items() if value is not None}))
|
|
132
132
|
|
|
133
133
|
def delete(self, checkpoint_id: str) -> Any:
|
|
134
|
-
return self.transport.request('DELETE', f"/v1/
|
|
134
|
+
return self.transport.request('DELETE', f"/v1/checkpoints/{quote(checkpoint_id, safe='')}")
|
|
135
135
|
|
|
136
|
-
def download(self,
|
|
136
|
+
def download(self, checkpoint: str, directory: str | Path, *, job_id: str | None = None, run_id: str | None = None) -> dict[str, Any]:
|
|
137
137
|
from pathlib import Path
|
|
138
138
|
|
|
139
139
|
directory = Path(directory)
|
|
@@ -141,7 +141,7 @@ class Checkpoints:
|
|
|
141
141
|
while True:
|
|
142
142
|
page = self.list(job_id=job_id, run_id=run_id, cursor=cursor, limit=100)
|
|
143
143
|
for item in page['items']:
|
|
144
|
-
if _checkpoint_matches(
|
|
144
|
+
if _checkpoint_matches(checkpoint, item):
|
|
145
145
|
matches.append(item)
|
|
146
146
|
cursor = page.get('next_cursor')
|
|
147
147
|
if cursor is None:
|
|
@@ -172,7 +172,7 @@ class Checkpoints:
|
|
|
172
172
|
|
|
173
173
|
def refresh(self) -> None:
|
|
174
174
|
# Keep the original authorized identity and file hashes across refreshes.
|
|
175
|
-
signed = transport.request('GET', query('/v1/
|
|
175
|
+
signed = transport.request('GET', query('/v1/checkpoints/download', uri=checkpoint,
|
|
176
176
|
job_id=item['job_id'], run_id=run_id))
|
|
177
177
|
urls = signed.get('urls', {})
|
|
178
178
|
if (set(names) != set(urls)
|
|
@@ -210,7 +210,7 @@ class Checkpoints:
|
|
|
210
210
|
import tempfile
|
|
211
211
|
import zipfile
|
|
212
212
|
|
|
213
|
-
job_id = item.get('
|
|
213
|
+
job_id = item.get('job_id')
|
|
214
214
|
if not isinstance(job_id, str) or not job_id:
|
|
215
215
|
raise RemoteError('CHECKPOINT_FILES_INVALID')
|
|
216
216
|
# Bound the streamed archive by its declared payload plus ZIP metadata.
|
|
@@ -6,21 +6,21 @@ from envloop.resource_cli import listing
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def add_resource_commands(groups: "argparse._SubParsersAction[argparse.ArgumentParser]"):
|
|
9
|
-
datasets = groups.add_parser('dataset', help='Discover
|
|
9
|
+
datasets = groups.add_parser('dataset', help='Discover Datasets, revisions and tasks').add_subparsers(dest='action', required=True)
|
|
10
10
|
command = listing(datasets)
|
|
11
|
-
command.add_argument('--type', choices=['environment', 'trajectory', 'record'], help='Filter by
|
|
11
|
+
command.add_argument('--type', choices=['environment', 'trajectory', 'record'], help='Filter by Dataset content type')
|
|
12
12
|
command.add_argument('--query', help='Search Dataset names')
|
|
13
|
-
datasets.add_parser('get', help='Show a
|
|
13
|
+
datasets.add_parser('get', help='Show a Dataset and its pinned Runner reference').add_argument('name', metavar='NAME')
|
|
14
14
|
for resource in ('revision', 'task'):
|
|
15
|
-
commands = datasets.add_parser(resource, help=f'Inspect
|
|
15
|
+
commands = datasets.add_parser(resource, help=f'Inspect Dataset {resource}').add_subparsers(dest='operation', required=True)
|
|
16
16
|
command = listing(commands)
|
|
17
|
-
command.add_argument('name')
|
|
17
|
+
command.add_argument('name', metavar='NAME')
|
|
18
18
|
if resource == 'task':
|
|
19
|
-
command.add_argument('revision')
|
|
19
|
+
command.add_argument('revision', metavar='REVISION')
|
|
20
20
|
else:
|
|
21
|
-
command = commands.add_parser('get', help='Show an immutable
|
|
22
|
-
command.add_argument('name')
|
|
23
|
-
command.add_argument('revision')
|
|
21
|
+
command = commands.add_parser('get', help='Show an immutable Dataset revision')
|
|
22
|
+
command.add_argument('name', metavar='NAME')
|
|
23
|
+
command.add_argument('revision', metavar='REVISION')
|
|
24
24
|
|
|
25
25
|
from envloop_data.data_cli import add_commands
|
|
26
26
|
add_commands(groups, listing)
|
|
@@ -34,8 +34,8 @@ def add_resource_commands(groups: "argparse._SubParsersAction[argparse.ArgumentP
|
|
|
34
34
|
'SHA-256, creates the Runner on first use and registers the revision; identical retries are idempotent and '
|
|
35
35
|
'changed content for an existing revision is refused. This is el data create --type runner with the native '
|
|
36
36
|
'manifest built for you; use that command to publish an existing manifest. The key needs envloop:data:write '
|
|
37
|
-
'and runners.write, and publish permission on a Runner owned by another
|
|
38
|
-
register.add_argument('directory', type=Path, help='Runner package directory; every file in it is published')
|
|
37
|
+
'and runners.write, and publish permission on a Runner owned by another Project.')
|
|
38
|
+
register.add_argument('directory', metavar='DIRECTORY', type=Path, help='Runner package directory; every file in it is published')
|
|
39
39
|
register.add_argument('--revision', required=True, help='Full 40- or 64-character source commit, for example $(git rev-parse HEAD)')
|
|
40
40
|
register.add_argument('--name', help='NAMESPACE/NAME; must equal [runner] name in runner.toml (default: that name)')
|
|
41
41
|
register.add_argument('--executable', action='append', dest='executables', metavar='PATH',
|
|
@@ -44,18 +44,18 @@ def add_resource_commands(groups: "argparse._SubParsersAction[argparse.ArgumentP
|
|
|
44
44
|
register.add_argument('--source-ref-kind', choices=['branch', 'tag', 'commit'], default='branch', help='Kind of --source-ref (default: branch)')
|
|
45
45
|
register.add_argument('--dry-run', action='store_true', help='Validate the package and authorization without publishing')
|
|
46
46
|
|
|
47
|
-
checkpoints = groups.add_parser('checkpoint', help='List and download saved training
|
|
47
|
+
checkpoints = groups.add_parser('checkpoint', help='List and download saved training Checkpoints').add_subparsers(dest='action', required=True)
|
|
48
48
|
command = listing(checkpoints)
|
|
49
|
-
command.add_argument('--job-id', help='Only
|
|
50
|
-
command.add_argument('--run-id', help='Only
|
|
49
|
+
command.add_argument('--job-id', help='Only Checkpoints of this Train Job')
|
|
50
|
+
command.add_argument('--run-id', help='Only Checkpoints of this training run label')
|
|
51
51
|
download = checkpoints.add_parser('download', help='Download files and verify their sizes and SHA-256 hashes')
|
|
52
|
-
download.add_argument('checkpoint', metavar='CHECKPOINT', help='
|
|
53
|
-
download.add_argument('directory', type=Path)
|
|
52
|
+
download.add_argument('checkpoint', metavar='CHECKPOINT', help='Checkpoint ID or uri from `checkpoint list`')
|
|
53
|
+
download.add_argument('directory', metavar='DIRECTORY', type=Path)
|
|
54
54
|
download.add_argument('--job-id')
|
|
55
55
|
download.add_argument('--run-id')
|
|
56
56
|
from envloop.lifecycle_cli import wait_options
|
|
57
|
-
delete = checkpoints.add_parser('delete', help='Remove an unreferenced
|
|
58
|
-
delete.add_argument('identifier')
|
|
57
|
+
delete = checkpoints.add_parser('delete', help='Remove an unreferenced Checkpoint and stored files')
|
|
58
|
+
delete.add_argument('identifier', metavar='CHECKPOINT_ID')
|
|
59
59
|
wait_options(delete)
|
|
60
60
|
|
|
61
61
|
|