agenticros 0.0.1 → 0.1.1
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 +179 -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 +15 -0
- package/dist/commands/down.d.ts.map +1 -0
- package/dist/commands/down.js +91 -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 +56 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/up.d.ts +20 -0
- package/dist/commands/up.d.ts.map +1 -0
- package/dist/commands/up.js +70 -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 +107 -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 +19 -0
- package/dist/runners/sim.d.ts.map +1 -0
- package/dist/runners/sim.js +53 -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 +406 -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/ros2_ws/src/agenticros_sim/CMakeLists.txt +24 -0
- package/runtime/ros2_ws/src/agenticros_sim/README.md +120 -0
- package/runtime/ros2_ws/src/agenticros_sim/config/agenticros-sim.config.json +28 -0
- package/runtime/ros2_ws/src/agenticros_sim/config/amr_bridge.yaml +111 -0
- package/runtime/ros2_ws/src/agenticros_sim/config/amr_view.rviz +172 -0
- package/runtime/ros2_ws/src/agenticros_sim/env-hooks/gz_resource_path.dsv.in +3 -0
- package/runtime/ros2_ws/src/agenticros_sim/env-hooks/gz_resource_path.sh.in +7 -0
- package/runtime/ros2_ws/src/agenticros_sim/launch/sim_amr.launch.py +159 -0
- package/runtime/ros2_ws/src/agenticros_sim/models/agenticros_amr/model.config +17 -0
- package/runtime/ros2_ws/src/agenticros_sim/models/agenticros_amr/model.sdf +244 -0
- package/runtime/ros2_ws/src/agenticros_sim/package.xml +27 -0
- package/runtime/ros2_ws/src/agenticros_sim/worlds/agenticros_indoor.sdf +183 -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/configure_for_sim.sh +64 -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/sim/run_sim.sh +146 -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-follow-me-sim.mjs +135 -0
- package/runtime/scripts/test-mcp-e2e.mjs +184 -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,333 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message conversion between plain JS objects and rclnodejs typed messages.
|
|
3
|
+
*
|
|
4
|
+
* The RosTransport interface works with `Record<string, unknown>`, but
|
|
5
|
+
* rclnodejs works with typed message class instances. This module bridges
|
|
6
|
+
* the two — analogous to rosbridge_library's `dict_to_msg` / `msg_to_dict`.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createRequire } from "node:module";
|
|
10
|
+
|
|
11
|
+
const require = createRequire(import.meta.url);
|
|
12
|
+
|
|
13
|
+
/** Cached message classes keyed by normalized type string. */
|
|
14
|
+
const typeCache = new Map<string, any>();
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the rclnodejs module. Uses createRequire because rclnodejs is CJS.
|
|
18
|
+
* Returns `any` — rclnodejs is an optional dependency and types may not be present.
|
|
19
|
+
*/
|
|
20
|
+
function getRclnodejs(): any {
|
|
21
|
+
return require("rclnodejs");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Normalize a ROS2 type string to the format rclnodejs expects.
|
|
26
|
+
* Accepts: "geometry_msgs/msg/Twist", "geometry_msgs/Twist", etc.
|
|
27
|
+
*/
|
|
28
|
+
function normalizeType(typeStr: string): string {
|
|
29
|
+
const parts = typeStr.split("/");
|
|
30
|
+
// Already fully qualified: "pkg/msg/Type" or "pkg/srv/Type" or "pkg/action/Type"
|
|
31
|
+
if (parts.length === 3) return typeStr;
|
|
32
|
+
// Short form: "pkg/Type" → assume msg
|
|
33
|
+
if (parts.length === 2) return `${parts[0]}/msg/${parts[1]}`;
|
|
34
|
+
return typeStr;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Load a ROS2 message/service/action class via rclnodejs, with caching.
|
|
39
|
+
*/
|
|
40
|
+
export function loadMessageClass(typeStr: string): any {
|
|
41
|
+
const normalized = normalizeType(typeStr);
|
|
42
|
+
const cached = typeCache.get(normalized);
|
|
43
|
+
if (cached) return cached;
|
|
44
|
+
|
|
45
|
+
const rclnodejs = getRclnodejs();
|
|
46
|
+
const cls = rclnodejs.require(normalized);
|
|
47
|
+
typeCache.set(normalized, cls);
|
|
48
|
+
return cls;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Convert a plain JS object to an rclnodejs message instance.
|
|
53
|
+
*
|
|
54
|
+
* Recursively assigns fields from `obj` onto a new message instance,
|
|
55
|
+
* handling nested sub-messages (e.g. Twist.linear is a Vector3).
|
|
56
|
+
*/
|
|
57
|
+
export function toRosMessage(typeStr: string, obj: Record<string, unknown>): any {
|
|
58
|
+
const MessageClass = loadMessageClass(typeStr);
|
|
59
|
+
const msg = new MessageClass();
|
|
60
|
+
assignFields(msg, obj);
|
|
61
|
+
return msg;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Recursively assign plain-object fields onto an rclnodejs message instance.
|
|
66
|
+
*/
|
|
67
|
+
function assignFields(target: any, source: Record<string, unknown>): void {
|
|
68
|
+
for (const [key, value] of Object.entries(source)) {
|
|
69
|
+
if (value === undefined || value === null) continue;
|
|
70
|
+
|
|
71
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
72
|
+
// Nested sub-message — the target field should already be initialized
|
|
73
|
+
// by rclnodejs with default values. Recurse into it.
|
|
74
|
+
if (target[key] !== undefined && target[key] !== null && typeof target[key] === "object") {
|
|
75
|
+
assignFields(target[key], value as Record<string, unknown>);
|
|
76
|
+
} else {
|
|
77
|
+
target[key] = value;
|
|
78
|
+
}
|
|
79
|
+
} else if (Array.isArray(value)) {
|
|
80
|
+
// Array field — could be primitives or nested messages.
|
|
81
|
+
// For nested message arrays, each element needs recursive assignment
|
|
82
|
+
// if the target has typed array elements. For now, assign directly —
|
|
83
|
+
// rclnodejs handles primitive arrays and typed arrays via setter coercion.
|
|
84
|
+
target[key] = value;
|
|
85
|
+
} else {
|
|
86
|
+
target[key] = value;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* True for message shapes whose `data` must stay as raw bytes.
|
|
93
|
+
* rclnodejs `toPlainObject()` often expands or mis-serializes `uint8[]` / sequences
|
|
94
|
+
* (e.g. sensor_msgs Image / CompressedImage), which breaks camera snapshot and similar tools.
|
|
95
|
+
*
|
|
96
|
+
* Use `in` / typeof — fields may be accessors on the prototype (not own properties).
|
|
97
|
+
*/
|
|
98
|
+
function isSensorImageLikeForExtraction(msg: any): boolean {
|
|
99
|
+
if (msg == null || typeof msg !== "object") return false;
|
|
100
|
+
if (!("data" in msg)) return false;
|
|
101
|
+
// sensor_msgs/msg/Image — PointCloud2 has width/height/data but no `encoding`.
|
|
102
|
+
// Width/height may be ref-wrapped in rclnodejs; only require presence + string encoding.
|
|
103
|
+
if (typeof msg.encoding === "string" && "width" in msg && "height" in msg) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
// sensor_msgs/msg/CompressedImage — `format` + `data`; no top-level `encoding` (unlike Image).
|
|
107
|
+
if (typeof msg.format === "string" && !(typeof msg.encoding === "string")) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** std_msgs/Header — read by name; stamp may be a nested ROS object. */
|
|
114
|
+
function copyHeaderField(header: any): Record<string, unknown> {
|
|
115
|
+
if (header == null || typeof header !== "object") return {};
|
|
116
|
+
const out: Record<string, unknown> = {};
|
|
117
|
+
if ("frame_id" in header) out.frame_id = header.frame_id;
|
|
118
|
+
if ("stamp" in header && header.stamp != null && typeof header.stamp === "object") {
|
|
119
|
+
const s = header.stamp;
|
|
120
|
+
const stamp: { sec?: number; nanosec?: number } = {};
|
|
121
|
+
if (typeof s.sec === "number" || typeof s.sec === "bigint") stamp.sec = Number(s.sec);
|
|
122
|
+
if (typeof s.nanosec === "number" || typeof s.nanosec === "bigint") {
|
|
123
|
+
stamp.nanosec = Number(s.nanosec);
|
|
124
|
+
}
|
|
125
|
+
out.stamp = stamp;
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** rclnodejs / ref-array `uint8[]` — numeric `.length` and indexed elements. */
|
|
131
|
+
function tryBufferFromArrayLike(value: unknown): Buffer | null {
|
|
132
|
+
if (value == null || typeof value !== "object") return null;
|
|
133
|
+
const v = value as Record<string, unknown> & { length?: unknown };
|
|
134
|
+
const len = v.length;
|
|
135
|
+
if (typeof len !== "number" || !Number.isFinite(len) || len < 0 || len > 200_000_000) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const anyVal = value as Record<number, unknown>;
|
|
140
|
+
const u8 = new Uint8Array(len);
|
|
141
|
+
for (let i = 0; i < len; i++) {
|
|
142
|
+
const el = anyVal[i];
|
|
143
|
+
const n = typeof el === "number" ? el : Number(el);
|
|
144
|
+
if (!Number.isFinite(n)) return null;
|
|
145
|
+
u8[i] = n & 0xff;
|
|
146
|
+
}
|
|
147
|
+
return Buffer.from(u8);
|
|
148
|
+
} catch {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function tryBufferFromIterable(value: unknown): Buffer | null {
|
|
154
|
+
if (value == null || typeof value !== "object") return null;
|
|
155
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return Buffer.from(value);
|
|
156
|
+
if (typeof (value as any)[Symbol.iterator] !== "function") return null;
|
|
157
|
+
try {
|
|
158
|
+
const arr = Uint8Array.from(value as Iterable<number>);
|
|
159
|
+
if (arr.length === 0) return null;
|
|
160
|
+
return Buffer.from(arr);
|
|
161
|
+
} catch {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Unwrap `data` for Image / CompressedImage (Buffer, views, JSON Buffer, nested `{ data }`). */
|
|
167
|
+
function coerceSensorImageDataField(value: unknown, depth = 0): unknown {
|
|
168
|
+
if (value == null || depth > 4) return value;
|
|
169
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) {
|
|
170
|
+
return Buffer.from(value);
|
|
171
|
+
}
|
|
172
|
+
if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView(value)) {
|
|
173
|
+
const view = value as ArrayBufferView;
|
|
174
|
+
return Buffer.from(view.buffer, view.byteOffset, view.byteLength);
|
|
175
|
+
}
|
|
176
|
+
if (Array.isArray(value)) return value;
|
|
177
|
+
if (typeof value === "object") {
|
|
178
|
+
const rec = value as Record<string, unknown>;
|
|
179
|
+
if (rec["type"] === "Buffer" && Array.isArray(rec["data"])) {
|
|
180
|
+
return coerceSensorImageDataField(rec["data"], depth + 1);
|
|
181
|
+
}
|
|
182
|
+
if ("data" in rec && rec["data"] !== undefined) {
|
|
183
|
+
return coerceSensorImageDataField(rec["data"], depth + 1);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const fromIterable = tryBufferFromIterable(value);
|
|
187
|
+
if (fromIterable !== null) return fromIterable;
|
|
188
|
+
const fromArrayLike = tryBufferFromArrayLike(value);
|
|
189
|
+
if (fromArrayLike !== null) return fromArrayLike;
|
|
190
|
+
return value;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Copy one field value from an rclnodejs message for plain-object consumers.
|
|
195
|
+
* Preserves byte blobs; recurses into typical nested ROS structs (not full generic graph).
|
|
196
|
+
*/
|
|
197
|
+
function copyValueForPlainTransport(value: any): unknown {
|
|
198
|
+
if (value === null || value === undefined) return value;
|
|
199
|
+
if (typeof value === "function") return undefined;
|
|
200
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) {
|
|
201
|
+
return Buffer.from(value);
|
|
202
|
+
}
|
|
203
|
+
if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView(value)) {
|
|
204
|
+
const view = value as ArrayBufferView;
|
|
205
|
+
return Buffer.from(view.buffer, view.byteOffset, view.byteLength);
|
|
206
|
+
}
|
|
207
|
+
if (Array.isArray(value)) {
|
|
208
|
+
return value.map((item: any) =>
|
|
209
|
+
typeof item === "object" && item !== null ? copyValueForPlainTransport(item) : item,
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
if (typeof value === "object") {
|
|
213
|
+
if (value.constructor && value.constructor.name !== "Object") {
|
|
214
|
+
return extractFields(value);
|
|
215
|
+
}
|
|
216
|
+
return value;
|
|
217
|
+
}
|
|
218
|
+
return value;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* rclnodejs often exposes Image/CompressedImage fields via prototype getters, so
|
|
223
|
+
* `Object.keys(msg)` is empty and `extractFields` produced `{}`. Read the known
|
|
224
|
+
* sensor_msgs field names explicitly.
|
|
225
|
+
*/
|
|
226
|
+
function extractSensorImageToPlain(msg: any): Record<string, unknown> {
|
|
227
|
+
const keys = [
|
|
228
|
+
"header",
|
|
229
|
+
"format",
|
|
230
|
+
"encoding",
|
|
231
|
+
"height",
|
|
232
|
+
"width",
|
|
233
|
+
"is_bigendian",
|
|
234
|
+
"step",
|
|
235
|
+
"data",
|
|
236
|
+
] as const;
|
|
237
|
+
const result: Record<string, unknown> = {};
|
|
238
|
+
for (const key of keys) {
|
|
239
|
+
if (!(key in msg)) continue;
|
|
240
|
+
const value = msg[key];
|
|
241
|
+
if (typeof value === "function") continue;
|
|
242
|
+
if (key === "header") {
|
|
243
|
+
result.header = copyHeaderField(value);
|
|
244
|
+
} else if (key === "data") {
|
|
245
|
+
result.data = coerceSensorImageDataField(value);
|
|
246
|
+
} else {
|
|
247
|
+
result[key] = copyValueForPlainTransport(value);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Convert an rclnodejs message instance to a plain JS object.
|
|
255
|
+
*
|
|
256
|
+
* Uses `toPlainObject()` if available (rclnodejs >= 0.21), otherwise
|
|
257
|
+
* falls back to manual recursive field extraction.
|
|
258
|
+
*/
|
|
259
|
+
export function fromRosMessage(msg: any, rosTypeHint?: string): Record<string, unknown> {
|
|
260
|
+
if (msg === null || msg === undefined) return {};
|
|
261
|
+
|
|
262
|
+
const hinted = rosTypeHint ? normalizeType(rosTypeHint) : "";
|
|
263
|
+
if (
|
|
264
|
+
hinted === "sensor_msgs/msg/Image" ||
|
|
265
|
+
hinted === "sensor_msgs/msg/CompressedImage"
|
|
266
|
+
) {
|
|
267
|
+
return extractSensorImageToPlain(msg);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (isSensorImageLikeForExtraction(msg)) {
|
|
271
|
+
return extractSensorImageToPlain(msg);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Preferred path: rclnodejs provides toPlainObject()
|
|
275
|
+
if (typeof msg.toPlainObject === "function") {
|
|
276
|
+
return msg.toPlainObject() as Record<string, unknown>;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Fallback: manual extraction
|
|
280
|
+
return extractFields(msg);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Recursively extract fields from an rclnodejs message into a plain object.
|
|
285
|
+
*/
|
|
286
|
+
function extractFields(msg: any): Record<string, unknown> {
|
|
287
|
+
if (msg === null || msg === undefined) return {};
|
|
288
|
+
if (typeof msg !== "object") return {};
|
|
289
|
+
|
|
290
|
+
const result: Record<string, unknown> = {};
|
|
291
|
+
|
|
292
|
+
// Get enumerable own properties
|
|
293
|
+
const keys = Object.keys(msg);
|
|
294
|
+
for (const key of keys) {
|
|
295
|
+
// Skip internal/private properties
|
|
296
|
+
if (key.startsWith("_")) continue;
|
|
297
|
+
|
|
298
|
+
const value = msg[key];
|
|
299
|
+
if (typeof value === "function") continue;
|
|
300
|
+
|
|
301
|
+
if (value === null || value === undefined) {
|
|
302
|
+
result[key] = value;
|
|
303
|
+
} else if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) {
|
|
304
|
+
// Keep raw byte blobs intact (sensor_msgs Image/CompressedImage `data`, etc.).
|
|
305
|
+
result[key] = Buffer.from(value);
|
|
306
|
+
} else if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView(value)) {
|
|
307
|
+
const view = value as ArrayBufferView;
|
|
308
|
+
result[key] = Buffer.from(view.buffer, view.byteOffset, view.byteLength);
|
|
309
|
+
} else if (Array.isArray(value)) {
|
|
310
|
+
result[key] = value.map((item: any) =>
|
|
311
|
+
typeof item === "object" && item !== null ? extractFields(item) : item,
|
|
312
|
+
);
|
|
313
|
+
} else if (typeof value === "object") {
|
|
314
|
+
// Check if it looks like a typed message (has constructor beyond Object)
|
|
315
|
+
if (value.constructor && value.constructor.name !== "Object") {
|
|
316
|
+
result[key] = extractFields(value);
|
|
317
|
+
} else {
|
|
318
|
+
result[key] = value;
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
result[key] = value;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return result;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Clear the type cache. Called during shutdown.
|
|
330
|
+
*/
|
|
331
|
+
export function clearTypeCache(): void {
|
|
332
|
+
typeCache.clear();
|
|
333
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entity cache for rclnodejs publishers, subscribers, and service clients.
|
|
3
|
+
*
|
|
4
|
+
* Lazily creates and caches DDS entities so repeated publishes to the same
|
|
5
|
+
* topic reuse a single publisher, etc. Same pattern as the reference agents'
|
|
6
|
+
* `_pubs`, `_subs`, `_srv_clients` maps.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { Subscription } from "../types.js";
|
|
10
|
+
import { loadMessageClass, fromRosMessage } from "./conversion.js";
|
|
11
|
+
|
|
12
|
+
type Node = any;
|
|
13
|
+
type MessageHandler = (msg: Record<string, unknown>) => void;
|
|
14
|
+
|
|
15
|
+
export class EntityCache {
|
|
16
|
+
private publishers = new Map<string, any>();
|
|
17
|
+
private subscriptions = new Map<string, { handle: any; handlers: Set<MessageHandler> }>();
|
|
18
|
+
private serviceClients = new Map<string, any>();
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get or create a cached publisher for the given topic and type.
|
|
22
|
+
*/
|
|
23
|
+
getPublisher(node: Node, topic: string, typeStr: string): any {
|
|
24
|
+
const key = `${topic}::${typeStr}`;
|
|
25
|
+
const cached = this.publishers.get(key);
|
|
26
|
+
if (cached) return cached;
|
|
27
|
+
|
|
28
|
+
const MessageClass = loadMessageClass(typeStr);
|
|
29
|
+
const publisher = node.createPublisher(MessageClass, topic);
|
|
30
|
+
this.publishers.set(key, publisher);
|
|
31
|
+
return publisher;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Subscribe to a topic. If already subscribed, adds the handler to the
|
|
36
|
+
* existing subscription's handler set. Returns a Subscription handle.
|
|
37
|
+
*/
|
|
38
|
+
addSubscription(
|
|
39
|
+
node: Node,
|
|
40
|
+
topic: string,
|
|
41
|
+
typeStr: string,
|
|
42
|
+
handler: MessageHandler,
|
|
43
|
+
): Subscription {
|
|
44
|
+
const key = `${topic}::${typeStr}`;
|
|
45
|
+
let entry = this.subscriptions.get(key);
|
|
46
|
+
|
|
47
|
+
if (!entry) {
|
|
48
|
+
const MessageClass = loadMessageClass(typeStr);
|
|
49
|
+
const handlers = new Set<MessageHandler>();
|
|
50
|
+
|
|
51
|
+
const handle = node.createSubscription(
|
|
52
|
+
MessageClass,
|
|
53
|
+
topic,
|
|
54
|
+
(msg: any) => {
|
|
55
|
+
const plain = fromRosMessage(msg, typeStr);
|
|
56
|
+
for (const h of handlers) {
|
|
57
|
+
h(plain);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
entry = { handle, handlers };
|
|
63
|
+
this.subscriptions.set(key, entry);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
entry.handlers.add(handler);
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
unsubscribe: () => {
|
|
70
|
+
entry!.handlers.delete(handler);
|
|
71
|
+
// If no more handlers, destroy the subscription
|
|
72
|
+
if (entry!.handlers.size === 0) {
|
|
73
|
+
try {
|
|
74
|
+
node.destroySubscription(entry!.handle);
|
|
75
|
+
} catch {
|
|
76
|
+
// Already destroyed
|
|
77
|
+
}
|
|
78
|
+
this.subscriptions.delete(key);
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get or create a cached service client for the given service and type.
|
|
86
|
+
*/
|
|
87
|
+
getServiceClient(node: Node, service: string, typeStr: string): any {
|
|
88
|
+
const key = `${service}::${typeStr}`;
|
|
89
|
+
const cached = this.serviceClients.get(key);
|
|
90
|
+
if (cached) return cached;
|
|
91
|
+
|
|
92
|
+
const ServiceClass = loadMessageClass(typeStr);
|
|
93
|
+
const client = node.createClient(ServiceClass, service);
|
|
94
|
+
this.serviceClients.set(key, client);
|
|
95
|
+
return client;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Destroy all cached entities. Called during transport shutdown.
|
|
100
|
+
*/
|
|
101
|
+
destroyAll(node: Node): void {
|
|
102
|
+
for (const pub of this.publishers.values()) {
|
|
103
|
+
try {
|
|
104
|
+
node.destroyPublisher(pub);
|
|
105
|
+
} catch {
|
|
106
|
+
// Best-effort cleanup
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
this.publishers.clear();
|
|
110
|
+
|
|
111
|
+
for (const { handle } of this.subscriptions.values()) {
|
|
112
|
+
try {
|
|
113
|
+
node.destroySubscription(handle);
|
|
114
|
+
} catch {
|
|
115
|
+
// Best-effort cleanup
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
this.subscriptions.clear();
|
|
119
|
+
|
|
120
|
+
for (const client of this.serviceClients.values()) {
|
|
121
|
+
try {
|
|
122
|
+
node.destroyClient(client);
|
|
123
|
+
} catch {
|
|
124
|
+
// Best-effort cleanup
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
this.serviceClients.clear();
|
|
128
|
+
}
|
|
129
|
+
}
|