simulo 0.30.0__tar.gz → 0.31.1__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 (61) hide show
  1. {simulo-0.30.0/src/simulo.egg-info → simulo-0.31.1}/PKG-INFO +8 -5
  2. {simulo-0.30.0 → simulo-0.31.1}/PYPI.md +7 -4
  3. {simulo-0.30.0 → simulo-0.31.1}/pyproject.toml +1 -1
  4. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/cli.py +39 -17
  5. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/templates/__init__.py +3 -2
  6. simulo-0.31.1/src/simulo/_client/templates/training/preview.py.tmpl +10 -0
  7. {simulo-0.30.0 → simulo-0.31.1/src/simulo.egg-info}/PKG-INFO +8 -5
  8. {simulo-0.30.0 → simulo-0.31.1}/src/simulo.egg-info/SOURCES.txt +1 -0
  9. {simulo-0.30.0 → simulo-0.31.1}/MANIFEST.in +0 -0
  10. {simulo-0.30.0 → simulo-0.31.1}/setup.cfg +0 -0
  11. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/__init__.py +0 -0
  12. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/__init__.py +0 -0
  13. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/_arguments.py +0 -0
  14. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/_mounts.py +0 -0
  15. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/_runner.py +0 -0
  16. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/_secure_downloads.py +0 -0
  17. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/app.py +0 -0
  18. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/asset.py +0 -0
  19. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/asset_api.py +0 -0
  20. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/asset_package.py +0 -0
  21. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/asset_pins.py +0 -0
  22. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/builtin_aliases.py +0 -0
  23. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/bundle.py +0 -0
  24. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/cancel_api.py +0 -0
  25. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/config.py +0 -0
  26. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/credentials.py +0 -0
  27. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/discovery.py +0 -0
  28. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/export_api.py +0 -0
  29. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/facades.py +0 -0
  30. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/http.py +0 -0
  31. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/identity_api.py +0 -0
  32. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/install_samples.py +0 -0
  33. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/jobs_api.py +0 -0
  34. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/learning.py +0 -0
  35. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/login.py +0 -0
  36. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/mode.py +0 -0
  37. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/onnx_bundle.py +0 -0
  38. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/outputs.py +0 -0
  39. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/packaging.py +0 -0
  40. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/policies_api.py +0 -0
  41. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/preflight_api.py +0 -0
  42. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/preflight_render.py +0 -0
  43. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/preview_report.py +0 -0
  44. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/registry.py +0 -0
  45. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/runtime.py +0 -0
  46. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/runtime_display.py +0 -0
  47. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/stub.py +0 -0
  48. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/submit_api.py +0 -0
  49. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/templates/training/play.py.tmpl +0 -0
  50. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/templates/training/simuloignore.tmpl +0 -0
  51. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/templates/training/task.py.tmpl +0 -0
  52. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/templates/training/train.py.tmpl +0 -0
  53. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/view_fragment.py +0 -0
  54. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/view_session_api.py +0 -0
  55. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/_client/volume.py +0 -0
  56. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/callbacks.py +0 -0
  57. {simulo-0.30.0 → simulo-0.31.1}/src/simulo/py.typed +0 -0
  58. {simulo-0.30.0 → simulo-0.31.1}/src/simulo.egg-info/dependency_links.txt +0 -0
  59. {simulo-0.30.0 → simulo-0.31.1}/src/simulo.egg-info/entry_points.txt +0 -0
  60. {simulo-0.30.0 → simulo-0.31.1}/src/simulo.egg-info/requires.txt +0 -0
  61. {simulo-0.30.0 → simulo-0.31.1}/src/simulo.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simulo
3
- Version: 0.30.0
3
+ Version: 0.31.1
4
4
  Summary: Python SDK and CLI for cloud-native robotics simulation, reinforcement learning, and robot policy training on managed GPUs.
5
5
  Author-email: Simulo Team <team@simulo.ai>
6
6
  License: BSD-3-Clause
@@ -92,14 +92,17 @@ Simulo requires Python 3.11 or newer. One installation provides both the
92
92
  simulo create mybot
93
93
  simulo login
94
94
  cd mybot
95
+ simulo run preview.py --frozen --strict-assets
95
96
  simulo run train.py --frozen --strict-assets
97
+ simulo run play.py --policy policy_<job>:best --frozen --strict-assets
96
98
  ```
97
99
 
98
100
  `simulo create` writes a complete starter application to your machine without
99
- requiring a login or network connection. It creates `task.py`, `train.py`, and
100
- `.simuloignore`; the default application trains a PPO policy on a validated cartpole
101
- asset. `simulo run` packages the source, resolves
102
- and pins its assets, submits the job, and follows its cloud logs.
101
+ requiring a login or network connection. It creates `task.py`, `preview.py`,
102
+ `train.py`, `play.py`, and `.simuloignore`. Run `preview.py` first as a separate
103
+ job to check the validated cartpole asset in its task, run `train.py` to train a
104
+ PPO policy, then pass that policy to `play.py`. `simulo run` packages the source,
105
+ resolves and pins its assets, submits the job, and follows its cloud logs.
103
106
 
104
107
  ## Explore robotics samples
105
108
 
@@ -36,14 +36,17 @@ Simulo requires Python 3.11 or newer. One installation provides both the
36
36
  simulo create mybot
37
37
  simulo login
38
38
  cd mybot
39
+ simulo run preview.py --frozen --strict-assets
39
40
  simulo run train.py --frozen --strict-assets
41
+ simulo run play.py --policy policy_<job>:best --frozen --strict-assets
40
42
  ```
41
43
 
42
44
  `simulo create` writes a complete starter application to your machine without
43
- requiring a login or network connection. It creates `task.py`, `train.py`, and
44
- `.simuloignore`; the default application trains a PPO policy on a validated cartpole
45
- asset. `simulo run` packages the source, resolves
46
- and pins its assets, submits the job, and follows its cloud logs.
45
+ requiring a login or network connection. It creates `task.py`, `preview.py`,
46
+ `train.py`, `play.py`, and `.simuloignore`. Run `preview.py` first as a separate
47
+ job to check the validated cartpole asset in its task, run `train.py` to train a
48
+ PPO policy, then pass that policy to `play.py`. `simulo run` packages the source,
49
+ resolves and pins its assets, submits the job, and follows its cloud logs.
47
50
 
48
51
  ## Explore robotics samples
49
52
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "simulo"
7
- version = "0.30.0"
7
+ version = "0.31.1"
8
8
  description = "Python SDK and CLI for cloud-native robotics simulation, reinforcement learning, and robot policy training on managed GPUs."
9
9
  readme = "PYPI.md"
10
10
  requires-python = ">=3.11"
@@ -27,7 +27,8 @@ default stays out of submitted ``args`` and preserves the no-flags
27
27
  ``package_id``.
28
28
 
29
29
  ``simulo create <name> [--dir PATH] [--force]`` scaffolds a training app folder
30
- (``<name>/task.py``, ``<name>/train.py``, and ``<name>/.simuloignore``) from a
30
+ (``<name>/task.py``, ``<name>/preview.py``, ``<name>/train.py``,
31
+ ``<name>/play.py``, and ``<name>/.simuloignore``) from a
31
32
  starter template bundled INSIDE this wheel as package data (loaded via
32
33
  ``importlib.resources``, not a path relative to this repo). This is the ONLY
33
34
  delivery vehicle for a starter app: the repo's ``demos/`` directory sits outside
@@ -672,6 +673,14 @@ def _resolve_client_context() -> tuple[str, Optional[str]]:
672
673
  return base_url, token
673
674
 
674
675
 
676
+ def _client_with_fresh_token(client: JobsApiClient) -> JobsApiClient:
677
+ """Return a client with current stored credentials, preserving its target."""
678
+ creds = credentials.try_get_valid_credentials(base_url=client.base_url)
679
+ if creds is None:
680
+ return client
681
+ return JobsApiClient(client.base_url, token=str(creds["access_token"]))
682
+
683
+
675
684
  def _is_uuid_text(value: Any) -> bool:
676
685
  try:
677
686
  UUID(str(value))
@@ -1469,10 +1478,16 @@ def _follow_and_report(handle: JobHandle, app_path: str) -> int:
1469
1478
  job_ref = str(getattr(handle, "public_id", None) or handle.job_id)
1470
1479
  exit_code = _drain_logs(client, job_ref, follow=True, scope=JOB_SCOPE_MINE)
1471
1480
  if handle.job_type is JobType.PREVIEW:
1481
+ client = _client_with_fresh_token(client)
1472
1482
  return _report_preview(client, job_ref, display_id, app_path, fallback_exit_code=exit_code)
1473
1483
  if exit_code == 0:
1474
1484
  if handle.job_type is JobType.TRAIN:
1475
- _print_training_next_steps(handle, app_path)
1485
+ client = _client_with_fresh_token(client)
1486
+ _print_training_next_steps(
1487
+ PoliciesApiClient(client.base_url, token=client._token),
1488
+ handle,
1489
+ app_path,
1490
+ )
1476
1491
  elif handle.job_type is JobType.PLAY:
1477
1492
  print(f"Next: simulo recordings {display_id}")
1478
1493
  return exit_code
@@ -1565,12 +1580,11 @@ def _checkpoint_iteration(handle: JobHandle, checkpoint_ref: str) -> Optional[in
1565
1580
  return None
1566
1581
 
1567
1582
 
1568
- def _print_training_next_steps(handle: JobHandle, app_path: str) -> None:
1583
+ def _print_training_next_steps(client: PoliciesApiClient, handle: JobHandle, app_path: str) -> None:
1569
1584
  """Print the sealed policy's checkpoints and the three canonical next steps."""
1570
- assert handle.base_url is not None
1571
1585
  policy_id = str(policy_id_for_job(_handle_display_id(handle)))
1572
1586
  try:
1573
- record = PoliciesApiClient(handle.base_url, token=handle.token).get_policy(policy_id)
1587
+ record = client.get_policy(policy_id)
1574
1588
  except http.HttpError:
1575
1589
  return
1576
1590
  rendered: list[str] = []
@@ -2385,6 +2399,7 @@ def _wait_for_job(client: JobsApiClient, job_id: str, *, scope: str = JOB_SCOPE_
2385
2399
  """Poll until ``job_id`` exists — lets a user arm the tail BEFORE the job is created."""
2386
2400
  waiting_announced = False
2387
2401
  while True:
2402
+ client = _client_with_fresh_token(client)
2388
2403
  try:
2389
2404
  return client.get_job(job_id, scope=scope)
2390
2405
  except JobsApiHTTPError as exc:
@@ -2413,6 +2428,7 @@ def _wait_for_latest_job(client: JobsApiClient) -> dict[str, Any]:
2413
2428
  """
2414
2429
  waiting_announced = False
2415
2430
  while True:
2431
+ client = _client_with_fresh_token(client)
2416
2432
  try:
2417
2433
  latest = client.get_latest_job()
2418
2434
  except JobsApiHTTPError as exc:
@@ -2607,6 +2623,8 @@ def _drain_logs(
2607
2623
  post-``simulo run`` default follow — one follow loop, one
2608
2624
  exit-code-mirrors-outcome rule.
2609
2625
  """
2626
+ if follow:
2627
+ client = _client_with_fresh_token(client)
2610
2628
  offset = 0
2611
2629
  if tail_lines is not None:
2612
2630
  try:
@@ -2632,6 +2650,8 @@ def _drain_logs(
2632
2650
  # Not honored (old server): the loop below simply continues the full
2633
2651
  # history from where the server's offset-0 answer left off.
2634
2652
  while True:
2653
+ if follow:
2654
+ client = _client_with_fresh_token(client)
2635
2655
  try:
2636
2656
  chunk, offset, status, _ = client.get_log_chunk(job_id, offset, scope=scope)
2637
2657
  except JobsApiHTTPError as exc:
@@ -2769,9 +2789,9 @@ def _cmd_result(args: argparse.Namespace) -> int:
2769
2789
  announced on stderr.
2770
2790
  A job whose run announced typed outputs gets a second
2771
2791
  stderr line, ``⚠ 1 anomaly (non_finite_reward)`` (:func:`_outputs_flag_summary`)
2772
- — the result JSON itself is untouched (``stats["anomaly_captures"]`` stays
2773
- byte-identical; a byte stream is an output, a JSON scalar is a metric,
2774
- surfaced together but never merged). Both lines print to
2792
+ while built-in training results omit anomaly-capture paths. Those paths
2793
+ are exposed through the recordings and outputs commands instead. Both
2794
+ lines print to
2775
2795
  stderr so stdout stays pure result JSON for pipelines. Best-effort: for
2776
2796
  an explicit JOB_ID this needs one extra ``get_job`` call, and a failure
2777
2797
  there (e.g. an older control plane) skips both lines rather than failing a
@@ -5074,11 +5094,9 @@ def _validate_app_name(name: str) -> None:
5074
5094
  )
5075
5095
 
5076
5096
 
5077
- #: The first ``simulo run`` a fresh scaffold user should type, printed as the
5078
- #: "Next steps" line by ``_cmd_create``.
5079
- #: Pinned end-to-end by ``test_create_next_step_command_actually_runs``, which
5080
- #: executes each printed command verbatim against a fresh scaffold.
5081
- _TEMPLATE_NEXT_RUN_COMMAND = "simulo run train.py"
5097
+ #: The ``simulo run`` commands a fresh scaffold user should type before policy
5098
+ #: playback, in order, printed as the "Next steps" lines by ``_cmd_create``.
5099
+ _TEMPLATE_NEXT_RUN_COMMANDS = ("simulo run preview.py", "simulo run train.py")
5082
5100
 
5083
5101
 
5084
5102
  def _cmd_create(args: argparse.Namespace) -> int:
@@ -5091,7 +5109,7 @@ def _cmd_create(args: argparse.Namespace) -> int:
5091
5109
  ``{{APP_NAME}}`` token. No network call, no auth.
5092
5110
 
5093
5111
  A pre-existing, non-empty target folder is refused unless ``--force`` (which
5094
- prints the two filenames it overwrote — a destructive action stays visible in
5112
+ prints the filenames it overwrote — a destructive action stays visible in
5095
5113
  the output); an existing EMPTY folder (or no folder at all) needs no
5096
5114
  ``--force``. Every filesystem failure writing the scaffold — including a bad
5097
5115
  ``--dir`` that names an existing FILE rather than a directory (``mkdir``
@@ -5153,7 +5171,8 @@ def _cmd_create(args: argparse.Namespace) -> int:
5153
5171
  print(f"{verb} app in {target_dir}/ ({written}).")
5154
5172
  print("Next steps:")
5155
5173
  print(f" cd {target_dir}")
5156
- print(f" {_TEMPLATE_NEXT_RUN_COMMAND}")
5174
+ for command in _TEMPLATE_NEXT_RUN_COMMANDS:
5175
+ print(f" {command}")
5157
5176
  print(" simulo run play.py --policy policy_<job>:best # after training")
5158
5177
  return 0
5159
5178
 
@@ -8145,10 +8164,13 @@ def _build_parser() -> argparse.ArgumentParser:
8145
8164
 
8146
8165
  create = sub.add_parser(
8147
8166
  "create",
8148
- description="Scaffold task.py, train.py, play.py, and .simuloignore without network access or authentication.",
8167
+ description=(
8168
+ "Scaffold task.py, preview.py, train.py, play.py, and .simuloignore "
8169
+ "without network access or authentication."
8170
+ ),
8149
8171
  help=(
8150
8172
  "Scaffold a new Simulo app folder from a starter template shipped inside this wheel "
8151
- "(writes task.py, train.py, play.py, and .simuloignore; no network, no auth)."
8173
+ "(writes task.py, preview.py, train.py, play.py, and .simuloignore; no network, no auth)."
8152
8174
  ),
8153
8175
  )
8154
8176
  create.add_argument(
@@ -2,8 +2,9 @@
2
2
 
3
3
  The repo's ``demos/`` tree lives outside the packaged ``src/`` layout and never
4
4
  reaches a real ``pip install simulo`` user — this package is the fix. The
5
- ``training/`` directory holds the three files created by ``simulo create``:
6
- ``task.py.tmpl``, ``train.py.tmpl``, and ``simuloignore.tmpl``.
5
+ ``training/`` directory holds the five files created by ``simulo create``:
6
+ ``task.py.tmpl``, ``preview.py.tmpl``, ``train.py.tmpl``, ``play.py.tmpl``,
7
+ and ``simuloignore.tmpl``.
7
8
 
8
9
  The ``.tmpl`` suffix is load-bearing, not cosmetic: these files contain
9
10
  ``import torch`` and other content that is not a valid, importable module on
@@ -0,0 +1,10 @@
1
+ """Check the robot inside the task before training; this preview makes no policy."""
2
+
3
+ import simulo
4
+
5
+ from task import StarterTask, app
6
+
7
+
8
+ @app.job(type="preview", system=simulo.SystemType.TIER_1, timeout=15 * 60)
9
+ def preview(num_envs: int = 16, checks: str = "all"):
10
+ return simulo.preview(StarterTask(), num_envs=num_envs, checks=checks, video=True)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simulo
3
- Version: 0.30.0
3
+ Version: 0.31.1
4
4
  Summary: Python SDK and CLI for cloud-native robotics simulation, reinforcement learning, and robot policy training on managed GPUs.
5
5
  Author-email: Simulo Team <team@simulo.ai>
6
6
  License: BSD-3-Clause
@@ -92,14 +92,17 @@ Simulo requires Python 3.11 or newer. One installation provides both the
92
92
  simulo create mybot
93
93
  simulo login
94
94
  cd mybot
95
+ simulo run preview.py --frozen --strict-assets
95
96
  simulo run train.py --frozen --strict-assets
97
+ simulo run play.py --policy policy_<job>:best --frozen --strict-assets
96
98
  ```
97
99
 
98
100
  `simulo create` writes a complete starter application to your machine without
99
- requiring a login or network connection. It creates `task.py`, `train.py`, and
100
- `.simuloignore`; the default application trains a PPO policy on a validated cartpole
101
- asset. `simulo run` packages the source, resolves
102
- and pins its assets, submits the job, and follows its cloud logs.
101
+ requiring a login or network connection. It creates `task.py`, `preview.py`,
102
+ `train.py`, `play.py`, and `.simuloignore`. Run `preview.py` first as a separate
103
+ job to check the validated cartpole asset in its task, run `train.py` to train a
104
+ PPO policy, then pass that policy to `play.py`. `simulo run` packages the source,
105
+ resolves and pins its assets, submits the job, and follows its cloud logs.
103
106
 
104
107
  ## Explore robotics samples
105
108
 
@@ -53,6 +53,7 @@ src/simulo/_client/view_session_api.py
53
53
  src/simulo/_client/volume.py
54
54
  src/simulo/_client/templates/__init__.py
55
55
  src/simulo/_client/templates/training/play.py.tmpl
56
+ src/simulo/_client/templates/training/preview.py.tmpl
56
57
  src/simulo/_client/templates/training/simuloignore.tmpl
57
58
  src/simulo/_client/templates/training/task.py.tmpl
58
59
  src/simulo/_client/templates/training/train.py.tmpl
File without changes
File without changes
File without changes
File without changes
File without changes