@agenticros/core 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +192 -0
- package/README.md +88 -0
- package/dist/banner.d.ts +7 -0
- package/dist/banner.d.ts.map +1 -0
- package/dist/banner.js +25 -0
- package/dist/banner.js.map +1 -0
- package/dist/capabilities.d.ts +101 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +240 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/cmd-vel-twist.d.ts +9 -0
- package/dist/cmd-vel-twist.d.ts.map +1 -0
- package/dist/cmd-vel-twist.js +32 -0
- package/dist/cmd-vel-twist.js.map +1 -0
- package/dist/config.d.ts +1195 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +427 -0
- package/dist/config.js.map +1 -0
- package/dist/discovery.d.ts +113 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +141 -0
- package/dist/discovery.js.map +1 -0
- package/dist/find-robots-for.d.ts +85 -0
- package/dist/find-robots-for.d.ts.map +1 -0
- package/dist/find-robots-for.js +120 -0
- package/dist/find-robots-for.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/factory.d.ts +18 -0
- package/dist/memory/factory.d.ts.map +1 -0
- package/dist/memory/factory.js +51 -0
- package/dist/memory/factory.js.map +1 -0
- package/dist/memory/index.d.ts +3 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +2 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/local/provider.d.ts +29 -0
- package/dist/memory/local/provider.d.ts.map +1 -0
- package/dist/memory/local/provider.js +202 -0
- package/dist/memory/local/provider.js.map +1 -0
- package/dist/memory/mem0/provider.d.ts +66 -0
- package/dist/memory/mem0/provider.d.ts.map +1 -0
- package/dist/memory/mem0/provider.js +310 -0
- package/dist/memory/mem0/provider.js.map +1 -0
- package/dist/memory/types.d.ts +91 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +10 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/mission-registry.d.ts +94 -0
- package/dist/mission-registry.d.ts.map +1 -0
- package/dist/mission-registry.js +123 -0
- package/dist/mission-registry.js.map +1 -0
- package/dist/mission-transcript-sink.d.ts +33 -0
- package/dist/mission-transcript-sink.d.ts.map +1 -0
- package/dist/mission-transcript-sink.js +76 -0
- package/dist/mission-transcript-sink.js.map +1 -0
- package/dist/mission.d.ts +281 -0
- package/dist/mission.d.ts.map +1 -0
- package/dist/mission.js +331 -0
- package/dist/mission.js.map +1 -0
- package/dist/planner/index.d.ts +84 -0
- package/dist/planner/index.d.ts.map +1 -0
- package/dist/planner/index.js +486 -0
- package/dist/planner/index.js.map +1 -0
- package/dist/robots.d.ts +133 -0
- package/dist/robots.d.ts.map +1 -0
- package/dist/robots.js +220 -0
- package/dist/robots.js.map +1 -0
- package/dist/topic-utils.d.ts +47 -0
- package/dist/topic-utils.d.ts.map +1 -0
- package/dist/topic-utils.js +136 -0
- package/dist/topic-utils.js.map +1 -0
- package/dist/transport/factory.d.ts +10 -0
- package/dist/transport/factory.d.ts.map +1 -0
- package/dist/transport/factory.js +40 -0
- package/dist/transport/factory.js.map +1 -0
- package/dist/transport/local/conversion.d.ts +30 -0
- package/dist/transport/local/conversion.d.ts.map +1 -0
- package/dist/transport/local/conversion.js +340 -0
- package/dist/transport/local/conversion.js.map +1 -0
- package/dist/transport/local/entities.d.ts +34 -0
- package/dist/transport/local/entities.d.ts.map +1 -0
- package/dist/transport/local/entities.js +108 -0
- package/dist/transport/local/entities.js.map +1 -0
- package/dist/transport/local/transport.d.ts +53 -0
- package/dist/transport/local/transport.d.ts.map +1 -0
- package/dist/transport/local/transport.js +344 -0
- package/dist/transport/local/transport.js.map +1 -0
- package/dist/transport/rosbridge/actions.d.ts +30 -0
- package/dist/transport/rosbridge/actions.d.ts.map +1 -0
- package/dist/transport/rosbridge/actions.js +61 -0
- package/dist/transport/rosbridge/actions.js.map +1 -0
- package/dist/transport/rosbridge/adapter.d.ts +29 -0
- package/dist/transport/rosbridge/adapter.d.ts.map +1 -0
- package/dist/transport/rosbridge/adapter.js +108 -0
- package/dist/transport/rosbridge/adapter.js.map +1 -0
- package/dist/transport/rosbridge/client.d.ts +55 -0
- package/dist/transport/rosbridge/client.d.ts.map +1 -0
- package/dist/transport/rosbridge/client.js +375 -0
- package/dist/transport/rosbridge/client.js.map +1 -0
- package/dist/transport/rosbridge/services.d.ts +14 -0
- package/dist/transport/rosbridge/services.d.ts.map +1 -0
- package/dist/transport/rosbridge/services.js +25 -0
- package/dist/transport/rosbridge/services.js.map +1 -0
- package/dist/transport/rosbridge/topics.d.ts +28 -0
- package/dist/transport/rosbridge/topics.d.ts.map +1 -0
- package/dist/transport/rosbridge/topics.js +59 -0
- package/dist/transport/rosbridge/topics.js.map +1 -0
- package/dist/transport/rosbridge/types.d.ts +87 -0
- package/dist/transport/rosbridge/types.d.ts.map +1 -0
- package/dist/transport/rosbridge/types.js +6 -0
- package/dist/transport/rosbridge/types.js.map +1 -0
- package/dist/transport/transport.d.ts +39 -0
- package/dist/transport/transport.d.ts.map +1 -0
- package/dist/transport/transport.js +2 -0
- package/dist/transport/transport.js.map +1 -0
- package/dist/transport/types.d.ts +100 -0
- package/dist/transport/types.d.ts.map +1 -0
- package/dist/transport/types.js +5 -0
- package/dist/transport/types.js.map +1 -0
- package/dist/transport/webrtc/signaling-client.d.ts +38 -0
- package/dist/transport/webrtc/signaling-client.d.ts.map +1 -0
- package/dist/transport/webrtc/signaling-client.js +161 -0
- package/dist/transport/webrtc/signaling-client.js.map +1 -0
- package/dist/transport/webrtc/signaling-types.d.ts +112 -0
- package/dist/transport/webrtc/signaling-types.d.ts.map +1 -0
- package/dist/transport/webrtc/signaling-types.js +8 -0
- package/dist/transport/webrtc/signaling-types.js.map +1 -0
- package/dist/transport/webrtc/transport.d.ts +67 -0
- package/dist/transport/webrtc/transport.d.ts.map +1 -0
- package/dist/transport/webrtc/transport.js +406 -0
- package/dist/transport/webrtc/transport.js.map +1 -0
- package/dist/transport/zenoh/adapter.d.ts +47 -0
- package/dist/transport/zenoh/adapter.d.ts.map +1 -0
- package/dist/transport/zenoh/adapter.js +296 -0
- package/dist/transport/zenoh/adapter.js.map +1 -0
- package/dist/transport/zenoh/cdr.d.ts +17 -0
- package/dist/transport/zenoh/cdr.d.ts.map +1 -0
- package/dist/transport/zenoh/cdr.js +170 -0
- package/dist/transport/zenoh/cdr.js.map +1 -0
- package/dist/transport/zenoh/keys.d.ts +21 -0
- package/dist/transport/zenoh/keys.d.ts.map +1 -0
- package/dist/transport/zenoh/keys.js +44 -0
- package/dist/transport/zenoh/keys.js.map +1 -0
- package/dist/transport-pool.d.ts +74 -0
- package/dist/transport-pool.d.ts.map +1 -0
- package/dist/transport-pool.js +135 -0
- package/dist/transport-pool.js.map +1 -0
- package/package.json +80 -0
package/dist/robots.d.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-robot support — Phase 1.d of the AgenticROS strategy.
|
|
3
|
+
*
|
|
4
|
+
* For most deployments today the gateway talks to a single robot, so
|
|
5
|
+
* config.robot (a single object) is all that's used. Phase 1.d adds a
|
|
6
|
+
* `robots` array to the config so a single gateway / chat session can
|
|
7
|
+
* address multiple robots by id.
|
|
8
|
+
*
|
|
9
|
+
* This module is the source of truth for that resolution: from the raw
|
|
10
|
+
* AgenticROSConfig, what robots does the agent see, and which one is the
|
|
11
|
+
* active default? Adapters call into it from:
|
|
12
|
+
* - `ros2_list_robots` (this phase) — list everything the gateway knows about.
|
|
13
|
+
* - `ros2_list_capabilities(robot_id?)` (next iteration) — scope to one robot.
|
|
14
|
+
* - `run_mission` (next iteration) — `mission.robot_id` field.
|
|
15
|
+
* - per-tool `robot_id` (next iteration) — `ros2_publish`, `ros2_subscribe_once`,
|
|
16
|
+
* `ros2_camera_snapshot`, etc.
|
|
17
|
+
*
|
|
18
|
+
* Backwards compatibility: when `robots` is empty (i.e. nothing in
|
|
19
|
+
* config.robots), this module synthesises a one-entry list from the
|
|
20
|
+
* legacy `config.robot` object so old configs and the single-robot
|
|
21
|
+
* mental model keep working unchanged. The synthesised entry is marked
|
|
22
|
+
* default so it's selected by `getActiveRobotId()`.
|
|
23
|
+
*/
|
|
24
|
+
import type { AgenticROSConfig } from "./config.js";
|
|
25
|
+
import type { TransportConfig } from "./transport/types.js";
|
|
26
|
+
/** Sensor/hardware tags on a robot (Phase 1.e). */
|
|
27
|
+
export interface RobotSensors {
|
|
28
|
+
/** Intel RealSense depth+RGB camera. */
|
|
29
|
+
has_realsense: boolean;
|
|
30
|
+
/** 2D or 3D LiDAR sensor. */
|
|
31
|
+
has_lidar: boolean;
|
|
32
|
+
/** Robotic manipulator (arm) attached. */
|
|
33
|
+
has_arm: boolean;
|
|
34
|
+
}
|
|
35
|
+
/** A resolved robot — what the agent + adapters operate on. */
|
|
36
|
+
export interface ResolvedRobot {
|
|
37
|
+
/** Stable, human-readable identifier. Falls back to namespace when not set. */
|
|
38
|
+
id: string;
|
|
39
|
+
/** Display name used by the agent in chat replies. */
|
|
40
|
+
name: string;
|
|
41
|
+
/** ROS2 topic namespace prefix (e.g. "robot3946b404..." → /robot3946.../cmd_vel). */
|
|
42
|
+
namespace: string;
|
|
43
|
+
/** Default camera topic for `ros2_camera_snapshot`. Empty string when unset. */
|
|
44
|
+
cameraTopic: string;
|
|
45
|
+
/**
|
|
46
|
+
* Phase 1.e robot kind ("amr" | "arm" | "drone" | "rover" | …).
|
|
47
|
+
* Free-form string. Defaults to "amr" for back-compat (the legacy
|
|
48
|
+
* fallback synthesises this too).
|
|
49
|
+
*/
|
|
50
|
+
kind: string;
|
|
51
|
+
/** Phase 1.e sensor/hardware tags. Defaults to all-false. */
|
|
52
|
+
sensors: RobotSensors;
|
|
53
|
+
/**
|
|
54
|
+
* Phase 1.e optional per-robot capability allowlist. When `undefined`
|
|
55
|
+
* the robot inherits the global capability registry (the common
|
|
56
|
+
* case); when set it's the exact list `ros2_find_robots_for` will
|
|
57
|
+
* filter against for this robot.
|
|
58
|
+
*/
|
|
59
|
+
capabilities?: string[];
|
|
60
|
+
/**
|
|
61
|
+
* Source tag — handy for diagnostics ("Why is this robot in the list?").
|
|
62
|
+
* - "config": from config.robots[]
|
|
63
|
+
* - "legacy": synthesised from the legacy single config.robot object
|
|
64
|
+
*/
|
|
65
|
+
source: "config" | "legacy";
|
|
66
|
+
}
|
|
67
|
+
export declare function listRobots(config: AgenticROSConfig): ResolvedRobot[];
|
|
68
|
+
/**
|
|
69
|
+
* Pick the active robot's id according to these rules, in order:
|
|
70
|
+
* 1. `override` argument (when truthy) — usually a per-tool-call robot_id.
|
|
71
|
+
* 2. An entry in config.robots with `default: true`.
|
|
72
|
+
* 3. The first entry in the resolved list (which includes the legacy
|
|
73
|
+
* fallback when nothing else is configured).
|
|
74
|
+
*
|
|
75
|
+
* Throws when no robots exist at all — that should be impossible because
|
|
76
|
+
* the legacy fallback always produces at least one — but the guard is
|
|
77
|
+
* there for robustness against a corrupted config.
|
|
78
|
+
*/
|
|
79
|
+
export declare function getActiveRobotId(config: AgenticROSConfig, override?: string): string;
|
|
80
|
+
/**
|
|
81
|
+
* Convenience wrapper for tool handlers: extract an optional `robot_id`
|
|
82
|
+
* (a string) from a tool-args record and call `resolveRobot`. Returns
|
|
83
|
+
* the active robot when `robot_id` is missing or not a string.
|
|
84
|
+
*
|
|
85
|
+
* Throws — with the known robot ids listed in the error — when
|
|
86
|
+
* `robot_id` is set to an unknown value. Adapters surface that as a
|
|
87
|
+
* tool error so the agent self-corrects via `ros2_list_robots`.
|
|
88
|
+
*/
|
|
89
|
+
export declare function resolveRobotFromArgs(config: AgenticROSConfig, args: Record<string, unknown>): ResolvedRobot;
|
|
90
|
+
/**
|
|
91
|
+
* Resolve a robot to its full record by id. When `robotId` is omitted or
|
|
92
|
+
* empty, the active robot is returned. When `robotId` is provided but
|
|
93
|
+
* doesn't match any configured robot, throws with the available ids in
|
|
94
|
+
* the message so the agent can correct itself.
|
|
95
|
+
*/
|
|
96
|
+
export declare function resolveRobot(config: AgenticROSConfig, robotId?: string): ResolvedRobot;
|
|
97
|
+
/**
|
|
98
|
+
* Phase 1.d-resolve helper: compute the effective `TransportConfig` for
|
|
99
|
+
* a given robot, honouring an optional per-robot override in
|
|
100
|
+
* `config.robots[i].transport`.
|
|
101
|
+
*
|
|
102
|
+
* Precedence (most specific wins):
|
|
103
|
+
* 1. The robot's `transport.<mode>` sub-section (e.g. the override's
|
|
104
|
+
* `zenoh: { routerEndpoint: ... }`).
|
|
105
|
+
* 2. The top-level `config.<mode>` section (e.g. the global
|
|
106
|
+
* `config.zenoh`).
|
|
107
|
+
*
|
|
108
|
+
* When the robot has no `transport` override at all, this returns the
|
|
109
|
+
* global transport from `getTransportConfig(config)` — so single-robot
|
|
110
|
+
* deployments behave exactly as before.
|
|
111
|
+
*
|
|
112
|
+
* Why this lives here (and not next to `createTransport`):
|
|
113
|
+
* - The resolver owns "which robot are we talking about?"; the
|
|
114
|
+
* transport factory owns "given a TransportConfig, build an
|
|
115
|
+
* instance". Mixing them couples a multi-robot decision into the
|
|
116
|
+
* low-level transport layer, which is wrong: adapters that don't
|
|
117
|
+
* care about per-robot transports keep using `createTransport` and
|
|
118
|
+
* never see this helper.
|
|
119
|
+
* - Callers that DO want per-robot pools call this to materialise the
|
|
120
|
+
* right `TransportConfig` per id, then hand it to `createTransport`.
|
|
121
|
+
*
|
|
122
|
+
* Throws when `robotId` is given but doesn't match any configured robot
|
|
123
|
+
* (delegated to `resolveRobot`'s error path).
|
|
124
|
+
*/
|
|
125
|
+
export declare function getTransportConfigForRobot(config: AgenticROSConfig, robotId?: string): TransportConfig;
|
|
126
|
+
/**
|
|
127
|
+
* True when the named robot (or active robot when `robotId` is omitted)
|
|
128
|
+
* has a per-robot transport override. Adapters use this as a cheap
|
|
129
|
+
* branch to decide between "reuse the global transport" (fast path) and
|
|
130
|
+
* "build a per-robot one via `getTransportConfigForRobot`" (pool path).
|
|
131
|
+
*/
|
|
132
|
+
export declare function hasRobotTransportOverride(config: AgenticROSConfig, robotId?: string): boolean;
|
|
133
|
+
//# sourceMappingURL=robots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"robots.d.ts","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,mDAAmD;AACnD,MAAM,WAAW,YAAY;IAC3B,wCAAwC;IACxC,aAAa,EAAE,OAAO,CAAC;IACvB,6BAA6B;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,+EAA+E;IAC/E,EAAE,EAAE,MAAM,CAAC;IACX,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,OAAO,EAAE,YAAY,CAAC;IACtB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;;OAIG;IACH,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC7B;AAiBD,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,EAAE,CAoCpE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAUpF;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,aAAa,CAIf;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,CAiBtF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,MAAM,GACf,eAAe,CAuCjB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAUT"}
|
package/dist/robots.js
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-robot support — Phase 1.d of the AgenticROS strategy.
|
|
3
|
+
*
|
|
4
|
+
* For most deployments today the gateway talks to a single robot, so
|
|
5
|
+
* config.robot (a single object) is all that's used. Phase 1.d adds a
|
|
6
|
+
* `robots` array to the config so a single gateway / chat session can
|
|
7
|
+
* address multiple robots by id.
|
|
8
|
+
*
|
|
9
|
+
* This module is the source of truth for that resolution: from the raw
|
|
10
|
+
* AgenticROSConfig, what robots does the agent see, and which one is the
|
|
11
|
+
* active default? Adapters call into it from:
|
|
12
|
+
* - `ros2_list_robots` (this phase) — list everything the gateway knows about.
|
|
13
|
+
* - `ros2_list_capabilities(robot_id?)` (next iteration) — scope to one robot.
|
|
14
|
+
* - `run_mission` (next iteration) — `mission.robot_id` field.
|
|
15
|
+
* - per-tool `robot_id` (next iteration) — `ros2_publish`, `ros2_subscribe_once`,
|
|
16
|
+
* `ros2_camera_snapshot`, etc.
|
|
17
|
+
*
|
|
18
|
+
* Backwards compatibility: when `robots` is empty (i.e. nothing in
|
|
19
|
+
* config.robots), this module synthesises a one-entry list from the
|
|
20
|
+
* legacy `config.robot` object so old configs and the single-robot
|
|
21
|
+
* mental model keep working unchanged. The synthesised entry is marked
|
|
22
|
+
* default so it's selected by `getActiveRobotId()`.
|
|
23
|
+
*/
|
|
24
|
+
import { getTransportConfig } from "./config.js";
|
|
25
|
+
/**
|
|
26
|
+
* Read every robot the config knows about, in declaration order, with
|
|
27
|
+
* the legacy single-robot fallback applied when config.robots is empty.
|
|
28
|
+
*
|
|
29
|
+
* Never throws — an empty list is returned when neither config.robots
|
|
30
|
+
* nor config.robot.namespace is meaningfully set (and the synthesised
|
|
31
|
+
* fallback uses "default" as the id in that degenerate case).
|
|
32
|
+
*/
|
|
33
|
+
/** All-false default for {@link RobotSensors}. */
|
|
34
|
+
const DEFAULT_SENSORS = {
|
|
35
|
+
has_realsense: false,
|
|
36
|
+
has_lidar: false,
|
|
37
|
+
has_arm: false,
|
|
38
|
+
};
|
|
39
|
+
export function listRobots(config) {
|
|
40
|
+
const explicit = Array.isArray(config.robots) ? config.robots : [];
|
|
41
|
+
if (explicit.length > 0) {
|
|
42
|
+
return explicit.map((r) => ({
|
|
43
|
+
id: String(r.id),
|
|
44
|
+
name: r.name ?? "Robot",
|
|
45
|
+
namespace: r.namespace ?? "",
|
|
46
|
+
cameraTopic: r.cameraTopic ?? "",
|
|
47
|
+
kind: r.kind ?? "amr",
|
|
48
|
+
sensors: { ...DEFAULT_SENSORS, ...(r.sensors ?? {}) },
|
|
49
|
+
capabilities: r.capabilities,
|
|
50
|
+
source: "config",
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
// Legacy fallback — synthesise one entry from config.robot. The
|
|
54
|
+
// legacy schema doesn't carry kind/sensors/capabilities, so we
|
|
55
|
+
// default them: kind="amr" (every existing real-robot deployment we
|
|
56
|
+
// ship is an AMR with RealSense) and sensors all-false (which is
|
|
57
|
+
// overly conservative but won't surface a false positive in
|
|
58
|
+
// ros2_find_robots_for). Users on multi-robot deployments will have
|
|
59
|
+
// promoted into config.robots[] anyway, where the fields are
|
|
60
|
+
// explicit.
|
|
61
|
+
const legacy = config.robot ?? { name: "Robot", namespace: "", cameraTopic: "" };
|
|
62
|
+
const id = (legacy.namespace?.trim() || "default");
|
|
63
|
+
return [
|
|
64
|
+
{
|
|
65
|
+
id,
|
|
66
|
+
name: legacy.name ?? "Robot",
|
|
67
|
+
namespace: legacy.namespace ?? "",
|
|
68
|
+
cameraTopic: legacy.cameraTopic ?? "",
|
|
69
|
+
kind: "amr",
|
|
70
|
+
sensors: { ...DEFAULT_SENSORS },
|
|
71
|
+
source: "legacy",
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Pick the active robot's id according to these rules, in order:
|
|
77
|
+
* 1. `override` argument (when truthy) — usually a per-tool-call robot_id.
|
|
78
|
+
* 2. An entry in config.robots with `default: true`.
|
|
79
|
+
* 3. The first entry in the resolved list (which includes the legacy
|
|
80
|
+
* fallback when nothing else is configured).
|
|
81
|
+
*
|
|
82
|
+
* Throws when no robots exist at all — that should be impossible because
|
|
83
|
+
* the legacy fallback always produces at least one — but the guard is
|
|
84
|
+
* there for robustness against a corrupted config.
|
|
85
|
+
*/
|
|
86
|
+
export function getActiveRobotId(config, override) {
|
|
87
|
+
if (override && override.trim().length > 0)
|
|
88
|
+
return override.trim();
|
|
89
|
+
const explicit = Array.isArray(config.robots) ? config.robots : [];
|
|
90
|
+
const flagged = explicit.find((r) => r.default === true);
|
|
91
|
+
if (flagged)
|
|
92
|
+
return flagged.id;
|
|
93
|
+
const robots = listRobots(config);
|
|
94
|
+
if (robots.length === 0) {
|
|
95
|
+
throw new Error("No robots configured (config.robots is empty and config.robot has no namespace).");
|
|
96
|
+
}
|
|
97
|
+
return robots[0].id;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Convenience wrapper for tool handlers: extract an optional `robot_id`
|
|
101
|
+
* (a string) from a tool-args record and call `resolveRobot`. Returns
|
|
102
|
+
* the active robot when `robot_id` is missing or not a string.
|
|
103
|
+
*
|
|
104
|
+
* Throws — with the known robot ids listed in the error — when
|
|
105
|
+
* `robot_id` is set to an unknown value. Adapters surface that as a
|
|
106
|
+
* tool error so the agent self-corrects via `ros2_list_robots`.
|
|
107
|
+
*/
|
|
108
|
+
export function resolveRobotFromArgs(config, args) {
|
|
109
|
+
const raw = args["robot_id"];
|
|
110
|
+
const robotId = typeof raw === "string" ? raw : undefined;
|
|
111
|
+
return resolveRobot(config, robotId);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Resolve a robot to its full record by id. When `robotId` is omitted or
|
|
115
|
+
* empty, the active robot is returned. When `robotId` is provided but
|
|
116
|
+
* doesn't match any configured robot, throws with the available ids in
|
|
117
|
+
* the message so the agent can correct itself.
|
|
118
|
+
*/
|
|
119
|
+
export function resolveRobot(config, robotId) {
|
|
120
|
+
const robots = listRobots(config);
|
|
121
|
+
if (!robotId || robotId.trim().length === 0) {
|
|
122
|
+
const activeId = getActiveRobotId(config);
|
|
123
|
+
const found = robots.find((r) => r.id === activeId);
|
|
124
|
+
if (!found) {
|
|
125
|
+
throw new Error(`Active robot id "${activeId}" is not in the resolved list. This is a bug.`);
|
|
126
|
+
}
|
|
127
|
+
return found;
|
|
128
|
+
}
|
|
129
|
+
const trimmed = robotId.trim();
|
|
130
|
+
const found = robots.find((r) => r.id === trimmed);
|
|
131
|
+
if (!found) {
|
|
132
|
+
const known = robots.map((r) => r.id).join(", ");
|
|
133
|
+
throw new Error(`Unknown robot_id "${trimmed}". Known ids: ${known || "(none)"}. Use ros2_list_robots to discover.`);
|
|
134
|
+
}
|
|
135
|
+
return found;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Phase 1.d-resolve helper: compute the effective `TransportConfig` for
|
|
139
|
+
* a given robot, honouring an optional per-robot override in
|
|
140
|
+
* `config.robots[i].transport`.
|
|
141
|
+
*
|
|
142
|
+
* Precedence (most specific wins):
|
|
143
|
+
* 1. The robot's `transport.<mode>` sub-section (e.g. the override's
|
|
144
|
+
* `zenoh: { routerEndpoint: ... }`).
|
|
145
|
+
* 2. The top-level `config.<mode>` section (e.g. the global
|
|
146
|
+
* `config.zenoh`).
|
|
147
|
+
*
|
|
148
|
+
* When the robot has no `transport` override at all, this returns the
|
|
149
|
+
* global transport from `getTransportConfig(config)` — so single-robot
|
|
150
|
+
* deployments behave exactly as before.
|
|
151
|
+
*
|
|
152
|
+
* Why this lives here (and not next to `createTransport`):
|
|
153
|
+
* - The resolver owns "which robot are we talking about?"; the
|
|
154
|
+
* transport factory owns "given a TransportConfig, build an
|
|
155
|
+
* instance". Mixing them couples a multi-robot decision into the
|
|
156
|
+
* low-level transport layer, which is wrong: adapters that don't
|
|
157
|
+
* care about per-robot transports keep using `createTransport` and
|
|
158
|
+
* never see this helper.
|
|
159
|
+
* - Callers that DO want per-robot pools call this to materialise the
|
|
160
|
+
* right `TransportConfig` per id, then hand it to `createTransport`.
|
|
161
|
+
*
|
|
162
|
+
* Throws when `robotId` is given but doesn't match any configured robot
|
|
163
|
+
* (delegated to `resolveRobot`'s error path).
|
|
164
|
+
*/
|
|
165
|
+
export function getTransportConfigForRobot(config, robotId) {
|
|
166
|
+
// No explicit robots[] AND no override possible — fast path.
|
|
167
|
+
const explicit = Array.isArray(config.robots) ? config.robots : [];
|
|
168
|
+
if (explicit.length === 0)
|
|
169
|
+
return getTransportConfig(config);
|
|
170
|
+
// Resolve the id to the *raw* entry (not the synthesised ResolvedRobot,
|
|
171
|
+
// because that strips the override). `resolveRobot` validates the id
|
|
172
|
+
// and throws on unknown — we reuse it for that side effect.
|
|
173
|
+
const robot = resolveRobot(config, robotId);
|
|
174
|
+
const raw = explicit.find((r) => r.id === robot.id);
|
|
175
|
+
if (!raw || !raw.transport)
|
|
176
|
+
return getTransportConfig(config);
|
|
177
|
+
// Build a synthetic config whose top-level transport mirrors the
|
|
178
|
+
// override, then run it through the standard `getTransportConfig`
|
|
179
|
+
// path. This keeps the "what shape does TransportConfig take?" logic
|
|
180
|
+
// in one place — if a new transport mode is added, only
|
|
181
|
+
// getTransportConfig needs to change.
|
|
182
|
+
const override = raw.transport;
|
|
183
|
+
const synthetic = {
|
|
184
|
+
...config,
|
|
185
|
+
transport: { mode: override.mode },
|
|
186
|
+
rosbridge: override.mode === "rosbridge" && override.rosbridge
|
|
187
|
+
? { ...config.rosbridge, ...override.rosbridge }
|
|
188
|
+
: config.rosbridge,
|
|
189
|
+
local: override.mode === "local" && override.local
|
|
190
|
+
? { ...config.local, ...override.local }
|
|
191
|
+
: config.local,
|
|
192
|
+
zenoh: override.mode === "zenoh" && override.zenoh
|
|
193
|
+
? { ...config.zenoh, ...override.zenoh }
|
|
194
|
+
: config.zenoh,
|
|
195
|
+
webrtc: override.mode === "webrtc" && override.webrtc
|
|
196
|
+
? { ...config.webrtc, ...override.webrtc }
|
|
197
|
+
: config.webrtc,
|
|
198
|
+
};
|
|
199
|
+
return getTransportConfig(synthetic);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* True when the named robot (or active robot when `robotId` is omitted)
|
|
203
|
+
* has a per-robot transport override. Adapters use this as a cheap
|
|
204
|
+
* branch to decide between "reuse the global transport" (fast path) and
|
|
205
|
+
* "build a per-robot one via `getTransportConfigForRobot`" (pool path).
|
|
206
|
+
*/
|
|
207
|
+
export function hasRobotTransportOverride(config, robotId) {
|
|
208
|
+
const explicit = Array.isArray(config.robots) ? config.robots : [];
|
|
209
|
+
if (explicit.length === 0)
|
|
210
|
+
return false;
|
|
211
|
+
try {
|
|
212
|
+
const robot = resolveRobot(config, robotId);
|
|
213
|
+
const raw = explicit.find((r) => r.id === robot.id);
|
|
214
|
+
return Boolean(raw?.transport);
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=robots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"robots.js","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AA8CjD;;;;;;;GAOG;AACH,kDAAkD;AAClD,MAAM,eAAe,GAAiB;IACpC,aAAa,EAAE,KAAK;IACpB,SAAS,EAAE,KAAK;IAChB,OAAO,EAAE,KAAK;CACf,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,MAAwB;IACjD,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC1B,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YAChB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,OAAO;YACvB,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,EAAE;YAC5B,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,EAAE;YAChC,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK;YACrB,OAAO,EAAE,EAAE,GAAG,eAAe,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE;YACrD,YAAY,EAAE,CAAC,CAAC,YAAY;YAC5B,MAAM,EAAE,QAAiB;SAC1B,CAAC,CAAC,CAAC;IACN,CAAC;IAED,gEAAgE;IAChE,+DAA+D;IAC/D,oEAAoE;IACpE,iEAAiE;IACjE,4DAA4D;IAC5D,oEAAoE;IACpE,6DAA6D;IAC7D,YAAY;IACZ,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;IACjF,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC,CAAC;IACnD,OAAO;QACL;YACE,EAAE;YACF,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,OAAO;YAC5B,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,EAAE;YACjC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;YACrC,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,EAAE,GAAG,eAAe,EAAE;YAC/B,MAAM,EAAE,QAAQ;SACjB;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAwB,EAAE,QAAiB;IAC1E,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnE,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;IACzD,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,kFAAkF,CAAC,CAAC;IACtG,CAAC;IACD,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACtB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAwB,EACxB,IAA6B;IAE7B,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1D,OAAO,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACvC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAwB,EAAE,OAAgB;IACrE,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QACpD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,+CAA+C,CAAC,CAAC;QAC/F,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,qBAAqB,OAAO,iBAAiB,KAAK,IAAI,QAAQ,qCAAqC,CAAC,CAAC;IACvH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAAwB,EACxB,OAAgB;IAEhB,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAE7D,wEAAwE;IACxE,qEAAqE;IACrE,4DAA4D;IAC5D,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC,CAAC;IACpD,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS;QAAE,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAE9D,iEAAiE;IACjE,kEAAkE;IAClE,qEAAqE;IACrE,wDAAwD;IACxD,sCAAsC;IACtC,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC;IAC/B,MAAM,SAAS,GAAqB;QAClC,GAAG,MAAM;QACT,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE;QAClC,SAAS,EACP,QAAQ,CAAC,IAAI,KAAK,WAAW,IAAI,QAAQ,CAAC,SAAS;YACjD,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,SAAS,EAAE,GAAG,QAAQ,CAAC,SAAS,EAAE;YAChD,CAAC,CAAC,MAAM,CAAC,SAAS;QACtB,KAAK,EACH,QAAQ,CAAC,IAAI,KAAK,OAAO,IAAI,QAAQ,CAAC,KAAK;YACzC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE;YACxC,CAAC,CAAC,MAAM,CAAC,KAAK;QAClB,KAAK,EACH,QAAQ,CAAC,IAAI,KAAK,OAAO,IAAI,QAAQ,CAAC,KAAK;YACzC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE;YACxC,CAAC,CAAC,MAAM,CAAC,KAAK;QAClB,MAAM,EACJ,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM;YAC3C,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,EAAE;YAC1C,CAAC,CAAC,MAAM,CAAC,MAAM;KACpB,CAAC;IACF,OAAO,kBAAkB,CAAC,SAAS,CAAC,CAAC;AACvC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAAwB,EACxB,OAAgB;IAEhB,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC,CAAC;QACpD,OAAO,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { AgenticROSConfig } from "./config.js";
|
|
2
|
+
/**
|
|
3
|
+
* Apply robot namespace to a topic (or service/action name) when configured.
|
|
4
|
+
* If the namespace is set and the name is root-level (e.g. cmd_vel, battery_state),
|
|
5
|
+
* returns /<namespace>/<name>. Otherwise returns the normalized name as-is.
|
|
6
|
+
*
|
|
7
|
+
* The first argument may be either an `AgenticROSConfig` (legacy single-
|
|
8
|
+
* robot path) or a bare namespace string (used by per-tool `robot_id`
|
|
9
|
+
* routing — pass `resolveRobot(config, robot_id).namespace`).
|
|
10
|
+
*
|
|
11
|
+
* Example: namespace "robot-uuid", topic "/cmd_vel" -> "/robot-uuid/cmd_vel"
|
|
12
|
+
* Example: namespace "", topic "/cmd_vel" -> "/cmd_vel"
|
|
13
|
+
* Example: namespace "robot-uuid", topic "/robot-uuid/odom" -> "/robot-uuid/odom" (unchanged)
|
|
14
|
+
*/
|
|
15
|
+
export declare function toNamespacedTopic(target: AgenticROSConfig | string, topic: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Apply robot namespace to any topic when configured (for transport subscribe/publish).
|
|
18
|
+
* Use this when the robot publishes/subscribes all topics under a namespace (e.g. Zenoh with
|
|
19
|
+
* zenoh-bridge-ros2dds or rmw_zenoh). If a namespace is set, returns /<namespace>/<topic>
|
|
20
|
+
* unless the topic already starts with /<namespace>/.
|
|
21
|
+
*
|
|
22
|
+
* The first argument may be either an `AgenticROSConfig` or a bare
|
|
23
|
+
* namespace string (per-robot routing).
|
|
24
|
+
*
|
|
25
|
+
* Example: namespace "robot-uuid", topic "/cmd_vel" -> "/robot-uuid/cmd_vel"
|
|
26
|
+
* Example: namespace "robot-uuid", topic "/camera/camera/color/image_raw/compressed" -> "/robot-uuid/camera/camera/color/image_raw/compressed"
|
|
27
|
+
* Example: namespace "robot-uuid", topic "/robot-uuid/odom" -> "/robot-uuid/odom" (unchanged)
|
|
28
|
+
*/
|
|
29
|
+
export declare function toNamespacedTopicFull(target: AgenticROSConfig | string, topic: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Canonical topic string for teleop UI and ?topic= query params: leading slash, no robot namespace prefix.
|
|
32
|
+
* Subscribe/publish still uses {@link toNamespacedTopicFull} on the server so Zenoh keys match the bridge.
|
|
33
|
+
*
|
|
34
|
+
* Teleop is single-robot today, so this still takes the full config.
|
|
35
|
+
*/
|
|
36
|
+
export declare function toTeleopCameraTopicShort(config: AgenticROSConfig, topic: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* ROS topic to use when subscribing to camera streams (Zenoh / DDS).
|
|
39
|
+
* Unlike {@link toNamespacedTopicFull}, common sensor topics stay at the graph root (`/camera/...`, `/zed/...`)
|
|
40
|
+
* even when the namespace is set for cmd_vel. If the topic already starts with `/<namespace>/`, it is left as-is.
|
|
41
|
+
* Other multi-segment paths get the namespace prefix (same as Full) for odd layouts.
|
|
42
|
+
*
|
|
43
|
+
* The first argument may be either an `AgenticROSConfig` or a bare
|
|
44
|
+
* namespace string (per-robot routing).
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolveCameraSubscribeTopic(target: AgenticROSConfig | string, topic: string): string;
|
|
47
|
+
//# sourceMappingURL=topic-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topic-utils.d.ts","sourceRoot":"","sources":["../src/topic-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA4CpD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAO1F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ9F;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAYxF;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAcpG"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Topic-utility module — the single source of truth for namespace
|
|
3
|
+
* prefixing across all adapters and the mission runner.
|
|
4
|
+
*
|
|
5
|
+
* Phase 1.d (multi-robot) extends every public helper to accept *either*
|
|
6
|
+
* the full AgenticROSConfig (uses config.robot.namespace, the legacy
|
|
7
|
+
* single-robot behaviour) *or* a bare namespace string. The string-arg
|
|
8
|
+
* form is what per-tool `robot_id` routing goes through: callers resolve
|
|
9
|
+
* a `ResolvedRobot` via `resolveRobot(config, robot_id)` and pass
|
|
10
|
+
* `robot.namespace` directly.
|
|
11
|
+
*
|
|
12
|
+
* Every existing call site continues to work unchanged because the
|
|
13
|
+
* config-arg form is preserved verbatim.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Normalize a ROS 2 topic name to a canonical form (leading slash, no trailing slash).
|
|
17
|
+
*/
|
|
18
|
+
function normalizeTopic(topic) {
|
|
19
|
+
const t = topic.trim().replace(/^\/+/, "").replace(/\/+$/, "");
|
|
20
|
+
return t ? `/${t}` : "/";
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Return true if the topic is "root-level" (single segment, e.g. cmd_vel, battery_state).
|
|
24
|
+
*/
|
|
25
|
+
function isRootLevelTopic(normalized) {
|
|
26
|
+
const withoutLeading = normalized.replace(/^\/+/, "");
|
|
27
|
+
return withoutLeading.length > 0 && !withoutLeading.includes("/");
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve a namespace from either a string or an AgenticROSConfig. The
|
|
31
|
+
* config form pulls from config.robot.namespace (legacy single-robot
|
|
32
|
+
* behaviour); the string form is taken verbatim. Empty/whitespace
|
|
33
|
+
* collapses to "" so the rest of the prefix logic short-circuits.
|
|
34
|
+
*/
|
|
35
|
+
function resolveNamespace(target) {
|
|
36
|
+
if (typeof target === "string")
|
|
37
|
+
return target.trim();
|
|
38
|
+
return (target.robot?.namespace ?? "").trim();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Apply robot namespace to a topic (or service/action name) when configured.
|
|
42
|
+
* If the namespace is set and the name is root-level (e.g. cmd_vel, battery_state),
|
|
43
|
+
* returns /<namespace>/<name>. Otherwise returns the normalized name as-is.
|
|
44
|
+
*
|
|
45
|
+
* The first argument may be either an `AgenticROSConfig` (legacy single-
|
|
46
|
+
* robot path) or a bare namespace string (used by per-tool `robot_id`
|
|
47
|
+
* routing — pass `resolveRobot(config, robot_id).namespace`).
|
|
48
|
+
*
|
|
49
|
+
* Example: namespace "robot-uuid", topic "/cmd_vel" -> "/robot-uuid/cmd_vel"
|
|
50
|
+
* Example: namespace "", topic "/cmd_vel" -> "/cmd_vel"
|
|
51
|
+
* Example: namespace "robot-uuid", topic "/robot-uuid/odom" -> "/robot-uuid/odom" (unchanged)
|
|
52
|
+
*/
|
|
53
|
+
export function toNamespacedTopic(target, topic) {
|
|
54
|
+
const normalized = normalizeTopic(topic);
|
|
55
|
+
const ns = resolveNamespace(target);
|
|
56
|
+
if (!ns)
|
|
57
|
+
return normalized;
|
|
58
|
+
if (!isRootLevelTopic(normalized))
|
|
59
|
+
return normalized;
|
|
60
|
+
const segment = normalized.replace(/^\/+/, "");
|
|
61
|
+
return `/${ns}/${segment}`;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Apply robot namespace to any topic when configured (for transport subscribe/publish).
|
|
65
|
+
* Use this when the robot publishes/subscribes all topics under a namespace (e.g. Zenoh with
|
|
66
|
+
* zenoh-bridge-ros2dds or rmw_zenoh). If a namespace is set, returns /<namespace>/<topic>
|
|
67
|
+
* unless the topic already starts with /<namespace>/.
|
|
68
|
+
*
|
|
69
|
+
* The first argument may be either an `AgenticROSConfig` or a bare
|
|
70
|
+
* namespace string (per-robot routing).
|
|
71
|
+
*
|
|
72
|
+
* Example: namespace "robot-uuid", topic "/cmd_vel" -> "/robot-uuid/cmd_vel"
|
|
73
|
+
* Example: namespace "robot-uuid", topic "/camera/camera/color/image_raw/compressed" -> "/robot-uuid/camera/camera/color/image_raw/compressed"
|
|
74
|
+
* Example: namespace "robot-uuid", topic "/robot-uuid/odom" -> "/robot-uuid/odom" (unchanged)
|
|
75
|
+
*/
|
|
76
|
+
export function toNamespacedTopicFull(target, topic) {
|
|
77
|
+
const normalized = normalizeTopic(topic);
|
|
78
|
+
const ns = resolveNamespace(target);
|
|
79
|
+
if (!ns)
|
|
80
|
+
return normalized;
|
|
81
|
+
const withoutLeading = normalized.replace(/^\/+/, "");
|
|
82
|
+
if (!withoutLeading)
|
|
83
|
+
return normalized;
|
|
84
|
+
if (withoutLeading.startsWith(`${ns}/`) || withoutLeading === ns)
|
|
85
|
+
return normalized;
|
|
86
|
+
return `/${ns}/${withoutLeading}`;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Canonical topic string for teleop UI and ?topic= query params: leading slash, no robot namespace prefix.
|
|
90
|
+
* Subscribe/publish still uses {@link toNamespacedTopicFull} on the server so Zenoh keys match the bridge.
|
|
91
|
+
*
|
|
92
|
+
* Teleop is single-robot today, so this still takes the full config.
|
|
93
|
+
*/
|
|
94
|
+
export function toTeleopCameraTopicShort(config, topic) {
|
|
95
|
+
const normalized = normalizeTopic(topic);
|
|
96
|
+
const ns = (config.robot?.namespace ?? "").trim();
|
|
97
|
+
if (!ns)
|
|
98
|
+
return normalized;
|
|
99
|
+
const withoutLeading = normalized.replace(/^\/+/, "");
|
|
100
|
+
if (!withoutLeading)
|
|
101
|
+
return normalized;
|
|
102
|
+
if (withoutLeading === ns)
|
|
103
|
+
return "/";
|
|
104
|
+
if (withoutLeading.startsWith(`${ns}/`)) {
|
|
105
|
+
const rest = withoutLeading.slice(ns.length + 1);
|
|
106
|
+
return rest ? `/${rest}` : "/";
|
|
107
|
+
}
|
|
108
|
+
return normalized;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* ROS topic to use when subscribing to camera streams (Zenoh / DDS).
|
|
112
|
+
* Unlike {@link toNamespacedTopicFull}, common sensor topics stay at the graph root (`/camera/...`, `/zed/...`)
|
|
113
|
+
* even when the namespace is set for cmd_vel. If the topic already starts with `/<namespace>/`, it is left as-is.
|
|
114
|
+
* Other multi-segment paths get the namespace prefix (same as Full) for odd layouts.
|
|
115
|
+
*
|
|
116
|
+
* The first argument may be either an `AgenticROSConfig` or a bare
|
|
117
|
+
* namespace string (per-robot routing).
|
|
118
|
+
*/
|
|
119
|
+
export function resolveCameraSubscribeTopic(target, topic) {
|
|
120
|
+
const normalized = normalizeTopic(topic);
|
|
121
|
+
const ns = resolveNamespace(target);
|
|
122
|
+
if (!ns)
|
|
123
|
+
return normalized;
|
|
124
|
+
const withoutLeading = normalized.replace(/^\/+/, "");
|
|
125
|
+
if (!withoutLeading)
|
|
126
|
+
return normalized;
|
|
127
|
+
if (withoutLeading === ns || withoutLeading.startsWith(`${ns}/`))
|
|
128
|
+
return normalized;
|
|
129
|
+
const first = withoutLeading.split("/")[0] ?? "";
|
|
130
|
+
/** First path segment for topics that usually remain unprefixed while cmd_vel is namespaced. */
|
|
131
|
+
const globalRoots = new Set(["camera", "zed", "usb_cam", "image_raw", "depth"]);
|
|
132
|
+
if (first && globalRoots.has(first))
|
|
133
|
+
return normalized;
|
|
134
|
+
return `/${ns}/${withoutLeading}`;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=topic-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topic-utils.js","sourceRoot":"","sources":["../src/topic-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TransportConfig } from "./types.js";
|
|
2
|
+
import type { RosTransport } from "./transport.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create a RosTransport instance for the given deployment mode.
|
|
5
|
+
*
|
|
6
|
+
* Uses dynamic import() to load the correct adapter so that
|
|
7
|
+
* unused adapters (and their dependencies) are never loaded.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createTransport(config: TransportConfig): Promise<RosTransport>;
|
|
10
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/transport/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CAqCpF"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a RosTransport instance for the given deployment mode.
|
|
3
|
+
*
|
|
4
|
+
* Uses dynamic import() to load the correct adapter so that
|
|
5
|
+
* unused adapters (and their dependencies) are never loaded.
|
|
6
|
+
*/
|
|
7
|
+
export async function createTransport(config) {
|
|
8
|
+
switch (config.mode) {
|
|
9
|
+
case "rosbridge": {
|
|
10
|
+
const { RosbridgeTransport } = await import("./rosbridge/adapter.js");
|
|
11
|
+
return new RosbridgeTransport(config.rosbridge);
|
|
12
|
+
}
|
|
13
|
+
case "local": {
|
|
14
|
+
try {
|
|
15
|
+
const { LocalTransport } = await import("./local/transport.js");
|
|
16
|
+
return new LocalTransport(config.local);
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
if (e?.code === "ERR_MODULE_NOT_FOUND" || e?.code === "MODULE_NOT_FOUND") {
|
|
20
|
+
throw new Error('Mode A (local) requires the "rclnodejs" package. ' +
|
|
21
|
+
"Install it with: pnpm add rclnodejs (with ROS2 workspace sourced)");
|
|
22
|
+
}
|
|
23
|
+
throw e;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
case "webrtc": {
|
|
27
|
+
const { WebRTCTransport } = await import("./webrtc/transport.js");
|
|
28
|
+
return new WebRTCTransport(config.webrtc);
|
|
29
|
+
}
|
|
30
|
+
case "zenoh": {
|
|
31
|
+
const { ZenohTransport } = await import("./zenoh/adapter.js");
|
|
32
|
+
return new ZenohTransport(config.zenoh);
|
|
33
|
+
}
|
|
34
|
+
default: {
|
|
35
|
+
const _exhaustive = config;
|
|
36
|
+
throw new Error(`Unknown transport mode: ${_exhaustive.mode}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/transport/factory.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAuB;IAC3D,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;YACtE,OAAO,IAAI,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClD,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,IAAI,CAAC;gBACH,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;gBAChE,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC1C,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,IAAI,CAAC,EAAE,IAAI,KAAK,sBAAsB,IAAI,CAAC,EAAE,IAAI,KAAK,kBAAkB,EAAE,CAAC;oBACzE,MAAM,IAAI,KAAK,CACb,mDAAmD;wBACjD,mEAAmE,CACtE,CAAC;gBACJ,CAAC;gBACD,MAAM,CAAC,CAAC;YACV,CAAC;QACH,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;YAClE,OAAO,IAAI,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC9D,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,WAAW,GAAU,MAAM,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,2BAA4B,WAA+B,CAAC,IAAI,EAAE,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message conversion between plain JS objects and rclnodejs typed messages.
|
|
3
|
+
*
|
|
4
|
+
* The RosTransport interface works with `Record<string, unknown>`, but
|
|
5
|
+
* rclnodejs works with typed message class instances. This module bridges
|
|
6
|
+
* the two — analogous to rosbridge_library's `dict_to_msg` / `msg_to_dict`.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Load a ROS2 message/service/action class via rclnodejs, with caching.
|
|
10
|
+
*/
|
|
11
|
+
export declare function loadMessageClass(typeStr: string): any;
|
|
12
|
+
/**
|
|
13
|
+
* Convert a plain JS object to an rclnodejs message instance.
|
|
14
|
+
*
|
|
15
|
+
* Recursively assigns fields from `obj` onto a new message instance,
|
|
16
|
+
* handling nested sub-messages (e.g. Twist.linear is a Vector3).
|
|
17
|
+
*/
|
|
18
|
+
export declare function toRosMessage(typeStr: string, obj: Record<string, unknown>): any;
|
|
19
|
+
/**
|
|
20
|
+
* Convert an rclnodejs message instance to a plain JS object.
|
|
21
|
+
*
|
|
22
|
+
* Uses `toPlainObject()` if available (rclnodejs >= 0.21), otherwise
|
|
23
|
+
* falls back to manual recursive field extraction.
|
|
24
|
+
*/
|
|
25
|
+
export declare function fromRosMessage(msg: any, rosTypeHint?: string): Record<string, unknown>;
|
|
26
|
+
/**
|
|
27
|
+
* Clear the type cache. Called during shutdown.
|
|
28
|
+
*/
|
|
29
|
+
export declare function clearTypeCache(): void;
|
|
30
|
+
//# sourceMappingURL=conversion.d.ts.map
|