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.
Files changed (330) hide show
  1. package/LICENSE +192 -0
  2. package/README.md +90 -4
  3. package/dist/commands/config.d.ts +20 -0
  4. package/dist/commands/config.d.ts.map +1 -0
  5. package/dist/commands/config.js +179 -0
  6. package/dist/commands/config.js.map +1 -0
  7. package/dist/commands/doctor.d.ts +33 -0
  8. package/dist/commands/doctor.d.ts.map +1 -0
  9. package/dist/commands/doctor.js +232 -0
  10. package/dist/commands/doctor.js.map +1 -0
  11. package/dist/commands/down.d.ts +15 -0
  12. package/dist/commands/down.d.ts.map +1 -0
  13. package/dist/commands/down.js +91 -0
  14. package/dist/commands/down.js.map +1 -0
  15. package/dist/commands/init.d.ts +21 -0
  16. package/dist/commands/init.d.ts.map +1 -0
  17. package/dist/commands/init.js +259 -0
  18. package/dist/commands/init.js.map +1 -0
  19. package/dist/commands/logs.d.ts +18 -0
  20. package/dist/commands/logs.d.ts.map +1 -0
  21. package/dist/commands/logs.js +67 -0
  22. package/dist/commands/logs.js.map +1 -0
  23. package/dist/commands/status.d.ts +12 -0
  24. package/dist/commands/status.d.ts.map +1 -0
  25. package/dist/commands/status.js +56 -0
  26. package/dist/commands/status.js.map +1 -0
  27. package/dist/commands/up.d.ts +20 -0
  28. package/dist/commands/up.d.ts.map +1 -0
  29. package/dist/commands/up.js +70 -0
  30. package/dist/commands/up.js.map +1 -0
  31. package/dist/index.d.ts +12 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +107 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/menu.d.ts +9 -0
  36. package/dist/menu.d.ts.map +1 -0
  37. package/dist/menu.js +96 -0
  38. package/dist/menu.js.map +1 -0
  39. package/dist/runners/real-robot.d.ts +15 -0
  40. package/dist/runners/real-robot.d.ts.map +1 -0
  41. package/dist/runners/real-robot.js +46 -0
  42. package/dist/runners/real-robot.js.map +1 -0
  43. package/dist/runners/sim.d.ts +19 -0
  44. package/dist/runners/sim.d.ts.map +1 -0
  45. package/dist/runners/sim.js +53 -0
  46. package/dist/runners/sim.js.map +1 -0
  47. package/dist/util/env.d.ts +24 -0
  48. package/dist/util/env.d.ts.map +1 -0
  49. package/dist/util/env.js +53 -0
  50. package/dist/util/env.js.map +1 -0
  51. package/dist/util/logger.d.ts +24 -0
  52. package/dist/util/logger.d.ts.map +1 -0
  53. package/dist/util/logger.js +62 -0
  54. package/dist/util/logger.js.map +1 -0
  55. package/dist/util/paths.d.ts +57 -0
  56. package/dist/util/paths.d.ts.map +1 -0
  57. package/dist/util/paths.js +132 -0
  58. package/dist/util/paths.js.map +1 -0
  59. package/dist/util/pidfile.d.ts +16 -0
  60. package/dist/util/pidfile.d.ts.map +1 -0
  61. package/dist/util/pidfile.js +63 -0
  62. package/dist/util/pidfile.js.map +1 -0
  63. package/dist/util/state.d.ts +26 -0
  64. package/dist/util/state.d.ts.map +1 -0
  65. package/dist/util/state.js +55 -0
  66. package/dist/util/state.js.map +1 -0
  67. package/package.json +60 -1
  68. package/runtime/BUNDLE.json +11 -0
  69. package/runtime/LICENSE +192 -0
  70. package/runtime/README.md +273 -0
  71. package/runtime/docs/architecture.md +366 -0
  72. package/runtime/docs/cli.md +140 -0
  73. package/runtime/docs/memory.md +292 -0
  74. package/runtime/docs/robot-setup.md +347 -0
  75. package/runtime/package.json +28 -0
  76. package/runtime/packages/agenticros/agenticros-agenticros-0.0.1.tgz +0 -0
  77. package/runtime/packages/agenticros/openclaw.plugin.json +451 -0
  78. package/runtime/packages/agenticros/package.json +41 -0
  79. package/runtime/packages/agenticros/src/camera-snapshot-cache.ts +59 -0
  80. package/runtime/packages/agenticros/src/camera-snapshot-routes.ts +44 -0
  81. package/runtime/packages/agenticros/src/commands/estop.ts +41 -0
  82. package/runtime/packages/agenticros/src/commands/transport.ts +195 -0
  83. package/runtime/packages/agenticros/src/config-file.ts +136 -0
  84. package/runtime/packages/agenticros/src/config-page.ts +498 -0
  85. package/runtime/packages/agenticros/src/context/robot-context.ts +373 -0
  86. package/runtime/packages/agenticros/src/depth.ts +313 -0
  87. package/runtime/packages/agenticros/src/describer.ts +157 -0
  88. package/runtime/packages/agenticros/src/image-binary-trim.ts +16 -0
  89. package/runtime/packages/agenticros/src/index.ts +85 -0
  90. package/runtime/packages/agenticros/src/landing-page.ts +38 -0
  91. package/runtime/packages/agenticros/src/memory.ts +44 -0
  92. package/runtime/packages/agenticros/src/plugin-api.ts +173 -0
  93. package/runtime/packages/agenticros/src/plugin-image-base64.ts +69 -0
  94. package/runtime/packages/agenticros/src/preflight.ts +110 -0
  95. package/runtime/packages/agenticros/src/routes.ts +328 -0
  96. package/runtime/packages/agenticros/src/safety/validator.ts +43 -0
  97. package/runtime/packages/agenticros/src/service.ts +359 -0
  98. package/runtime/packages/agenticros/src/skill-api.ts +65 -0
  99. package/runtime/packages/agenticros/src/skill-loader.ts +146 -0
  100. package/runtime/packages/agenticros/src/teleop/page.ts +498 -0
  101. package/runtime/packages/agenticros/src/teleop/routes.ts +650 -0
  102. package/runtime/packages/agenticros/src/tools/index.ts +26 -0
  103. package/runtime/packages/agenticros/src/tools/ros2-action.ts +50 -0
  104. package/runtime/packages/agenticros/src/tools/ros2-camera.ts +221 -0
  105. package/runtime/packages/agenticros/src/tools/ros2-depth-distance.ts +58 -0
  106. package/runtime/packages/agenticros/src/tools/ros2-introspect.ts +62 -0
  107. package/runtime/packages/agenticros/src/tools/ros2-memory.ts +158 -0
  108. package/runtime/packages/agenticros/src/tools/ros2-param.ts +87 -0
  109. package/runtime/packages/agenticros/src/tools/ros2-publish.ts +52 -0
  110. package/runtime/packages/agenticros/src/tools/ros2-service.ts +46 -0
  111. package/runtime/packages/agenticros/src/tools/ros2-subscribe.ts +71 -0
  112. package/runtime/packages/agenticros/tsconfig.json +9 -0
  113. package/runtime/packages/agenticros-claude-code/README.md +260 -0
  114. package/runtime/packages/agenticros-claude-code/config.example.json +9 -0
  115. package/runtime/packages/agenticros-claude-code/dist/config.d.ts +8 -0
  116. package/runtime/packages/agenticros-claude-code/dist/config.d.ts.map +1 -0
  117. package/runtime/packages/agenticros-claude-code/dist/config.js +93 -0
  118. package/runtime/packages/agenticros-claude-code/dist/config.js.map +1 -0
  119. package/runtime/packages/agenticros-claude-code/dist/depth.d.ts +20 -0
  120. package/runtime/packages/agenticros-claude-code/dist/depth.d.ts.map +1 -0
  121. package/runtime/packages/agenticros-claude-code/dist/depth.js +126 -0
  122. package/runtime/packages/agenticros-claude-code/dist/depth.js.map +1 -0
  123. package/runtime/packages/agenticros-claude-code/dist/find-object/coco-classes.d.ts +6 -0
  124. package/runtime/packages/agenticros-claude-code/dist/find-object/coco-classes.d.ts.map +1 -0
  125. package/runtime/packages/agenticros-claude-code/dist/find-object/coco-classes.js +36 -0
  126. package/runtime/packages/agenticros-claude-code/dist/find-object/coco-classes.js.map +1 -0
  127. package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.d.ts +33 -0
  128. package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.d.ts.map +1 -0
  129. package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.js +134 -0
  130. package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.js.map +1 -0
  131. package/runtime/packages/agenticros-claude-code/dist/follow-me/controller.d.ts +43 -0
  132. package/runtime/packages/agenticros-claude-code/dist/follow-me/controller.d.ts.map +1 -0
  133. package/runtime/packages/agenticros-claude-code/dist/follow-me/controller.js +73 -0
  134. package/runtime/packages/agenticros-claude-code/dist/follow-me/controller.js.map +1 -0
  135. package/runtime/packages/agenticros-claude-code/dist/follow-me/detector.d.ts +58 -0
  136. package/runtime/packages/agenticros-claude-code/dist/follow-me/detector.d.ts.map +1 -0
  137. package/runtime/packages/agenticros-claude-code/dist/follow-me/detector.js +251 -0
  138. package/runtime/packages/agenticros-claude-code/dist/follow-me/detector.js.map +1 -0
  139. package/runtime/packages/agenticros-claude-code/dist/follow-me/loop.d.ts +61 -0
  140. package/runtime/packages/agenticros-claude-code/dist/follow-me/loop.d.ts.map +1 -0
  141. package/runtime/packages/agenticros-claude-code/dist/follow-me/loop.js +268 -0
  142. package/runtime/packages/agenticros-claude-code/dist/follow-me/loop.js.map +1 -0
  143. package/runtime/packages/agenticros-claude-code/dist/index.d.ts +3 -0
  144. package/runtime/packages/agenticros-claude-code/dist/index.d.ts.map +1 -0
  145. package/runtime/packages/agenticros-claude-code/dist/index.js +111 -0
  146. package/runtime/packages/agenticros-claude-code/dist/index.js.map +1 -0
  147. package/runtime/packages/agenticros-claude-code/dist/memory.d.ts +17 -0
  148. package/runtime/packages/agenticros-claude-code/dist/memory.d.ts.map +1 -0
  149. package/runtime/packages/agenticros-claude-code/dist/memory.js +44 -0
  150. package/runtime/packages/agenticros-claude-code/dist/memory.js.map +1 -0
  151. package/runtime/packages/agenticros-claude-code/dist/safety.d.ts +10 -0
  152. package/runtime/packages/agenticros-claude-code/dist/safety.d.ts.map +1 -0
  153. package/runtime/packages/agenticros-claude-code/dist/safety.js +34 -0
  154. package/runtime/packages/agenticros-claude-code/dist/safety.js.map +1 -0
  155. package/runtime/packages/agenticros-claude-code/dist/tools.d.ts +36 -0
  156. package/runtime/packages/agenticros-claude-code/dist/tools.d.ts.map +1 -0
  157. package/runtime/packages/agenticros-claude-code/dist/tools.js +777 -0
  158. package/runtime/packages/agenticros-claude-code/dist/tools.js.map +1 -0
  159. package/runtime/packages/agenticros-claude-code/dist/transport.d.ts +17 -0
  160. package/runtime/packages/agenticros-claude-code/dist/transport.d.ts.map +1 -0
  161. package/runtime/packages/agenticros-claude-code/dist/transport.js +46 -0
  162. package/runtime/packages/agenticros-claude-code/dist/transport.js.map +1 -0
  163. package/runtime/packages/agenticros-claude-code/dist/zero-shot/detector.d.ts +42 -0
  164. package/runtime/packages/agenticros-claude-code/dist/zero-shot/detector.d.ts.map +1 -0
  165. package/runtime/packages/agenticros-claude-code/dist/zero-shot/detector.js +114 -0
  166. package/runtime/packages/agenticros-claude-code/dist/zero-shot/detector.js.map +1 -0
  167. package/runtime/packages/agenticros-claude-code/package.json +29 -0
  168. package/runtime/packages/agenticros-claude-code/src/config.ts +96 -0
  169. package/runtime/packages/agenticros-claude-code/src/depth.ts +173 -0
  170. package/runtime/packages/agenticros-claude-code/src/find-object/coco-classes.ts +38 -0
  171. package/runtime/packages/agenticros-claude-code/src/find-object/find-object.ts +190 -0
  172. package/runtime/packages/agenticros-claude-code/src/follow-me/controller.ts +109 -0
  173. package/runtime/packages/agenticros-claude-code/src/follow-me/depth-loop.ts +420 -0
  174. package/runtime/packages/agenticros-claude-code/src/follow-me/detector.ts +303 -0
  175. package/runtime/packages/agenticros-claude-code/src/follow-me/loop.ts +330 -0
  176. package/runtime/packages/agenticros-claude-code/src/index.ts +125 -0
  177. package/runtime/packages/agenticros-claude-code/src/memory.ts +51 -0
  178. package/runtime/packages/agenticros-claude-code/src/safety.ts +44 -0
  179. package/runtime/packages/agenticros-claude-code/src/tools.ts +891 -0
  180. package/runtime/packages/agenticros-claude-code/src/transport.ts +58 -0
  181. package/runtime/packages/agenticros-claude-code/src/zero-shot/detector.ts +169 -0
  182. package/runtime/packages/agenticros-claude-code/tsconfig.json +9 -0
  183. package/runtime/packages/agenticros-claude-code/yolo-debug.mjs +106 -0
  184. package/runtime/packages/agenticros-gemini/README.md +139 -0
  185. package/runtime/packages/agenticros-gemini/package.json +28 -0
  186. package/runtime/packages/agenticros-gemini/scripts/smoke-api.mjs +42 -0
  187. package/runtime/packages/agenticros-gemini/src/chat.ts +139 -0
  188. package/runtime/packages/agenticros-gemini/src/config.ts +92 -0
  189. package/runtime/packages/agenticros-gemini/src/depth.ts +173 -0
  190. package/runtime/packages/agenticros-gemini/src/index.ts +58 -0
  191. package/runtime/packages/agenticros-gemini/src/memory.ts +32 -0
  192. package/runtime/packages/agenticros-gemini/src/safety.ts +44 -0
  193. package/runtime/packages/agenticros-gemini/src/tools.ts +516 -0
  194. package/runtime/packages/agenticros-gemini/src/transport.ts +58 -0
  195. package/runtime/packages/agenticros-gemini/tsconfig.json +8 -0
  196. package/runtime/packages/core/package.json +47 -0
  197. package/runtime/packages/core/src/banner.ts +32 -0
  198. package/runtime/packages/core/src/cmd-vel-twist.ts +31 -0
  199. package/runtime/packages/core/src/config.ts +279 -0
  200. package/runtime/packages/core/src/index.ts +54 -0
  201. package/runtime/packages/core/src/memory/__tests__/factory.test.ts +70 -0
  202. package/runtime/packages/core/src/memory/__tests__/local-provider.test.ts +195 -0
  203. package/runtime/packages/core/src/memory/__tests__/mem0-provider.test.ts +192 -0
  204. package/runtime/packages/core/src/memory/__tests__/smart-defaults.test.ts +46 -0
  205. package/runtime/packages/core/src/memory/factory.ts +63 -0
  206. package/runtime/packages/core/src/memory/index.ts +10 -0
  207. package/runtime/packages/core/src/memory/local/provider.ts +229 -0
  208. package/runtime/packages/core/src/memory/mem0/provider.ts +379 -0
  209. package/runtime/packages/core/src/memory/types.ts +96 -0
  210. package/runtime/packages/core/src/topic-utils.ts +95 -0
  211. package/runtime/packages/core/src/transport/factory.ts +47 -0
  212. package/runtime/packages/core/src/transport/local/conversion.ts +333 -0
  213. package/runtime/packages/core/src/transport/local/entities.ts +129 -0
  214. package/runtime/packages/core/src/transport/local/transport.ts +406 -0
  215. package/runtime/packages/core/src/transport/rosbridge/actions.ts +81 -0
  216. package/runtime/packages/core/src/transport/rosbridge/adapter.ts +157 -0
  217. package/runtime/packages/core/src/transport/rosbridge/client.ts +438 -0
  218. package/runtime/packages/core/src/transport/rosbridge/services.ts +41 -0
  219. package/runtime/packages/core/src/transport/rosbridge/topics.ts +60 -0
  220. package/runtime/packages/core/src/transport/rosbridge/types.ts +118 -0
  221. package/runtime/packages/core/src/transport/transport.ts +77 -0
  222. package/runtime/packages/core/src/transport/types.ts +137 -0
  223. package/runtime/packages/core/src/transport/webrtc/signaling-client.ts +196 -0
  224. package/runtime/packages/core/src/transport/webrtc/signaling-types.ts +130 -0
  225. package/runtime/packages/core/src/transport/webrtc/transport.ts +516 -0
  226. package/runtime/packages/core/src/transport/zenoh/adapter.ts +357 -0
  227. package/runtime/packages/core/src/transport/zenoh/cdr.ts +183 -0
  228. package/runtime/packages/core/src/transport/zenoh/keys.ts +51 -0
  229. package/runtime/packages/core/tsconfig.json +9 -0
  230. package/runtime/packages/ros-camera/package.json +30 -0
  231. package/runtime/packages/ros-camera/src/index.ts +13 -0
  232. package/runtime/packages/ros-camera/src/snapshot.ts +372 -0
  233. package/runtime/packages/ros-camera/tsconfig.json +9 -0
  234. package/runtime/pnpm-lock.yaml +5260 -0
  235. package/runtime/pnpm-workspace.yaml +2 -0
  236. package/runtime/ros2_ws/src/agenticros_agent/agenticros_agent/__init__.py +0 -0
  237. package/runtime/ros2_ws/src/agenticros_agent/agenticros_agent/agent_node.py +561 -0
  238. package/runtime/ros2_ws/src/agenticros_agent/package.xml +25 -0
  239. package/runtime/ros2_ws/src/agenticros_agent/resource/agenticros_agent +0 -0
  240. package/runtime/ros2_ws/src/agenticros_agent/setup.cfg +4 -0
  241. package/runtime/ros2_ws/src/agenticros_agent/setup.py +25 -0
  242. package/runtime/ros2_ws/src/agenticros_bringup/README.md +128 -0
  243. package/runtime/ros2_ws/src/agenticros_bringup/agenticros_bringup/__init__.py +1 -0
  244. package/runtime/ros2_ws/src/agenticros_bringup/agenticros_bringup/cmd_vel_relay.py +33 -0
  245. package/runtime/ros2_ws/src/agenticros_bringup/launch/cmd_vel_bridge.launch.py +58 -0
  246. package/runtime/ros2_ws/src/agenticros_bringup/launch/gazebo_turtlebot3.launch.py +69 -0
  247. package/runtime/ros2_ws/src/agenticros_bringup/launch/mode_a_gazebo.launch.py +55 -0
  248. package/runtime/ros2_ws/src/agenticros_bringup/launch/mode_a_gazebo_rviz.launch.py +48 -0
  249. package/runtime/ros2_ws/src/agenticros_bringup/launch/realsense_rosbridge.launch.py +154 -0
  250. package/runtime/ros2_ws/src/agenticros_bringup/launch/rosbridge_gazebo.launch.py +54 -0
  251. package/runtime/ros2_ws/src/agenticros_bringup/launch/rviz.launch.py +38 -0
  252. package/runtime/ros2_ws/src/agenticros_bringup/launch/turtlebot3_gazebo_rviz.launch.py +42 -0
  253. package/runtime/ros2_ws/src/agenticros_bringup/package.xml +24 -0
  254. package/runtime/ros2_ws/src/agenticros_bringup/resource/agenticros_bringup +0 -0
  255. package/runtime/ros2_ws/src/agenticros_bringup/rviz/turtlebot3_agenticros.rviz +174 -0
  256. package/runtime/ros2_ws/src/agenticros_bringup/setup.cfg +4 -0
  257. package/runtime/ros2_ws/src/agenticros_bringup/setup.py +28 -0
  258. package/runtime/ros2_ws/src/agenticros_discovery/agenticros_discovery/__init__.py +0 -0
  259. package/runtime/ros2_ws/src/agenticros_discovery/agenticros_discovery/discovery_node.py +172 -0
  260. package/runtime/ros2_ws/src/agenticros_discovery/package.xml +22 -0
  261. package/runtime/ros2_ws/src/agenticros_discovery/resource/agenticros_discovery +0 -0
  262. package/runtime/ros2_ws/src/agenticros_discovery/setup.cfg +5 -0
  263. package/runtime/ros2_ws/src/agenticros_discovery/setup.py +25 -0
  264. package/runtime/ros2_ws/src/agenticros_follow_me/README.md +66 -0
  265. package/runtime/ros2_ws/src/agenticros_follow_me/agenticros_follow_me/__init__.py +1 -0
  266. package/runtime/ros2_ws/src/agenticros_follow_me/agenticros_follow_me/__main__.py +5 -0
  267. package/runtime/ros2_ws/src/agenticros_follow_me/agenticros_follow_me/follow_me_node.py +278 -0
  268. package/runtime/ros2_ws/src/agenticros_follow_me/agenticros_follow_me/follower_controller.py +631 -0
  269. package/runtime/ros2_ws/src/agenticros_follow_me/agenticros_follow_me/person_tracker.py +635 -0
  270. package/runtime/ros2_ws/src/agenticros_follow_me/package.xml +22 -0
  271. package/runtime/ros2_ws/src/agenticros_follow_me/resource/agenticros_follow_me +0 -0
  272. package/runtime/ros2_ws/src/agenticros_follow_me/setup.py +25 -0
  273. package/runtime/ros2_ws/src/agenticros_msgs/CMakeLists.txt +26 -0
  274. package/runtime/ros2_ws/src/agenticros_msgs/msg/CapabilityManifest.msg +9 -0
  275. package/runtime/ros2_ws/src/agenticros_msgs/package.xml +22 -0
  276. package/runtime/ros2_ws/src/agenticros_msgs/srv/FollowMeGetStatus.srv +11 -0
  277. package/runtime/ros2_ws/src/agenticros_msgs/srv/FollowMeSetDistance.srv +4 -0
  278. package/runtime/ros2_ws/src/agenticros_msgs/srv/FollowMeSetTarget.srv +6 -0
  279. package/runtime/ros2_ws/src/agenticros_msgs/srv/FollowMeStart.srv +5 -0
  280. package/runtime/ros2_ws/src/agenticros_msgs/srv/FollowMeStop.srv +3 -0
  281. package/runtime/ros2_ws/src/agenticros_msgs/srv/GetCapabilities.srv +5 -0
  282. package/runtime/ros2_ws/src/agenticros_sim/CMakeLists.txt +24 -0
  283. package/runtime/ros2_ws/src/agenticros_sim/README.md +120 -0
  284. package/runtime/ros2_ws/src/agenticros_sim/config/agenticros-sim.config.json +28 -0
  285. package/runtime/ros2_ws/src/agenticros_sim/config/amr_bridge.yaml +111 -0
  286. package/runtime/ros2_ws/src/agenticros_sim/config/amr_view.rviz +172 -0
  287. package/runtime/ros2_ws/src/agenticros_sim/env-hooks/gz_resource_path.dsv.in +3 -0
  288. package/runtime/ros2_ws/src/agenticros_sim/env-hooks/gz_resource_path.sh.in +7 -0
  289. package/runtime/ros2_ws/src/agenticros_sim/launch/sim_amr.launch.py +159 -0
  290. package/runtime/ros2_ws/src/agenticros_sim/models/agenticros_amr/model.config +17 -0
  291. package/runtime/ros2_ws/src/agenticros_sim/models/agenticros_amr/model.sdf +244 -0
  292. package/runtime/ros2_ws/src/agenticros_sim/package.xml +27 -0
  293. package/runtime/ros2_ws/src/agenticros_sim/worlds/agenticros_indoor.sdf +183 -0
  294. package/runtime/scripts/activate_workspace.sh +285 -0
  295. package/runtime/scripts/agenticros-describer.policy.yaml +96 -0
  296. package/runtime/scripts/agenticros-proxy.cjs +99 -0
  297. package/runtime/scripts/agenticros-rosbridge.policy.yaml +62 -0
  298. package/runtime/scripts/check-cli-tarball-size.mjs +42 -0
  299. package/runtime/scripts/configure_agenticros.sh +200 -0
  300. package/runtime/scripts/configure_for_sim.sh +64 -0
  301. package/runtime/scripts/fix-openclaw-control-ui-path.sh +20 -0
  302. package/runtime/scripts/install_cli.sh +94 -0
  303. package/runtime/scripts/install_rosbridge_from_source.sh +67 -0
  304. package/runtime/scripts/lib/agenticros-banner.sh +28 -0
  305. package/runtime/scripts/onboard_robot.sh +75 -0
  306. package/runtime/scripts/openai.policy.yaml +77 -0
  307. package/runtime/scripts/openclaw-dashboard-url.cjs +49 -0
  308. package/runtime/scripts/pack-runtime.mjs +245 -0
  309. package/runtime/scripts/run_demo_native.sh +43 -0
  310. package/runtime/scripts/run_nemoclaw_host_stack.sh +91 -0
  311. package/runtime/scripts/run_robot_rosbridge.sh +36 -0
  312. package/runtime/scripts/sandbox_rosbridge_relay.py +137 -0
  313. package/runtime/scripts/setup-openclaw-local.cjs +75 -0
  314. package/runtime/scripts/setup_gateway_plugin.sh +329 -0
  315. package/runtime/scripts/setup_robot.sh +113 -0
  316. package/runtime/scripts/setup_workspace.sh +484 -0
  317. package/runtime/scripts/sim/run_sim.sh +146 -0
  318. package/runtime/scripts/smoke_test_nemoclaw.sh +123 -0
  319. package/runtime/scripts/start_demo.sh +55 -0
  320. package/runtime/scripts/sync-skill-tools.mjs +335 -0
  321. package/runtime/scripts/test-follow-me-sim.mjs +135 -0
  322. package/runtime/scripts/test-mcp-e2e.mjs +184 -0
  323. package/runtime/scripts/test-rclnodejs.mts +129 -0
  324. package/runtime/scripts/use-openclaw-2026.2.26.sh +19 -0
  325. package/runtime/scripts/use-openclaw-2026.3.11.sh +19 -0
  326. package/runtime/scripts/zenoh-bridge-ros2dds-robot.json5 +30 -0
  327. package/runtime/scripts/zenohd-agenticros.json5 +11 -0
  328. package/runtime/scripts/zenohd-rosclaw.json5 +11 -0
  329. package/runtime/tsconfig.base.json +19 -0
  330. package/index.js +0 -6
@@ -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)"
@@ -0,0 +1,335 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * sync-skill-tools.mjs
4
+ *
5
+ * Discover AgenticROS skill tool names and merge them into the agenticros plugin's
6
+ * `contracts.tools` allowlist in `packages/agenticros/openclaw.plugin.json`.
7
+ *
8
+ * OpenClaw 2026+ enforces `contracts.tools` as a strict allowlist: any tool that a
9
+ * plugin registers at runtime but that is not declared in the manifest is rejected
10
+ * with `plugin must declare contracts.tools for: <name>` and silently dropped.
11
+ * Since AgenticROS skills register their own tools dynamically (e.g. `follow_robot`),
12
+ * the manifest must list every skill tool that should be exposed.
13
+ *
14
+ * How it works
15
+ * ------------
16
+ * 1. Resolve the OpenClaw config (OPENCLAW_CONFIG or ~/.openclaw/openclaw.json).
17
+ * 2. Read `plugins.entries.agenticros.config.skillPaths` and `.skillPackages`.
18
+ * 3. For each entry, locate the skill's built entry (dist/index.js), import it,
19
+ * and call `registerSkill(api, config, context)` with a stub `api` whose
20
+ * `registerTool` is a spy that just records `tool.name`.
21
+ * 4. Merge the discovered tool names with the static core tool list and write
22
+ * them back into `packages/agenticros/openclaw.plugin.json`.
23
+ *
24
+ * Usage
25
+ * -----
26
+ * node scripts/sync-skill-tools.mjs # write the manifest
27
+ * node scripts/sync-skill-tools.mjs --dry-run # print what would change
28
+ * node scripts/sync-skill-tools.mjs --verbose # show per-skill discovery details
29
+ *
30
+ * Run this whenever you add, remove, or rebuild a skill in `skillPaths` /
31
+ * `skillPackages`. After it succeeds, refresh the OpenClaw plugin registry
32
+ * (`openclaw plugins registry --refresh`) and restart the gateway so OpenClaw
33
+ * re-reads the updated `contracts.tools`.
34
+ */
35
+
36
+ import { readFileSync, writeFileSync, existsSync } from "node:fs";
37
+ import { join, resolve, dirname, isAbsolute } from "node:path";
38
+ import { homedir } from "node:os";
39
+ import { pathToFileURL, fileURLToPath } from "node:url";
40
+ import { createRequire } from "node:module";
41
+
42
+ const __filename = fileURLToPath(import.meta.url);
43
+ const __dirname = dirname(__filename);
44
+ const REPO_ROOT = resolve(__dirname, "..");
45
+ const MANIFEST_PATH = join(REPO_ROOT, "packages/agenticros/openclaw.plugin.json");
46
+
47
+ const args = new Set(process.argv.slice(2));
48
+ const DRY_RUN = args.has("--dry-run") || args.has("-n");
49
+ const VERBOSE = args.has("--verbose") || args.has("-v");
50
+
51
+ const CORE_TOOLS = [
52
+ "ros2_publish",
53
+ "ros2_subscribe_once",
54
+ "ros2_service_call",
55
+ "ros2_action_goal",
56
+ "ros2_param_get",
57
+ "ros2_param_set",
58
+ "ros2_list_topics",
59
+ "ros2_camera_snapshot",
60
+ "ros2_depth_distance",
61
+ // Memory tools (registered conditionally at runtime when memory.enabled=true).
62
+ // Listed here so they remain in the allowlist after sync-skill-tools rewrites it.
63
+ "memory_remember",
64
+ "memory_recall",
65
+ "memory_forget",
66
+ "memory_status",
67
+ ];
68
+
69
+ function log(...m) {
70
+ console.log("[sync-skill-tools]", ...m);
71
+ }
72
+ function vlog(...m) {
73
+ if (VERBOSE) console.log("[sync-skill-tools]", ...m);
74
+ }
75
+ function warn(...m) {
76
+ console.warn("[sync-skill-tools] WARN:", ...m);
77
+ }
78
+ function fail(msg) {
79
+ console.error("[sync-skill-tools] ERROR:", msg);
80
+ process.exit(1);
81
+ }
82
+
83
+ function getOpenClawConfigPath() {
84
+ const env = process.env.OPENCLAW_CONFIG;
85
+ if (env && env.length > 0) return resolve(env);
86
+ return join(homedir(), ".openclaw", "openclaw.json");
87
+ }
88
+
89
+ function readOpenClawConfig() {
90
+ const p = getOpenClawConfigPath();
91
+ if (!existsSync(p)) {
92
+ warn(`OpenClaw config not found: ${p} — assuming no skills configured.`);
93
+ return null;
94
+ }
95
+ try {
96
+ return JSON.parse(readFileSync(p, "utf8"));
97
+ } catch (e) {
98
+ fail(`Cannot parse ${p}: ${e?.message ?? e}`);
99
+ }
100
+ }
101
+
102
+ function getSkillEntries(cfg) {
103
+ const skillPaths = cfg?.plugins?.entries?.agenticros?.config?.skillPaths ?? [];
104
+ const skillPackages = cfg?.plugins?.entries?.agenticros?.config?.skillPackages ?? [];
105
+ return { skillPaths, skillPackages };
106
+ }
107
+
108
+ function findSkillEntryFromPath(dirPath) {
109
+ if (!existsSync(dirPath)) {
110
+ warn(`skillPaths entry does not exist: ${dirPath}`);
111
+ return null;
112
+ }
113
+ const pkgPath = join(dirPath, "package.json");
114
+ if (!existsSync(pkgPath)) {
115
+ warn(`skillPaths entry missing package.json: ${dirPath}`);
116
+ return null;
117
+ }
118
+ let pkg;
119
+ try {
120
+ pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
121
+ } catch (e) {
122
+ warn(`Invalid package.json in ${dirPath}: ${e?.message ?? e}`);
123
+ return null;
124
+ }
125
+ if (!pkg.agenticrosSkill) {
126
+ warn(`Not an AgenticROS skill (missing agenticrosSkill flag): ${dirPath}`);
127
+ return null;
128
+ }
129
+ const main = pkg.main ?? "index.js";
130
+ const entry = join(dirPath, main);
131
+ if (!existsSync(entry)) {
132
+ warn(`Skill entry not built (run pnpm build in the skill repo): ${entry}`);
133
+ return null;
134
+ }
135
+ return { entry, packageName: pkg.name ?? dirPath, packageJson: pkg };
136
+ }
137
+
138
+ function resolvePackageEntry(packageName) {
139
+ if (!packageName || packageName.trim() === "") return null;
140
+ if (packageName.includes(" ")) {
141
+ warn(`Invalid skillPackages entry (contains spaces): "${packageName}"`);
142
+ return null;
143
+ }
144
+ try {
145
+ const req = createRequire(join(REPO_ROOT, "package.json"));
146
+ const entry = req.resolve(packageName);
147
+ return entry;
148
+ } catch {
149
+ warn(`Skill package not resolvable from repo root: ${packageName}`);
150
+ return null;
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Create a stub OpenClawPluginApi that captures registerTool calls.
156
+ * Other methods are no-ops so that registerSkill can complete without crashing.
157
+ */
158
+ function createSpyApi() {
159
+ const tools = [];
160
+ const noop = () => {};
161
+ const noopLog = {
162
+ info: (m) => vlog(" skill.logger.info:", m),
163
+ warn: (m) => vlog(" skill.logger.warn:", m),
164
+ error: (m) => vlog(" skill.logger.error:", m),
165
+ };
166
+ return {
167
+ tools,
168
+ api: {
169
+ pluginConfig: {},
170
+ logger: noopLog,
171
+ registerTool(tool) {
172
+ if (tool && typeof tool.name === "string" && tool.name.length > 0) {
173
+ tools.push(tool.name);
174
+ }
175
+ },
176
+ registerService: noop,
177
+ registerCommand: noop,
178
+ registerHttpRoute: noop,
179
+ on: noop,
180
+ },
181
+ };
182
+ }
183
+
184
+ function createStubContext() {
185
+ return {
186
+ getTransport() {
187
+ throw new Error("stub: getTransport not available during contract discovery");
188
+ },
189
+ getDepthDistance() {
190
+ return Promise.resolve({ valid: false, distance_m: 0 });
191
+ },
192
+ getDepthSectors() {
193
+ return Promise.resolve({ valid: false, left_m: 0, center_m: 0, right_m: 0 });
194
+ },
195
+ logger: {
196
+ info: () => {},
197
+ warn: () => {},
198
+ error: () => {},
199
+ },
200
+ };
201
+ }
202
+
203
+ async function discoverSkillTools(entryPath, packageName) {
204
+ const url = pathToFileURL(entryPath).href;
205
+ let mod;
206
+ try {
207
+ mod = await import(url);
208
+ } catch (e) {
209
+ warn(`Failed to import ${packageName} (${entryPath}): ${e?.message ?? e}`);
210
+ return [];
211
+ }
212
+ const registerSkill =
213
+ mod.registerSkill ?? mod.default?.registerSkill ?? mod.default;
214
+ if (typeof registerSkill !== "function") {
215
+ warn(`${packageName}: no registerSkill export — skipping discovery`);
216
+ return [];
217
+ }
218
+ const { tools, api } = createSpyApi();
219
+ const ctx = createStubContext();
220
+ // Provide a config skeleton that matches AgenticROSConfig defaults loosely
221
+ // enough that registration doesn't crash on access paths like config.skills.x.
222
+ const stubConfig = {
223
+ transport: { mode: "rosbridge" },
224
+ robot: { name: "Robot", namespace: "", cameraTopic: "" },
225
+ teleop: { cmdVelTopic: "", cameraTopic: "", speedDefault: 0.3, cameraPollMs: 150 },
226
+ safety: { maxLinearVelocity: 1, maxAngularVelocity: 1.5 },
227
+ skills: {},
228
+ skillPaths: [],
229
+ skillPackages: [],
230
+ };
231
+ try {
232
+ await Promise.resolve(registerSkill(api, stubConfig, ctx));
233
+ } catch (e) {
234
+ warn(
235
+ `${packageName} registerSkill threw during discovery — captured ${tools.length} tools before error: ${e?.message ?? e}`,
236
+ );
237
+ }
238
+ return tools;
239
+ }
240
+
241
+ function uniqueOrdered(...lists) {
242
+ const seen = new Set();
243
+ const out = [];
244
+ for (const list of lists) {
245
+ for (const name of list) {
246
+ if (typeof name !== "string") continue;
247
+ const trimmed = name.trim();
248
+ if (!trimmed || seen.has(trimmed)) continue;
249
+ seen.add(trimmed);
250
+ out.push(trimmed);
251
+ }
252
+ }
253
+ return out;
254
+ }
255
+
256
+ function arraysEqual(a, b) {
257
+ if (a.length !== b.length) return false;
258
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
259
+ return true;
260
+ }
261
+
262
+ async function main() {
263
+ if (!existsSync(MANIFEST_PATH)) fail(`Manifest not found: ${MANIFEST_PATH}`);
264
+ const manifestRaw = readFileSync(MANIFEST_PATH, "utf8");
265
+ let manifest;
266
+ try {
267
+ manifest = JSON.parse(manifestRaw);
268
+ } catch (e) {
269
+ fail(`Cannot parse manifest: ${e?.message ?? e}`);
270
+ }
271
+
272
+ const cfg = readOpenClawConfig();
273
+ const { skillPaths, skillPackages } = cfg ? getSkillEntries(cfg) : { skillPaths: [], skillPackages: [] };
274
+
275
+ log(`Resolved OpenClaw config: ${getOpenClawConfigPath()}`);
276
+ log(`skillPaths: ${skillPaths.length === 0 ? "(none)" : skillPaths.join(", ")}`);
277
+ log(`skillPackages: ${skillPackages.length === 0 ? "(none)" : skillPackages.join(", ")}`);
278
+
279
+ const discovered = new Map(); // skillId/packageName -> tools[]
280
+
281
+ for (const pkg of skillPackages) {
282
+ const entry = resolvePackageEntry(pkg);
283
+ if (!entry) continue;
284
+ vlog(`Resolving package "${pkg}" → ${entry}`);
285
+ const tools = await discoverSkillTools(entry, pkg);
286
+ if (tools.length > 0) discovered.set(pkg, tools);
287
+ else vlog(` no tools discovered for ${pkg}`);
288
+ }
289
+
290
+ for (const dir of skillPaths) {
291
+ const absDir = isAbsolute(dir) ? dir : resolve(REPO_ROOT, dir);
292
+ const resolved = findSkillEntryFromPath(absDir);
293
+ if (!resolved) continue;
294
+ vlog(`Resolving path "${absDir}" → ${resolved.entry} (${resolved.packageName})`);
295
+ const tools = await discoverSkillTools(resolved.entry, resolved.packageName);
296
+ if (tools.length > 0) discovered.set(resolved.packageName, tools);
297
+ else vlog(` no tools discovered for ${resolved.packageName}`);
298
+ }
299
+
300
+ if (discovered.size === 0) {
301
+ log("No skill tools discovered. contracts.tools will contain only core tools.");
302
+ } else {
303
+ for (const [name, tools] of discovered.entries()) {
304
+ log(`Discovered ${tools.length} tool(s) from ${name}: ${tools.join(", ")}`);
305
+ }
306
+ }
307
+
308
+ const skillTools = [...discovered.values()].flat();
309
+ const merged = uniqueOrdered(CORE_TOOLS, skillTools);
310
+ const previous = Array.isArray(manifest?.contracts?.tools)
311
+ ? manifest.contracts.tools.slice()
312
+ : [];
313
+
314
+ if (arraysEqual(previous, merged)) {
315
+ log("Manifest is already up to date.");
316
+ return;
317
+ }
318
+
319
+ log(`Updating contracts.tools:\n before: [${previous.join(", ")}]\n after: [${merged.join(", ")}]`);
320
+
321
+ if (DRY_RUN) {
322
+ log("Dry run — manifest not modified.");
323
+ return;
324
+ }
325
+
326
+ manifest.contracts = manifest.contracts ?? {};
327
+ manifest.contracts.tools = merged;
328
+ writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2) + "\n", "utf8");
329
+ log(`Wrote ${MANIFEST_PATH}`);
330
+ log("Next steps:");
331
+ log(" 1. openclaw plugins registry --refresh");
332
+ log(" 2. Restart the OpenClaw gateway so the new contracts take effect.");
333
+ }
334
+
335
+ main().catch((e) => fail(e?.stack ?? String(e)));
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Drive ros2_follow_me_start (mode=depth) against the AMR sim.
4
+ *
5
+ * Sequence:
6
+ * 1. start follow-me in depth mode
7
+ * 2. poll status every 1.5s for 15s, capturing detection events
8
+ * 3. stop follow-me
9
+ * 4. send a zero cmd_vel just in case
10
+ *
11
+ * Reports: did the depth loop see a target, what distance/lateral did it pick,
12
+ * how many cmd_vel commands were issued.
13
+ */
14
+
15
+ import { spawn } from "node:child_process";
16
+ import { fileURLToPath } from "node:url";
17
+ import { dirname, join, resolve } from "node:path";
18
+
19
+ const __dirname = dirname(fileURLToPath(import.meta.url));
20
+ const repoRoot = resolve(__dirname, "..");
21
+ const serverDist = join(repoRoot, "packages/agenticros-claude-code/dist/index.js");
22
+
23
+ const child = spawn(process.execPath, [serverDist], {
24
+ stdio: ["pipe", "pipe", "pipe"],
25
+ env: { ...process.env },
26
+ });
27
+
28
+ child.stderr.on("data", (d) => {
29
+ process.stderr.write(`[mcp-stderr] ${d}`);
30
+ });
31
+
32
+ let nextId = 1;
33
+ const pending = new Map();
34
+ let buf = "";
35
+
36
+ child.stdout.on("data", (chunk) => {
37
+ buf += chunk.toString();
38
+ let nl;
39
+ while ((nl = buf.indexOf("\n")) !== -1) {
40
+ const line = buf.slice(0, nl).trim();
41
+ buf = buf.slice(nl + 1);
42
+ if (!line) continue;
43
+ let msg;
44
+ try {
45
+ msg = JSON.parse(line);
46
+ } catch {
47
+ continue;
48
+ }
49
+ if (msg.id !== undefined && pending.has(msg.id)) {
50
+ const { resolve, reject } = pending.get(msg.id);
51
+ pending.delete(msg.id);
52
+ if (msg.error) reject(new Error(msg.error.message));
53
+ else resolve(msg.result);
54
+ }
55
+ }
56
+ });
57
+
58
+ function rpc(method, params = {}, timeoutMs = 15000) {
59
+ const id = nextId++;
60
+ return new Promise((resolveOuter, reject) => {
61
+ const t = setTimeout(() => {
62
+ pending.delete(id);
63
+ reject(new Error(`Timeout: ${method}`));
64
+ }, timeoutMs);
65
+ pending.set(id, {
66
+ resolve: (v) => {
67
+ clearTimeout(t);
68
+ resolveOuter(v);
69
+ },
70
+ reject: (e) => {
71
+ clearTimeout(t);
72
+ reject(e);
73
+ },
74
+ });
75
+ child.stdin.write(JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n");
76
+ });
77
+ }
78
+
79
+ function pickText(result) {
80
+ return result?.content?.map((c) => c.text ?? "").join("\n") ?? "";
81
+ }
82
+
83
+ async function main() {
84
+ console.log("=== follow_me (depth) E2E ===");
85
+
86
+ await rpc("initialize", {
87
+ protocolVersion: "2024-11-05",
88
+ capabilities: { tools: {} },
89
+ clientInfo: { name: "fm-e2e", version: "0.0.1" },
90
+ });
91
+ await rpc("notifications/initialized", {}).catch(() => {});
92
+
93
+ console.log("\n-- start follow_me mode=depth --");
94
+ const start = await rpc("tools/call", {
95
+ name: "ros2_follow_me_start",
96
+ arguments: { mode: "depth", targetDistance: 1.5 },
97
+ });
98
+ console.log(pickText(start));
99
+
100
+ console.log("\n-- poll status for 15s --");
101
+ const polls = [];
102
+ for (let i = 0; i < 10; i++) {
103
+ await new Promise((r) => setTimeout(r, 1500));
104
+ const s = await rpc("tools/call", { name: "ros2_follow_me_status", arguments: {} });
105
+ const text = pickText(s);
106
+ polls.push({ t: (i + 1) * 1.5, text });
107
+ console.log(`t+${((i + 1) * 1.5).toFixed(1)}s :: ${text.replace(/\s+/g, " ").slice(0, 200)}`);
108
+ }
109
+
110
+ console.log("\n-- stop follow_me --");
111
+ const stop = await rpc("tools/call", {
112
+ name: "ros2_follow_me_stop",
113
+ arguments: {},
114
+ });
115
+ console.log(pickText(stop));
116
+
117
+ console.log("\n-- safety zero-twist --");
118
+ await rpc("tools/call", {
119
+ name: "ros2_publish",
120
+ arguments: {
121
+ topic: "/cmd_vel",
122
+ type: "geometry_msgs/msg/Twist",
123
+ message: { linear: { x: 0, y: 0, z: 0 }, angular: { x: 0, y: 0, z: 0 } },
124
+ },
125
+ });
126
+
127
+ child.kill("SIGTERM");
128
+ console.log("\n=== Done ===");
129
+ }
130
+
131
+ main().catch((e) => {
132
+ console.error("Failed:", e);
133
+ child.kill("SIGKILL");
134
+ process.exit(1);
135
+ });