agenticros 0.0.1 → 0.1.0
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.
- package/LICENSE +192 -0
- package/README.md +90 -4
- package/dist/commands/config.d.ts +20 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +143 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/doctor.d.ts +33 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +232 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/down.d.ts +13 -0
- package/dist/commands/down.d.ts.map +1 -0
- package/dist/commands/down.js +81 -0
- package/dist/commands/down.js.map +1 -0
- package/dist/commands/init.d.ts +21 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +259 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/logs.d.ts +18 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +67 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/status.d.ts +12 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +52 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/up.d.ts +19 -0
- package/dist/commands/up.d.ts.map +1 -0
- package/dist/commands/up.js +58 -0
- package/dist/commands/up.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +106 -0
- package/dist/index.js.map +1 -0
- package/dist/menu.d.ts +9 -0
- package/dist/menu.d.ts.map +1 -0
- package/dist/menu.js +96 -0
- package/dist/menu.js.map +1 -0
- package/dist/runners/real-robot.d.ts +15 -0
- package/dist/runners/real-robot.d.ts.map +1 -0
- package/dist/runners/real-robot.js +46 -0
- package/dist/runners/real-robot.js.map +1 -0
- package/dist/runners/sim.d.ts +17 -0
- package/dist/runners/sim.d.ts.map +1 -0
- package/dist/runners/sim.js +51 -0
- package/dist/runners/sim.js.map +1 -0
- package/dist/util/env.d.ts +24 -0
- package/dist/util/env.d.ts.map +1 -0
- package/dist/util/env.js +53 -0
- package/dist/util/env.js.map +1 -0
- package/dist/util/logger.d.ts +24 -0
- package/dist/util/logger.d.ts.map +1 -0
- package/dist/util/logger.js +62 -0
- package/dist/util/logger.js.map +1 -0
- package/dist/util/paths.d.ts +57 -0
- package/dist/util/paths.d.ts.map +1 -0
- package/dist/util/paths.js +132 -0
- package/dist/util/paths.js.map +1 -0
- package/dist/util/pidfile.d.ts +16 -0
- package/dist/util/pidfile.d.ts.map +1 -0
- package/dist/util/pidfile.js +63 -0
- package/dist/util/pidfile.js.map +1 -0
- package/dist/util/state.d.ts +26 -0
- package/dist/util/state.d.ts.map +1 -0
- package/dist/util/state.js +55 -0
- package/dist/util/state.js.map +1 -0
- package/package.json +60 -1
- package/runtime/BUNDLE.json +11 -0
- package/runtime/LICENSE +192 -0
- package/runtime/README.md +273 -0
- package/runtime/docs/architecture.md +366 -0
- package/runtime/docs/cli.md +140 -0
- package/runtime/docs/memory.md +292 -0
- package/runtime/docs/robot-setup.md +347 -0
- package/runtime/package.json +28 -0
- package/runtime/packages/agenticros/agenticros-agenticros-0.0.1.tgz +0 -0
- package/runtime/packages/agenticros/openclaw.plugin.json +451 -0
- package/runtime/packages/agenticros/package.json +41 -0
- package/runtime/packages/agenticros/src/camera-snapshot-cache.ts +59 -0
- package/runtime/packages/agenticros/src/camera-snapshot-routes.ts +44 -0
- package/runtime/packages/agenticros/src/commands/estop.ts +41 -0
- package/runtime/packages/agenticros/src/commands/transport.ts +195 -0
- package/runtime/packages/agenticros/src/config-file.ts +136 -0
- package/runtime/packages/agenticros/src/config-page.ts +498 -0
- package/runtime/packages/agenticros/src/context/robot-context.ts +373 -0
- package/runtime/packages/agenticros/src/depth.ts +313 -0
- package/runtime/packages/agenticros/src/describer.ts +157 -0
- package/runtime/packages/agenticros/src/image-binary-trim.ts +16 -0
- package/runtime/packages/agenticros/src/index.ts +85 -0
- package/runtime/packages/agenticros/src/landing-page.ts +38 -0
- package/runtime/packages/agenticros/src/memory.ts +44 -0
- package/runtime/packages/agenticros/src/plugin-api.ts +173 -0
- package/runtime/packages/agenticros/src/plugin-image-base64.ts +69 -0
- package/runtime/packages/agenticros/src/preflight.ts +110 -0
- package/runtime/packages/agenticros/src/routes.ts +328 -0
- package/runtime/packages/agenticros/src/safety/validator.ts +43 -0
- package/runtime/packages/agenticros/src/service.ts +359 -0
- package/runtime/packages/agenticros/src/skill-api.ts +65 -0
- package/runtime/packages/agenticros/src/skill-loader.ts +146 -0
- package/runtime/packages/agenticros/src/teleop/page.ts +498 -0
- package/runtime/packages/agenticros/src/teleop/routes.ts +650 -0
- package/runtime/packages/agenticros/src/tools/index.ts +26 -0
- package/runtime/packages/agenticros/src/tools/ros2-action.ts +50 -0
- package/runtime/packages/agenticros/src/tools/ros2-camera.ts +221 -0
- package/runtime/packages/agenticros/src/tools/ros2-depth-distance.ts +58 -0
- package/runtime/packages/agenticros/src/tools/ros2-introspect.ts +62 -0
- package/runtime/packages/agenticros/src/tools/ros2-memory.ts +158 -0
- package/runtime/packages/agenticros/src/tools/ros2-param.ts +87 -0
- package/runtime/packages/agenticros/src/tools/ros2-publish.ts +52 -0
- package/runtime/packages/agenticros/src/tools/ros2-service.ts +46 -0
- package/runtime/packages/agenticros/src/tools/ros2-subscribe.ts +71 -0
- package/runtime/packages/agenticros/tsconfig.json +9 -0
- package/runtime/packages/agenticros-claude-code/README.md +260 -0
- package/runtime/packages/agenticros-claude-code/config.example.json +9 -0
- package/runtime/packages/agenticros-claude-code/dist/config.d.ts +8 -0
- package/runtime/packages/agenticros-claude-code/dist/config.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/config.js +93 -0
- package/runtime/packages/agenticros-claude-code/dist/config.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/depth.d.ts +20 -0
- package/runtime/packages/agenticros-claude-code/dist/depth.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/depth.js +126 -0
- package/runtime/packages/agenticros-claude-code/dist/depth.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/find-object/coco-classes.d.ts +6 -0
- package/runtime/packages/agenticros-claude-code/dist/find-object/coco-classes.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/find-object/coco-classes.js +36 -0
- package/runtime/packages/agenticros-claude-code/dist/find-object/coco-classes.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.d.ts +33 -0
- package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.js +134 -0
- package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/controller.d.ts +43 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/controller.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/controller.js +73 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/controller.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/detector.d.ts +58 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/detector.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/detector.js +251 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/detector.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/loop.d.ts +61 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/loop.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/loop.js +268 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/loop.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/index.d.ts +3 -0
- package/runtime/packages/agenticros-claude-code/dist/index.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/index.js +111 -0
- package/runtime/packages/agenticros-claude-code/dist/index.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/memory.d.ts +17 -0
- package/runtime/packages/agenticros-claude-code/dist/memory.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/memory.js +44 -0
- package/runtime/packages/agenticros-claude-code/dist/memory.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/safety.d.ts +10 -0
- package/runtime/packages/agenticros-claude-code/dist/safety.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/safety.js +34 -0
- package/runtime/packages/agenticros-claude-code/dist/safety.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/tools.d.ts +36 -0
- package/runtime/packages/agenticros-claude-code/dist/tools.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/tools.js +777 -0
- package/runtime/packages/agenticros-claude-code/dist/tools.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/transport.d.ts +17 -0
- package/runtime/packages/agenticros-claude-code/dist/transport.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/transport.js +46 -0
- package/runtime/packages/agenticros-claude-code/dist/transport.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/zero-shot/detector.d.ts +42 -0
- package/runtime/packages/agenticros-claude-code/dist/zero-shot/detector.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/zero-shot/detector.js +114 -0
- package/runtime/packages/agenticros-claude-code/dist/zero-shot/detector.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/package.json +29 -0
- package/runtime/packages/agenticros-claude-code/src/config.ts +96 -0
- package/runtime/packages/agenticros-claude-code/src/depth.ts +173 -0
- package/runtime/packages/agenticros-claude-code/src/find-object/coco-classes.ts +38 -0
- package/runtime/packages/agenticros-claude-code/src/find-object/find-object.ts +190 -0
- package/runtime/packages/agenticros-claude-code/src/follow-me/controller.ts +109 -0
- package/runtime/packages/agenticros-claude-code/src/follow-me/depth-loop.ts +420 -0
- package/runtime/packages/agenticros-claude-code/src/follow-me/detector.ts +303 -0
- package/runtime/packages/agenticros-claude-code/src/follow-me/loop.ts +330 -0
- package/runtime/packages/agenticros-claude-code/src/index.ts +125 -0
- package/runtime/packages/agenticros-claude-code/src/memory.ts +51 -0
- package/runtime/packages/agenticros-claude-code/src/safety.ts +44 -0
- package/runtime/packages/agenticros-claude-code/src/tools.ts +891 -0
- package/runtime/packages/agenticros-claude-code/src/transport.ts +58 -0
- package/runtime/packages/agenticros-claude-code/src/zero-shot/detector.ts +169 -0
- package/runtime/packages/agenticros-claude-code/tsconfig.json +9 -0
- package/runtime/packages/agenticros-claude-code/yolo-debug.mjs +106 -0
- package/runtime/packages/agenticros-gemini/README.md +139 -0
- package/runtime/packages/agenticros-gemini/package.json +28 -0
- package/runtime/packages/agenticros-gemini/scripts/smoke-api.mjs +42 -0
- package/runtime/packages/agenticros-gemini/src/chat.ts +139 -0
- package/runtime/packages/agenticros-gemini/src/config.ts +92 -0
- package/runtime/packages/agenticros-gemini/src/depth.ts +173 -0
- package/runtime/packages/agenticros-gemini/src/index.ts +58 -0
- package/runtime/packages/agenticros-gemini/src/memory.ts +32 -0
- package/runtime/packages/agenticros-gemini/src/safety.ts +44 -0
- package/runtime/packages/agenticros-gemini/src/tools.ts +516 -0
- package/runtime/packages/agenticros-gemini/src/transport.ts +58 -0
- package/runtime/packages/agenticros-gemini/tsconfig.json +8 -0
- package/runtime/packages/core/package.json +47 -0
- package/runtime/packages/core/src/banner.ts +32 -0
- package/runtime/packages/core/src/cmd-vel-twist.ts +31 -0
- package/runtime/packages/core/src/config.ts +279 -0
- package/runtime/packages/core/src/index.ts +54 -0
- package/runtime/packages/core/src/memory/__tests__/factory.test.ts +70 -0
- package/runtime/packages/core/src/memory/__tests__/local-provider.test.ts +195 -0
- package/runtime/packages/core/src/memory/__tests__/mem0-provider.test.ts +192 -0
- package/runtime/packages/core/src/memory/__tests__/smart-defaults.test.ts +46 -0
- package/runtime/packages/core/src/memory/factory.ts +63 -0
- package/runtime/packages/core/src/memory/index.ts +10 -0
- package/runtime/packages/core/src/memory/local/provider.ts +229 -0
- package/runtime/packages/core/src/memory/mem0/provider.ts +379 -0
- package/runtime/packages/core/src/memory/types.ts +96 -0
- package/runtime/packages/core/src/topic-utils.ts +95 -0
- package/runtime/packages/core/src/transport/factory.ts +47 -0
- package/runtime/packages/core/src/transport/local/conversion.ts +333 -0
- package/runtime/packages/core/src/transport/local/entities.ts +129 -0
- package/runtime/packages/core/src/transport/local/transport.ts +386 -0
- package/runtime/packages/core/src/transport/rosbridge/actions.ts +81 -0
- package/runtime/packages/core/src/transport/rosbridge/adapter.ts +157 -0
- package/runtime/packages/core/src/transport/rosbridge/client.ts +438 -0
- package/runtime/packages/core/src/transport/rosbridge/services.ts +41 -0
- package/runtime/packages/core/src/transport/rosbridge/topics.ts +60 -0
- package/runtime/packages/core/src/transport/rosbridge/types.ts +118 -0
- package/runtime/packages/core/src/transport/transport.ts +77 -0
- package/runtime/packages/core/src/transport/types.ts +137 -0
- package/runtime/packages/core/src/transport/webrtc/signaling-client.ts +196 -0
- package/runtime/packages/core/src/transport/webrtc/signaling-types.ts +130 -0
- package/runtime/packages/core/src/transport/webrtc/transport.ts +516 -0
- package/runtime/packages/core/src/transport/zenoh/adapter.ts +357 -0
- package/runtime/packages/core/src/transport/zenoh/cdr.ts +183 -0
- package/runtime/packages/core/src/transport/zenoh/keys.ts +51 -0
- package/runtime/packages/core/tsconfig.json +9 -0
- package/runtime/packages/ros-camera/package.json +30 -0
- package/runtime/packages/ros-camera/src/index.ts +13 -0
- package/runtime/packages/ros-camera/src/snapshot.ts +372 -0
- package/runtime/packages/ros-camera/tsconfig.json +9 -0
- package/runtime/pnpm-lock.yaml +5260 -0
- package/runtime/pnpm-workspace.yaml +2 -0
- package/runtime/ros2_ws/src/agenticros_agent/agenticros_agent/__init__.py +0 -0
- package/runtime/ros2_ws/src/agenticros_agent/agenticros_agent/agent_node.py +561 -0
- package/runtime/ros2_ws/src/agenticros_agent/package.xml +25 -0
- package/runtime/ros2_ws/src/agenticros_agent/resource/agenticros_agent +0 -0
- package/runtime/ros2_ws/src/agenticros_agent/setup.cfg +4 -0
- package/runtime/ros2_ws/src/agenticros_agent/setup.py +25 -0
- package/runtime/ros2_ws/src/agenticros_bringup/README.md +128 -0
- package/runtime/ros2_ws/src/agenticros_bringup/agenticros_bringup/__init__.py +1 -0
- package/runtime/ros2_ws/src/agenticros_bringup/agenticros_bringup/cmd_vel_relay.py +33 -0
- package/runtime/ros2_ws/src/agenticros_bringup/launch/cmd_vel_bridge.launch.py +58 -0
- package/runtime/ros2_ws/src/agenticros_bringup/launch/gazebo_turtlebot3.launch.py +69 -0
- package/runtime/ros2_ws/src/agenticros_bringup/launch/mode_a_gazebo.launch.py +55 -0
- package/runtime/ros2_ws/src/agenticros_bringup/launch/mode_a_gazebo_rviz.launch.py +48 -0
- package/runtime/ros2_ws/src/agenticros_bringup/launch/realsense_rosbridge.launch.py +154 -0
- package/runtime/ros2_ws/src/agenticros_bringup/launch/rosbridge_gazebo.launch.py +54 -0
- package/runtime/ros2_ws/src/agenticros_bringup/launch/rviz.launch.py +38 -0
- package/runtime/ros2_ws/src/agenticros_bringup/launch/turtlebot3_gazebo_rviz.launch.py +42 -0
- package/runtime/ros2_ws/src/agenticros_bringup/package.xml +24 -0
- package/runtime/ros2_ws/src/agenticros_bringup/resource/agenticros_bringup +0 -0
- package/runtime/ros2_ws/src/agenticros_bringup/rviz/turtlebot3_agenticros.rviz +174 -0
- package/runtime/ros2_ws/src/agenticros_bringup/setup.cfg +4 -0
- package/runtime/ros2_ws/src/agenticros_bringup/setup.py +28 -0
- package/runtime/ros2_ws/src/agenticros_discovery/agenticros_discovery/__init__.py +0 -0
- package/runtime/ros2_ws/src/agenticros_discovery/agenticros_discovery/discovery_node.py +172 -0
- package/runtime/ros2_ws/src/agenticros_discovery/package.xml +22 -0
- package/runtime/ros2_ws/src/agenticros_discovery/resource/agenticros_discovery +0 -0
- package/runtime/ros2_ws/src/agenticros_discovery/setup.cfg +5 -0
- package/runtime/ros2_ws/src/agenticros_discovery/setup.py +25 -0
- package/runtime/ros2_ws/src/agenticros_follow_me/README.md +66 -0
- package/runtime/ros2_ws/src/agenticros_follow_me/agenticros_follow_me/__init__.py +1 -0
- package/runtime/ros2_ws/src/agenticros_follow_me/agenticros_follow_me/__main__.py +5 -0
- package/runtime/ros2_ws/src/agenticros_follow_me/agenticros_follow_me/follow_me_node.py +278 -0
- package/runtime/ros2_ws/src/agenticros_follow_me/agenticros_follow_me/follower_controller.py +631 -0
- package/runtime/ros2_ws/src/agenticros_follow_me/agenticros_follow_me/person_tracker.py +635 -0
- package/runtime/ros2_ws/src/agenticros_follow_me/package.xml +22 -0
- package/runtime/ros2_ws/src/agenticros_follow_me/resource/agenticros_follow_me +0 -0
- package/runtime/ros2_ws/src/agenticros_follow_me/setup.py +25 -0
- package/runtime/ros2_ws/src/agenticros_msgs/CMakeLists.txt +26 -0
- package/runtime/ros2_ws/src/agenticros_msgs/msg/CapabilityManifest.msg +9 -0
- package/runtime/ros2_ws/src/agenticros_msgs/package.xml +22 -0
- package/runtime/ros2_ws/src/agenticros_msgs/srv/FollowMeGetStatus.srv +11 -0
- package/runtime/ros2_ws/src/agenticros_msgs/srv/FollowMeSetDistance.srv +4 -0
- package/runtime/ros2_ws/src/agenticros_msgs/srv/FollowMeSetTarget.srv +6 -0
- package/runtime/ros2_ws/src/agenticros_msgs/srv/FollowMeStart.srv +5 -0
- package/runtime/ros2_ws/src/agenticros_msgs/srv/FollowMeStop.srv +3 -0
- package/runtime/ros2_ws/src/agenticros_msgs/srv/GetCapabilities.srv +5 -0
- package/runtime/scripts/activate_workspace.sh +285 -0
- package/runtime/scripts/agenticros-describer.policy.yaml +96 -0
- package/runtime/scripts/agenticros-proxy.cjs +99 -0
- package/runtime/scripts/agenticros-rosbridge.policy.yaml +62 -0
- package/runtime/scripts/check-cli-tarball-size.mjs +42 -0
- package/runtime/scripts/configure_agenticros.sh +200 -0
- package/runtime/scripts/fix-openclaw-control-ui-path.sh +20 -0
- package/runtime/scripts/install_cli.sh +94 -0
- package/runtime/scripts/install_rosbridge_from_source.sh +67 -0
- package/runtime/scripts/lib/agenticros-banner.sh +28 -0
- package/runtime/scripts/onboard_robot.sh +75 -0
- package/runtime/scripts/openai.policy.yaml +77 -0
- package/runtime/scripts/openclaw-dashboard-url.cjs +49 -0
- package/runtime/scripts/pack-runtime.mjs +245 -0
- package/runtime/scripts/run_demo_native.sh +43 -0
- package/runtime/scripts/run_nemoclaw_host_stack.sh +91 -0
- package/runtime/scripts/run_robot_rosbridge.sh +36 -0
- package/runtime/scripts/sandbox_rosbridge_relay.py +137 -0
- package/runtime/scripts/setup-openclaw-local.cjs +75 -0
- package/runtime/scripts/setup_gateway_plugin.sh +329 -0
- package/runtime/scripts/setup_robot.sh +113 -0
- package/runtime/scripts/setup_workspace.sh +484 -0
- package/runtime/scripts/smoke_test_nemoclaw.sh +123 -0
- package/runtime/scripts/start_demo.sh +55 -0
- package/runtime/scripts/sync-skill-tools.mjs +335 -0
- package/runtime/scripts/test-rclnodejs.mts +129 -0
- package/runtime/scripts/use-openclaw-2026.2.26.sh +19 -0
- package/runtime/scripts/use-openclaw-2026.3.11.sh +19 -0
- package/runtime/scripts/zenoh-bridge-ros2dds-robot.json5 +30 -0
- package/runtime/scripts/zenohd-agenticros.json5 +11 -0
- package/runtime/scripts/zenohd-rosclaw.json5 +11 -0
- package/runtime/tsconfig.base.json +19 -0
- package/index.js +0 -6
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# setup_workspace.sh - Cross-platform setup for AgenticROS development environment
|
|
3
|
+
#
|
|
4
|
+
# DESCRIPTION:
|
|
5
|
+
# This script performs the initial setup required for AgenticROS development.
|
|
6
|
+
# It supports both Ubuntu (native ROS2) and macOS (RoboStack with mamba).
|
|
7
|
+
# The script installs dependencies, creates the appropriate environment,
|
|
8
|
+
# and builds all ROS2 packages. Run this script once before using the
|
|
9
|
+
# activate_workspace.sh script for daily development.
|
|
10
|
+
#
|
|
11
|
+
# USAGE:
|
|
12
|
+
# ./scripts/setup_workspace.sh [options]
|
|
13
|
+
#
|
|
14
|
+
# OPTIONS:
|
|
15
|
+
# -e, --env-name NAME Name of the environment to create (default: ros_env)
|
|
16
|
+
# -d, --ros-distro DISTRO ROS2 distribution (default: humble)
|
|
17
|
+
# -h, --help Show this help message
|
|
18
|
+
#
|
|
19
|
+
# EXAMPLES:
|
|
20
|
+
# # Use defaults (ros_env, jazzy)
|
|
21
|
+
# ./scripts/setup_workspace.sh
|
|
22
|
+
#
|
|
23
|
+
# # Custom environment name
|
|
24
|
+
# ./scripts/setup_workspace.sh --env-name my_ros_env
|
|
25
|
+
#
|
|
26
|
+
# # Different ROS2 distro
|
|
27
|
+
# ./scripts/setup_workspace.sh --ros-distro humble
|
|
28
|
+
#
|
|
29
|
+
# PLATFORMS SUPPORTED:
|
|
30
|
+
# - Ubuntu/Debian: Native ROS2 installation with apt + venv
|
|
31
|
+
# - macOS: RoboStack with mamba/conda environment
|
|
32
|
+
#
|
|
33
|
+
# WHAT IT DOES:
|
|
34
|
+
# 1. Detects platform (Ubuntu vs macOS)
|
|
35
|
+
# 2. Installs platform-specific infrastructure
|
|
36
|
+
# 3. Creates appropriate environment (venv with --system-site-packages vs conda)
|
|
37
|
+
# 4. Installs ROS2, rosbridge_library, and all required development tools
|
|
38
|
+
# 5. Installs agent-specific pip dependencies (aiortc, websockets)
|
|
39
|
+
# 6. Builds all ROS2 packages in ros2_ws
|
|
40
|
+
# 7. Validates the complete setup
|
|
41
|
+
|
|
42
|
+
set -e # Exit on any error
|
|
43
|
+
|
|
44
|
+
# Default values
|
|
45
|
+
DEFAULT_ENV_NAME="ros_env"
|
|
46
|
+
DEFAULT_ROS_DISTRO="humble"
|
|
47
|
+
ENV_NAME=""
|
|
48
|
+
ROS_DISTRO=""
|
|
49
|
+
|
|
50
|
+
# Find the repository root
|
|
51
|
+
REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
52
|
+
ROS2_WS_PATH="$REPO_ROOT/ros2_ws"
|
|
53
|
+
|
|
54
|
+
# Colors for output
|
|
55
|
+
RED='\033[0;31m'
|
|
56
|
+
GREEN='\033[0;32m'
|
|
57
|
+
YELLOW='\033[1;33m'
|
|
58
|
+
BLUE='\033[0;34m'
|
|
59
|
+
NC='\033[0m' # No Color
|
|
60
|
+
|
|
61
|
+
# Logging functions
|
|
62
|
+
log_info() {
|
|
63
|
+
echo -e "${BLUE}[INFO]${NC} $1"
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
log_success() {
|
|
67
|
+
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
log_warning() {
|
|
71
|
+
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
log_error() {
|
|
75
|
+
echo -e "${RED}[ERROR]${NC} $1"
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
# Help function
|
|
79
|
+
show_help() {
|
|
80
|
+
cat << EOF
|
|
81
|
+
AgenticROS Development Environment Setup
|
|
82
|
+
|
|
83
|
+
USAGE:
|
|
84
|
+
$0 [options]
|
|
85
|
+
|
|
86
|
+
OPTIONS:
|
|
87
|
+
-e, --env-name NAME Name of the environment to create (default: $DEFAULT_ENV_NAME)
|
|
88
|
+
-d, --ros-distro DISTRO ROS2 distribution (default: $DEFAULT_ROS_DISTRO)
|
|
89
|
+
-h, --help Show this help message
|
|
90
|
+
|
|
91
|
+
EXAMPLES:
|
|
92
|
+
# Use defaults
|
|
93
|
+
$0
|
|
94
|
+
|
|
95
|
+
# Custom environment name
|
|
96
|
+
$0 --env-name my_ros_env
|
|
97
|
+
|
|
98
|
+
# Different ROS2 distribution
|
|
99
|
+
$0 --ros-distro humble
|
|
100
|
+
|
|
101
|
+
SUPPORTED PLATFORMS:
|
|
102
|
+
- Ubuntu/Debian: Native ROS2 with apt + Python venv
|
|
103
|
+
- macOS: RoboStack with mamba/conda environment
|
|
104
|
+
|
|
105
|
+
SUPPORTED ROS2 DISTRIBUTIONS:
|
|
106
|
+
- jazzy (default)
|
|
107
|
+
- humble
|
|
108
|
+
- kilted
|
|
109
|
+
EOF
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# Parse command line arguments
|
|
113
|
+
parse_args() {
|
|
114
|
+
while [[ $# -gt 0 ]]; do
|
|
115
|
+
case $1 in
|
|
116
|
+
-e|--env-name)
|
|
117
|
+
ENV_NAME="$2"
|
|
118
|
+
shift 2
|
|
119
|
+
;;
|
|
120
|
+
-d|--ros-distro)
|
|
121
|
+
ROS_DISTRO="$2"
|
|
122
|
+
shift 2
|
|
123
|
+
;;
|
|
124
|
+
-h|--help)
|
|
125
|
+
show_help
|
|
126
|
+
exit 0
|
|
127
|
+
;;
|
|
128
|
+
*)
|
|
129
|
+
log_error "Unknown option: $1"
|
|
130
|
+
show_help
|
|
131
|
+
exit 1
|
|
132
|
+
;;
|
|
133
|
+
esac
|
|
134
|
+
done
|
|
135
|
+
|
|
136
|
+
# Set defaults if not specified
|
|
137
|
+
ENV_NAME="${ENV_NAME:-$DEFAULT_ENV_NAME}"
|
|
138
|
+
ROS_DISTRO="${ROS_DISTRO:-$DEFAULT_ROS_DISTRO}"
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
# Platform detection
|
|
142
|
+
detect_platform() {
|
|
143
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
144
|
+
PLATFORM="macos"
|
|
145
|
+
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|
146
|
+
if command -v apt &> /dev/null; then
|
|
147
|
+
PLATFORM="ubuntu"
|
|
148
|
+
else
|
|
149
|
+
log_error "Linux platform detected but apt not found. Only Ubuntu/Debian supported."
|
|
150
|
+
exit 1
|
|
151
|
+
fi
|
|
152
|
+
else
|
|
153
|
+
log_error "Unsupported platform: $OSTYPE"
|
|
154
|
+
log_error "Supported platforms: macOS, Ubuntu/Debian"
|
|
155
|
+
exit 1
|
|
156
|
+
fi
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# Check and install mamba/conda if needed (for macOS)
|
|
160
|
+
check_mamba() {
|
|
161
|
+
if ! command -v mamba &> /dev/null; then
|
|
162
|
+
if ! command -v conda &> /dev/null; then
|
|
163
|
+
log_info "Neither mamba nor conda found. Installing miniforge automatically..."
|
|
164
|
+
|
|
165
|
+
local installer="Miniforge3-MacOSX-$(uname -m).sh"
|
|
166
|
+
local url="https://github.com/conda-forge/miniforge/releases/latest/download/$installer"
|
|
167
|
+
|
|
168
|
+
log_info "Downloading miniforge installer..."
|
|
169
|
+
if ! curl -L -O "$url"; then
|
|
170
|
+
log_error "Failed to download miniforge installer"
|
|
171
|
+
exit 1
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
log_info "Installing miniforge..."
|
|
175
|
+
if ! bash "$installer" -b -p "$HOME/miniforge3"; then
|
|
176
|
+
log_error "Failed to install miniforge"
|
|
177
|
+
exit 1
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
rm -f "$installer"
|
|
181
|
+
eval "$($HOME/miniforge3/bin/conda shell.$(basename $SHELL) hook)"
|
|
182
|
+
log_success "Miniforge installed successfully"
|
|
183
|
+
else
|
|
184
|
+
log_warning "conda found but mamba not available. Installing mamba..."
|
|
185
|
+
conda install mamba -c conda-forge -y
|
|
186
|
+
fi
|
|
187
|
+
fi
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
# Validate ROS2 distribution support
|
|
191
|
+
validate_ros_distro() {
|
|
192
|
+
local supported_distros=("humble" "jazzy" "kilted")
|
|
193
|
+
local distro_supported=false
|
|
194
|
+
|
|
195
|
+
for supported in "${supported_distros[@]}"; do
|
|
196
|
+
if [[ "$ROS_DISTRO" == "$supported" ]]; then
|
|
197
|
+
distro_supported=true
|
|
198
|
+
break
|
|
199
|
+
fi
|
|
200
|
+
done
|
|
201
|
+
|
|
202
|
+
if [[ "$distro_supported" == false ]]; then
|
|
203
|
+
log_error "ROS2 distribution '$ROS_DISTRO' is not supported"
|
|
204
|
+
log_error "Supported distributions: ${supported_distros[*]}"
|
|
205
|
+
exit 1
|
|
206
|
+
fi
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
# Check if already in conda environment
|
|
210
|
+
check_conda_env_active() {
|
|
211
|
+
if [[ -n "$CONDA_DEFAULT_ENV" ]]; then
|
|
212
|
+
log_warning "Already in conda environment: $CONDA_DEFAULT_ENV"
|
|
213
|
+
if [[ "$CONDA_DEFAULT_ENV" == "$ENV_NAME" ]]; then
|
|
214
|
+
log_info "Already in target environment '$ENV_NAME', continuing setup..."
|
|
215
|
+
return 0
|
|
216
|
+
else
|
|
217
|
+
log_warning "In different environment. Will deactivate and switch to '$ENV_NAME'"
|
|
218
|
+
conda deactivate 2>/dev/null || true
|
|
219
|
+
mamba deactivate 2>/dev/null || true
|
|
220
|
+
fi
|
|
221
|
+
fi
|
|
222
|
+
return 1
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
# Ubuntu setup function
|
|
226
|
+
setup_ubuntu() {
|
|
227
|
+
log_info "Setting up Ubuntu environment..."
|
|
228
|
+
|
|
229
|
+
# Step 1: Install system dependencies
|
|
230
|
+
log_info "[1/5] Installing system dependencies..."
|
|
231
|
+
sudo apt update
|
|
232
|
+
sudo apt install -y \
|
|
233
|
+
python3-dev \
|
|
234
|
+
python3-venv \
|
|
235
|
+
python3-pip \
|
|
236
|
+
build-essential \
|
|
237
|
+
cmake \
|
|
238
|
+
pkg-config \
|
|
239
|
+
curl \
|
|
240
|
+
gnupg2 \
|
|
241
|
+
lsb-release \
|
|
242
|
+
software-properties-common
|
|
243
|
+
|
|
244
|
+
# Step 2: Install ROS2 and required packages
|
|
245
|
+
log_info "[2/5] Setting up ROS2 $ROS_DISTRO..."
|
|
246
|
+
|
|
247
|
+
if ! command -v ros2 &> /dev/null; then
|
|
248
|
+
log_info "Installing ROS2 $ROS_DISTRO..."
|
|
249
|
+
|
|
250
|
+
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
|
|
251
|
+
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
|
|
252
|
+
|
|
253
|
+
sudo apt update
|
|
254
|
+
else
|
|
255
|
+
log_success "ROS2 base already installed"
|
|
256
|
+
fi
|
|
257
|
+
|
|
258
|
+
log_info "Ensuring all required ROS2 packages are installed..."
|
|
259
|
+
sudo apt install -y \
|
|
260
|
+
ros-$ROS_DISTRO-ros-base \
|
|
261
|
+
ros-$ROS_DISTRO-rosbridge-library \
|
|
262
|
+
ros-$ROS_DISTRO-rosbridge-suite \
|
|
263
|
+
python3-colcon-common-extensions
|
|
264
|
+
|
|
265
|
+
log_success "All required ROS2 packages installed"
|
|
266
|
+
|
|
267
|
+
# Step 3: Create Python virtual environment with system site-packages
|
|
268
|
+
# This is critical: rclpy and rosbridge_library are system-installed via apt.
|
|
269
|
+
# The venv must inherit them via --system-site-packages.
|
|
270
|
+
log_info "[3/5] Setting up Python virtual environment..."
|
|
271
|
+
VENV_PATH="$REPO_ROOT/$ENV_NAME"
|
|
272
|
+
|
|
273
|
+
if [ -d "$VENV_PATH" ]; then
|
|
274
|
+
log_warning "Virtual environment already exists at: $VENV_PATH"
|
|
275
|
+
else
|
|
276
|
+
log_info "Creating virtual environment at: $VENV_PATH (with --system-site-packages)"
|
|
277
|
+
python3 -m venv "$VENV_PATH" --system-site-packages
|
|
278
|
+
log_success "Virtual environment created"
|
|
279
|
+
fi
|
|
280
|
+
|
|
281
|
+
# Step 4: Install agent-specific Python packages
|
|
282
|
+
log_info "[4/5] Installing Python packages for agenticros_agent..."
|
|
283
|
+
source "$VENV_PATH/bin/activate"
|
|
284
|
+
pip install --upgrade pip
|
|
285
|
+
pip install aiortc websockets
|
|
286
|
+
log_success "Python packages installed (aiortc, websockets)"
|
|
287
|
+
|
|
288
|
+
# Step 5: Build ROS2 packages
|
|
289
|
+
log_info "[5/5] Building ROS2 packages..."
|
|
290
|
+
cd "$ROS2_WS_PATH"
|
|
291
|
+
source /opt/ros/$ROS_DISTRO/setup.bash
|
|
292
|
+
colcon build --symlink-install
|
|
293
|
+
log_success "ROS2 packages built successfully"
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
# macOS setup function
|
|
297
|
+
setup_macos() {
|
|
298
|
+
log_info "Setting up macOS environment with RoboStack..."
|
|
299
|
+
|
|
300
|
+
# Step 1: Check mamba installation
|
|
301
|
+
log_info "[1/5] Checking mamba installation..."
|
|
302
|
+
check_mamba
|
|
303
|
+
log_success "Mamba is available"
|
|
304
|
+
|
|
305
|
+
# Step 2: Create conda environment
|
|
306
|
+
log_info "[2/5] Setting up conda environment '$ENV_NAME'..."
|
|
307
|
+
|
|
308
|
+
local already_in_target_env=false
|
|
309
|
+
if check_conda_env_active; then
|
|
310
|
+
already_in_target_env=true
|
|
311
|
+
fi
|
|
312
|
+
|
|
313
|
+
if mamba env list | grep -q "^$ENV_NAME "; then
|
|
314
|
+
log_warning "Environment '$ENV_NAME' already exists"
|
|
315
|
+
if [[ "$already_in_target_env" == false ]]; then
|
|
316
|
+
log_info "Activating existing environment..."
|
|
317
|
+
eval "$(mamba shell hook)"
|
|
318
|
+
mamba activate "$ENV_NAME"
|
|
319
|
+
fi
|
|
320
|
+
else
|
|
321
|
+
log_info "Creating new environment '$ENV_NAME'..."
|
|
322
|
+
mamba create -n "$ENV_NAME" -y
|
|
323
|
+
eval "$(mamba shell hook)"
|
|
324
|
+
mamba activate "$ENV_NAME"
|
|
325
|
+
fi
|
|
326
|
+
|
|
327
|
+
conda config --env --add channels conda-forge
|
|
328
|
+
conda config --env --remove channels defaults 2>/dev/null || true
|
|
329
|
+
conda config --env --add channels robostack-$ROS_DISTRO
|
|
330
|
+
|
|
331
|
+
# Step 3: Install ROS2 and development tools
|
|
332
|
+
log_info "[3/5] Installing ROS2 $ROS_DISTRO and development tools..."
|
|
333
|
+
mamba install -y \
|
|
334
|
+
ros-$ROS_DISTRO-ros-base \
|
|
335
|
+
ros-$ROS_DISTRO-rosbridge-library \
|
|
336
|
+
compilers \
|
|
337
|
+
cmake \
|
|
338
|
+
pkg-config \
|
|
339
|
+
make \
|
|
340
|
+
ninja \
|
|
341
|
+
colcon-common-extensions \
|
|
342
|
+
python \
|
|
343
|
+
pip
|
|
344
|
+
|
|
345
|
+
log_success "ROS2 and development tools installed"
|
|
346
|
+
|
|
347
|
+
# Step 4: Install agent-specific Python packages
|
|
348
|
+
log_info "[4/5] Installing Python packages for agenticros_agent..."
|
|
349
|
+
pip install aiortc websockets
|
|
350
|
+
log_success "Python packages installed (aiortc, websockets)"
|
|
351
|
+
|
|
352
|
+
# Deactivate and reactivate to ensure proper ROS setup
|
|
353
|
+
mamba deactivate
|
|
354
|
+
mamba activate "$ENV_NAME"
|
|
355
|
+
|
|
356
|
+
# Step 5: Build ROS2 packages
|
|
357
|
+
log_info "[5/5] Building ROS2 packages..."
|
|
358
|
+
cd "$ROS2_WS_PATH"
|
|
359
|
+
colcon build --symlink-install
|
|
360
|
+
log_success "ROS2 packages built successfully"
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
# Validation function
|
|
364
|
+
validate_setup() {
|
|
365
|
+
log_info "Validating setup..."
|
|
366
|
+
|
|
367
|
+
cd "$ROS2_WS_PATH"
|
|
368
|
+
|
|
369
|
+
if [[ "$PLATFORM" == "macos" ]]; then
|
|
370
|
+
eval "$(mamba shell hook)"
|
|
371
|
+
mamba activate "$ENV_NAME"
|
|
372
|
+
else
|
|
373
|
+
source /opt/ros/$ROS_DISTRO/setup.bash
|
|
374
|
+
source "$REPO_ROOT/$ENV_NAME/bin/activate"
|
|
375
|
+
fi
|
|
376
|
+
|
|
377
|
+
# Source workspace
|
|
378
|
+
if [ -f "install/setup.bash" ]; then
|
|
379
|
+
source install/setup.bash
|
|
380
|
+
log_success "Workspace sourced successfully"
|
|
381
|
+
else
|
|
382
|
+
log_error "Workspace build failed - install/setup.bash not found"
|
|
383
|
+
return 1
|
|
384
|
+
fi
|
|
385
|
+
|
|
386
|
+
# Test ROS2 functionality
|
|
387
|
+
if command -v ros2 &> /dev/null; then
|
|
388
|
+
log_success "ROS2 command available"
|
|
389
|
+
else
|
|
390
|
+
log_error "ROS2 command not available"
|
|
391
|
+
return 1
|
|
392
|
+
fi
|
|
393
|
+
|
|
394
|
+
# Test if our packages are available
|
|
395
|
+
local all_found=true
|
|
396
|
+
for pkg in agenticros_msgs agenticros_discovery agenticros_agent; do
|
|
397
|
+
if ros2 pkg list 2>/dev/null | grep -q "$pkg"; then
|
|
398
|
+
log_success "Package found: $pkg"
|
|
399
|
+
else
|
|
400
|
+
log_warning "Package not found: $pkg"
|
|
401
|
+
all_found=false
|
|
402
|
+
fi
|
|
403
|
+
done
|
|
404
|
+
|
|
405
|
+
# Test agent Python dependencies
|
|
406
|
+
if python3 -c "import aiortc; import websockets" 2>/dev/null; then
|
|
407
|
+
log_success "Agent Python dependencies available (aiortc, websockets)"
|
|
408
|
+
else
|
|
409
|
+
log_warning "Agent Python dependencies missing (aiortc or websockets)"
|
|
410
|
+
fi
|
|
411
|
+
|
|
412
|
+
# Test rosbridge_library availability
|
|
413
|
+
if python3 -c "from rosbridge_library.internal.ros_loader import get_message_class" 2>/dev/null; then
|
|
414
|
+
log_success "rosbridge_library available"
|
|
415
|
+
else
|
|
416
|
+
log_warning "rosbridge_library not available"
|
|
417
|
+
fi
|
|
418
|
+
|
|
419
|
+
return 0
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
# Main execution
|
|
423
|
+
main() {
|
|
424
|
+
# shellcheck source=scripts/lib/agenticros-banner.sh
|
|
425
|
+
source "$REPO_ROOT/scripts/lib/agenticros-banner.sh"
|
|
426
|
+
agenticros_banner
|
|
427
|
+
echo "AgenticROS Development Setup"
|
|
428
|
+
echo ""
|
|
429
|
+
|
|
430
|
+
parse_args "$@"
|
|
431
|
+
detect_platform
|
|
432
|
+
|
|
433
|
+
if [[ "$PLATFORM" == "macos" ]]; then
|
|
434
|
+
validate_ros_distro
|
|
435
|
+
fi
|
|
436
|
+
|
|
437
|
+
log_info "Platform detected: $PLATFORM"
|
|
438
|
+
log_info "Environment name: $ENV_NAME"
|
|
439
|
+
log_info "ROS2 distribution: $ROS_DISTRO"
|
|
440
|
+
log_info "Repository root: $REPO_ROOT"
|
|
441
|
+
|
|
442
|
+
if [[ "$PLATFORM" == "macos" && -n "$CONDA_DEFAULT_ENV" ]]; then
|
|
443
|
+
log_info "Current conda environment: $CONDA_DEFAULT_ENV"
|
|
444
|
+
fi
|
|
445
|
+
echo ""
|
|
446
|
+
|
|
447
|
+
case $PLATFORM in
|
|
448
|
+
ubuntu)
|
|
449
|
+
setup_ubuntu
|
|
450
|
+
;;
|
|
451
|
+
macos)
|
|
452
|
+
setup_macos
|
|
453
|
+
;;
|
|
454
|
+
*)
|
|
455
|
+
log_error "Unsupported platform: $PLATFORM"
|
|
456
|
+
exit 1
|
|
457
|
+
;;
|
|
458
|
+
esac
|
|
459
|
+
|
|
460
|
+
echo ""
|
|
461
|
+
|
|
462
|
+
if validate_setup; then
|
|
463
|
+
log_success "Setup validation passed!"
|
|
464
|
+
else
|
|
465
|
+
log_error "Setup validation failed!"
|
|
466
|
+
exit 1
|
|
467
|
+
fi
|
|
468
|
+
|
|
469
|
+
echo ""
|
|
470
|
+
echo "Setup complete!"
|
|
471
|
+
echo ""
|
|
472
|
+
echo "Next steps:"
|
|
473
|
+
echo " 1. Activate your development environment for daily use:"
|
|
474
|
+
echo " source $REPO_ROOT/scripts/activate_workspace.sh"
|
|
475
|
+
echo ""
|
|
476
|
+
echo " 2. Test discovery node:"
|
|
477
|
+
echo " ros2 run agenticros_discovery discovery_node"
|
|
478
|
+
echo ""
|
|
479
|
+
echo " 3. Test agent node (requires signaling server):"
|
|
480
|
+
echo " AGENTICROS_SIGNALING_URL=ws://localhost:8000 ros2 run agenticros_agent agent_node"
|
|
481
|
+
echo ""
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
main "$@"
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Smoke-test the hybrid NemoClaw + AgenticROS bridge.
|
|
4
|
+
#
|
|
5
|
+
# Checks, in order:
|
|
6
|
+
# 1. NemoClaw sandbox container is up.
|
|
7
|
+
# 2. agenticros_rosbridge policy is loaded into the live gateway bundle
|
|
8
|
+
# with the SSRF allowed_ips block (so host.docker.internal is reachable).
|
|
9
|
+
# 3. rosbridge_server is bound on the host (0.0.0.0:9090).
|
|
10
|
+
# 4. The plugin's actual TCP connection through the OPA proxy is ALLOWED
|
|
11
|
+
# (not denied by engine:ssrf or engine:opa).
|
|
12
|
+
# 5. A real WebSocket request to /rosapi/topics through the proxy returns
|
|
13
|
+
# a list of ROS 2 topics (i.e. the gateway can both reach rosbridge and
|
|
14
|
+
# speak its protocol).
|
|
15
|
+
# 6. The NemoClaw dashboard HTTP endpoint serves a non-empty body.
|
|
16
|
+
#
|
|
17
|
+
# Exit code: 0 on all-pass, 1 on any failure. Prints a one-line PASS/FAIL per
|
|
18
|
+
# check + a final summary.
|
|
19
|
+
#
|
|
20
|
+
# Usage: ./scripts/smoke_test_nemoclaw.sh
|
|
21
|
+
|
|
22
|
+
set -uo pipefail
|
|
23
|
+
|
|
24
|
+
GREEN=$'\033[32m'; RED=$'\033[31m'; YELLOW=$'\033[33m'; RESET=$'\033[0m'
|
|
25
|
+
PASS=0; FAIL=0
|
|
26
|
+
pass() { echo "${GREEN}PASS${RESET} $*"; PASS=$((PASS+1)); }
|
|
27
|
+
fail() { echo "${RED}FAIL${RESET} $*"; FAIL=$((FAIL+1)); }
|
|
28
|
+
warn() { echo "${YELLOW}WARN${RESET} $*"; }
|
|
29
|
+
|
|
30
|
+
CONTAINER=$(docker ps --format '{{.Names}}' 2>/dev/null | grep '^openshell-nemo-' | head -1 || true)
|
|
31
|
+
if [[ -z "${CONTAINER}" ]]; then
|
|
32
|
+
fail "No openshell-nemo-* container running — start NemoClaw with 'nemoclaw nemo start'"
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
pass "sandbox container: ${CONTAINER}"
|
|
36
|
+
|
|
37
|
+
# ----- 2. agenticros_rosbridge policy loaded with allowed_ips ---------------
|
|
38
|
+
OPENSHELL_BIN="${OPENSHELL_BIN:-$(command -v openshell || echo "$HOME/.local/bin/openshell")}"
|
|
39
|
+
if [[ ! -x "${OPENSHELL_BIN}" ]]; then
|
|
40
|
+
warn "openshell CLI not found at ${OPENSHELL_BIN} — skipping policy bundle check"
|
|
41
|
+
else
|
|
42
|
+
POLICY_BUNDLE=$("${OPENSHELL_BIN}" policy get --full nemo 2>/dev/null || true)
|
|
43
|
+
if grep -q 'agenticros_rosbridge:' <<<"${POLICY_BUNDLE}"; then
|
|
44
|
+
if grep -q 'allowed_ips:' <<<"${POLICY_BUNDLE}"; then
|
|
45
|
+
pass "agenticros_rosbridge policy is loaded with allowed_ips (SSRF guard satisfied)"
|
|
46
|
+
else
|
|
47
|
+
fail "agenticros_rosbridge policy is loaded but missing allowed_ips — SSRF guard will deny"
|
|
48
|
+
fi
|
|
49
|
+
else
|
|
50
|
+
fail "agenticros_rosbridge policy is NOT loaded — run: nemoclaw nemo policy-add --yes --from-file scripts/agenticros-rosbridge.policy.yaml"
|
|
51
|
+
fi
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# ----- 3. rosbridge_server bound on host:9090 -------------------------------
|
|
55
|
+
if ss -ltn 2>/dev/null | awk '{print $4}' | grep -qE '(:9090|:::9090|0\.0\.0\.0:9090)$'; then
|
|
56
|
+
pass "rosbridge_server is listening on host :9090"
|
|
57
|
+
else
|
|
58
|
+
fail "nothing is listening on host :9090 — start the host stack: ./scripts/run_nemoclaw_host_stack.sh humble"
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# ----- 4. sandbox proxy decision for the plugin's binary --------------------
|
|
62
|
+
LOG_FILE=$(docker exec "${CONTAINER}" sh -c 'ls -t /var/log/openshell.*.log 2>/dev/null | head -1' 2>/dev/null | tr -d '\r')
|
|
63
|
+
if [[ -n "${LOG_FILE}" ]]; then
|
|
64
|
+
LAST_DECISION=$(docker exec "${CONTAINER}" sh -c "grep -E 'host.docker.internal:9090|host.openshell.internal:9090' '${LOG_FILE}' | tail -1" 2>/dev/null)
|
|
65
|
+
if [[ -z "${LAST_DECISION}" ]]; then
|
|
66
|
+
warn "no recent proxy decisions for host.docker.internal:9090 in ${LOG_FILE} (gateway hasn't tried yet?)"
|
|
67
|
+
elif grep -qE 'ALLOWED.*policy:agenticros_rosbridge' <<<"${LAST_DECISION}"; then
|
|
68
|
+
pass "last proxy decision: ALLOWED via agenticros_rosbridge"
|
|
69
|
+
elif grep -q 'engine:ssrf' <<<"${LAST_DECISION}"; then
|
|
70
|
+
fail "last proxy decision: DENIED by SSRF guard — add allowed_ips to the policy. Saw: ${LAST_DECISION##*OCSF }"
|
|
71
|
+
elif grep -q 'engine:opa' <<<"${LAST_DECISION}"; then
|
|
72
|
+
fail "last proxy decision: DENIED by OPA — endpoint missing from agenticros_rosbridge. Saw: ${LAST_DECISION##*OCSF }"
|
|
73
|
+
else
|
|
74
|
+
warn "unrecognised proxy decision: ${LAST_DECISION##*OCSF }"
|
|
75
|
+
fi
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# ----- 5. live WebSocket roundtrip to /rosapi/topics through the proxy ------
|
|
79
|
+
GW_PID=$(docker exec "${CONTAINER}" pgrep -f openclaw-gateway 2>/dev/null | head -1 | tr -d '\r')
|
|
80
|
+
WS_PATH=$(docker exec "${CONTAINER}" sh -c 'ls -d /sandbox/agenticros/node_modules/.pnpm/ws@*/node_modules/ws 2>/dev/null | head -1' | tr -d '\r')
|
|
81
|
+
if [[ -z "${GW_PID}" ]] || [[ -z "${WS_PATH}" ]]; then
|
|
82
|
+
warn "skip WebSocket roundtrip — gateway pid=${GW_PID:-?} ws=${WS_PATH:-?}"
|
|
83
|
+
else
|
|
84
|
+
TOPICS_JSON=$(docker exec "${CONTAINER}" sh -c "nsenter --target ${GW_PID} --net -- node --input-type=commonjs -e '
|
|
85
|
+
const http=require(\"http\");
|
|
86
|
+
const WebSocket=require(\"${WS_PATH}\");
|
|
87
|
+
const agent=new http.Agent({keepAlive:false});
|
|
88
|
+
agent.createConnection=(opts,cb)=>{
|
|
89
|
+
const req=http.request({host:\"10.200.0.1\",port:3128,method:\"CONNECT\",path:opts.host+\":\"+opts.port,headers:{Host:opts.host+\":\"+opts.port}});
|
|
90
|
+
req.on(\"connect\",(res,sock)=>{ if(res.statusCode!==200){cb(new Error(\"proxy \"+res.statusCode));return;} cb(null,sock); });
|
|
91
|
+
req.on(\"error\",cb); req.end();
|
|
92
|
+
};
|
|
93
|
+
const ws=new WebSocket(\"ws://host.docker.internal:9090\",{agent});
|
|
94
|
+
ws.on(\"open\",()=>ws.send(JSON.stringify({op:\"call_service\",service:\"/rosapi/topics\",id:\"smoke\"})));
|
|
95
|
+
ws.on(\"message\",m=>{const o=JSON.parse(m.toString()); console.log(JSON.stringify({count:(o.values&&o.values.topics||[]).length, sample:(o.values&&o.values.topics||[]).slice(0,3)})); ws.close(); process.exit(0);});
|
|
96
|
+
ws.on(\"error\",e=>{console.error(\"ERR\",e.message); process.exit(1);});
|
|
97
|
+
setTimeout(()=>{console.error(\"timeout\"); process.exit(2);},6000);
|
|
98
|
+
' 2>&1" 2>/dev/null | tail -1)
|
|
99
|
+
if grep -qE '^\{"count":[0-9]+' <<<"${TOPICS_JSON}"; then
|
|
100
|
+
pass "WebSocket roundtrip: $(jq -r '"\(.count) topics, sample=\(.sample|join(", "))"' <<<"${TOPICS_JSON}" 2>/dev/null || echo "${TOPICS_JSON}")"
|
|
101
|
+
else
|
|
102
|
+
fail "WebSocket roundtrip failed: ${TOPICS_JSON:-<no output>}"
|
|
103
|
+
fi
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# ----- 6. NemoClaw dashboard reachable + non-empty --------------------------
|
|
107
|
+
DASH_URL=$(nemoclaw nemo dashboard-url --quiet 2>/dev/null | head -1 || true)
|
|
108
|
+
DASH_BASE=${DASH_URL%%#*}
|
|
109
|
+
if [[ -z "${DASH_BASE}" ]]; then
|
|
110
|
+
warn "dashboard URL not reported by nemoclaw (sandbox not Ready?)"
|
|
111
|
+
else
|
|
112
|
+
DASH_BYTES=$(curl -fsS "${DASH_BASE}" 2>/dev/null | wc -c | tr -d ' ')
|
|
113
|
+
if [[ -n "${DASH_BYTES}" ]] && [[ "${DASH_BYTES}" -gt 200 ]]; then
|
|
114
|
+
pass "dashboard at ${DASH_BASE} returns ${DASH_BYTES}-byte body"
|
|
115
|
+
echo " URL with token: ${DASH_URL}"
|
|
116
|
+
else
|
|
117
|
+
fail "dashboard at ${DASH_BASE} returned ${DASH_BYTES:-0} bytes — gateway crashed?"
|
|
118
|
+
fi
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
echo
|
|
122
|
+
echo "Summary: ${GREEN}${PASS} passed${RESET}, ${RED}${FAIL} failed${RESET}"
|
|
123
|
+
[[ ${FAIL} -eq 0 ]]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# start_demo.sh - Prepare the AgenticROS Claude Code demo (local DDS transport).
|
|
3
|
+
#
|
|
4
|
+
# What this does:
|
|
5
|
+
# 1. Sources ROS2 + the agenticros workspace
|
|
6
|
+
# 2. Launches the RealSense camera in the background (logs to /tmp)
|
|
7
|
+
# 3. Builds the @agenticros/claude-code MCP server
|
|
8
|
+
# 4. Starts the robot's motor controller via `robotics start motors`
|
|
9
|
+
#
|
|
10
|
+
# After this finishes, launch Claude Code from the repo root. The MCP server
|
|
11
|
+
# is auto-started by .mcp.json over stdio — nothing else to run on this host.
|
|
12
|
+
#
|
|
13
|
+
# Usage: ./scripts/start_demo.sh [jazzy|humble]
|
|
14
|
+
|
|
15
|
+
set -e
|
|
16
|
+
|
|
17
|
+
ROS_DISTRO="${1:-jazzy}"
|
|
18
|
+
REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
19
|
+
CAMERA_LOG=/tmp/agenticros-camera.log
|
|
20
|
+
CAMERA_PID_FILE=/tmp/agenticros-camera.pid
|
|
21
|
+
source "$REPO_ROOT/scripts/lib/agenticros-banner.sh"
|
|
22
|
+
|
|
23
|
+
agenticros_banner
|
|
24
|
+
echo "Starting AgenticROS Claude Code demo"
|
|
25
|
+
echo ""
|
|
26
|
+
|
|
27
|
+
echo "==> Sourcing ROS2 ($ROS_DISTRO) and agenticros workspace"
|
|
28
|
+
source "/opt/ros/$ROS_DISTRO/setup.bash"
|
|
29
|
+
if [[ -f "$REPO_ROOT/ros2_ws/install/setup.bash" ]]; then
|
|
30
|
+
source "$REPO_ROOT/ros2_ws/install/setup.bash"
|
|
31
|
+
else
|
|
32
|
+
echo " (ros2_ws is not built — run: cd ros2_ws && colcon build --symlink-install)"
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
echo "==> Starting RealSense camera (logs: $CAMERA_LOG)"
|
|
36
|
+
if [[ -f "$CAMERA_PID_FILE" ]] && kill -0 "$(cat "$CAMERA_PID_FILE")" 2>/dev/null; then
|
|
37
|
+
echo " Already running (pid $(cat "$CAMERA_PID_FILE")) — skipping"
|
|
38
|
+
elif pgrep -f "realsense2_camera_node" >/dev/null; then
|
|
39
|
+
echo " Detected an existing realsense2_camera_node — skipping"
|
|
40
|
+
else
|
|
41
|
+
nohup ros2 launch realsense2_camera rs_launch.py >"$CAMERA_LOG" 2>&1 &
|
|
42
|
+
echo $! >"$CAMERA_PID_FILE"
|
|
43
|
+
echo " Started (pid $(cat "$CAMERA_PID_FILE"))"
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
echo "==> Building @agenticros/claude-code MCP server"
|
|
47
|
+
cd "$REPO_ROOT"
|
|
48
|
+
pnpm --filter @agenticros/claude-code build
|
|
49
|
+
|
|
50
|
+
echo "==> Starting motor controller (robotics start motors)"
|
|
51
|
+
robotics start motors
|
|
52
|
+
|
|
53
|
+
echo ""
|
|
54
|
+
echo "Demo ready. Launch Claude Code from $REPO_ROOT — .mcp.json starts the MCP server."
|
|
55
|
+
echo "Stop the camera with: kill \$(cat $CAMERA_PID_FILE)"
|