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,50 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import type { OpenClawPluginApi } from "../plugin-api.js";
3
+ import type { AgenticROSConfig } from "@agenticros/core";
4
+ import { toNamespacedTopic } from "@agenticros/core";
5
+ import { getTransport } from "../service.js";
6
+
7
+ /**
8
+ * Register the ros2_action_goal tool with the AI agent.
9
+ * Sends action goals with progress feedback streaming.
10
+ */
11
+ export function registerActionTool(api: OpenClawPluginApi, config: AgenticROSConfig): void {
12
+ api.registerTool({
13
+ name: "ros2_action_goal",
14
+ label: "ROS2 Action Goal",
15
+ description:
16
+ "Send a goal to a ROS2 action server and stream feedback. " +
17
+ "Use this for long-running operations like navigation or arm movements.",
18
+ parameters: Type.Object({
19
+ action: Type.String({ description: "The ROS2 action server name (e.g., '/navigate_to_pose')" }),
20
+ actionType: Type.String({ description: "The ROS2 action type (e.g., 'nav2_msgs/action/NavigateToPose')" }),
21
+ goal: Type.Record(Type.String(), Type.Unknown(), {
22
+ description: "The action goal parameters",
23
+ }),
24
+ }),
25
+
26
+ async execute(_toolCallId, params) {
27
+ const rawAction = params["action"] as string;
28
+ const action = toNamespacedTopic(config, rawAction);
29
+ const actionType = params["actionType"] as string;
30
+ const goal = params["goal"] as Record<string, unknown>;
31
+
32
+ const transport = getTransport();
33
+ const actionResult = await transport.sendActionGoal({
34
+ action,
35
+ actionType,
36
+ args: goal,
37
+ });
38
+
39
+ const result = {
40
+ success: actionResult.result,
41
+ action,
42
+ result: actionResult.values,
43
+ };
44
+ return {
45
+ content: [{ type: "text", text: JSON.stringify(result) }],
46
+ details: result,
47
+ };
48
+ },
49
+ });
50
+ }
@@ -0,0 +1,221 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import type { OpenClawPluginApi } from "../plugin-api.js";
3
+ import type { AgenticROSConfig } from "@agenticros/core";
4
+ import { resolveCameraSubscribeTopic } from "@agenticros/core";
5
+ import {
6
+ ROS_MSG_COMPRESSED_IMAGE,
7
+ ROS_MSG_IMAGE,
8
+ cameraSnapshotFromPlainMessage,
9
+ mimeTypeForSnapshotBase64,
10
+ rosNumericField,
11
+ } from "@agenticros/ros-camera";
12
+ import { getTransport } from "../service.js";
13
+ import { normalizePluginToolImageBase64 } from "../plugin-image-base64.js";
14
+ import { trimJpegToLastEoi } from "../image-binary-trim.js";
15
+ import { storeCameraSnapshot } from "../camera-snapshot-cache.js";
16
+ import { describeImageBestEffort } from "../describer.js";
17
+
18
+ /** Known camera topic patterns for common setups (e.g. RealSense). */
19
+ export const REALSENSE_CAMERA_TOPICS = {
20
+ color_compressed: "/camera/camera/color/image_raw/compressed",
21
+ color_raw: "/camera/camera/color/image_raw",
22
+ depth_raw: "/camera/camera/depth/image_rect_raw",
23
+ aligned_depth: "/camera/camera/aligned_depth_to_color/image_raw",
24
+ } as const;
25
+
26
+ /**
27
+ * Register the ros2_camera_snapshot tool with the AI agent.
28
+ * Grabs a single frame from a ROS2 camera topic.
29
+ * Supports CompressedImage (default) and raw Image (e.g. RealSense color/depth).
30
+ */
31
+ export function registerCameraTool(api: OpenClawPluginApi, config: AgenticROSConfig): void {
32
+ const describerEnabled = config.describer?.enabled === true;
33
+ const baseDescription =
34
+ "Capture a single image from a ROS2 camera topic. Returns a structured image block for the chat UI (plus a short text summary). " +
35
+ "Use when the user asks what the robot sees or requests a photo. " +
36
+ "Do not paste raw base64 or data: URLs in your reply—describe the scene from the image you receive. " +
37
+ "The tool also embeds an HTTP snapshot link in the text (same kind of URL as teleop) for the chat UI. " +
38
+ "Supports sensor_msgs/CompressedImage (e.g. /camera/image_raw/compressed, optional zstd) and sensor_msgs/Image (raw encodings are encoded to PNG).";
39
+ const describerHint =
40
+ " A `Vision description:` section is appended automatically to the result text when a vision describer is configured; " +
41
+ "treat that paragraph as the authoritative description of what the camera sees and quote/paraphrase it in your reply.";
42
+
43
+ api.registerTool({
44
+ name: "ros2_camera_snapshot",
45
+ label: "ROS2 Camera Snapshot",
46
+ description: describerEnabled ? baseDescription + describerHint : baseDescription,
47
+ parameters: Type.Object({
48
+ topic: Type.Optional(
49
+ Type.String({
50
+ description:
51
+ "Camera image topic. Examples: '/camera/image_raw/compressed', RealSense color '/camera/camera/color/image_raw', RealSense depth '/camera/camera/depth/image_rect_raw'. Default: '/camera/image_raw/compressed'.",
52
+ }),
53
+ ),
54
+ message_type: Type.Optional(
55
+ Type.Union(
56
+ [
57
+ Type.Literal("CompressedImage"),
58
+ Type.Literal("Image"),
59
+ ],
60
+ {
61
+ description:
62
+ "Message type: 'CompressedImage' for JPEG/PNG topics (default), 'Image' for raw sensor_msgs/Image (e.g. RealSense color/depth).",
63
+ },
64
+ ),
65
+ ),
66
+ timeout: Type.Optional(Type.Number({ description: "Timeout in milliseconds (default: 10000)" })),
67
+ }),
68
+
69
+ async execute(_toolCallId, params) {
70
+ const defaultTopic =
71
+ (config.robot?.cameraTopic ?? "").trim() || "/camera/camera/color/image_raw/compressed";
72
+ const rawTopic = (params["topic"] as string | undefined) ?? defaultTopic;
73
+ const topic = resolveCameraSubscribeTopic(config, rawTopic);
74
+ const rawMsgType = params["message_type"] as string | undefined;
75
+ const messageType: "CompressedImage" | "Image" =
76
+ rawMsgType === "Image" ? "Image" : "CompressedImage";
77
+ const timeout = (params["timeout"] as number | undefined) ?? 10000;
78
+
79
+ try {
80
+ const transport = getTransport();
81
+ const typeSel = messageType === "Image" ? ROS_MSG_IMAGE : ROS_MSG_COMPRESSED_IMAGE;
82
+
83
+ const result = await new Promise<{
84
+ success: boolean;
85
+ topic: string;
86
+ format: string;
87
+ data: string;
88
+ width?: unknown;
89
+ height?: unknown;
90
+ }>((resolve, reject) => {
91
+ let subscription: { unsubscribe: () => void };
92
+ let timer: ReturnType<typeof setTimeout>;
93
+ try {
94
+ subscription = transport.subscribe({ topic, type: typeSel }, (msg: Record<string, unknown>) => {
95
+ try {
96
+ clearTimeout(timer);
97
+ subscription.unsubscribe();
98
+ const payload = cameraSnapshotFromPlainMessage(messageType, msg);
99
+ resolve({
100
+ success: true,
101
+ topic,
102
+ format: payload.formatLabel,
103
+ data: payload.dataBase64,
104
+ width: payload.width,
105
+ height: payload.height,
106
+ });
107
+ } catch (err) {
108
+ clearTimeout(timer);
109
+ try {
110
+ subscription.unsubscribe();
111
+ } catch {
112
+ // ignore
113
+ }
114
+ reject(err instanceof Error ? err : new Error(String(err)));
115
+ }
116
+ });
117
+ } catch (err) {
118
+ reject(err instanceof Error ? err : new Error(String(err)));
119
+ return;
120
+ }
121
+ timer = setTimeout(() => {
122
+ try {
123
+ subscription.unsubscribe();
124
+ } catch {
125
+ // ignore
126
+ }
127
+ reject(new Error(`Timeout waiting for camera frame on ${topic}`));
128
+ }, timeout);
129
+ });
130
+
131
+ const rawB64 = (result.data as string) ?? "";
132
+ let base64 = normalizePluginToolImageBase64(rawB64);
133
+ const formatLabel = String((result.format as string) ?? "jpeg").toLowerCase();
134
+ let mimeType = base64 ? mimeTypeForSnapshotBase64(base64, formatLabel) : "image/jpeg";
135
+
136
+ let buf: Buffer | null = base64 ? Buffer.from(base64, "base64") : null;
137
+ if (buf && buf.length >= 2 && buf[0] === 0xff && buf[1] === 0xd8) {
138
+ buf = trimJpegToLastEoi(buf);
139
+ base64 = buf.toString("base64");
140
+ mimeType = mimeTypeForSnapshotBase64(base64, formatLabel);
141
+ }
142
+
143
+ const wNum =
144
+ result.width != null ? rosNumericField(result.width, "width") : undefined;
145
+ const hNum =
146
+ result.height != null ? rosNumericField(result.height, "height") : undefined;
147
+ let summary = `Captured one frame from ${topic}${wNum != null && hNum != null ? ` (${wNum}×${hNum})` : ""}.`;
148
+
149
+ let snapshotId: string | undefined;
150
+ const minDecodedBytes = 80;
151
+ const decodedLen = buf ? buf.length : 0;
152
+ if (buf && decodedLen >= minDecodedBytes) {
153
+ try {
154
+ snapshotId = storeCameraSnapshot(buf, mimeType);
155
+ } catch {
156
+ /* ignore oversized / cache errors */
157
+ }
158
+ }
159
+ if (snapshotId) {
160
+ const snapPath = `/plugins/agenticros/camera/snapshot?id=${encodeURIComponent(snapshotId)}`;
161
+ const origin = (process.env.AGENTICROS_GATEWAY_PUBLIC_URL ?? "").trim().replace(/\/$/, "");
162
+ const snapUrl = origin ? `${origin}${snapPath}` : snapPath;
163
+ summary += `\n\n![camera snapshot](${snapUrl})`;
164
+ }
165
+
166
+ if (
167
+ config.describer?.enabled === true &&
168
+ base64 &&
169
+ buf &&
170
+ decodedLen >= minDecodedBytes
171
+ ) {
172
+ try {
173
+ const described = await describeImageBestEffort({
174
+ config,
175
+ base64,
176
+ mimeType,
177
+ logger: api.logger,
178
+ });
179
+ if (described) {
180
+ summary += `\n\n**Vision description** (auto-generated by ${described.model} in ${described.latencyMs}ms — quote or paraphrase this when reporting what the robot sees):\n${described.description.trim()}`;
181
+ } else {
182
+ summary +=
183
+ "\n\n_(Vision description was requested but the describer endpoint did not respond — the camera image was captured successfully; see the snapshot link above. Report this to the operator if the user needs a description.)_";
184
+ }
185
+ } catch {
186
+ /* describeImageBestEffort never throws; this is just defense in depth */
187
+ }
188
+ }
189
+
190
+ const content: Array<
191
+ { type: "text"; text: string } | { type: "image"; data: string; mimeType: string }
192
+ > = [{ type: "text", text: summary }];
193
+ if (base64 && buf && decodedLen >= minDecodedBytes) {
194
+ content.push({ type: "image", data: base64, mimeType });
195
+ } else if (rawB64 && (!base64 || decodedLen < minDecodedBytes)) {
196
+ content.push({
197
+ type: "text",
198
+ text:
199
+ " (Image payload was missing, not valid base64 after normalization, or too small—check topic, message_type, or transport.)",
200
+ });
201
+ } else if (!rawB64) {
202
+ content.push({
203
+ type: "text",
204
+ text: " (No image data received—topic may be idle or transport returned empty.)",
205
+ });
206
+ }
207
+
208
+ return {
209
+ content,
210
+ details: { success: result.success, topic, width: result.width, height: result.height },
211
+ };
212
+ } catch (err) {
213
+ const msg = err instanceof Error ? err.message : String(err);
214
+ return {
215
+ content: [{ type: "text", text: `ros2_camera_snapshot failed: ${msg}` }],
216
+ details: { success: false, topic: rawTopic, error: msg },
217
+ };
218
+ }
219
+ },
220
+ });
221
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Tool to read distance (meters) from a ROS2 depth image topic (e.g. RealSense).
3
+ * Use when the user asks "how far am I" or "distance to the robot" / "distance from the robot".
4
+ */
5
+
6
+ import { Type } from "@sinclair/typebox";
7
+ import type { OpenClawPluginApi } from "../plugin-api.js";
8
+ import type { AgenticROSConfig } from "@agenticros/core";
9
+ import { toNamespacedTopic } from "@agenticros/core";
10
+ import { getTransport } from "../service.js";
11
+ import { getDepthDistance } from "../depth.js";
12
+ import { REALSENSE_CAMERA_TOPICS } from "./ros2-camera.js";
13
+
14
+ const DEFAULT_DEPTH_TOPIC = REALSENSE_CAMERA_TOPICS.depth_raw;
15
+
16
+ export function registerDepthDistanceTool(api: OpenClawPluginApi, config: AgenticROSConfig): void {
17
+ api.registerTool({
18
+ name: "ros2_depth_distance",
19
+ label: "ROS2 depth distance",
20
+ description:
21
+ "Get distance in meters from the robot's depth camera (e.g. RealSense). " +
22
+ "Samples the center of the depth image and returns distance biased toward nearer pixels (~12th percentile), not median (median often tracks walls when the person only covers part of the patch). " +
23
+ "Use when the user asks how far they are from the robot, or distance to/from the robot.",
24
+
25
+ parameters: Type.Object({
26
+ topic: Type.Optional(
27
+ Type.String({
28
+ description: `Depth image topic (sensor_msgs/Image, 16UC1 or 32FC1). Default: ${DEFAULT_DEPTH_TOPIC}.`,
29
+ }),
30
+ ),
31
+ timeout: Type.Optional(Type.Number({ description: "Timeout in ms (default 5000)" })),
32
+ }),
33
+
34
+ async execute(_toolCallId, params) {
35
+ const rawTopic = (params["topic"] as string | undefined)?.trim() || DEFAULT_DEPTH_TOPIC;
36
+ const topic = toNamespacedTopic(config, rawTopic);
37
+ const timeout = (params["timeout"] as number | undefined) ?? 5000;
38
+
39
+ try {
40
+ const transport = getTransport();
41
+ const result = await getDepthDistance(transport, topic, timeout);
42
+ const text = result.valid
43
+ ? `Distance at center (~12th percentile, nearer surfaces): **${result.distance_m} m** (median in same patch: ${result.median_m} m; range ${result.min_m}–${result.max_m} m; ${result.sample_count} pixels). Topic: ${result.topic}.`
44
+ : `No valid depth in center region (topic: ${result.topic}, ${result.width}×${result.height}, encoding ${result.encoding}). The scene may be out of range or obscured.`;
45
+ return {
46
+ content: [{ type: "text" as const, text }],
47
+ details: result,
48
+ };
49
+ } catch (err) {
50
+ const message = err instanceof Error ? err.message : String(err);
51
+ return {
52
+ content: [{ type: "text" as const, text: `Depth distance failed: ${message}` }],
53
+ details: { success: false, error: message, topic },
54
+ };
55
+ }
56
+ },
57
+ });
58
+ }
@@ -0,0 +1,62 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import type { OpenClawPluginApi } from "../plugin-api.js";
3
+ import { getTransport } from "../service.js";
4
+
5
+ /**
6
+ * Register the ros2_list_topics tool with the AI agent.
7
+ * Allows the agent to discover available ROS2 topics at runtime.
8
+ */
9
+ export function registerIntrospectTool(api: OpenClawPluginApi): void {
10
+ api.registerTool({
11
+ name: "ros2_list_topics",
12
+ label: "ROS2 List Topics",
13
+ description:
14
+ "List ROS 2 topics seen by the transport (authoritative for this moment). " +
15
+ "Use when the user asks what topics exist, or when system context did not list discovery results—" +
16
+ "do not assume names like /odom, /scan, or /battery_state exist without this tool (or subscribe) confirming them.",
17
+ parameters: Type.Object({}),
18
+
19
+ async execute(_toolCallId, _params) {
20
+ const transport = getTransport();
21
+ const topics = await transport.listTopics();
22
+
23
+ // Cap output size to avoid rate limits / token burn when robot has many topics
24
+ const MAX_TOPICS_IN_RESPONSE = 50;
25
+ const MAX_CHARS = 6000;
26
+ const truncated =
27
+ topics.length > MAX_TOPICS_IN_RESPONSE
28
+ ? topics.slice(0, MAX_TOPICS_IN_RESPONSE)
29
+ : topics;
30
+ const result = {
31
+ success: true,
32
+ topics: truncated,
33
+ total: topics.length,
34
+ truncated: topics.length > MAX_TOPICS_IN_RESPONSE,
35
+ ...(topics.length === 0
36
+ ? {
37
+ hint:
38
+ "No Zenoh keys were sampled. OpenClaw uses WebSocket to the Mac zenohd remote-api (not tcp://ROBOT_IP). " +
39
+ "If you see traffic with `zenoh subscribe -k '**' -e tcp/ROBOT_IP:7447`, that is often the robot's router — " +
40
+ "the bridge must peer to the same router as OpenClaw, and CLI garbled output is usually CDR/binary payloads, not topic names. " +
41
+ "Retry after confirming topology; optionally set AGENTICROS_ZENOH_LIST_TOPICS_MS for a longer sample window.",
42
+ }
43
+ : {}),
44
+ };
45
+ let text = JSON.stringify(result);
46
+ if (text.length > MAX_CHARS) {
47
+ const fewer = truncated.slice(0, 20);
48
+ text = JSON.stringify({
49
+ success: true,
50
+ total: topics.length,
51
+ message: `Topic list truncated to save tokens (${topics.length} total). Showing first 20.`,
52
+ topics: fewer,
53
+ });
54
+ }
55
+
56
+ return {
57
+ content: [{ type: "text", text }],
58
+ details: result,
59
+ };
60
+ },
61
+ });
62
+ }
@@ -0,0 +1,158 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import type { OpenClawPluginApi, ToolContent } from "../plugin-api.js";
3
+ import type { AgenticROSConfig } from "@agenticros/core";
4
+ import { resolveMemoryNamespace } from "@agenticros/core";
5
+ import { getMemory } from "../memory.js";
6
+
7
+ /**
8
+ * Register the four memory tools with the OpenClaw AI agent.
9
+ *
10
+ * Memory tools are only registered when `config.memory.enabled === true` and
11
+ * the provider initialized successfully. See ../memory.ts for the provider
12
+ * lifecycle.
13
+ */
14
+ export function registerMemoryTools(
15
+ api: OpenClawPluginApi,
16
+ config: AgenticROSConfig,
17
+ ): void {
18
+ api.registerTool({
19
+ name: "memory_remember",
20
+ label: "Memory: remember",
21
+ description:
22
+ "Store a durable fact in long-term memory. Call this when the user says \"remember that ...\", \"note that ...\", \"from now on ...\", or shares a stable personal fact (preferences, names, places, routines, robot hardware like the camera/eyes the robot has). The store is shared across all AgenticROS adapters talking to this robot (OpenClaw, Claude Desktop, Claude Code, Gemini). Do NOT auto-store chat transcripts or transient state. Namespace defaults to the robot namespace.",
23
+ parameters: Type.Object({
24
+ content: Type.String({ description: "The fact to remember, written as a self-contained sentence." }),
25
+ tags: Type.Optional(
26
+ Type.Array(Type.String(), {
27
+ description: "Optional list of tag strings for filtering later.",
28
+ }),
29
+ ),
30
+ path: Type.Optional(
31
+ Type.String({ description: "Optional hierarchical hint (e.g. 'preferences.movement.speed')." }),
32
+ ),
33
+ namespace: Type.Optional(Type.String({ description: "Optional namespace override; defaults to the robot namespace." })),
34
+ }),
35
+ async execute(_toolCallId, params) {
36
+ const memory = getMemory();
37
+ if (!memory) return memoryDisabled();
38
+ const content = String((params as any).content ?? "").trim();
39
+ if (!content) return errResult("memory_remember requires 'content'.");
40
+ const namespace = resolveMemoryNamespace(config, (params as any).namespace as string | undefined);
41
+ try {
42
+ const record = await memory.remember({
43
+ content,
44
+ namespace,
45
+ tags: Array.isArray((params as any).tags)
46
+ ? ((params as any).tags as unknown[]).map(String)
47
+ : undefined,
48
+ path: typeof (params as any).path === "string" ? ((params as any).path as string) : undefined,
49
+ });
50
+ const text = JSON.stringify({
51
+ success: true,
52
+ id: record.id,
53
+ namespace: record.namespace,
54
+ backend: memory.backend,
55
+ });
56
+ return { content: [{ type: "text", text }], details: record };
57
+ } catch (err) {
58
+ return errResult(`memory_remember failed: ${err instanceof Error ? err.message : String(err)}`);
59
+ }
60
+ },
61
+ });
62
+
63
+ api.registerTool({
64
+ name: "memory_recall",
65
+ label: "Memory: recall",
66
+ description:
67
+ "Semantic search of long-term memory. ALWAYS call this BEFORE answering a personal-context question, including: \"what do I have for X?\", \"what's my Y?\", \"where is the Z?\", \"what did I tell you about ...?\", \"do you remember ...?\". The store is shared across every adapter for this robot — a fact saved from Claude Desktop or Claude Code lives in the same store. Returns the top matches ranked by relevance.",
68
+ parameters: Type.Object({
69
+ query: Type.String({ description: "Free-text query describing what you want to recall." }),
70
+ limit: Type.Optional(Type.Number({ description: "Max matches to return (default 5)." })),
71
+ namespace: Type.Optional(Type.String({ description: "Optional namespace override; defaults to the robot namespace." })),
72
+ }),
73
+ async execute(_toolCallId, params) {
74
+ const memory = getMemory();
75
+ if (!memory) return memoryDisabled();
76
+ const query = String((params as any).query ?? "").trim();
77
+ if (!query) return errResult("memory_recall requires 'query'.");
78
+ const namespace = resolveMemoryNamespace(config, (params as any).namespace as string | undefined);
79
+ const limit = typeof (params as any).limit === "number" ? ((params as any).limit as number) : 5;
80
+ try {
81
+ const hits = await memory.recall({ query, namespace, limit });
82
+ const text = JSON.stringify({
83
+ success: true,
84
+ namespace,
85
+ backend: memory.backend,
86
+ count: hits.length,
87
+ results: hits,
88
+ });
89
+ return { content: [{ type: "text", text }], details: hits };
90
+ } catch (err) {
91
+ return errResult(`memory_recall failed: ${err instanceof Error ? err.message : String(err)}`);
92
+ }
93
+ },
94
+ });
95
+
96
+ api.registerTool({
97
+ name: "memory_forget",
98
+ label: "Memory: forget",
99
+ description:
100
+ "Delete memories. Provide an id (delete one), a query (delete matches in the namespace), or just namespace (delete all in that namespace). Irreversible.",
101
+ parameters: Type.Object({
102
+ id: Type.Optional(Type.String({ description: "Record id returned by memory_remember." })),
103
+ query: Type.Optional(
104
+ Type.String({ description: "Free-text query; deletes every matching memory in the namespace." }),
105
+ ),
106
+ namespace: Type.Optional(Type.String({ description: "Namespace to delete from." })),
107
+ }),
108
+ async execute(_toolCallId, params) {
109
+ const memory = getMemory();
110
+ if (!memory) return memoryDisabled();
111
+ const namespace = resolveMemoryNamespace(config, (params as any).namespace as string | undefined);
112
+ try {
113
+ const result = await memory.forget({
114
+ id: typeof (params as any).id === "string" ? ((params as any).id as string) : undefined,
115
+ query: typeof (params as any).query === "string" ? ((params as any).query as string) : undefined,
116
+ namespace,
117
+ });
118
+ const text = JSON.stringify({ success: true, ...result, namespace, backend: memory.backend });
119
+ return { content: [{ type: "text", text }], details: result };
120
+ } catch (err) {
121
+ return errResult(`memory_forget failed: ${err instanceof Error ? err.message : String(err)}`);
122
+ }
123
+ },
124
+ });
125
+
126
+ api.registerTool({
127
+ name: "memory_status",
128
+ label: "Memory: status",
129
+ description:
130
+ "Health check for the memory subsystem: enabled state, backend, record count for the current namespace, last write timestamp, and embedder info (when applicable).",
131
+ parameters: Type.Object({
132
+ namespace: Type.Optional(Type.String({ description: "Optional namespace override; defaults to the robot namespace." })),
133
+ }),
134
+ async execute(_toolCallId, params) {
135
+ const memory = getMemory();
136
+ if (!memory) return memoryDisabled();
137
+ const namespace = resolveMemoryNamespace(config, (params as any).namespace as string | undefined);
138
+ try {
139
+ const status = await memory.status(namespace);
140
+ const text = JSON.stringify({ success: true, ...status });
141
+ return { content: [{ type: "text", text }], details: status };
142
+ } catch (err) {
143
+ return errResult(`memory_status failed: ${err instanceof Error ? err.message : String(err)}`);
144
+ }
145
+ },
146
+ });
147
+ }
148
+
149
+ function memoryDisabled() {
150
+ return errResult(
151
+ "Memory is not enabled. Set memory.enabled=true in ~/.agenticros/config.json (backend: 'local' for zero deps, 'mem0' for semantic search). See docs/memory.md.",
152
+ );
153
+ }
154
+
155
+ function errResult(text: string) {
156
+ const content: ToolContent[] = [{ type: "text", text }];
157
+ return { content, details: { error: text } };
158
+ }
@@ -0,0 +1,87 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import type { OpenClawPluginApi } from "../plugin-api.js";
3
+ import type { AgenticROSConfig } from "@agenticros/core";
4
+ import { toNamespacedTopic } from "@agenticros/core";
5
+ import { getTransport } from "../service.js";
6
+
7
+ /**
8
+ * Register ros2_param_get and ros2_param_set tools with the AI agent.
9
+ */
10
+ export function registerParamTools(api: OpenClawPluginApi, config: AgenticROSConfig): void {
11
+ api.registerTool({
12
+ name: "ros2_param_get",
13
+ label: "ROS2 Get Parameter",
14
+ description:
15
+ "Get the value of a ROS2 parameter from a node. " +
16
+ "Use this to check robot configuration values.",
17
+ parameters: Type.Object({
18
+ node: Type.String({ description: "The fully qualified node name (e.g., '/turtlebot3/controller')" }),
19
+ parameter: Type.String({ description: "The parameter name (e.g., 'max_velocity')" }),
20
+ }),
21
+
22
+ async execute(_toolCallId, params) {
23
+ const rawNode = params["node"] as string;
24
+ const node = toNamespacedTopic(config, rawNode);
25
+ const parameter = params["parameter"] as string;
26
+
27
+ const transport = getTransport();
28
+ const response = await transport.callService({
29
+ service: `${node}/get_parameters`,
30
+ type: "rcl_interfaces/srv/GetParameters",
31
+ args: { names: [parameter] },
32
+ });
33
+
34
+ const result = {
35
+ success: response.result,
36
+ node,
37
+ parameter,
38
+ value: response.values,
39
+ };
40
+ return {
41
+ content: [{ type: "text", text: JSON.stringify(result) }],
42
+ details: result,
43
+ };
44
+ },
45
+ });
46
+
47
+ api.registerTool({
48
+ name: "ros2_param_set",
49
+ label: "ROS2 Set Parameter",
50
+ description:
51
+ "Set the value of a ROS2 parameter on a node. " +
52
+ "Use this to change robot configuration at runtime.",
53
+ parameters: Type.Object({
54
+ node: Type.String({ description: "The fully qualified node name" }),
55
+ parameter: Type.String({ description: "The parameter name" }),
56
+ value: Type.Unknown({ description: "The new parameter value" }),
57
+ }),
58
+
59
+ async execute(_toolCallId, params) {
60
+ const rawNode = params["node"] as string;
61
+ const node = toNamespacedTopic(config, rawNode);
62
+ const parameter = params["parameter"] as string;
63
+ const value = params["value"];
64
+
65
+ const transport = getTransport();
66
+ const response = await transport.callService({
67
+ service: `${node}/set_parameters`,
68
+ type: "rcl_interfaces/srv/SetParameters",
69
+ args: {
70
+ parameters: [
71
+ { name: parameter, value },
72
+ ],
73
+ },
74
+ });
75
+
76
+ const result = {
77
+ success: response.result,
78
+ node,
79
+ parameter,
80
+ };
81
+ return {
82
+ content: [{ type: "text", text: JSON.stringify(result) }],
83
+ details: result,
84
+ };
85
+ },
86
+ });
87
+ }