@agenticros/core 0.8.4 → 0.8.6
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/dist/capabilities.js +1 -1
- package/dist/capabilities.js.map +1 -1
- package/dist/config.d.ts +185 -35
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +29 -8
- package/dist/config.js.map +1 -1
- package/dist/external-capability.d.ts +3 -0
- package/dist/external-capability.d.ts.map +1 -1
- package/dist/external-capability.js +10 -0
- package/dist/external-capability.js.map +1 -1
- package/dist/find-robots-for.d.ts.map +1 -1
- package/dist/find-robots-for.js +15 -5
- package/dist/find-robots-for.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/robot-profile.d.ts.map +1 -1
- package/dist/robot-profile.js +3 -0
- package/dist/robot-profile.js.map +1 -1
- package/dist/robots.d.ts +6 -1
- package/dist/robots.d.ts.map +1 -1
- package/dist/robots.js +1 -0
- package/dist/robots.js.map +1 -1
- package/dist/safety.d.ts +116 -0
- package/dist/safety.d.ts.map +1 -0
- package/dist/safety.js +365 -0
- package/dist/safety.js.map +1 -0
- package/dist/transport-pool.d.ts +4 -0
- package/dist/transport-pool.d.ts.map +1 -1
- package/dist/transport-pool.js +47 -5
- package/dist/transport-pool.js.map +1 -1
- package/package.json +9 -10
package/dist/safety.js
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared safety gates: per-robot velocity limits, optional workspace
|
|
3
|
+
* geofence, and fail-safe zero-Twist on transport loss.
|
|
4
|
+
*
|
|
5
|
+
* Adapters (MCP, OpenClaw, Gemini, teleop, skills) must call these
|
|
6
|
+
* helpers rather than reading `config.safety` directly so a mixed
|
|
7
|
+
* fleet does not share one clamp.
|
|
8
|
+
*/
|
|
9
|
+
import { resolveBinding } from "./robot-profile.js";
|
|
10
|
+
export const TWIST_MSG_TYPE = "geometry_msgs/msg/Twist";
|
|
11
|
+
export const ZERO_TWIST = {
|
|
12
|
+
linear: { x: 0, y: 0, z: 0 },
|
|
13
|
+
angular: { x: 0, y: 0, z: 0 },
|
|
14
|
+
};
|
|
15
|
+
const PASS = { block: false };
|
|
16
|
+
function overlayOf(robot) {
|
|
17
|
+
return robot?.safety;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolve velocity + workspace limits for a robot. Robot overlay fields
|
|
21
|
+
* win; unset fields inherit the gateway `config.safety` defaults.
|
|
22
|
+
*/
|
|
23
|
+
export function resolveSafetyForRobot(config, robot) {
|
|
24
|
+
const gateway = config.safety ?? {
|
|
25
|
+
maxLinearVelocity: 1.0,
|
|
26
|
+
maxAngularVelocity: 1.5,
|
|
27
|
+
};
|
|
28
|
+
const overlay = overlayOf(robot);
|
|
29
|
+
return {
|
|
30
|
+
maxLinearVelocity: overlay?.maxLinearVelocity ?? gateway.maxLinearVelocity ?? 1.0,
|
|
31
|
+
maxAngularVelocity: overlay?.maxAngularVelocity ?? gateway.maxAngularVelocity ?? 1.5,
|
|
32
|
+
workspaceLimits: overlay?.workspaceLimits ?? gateway.workspaceLimits,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function asRecord(value) {
|
|
36
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
37
|
+
return undefined;
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
function num(value, fallback = 0) {
|
|
41
|
+
const n = Number(value);
|
|
42
|
+
return Number.isFinite(n) ? n : fallback;
|
|
43
|
+
}
|
|
44
|
+
/** True when the payload looks like geometry_msgs/Twist. */
|
|
45
|
+
export function isTwistMessage(msg) {
|
|
46
|
+
const rec = asRecord(msg);
|
|
47
|
+
if (!rec)
|
|
48
|
+
return false;
|
|
49
|
+
return asRecord(rec["linear"]) !== undefined || asRecord(rec["angular"]) !== undefined;
|
|
50
|
+
}
|
|
51
|
+
export function checkTwistMessage(limits, msg) {
|
|
52
|
+
if (!isTwistMessage(msg))
|
|
53
|
+
return PASS;
|
|
54
|
+
const rec = asRecord(msg);
|
|
55
|
+
const linear = asRecord(rec["linear"]);
|
|
56
|
+
const angular = asRecord(rec["angular"]);
|
|
57
|
+
if (linear) {
|
|
58
|
+
const speed = Math.sqrt(num(linear["x"]) ** 2 + num(linear["y"]) ** 2 + num(linear["z"]) ** 2);
|
|
59
|
+
if (speed > limits.maxLinearVelocity) {
|
|
60
|
+
return {
|
|
61
|
+
block: true,
|
|
62
|
+
blockReason: `Linear velocity ${speed.toFixed(2)} m/s exceeds safety limit of ${limits.maxLinearVelocity} m/s`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (angular) {
|
|
67
|
+
const rate = Math.abs(num(angular["z"]));
|
|
68
|
+
if (rate > limits.maxAngularVelocity) {
|
|
69
|
+
return {
|
|
70
|
+
block: true,
|
|
71
|
+
blockReason: `Angular velocity ${rate.toFixed(2)} rad/s exceeds safety limit of ${limits.maxAngularVelocity} rad/s`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return PASS;
|
|
76
|
+
}
|
|
77
|
+
/** Scale a Twist down to the velocity ceilings (teleop / skills). */
|
|
78
|
+
export function clampTwistToLimits(limits, linearX, linearY, linearZ, angularX, angularY, angularZ) {
|
|
79
|
+
const maxLin = limits.maxLinearVelocity;
|
|
80
|
+
const maxAng = limits.maxAngularVelocity;
|
|
81
|
+
const linMag = Math.sqrt(linearX * linearX + linearY * linearY + linearZ * linearZ);
|
|
82
|
+
const scaleLin = linMag > maxLin && linMag > 0 ? maxLin / linMag : 1;
|
|
83
|
+
const angMag = Math.abs(angularZ);
|
|
84
|
+
const scaleAng = angMag > maxAng && angMag > 0 ? maxAng / angMag : 1;
|
|
85
|
+
return {
|
|
86
|
+
linear: {
|
|
87
|
+
x: linearX * scaleLin,
|
|
88
|
+
y: linearY * scaleLin,
|
|
89
|
+
z: linearZ * scaleLin,
|
|
90
|
+
},
|
|
91
|
+
angular: {
|
|
92
|
+
x: angularX * scaleAng,
|
|
93
|
+
y: angularY * scaleAng,
|
|
94
|
+
z: Math.max(-maxAng, Math.min(maxAng, angularZ)),
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function workspaceMalformed(bounds) {
|
|
99
|
+
if (bounds.xMin > bounds.xMax) {
|
|
100
|
+
return `Malformed workspaceLimits: xMin (${bounds.xMin}) > xMax (${bounds.xMax})`;
|
|
101
|
+
}
|
|
102
|
+
if (bounds.yMin > bounds.yMax) {
|
|
103
|
+
return `Malformed workspaceLimits: yMin (${bounds.yMin}) > yMax (${bounds.yMax})`;
|
|
104
|
+
}
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
export function checkWorkspacePosition(limits, x, y) {
|
|
108
|
+
const bounds = limits.workspaceLimits;
|
|
109
|
+
if (!bounds)
|
|
110
|
+
return PASS;
|
|
111
|
+
const malformed = workspaceMalformed(bounds);
|
|
112
|
+
if (malformed)
|
|
113
|
+
return { block: true, blockReason: malformed };
|
|
114
|
+
if (x < bounds.xMin || x > bounds.xMax || y < bounds.yMin || y > bounds.yMax) {
|
|
115
|
+
return {
|
|
116
|
+
block: true,
|
|
117
|
+
blockReason: `Position (${x.toFixed(2)}, ${y.toFixed(2)}) is outside workspaceLimits ` +
|
|
118
|
+
`[x ${bounds.xMin}..${bounds.xMax}, y ${bounds.yMin}..${bounds.yMax}]`,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return PASS;
|
|
122
|
+
}
|
|
123
|
+
function pushPosition(out, rec) {
|
|
124
|
+
if (!rec)
|
|
125
|
+
return;
|
|
126
|
+
if ("x" in rec && "y" in rec) {
|
|
127
|
+
out.push({ x: num(rec["x"]), y: num(rec["y"]) });
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const position = asRecord(rec["position"]);
|
|
131
|
+
if (position && "x" in position && "y" in position) {
|
|
132
|
+
out.push({ x: num(position["x"]), y: num(position["y"]) });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Pull map-frame (x, y) pairs from Twist-unrelated nav payloads:
|
|
137
|
+
* `{x,y}`, Pose, PoseStamped, NavigateToPose goal, NavigateThroughPoses.
|
|
138
|
+
*/
|
|
139
|
+
export function extractWorkspacePositions(payload) {
|
|
140
|
+
const out = [];
|
|
141
|
+
const rec = asRecord(payload);
|
|
142
|
+
if (!rec)
|
|
143
|
+
return out;
|
|
144
|
+
if (Array.isArray(rec["poses"])) {
|
|
145
|
+
for (const p of rec["poses"]) {
|
|
146
|
+
out.push(...extractWorkspacePositions(p));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const nestedGoal = rec["goal"] ?? rec["request"] ?? rec["message"];
|
|
150
|
+
if (nestedGoal && nestedGoal !== payload) {
|
|
151
|
+
out.push(...extractWorkspacePositions(nestedGoal));
|
|
152
|
+
}
|
|
153
|
+
const pose = asRecord(rec["pose"]);
|
|
154
|
+
if (pose) {
|
|
155
|
+
const inner = asRecord(pose["pose"]);
|
|
156
|
+
if (inner) {
|
|
157
|
+
pushPosition(out, inner);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
pushPosition(out, pose);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if ("x" in rec && "y" in rec && !asRecord(rec["linear"]) && !asRecord(rec["angular"])) {
|
|
164
|
+
pushPosition(out, rec);
|
|
165
|
+
}
|
|
166
|
+
return out;
|
|
167
|
+
}
|
|
168
|
+
export function checkWorkspacePayload(limits, payload) {
|
|
169
|
+
if (!limits.workspaceLimits)
|
|
170
|
+
return PASS;
|
|
171
|
+
for (const pos of extractWorkspacePositions(payload)) {
|
|
172
|
+
const hit = checkWorkspacePosition(limits, pos.x, pos.y);
|
|
173
|
+
if (hit.block)
|
|
174
|
+
return hit;
|
|
175
|
+
}
|
|
176
|
+
return PASS;
|
|
177
|
+
}
|
|
178
|
+
export function checkPublishSafety(config, params, robot) {
|
|
179
|
+
const limits = resolveSafetyForRobot(config, robot);
|
|
180
|
+
const msg = params["message"];
|
|
181
|
+
const twist = checkTwistMessage(limits, msg);
|
|
182
|
+
if (twist.block)
|
|
183
|
+
return twist;
|
|
184
|
+
return checkWorkspacePayload(limits, msg);
|
|
185
|
+
}
|
|
186
|
+
export function checkActionGoalSafety(config, params, robot) {
|
|
187
|
+
const limits = resolveSafetyForRobot(config, robot);
|
|
188
|
+
const goal = params["goal"] ?? params["args"] ?? params["inputs"] ?? params;
|
|
189
|
+
return checkWorkspacePayload(limits, goal);
|
|
190
|
+
}
|
|
191
|
+
export function checkInputsWorkspace(config, inputs, robot) {
|
|
192
|
+
return checkWorkspacePayload(resolveSafetyForRobot(config, robot), inputs);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* A body that accepts Twist. Profile `base` wins; with no profile,
|
|
196
|
+
* anything except an arm-only cell is treated as having a base
|
|
197
|
+
* (legacy configs default kind to "amr").
|
|
198
|
+
*/
|
|
199
|
+
export function robotHasMobileBase(robot) {
|
|
200
|
+
if (robot.profile) {
|
|
201
|
+
return robot.profile.features.includes("base");
|
|
202
|
+
}
|
|
203
|
+
const kind = (robot.kind ?? "amr").trim().toLowerCase();
|
|
204
|
+
return kind !== "arm";
|
|
205
|
+
}
|
|
206
|
+
const STOP_PUBLISH_BUDGET_MS = 500;
|
|
207
|
+
/** Best-effort zero Twist on every mobile-base robot sharing this transport. */
|
|
208
|
+
export async function publishStopForBases(transport, robots) {
|
|
209
|
+
const pubs = [];
|
|
210
|
+
for (const robot of robots) {
|
|
211
|
+
if (!robotHasMobileBase(robot))
|
|
212
|
+
continue;
|
|
213
|
+
const topic = resolveBinding(robot, "cmd_vel");
|
|
214
|
+
if (!topic)
|
|
215
|
+
continue;
|
|
216
|
+
try {
|
|
217
|
+
transport.advertise?.({ topic, type: TWIST_MSG_TYPE });
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
/* rosbridge advertise is optional */
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
const result = transport.publish({
|
|
224
|
+
topic,
|
|
225
|
+
type: TWIST_MSG_TYPE,
|
|
226
|
+
msg: {
|
|
227
|
+
linear: { ...ZERO_TWIST.linear },
|
|
228
|
+
angular: { ...ZERO_TWIST.angular },
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
if (result && typeof result.then === "function") {
|
|
232
|
+
pubs.push(Promise.resolve(result).catch(() => { }));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
/* socket may already be half-closed */
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (pubs.length === 0)
|
|
240
|
+
return;
|
|
241
|
+
await Promise.race([
|
|
242
|
+
Promise.all(pubs),
|
|
243
|
+
new Promise((resolve) => setTimeout(resolve, STOP_PUBLISH_BUDGET_MS)),
|
|
244
|
+
]);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Publish zero Twist when the transport drops (and again on reconnect
|
|
248
|
+
* so a stale last-command cannot resume). Returns an unsubscribe.
|
|
249
|
+
*/
|
|
250
|
+
export function attachDisconnectFailSafe(transport, robots) {
|
|
251
|
+
if (typeof transport.onConnection !== "function")
|
|
252
|
+
return () => { };
|
|
253
|
+
let everConnected = transport.getStatus() === "connected";
|
|
254
|
+
return transport.onConnection((status) => {
|
|
255
|
+
if (status === "connected") {
|
|
256
|
+
if (everConnected) {
|
|
257
|
+
void publishStopForBases(transport, robots);
|
|
258
|
+
}
|
|
259
|
+
everConnected = true;
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (status === "disconnected" && everConnected) {
|
|
263
|
+
void publishStopForBases(transport, robots);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
const ACTION_BINDING_KEYS = new Set(["navigate_to_pose", "dock"]);
|
|
268
|
+
const EXPECTED_TYPE_FRAGMENT = {
|
|
269
|
+
cmd_vel: /Twist/i,
|
|
270
|
+
odom: /Odometry/i,
|
|
271
|
+
"camera.rgb": /Image/i,
|
|
272
|
+
"camera.depth": /Image/i,
|
|
273
|
+
lidar: /LaserScan|PointCloud/i,
|
|
274
|
+
joint_states: /JointState/i,
|
|
275
|
+
battery: /BatteryState/i,
|
|
276
|
+
};
|
|
277
|
+
function normalizeGraphName(name) {
|
|
278
|
+
const trimmed = name.trim();
|
|
279
|
+
if (!trimmed)
|
|
280
|
+
return trimmed;
|
|
281
|
+
const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
282
|
+
return withSlash.replace(/\/+$/, "") || "/";
|
|
283
|
+
}
|
|
284
|
+
function findGraphEntry(names, wanted) {
|
|
285
|
+
const target = normalizeGraphName(wanted);
|
|
286
|
+
return names.find((n) => normalizeGraphName(n.name) === target);
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Compare declared profile bindings against a live topic/action list.
|
|
290
|
+
* Missing declared hardware is red; type mismatch is yellow.
|
|
291
|
+
*/
|
|
292
|
+
export function checkLiveBindings(robots, graph) {
|
|
293
|
+
const checks = [];
|
|
294
|
+
for (const robot of robots) {
|
|
295
|
+
const profile = robot.profile;
|
|
296
|
+
if (!profile)
|
|
297
|
+
continue;
|
|
298
|
+
const entries = Object.entries(profile.bindings);
|
|
299
|
+
if (entries.length === 0) {
|
|
300
|
+
checks.push({
|
|
301
|
+
id: `live-${robot.id}-no-bindings`,
|
|
302
|
+
robotId: robot.id,
|
|
303
|
+
key: "",
|
|
304
|
+
name: "",
|
|
305
|
+
severity: "yellow",
|
|
306
|
+
reason: `Robot "${robot.id}" has a profile but no bindings to verify`,
|
|
307
|
+
});
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
for (const [key, raw] of entries) {
|
|
311
|
+
const resolved = resolveBinding(robot, key) ??
|
|
312
|
+
(typeof raw === "string" ? raw.trim() : "");
|
|
313
|
+
if (!resolved)
|
|
314
|
+
continue;
|
|
315
|
+
const isAction = ACTION_BINDING_KEYS.has(key);
|
|
316
|
+
const pool = isAction ? (graph.actions ?? []) : graph.topics;
|
|
317
|
+
const found = findGraphEntry(pool, resolved);
|
|
318
|
+
const checkId = `live-${robot.id}-${key}`;
|
|
319
|
+
if (!found) {
|
|
320
|
+
if (isAction && (graph.actions === undefined || graph.actions.length === 0)) {
|
|
321
|
+
checks.push({
|
|
322
|
+
id: checkId,
|
|
323
|
+
robotId: robot.id,
|
|
324
|
+
key,
|
|
325
|
+
name: resolved,
|
|
326
|
+
severity: "yellow",
|
|
327
|
+
reason: `Could not verify action ${key}=${resolved} (transport returned no action list)`,
|
|
328
|
+
});
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
checks.push({
|
|
332
|
+
id: checkId,
|
|
333
|
+
robotId: robot.id,
|
|
334
|
+
key,
|
|
335
|
+
name: resolved,
|
|
336
|
+
severity: "red",
|
|
337
|
+
reason: `Declared ${key}=${resolved} is not on the live graph`,
|
|
338
|
+
});
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
const expected = EXPECTED_TYPE_FRAGMENT[key];
|
|
342
|
+
if (expected && found.type && !expected.test(found.type)) {
|
|
343
|
+
checks.push({
|
|
344
|
+
id: checkId,
|
|
345
|
+
robotId: robot.id,
|
|
346
|
+
key,
|
|
347
|
+
name: resolved,
|
|
348
|
+
severity: "yellow",
|
|
349
|
+
reason: `${key}=${resolved} type is ${found.type} (expected ${expected})`,
|
|
350
|
+
});
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
checks.push({
|
|
354
|
+
id: checkId,
|
|
355
|
+
robotId: robot.id,
|
|
356
|
+
key,
|
|
357
|
+
name: resolved,
|
|
358
|
+
severity: "green",
|
|
359
|
+
reason: `${key}=${resolved} present`,
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return checks;
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=safety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety.js","sourceRoot":"","sources":["../src/safety.ts"],"names":[],"mappings":"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"}
|
package/dist/transport-pool.d.ts
CHANGED
|
@@ -48,6 +48,9 @@ export declare class TransportPool {
|
|
|
48
48
|
private readonly entries;
|
|
49
49
|
/** Promises kept while a connection is in flight, so concurrent acquires share the same connect. */
|
|
50
50
|
private readonly inFlight;
|
|
51
|
+
private readonly failSafeUnsub;
|
|
52
|
+
/** Last config passed to acquire — used to resolve which robots share a transport on drain. */
|
|
53
|
+
private lastConfig;
|
|
51
54
|
constructor(factory?: TransportFactory);
|
|
52
55
|
/**
|
|
53
56
|
* Acquire (lazy-connect on first call) the transport for this robot.
|
|
@@ -65,6 +68,7 @@ export declare class TransportPool {
|
|
|
65
68
|
* times. Errors on individual disconnects are swallowed.
|
|
66
69
|
*/
|
|
67
70
|
disconnectAll(): Promise<void>;
|
|
71
|
+
private clearFailSafe;
|
|
68
72
|
/** Visible for tests: how many distinct transports are alive right now. */
|
|
69
73
|
get size(): number;
|
|
70
74
|
/** Visible for tests: list of pool keys currently cached. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport-pool.d.ts","sourceRoot":"","sources":["../src/transport-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,eAAe,EAChB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"transport-pool.d.ts","sourceRoot":"","sources":["../src/transport-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,eAAe,EAChB,MAAM,YAAY,CAAC;AAYpB,eAAO,MAAM,yBAAyB,eAAe,CAAC;AAEtD,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAE/E,qBAAa,aAAa;IAQZ,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAC3D,oGAAoG;IACpG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4C;IACrE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiC;IAC/D,+FAA+F;IAC/F,OAAO,CAAC,UAAU,CAA+B;gBAEpB,OAAO,GAAE,gBAAkC;IAExE;;;OAGG;IACG,OAAO,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAYpF;;;;OAIG;IACG,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5D;;;OAGG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBpC,OAAO,CAAC,aAAa;IAYrB,2EAA2E;IAC3E,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,6DAA6D;IAC7D,IAAI,IAAI,MAAM,EAAE;YAIF,YAAY;CA2C3B"}
|
package/dist/transport-pool.js
CHANGED
|
@@ -41,6 +41,8 @@
|
|
|
41
41
|
* for the unit-test seam.
|
|
42
42
|
*/
|
|
43
43
|
import { createTransport, getTransportConfig, getTransportConfigForRobot, hasRobotTransportOverride, resolveRobot, } from "./index.js";
|
|
44
|
+
import { listRobots } from "./robots.js";
|
|
45
|
+
import { attachDisconnectFailSafe, publishStopForBases } from "./safety.js";
|
|
44
46
|
const CONNECT_TIMEOUT_MS = 15_000;
|
|
45
47
|
export const TRANSPORT_POOL_GLOBAL_KEY = "__global__";
|
|
46
48
|
export class TransportPool {
|
|
@@ -48,6 +50,9 @@ export class TransportPool {
|
|
|
48
50
|
entries = new Map();
|
|
49
51
|
/** Promises kept while a connection is in flight, so concurrent acquires share the same connect. */
|
|
50
52
|
inFlight = new Map();
|
|
53
|
+
failSafeUnsub = new Map();
|
|
54
|
+
/** Last config passed to acquire — used to resolve which robots share a transport on drain. */
|
|
55
|
+
lastConfig;
|
|
51
56
|
constructor(factory = createTransport) {
|
|
52
57
|
this.factory = factory;
|
|
53
58
|
}
|
|
@@ -56,6 +61,7 @@ export class TransportPool {
|
|
|
56
61
|
* See the module docstring for the full key + caching contract.
|
|
57
62
|
*/
|
|
58
63
|
async acquire(config, robot) {
|
|
64
|
+
this.lastConfig = config;
|
|
59
65
|
const key = hasRobotTransportOverride(config, robot.id)
|
|
60
66
|
? robot.id
|
|
61
67
|
: TRANSPORT_POOL_GLOBAL_KEY;
|
|
@@ -78,15 +84,33 @@ export class TransportPool {
|
|
|
78
84
|
*/
|
|
79
85
|
async disconnectAll() {
|
|
80
86
|
const pending = [];
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
const cfg = this.lastConfig;
|
|
88
|
+
for (const [key, t] of this.entries) {
|
|
89
|
+
const robots = cfg ? robotsForPoolKey(cfg, key) : [];
|
|
90
|
+
pending.push((async () => {
|
|
91
|
+
await publishStopForBases(t, robots).catch(() => { });
|
|
92
|
+
this.clearFailSafe(key);
|
|
93
|
+
await t.disconnect().catch(() => {
|
|
94
|
+
/* best-effort drain */
|
|
95
|
+
});
|
|
96
|
+
})());
|
|
85
97
|
}
|
|
86
98
|
this.entries.clear();
|
|
87
99
|
this.inFlight.clear();
|
|
88
100
|
await Promise.all(pending);
|
|
89
101
|
}
|
|
102
|
+
clearFailSafe(key) {
|
|
103
|
+
const unsub = this.failSafeUnsub.get(key);
|
|
104
|
+
if (unsub) {
|
|
105
|
+
try {
|
|
106
|
+
unsub();
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
/* ignore */
|
|
110
|
+
}
|
|
111
|
+
this.failSafeUnsub.delete(key);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
90
114
|
/** Visible for tests: how many distinct transports are alive right now. */
|
|
91
115
|
get size() {
|
|
92
116
|
return this.entries.size;
|
|
@@ -107,13 +131,24 @@ export class TransportPool {
|
|
|
107
131
|
if (cached) {
|
|
108
132
|
// Stale entry (e.g. router restarted under us). Drop it cleanly.
|
|
109
133
|
this.entries.delete(key);
|
|
110
|
-
|
|
134
|
+
this.clearFailSafe(key);
|
|
135
|
+
const staleRobots = this.lastConfig ? robotsForPoolKey(this.lastConfig, key) : [];
|
|
136
|
+
void publishStopForBases(cached, staleRobots)
|
|
137
|
+
.catch(() => { })
|
|
138
|
+
.finally(() => {
|
|
139
|
+
cached.disconnect().catch(() => { });
|
|
140
|
+
});
|
|
111
141
|
}
|
|
112
142
|
const connectFlight = (async () => {
|
|
113
143
|
const cfg = resolveCfg();
|
|
114
144
|
const t = await this.factory(cfg);
|
|
115
145
|
await connectWithTimeout(t);
|
|
116
146
|
this.entries.set(key, t);
|
|
147
|
+
if (this.lastConfig) {
|
|
148
|
+
this.clearFailSafe(key);
|
|
149
|
+
const unsub = attachDisconnectFailSafe(t, robotsForPoolKey(this.lastConfig, key));
|
|
150
|
+
this.failSafeUnsub.set(key, unsub);
|
|
151
|
+
}
|
|
117
152
|
return t;
|
|
118
153
|
})();
|
|
119
154
|
this.inFlight.set(key, connectFlight);
|
|
@@ -132,4 +167,11 @@ async function connectWithTimeout(t) {
|
|
|
132
167
|
});
|
|
133
168
|
await Promise.race([t.connect(), timeout]);
|
|
134
169
|
}
|
|
170
|
+
function robotsForPoolKey(config, key) {
|
|
171
|
+
const robots = listRobots(config);
|
|
172
|
+
if (key === TRANSPORT_POOL_GLOBAL_KEY) {
|
|
173
|
+
return robots.filter((r) => !hasRobotTransportOverride(config, r.id));
|
|
174
|
+
}
|
|
175
|
+
return robots.filter((r) => r.id === key);
|
|
176
|
+
}
|
|
135
177
|
//# sourceMappingURL=transport-pool.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport-pool.js","sourceRoot":"","sources":["../src/transport-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAQH,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,0BAA0B,EAC1B,yBAAyB,EACzB,YAAY,GACb,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"transport-pool.js","sourceRoot":"","sources":["../src/transport-pool.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agenticros/core",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AgenticROS core — platform-agnostic ROS2 transport, types, and config (the dep every AgenticROS skill imports).",
|
|
6
6
|
"keywords": [
|
|
@@ -43,13 +43,6 @@
|
|
|
43
43
|
"engines": {
|
|
44
44
|
"node": ">=20"
|
|
45
45
|
},
|
|
46
|
-
"scripts": {
|
|
47
|
-
"build": "tsc",
|
|
48
|
-
"typecheck": "tsc --noEmit",
|
|
49
|
-
"test": "node --test \"dist/memory/__tests__/*.test.js\" \"dist/__tests__/*.test.js\"",
|
|
50
|
-
"prepublishOnly": "npm run build",
|
|
51
|
-
"pack:dry": "npm pack --dry-run"
|
|
52
|
-
},
|
|
53
46
|
"dependencies": {
|
|
54
47
|
"@eclipse-zenoh/zenoh-ts": "^1.9.0",
|
|
55
48
|
"@foxglove/cdr": "^3.5.0",
|
|
@@ -68,5 +61,11 @@
|
|
|
68
61
|
"typescript": "^5.7.0"
|
|
69
62
|
},
|
|
70
63
|
"author": "PlaiPin",
|
|
71
|
-
"license": "Apache-2.0"
|
|
72
|
-
|
|
64
|
+
"license": "Apache-2.0",
|
|
65
|
+
"scripts": {
|
|
66
|
+
"build": "tsc",
|
|
67
|
+
"typecheck": "tsc --noEmit",
|
|
68
|
+
"test": "node --test \"dist/memory/__tests__/*.test.js\" \"dist/__tests__/*.test.js\"",
|
|
69
|
+
"pack:dry": "npm pack --dry-run"
|
|
70
|
+
}
|
|
71
|
+
}
|