ap-client 0.5.1.dev3__tar.gz → 0.5.1.dev5__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.
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/PKG-INFO +3 -3
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/instance_commands.py +11 -1
- ap_client-0.5.1.dev5/ap_client/manifest_view.py +103 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/pyproject.toml +3 -3
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/__init__.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/akpool_commands.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/api.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/cli.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/config.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/dataset_commands.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/dataset_register.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/exporter.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/fs_commands.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/irepo_sdk.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/managed_ak.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/profile_commands.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/split_publish.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/tbb.py +0 -0
- {ap_client-0.5.1.dev3 → ap_client-0.5.1.dev5}/ap_client/waiter.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ap-client
|
|
3
|
-
Version: 0.5.1.
|
|
3
|
+
Version: 0.5.1.dev5
|
|
4
4
|
Summary: Agent Platform API Client & CLI
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Requires-Dist: pyyaml>=6.0
|
|
@@ -9,9 +9,9 @@ Requires-Dist: rich>=13.0.0
|
|
|
9
9
|
Requires-Dist: typer>=0.9.0
|
|
10
10
|
Requires-Dist: websockets>=13.0
|
|
11
11
|
Provides-Extra: all
|
|
12
|
-
Requires-Dist: instance-repo[oss]==1.3.2.
|
|
12
|
+
Requires-Dist: instance-repo[oss]==1.3.2.dev5; extra == 'all'
|
|
13
13
|
Provides-Extra: dataset
|
|
14
|
-
Requires-Dist: instance-repo[oss]==1.3.2.
|
|
14
|
+
Requires-Dist: instance-repo[oss]==1.3.2.dev5; extra == 'dataset'
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
|
|
17
17
|
A lightweight Python SDK and command line interface for Agent Platform. It provides helpers for configuring API access and managing templates, datasets, jobs, and groups.
|
|
@@ -493,7 +493,17 @@ def instance_get(
|
|
|
493
493
|
f"Failed to query instance {instance}: not found",
|
|
494
494
|
f"Check the instance id: ap instance list --dataset {dataset} --split {split}",
|
|
495
495
|
)
|
|
496
|
-
|
|
496
|
+
payload = _instance_record(record)
|
|
497
|
+
manifest = payload.get("manifest")
|
|
498
|
+
if output_format in ("json", "yaml") or not isinstance(manifest, list):
|
|
499
|
+
_emit_detail(payload, output_format)
|
|
500
|
+
return
|
|
501
|
+
from .manifest_view import manifest_lines
|
|
502
|
+
|
|
503
|
+
_emit_detail({key: value for key, value in payload.items() if key != "manifest"}, output_format)
|
|
504
|
+
typer.echo()
|
|
505
|
+
for line in manifest_lines(manifest):
|
|
506
|
+
typer.echo(line)
|
|
497
507
|
|
|
498
508
|
|
|
499
509
|
def _check_version_autocreate(repo, dataset: str, version: str, *, environment: str) -> bool:
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Human-readable manifest paths; never resolve or fetch the referenced files."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import re
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class _Directory:
|
|
13
|
+
directories: dict[str, _Directory] = field(default_factory=dict)
|
|
14
|
+
files: list[str] = field(default_factory=list)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _visible(value: str) -> str:
|
|
18
|
+
"""Escape control characters without interpreting terminal or Rich markup."""
|
|
19
|
+
return "".join(
|
|
20
|
+
json.dumps(char)[1:-1] if ord(char) < 32 or ord(char) == 127 else char for char in value
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _path(entry: Any) -> tuple[str, list[str]] | None:
|
|
25
|
+
if not isinstance(entry, dict):
|
|
26
|
+
return None
|
|
27
|
+
path = entry.get("file_path") or entry.get("object_path")
|
|
28
|
+
if not isinstance(path, str) or not path:
|
|
29
|
+
return None
|
|
30
|
+
uri = re.match(r"^([a-zA-Z][a-zA-Z0-9+.-]*://[^/]+/)(.*)$", path, re.DOTALL)
|
|
31
|
+
if uri:
|
|
32
|
+
root, path = uri.groups()
|
|
33
|
+
elif "://" in path:
|
|
34
|
+
return None
|
|
35
|
+
elif path.startswith("/"):
|
|
36
|
+
root, path = "/", path[1:]
|
|
37
|
+
else:
|
|
38
|
+
root = ""
|
|
39
|
+
parts = path.split("/")
|
|
40
|
+
# Unusual paths remain verbatim instead of being silently normalized.
|
|
41
|
+
if any(part in ("", ".", "..") for part in parts):
|
|
42
|
+
return None
|
|
43
|
+
return root, parts
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _tree(directory: _Directory) -> list[str]:
|
|
47
|
+
lines: list[str] = []
|
|
48
|
+
pending: list[tuple[_Directory | str, str]] = [(directory, "")]
|
|
49
|
+
# Iterative traversal also supports paths deeper than Python's recursion limit.
|
|
50
|
+
while pending:
|
|
51
|
+
node, prefix = pending.pop()
|
|
52
|
+
if isinstance(node, str):
|
|
53
|
+
lines.append(node)
|
|
54
|
+
continue
|
|
55
|
+
children = [(name + "/", child) for name, child in sorted(node.directories.items())]
|
|
56
|
+
children.extend((name, None) for name in sorted(node.files))
|
|
57
|
+
for index in range(len(children) - 1, -1, -1):
|
|
58
|
+
name, child = children[index]
|
|
59
|
+
last = index == len(children) - 1
|
|
60
|
+
if child is not None:
|
|
61
|
+
pending.append((child, prefix + (" " if last else "│ ")))
|
|
62
|
+
pending.append((prefix + ("└── " if last else "├── ") + _visible(name), ""))
|
|
63
|
+
return lines
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def manifest_lines(manifest: list[Any]) -> list[str]:
|
|
67
|
+
"""Group by storage root and show a lossless hierarchy of file paths.
|
|
68
|
+
|
|
69
|
+
Entries without usable paths retain their original values in a separate block.
|
|
70
|
+
Full metadata remains available through the command's JSON/YAML output.
|
|
71
|
+
"""
|
|
72
|
+
groups: dict[str, list[list[str]]] = {}
|
|
73
|
+
other: list[Any] = []
|
|
74
|
+
for entry in manifest:
|
|
75
|
+
path = _path(entry)
|
|
76
|
+
if path is None:
|
|
77
|
+
other.append(entry)
|
|
78
|
+
else:
|
|
79
|
+
root, parts = path
|
|
80
|
+
groups.setdefault(root, []).append(parts)
|
|
81
|
+
|
|
82
|
+
count = sum(len(paths) for paths in groups.values())
|
|
83
|
+
lines = [f"manifest: {count} {'file' if count == 1 else 'files'}"]
|
|
84
|
+
for root, paths in sorted(groups.items()):
|
|
85
|
+
common: list[str] = []
|
|
86
|
+
for parts in zip(*(path[:-1] for path in paths)):
|
|
87
|
+
if len(set(parts)) != 1:
|
|
88
|
+
break
|
|
89
|
+
common.append(parts[0])
|
|
90
|
+
shared_root = root + "/".join(common) + ("/" if common else "")
|
|
91
|
+
lines.append(f"root: {_visible(shared_root or './')}")
|
|
92
|
+
directory = _Directory()
|
|
93
|
+
for parts in paths:
|
|
94
|
+
node = directory
|
|
95
|
+
for part in parts[len(common) : -1]:
|
|
96
|
+
node = node.directories.setdefault(part, _Directory())
|
|
97
|
+
node.files.append(parts[-1])
|
|
98
|
+
lines.extend(_tree(directory))
|
|
99
|
+
if other:
|
|
100
|
+
lines.append(f"other entries: {len(other)}")
|
|
101
|
+
for entry in other:
|
|
102
|
+
lines.append(" " + json.dumps(entry, ensure_ascii=False, default=str))
|
|
103
|
+
return lines
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ap-client"
|
|
7
|
-
version = "0.5.1.
|
|
7
|
+
version = "0.5.1.dev5"
|
|
8
8
|
description = "Agent Platform API Client & CLI"
|
|
9
9
|
readme = { text = "A lightweight Python SDK and command line interface for Agent Platform. It provides helpers for configuring API access and managing templates, datasets, jobs, and groups.", content-type = "text/markdown" }
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -18,10 +18,10 @@ dependencies = [
|
|
|
18
18
|
|
|
19
19
|
[project.optional-dependencies]
|
|
20
20
|
dataset = [
|
|
21
|
-
"instance-repo[oss]==1.3.2.
|
|
21
|
+
"instance-repo[oss]==1.3.2.dev5",
|
|
22
22
|
]
|
|
23
23
|
all = [
|
|
24
|
-
"instance-repo[oss]==1.3.2.
|
|
24
|
+
"instance-repo[oss]==1.3.2.dev5",
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
[project.scripts]
|
|
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
|