ap-client 0.6.0.dev2__tar.gz → 0.6.1.dev0__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 (26) hide show
  1. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/PKG-INFO +5 -3
  2. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/api.py +1 -33
  3. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/cli.py +6 -72
  4. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/dataset_commands.py +46 -12
  5. ap_client-0.6.1.dev0/ap_client/dataset_name.py +53 -0
  6. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/dataset_register.py +20 -6
  7. ap_client-0.6.1.dev0/ap_client/dfs_commands.py +680 -0
  8. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/instance_commands.py +519 -52
  9. ap_client-0.6.1.dev0/ap_client/instance_options.py +94 -0
  10. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/irepo_sdk.py +69 -1
  11. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/managed_ak.py +5 -16
  12. ap_client-0.6.1.dev0/ap_client/ossutil_hash.py +329 -0
  13. ap_client-0.6.1.dev0/ap_client/ossutil_io.py +1168 -0
  14. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/repo_read_guard.py +6 -2
  15. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/split_publish.py +1 -1
  16. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/pyproject.toml +6 -3
  17. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/__init__.py +0 -0
  18. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/akpool_commands.py +0 -0
  19. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/config.py +0 -0
  20. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/exporter.py +0 -0
  21. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/fs_commands.py +0 -0
  22. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/manifest_view.py +0 -0
  23. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/profile_commands.py +0 -0
  24. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/share_api.py +0 -0
  25. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/tbb.py +0 -0
  26. {ap_client-0.6.0.dev2 → ap_client-0.6.1.dev0}/ap_client/waiter.py +0 -0
@@ -1,18 +1,20 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ap-client
3
- Version: 0.6.0.dev2
3
+ Version: 0.6.1.dev0
4
4
  Summary: Agent Platform API Client & CLI
5
5
  Requires-Python: >=3.10
6
+ Requires-Dist: click>=8.0.0
6
7
  Requires-Dist: irepo-artifact==0.2.1
7
8
  Requires-Dist: pyyaml>=6.0
8
9
  Requires-Dist: requests>=2.28.0
9
10
  Requires-Dist: rich>=13.0.0
10
11
  Requires-Dist: typer>=0.9.0
12
+ Requires-Dist: urllib3>=1.26
11
13
  Requires-Dist: websockets>=13.0
12
14
  Provides-Extra: all
13
- Requires-Dist: instance-repo[oss]<2.0.0,>=1.3.2; extra == 'all'
15
+ Requires-Dist: instance-repo[oss]<2.0.0,>=1.4.0.dev3; extra == 'all'
14
16
  Provides-Extra: dataset
15
- Requires-Dist: instance-repo[oss]<2.0.0,>=1.3.2; extra == 'dataset'
17
+ Requires-Dist: instance-repo[oss]<2.0.0,>=1.4.0.dev3; extra == 'dataset'
16
18
  Description-Content-Type: text/markdown
17
19
 
18
20
  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.
@@ -1125,15 +1125,8 @@ class APIClient:
1125
1125
  benchmark: Optional[str] = None,
1126
1126
  experiment: Optional[str] = None,
1127
1127
  ak_ids: Optional[list[str]] = None,
1128
- priority: Optional[str] = None,
1129
- priority_weight: Optional[int] = None,
1130
1128
  ) -> dict:
1131
- """Create a group with optional scheduling defaults for its Jobs.
1132
-
1133
- Omitted priority fields use the server defaults: medium and weight 0.
1134
- """
1135
- if priority is not None and priority not in {"high", "medium"}:
1136
- raise ValueError("priority must be one of high/medium")
1129
+ """Create a group."""
1137
1130
  if ak_ids is not None and not isinstance(ak_ids, list):
1138
1131
  raise ValueError("ak_ids must be a list")
1139
1132
  references = list(ak_ids or [])
@@ -1171,10 +1164,6 @@ class APIClient:
1171
1164
  body["queue_id"] = effective_queue_id
1172
1165
  if max_concurrency is not None:
1173
1166
  body["max_concurrency"] = max_concurrency
1174
- if priority is not None:
1175
- body["priority"] = priority
1176
- if priority_weight is not None:
1177
- body["priority_weight"] = priority_weight
1178
1167
  if eval_config is not None:
1179
1168
  body["eval_config"] = eval_config
1180
1169
  if model_base_url_collection is not None:
@@ -1893,9 +1882,6 @@ class APIClient:
1893
1882
  meta_teacher_direction: Optional[str] = None,
1894
1883
  meta_train_stage: Optional[str] = None,
1895
1884
  benchmark: Optional[str] = None,
1896
- priority: Optional[str] = None,
1897
- priority_weight: Optional[int] = None,
1898
- priority_update_mode: Optional[str] = None,
1899
1885
  ) -> dict:
1900
1886
  """Update group properties.
1901
1887
 
@@ -1908,19 +1894,7 @@ class APIClient:
1908
1894
  ``meta_*`` 独立属性为部分更新(传了才改,不支持清除);新服务端
1909
1895
  优先读属性,老服务端忽略属性——因此过渡期内同时也会将属性合并进
1910
1896
  tags 轨(双写)。
1911
-
1912
- Priority changes update the Group defaults. The default existing mode
1913
- also updates all current Jobs, including PostProcess; incremental mode
1914
- changes only the defaults for future Jobs. Updating priority alone uses
1915
- weight 0; updating only weight preserves the current priority tier.
1916
1897
  """
1917
- if priority is not None and priority not in {"high", "medium"}:
1918
- raise ValueError("priority must be one of high/medium")
1919
- if priority_update_mode is not None:
1920
- if priority_update_mode not in {"existing", "incremental"}:
1921
- raise ValueError("priority_update_mode must be one of existing/incremental")
1922
- if priority is None and priority_weight is None:
1923
- raise ValueError("priority_update_mode requires priority or priority_weight")
1924
1898
  body: dict = {}
1925
1899
 
1926
1900
  if max_concurrency is not None:
@@ -1937,12 +1911,6 @@ class APIClient:
1937
1911
  body["scaffold"] = scaffold
1938
1912
  if benchmark is not None:
1939
1913
  body["benchmark"] = benchmark
1940
- if priority is not None:
1941
- body["priority"] = priority
1942
- if priority_weight is not None:
1943
- body["priority_weight"] = priority_weight
1944
- if priority_update_mode is not None:
1945
- body["priority_update_mode"] = priority_update_mode
1946
1914
  meta_attr_tags = _merge_meta_tags(
1947
1915
  None,
1948
1916
  meta_model=meta_model,
@@ -25,6 +25,7 @@ from ap_client.api import (
25
25
  )
26
26
  from ap_client.config import ENV_VAR_SPECS, ConfigurationError, _parse_bool, normalize_output_format
27
27
  from ap_client.dataset_commands import register as _register_dataset_commands
28
+ from ap_client.dfs_commands import register as _register_dfs_commands
28
29
  from ap_client.exporter import export_group, export_job, export_jobs
29
30
  from ap_client.fs_commands import register as _register_fs_commands
30
31
  from ap_client.instance_commands import register as _register_instance_commands
@@ -167,6 +168,7 @@ app.add_typer(checkpoint_app, name="checkpoint")
167
168
  # ap dataset version/split/access 嵌套在 dataset 下;instance/fs 是一等资源。
168
169
  _register_dataset_commands(dataset_app)
169
170
  _register_instance_commands(app)
171
+ _register_dfs_commands(app)
170
172
  _register_fs_commands(app)
171
173
  _register_akpool_commands(app)
172
174
 
@@ -642,18 +644,7 @@ def _print_formatted(data: dict, output_format: str) -> None:
642
644
  import yaml
643
645
  except ImportError as exc:
644
646
  raise typer.BadParameter("--format yaml requires PyYAML to be installed") from exc
645
-
646
- class LosslessDumper(yaml.SafeDumper):
647
- pass
648
-
649
- def represent_string(dumper, value):
650
- # YAML normalizes literal NEL/line separators in unquoted scalars.
651
- # Double quotes make the emitter escape them while keeping Chinese readable.
652
- style = '"' if any(character in value for character in "\x85\u2028\u2029") else None
653
- return dumper.represent_scalar("tag:yaml.org,2002:str", value, style=style)
654
-
655
- LosslessDumper.add_representer(str, represent_string)
656
- typer.echo(yaml.dump(data, Dumper=LosslessDumper, allow_unicode=True, sort_keys=False))
647
+ typer.echo(yaml.safe_dump(data, allow_unicode=True, sort_keys=False))
657
648
  return
658
649
  _print_json(data)
659
650
 
@@ -3230,12 +3221,12 @@ def job_create(
3230
3221
  priority: Optional[str] = typer.Option(
3231
3222
  None,
3232
3223
  "--priority",
3233
- help="Scheduling tier: high or medium. Omit both priority flags to inherit Group defaults; otherwise an omitted tier is medium",
3224
+ help="Scheduling priority tier: high or medium (default: medium)",
3234
3225
  ),
3235
3226
  priority_weight: Optional[int] = typer.Option(
3236
3227
  None,
3237
3228
  "--priority-weight",
3238
- help="Priority weight, 0-10. Omit both priority flags to inherit Group defaults; otherwise an omitted weight is 0",
3229
+ help="Fine-grained priority weight within tier, 0-10 (default: 0)",
3239
3230
  ),
3240
3231
  resource_mode: Optional[str] = typer.Option(
3241
3232
  None,
@@ -5468,18 +5459,6 @@ def group_create(
5468
5459
  min=1,
5469
5460
  help="Maximum concurrent jobs. Server default: 50.",
5470
5461
  ),
5471
- priority: Optional[str] = typer.Option(
5472
- None,
5473
- "--priority",
5474
- help="Default priority inherited by Jobs: high or medium (server default: medium)",
5475
- ),
5476
- priority_weight: Optional[int] = typer.Option(
5477
- None,
5478
- "--priority-weight",
5479
- min=0,
5480
- max=10,
5481
- help="Default priority weight inherited by Jobs, 0-10 (server default: 0)",
5482
- ),
5483
5462
  eval_config: Optional[str] = typer.Option(
5484
5463
  None, "--eval-config", help="Evaluation config (JSON)"
5485
5464
  ),
@@ -5592,8 +5571,6 @@ def group_create(
5592
5571
  ):
5593
5572
  """Create a Group."""
5594
5573
  output_format = _normalize_output_format(output_format)
5595
- if priority is not None and priority not in {"high", "medium"}:
5596
- raise typer.BadParameter("--priority must be one of high/medium")
5597
5574
  try:
5598
5575
  for reference in ak_id or []:
5599
5576
  validate_ak_id(reference)
@@ -5675,8 +5652,6 @@ def group_create(
5675
5652
  checkpoint=checkpoint_dict,
5676
5653
  benchmark=benchmark,
5677
5654
  experiment=experiment,
5678
- **({"priority": priority} if priority is not None else {}),
5679
- **({"priority_weight": priority_weight} if priority_weight is not None else {}),
5680
5655
  )
5681
5656
  except ManagedAKProtocolError as exc:
5682
5657
  _emit_error(str(exc))
@@ -5689,10 +5664,6 @@ def group_create(
5689
5664
  print(f" ak_ids: {response_ak_ids(result)}")
5690
5665
  if result.get("queue_id") is not None:
5691
5666
  print(f" queue_id: {result.get('queue_id')}")
5692
- if result.get("priority") is not None:
5693
- print(f" priority: {result.get('priority')}")
5694
- if result.get("priority_weight") is not None:
5695
- print(f" priority_weight: {result.get('priority_weight')}")
5696
5667
  if result.get("template") is not None:
5697
5668
  print(f" template: {result.get('template')}")
5698
5669
  if result.get("agenthub_revision") is not None:
@@ -6119,40 +6090,14 @@ def group_update(
6119
6090
  "--meta-train-stage",
6120
6091
  help="Set meta_train_stage tag (options: ap meta-train-stage list)",
6121
6092
  ),
6122
- priority: Optional[str] = typer.Option(
6123
- None,
6124
- "--priority",
6125
- help="Group priority default: high or medium; --priority alone sets weight to 0",
6126
- ),
6127
- priority_weight: Optional[int] = typer.Option(
6128
- None,
6129
- "--priority-weight",
6130
- min=0,
6131
- max=10,
6132
- help="Group priority weight default, 0-10; weight alone preserves the current tier",
6133
- ),
6134
- priority_update_mode: Optional[str] = typer.Option(
6135
- None,
6136
- "--priority-update-mode",
6137
- help="existing updates defaults and all current Jobs (including PostProcess); incremental updates only defaults (server default: existing)",
6138
- ),
6139
6093
  output_format: str = typer.Option(
6140
6094
  None,
6141
6095
  "--format",
6142
6096
  help="Output format: plain/table/json/yaml (default: AP_FORMAT or command default)",
6143
6097
  ),
6144
6098
  ):
6145
- """Update Group properties and scheduling defaults inherited by Jobs."""
6099
+ """Update Group properties."""
6146
6100
  output_format = _normalize_output_format(output_format)
6147
- if priority is not None and priority not in {"high", "medium"}:
6148
- raise typer.BadParameter("--priority must be one of high/medium")
6149
- if priority_update_mode is not None:
6150
- if priority_update_mode not in {"existing", "incremental"}:
6151
- raise typer.BadParameter("--priority-update-mode must be one of existing/incremental")
6152
- if priority is None and priority_weight is None:
6153
- raise typer.BadParameter(
6154
- "--priority-update-mode requires --priority or --priority-weight"
6155
- )
6156
6101
  eval_config_dict = _parse_json_object(eval_config, "--eval-config")
6157
6102
  model_base_url_collection_list = _parse_model_base_url_collection_option(
6158
6103
  model_base_url_collection, model_base_url_file
@@ -6189,8 +6134,6 @@ def group_update(
6189
6134
  scaffold,
6190
6135
  benchmark,
6191
6136
  tags_list,
6192
- priority,
6193
- priority_weight,
6194
6137
  )
6195
6138
  ):
6196
6139
  raise typer.BadParameter("At least one field must be provided to update")
@@ -6206,13 +6149,6 @@ def group_update(
6206
6149
  scaffold=scaffold,
6207
6150
  **({"benchmark": benchmark} if benchmark is not None else {}),
6208
6151
  **({"tags": tags_list} if tags_list is not None else {}),
6209
- **({"priority": priority} if priority is not None else {}),
6210
- **({"priority_weight": priority_weight} if priority_weight is not None else {}),
6211
- **(
6212
- {"priority_update_mode": priority_update_mode}
6213
- if priority_update_mode is not None
6214
- else {}
6215
- ),
6216
6152
  )
6217
6153
  if output_format == "plain":
6218
6154
  _print_group_action_plain(
@@ -6227,8 +6163,6 @@ def group_update(
6227
6163
  "model",
6228
6164
  "scaffold",
6229
6165
  "benchmark",
6230
- "priority",
6231
- "priority_weight",
6232
6166
  "updated_at",
6233
6167
  ],
6234
6168
  )
@@ -123,7 +123,10 @@ _NO_BENCHMARK = "none"
123
123
  _FORMAT_HELP = "Output format: plain/table/json/yaml (default: AP_FORMAT or command default)"
124
124
 
125
125
  _METADATA_MODELS = ("version_first", "split_first")
126
- _VERSION_SPLIT_METADATA_MODEL = "version_first"
126
+ # IR SDK >= 1.4.0.dev3 的业务入口固定 split_first:business_metadata_model 拒绝
127
+ # version_first(仅保留给低层 legacy 读)。带 version 的 split 查询在两种模型下
128
+ # 结果一致(实测),显式 split_first 与 SDK 归一值一致且新旧 SDK 均接受。
129
+ _VERSION_SPLIT_METADATA_MODEL = "split_first"
127
130
 
128
131
  #: CLI **不替 SDK 决定元数据模型**:不下发 ``metadata_model``,由 SDK 按 profile 归一
129
132
  #: (当前为 ``split_first``)。
@@ -1186,9 +1189,26 @@ def dataset_get(
1186
1189
  "dataset_name": dataset,
1187
1190
  "registered": False,
1188
1191
  }
1189
- parts = dataset.split("/")
1190
- if len(parts) == 2 and all(parts):
1191
- rendered.update(dataset_l1=parts[0], dataset_l2=parts[1])
1192
+ from .dataset_name import (
1193
+ DatasetNameError,
1194
+ DatasetNameUpgradeRequired,
1195
+ parse_dataset_name,
1196
+ )
1197
+
1198
+ try:
1199
+ name = parse_dataset_name(dataset)
1200
+ except DatasetNameUpgradeRequired as exc:
1201
+ raise _fail(
1202
+ f"Failed to query dataset {dataset}: {exc}",
1203
+ "pip install 'ap-client[dataset]' --upgrade",
1204
+ exit_code=2,
1205
+ ) from exc
1206
+ except DatasetNameError:
1207
+ # 非规范名:不凭空发明 level 字段(与历史行为一致)。
1208
+ pass
1209
+ else:
1210
+ rendered["dataset_l1"] = name.l1
1211
+ rendered["dataset_l2"] = name.l2
1192
1212
  else:
1193
1213
  rendered = _registered_dict(detail)
1194
1214
  _emit_detail(rendered, output_format, order=_DATASET_DETAIL_ORDER, always=("status",))
@@ -1197,7 +1217,9 @@ def dataset_get(
1197
1217
 
1198
1218
 
1199
1219
  def dataset_create(
1200
- dataset: str = typer.Argument(..., help="Dataset name (e.g. alibaba/my-bench)"),
1220
+ dataset: str = typer.Argument(
1221
+ ..., help="Dataset name: L1 or L1/L2 (e.g. my-bench or alibaba/my-bench)"
1222
+ ),
1201
1223
  benchmark: str = typer.Option(..., "--benchmark", help="Benchmark name or source_id"),
1202
1224
  description: Optional[str] = typer.Option(None, "--description", help="Dataset description"),
1203
1225
  visibility: str = typer.Option(
@@ -1216,20 +1238,32 @@ def dataset_create(
1216
1238
 
1217
1239
  from instance_repo.models import DatasetSeries
1218
1240
 
1241
+ from .dataset_name import (
1242
+ DatasetNameError,
1243
+ DatasetNameUpgradeRequired,
1244
+ parse_dataset_name,
1245
+ )
1219
1246
  from .irepo_sdk import _reason
1220
1247
 
1221
- parts = dataset.split("/")
1222
- if len(parts) != 2 or not all(parts):
1248
+ try:
1249
+ name = parse_dataset_name(dataset)
1250
+ except DatasetNameUpgradeRequired as exc:
1251
+ raise _fail(
1252
+ f"Failed to create dataset {dataset}: {exc}",
1253
+ "pip install 'ap-client[dataset]' --upgrade",
1254
+ exit_code=2,
1255
+ ) from exc
1256
+ except DatasetNameError:
1223
1257
  raise _fail(
1224
- f"Failed to create dataset {dataset}: the name must be two segments <team>/<name>",
1225
- "e.g. your-team/my-bench",
1258
+ f"Failed to create dataset {dataset}: the name must be one segment (L1) "
1259
+ "or two segments (L1/L2)",
1260
+ "e.g. my-bench or your-team/my-bench",
1226
1261
  exit_code=2,
1227
1262
  )
1228
- l1, l2 = parts
1229
1263
  series = DatasetSeries(
1230
1264
  dataset_name=dataset,
1231
- dataset_l1=l1,
1232
- dataset_l2=l2,
1265
+ dataset_l1=name.l1,
1266
+ dataset_l2=name.l2,
1233
1267
  benchmark_id=benchmark_id,
1234
1268
  visibility=resolved_visibility,
1235
1269
  description=description or None,
@@ -0,0 +1,53 @@
1
+ """DatasetName 解析 Adapter:唯一入口委托给已安装的 InstanceRepo SDK。
2
+
3
+ AP CLI 不维护第三套 dataset 名解析:``instance_repo.paths.DatasetName`` 是客户端
4
+ 路径契约的唯一事实源(L1 单段 ``A`` / 两段 ``A/B``,与 apiserver 的 namespace
5
+ guard 及 conformance 契约对齐)。SDK 缺失或过旧(没有 ``DatasetName.parse``
6
+ 能力)时,给出明确的升级提示,不静默降级、不本地重写解析规则。
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import Any
12
+
13
+ __all__ = [
14
+ "DatasetNameError",
15
+ "DatasetNameUpgradeRequired",
16
+ "parse_dataset_name",
17
+ ]
18
+
19
+ #: SDK 缺失/无 DatasetName 能力时的升级提示(与 irepo_sdk 的 SdkMissing 同范式)。
20
+ _UPGRADE_HINT = (
21
+ "The installed instance-repo SDK does not provide DatasetName parsing "
22
+ "(single-segment L1 dataset names need it).\n"
23
+ "Install it with: pip install 'ap-client[dataset]' --upgrade"
24
+ )
25
+
26
+
27
+ class DatasetNameUpgradeRequired(RuntimeError):
28
+ """已安装的 instance-repo SDK 缺少 DatasetName 能力,必须升级。"""
29
+
30
+
31
+ class DatasetNameError(ValueError):
32
+ """Dataset 名不符合 IR DatasetName 契约(单段或两段、无非法段)。"""
33
+
34
+
35
+ def parse_dataset_name(value: str) -> Any:
36
+ """Parse ``value`` through the installed IR ``DatasetName`` capability.
37
+
38
+ Returns the SDK ``DatasetName`` (``canonical`` / ``l1`` / ``l2`` /
39
+ ``segments`` / ``leaf``)。Raises :class:`DatasetNameUpgradeRequired` when the
40
+ installed SDK lacks the capability; raises :class:`DatasetNameError` when
41
+ the value is not a valid L1 or L1/L2 name.
42
+ """
43
+ try:
44
+ from instance_repo.paths import DatasetName
45
+ except ImportError as exc:
46
+ raise DatasetNameUpgradeRequired(_UPGRADE_HINT) from exc
47
+ parse = getattr(DatasetName, "parse", None)
48
+ if not callable(parse):
49
+ raise DatasetNameUpgradeRequired(_UPGRADE_HINT)
50
+ try:
51
+ return parse(value)
52
+ except Exception as exc: # noqa: BLE001 - SDK 校验失败统一转成 CLI 契约
53
+ raise DatasetNameError(str(exc)) from exc
@@ -66,11 +66,25 @@ def _claim_without_workspace(
66
66
 
67
67
 
68
68
  def _create_owned_dataset(repo: Any, dataset: str, benchmark_id: str) -> dict:
69
- parts = dataset.split("/")
70
- if len(parts) != 2 or not all(parts):
69
+ from .dataset_name import (
70
+ DatasetNameError,
71
+ DatasetNameUpgradeRequired,
72
+ parse_dataset_name,
73
+ )
74
+
75
+ try:
76
+ name = parse_dataset_name(dataset)
77
+ except DatasetNameUpgradeRequired as exc:
78
+ raise datasets._fail(
79
+ f"Failed to create dataset {dataset}: {exc}",
80
+ "pip install 'ap-client[dataset]' --upgrade",
81
+ exit_code=2,
82
+ ) from exc
83
+ except DatasetNameError:
71
84
  raise datasets._fail(
72
- f"Failed to create dataset {dataset}: the name must be two segments <team>/<name>",
73
- "Use a dataset name such as your-team/my-bench",
85
+ f"Failed to create dataset {dataset}: the name must be one segment (L1) "
86
+ "or two segments (L1/L2)",
87
+ "Use a dataset name such as my-bench or your-team/my-bench",
74
88
  exit_code=2,
75
89
  )
76
90
 
@@ -78,8 +92,8 @@ def _create_owned_dataset(repo: Any, dataset: str, benchmark_id: str) -> dict:
78
92
 
79
93
  fields: dict[str, Any] = {
80
94
  "dataset_name": dataset,
81
- "dataset_l1": parts[0],
82
- "dataset_l2": parts[1],
95
+ "dataset_l1": name.l1,
96
+ "dataset_l2": name.l2,
83
97
  "visibility": "private",
84
98
  }
85
99
  if benchmark_id: