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,516 @@
1
+ /**
2
+ * Gemini function declarations and tool execution. Same ROS2 tool set as Claude Code.
3
+ */
4
+
5
+ import type { AgenticROSConfig } from "@agenticros/core";
6
+ import {
7
+ resolveCameraSubscribeTopic,
8
+ resolveMemoryNamespace,
9
+ toNamespacedTopic,
10
+ } from "@agenticros/core";
11
+ import {
12
+ ROS_MSG_COMPRESSED_IMAGE,
13
+ ROS_MSG_IMAGE,
14
+ cameraSnapshotFromPlainMessage,
15
+ mimeTypeForSnapshotBase64,
16
+ rosNumericField,
17
+ } from "@agenticros/ros-camera";
18
+ import type { FunctionDeclaration, FunctionResponsePart } from "@google/genai";
19
+ import { createFunctionResponsePartFromBase64 } from "@google/genai";
20
+ import { getTransport } from "./transport.js";
21
+ import { checkPublishSafety } from "./safety.js";
22
+ import { getDepthDistance } from "./depth.js";
23
+ import { ensureMemory } from "./memory.js";
24
+
25
+ const MEMORY_TOOL_NAMES = new Set([
26
+ "memory_remember",
27
+ "memory_recall",
28
+ "memory_forget",
29
+ "memory_status",
30
+ ]);
31
+
32
+ const DEFAULT_DEPTH_TOPIC = "/camera/camera/depth/image_rect_raw";
33
+ const ENABLE_MULTIMODAL_FUNCTION_RESPONSE =
34
+ (process.env.GEMINI_ENABLE_MULTIMODAL_TOOL_RESPONSE ?? "").toLowerCase() === "true";
35
+
36
+ /** JSON Schema for Gemini parameters (object with type, properties, required). */
37
+ function schemaFromProps(properties: Record<string, { type: string; description?: string }>, required?: string[]): Record<string, unknown> {
38
+ const schema: Record<string, unknown> = { type: "object", properties: {} };
39
+ for (const [k, v] of Object.entries(properties)) {
40
+ (schema.properties as Record<string, unknown>)[k] = { type: v.type, description: v.description };
41
+ }
42
+ if (required && required.length > 0) schema.required = required;
43
+ return schema;
44
+ }
45
+
46
+ export const GEMINI_FUNCTION_DECLARATIONS: FunctionDeclaration[] = [
47
+ {
48
+ name: "ros2_list_topics",
49
+ description: "List all available ROS2 topics and their message types. Use this to discover what data the robot publishes and what commands it accepts.",
50
+ parametersJsonSchema: schemaFromProps({}),
51
+ },
52
+ {
53
+ name: "ros2_publish",
54
+ description: "Publish a message to a ROS2 topic. Use this to send commands to the robot (e.g., velocity commands to /cmd_vel, navigation goals).",
55
+ parametersJsonSchema: schemaFromProps(
56
+ {
57
+ topic: { type: "string", description: "The ROS2 topic name (e.g., '/cmd_vel')" },
58
+ type: { type: "string", description: "The ROS2 message type (e.g., 'geometry_msgs/msg/Twist')" },
59
+ message: { type: "object", description: "The message payload matching the ROS2 message type schema" },
60
+ },
61
+ ["topic", "type", "message"],
62
+ ),
63
+ },
64
+ {
65
+ name: "ros2_subscribe_once",
66
+ description: "Subscribe to a ROS2 topic and return the next message. Use this to read sensor data, check robot state, or get the current value of a topic.",
67
+ parametersJsonSchema: schemaFromProps({
68
+ topic: { type: "string", description: "The ROS2 topic name (e.g., '/battery_state')" },
69
+ type: { type: "string", description: "The ROS2 message type (optional)" },
70
+ timeout: { type: "number", description: "Timeout in milliseconds (default: 5000)" },
71
+ }, ["topic"]),
72
+ },
73
+ {
74
+ name: "ros2_service_call",
75
+ description: "Call a ROS2 service and return the response. Use for request/response operations like setting parameters or querying node state.",
76
+ parametersJsonSchema: schemaFromProps({
77
+ service: { type: "string", description: "The ROS2 service name (e.g., '/spawn_entity')" },
78
+ type: { type: "string", description: "The ROS2 service type (optional)" },
79
+ args: { type: "object", description: "The service request arguments" },
80
+ }, ["service"]),
81
+ },
82
+ {
83
+ name: "ros2_action_goal",
84
+ description: "Send a goal to a ROS2 action server. Use for long-running operations like navigation or arm movements.",
85
+ parametersJsonSchema: schemaFromProps(
86
+ {
87
+ action: { type: "string", description: "The ROS2 action server name (e.g., '/navigate_to_pose')" },
88
+ actionType: { type: "string", description: "The ROS2 action type (e.g., 'nav2_msgs/action/NavigateToPose')" },
89
+ goal: { type: "object", description: "The action goal parameters" },
90
+ },
91
+ ["action", "actionType", "goal"],
92
+ ),
93
+ },
94
+ {
95
+ name: "ros2_param_get",
96
+ description: "Get the value of a ROS2 parameter from a node. Use to check robot configuration values.",
97
+ parametersJsonSchema: schemaFromProps(
98
+ {
99
+ node: { type: "string", description: "The fully qualified node name (e.g., '/turtlebot3/controller')" },
100
+ parameter: { type: "string", description: "The parameter name (e.g., 'max_velocity')" },
101
+ },
102
+ ["node", "parameter"],
103
+ ),
104
+ },
105
+ {
106
+ name: "ros2_param_set",
107
+ description: "Set the value of a ROS2 parameter on a node. Use to change robot configuration at runtime.",
108
+ parametersJsonSchema: schemaFromProps(
109
+ {
110
+ node: { type: "string", description: "The fully qualified node name" },
111
+ parameter: { type: "string", description: "The parameter name" },
112
+ value: { type: "object", description: "The new parameter value" },
113
+ },
114
+ ["node", "parameter", "value"],
115
+ ),
116
+ },
117
+ {
118
+ name: "ros2_camera_snapshot",
119
+ description: "Capture a single image from a ROS2 camera topic. Use when the user asks what the robot sees or requests a photo. Supports CompressedImage and raw Image.",
120
+ parametersJsonSchema: schemaFromProps({
121
+ topic: { type: "string", description: "Camera image topic (default from config or /camera/camera/color/image_raw/compressed)" },
122
+ message_type: { type: "string", description: "'CompressedImage' or 'Image' (default: CompressedImage)" },
123
+ timeout: { type: "number", description: "Timeout in milliseconds (default: 10000)" },
124
+ }),
125
+ },
126
+ {
127
+ name: "ros2_depth_distance",
128
+ description: "Get distance in meters from the robot's depth camera. Samples the center of the depth image. Use when the user asks how far they are from the robot.",
129
+ parametersJsonSchema: schemaFromProps({
130
+ topic: { type: "string", description: `Depth image topic (default: ${DEFAULT_DEPTH_TOPIC})` },
131
+ timeout: { type: "number", description: "Timeout in ms (default 5000)" },
132
+ }),
133
+ },
134
+ {
135
+ name: "memory_remember",
136
+ description:
137
+ "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. Only available when memory is enabled in config.",
138
+ parametersJsonSchema: schemaFromProps(
139
+ {
140
+ content: { type: "string", description: "The fact to remember, written as a self-contained sentence." },
141
+ tags: { type: "array", description: "Optional list of tag strings for filtering later." },
142
+ path: { type: "string", description: "Optional hierarchical hint (e.g. 'preferences.movement.speed')." },
143
+ namespace: { type: "string", description: "Optional namespace override; defaults to the robot namespace." },
144
+ },
145
+ ["content"],
146
+ ),
147
+ },
148
+ {
149
+ name: "memory_recall",
150
+ description:
151
+ "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.",
152
+ parametersJsonSchema: schemaFromProps(
153
+ {
154
+ query: { type: "string", description: "Free-text query describing what you want to recall." },
155
+ limit: { type: "number", description: "Max matches to return (default 5)." },
156
+ namespace: { type: "string", description: "Optional namespace override; defaults to the robot namespace." },
157
+ },
158
+ ["query"],
159
+ ),
160
+ },
161
+ {
162
+ name: "memory_forget",
163
+ description:
164
+ "Delete memories. Provide id (one), query (matches in namespace), or just namespace (all in that namespace). Irreversible.",
165
+ parametersJsonSchema: schemaFromProps({
166
+ id: { type: "string", description: "Record id returned by memory_remember." },
167
+ query: { type: "string", description: "Free-text query; deletes every matching memory in the namespace." },
168
+ namespace: { type: "string", description: "Namespace to delete from." },
169
+ }),
170
+ },
171
+ {
172
+ name: "memory_status",
173
+ description:
174
+ "Health check for the memory subsystem. Returns enabled state, backend, record count, last write timestamp, and embedder info.",
175
+ parametersJsonSchema: schemaFromProps({
176
+ namespace: { type: "string", description: "Optional namespace override; defaults to the robot namespace." },
177
+ }),
178
+ },
179
+ ];
180
+
181
+ /** Single tool object for Gemini (one item in config.tools array). */
182
+ export const GEMINI_TOOLS = [{ functionDeclarations: GEMINI_FUNCTION_DECLARATIONS }];
183
+
184
+ /**
185
+ * Build the per-invocation tools list for Gemini, filtering out memory tools
186
+ * when memory is disabled. Call this from chat.ts so the model never sees
187
+ * tools it cannot use.
188
+ */
189
+ export async function buildGeminiTools(config: AgenticROSConfig) {
190
+ const memory = await ensureMemory(config);
191
+ const declarations = memory
192
+ ? GEMINI_FUNCTION_DECLARATIONS
193
+ : GEMINI_FUNCTION_DECLARATIONS.filter(
194
+ (d) => !MEMORY_TOOL_NAMES.has(d.name ?? ""),
195
+ );
196
+ return [{ functionDeclarations: declarations }];
197
+ }
198
+
199
+ export interface ToolResult {
200
+ output: string;
201
+ parts?: FunctionResponsePart[];
202
+ inlineImage?: { data: string; mimeType: string };
203
+ }
204
+
205
+ export async function executeTool(
206
+ name: string,
207
+ args: Record<string, unknown>,
208
+ config: AgenticROSConfig,
209
+ ): Promise<ToolResult> {
210
+ // Memory tools never need the ROS transport — dispatch them before
211
+ // getTransport() (which throws when zenohd is down). Mirrors the gating in
212
+ // packages/agenticros-claude-code/src/tools.ts.
213
+ if (MEMORY_TOOL_NAMES.has(name)) {
214
+ return executeMemoryTool(name, args, config);
215
+ }
216
+ const transport = getTransport();
217
+
218
+ switch (name) {
219
+ case "ros2_list_topics": {
220
+ const topics = await transport.listTopics();
221
+ const MAX = 50;
222
+ const truncated = topics.length > MAX ? topics.slice(0, MAX) : topics;
223
+ const text = JSON.stringify({
224
+ success: true,
225
+ topics: truncated,
226
+ total: topics.length,
227
+ truncated: topics.length > MAX,
228
+ });
229
+ return { output: text };
230
+ }
231
+
232
+ case "ros2_publish": {
233
+ const rawTopicIn = String(args["topic"] ?? "").trim();
234
+ if (process.stderr?.write) {
235
+ process.stderr.write(`[AgenticROS] ros2_publish called topic=${JSON.stringify(rawTopicIn)}\n`);
236
+ }
237
+ if (transport.getStatus() !== "connected") {
238
+ return {
239
+ output: "Transport not connected to Zenoh/ROS2. Check zenohd is running (ws://localhost:10000) and config in ~/.agenticros/config.json.",
240
+ };
241
+ }
242
+ const safe = checkPublishSafety(config, args);
243
+ if (safe.block) {
244
+ return { output: safe.blockReason ?? "Blocked by safety." };
245
+ }
246
+ const cmdVelMatch = rawTopicIn.match(/^\/([^/]+)\/cmd_vel$/i);
247
+ const segment = cmdVelMatch?.[1] ?? "";
248
+ const topic =
249
+ cmdVelMatch && !segment.toLowerCase().startsWith("robot")
250
+ ? `/robot${segment.replace(/-/g, "")}/cmd_vel`
251
+ : toNamespacedTopic(config, rawTopicIn);
252
+ if (process.stderr?.write) {
253
+ process.stderr.write(`[AgenticROS] ros2_publish: → topic=${topic}\n`);
254
+ }
255
+ const type = args["type"] as string;
256
+ const message = args["message"] as Record<string, unknown>;
257
+ const PUBLISH_TIMEOUT_MS = 10_000;
258
+ const timeoutPromise = new Promise<never>((_, reject) => {
259
+ setTimeout(() => reject(new Error("Publish timed out after " + PUBLISH_TIMEOUT_MS / 1000 + "s (Zenoh put may be hanging). Check zenohd and logs.")), PUBLISH_TIMEOUT_MS);
260
+ });
261
+ try {
262
+ await Promise.race([transport.publish({ topic, type, msg: message }), timeoutPromise]);
263
+ } catch (err) {
264
+ const msg = err instanceof Error ? err.message : String(err);
265
+ return { output: `Publish failed: ${msg}` };
266
+ }
267
+ const summary = cmdVelMatch && topic.startsWith("/robot") ? `Published to ${topic} (robot prefix applied).` : `Published to ${topic}.`;
268
+ return { output: summary + "\n" + JSON.stringify({ success: true, topic, type }) };
269
+ }
270
+
271
+ case "ros2_subscribe_once": {
272
+ const rawTopic = args["topic"] as string;
273
+ const topic = toNamespacedTopic(config, rawTopic);
274
+ let msgType = args["type"] as string | undefined;
275
+ const timeout = (args["timeout"] as number | undefined) ?? 5000;
276
+ if (!msgType && /\/?(camera|image|color|depth)/i.test(rawTopic)) {
277
+ msgType = rawTopic.includes("compressed") ? "sensor_msgs/msg/CompressedImage" : "sensor_msgs/msg/Image";
278
+ }
279
+ const result = await new Promise<Record<string, unknown>>((resolve, reject) => {
280
+ const sub = transport.subscribe(
281
+ { topic, type: msgType },
282
+ (msg: Record<string, unknown>) => {
283
+ clearTimeout(timer);
284
+ sub.unsubscribe();
285
+ resolve({ success: true, topic, message: msg });
286
+ },
287
+ );
288
+ const timer = setTimeout(() => {
289
+ sub.unsubscribe();
290
+ reject(new Error(`Timeout waiting for message on ${topic}`));
291
+ }, timeout);
292
+ });
293
+ let text = JSON.stringify(result);
294
+ const MAX_CHARS = 8000;
295
+ if (text.length > MAX_CHARS) {
296
+ text = JSON.stringify({
297
+ success: true,
298
+ topic,
299
+ message: "[truncated: message too large]",
300
+ originalSize: text.length,
301
+ }) + "\n(Use ros2_camera_snapshot for image topics.)";
302
+ }
303
+ return { output: text };
304
+ }
305
+
306
+ case "ros2_service_call": {
307
+ const rawService = args["service"] as string;
308
+ const service = toNamespacedTopic(config, rawService);
309
+ const type = args["type"] as string | undefined;
310
+ const reqArgs = args["args"] as Record<string, unknown> | undefined;
311
+ const response = await transport.callService({ service, type, args: reqArgs });
312
+ const text = JSON.stringify({
313
+ success: response.result,
314
+ service,
315
+ response: response.values,
316
+ });
317
+ return { output: text };
318
+ }
319
+
320
+ case "ros2_action_goal": {
321
+ const rawAction = args["action"] as string;
322
+ const action = toNamespacedTopic(config, rawAction);
323
+ const actionType = args["actionType"] as string;
324
+ const goal = args["goal"] as Record<string, unknown>;
325
+ const actionResult = await transport.sendActionGoal({ action, actionType, args: goal });
326
+ const text = JSON.stringify({
327
+ success: actionResult.result,
328
+ action,
329
+ result: actionResult.values,
330
+ });
331
+ return { output: text };
332
+ }
333
+
334
+ case "ros2_param_get": {
335
+ const rawNode = args["node"] as string;
336
+ const node = toNamespacedTopic(config, rawNode);
337
+ const parameter = args["parameter"] as string;
338
+ const response = await transport.callService({
339
+ service: `${node}/get_parameters`,
340
+ type: "rcl_interfaces/srv/GetParameters",
341
+ args: { names: [parameter] },
342
+ });
343
+ const text = JSON.stringify({
344
+ success: response.result,
345
+ node,
346
+ parameter,
347
+ value: response.values,
348
+ });
349
+ return { output: text };
350
+ }
351
+
352
+ case "ros2_param_set": {
353
+ const rawNode = args["node"] as string;
354
+ const node = toNamespacedTopic(config, rawNode);
355
+ const parameter = args["parameter"] as string;
356
+ const value = args["value"];
357
+ const response = await transport.callService({
358
+ service: `${node}/set_parameters`,
359
+ type: "rcl_interfaces/srv/SetParameters",
360
+ args: { parameters: [{ name: parameter, value }] },
361
+ });
362
+ const text = JSON.stringify({
363
+ success: response.result,
364
+ node,
365
+ parameter,
366
+ });
367
+ return { output: text };
368
+ }
369
+
370
+ case "ros2_camera_snapshot": {
371
+ const defaultTopic =
372
+ (config.robot?.cameraTopic ?? "").trim() || "/camera/camera/color/image_raw/compressed";
373
+ const rawTopic = (args["topic"] as string | undefined) ?? defaultTopic;
374
+ const topic = resolveCameraSubscribeTopic(config, rawTopic);
375
+ const rawMsgType = args["message_type"] as string | undefined;
376
+ const messageType: "CompressedImage" | "Image" = rawMsgType === "Image" ? "Image" : "CompressedImage";
377
+ const timeout = (args["timeout"] as number | undefined) ?? 10000;
378
+ const type = messageType === "Image" ? ROS_MSG_IMAGE : ROS_MSG_COMPRESSED_IMAGE;
379
+
380
+ let result: Record<string, unknown>;
381
+ try {
382
+ result = await new Promise<Record<string, unknown>>((resolve, reject) => {
383
+ const subscription = transport.subscribe(
384
+ { topic, type },
385
+ (msg: Record<string, unknown>) => {
386
+ clearTimeout(timer);
387
+ subscription.unsubscribe();
388
+ try {
389
+ const payload = cameraSnapshotFromPlainMessage(messageType, msg);
390
+ resolve({
391
+ success: true,
392
+ topic,
393
+ format: payload.formatLabel,
394
+ data: payload.dataBase64,
395
+ width: payload.width,
396
+ height: payload.height,
397
+ });
398
+ } catch (e) {
399
+ reject(e instanceof Error ? e : new Error(String(e)));
400
+ }
401
+ },
402
+ );
403
+ const timer = setTimeout(() => {
404
+ subscription.unsubscribe();
405
+ reject(new Error(`Timeout waiting for camera frame on ${topic}`));
406
+ }, timeout);
407
+ });
408
+ } catch (err) {
409
+ const message = err instanceof Error ? err.message : String(err);
410
+ return {
411
+ output: `Camera snapshot failed: ${message}. Set robot.cameraTopic in config or pass topic= + message_type=Image if only raw Image exists.`,
412
+ };
413
+ }
414
+
415
+ const base64 = (result.data as string) ?? "";
416
+ const format = String((result.format as string) ?? "jpeg").toLowerCase();
417
+ const mimeType = mimeTypeForSnapshotBase64(base64, format);
418
+ const wNum = result.width != null ? rosNumericField(result.width, "width") : undefined;
419
+ const hNum = result.height != null ? rosNumericField(result.height, "height") : undefined;
420
+ const summary = `Captured one frame from ${topic}${wNum != null && hNum != null ? ` (${wNum}×${hNum})` : ""}.`;
421
+ const parts: FunctionResponsePart[] = [];
422
+ if (base64 && /^[A-Za-z0-9+/=]+$/.test(base64) && base64.length >= 100) {
423
+ if (ENABLE_MULTIMODAL_FUNCTION_RESPONSE) {
424
+ parts.push(createFunctionResponsePartFromBase64(base64, mimeType));
425
+ }
426
+ } else if (base64 && (!/^[A-Za-z0-9+/=]+$/.test(base64) || base64.length < 100)) {
427
+ return {
428
+ output:
429
+ summary +
430
+ " (Image payload was present but not valid base64 or too small—check topic, message_type, or transport.)",
431
+ };
432
+ } else if (!base64) {
433
+ return { output: summary + " (No image data received—topic may be idle or transport returned empty.)" };
434
+ }
435
+ if (!ENABLE_MULTIMODAL_FUNCTION_RESPONSE) {
436
+ return {
437
+ output:
438
+ summary +
439
+ " (Image bytes captured; multimodal function response disabled for compatibility with models that reject it.)",
440
+ inlineImage: { data: base64, mimeType },
441
+ };
442
+ }
443
+ return { output: summary, parts };
444
+ }
445
+
446
+ case "ros2_depth_distance": {
447
+ const rawTopic = (args["topic"] as string | undefined)?.trim() || DEFAULT_DEPTH_TOPIC;
448
+ const topic = resolveCameraSubscribeTopic(config, rawTopic);
449
+ const timeout = (args["timeout"] as number | undefined) ?? 5000;
450
+ try {
451
+ const result = await getDepthDistance(transport, topic, timeout);
452
+ const text = result.valid
453
+ ? `Distance at center (~12th percentile, nearer surfaces): **${result.distance_m} m** (median: ${result.median_m} m; range ${result.min_m}–${result.max_m} m; ${result.sample_count} pixels). Topic: ${result.topic}.`
454
+ : `No valid depth in center region (topic: ${result.topic}, ${result.width}×${result.height}, encoding ${result.encoding}).`;
455
+ return { output: text };
456
+ } catch (err) {
457
+ const message = err instanceof Error ? err.message : String(err);
458
+ return { output: `Depth distance failed: ${message}` };
459
+ }
460
+ }
461
+
462
+ default:
463
+ return { output: `Unknown tool: ${name}` };
464
+ }
465
+ }
466
+
467
+ /**
468
+ * Dispatcher for the four memory_* Gemini tools. Kept separate from the ROS
469
+ * tool switch because memory tools must work without the ROS transport.
470
+ */
471
+ async function executeMemoryTool(
472
+ name: string,
473
+ args: Record<string, unknown>,
474
+ config: AgenticROSConfig,
475
+ ): Promise<ToolResult> {
476
+ const memory = await ensureMemory(config);
477
+ if (!memory) {
478
+ return {
479
+ output:
480
+ "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.",
481
+ };
482
+ }
483
+ const namespace = resolveMemoryNamespace(config, args["namespace"] as string | undefined);
484
+ try {
485
+ if (name === "memory_remember") {
486
+ const content = String(args["content"] ?? "").trim();
487
+ if (!content) return { output: "memory_remember requires 'content'." };
488
+ const tags = Array.isArray(args["tags"]) ? (args["tags"] as unknown[]).map(String) : undefined;
489
+ const pathHint = typeof args["path"] === "string" ? (args["path"] as string) : undefined;
490
+ const record = await memory.remember({ content, namespace, tags, path: pathHint });
491
+ return {
492
+ output: JSON.stringify({ success: true, id: record.id, namespace: record.namespace, backend: memory.backend }),
493
+ };
494
+ }
495
+ if (name === "memory_recall") {
496
+ const query = String(args["query"] ?? "").trim();
497
+ if (!query) return { output: "memory_recall requires 'query'." };
498
+ const limit = typeof args["limit"] === "number" ? (args["limit"] as number) : 5;
499
+ const hits = await memory.recall({ query, namespace, limit });
500
+ return {
501
+ output: JSON.stringify({ success: true, namespace, backend: memory.backend, count: hits.length, results: hits }),
502
+ };
503
+ }
504
+ if (name === "memory_forget") {
505
+ const id = typeof args["id"] === "string" ? (args["id"] as string) : undefined;
506
+ const query = typeof args["query"] === "string" ? (args["query"] as string) : undefined;
507
+ const result = await memory.forget({ id, query, namespace });
508
+ return { output: JSON.stringify({ success: true, ...result, namespace, backend: memory.backend }) };
509
+ }
510
+ const status = await memory.status(namespace);
511
+ return { output: JSON.stringify({ success: true, ...status }) };
512
+ } catch (err) {
513
+ const message = err instanceof Error ? err.message : String(err);
514
+ return { output: `${name} failed: ${message}` };
515
+ }
516
+ }
@@ -0,0 +1,58 @@
1
+ import type { RosTransport } from "@agenticros/core";
2
+ import { createTransport, getTransportConfig } from "@agenticros/core";
3
+ import type { AgenticROSConfig } from "@agenticros/core";
4
+
5
+ let transport: RosTransport | null = null;
6
+
7
+ /**
8
+ * Get the active transport. Throws if not connected.
9
+ */
10
+ export function getTransport(): RosTransport {
11
+ if (!transport) {
12
+ throw new Error("Transport not initialized. Ensure config is loaded and connect() has been called.");
13
+ }
14
+ return transport;
15
+ }
16
+
17
+ export function getTransportOrNull(): RosTransport | null {
18
+ return transport;
19
+ }
20
+
21
+ const CONNECT_TIMEOUT_MS = 15_000;
22
+
23
+ /**
24
+ * Create and connect the transport. Idempotent.
25
+ * Fails after CONNECT_TIMEOUT_MS if Zenoh/router is unreachable.
26
+ */
27
+ export async function connect(config: AgenticROSConfig): Promise<void> {
28
+ if (transport && transport.getStatus() === "connected") {
29
+ return;
30
+ }
31
+ if (transport) {
32
+ await transport.disconnect();
33
+ transport = null;
34
+ }
35
+ const transportCfg = getTransportConfig(config);
36
+ const newTransport = await createTransport(transportCfg);
37
+ const timeoutPromise = new Promise<never>((_, reject) => {
38
+ setTimeout(
39
+ () => reject(new Error(
40
+ `Transport connection timed out after ${CONNECT_TIMEOUT_MS / 1000}s. ` +
41
+ "Is zenohd running? (e.g. ws://localhost:10000). Check config and logs.",
42
+ )),
43
+ CONNECT_TIMEOUT_MS,
44
+ );
45
+ });
46
+ await Promise.race([newTransport.connect(), timeoutPromise]);
47
+ transport = newTransport;
48
+ }
49
+
50
+ /**
51
+ * Disconnect and clear the transport. Call on process exit.
52
+ */
53
+ export async function disconnect(): Promise<void> {
54
+ if (transport) {
55
+ await transport.disconnect();
56
+ transport = null;
57
+ }
58
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src/**/*"]
8
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@agenticros/core",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "description": "AgenticROS core — platform-agnostic ROS2 transport, types, and config",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "typecheck": "tsc --noEmit",
18
+ "test": "node --test \"dist/memory/__tests__/*.test.js\""
19
+ },
20
+ "dependencies": {
21
+ "@eclipse-zenoh/zenoh-ts": "^1.9.0",
22
+ "@foxglove/cdr": "^3.5.0",
23
+ "@foxglove/rosmsg": "^4.2.2",
24
+ "@foxglove/rosmsg2-serialization": "^3.1.0",
25
+ "node-datachannel": "^0.12.0",
26
+ "ws": "^8.18.0",
27
+ "zod": "^3.24.0"
28
+ },
29
+ "optionalDependencies": {
30
+ "rclnodejs": "^1.8.1"
31
+ },
32
+ "peerDependencies": {
33
+ "mem0ai": "^2.0.0"
34
+ },
35
+ "peerDependenciesMeta": {
36
+ "mem0ai": {
37
+ "optional": true
38
+ }
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^20.17.0",
42
+ "@types/ws": "^8.5.13",
43
+ "typescript": "^5.7.0"
44
+ },
45
+ "author": "PlaiPin",
46
+ "license": "Apache-2.0"
47
+ }
@@ -0,0 +1,32 @@
1
+ export interface AgenticROSBannerOptions {
2
+ color?: boolean;
3
+ tagline?: boolean;
4
+ }
5
+
6
+ const ANSI_GREEN = "\x1b[92m";
7
+ const ANSI_YELLOW = "\x1b[93m";
8
+ const ANSI_DIM = "\x1b[2m";
9
+ const ANSI_RESET = "\x1b[0m";
10
+
11
+ const LOGO = String.raw`
12
+ _ _ _ ____ ___ ____
13
+ / \ __ _ ___ _ __ | |_(_) ___ | _ \ / _ \/ ___|
14
+ / _ \ / _` + "`" + String.raw` |/ _ \ '_ \| __| |/ __|| |_) | | | \___ \
15
+ / ___ \ (_| | __/ | | | |_| | (__ | _ <| |_| |___) |
16
+ /_/ \_\__, |\___|_| |_|\__|_|\___||_| \_\___/|____/
17
+ |___/`;
18
+
19
+ export function renderAgenticROSBanner(options: AgenticROSBannerOptions = {}): string {
20
+ const tagline = options.tagline ?? true;
21
+ if (!options.color) {
22
+ return tagline ? `${LOGO}\n AgenticROS - agentic AI for ROS-powered robots` : LOGO;
23
+ }
24
+ const coloredLogo = `${ANSI_GREEN}${LOGO}${ANSI_RESET}`;
25
+ return tagline
26
+ ? `${coloredLogo}\n${ANSI_YELLOW} AgenticROS${ANSI_RESET} ${ANSI_DIM}- agentic AI for ROS-powered robots${ANSI_RESET}`
27
+ : coloredLogo;
28
+ }
29
+
30
+ export function agenticROSBannerLines(options: AgenticROSBannerOptions = {}): string[] {
31
+ return renderAgenticROSBanner(options).split("\n");
32
+ }