ap-client 0.5.3.dev9__tar.gz → 0.6.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.
Files changed (24) hide show
  1. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/PKG-INFO +4 -6
  2. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/api.py +33 -1
  3. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/cli.py +72 -6
  4. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/instance_commands.py +51 -482
  5. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/irepo_sdk.py +2 -68
  6. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/managed_ak.py +19 -13
  7. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/repo_read_guard.py +2 -6
  8. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/pyproject.toml +4 -6
  9. ap_client-0.5.3.dev9/ap_client/instance_options.py +0 -94
  10. ap_client-0.5.3.dev9/ap_client/ossutil_commands.py +0 -469
  11. ap_client-0.5.3.dev9/ap_client/ossutil_io.py +0 -1025
  12. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/__init__.py +0 -0
  13. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/akpool_commands.py +0 -0
  14. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/config.py +0 -0
  15. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/dataset_commands.py +0 -0
  16. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/dataset_register.py +0 -0
  17. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/exporter.py +0 -0
  18. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/fs_commands.py +0 -0
  19. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/manifest_view.py +0 -0
  20. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/profile_commands.py +0 -0
  21. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/share_api.py +0 -0
  22. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/split_publish.py +0 -0
  23. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/tbb.py +0 -0
  24. {ap_client-0.5.3.dev9 → ap_client-0.6.0}/ap_client/waiter.py +0 -0
@@ -1,20 +1,18 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ap-client
3
- Version: 0.5.3.dev9
3
+ Version: 0.6.0
4
4
  Summary: Agent Platform API Client & CLI
5
5
  Requires-Python: >=3.10
6
- Requires-Dist: click>=8.0.0
7
- Requires-Dist: irepo-artifact==0.2.1
6
+ Requires-Dist: irepo-artifact==0.2.2
8
7
  Requires-Dist: pyyaml>=6.0
9
8
  Requires-Dist: requests>=2.28.0
10
9
  Requires-Dist: rich>=13.0.0
11
10
  Requires-Dist: typer>=0.9.0
12
- Requires-Dist: urllib3>=1.26
13
11
  Requires-Dist: websockets>=13.0
14
12
  Provides-Extra: all
15
- Requires-Dist: instance-repo[oss]<2.0.0,>=1.3.5.dev4; extra == 'all'
13
+ Requires-Dist: instance-repo[oss]<2.0.0,>=1.3.4; extra == 'all'
16
14
  Provides-Extra: dataset
17
- Requires-Dist: instance-repo[oss]<2.0.0,>=1.3.5.dev4; extra == 'dataset'
15
+ Requires-Dist: instance-repo[oss]<2.0.0,>=1.3.4; extra == 'dataset'
18
16
  Description-Content-Type: text/markdown
19
17
 
20
18
  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,8 +1125,15 @@ 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,
1128
1130
  ) -> dict:
1129
- """Create a group."""
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")
1130
1137
  if ak_ids is not None and not isinstance(ak_ids, list):
1131
1138
  raise ValueError("ak_ids must be a list")
1132
1139
  references = list(ak_ids or [])
@@ -1164,6 +1171,10 @@ class APIClient:
1164
1171
  body["queue_id"] = effective_queue_id
1165
1172
  if max_concurrency is not None:
1166
1173
  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
1167
1178
  if eval_config is not None:
1168
1179
  body["eval_config"] = eval_config
1169
1180
  if model_base_url_collection is not None:
@@ -1882,6 +1893,9 @@ class APIClient:
1882
1893
  meta_teacher_direction: Optional[str] = None,
1883
1894
  meta_train_stage: Optional[str] = None,
1884
1895
  benchmark: Optional[str] = None,
1896
+ priority: Optional[str] = None,
1897
+ priority_weight: Optional[int] = None,
1898
+ priority_update_mode: Optional[str] = None,
1885
1899
  ) -> dict:
1886
1900
  """Update group properties.
1887
1901
 
@@ -1894,7 +1908,19 @@ class APIClient:
1894
1908
  ``meta_*`` 独立属性为部分更新(传了才改,不支持清除);新服务端
1895
1909
  优先读属性,老服务端忽略属性——因此过渡期内同时也会将属性合并进
1896
1910
  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.
1897
1916
  """
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")
1898
1924
  body: dict = {}
1899
1925
 
1900
1926
  if max_concurrency is not None:
@@ -1911,6 +1937,12 @@ class APIClient:
1911
1937
  body["scaffold"] = scaffold
1912
1938
  if benchmark is not None:
1913
1939
  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
1914
1946
  meta_attr_tags = _merge_meta_tags(
1915
1947
  None,
1916
1948
  meta_model=meta_model,
@@ -35,7 +35,6 @@ from ap_client.managed_ak import (
35
35
  validate_ak_id,
36
36
  validate_ak_selection,
37
37
  )
38
- from ap_client.ossutil_commands import register as _register_ossutil_commands
39
38
  from ap_client.profile_commands import profile_app
40
39
  from ap_client.waiter import (
41
40
  WaitTimeoutError,
@@ -168,7 +167,6 @@ app.add_typer(checkpoint_app, name="checkpoint")
168
167
  # ap dataset version/split/access 嵌套在 dataset 下;instance/fs 是一等资源。
169
168
  _register_dataset_commands(dataset_app)
170
169
  _register_instance_commands(app)
171
- _register_ossutil_commands(app)
172
170
  _register_fs_commands(app)
173
171
  _register_akpool_commands(app)
174
172
 
@@ -644,7 +642,18 @@ def _print_formatted(data: dict, output_format: str) -> None:
644
642
  import yaml
645
643
  except ImportError as exc:
646
644
  raise typer.BadParameter("--format yaml requires PyYAML to be installed") from exc
647
- typer.echo(yaml.safe_dump(data, allow_unicode=True, sort_keys=False))
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))
648
657
  return
649
658
  _print_json(data)
650
659
 
@@ -3221,12 +3230,12 @@ def job_create(
3221
3230
  priority: Optional[str] = typer.Option(
3222
3231
  None,
3223
3232
  "--priority",
3224
- help="Scheduling priority tier: high or medium (default: medium)",
3233
+ help="Scheduling tier: high or medium. Omit both priority flags to inherit Group defaults; otherwise an omitted tier is medium",
3225
3234
  ),
3226
3235
  priority_weight: Optional[int] = typer.Option(
3227
3236
  None,
3228
3237
  "--priority-weight",
3229
- help="Fine-grained priority weight within tier, 0-10 (default: 0)",
3238
+ help="Priority weight, 0-10. Omit both priority flags to inherit Group defaults; otherwise an omitted weight is 0",
3230
3239
  ),
3231
3240
  resource_mode: Optional[str] = typer.Option(
3232
3241
  None,
@@ -5459,6 +5468,18 @@ def group_create(
5459
5468
  min=1,
5460
5469
  help="Maximum concurrent jobs. Server default: 50.",
5461
5470
  ),
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
+ ),
5462
5483
  eval_config: Optional[str] = typer.Option(
5463
5484
  None, "--eval-config", help="Evaluation config (JSON)"
5464
5485
  ),
@@ -5571,6 +5592,8 @@ def group_create(
5571
5592
  ):
5572
5593
  """Create a Group."""
5573
5594
  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")
5574
5597
  try:
5575
5598
  for reference in ak_id or []:
5576
5599
  validate_ak_id(reference)
@@ -5652,6 +5675,8 @@ def group_create(
5652
5675
  checkpoint=checkpoint_dict,
5653
5676
  benchmark=benchmark,
5654
5677
  experiment=experiment,
5678
+ **({"priority": priority} if priority is not None else {}),
5679
+ **({"priority_weight": priority_weight} if priority_weight is not None else {}),
5655
5680
  )
5656
5681
  except ManagedAKProtocolError as exc:
5657
5682
  _emit_error(str(exc))
@@ -5664,6 +5689,10 @@ def group_create(
5664
5689
  print(f" ak_ids: {response_ak_ids(result)}")
5665
5690
  if result.get("queue_id") is not None:
5666
5691
  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')}")
5667
5696
  if result.get("template") is not None:
5668
5697
  print(f" template: {result.get('template')}")
5669
5698
  if result.get("agenthub_revision") is not None:
@@ -6090,14 +6119,40 @@ def group_update(
6090
6119
  "--meta-train-stage",
6091
6120
  help="Set meta_train_stage tag (options: ap meta-train-stage list)",
6092
6121
  ),
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
+ ),
6093
6139
  output_format: str = typer.Option(
6094
6140
  None,
6095
6141
  "--format",
6096
6142
  help="Output format: plain/table/json/yaml (default: AP_FORMAT or command default)",
6097
6143
  ),
6098
6144
  ):
6099
- """Update Group properties."""
6145
+ """Update Group properties and scheduling defaults inherited by Jobs."""
6100
6146
  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
+ )
6101
6156
  eval_config_dict = _parse_json_object(eval_config, "--eval-config")
6102
6157
  model_base_url_collection_list = _parse_model_base_url_collection_option(
6103
6158
  model_base_url_collection, model_base_url_file
@@ -6134,6 +6189,8 @@ def group_update(
6134
6189
  scaffold,
6135
6190
  benchmark,
6136
6191
  tags_list,
6192
+ priority,
6193
+ priority_weight,
6137
6194
  )
6138
6195
  ):
6139
6196
  raise typer.BadParameter("At least one field must be provided to update")
@@ -6149,6 +6206,13 @@ def group_update(
6149
6206
  scaffold=scaffold,
6150
6207
  **({"benchmark": benchmark} if benchmark is not None else {}),
6151
6208
  **({"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
+ ),
6152
6216
  )
6153
6217
  if output_format == "plain":
6154
6218
  _print_group_action_plain(
@@ -6163,6 +6227,8 @@ def group_update(
6163
6227
  "model",
6164
6228
  "scaffold",
6165
6229
  "benchmark",
6230
+ "priority",
6231
+ "priority_weight",
6166
6232
  "updated_at",
6167
6233
  ],
6168
6234
  )