so101-nexus 0.4.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.
- so101_nexus-0.4.0/.github/dependabot.yml +43 -0
- so101_nexus-0.4.0/.github/scripts/protect_main_branch.sh +126 -0
- so101_nexus-0.4.0/.github/scripts/pypi_smoke_check.py +70 -0
- so101_nexus-0.4.0/.github/workflows/ci.yml +148 -0
- so101_nexus-0.4.0/.github/workflows/dependency-review.yml +32 -0
- so101_nexus-0.4.0/.github/workflows/deploy-docs.yml +71 -0
- so101_nexus-0.4.0/.github/workflows/publish.yml +68 -0
- so101_nexus-0.4.0/.github/workflows/release-smoke.yml +95 -0
- so101_nexus-0.4.0/.gitignore +240 -0
- so101_nexus-0.4.0/.python-version +1 -0
- so101_nexus-0.4.0/.vscode/settings.json +4 -0
- so101_nexus-0.4.0/LICENSE.md +201 -0
- so101_nexus-0.4.0/Makefile +35 -0
- so101_nexus-0.4.0/PKG-INFO +45 -0
- so101_nexus-0.4.0/README.md +130 -0
- so101_nexus-0.4.0/assets/so101.png +0 -0
- so101_nexus-0.4.0/docs/.gitignore +4 -0
- so101_nexus-0.4.0/docs/app/api/search/route.ts +5 -0
- so101_nexus-0.4.0/docs/app/docs/[[...slug]]/page.tsx +33 -0
- so101_nexus-0.4.0/docs/app/docs/layout.tsx +15 -0
- so101_nexus-0.4.0/docs/app/global.css +3 -0
- so101_nexus-0.4.0/docs/app/layout.tsx +27 -0
- so101_nexus-0.4.0/docs/app/page.tsx +5 -0
- so101_nexus-0.4.0/docs/content/docs/api/assets-and-geometry.mdx +152 -0
- so101_nexus-0.4.0/docs/content/docs/api/configs.mdx +405 -0
- so101_nexus-0.4.0/docs/content/docs/api/core-overview.mdx +125 -0
- so101_nexus-0.4.0/docs/content/docs/api/environment-registry.mdx +86 -0
- so101_nexus-0.4.0/docs/content/docs/api/lerobot-processors.mdx +168 -0
- so101_nexus-0.4.0/docs/content/docs/api/meta.json +11 -0
- so101_nexus-0.4.0/docs/content/docs/api/objects.mdx +127 -0
- so101_nexus-0.4.0/docs/content/docs/concepts/backend-support.mdx +30 -0
- so101_nexus-0.4.0/docs/content/docs/concepts/lerobot-compatibility.mdx +135 -0
- so101_nexus-0.4.0/docs/content/docs/concepts/meta.json +10 -0
- so101_nexus-0.4.0/docs/content/docs/concepts/observations-and-camera-modes.mdx +161 -0
- so101_nexus-0.4.0/docs/content/docs/concepts/poses.mdx +72 -0
- so101_nexus-0.4.0/docs/content/docs/concepts/tasks-and-success-conditions.mdx +38 -0
- so101_nexus-0.4.0/docs/content/docs/environments/index.mdx +29 -0
- so101_nexus-0.4.0/docs/content/docs/environments/meta.json +12 -0
- so101_nexus-0.4.0/docs/content/docs/environments/mujoco-look-at.mdx +68 -0
- so101_nexus-0.4.0/docs/content/docs/environments/mujoco-move.mdx +68 -0
- so101_nexus-0.4.0/docs/content/docs/environments/mujoco-pick-and-place.mdx +75 -0
- so101_nexus-0.4.0/docs/content/docs/environments/mujoco-pick-lift.mdx +89 -0
- so101_nexus-0.4.0/docs/content/docs/environments/mujoco-reach.mdx +68 -0
- so101_nexus-0.4.0/docs/content/docs/getting-started/environment-ids.mdx +51 -0
- so101_nexus-0.4.0/docs/content/docs/getting-started/installation.mdx +43 -0
- so101_nexus-0.4.0/docs/content/docs/getting-started/meta.json +9 -0
- so101_nexus-0.4.0/docs/content/docs/getting-started/overview.mdx +42 -0
- so101_nexus-0.4.0/docs/content/docs/getting-started/quickstart-mujoco.mdx +70 -0
- so101_nexus-0.4.0/docs/content/docs/guides/customizing-environments.mdx +173 -0
- so101_nexus-0.4.0/docs/content/docs/guides/meta.json +9 -0
- so101_nexus-0.4.0/docs/content/docs/guides/teleop-dataset-recording.mdx +11 -0
- so101_nexus-0.4.0/docs/content/docs/guides/training-with-ppo.mdx +80 -0
- so101_nexus-0.4.0/docs/content/docs/guides/working-with-objects.mdx +114 -0
- so101_nexus-0.4.0/docs/content/docs/guides/ycb-assets.mdx +116 -0
- so101_nexus-0.4.0/docs/content/docs/index.mdx +92 -0
- so101_nexus-0.4.0/docs/content/docs/meta.json +17 -0
- so101_nexus-0.4.0/docs/content/docs/policies/meta.json +6 -0
- so101_nexus-0.4.0/docs/content/docs/policies/molmoact.mdx +75 -0
- so101_nexus-0.4.0/docs/content/docs/teleoperation/meta.json +7 -0
- so101_nexus-0.4.0/docs/content/docs/teleoperation/overview.mdx +296 -0
- so101_nexus-0.4.0/docs/content/docs/teleoperation/troubleshooting.mdx +62 -0
- so101_nexus-0.4.0/docs/lib/source.ts +7 -0
- so101_nexus-0.4.0/docs/next-env.d.ts +6 -0
- so101_nexus-0.4.0/docs/next.config.mjs +17 -0
- so101_nexus-0.4.0/docs/pnpm-lock.yaml +4098 -0
- so101_nexus-0.4.0/docs/postcss.config.mjs +7 -0
- so101_nexus-0.4.0/docs/source.config.ts +5 -0
- so101_nexus-0.4.0/docs/tsconfig.json +42 -0
- so101_nexus-0.4.0/examples/README.md +110 -0
- so101_nexus-0.4.0/examples/__init__.py +1 -0
- so101_nexus-0.4.0/examples/list_envs.py +6 -0
- so101_nexus-0.4.0/examples/ppo.py +495 -0
- so101_nexus-0.4.0/examples/ppo_warp.py +251 -0
- so101_nexus-0.4.0/pyproject.toml +195 -0
- so101_nexus-0.4.0/pyrightconfig.json +7 -0
- so101_nexus-0.4.0/scripts/smoke_molmoact_rollout.py +79 -0
- so101_nexus-0.4.0/src/so101_nexus/__init__.py +156 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/README.md +35 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/base_motor_holder_so101_v1.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/base_motor_holder_so101_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/base_so101_v2.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/base_so101_v2.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/motor_holder_so101_base_v1.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/motor_holder_so101_base_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/motor_holder_so101_wrist_v1.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/motor_holder_so101_wrist_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/moving_jaw_so101_v1.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/moving_jaw_so101_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/rotation_pitch_so101_v1.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/rotation_pitch_so101_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/sts3215_03a_no_horn_v1.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/sts3215_03a_no_horn_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/sts3215_03a_v1.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/sts3215_03a_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/under_arm_so101_v1.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/under_arm_so101_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/upper_arm_so101_v1.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/upper_arm_so101_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/waveshare_mounting_plate_so101_v2.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/waveshare_mounting_plate_so101_v2.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/wrist_roll_follower_so101_v1.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/wrist_roll_follower_so101_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/wrist_roll_pitch_so101_v2.part +14 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/assets/wrist_roll_pitch_so101_v2.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/joints_properties.xml +12 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/scene.xml +24 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/so101_new_calib.urdf +453 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/so101_new_calib.xml +179 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/so101_old_calib.urdf +435 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101/so101_old_calib.xml +160 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/CHANGELOG.md +7 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/LICENSE +201 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/PROVENANCE.md +27 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/README.md +32 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/base_motor_holder_so101_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/base_so101_v2.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/motor_holder_so101_base_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/motor_holder_so101_wrist_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/moving_jaw_so101_gripper_part0_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/moving_jaw_so101_gripper_part1_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/moving_jaw_so101_gripper_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/moving_jaw_so101_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/rotation_pitch_so101_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/sts3215_03a_no_horn_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/sts3215_03a_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/under_arm_so101_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/upper_arm_so101_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/waveshare_mounting_plate_so101_v2.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/wrist_roll_follower_so101_camera_mount.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/wrist_roll_follower_so101_gripper_part0_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/wrist_roll_follower_so101_gripper_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/wrist_roll_follower_so101_v1.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/assets/wrist_roll_pitch_so101_v2.stl +0 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/scene.xml +23 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/scene_box.xml +35 -0
- so101_nexus-0.4.0/src/so101_nexus/assets/SO101_menagerie/so101.xml +269 -0
- so101_nexus-0.4.0/src/so101_nexus/camera_utils.py +182 -0
- so101_nexus-0.4.0/src/so101_nexus/cli.py +34 -0
- so101_nexus-0.4.0/src/so101_nexus/config.py +900 -0
- so101_nexus-0.4.0/src/so101_nexus/constants.py +85 -0
- so101_nexus-0.4.0/src/so101_nexus/env_ids.py +44 -0
- so101_nexus-0.4.0/src/so101_nexus/lerobot_adapter/__init__.py +15 -0
- so101_nexus-0.4.0/src/so101_nexus/lerobot_adapter/normalization.py +229 -0
- so101_nexus-0.4.0/src/so101_nexus/lerobot_adapter/sim_camera.py +111 -0
- so101_nexus-0.4.0/src/so101_nexus/lerobot_adapter/sim_camera_config.py +15 -0
- so101_nexus-0.4.0/src/so101_nexus/lerobot_adapter/sim_follower.py +296 -0
- so101_nexus-0.4.0/src/so101_nexus/lerobot_adapter/sim_follower_config.py +25 -0
- so101_nexus-0.4.0/src/so101_nexus/lerobot_adapter/synthetic_calibration.py +85 -0
- so101_nexus-0.4.0/src/so101_nexus/mujoco/__init__.py +40 -0
- so101_nexus-0.4.0/src/so101_nexus/mujoco/base_env.py +667 -0
- so101_nexus-0.4.0/src/so101_nexus/mujoco/look_at_env.py +193 -0
- so101_nexus-0.4.0/src/so101_nexus/mujoco/move_env.py +156 -0
- so101_nexus-0.4.0/src/so101_nexus/mujoco/pick_and_place.py +272 -0
- so101_nexus-0.4.0/src/so101_nexus/mujoco/pick_env.py +457 -0
- so101_nexus-0.4.0/src/so101_nexus/mujoco/reach_env.py +118 -0
- so101_nexus-0.4.0/src/so101_nexus/mujoco/spawn_utils.py +136 -0
- so101_nexus-0.4.0/src/so101_nexus/objects.py +130 -0
- so101_nexus-0.4.0/src/so101_nexus/observations.py +266 -0
- so101_nexus-0.4.0/src/so101_nexus/policy_adapters/__init__.py +9 -0
- so101_nexus-0.4.0/src/so101_nexus/policy_adapters/chunked_policy.py +15 -0
- so101_nexus-0.4.0/src/so101_nexus/policy_adapters/molmoact.py +187 -0
- so101_nexus-0.4.0/src/so101_nexus/policy_adapters/recorder.py +190 -0
- so101_nexus-0.4.0/src/so101_nexus/processors/__init__.py +33 -0
- so101_nexus-0.4.0/src/so101_nexus/processors/action.py +125 -0
- so101_nexus-0.4.0/src/so101_nexus/processors/lerobot_env_wrapper.py +127 -0
- so101_nexus-0.4.0/src/so101_nexus/processors/observation.py +67 -0
- so101_nexus-0.4.0/src/so101_nexus/processors/pipelines.py +150 -0
- so101_nexus-0.4.0/src/so101_nexus/rewards.py +100 -0
- so101_nexus-0.4.0/src/so101_nexus/scene.py +110 -0
- so101_nexus-0.4.0/src/so101_nexus/teleop/__init__.py +29 -0
- so101_nexus-0.4.0/src/so101_nexus/teleop/__main__.py +8 -0
- so101_nexus-0.4.0/src/so101_nexus/teleop/app.py +1628 -0
- so101_nexus-0.4.0/src/so101_nexus/teleop/cli.py +51 -0
- so101_nexus-0.4.0/src/so101_nexus/teleop/config_customization.py +407 -0
- so101_nexus-0.4.0/src/so101_nexus/teleop/dataset.py +125 -0
- so101_nexus-0.4.0/src/so101_nexus/teleop/leader.py +151 -0
- so101_nexus-0.4.0/src/so101_nexus/teleop/recorder.py +327 -0
- so101_nexus-0.4.0/src/so101_nexus/teleop/session.py +370 -0
- so101_nexus-0.4.0/src/so101_nexus/testing/__init__.py +12 -0
- so101_nexus-0.4.0/src/so101_nexus/testing/cli_contract.py +55 -0
- so101_nexus-0.4.0/src/so101_nexus/testing/contract.py +114 -0
- so101_nexus-0.4.0/src/so101_nexus/testing/env_id_filter.py +32 -0
- so101_nexus-0.4.0/src/so101_nexus/testing/invariants.py +107 -0
- so101_nexus-0.4.0/src/so101_nexus/visualization.py +168 -0
- so101_nexus-0.4.0/src/so101_nexus/warp/__init__.py +41 -0
- so101_nexus-0.4.0/src/so101_nexus/warp/base_env.py +587 -0
- so101_nexus-0.4.0/src/so101_nexus/warp/look_at_env.py +133 -0
- so101_nexus-0.4.0/src/so101_nexus/warp/move_env.py +129 -0
- so101_nexus-0.4.0/src/so101_nexus/warp/pick_and_place.py +269 -0
- so101_nexus-0.4.0/src/so101_nexus/warp/pick_env.py +209 -0
- so101_nexus-0.4.0/src/so101_nexus/warp/reach_env.py +122 -0
- so101_nexus-0.4.0/src/so101_nexus/ycb_assets.py +203 -0
- so101_nexus-0.4.0/src/so101_nexus/ycb_geometry.py +39 -0
- so101_nexus-0.4.0/tests/conftest.py +5 -0
- so101_nexus-0.4.0/tests/core/test_assets.py +15 -0
- so101_nexus-0.4.0/tests/core/test_camera_utils.py +106 -0
- so101_nexus-0.4.0/tests/core/test_camera_utils_properties.py +77 -0
- so101_nexus-0.4.0/tests/core/test_config.py +711 -0
- so101_nexus-0.4.0/tests/core/test_contract.py +20 -0
- so101_nexus-0.4.0/tests/core/test_env_ids.py +79 -0
- so101_nexus-0.4.0/tests/core/test_lerobot_adapter_camera.py +85 -0
- so101_nexus-0.4.0/tests/core/test_lerobot_adapter_follower.py +363 -0
- so101_nexus-0.4.0/tests/core/test_lerobot_adapter_mujoco.py +96 -0
- so101_nexus-0.4.0/tests/core/test_lerobot_adapter_normalization.py +240 -0
- so101_nexus-0.4.0/tests/core/test_lerobot_adapter_record_loop.py +224 -0
- so101_nexus-0.4.0/tests/core/test_lerobot_adapter_registration.py +41 -0
- so101_nexus-0.4.0/tests/core/test_lerobot_adapter_synthetic_calibration.py +86 -0
- so101_nexus-0.4.0/tests/core/test_lerobot_env_wrapper.py +147 -0
- so101_nexus-0.4.0/tests/core/test_molmoact_policy.py +191 -0
- so101_nexus-0.4.0/tests/core/test_objects.py +91 -0
- so101_nexus-0.4.0/tests/core/test_observations.py +139 -0
- so101_nexus-0.4.0/tests/core/test_processors_action.py +100 -0
- so101_nexus-0.4.0/tests/core/test_processors_observation.py +62 -0
- so101_nexus-0.4.0/tests/core/test_processors_pipelines.py +190 -0
- so101_nexus-0.4.0/tests/core/test_rewards.py +59 -0
- so101_nexus-0.4.0/tests/core/test_rewards_properties.py +72 -0
- so101_nexus-0.4.0/tests/core/test_rewards_tensor.py +77 -0
- so101_nexus-0.4.0/tests/core/test_rollout_recorder.py +157 -0
- so101_nexus-0.4.0/tests/core/test_rollout_recorder_dataset.py +116 -0
- so101_nexus-0.4.0/tests/core/test_scene.py +68 -0
- so101_nexus-0.4.0/tests/core/test_source_guardrails.py +195 -0
- so101_nexus-0.4.0/tests/core/test_teleop_app_helpers.py +1231 -0
- so101_nexus-0.4.0/tests/core/test_teleop_cli.py +83 -0
- so101_nexus-0.4.0/tests/core/test_teleop_config_customization.py +356 -0
- so101_nexus-0.4.0/tests/core/test_teleop_dataset.py +232 -0
- so101_nexus-0.4.0/tests/core/test_teleop_dataset_compat.py +125 -0
- so101_nexus-0.4.0/tests/core/test_teleop_leader.py +195 -0
- so101_nexus-0.4.0/tests/core/test_teleop_recorder.py +316 -0
- so101_nexus-0.4.0/tests/core/test_teleop_session.py +394 -0
- so101_nexus-0.4.0/tests/core/test_teleop_ui.py +73 -0
- so101_nexus-0.4.0/tests/core/test_visualization.py +165 -0
- so101_nexus-0.4.0/tests/core/test_warp_registration.py +25 -0
- so101_nexus-0.4.0/tests/core/test_ycb.py +443 -0
- so101_nexus-0.4.0/tests/core/test_ycb_geometry_properties.py +83 -0
- so101_nexus-0.4.0/tests/mujoco/__init__.py +0 -0
- so101_nexus-0.4.0/tests/mujoco/test_base_env_init_qpos.py +243 -0
- so101_nexus-0.4.0/tests/mujoco/test_cli.py +86 -0
- so101_nexus-0.4.0/tests/mujoco/test_env_ids_filter.py +19 -0
- so101_nexus-0.4.0/tests/mujoco/test_env_invariants.py +54 -0
- so101_nexus-0.4.0/tests/mujoco/test_envs.py +1112 -0
- so101_nexus-0.4.0/tests/mujoco/test_menagerie_model.py +227 -0
- so101_nexus-0.4.0/tests/mujoco/test_obs_mode_config.py +201 -0
- so101_nexus-0.4.0/tests/mujoco/test_pick_and_place_config.py +77 -0
- so101_nexus-0.4.0/tests/mujoco/test_reward_penalties.py +115 -0
- so101_nexus-0.4.0/tests/mujoco/test_spawn_utils.py +381 -0
- so101_nexus-0.4.0/tests/mujoco/test_teleop_env_kwargs.py +67 -0
- so101_nexus-0.4.0/tests/test_docs_consistency.py +76 -0
- so101_nexus-0.4.0/tests/test_release_smoke_workflow.py +42 -0
- so101_nexus-0.4.0/tests/visual/__init__.py +0 -0
- so101_nexus-0.4.0/tests/visual/conftest.py +152 -0
- so101_nexus-0.4.0/tests/visual/test_mujoco_visual.py +182 -0
- so101_nexus-0.4.0/tests/warp/conftest.py +14 -0
- so101_nexus-0.4.0/tests/warp/test_package.py +15 -0
- so101_nexus-0.4.0/tests/warp/test_ppo_warp_smoke.py +49 -0
- so101_nexus-0.4.0/tests/warp/test_warp_envs.py +314 -0
- so101_nexus-0.4.0/tests/warp/test_warp_helpers.py +80 -0
- so101_nexus-0.4.0/tests/warp/test_warp_make_vec.py +24 -0
- so101_nexus-0.4.0/tests/warp/test_warp_reach.py +221 -0
- so101_nexus-0.4.0/tests/warp/test_warp_reset_contract.py +98 -0
- so101_nexus-0.4.0/utils/visualize_env.py +150 -0
- so101_nexus-0.4.0/uv.lock +4277 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: github-actions
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
day: monday
|
|
8
|
+
time: "10:00"
|
|
9
|
+
timezone: America/New_York
|
|
10
|
+
groups:
|
|
11
|
+
github-actions:
|
|
12
|
+
patterns:
|
|
13
|
+
- "*"
|
|
14
|
+
commit-message:
|
|
15
|
+
prefix: chore
|
|
16
|
+
|
|
17
|
+
- package-ecosystem: uv
|
|
18
|
+
directory: /
|
|
19
|
+
schedule:
|
|
20
|
+
interval: weekly
|
|
21
|
+
day: monday
|
|
22
|
+
time: "10:30"
|
|
23
|
+
timezone: America/New_York
|
|
24
|
+
groups:
|
|
25
|
+
python-dependencies:
|
|
26
|
+
patterns:
|
|
27
|
+
- "*"
|
|
28
|
+
commit-message:
|
|
29
|
+
prefix: chore
|
|
30
|
+
|
|
31
|
+
- package-ecosystem: npm
|
|
32
|
+
directory: /docs
|
|
33
|
+
schedule:
|
|
34
|
+
interval: weekly
|
|
35
|
+
day: monday
|
|
36
|
+
time: "11:00"
|
|
37
|
+
timezone: America/New_York
|
|
38
|
+
groups:
|
|
39
|
+
docs-dependencies:
|
|
40
|
+
patterns:
|
|
41
|
+
- "*"
|
|
42
|
+
commit-message:
|
|
43
|
+
prefix: chore
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
api_version="${GITHUB_API_VERSION:-2026-03-10}"
|
|
5
|
+
token="${GITHUB_TOKEN:-${GH_TOKEN:-}}"
|
|
6
|
+
branch="${BRANCH:-main}"
|
|
7
|
+
|
|
8
|
+
remote_url="$(git config --get remote.origin.url)"
|
|
9
|
+
owner_repo="${remote_url#git@github.com:}"
|
|
10
|
+
owner_repo="${owner_repo#https://github.com/}"
|
|
11
|
+
owner_repo="${owner_repo%.git}"
|
|
12
|
+
|
|
13
|
+
owner="${GITHUB_OWNER:-${OWNER:-${owner_repo%%/*}}}"
|
|
14
|
+
repo="${GITHUB_REPO:-${REPO:-${owner_repo#*/}}}"
|
|
15
|
+
|
|
16
|
+
if [[ -z "$token" ]]; then
|
|
17
|
+
cat >&2 <<'EOF'
|
|
18
|
+
Set GITHUB_TOKEN or GH_TOKEN to a token with Administration: write for this repository.
|
|
19
|
+
For a fine-grained PAT, grant Repository administration: read and write.
|
|
20
|
+
EOF
|
|
21
|
+
exit 2
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
api() {
|
|
25
|
+
local method="$1"
|
|
26
|
+
local path="$2"
|
|
27
|
+
shift 2
|
|
28
|
+
|
|
29
|
+
curl -fsSL \
|
|
30
|
+
-X "$method" \
|
|
31
|
+
-H "Accept: application/vnd.github+json" \
|
|
32
|
+
-H "Authorization: Bearer ${token}" \
|
|
33
|
+
-H "X-GitHub-Api-Version: ${api_version}" \
|
|
34
|
+
"https://api.github.com${path}" \
|
|
35
|
+
"$@"
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
tmpdir="$(mktemp -d)"
|
|
39
|
+
trap 'rm -rf "$tmpdir"' EXIT
|
|
40
|
+
|
|
41
|
+
cat >"$tmpdir/actions-permissions.json" <<'JSON'
|
|
42
|
+
{
|
|
43
|
+
"enabled": true,
|
|
44
|
+
"allowed_actions": "selected",
|
|
45
|
+
"sha_pinning_required": true
|
|
46
|
+
}
|
|
47
|
+
JSON
|
|
48
|
+
|
|
49
|
+
cat >"$tmpdir/selected-actions.json" <<'JSON'
|
|
50
|
+
{
|
|
51
|
+
"github_owned_allowed": true,
|
|
52
|
+
"verified_allowed": false,
|
|
53
|
+
"patterns_allowed": [
|
|
54
|
+
"astral-sh/setup-uv@*",
|
|
55
|
+
"pnpm/action-setup@*",
|
|
56
|
+
"pypa/gh-action-pypi-publish@*"
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
JSON
|
|
60
|
+
|
|
61
|
+
cat >"$tmpdir/workflow-permissions.json" <<'JSON'
|
|
62
|
+
{
|
|
63
|
+
"default_workflow_permissions": "read",
|
|
64
|
+
"can_approve_pull_request_reviews": false
|
|
65
|
+
}
|
|
66
|
+
JSON
|
|
67
|
+
|
|
68
|
+
cat >"$tmpdir/fork-pr-approval.json" <<'JSON'
|
|
69
|
+
{
|
|
70
|
+
"approval_policy": "all_external_contributors"
|
|
71
|
+
}
|
|
72
|
+
JSON
|
|
73
|
+
|
|
74
|
+
cat >"$tmpdir/branch-protection.json" <<'JSON'
|
|
75
|
+
{
|
|
76
|
+
"required_status_checks": {
|
|
77
|
+
"strict": true,
|
|
78
|
+
"contexts": [
|
|
79
|
+
"lint",
|
|
80
|
+
"test",
|
|
81
|
+
"docs",
|
|
82
|
+
"dependency-review"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
"enforce_admins": true,
|
|
86
|
+
"required_pull_request_reviews": {
|
|
87
|
+
"dismiss_stale_reviews": true,
|
|
88
|
+
"require_code_owner_reviews": false,
|
|
89
|
+
"required_approving_review_count": 1,
|
|
90
|
+
"require_last_push_approval": true
|
|
91
|
+
},
|
|
92
|
+
"restrictions": null,
|
|
93
|
+
"required_linear_history": true,
|
|
94
|
+
"allow_force_pushes": false,
|
|
95
|
+
"allow_deletions": false,
|
|
96
|
+
"block_creations": false,
|
|
97
|
+
"required_conversation_resolution": true,
|
|
98
|
+
"lock_branch": false,
|
|
99
|
+
"allow_fork_syncing": true
|
|
100
|
+
}
|
|
101
|
+
JSON
|
|
102
|
+
|
|
103
|
+
echo "Applying repository Actions policy for ${owner}/${repo}"
|
|
104
|
+
api PUT "/repos/${owner}/${repo}/actions/permissions" \
|
|
105
|
+
-d @"$tmpdir/actions-permissions.json" >/dev/null
|
|
106
|
+
|
|
107
|
+
echo "Allowing only GitHub-owned actions and explicit third-party action repositories"
|
|
108
|
+
api PUT "/repos/${owner}/${repo}/actions/permissions/selected-actions" \
|
|
109
|
+
-d @"$tmpdir/selected-actions.json" >/dev/null
|
|
110
|
+
|
|
111
|
+
echo "Setting the default GITHUB_TOKEN permission to read-only"
|
|
112
|
+
api PUT "/repos/${owner}/${repo}/actions/permissions/workflow" \
|
|
113
|
+
-d @"$tmpdir/workflow-permissions.json" >/dev/null
|
|
114
|
+
|
|
115
|
+
echo "Requiring approval for all external fork pull request workflows"
|
|
116
|
+
api PUT "/repos/${owner}/${repo}/actions/permissions/fork-pr-contributor-approval" \
|
|
117
|
+
-d @"$tmpdir/fork-pr-approval.json" >/dev/null
|
|
118
|
+
|
|
119
|
+
echo "Applying branch protection to ${branch}"
|
|
120
|
+
api PUT "/repos/${owner}/${repo}/branches/${branch}/protection" \
|
|
121
|
+
-d @"$tmpdir/branch-protection.json" >/dev/null
|
|
122
|
+
|
|
123
|
+
echo "Requiring signed commits on ${branch}"
|
|
124
|
+
api POST "/repos/${owner}/${repo}/branches/${branch}/protection/required_signatures" >/dev/null
|
|
125
|
+
|
|
126
|
+
echo "Repository Actions policy and ${branch} branch protection are configured."
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Smoke-check the installed so101-nexus package from PyPI."""
|
|
3
|
+
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
import gymnasium as gym
|
|
8
|
+
import tyro
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def run_mujoco(env_id: str) -> None:
|
|
12
|
+
"""Reset and step a registered MuJoCo env to verify the install works."""
|
|
13
|
+
import so101_nexus.mujoco # noqa: F401
|
|
14
|
+
|
|
15
|
+
env = gym.make(env_id)
|
|
16
|
+
try:
|
|
17
|
+
obs, info = env.reset(seed=0)
|
|
18
|
+
action = env.action_space.sample()
|
|
19
|
+
step_result = env.step(action)
|
|
20
|
+
finally:
|
|
21
|
+
env.close()
|
|
22
|
+
|
|
23
|
+
if obs is None or info is None:
|
|
24
|
+
raise RuntimeError("MuJoCo smoke check failed: reset returned empty values.")
|
|
25
|
+
if len(step_result) != 5:
|
|
26
|
+
raise RuntimeError("MuJoCo smoke check failed: step did not return a 5-tuple.")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def run_warp(env_id: str, *, device: str, num_envs: int) -> None:
|
|
30
|
+
"""Reset and step a batched Warp vector env to verify the install works."""
|
|
31
|
+
import so101_nexus.warp # noqa: F401
|
|
32
|
+
|
|
33
|
+
env = gym.make_vec(
|
|
34
|
+
env_id, num_envs=num_envs, device=device, vectorization_mode="vector_entry_point"
|
|
35
|
+
)
|
|
36
|
+
try:
|
|
37
|
+
obs, info = env.reset(seed=0)
|
|
38
|
+
action = env.action_space.sample()
|
|
39
|
+
step_result = env.step(action)
|
|
40
|
+
finally:
|
|
41
|
+
env.close()
|
|
42
|
+
|
|
43
|
+
if obs is None or info is None:
|
|
44
|
+
raise RuntimeError("Warp smoke check failed: reset returned empty values.")
|
|
45
|
+
if len(step_result) != 5:
|
|
46
|
+
raise RuntimeError("Warp smoke check failed: step did not return a 5-tuple.")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class Args:
|
|
51
|
+
"""Command-line arguments for the PyPI smoke check."""
|
|
52
|
+
|
|
53
|
+
env_id: str
|
|
54
|
+
backend: Literal["mujoco", "warp"] = "mujoco"
|
|
55
|
+
device: str = "cpu"
|
|
56
|
+
num_envs: int = 2
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def main(args: Args) -> None:
|
|
60
|
+
"""Run the smoke check for the requested backend."""
|
|
61
|
+
print(f"Running smoke check for backend={args.backend}, env={args.env_id}")
|
|
62
|
+
if args.backend == "warp":
|
|
63
|
+
run_warp(args.env_id, device=args.device, num_envs=args.num_envs)
|
|
64
|
+
else:
|
|
65
|
+
run_mujoco(args.env_id)
|
|
66
|
+
print("Smoke check passed.")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
if __name__ == "__main__":
|
|
70
|
+
main(tyro.cli(Args))
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
env:
|
|
17
|
+
PYTHON_VERSION: "3.12"
|
|
18
|
+
UV_CACHE_DEPENDENCY_GLOB: uv.lock
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
lint:
|
|
22
|
+
name: lint
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
timeout-minutes: 20
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@9f698171ed81b15d1823a05fc7211befd50c8ae0 # v6.0.3
|
|
27
|
+
with:
|
|
28
|
+
persist-credentials: false
|
|
29
|
+
- name: Install uv
|
|
30
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
31
|
+
with:
|
|
32
|
+
enable-cache: true
|
|
33
|
+
cache-dependency-glob: ${{ env.UV_CACHE_DEPENDENCY_GLOB }}
|
|
34
|
+
cache-suffix: ci-lint
|
|
35
|
+
- name: Set up Python
|
|
36
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
37
|
+
with:
|
|
38
|
+
python-version: ${{ env.PYTHON_VERSION }}
|
|
39
|
+
- name: Install dev dependencies
|
|
40
|
+
run: uv sync --locked --group dev
|
|
41
|
+
- name: Lint
|
|
42
|
+
run: make lint
|
|
43
|
+
|
|
44
|
+
test:
|
|
45
|
+
name: test
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
timeout-minutes: 60
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@9f698171ed81b15d1823a05fc7211befd50c8ae0 # v6.0.3
|
|
50
|
+
with:
|
|
51
|
+
persist-credentials: false
|
|
52
|
+
|
|
53
|
+
- name: System deps
|
|
54
|
+
run: |
|
|
55
|
+
sudo apt-get update
|
|
56
|
+
sudo apt-get install -y xvfb ffmpeg libgl1 libglx-mesa0 libegl1-mesa-dev libosmesa6-dev
|
|
57
|
+
|
|
58
|
+
- name: Install uv
|
|
59
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
60
|
+
with:
|
|
61
|
+
enable-cache: true
|
|
62
|
+
cache-dependency-glob: ${{ env.UV_CACHE_DEPENDENCY_GLOB }}
|
|
63
|
+
cache-suffix: ci-test
|
|
64
|
+
|
|
65
|
+
- name: Set up Python
|
|
66
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
67
|
+
with:
|
|
68
|
+
python-version: ${{ env.PYTHON_VERSION }}
|
|
69
|
+
|
|
70
|
+
- name: Install dependencies
|
|
71
|
+
run: uv sync --locked --group test
|
|
72
|
+
|
|
73
|
+
- name: Run tests
|
|
74
|
+
run: xvfb-run -a make test
|
|
75
|
+
|
|
76
|
+
test-warp:
|
|
77
|
+
name: test-warp
|
|
78
|
+
runs-on: ubuntu-latest
|
|
79
|
+
timeout-minutes: 45
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/checkout@9f698171ed81b15d1823a05fc7211befd50c8ae0 # v6.0.3
|
|
82
|
+
with:
|
|
83
|
+
persist-credentials: false
|
|
84
|
+
|
|
85
|
+
- name: System deps
|
|
86
|
+
run: |
|
|
87
|
+
sudo apt-get update
|
|
88
|
+
sudo apt-get install -y libgl1 libglx-mesa0 libegl1-mesa-dev libosmesa6-dev
|
|
89
|
+
|
|
90
|
+
- name: Install uv
|
|
91
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
92
|
+
with:
|
|
93
|
+
enable-cache: true
|
|
94
|
+
cache-dependency-glob: ${{ env.UV_CACHE_DEPENDENCY_GLOB }}
|
|
95
|
+
cache-suffix: ci-test-warp
|
|
96
|
+
|
|
97
|
+
- name: Set up Python
|
|
98
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
99
|
+
with:
|
|
100
|
+
python-version: ${{ env.PYTHON_VERSION }}
|
|
101
|
+
|
|
102
|
+
- name: Install dependencies
|
|
103
|
+
run: uv sync --locked --extra warp
|
|
104
|
+
|
|
105
|
+
- name: Run Warp tests
|
|
106
|
+
env:
|
|
107
|
+
MUJOCO_GL: egl
|
|
108
|
+
run: make test-warp
|
|
109
|
+
|
|
110
|
+
docs:
|
|
111
|
+
name: docs
|
|
112
|
+
runs-on: ubuntu-latest
|
|
113
|
+
timeout-minutes: 25
|
|
114
|
+
steps:
|
|
115
|
+
- uses: actions/checkout@9f698171ed81b15d1823a05fc7211befd50c8ae0 # v6.0.3
|
|
116
|
+
with:
|
|
117
|
+
persist-credentials: false
|
|
118
|
+
- name: Install uv
|
|
119
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
120
|
+
with:
|
|
121
|
+
enable-cache: true
|
|
122
|
+
cache-dependency-glob: ${{ env.UV_CACHE_DEPENDENCY_GLOB }}
|
|
123
|
+
cache-suffix: ci-docs
|
|
124
|
+
- name: Set up Python
|
|
125
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
126
|
+
with:
|
|
127
|
+
python-version: ${{ env.PYTHON_VERSION }}
|
|
128
|
+
- name: Set up pnpm
|
|
129
|
+
uses: pnpm/action-setup@d15e628ca66d93ee5f352c71671a7bc6a97af5c9 # v6.0.8
|
|
130
|
+
with:
|
|
131
|
+
version: 9
|
|
132
|
+
- name: Set up Node
|
|
133
|
+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
134
|
+
with:
|
|
135
|
+
node-version: "22"
|
|
136
|
+
cache: pnpm
|
|
137
|
+
cache-dependency-path: docs/pnpm-lock.yaml
|
|
138
|
+
- name: Cache Next.js build output
|
|
139
|
+
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
|
140
|
+
with:
|
|
141
|
+
path: docs/.next/cache
|
|
142
|
+
key: ${{ runner.os }}-next-${{ hashFiles('docs/pnpm-lock.yaml') }}-${{ hashFiles('docs/app/**', 'docs/content/**', 'docs/lib/**', 'docs/*.mjs', 'docs/*.ts', 'docs/*.json') }}
|
|
143
|
+
restore-keys: |
|
|
144
|
+
${{ runner.os }}-next-${{ hashFiles('docs/pnpm-lock.yaml') }}-
|
|
145
|
+
- name: Install dev dependencies
|
|
146
|
+
run: uv sync --locked --group dev
|
|
147
|
+
- name: Run docs checks
|
|
148
|
+
run: make docs-check
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Dependency Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
dependency-review:
|
|
16
|
+
name: dependency-review
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
timeout-minutes: 10
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@9f698171ed81b15d1823a05fc7211befd50c8ae0 # v6.0.3
|
|
21
|
+
with:
|
|
22
|
+
persist-credentials: false
|
|
23
|
+
|
|
24
|
+
- name: Dependency Review
|
|
25
|
+
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
|
|
26
|
+
with:
|
|
27
|
+
fail-on-severity: moderate
|
|
28
|
+
fail-on-scopes: runtime,development
|
|
29
|
+
vulnerability-check: true
|
|
30
|
+
license-check: false
|
|
31
|
+
show-openssf-scorecard: true
|
|
32
|
+
warn-on-openssf-scorecard-level: 3
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
name: Deploy Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- "docs/**"
|
|
8
|
+
- ".github/workflows/deploy-docs.yml"
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: "pages"
|
|
16
|
+
cancel-in-progress: false
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
build:
|
|
20
|
+
name: build
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
timeout-minutes: 25
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@9f698171ed81b15d1823a05fc7211befd50c8ae0 # v6.0.3
|
|
25
|
+
with:
|
|
26
|
+
persist-credentials: false
|
|
27
|
+
|
|
28
|
+
- uses: pnpm/action-setup@d15e628ca66d93ee5f352c71671a7bc6a97af5c9 # v6.0.8
|
|
29
|
+
with:
|
|
30
|
+
version: 10
|
|
31
|
+
|
|
32
|
+
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
33
|
+
with:
|
|
34
|
+
node-version: 22
|
|
35
|
+
cache: pnpm
|
|
36
|
+
cache-dependency-path: docs/pnpm-lock.yaml
|
|
37
|
+
|
|
38
|
+
- name: Cache Next.js build output
|
|
39
|
+
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
|
40
|
+
with:
|
|
41
|
+
path: docs/.next/cache
|
|
42
|
+
key: ${{ runner.os }}-next-${{ hashFiles('docs/pnpm-lock.yaml') }}-${{ hashFiles('docs/app/**', 'docs/content/**', 'docs/lib/**', 'docs/*.mjs', 'docs/*.ts', 'docs/*.json') }}
|
|
43
|
+
restore-keys: |
|
|
44
|
+
${{ runner.os }}-next-${{ hashFiles('docs/pnpm-lock.yaml') }}-
|
|
45
|
+
|
|
46
|
+
- name: Install dependencies
|
|
47
|
+
working-directory: docs
|
|
48
|
+
run: pnpm install --frozen-lockfile
|
|
49
|
+
|
|
50
|
+
- name: Build
|
|
51
|
+
working-directory: docs
|
|
52
|
+
run: pnpm build
|
|
53
|
+
|
|
54
|
+
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
|
55
|
+
with:
|
|
56
|
+
path: docs/out
|
|
57
|
+
|
|
58
|
+
deploy:
|
|
59
|
+
name: deploy
|
|
60
|
+
environment:
|
|
61
|
+
name: github-pages
|
|
62
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
needs: build
|
|
65
|
+
timeout-minutes: 10
|
|
66
|
+
permissions:
|
|
67
|
+
pages: write
|
|
68
|
+
id-token: write
|
|
69
|
+
steps:
|
|
70
|
+
- id: deployment
|
|
71
|
+
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: publish-${{ github.event.release.tag_name }}
|
|
12
|
+
cancel-in-progress: false
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
name: build
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
timeout-minutes: 25
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@9f698171ed81b15d1823a05fc7211befd50c8ae0 # v6.0.3
|
|
22
|
+
with:
|
|
23
|
+
persist-credentials: false
|
|
24
|
+
|
|
25
|
+
- name: Install uv
|
|
26
|
+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
|
|
27
|
+
with:
|
|
28
|
+
enable-cache: false
|
|
29
|
+
|
|
30
|
+
- name: Set up Python
|
|
31
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
32
|
+
with:
|
|
33
|
+
python-version: "3.x"
|
|
34
|
+
|
|
35
|
+
- name: Build so101-nexus
|
|
36
|
+
run: uv build --out-dir dist/
|
|
37
|
+
|
|
38
|
+
- name: Upload distributions
|
|
39
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
40
|
+
with:
|
|
41
|
+
name: release-dists
|
|
42
|
+
path: dist/
|
|
43
|
+
if-no-files-found: error
|
|
44
|
+
retention-days: 7
|
|
45
|
+
|
|
46
|
+
pypi-publish:
|
|
47
|
+
name: pypi-publish
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
needs: build
|
|
50
|
+
timeout-minutes: 15
|
|
51
|
+
permissions:
|
|
52
|
+
id-token: write
|
|
53
|
+
|
|
54
|
+
environment:
|
|
55
|
+
name: pypi
|
|
56
|
+
|
|
57
|
+
steps:
|
|
58
|
+
- name: Download all distributions
|
|
59
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
60
|
+
with:
|
|
61
|
+
name: release-dists
|
|
62
|
+
path: dist/
|
|
63
|
+
|
|
64
|
+
- name: Publish to PyPI
|
|
65
|
+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
|
|
66
|
+
with:
|
|
67
|
+
packages-dir: dist/
|
|
68
|
+
attestations: true
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
name: Release Smoke Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
version:
|
|
9
|
+
description: "Package version to install (e.g. 0.1.0 or v0.1.0). Empty = latest."
|
|
10
|
+
required: false
|
|
11
|
+
type: string
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
group: release-smoke-${{ github.event.release.tag_name || github.event.inputs.version || github.ref }}
|
|
18
|
+
cancel-in-progress: false
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
smoke-test:
|
|
22
|
+
name: smoke-test (${{ matrix.backend }})
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
timeout-minutes: 45
|
|
25
|
+
strategy:
|
|
26
|
+
fail-fast: false
|
|
27
|
+
matrix:
|
|
28
|
+
include:
|
|
29
|
+
- backend: mujoco
|
|
30
|
+
package: so101-nexus
|
|
31
|
+
env_id: MuJoCoReach-v1
|
|
32
|
+
apt_packages: "xvfb libgl1 libglx-mesa0 libegl1-mesa-dev libosmesa6-dev"
|
|
33
|
+
- backend: warp
|
|
34
|
+
package: "so101-nexus[warp]"
|
|
35
|
+
env_id: WarpReach-v1
|
|
36
|
+
apt_packages: "xvfb libgl1 libglx-mesa0 libegl1-mesa-dev libosmesa6-dev"
|
|
37
|
+
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@9f698171ed81b15d1823a05fc7211befd50c8ae0 # v6.0.3
|
|
40
|
+
with:
|
|
41
|
+
persist-credentials: false
|
|
42
|
+
|
|
43
|
+
- name: Set up Python
|
|
44
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
45
|
+
with:
|
|
46
|
+
python-version: "3.12"
|
|
47
|
+
|
|
48
|
+
- name: Install system dependencies
|
|
49
|
+
run: |
|
|
50
|
+
sudo apt-get update
|
|
51
|
+
sudo apt-get install -y ${{ matrix.apt_packages }}
|
|
52
|
+
|
|
53
|
+
- name: Install package from PyPI (with retries)
|
|
54
|
+
env:
|
|
55
|
+
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
56
|
+
INPUT_VERSION: ${{ github.event.inputs.version }}
|
|
57
|
+
PACKAGE: ${{ matrix.package }}
|
|
58
|
+
run: |
|
|
59
|
+
set -euo pipefail
|
|
60
|
+
python -m pip install --upgrade pip
|
|
61
|
+
|
|
62
|
+
VERSION="${INPUT_VERSION:-}"
|
|
63
|
+
if [ -z "$VERSION" ]; then
|
|
64
|
+
VERSION="${RELEASE_TAG:-}"
|
|
65
|
+
fi
|
|
66
|
+
VERSION="${VERSION#v}"
|
|
67
|
+
|
|
68
|
+
if [ -n "$VERSION" ]; then
|
|
69
|
+
SPEC="${PACKAGE}==${VERSION}"
|
|
70
|
+
else
|
|
71
|
+
SPEC="${PACKAGE}"
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
echo "Installing ${SPEC}"
|
|
75
|
+
for i in {1..10}; do
|
|
76
|
+
if python -m pip install "${SPEC}"; then
|
|
77
|
+
exit 0
|
|
78
|
+
fi
|
|
79
|
+
echo "Install attempt ${i}/10 failed; retrying in 30s..."
|
|
80
|
+
sleep 30
|
|
81
|
+
done
|
|
82
|
+
|
|
83
|
+
echo "Failed to install ${SPEC} from PyPI after retries."
|
|
84
|
+
exit 1
|
|
85
|
+
|
|
86
|
+
- name: Install smoke-check harness deps
|
|
87
|
+
run: python -m pip install tyro
|
|
88
|
+
|
|
89
|
+
- name: Run backend smoke check
|
|
90
|
+
env:
|
|
91
|
+
MUJOCO_GL: egl
|
|
92
|
+
run: |
|
|
93
|
+
python .github/scripts/pypi_smoke_check.py \
|
|
94
|
+
--backend "${{ matrix.backend }}" \
|
|
95
|
+
--env-id "${{ matrix.env_id }}"
|