@fleetless/contracts 1.0.0 → 1.0.2
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/CHANGELOG.md +68 -2
- package/CODE_OF_CONDUCT.md +83 -0
- package/CONTRIBUTING.md +136 -0
- package/README.md +49 -13
- package/SECURITY.md +55 -0
- package/artifacts/openapi.json +1 -1
- package/artifacts/routes.json +1 -1
- package/dist/alerts.d.ts +19 -24
- package/dist/alerts.js +18 -24
- package/dist/app-users.d.ts +7 -6
- package/dist/app-users.js +6 -6
- package/dist/apps.d.ts +21 -25
- package/dist/apps.js +40 -51
- package/dist/assets.d.ts +70 -132
- package/dist/assets.js +130 -223
- package/dist/audit.d.ts +11 -11
- package/dist/audit.js +25 -51
- package/dist/client-auth.d.ts +4 -4
- package/dist/client-auth.js +3 -4
- package/dist/common.d.ts +27 -35
- package/dist/common.js +26 -35
- package/dist/config-issues.d.ts +4 -3
- package/dist/config-issues.js +7 -6
- package/dist/config.d.ts +31 -37
- package/dist/config.js +81 -110
- package/dist/errors.d.ts +4 -3
- package/dist/errors.js +61 -87
- package/dist/identity.d.ts +18 -21
- package/dist/identity.js +17 -21
- package/dist/index.d.ts +4 -4
- package/dist/index.js +12 -13
- package/dist/introspection.d.ts +7 -6
- package/dist/introspection.js +6 -6
- package/dist/jobs.d.ts +12 -12
- package/dist/jobs.js +20 -25
- package/dist/mcp.d.ts +11 -12
- package/dist/mcp.js +10 -12
- package/dist/oauth.d.ts +13 -18
- package/dist/oauth.js +13 -19
- package/dist/protocol.d.ts +51 -62
- package/dist/protocol.js +107 -139
- package/dist/realtime.d.ts +53 -68
- package/dist/realtime.js +77 -103
- package/dist/rest.d.ts +182 -243
- package/dist/rest.js +301 -395
- package/dist/routes.d.ts +4 -3
- package/dist/routes.js +3 -2
- package/package.json +12 -7
package/dist/protocol.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
1
2
|
import { z } from 'zod';
|
|
2
3
|
/**
|
|
3
4
|
* Bridge <-> cloud protocol, version 2.
|
|
4
5
|
*
|
|
5
6
|
* The version is exchanged in the hello handshake; the cloud refuses an
|
|
6
|
-
* incompatible bridge with a clear message
|
|
7
|
-
*
|
|
8
|
-
* detail page as `last_hello_error`.
|
|
7
|
+
* incompatible bridge with a clear message: `protocol_mismatch`, which names
|
|
8
|
+
* both versions and reaches the robot's detail view as `last_hello_error`.
|
|
9
9
|
*
|
|
10
10
|
* **2 (2026-08-21):** `config_applied.errors` entries gained `kind` and `code`
|
|
11
11
|
* beside `message`. The check is `!==`, not a floor, so a bridge that is not
|
|
@@ -14,7 +14,7 @@ import { z } from 'zod';
|
|
|
14
14
|
*/
|
|
15
15
|
export declare const PROTOCOL_VERSION = 2;
|
|
16
16
|
/**
|
|
17
|
-
* The bridge socket close code for "this robot no longer exists"
|
|
17
|
+
* The bridge socket close code for "this robot no longer exists".
|
|
18
18
|
*
|
|
19
19
|
* Deliberately distinct from the auth failures: a deleted robot must **stop**,
|
|
20
20
|
* and a token that was valid a second ago is indistinguishable from one that
|
|
@@ -26,42 +26,37 @@ export declare const PROTOCOL_VERSION = 2;
|
|
|
26
26
|
export declare const CLOSE_ROBOT_DELETED = 4004;
|
|
27
27
|
/**
|
|
28
28
|
* How long a command waits for its answer when the caller names no patience
|
|
29
|
-
* of its own
|
|
29
|
+
* of its own.
|
|
30
30
|
*
|
|
31
|
-
* 15 s,
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* makes it one number rather than two that happen to match.
|
|
31
|
+
* 15 s, stated once here rather than once in the cloud and once in the bridge.
|
|
32
|
+
* Two constants that happen to match are not one number: neither side can be
|
|
33
|
+
* told otherwise for a single call, and when they drift nobody can say whose
|
|
34
|
+
* deadline a caller hit.
|
|
36
35
|
*
|
|
37
|
-
* A caller who knows their robot's work takes longer says so per call.
|
|
38
|
-
* caller who says nothing gets exactly today's behaviour — which is the point
|
|
39
|
-
* of picking today's number as the default rather than a nicer one.
|
|
36
|
+
* A caller who knows their robot's work takes longer says so per call.
|
|
40
37
|
*/
|
|
41
38
|
export declare const DEFAULT_PATIENCE_MS = 15000;
|
|
42
39
|
/**
|
|
43
40
|
* The longest patience a caller may ask for.
|
|
44
41
|
*
|
|
45
|
-
* A waiting REST request is a held-open connection,
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* enough for the robot work anybody has described (a planner, a docking
|
|
42
|
+
* A waiting REST request is a held-open connection, so an unbounded
|
|
43
|
+
* `patience_ms` is a way to pin the cloud's sockets open. Two minutes is long
|
|
44
|
+
* enough for the robot work this API is meant for (a planner, a docking
|
|
49
45
|
* manoeuvre, an arm trajectory) and short enough that a thousand of them is
|
|
50
46
|
* still a bounded amount of cloud.
|
|
51
47
|
*
|
|
52
|
-
* Raising it is a
|
|
53
|
-
*
|
|
48
|
+
* Raising it is a conversation about rate limiting, not a one-line change
|
|
49
|
+
* here.
|
|
54
50
|
*/
|
|
55
51
|
export declare const MAX_PATIENCE_MS = 120000;
|
|
56
52
|
/**
|
|
57
53
|
* The shortest patience a caller may ask for.
|
|
58
54
|
*
|
|
59
|
-
* A floor exists because **impatience reaches the robot**.
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* Repeatable, and on a platform with no rate limiting until W8.
|
|
55
|
+
* A floor exists because **impatience reaches the robot**. A `patience_ms` of
|
|
56
|
+
* 1 on an action makes the bridge report `goal_timeout` and then issue a
|
|
57
|
+
* *corrective cancel* against a goal the action server accepts a moment later
|
|
58
|
+
* — so a caller who asks for an unreachable deadline does not merely get an
|
|
59
|
+
* error, they cause a cancellation on the machine.
|
|
65
60
|
*
|
|
66
61
|
* One second, because it has to be longer than a goal-acceptance round trip on
|
|
67
62
|
* a healthy robot and shorter than any wait a human would call patient. It is
|
|
@@ -73,7 +68,7 @@ export declare const MIN_PATIENCE_MS = 1000;
|
|
|
73
68
|
/** Re-exported so consumers keep importing wire names from one place. */
|
|
74
69
|
export { slug } from './common.js';
|
|
75
70
|
/**
|
|
76
|
-
* One job the bridge still has, as reported in the handshake
|
|
71
|
+
* One job the bridge still has, as reported in the handshake.
|
|
77
72
|
*
|
|
78
73
|
* It carries the **slug and the state**, not only the id, because the cloud's
|
|
79
74
|
* reconciliation needs both and had neither. Reading `active_job_ids` as bare
|
|
@@ -134,7 +129,7 @@ export declare const cloudHelloError: z.ZodObject<{
|
|
|
134
129
|
export type CloudHelloError = z.infer<typeof cloudHelloError>;
|
|
135
130
|
/**
|
|
136
131
|
* One datapoint sample. `timestamp_ms` is the capture time at the bridge —
|
|
137
|
-
* never the receive time — so clients compute age themselves
|
|
132
|
+
* never the receive time — so clients compute age themselves.
|
|
138
133
|
*/
|
|
139
134
|
export declare const datapointFrame: z.ZodObject<{
|
|
140
135
|
type: z.ZodLiteral<"datapoint">;
|
|
@@ -160,9 +155,9 @@ export declare const bridgePong: z.ZodObject<{
|
|
|
160
155
|
}, z.core.$strip>;
|
|
161
156
|
export type BridgePong = z.infer<typeof bridgePong>;
|
|
162
157
|
/**
|
|
163
|
-
* The published configuration, cloud → bridge
|
|
164
|
-
*
|
|
165
|
-
*
|
|
158
|
+
* The published configuration, cloud → bridge — the bridge applies the
|
|
159
|
+
* published version. Sent right after `hello_ok` and again on every publish,
|
|
160
|
+
* so a bridge never has to ask.
|
|
166
161
|
*
|
|
167
162
|
* `version: 0` with an empty document means *nothing published yet* — a fresh
|
|
168
163
|
* robot, not an error.
|
|
@@ -391,7 +386,7 @@ export declare const bridgeConfigApplied: z.ZodObject<{
|
|
|
391
386
|
}, z.core.$strip>;
|
|
392
387
|
export type BridgeConfigApplied = z.infer<typeof bridgeConfigApplied>;
|
|
393
388
|
/**
|
|
394
|
-
* Commands, cloud → bridge
|
|
389
|
+
* Commands, cloud → bridge. The **cloud** mints the
|
|
395
390
|
* `job_id` before the bridge is asked to do anything, so a job exists —
|
|
396
391
|
* and can be reported `lost` — even if the answer never comes back.
|
|
397
392
|
*/
|
|
@@ -404,13 +399,13 @@ export declare const cloudInvoke: z.ZodObject<{
|
|
|
404
399
|
}, z.core.$strip>;
|
|
405
400
|
export type CloudInvoke = z.infer<typeof cloudInvoke>;
|
|
406
401
|
/**
|
|
407
|
-
* Cancel — the bridge must issue a real ROS goal cancel
|
|
402
|
+
* Cancel — the bridge must issue a real ROS goal cancel.
|
|
408
403
|
*
|
|
409
404
|
* `slug` stays, and stays required: it is how the bridge finds the tracker,
|
|
410
405
|
* and it is what a cancel with no id means.
|
|
411
406
|
*
|
|
412
|
-
* `job_id` is what
|
|
413
|
-
*
|
|
407
|
+
* `job_id` is what makes a cancel say *which* job. Without it a cancel
|
|
408
|
+
* arriving a moment after one job ended and another began on the
|
|
414
409
|
* same slug stops the **new** one — the caller asked to stop something that
|
|
415
410
|
* had already finished and stopped a machine that had just started moving.
|
|
416
411
|
* That is not a race anybody had to lose: the caller knew the id, and the
|
|
@@ -437,7 +432,7 @@ export declare const cloudPublish: z.ZodObject<{
|
|
|
437
432
|
export type CloudPublish = z.infer<typeof cloudPublish>;
|
|
438
433
|
/**
|
|
439
434
|
* Progress on a job, bridge → cloud. `timestamp_ms` is capture time, so a
|
|
440
|
-
* burst delivered late after a reconnect is visibly late
|
|
435
|
+
* burst delivered late after a reconnect is visibly late.
|
|
441
436
|
*/
|
|
442
437
|
export declare const bridgeJobUpdate: z.ZodObject<{
|
|
443
438
|
type: z.ZodLiteral<"job_update">;
|
|
@@ -462,7 +457,7 @@ export declare const bridgeJobUpdate: z.ZodObject<{
|
|
|
462
457
|
}, z.core.$strip>;
|
|
463
458
|
export type BridgeJobUpdate = z.infer<typeof bridgeJobUpdate>;
|
|
464
459
|
/**
|
|
465
|
-
* Jobs the bridge can no longer account for **while connected**
|
|
460
|
+
* Jobs the bridge can no longer account for **while connected** — a
|
|
466
461
|
* tracker dropped, an action server that vanished mid-goal, anything where
|
|
467
462
|
* the honest answer is "I lost this" rather than a state.
|
|
468
463
|
*
|
|
@@ -542,8 +537,8 @@ export declare const bridgeTypeDefinitions: z.ZodObject<{
|
|
|
542
537
|
}, z.core.$strip>;
|
|
543
538
|
export type BridgeTypeDefinitions = z.infer<typeof bridgeTypeDefinitions>;
|
|
544
539
|
/**
|
|
545
|
-
* The built-in `bridge_state` datapoint every robot has
|
|
546
|
-
*
|
|
540
|
+
* The built-in `bridge_state` datapoint every robot has: connection status
|
|
541
|
+
* plus latency, the basis for offline-aware client UIs.
|
|
547
542
|
*/
|
|
548
543
|
export declare const bridgeState: z.ZodObject<{
|
|
549
544
|
online: z.ZodBoolean;
|
|
@@ -551,8 +546,7 @@ export declare const bridgeState: z.ZodObject<{
|
|
|
551
546
|
}, z.core.$strip>;
|
|
552
547
|
export type BridgeState = z.infer<typeof bridgeState>;
|
|
553
548
|
/**
|
|
554
|
-
* The built-in `bridge_pressure` datapoint
|
|
555
|
-
* design's "The decision that shapes everything"): the bridge's own
|
|
549
|
+
* The built-in `bridge_pressure` datapoint: the bridge's own
|
|
556
550
|
* bandwidth-shaping state, sent on the same reserved-slug path as
|
|
557
551
|
* `bridge_state` so history, realtime, REST and MCP exposure fall out of the
|
|
558
552
|
* ordinary datapoint machinery for free.
|
|
@@ -621,13 +615,11 @@ export declare const PRESSURE_SLUG: "bridge_pressure";
|
|
|
621
615
|
* Binary rather than base64 in a text frame, because base64 costs a third of
|
|
622
616
|
* the robot's upstream for nothing. Self-contained rather than a JSON frame
|
|
623
617
|
* followed by a binary one, because that pairing would depend on frame
|
|
624
|
-
* ordering
|
|
625
|
-
* is not something to lean on.
|
|
618
|
+
* ordering, and ordering across a socket is not something to lean on.
|
|
626
619
|
*
|
|
627
|
-
* `timestamp_ms` is the bridge's **capture** time
|
|
628
|
-
*
|
|
629
|
-
*
|
|
630
|
-
* nobody knows.
|
|
620
|
+
* `timestamp_ms` is the bridge's **capture** time, which is what lets every
|
|
621
|
+
* consumer state a snapshot's true age. A picture that lies about when it was
|
|
622
|
+
* taken is as bad as a job that reads "running" when nobody knows.
|
|
631
623
|
*/
|
|
632
624
|
/**
|
|
633
625
|
* The largest a snapshot frame — header and image bytes together — may be on
|
|
@@ -643,15 +635,13 @@ export declare const PRESSURE_SLUG: "bridge_pressure";
|
|
|
643
635
|
* connection with 1009 — taking datapoints, jobs, commands and configuration
|
|
644
636
|
* down with it. The bridge would then reconnect, receive the same
|
|
645
637
|
* configuration, capture the same frame and be closed again: a robot that
|
|
646
|
-
* will not stay online, from a configuration the platform accepted.
|
|
647
|
-
*
|
|
648
|
-
* 2.2 MiB and 1080p on a noisy scene within
|
|
649
|
-
* is thinner than it looks.
|
|
638
|
+
* will not stay online, from a configuration the platform accepted. The margin
|
|
639
|
+
* is thinner than it looks — a 4K JPEG of real camera content lands around
|
|
640
|
+
* 2.2 MiB, and 1080p on a noisy scene comes within half of this number.
|
|
650
641
|
*
|
|
651
|
-
* **The bridge must degrade rather than exceed it** — lower JPEG quality,
|
|
652
|
-
*
|
|
653
|
-
*
|
|
654
|
-
* is an honest answer; a closed socket is not.
|
|
642
|
+
* **The bridge must degrade rather than exceed it** — lower JPEG quality, then
|
|
643
|
+
* downscale, and if it still does not fit, skip the frame and say so. A missing
|
|
644
|
+
* snapshot is a gap, and a gap is an honest answer; a closed socket is not.
|
|
655
645
|
*/
|
|
656
646
|
export declare const SNAPSHOT_MAX_BYTES = 1572864;
|
|
657
647
|
export declare const snapshotHeader: z.ZodObject<{
|
|
@@ -667,7 +657,7 @@ export type SnapshotHeader = z.infer<typeof snapshotHeader>;
|
|
|
667
657
|
* Cloud → bridge: start publishing this camera live.
|
|
668
658
|
*
|
|
669
659
|
* The **cloud** mints the room and the publisher token, for the same reason
|
|
670
|
-
* it mints a `job_id` before asking anything
|
|
660
|
+
* it mints a `job_id` before asking anything: the side that owns the
|
|
671
661
|
* refcount must own the identity of the stream, or a robot could end up
|
|
672
662
|
* publishing into a room nobody is watching.
|
|
673
663
|
*/
|
|
@@ -680,14 +670,13 @@ export declare const cloudCameraStart: z.ZodObject<{
|
|
|
680
670
|
request_id: z.ZodString;
|
|
681
671
|
}, z.core.$strip>;
|
|
682
672
|
export type CloudCameraStart = z.infer<typeof cloudCameraStart>;
|
|
683
|
-
/** Cloud → bridge: the last viewer left; stop publishing
|
|
673
|
+
/** Cloud → bridge: the last viewer left; stop publishing. */
|
|
684
674
|
/**
|
|
685
|
-
* Assets
|
|
686
|
-
*
|
|
675
|
+
* Assets: the bridge **reports availability and transfers nothing** until
|
|
676
|
+
* asked.
|
|
687
677
|
*
|
|
688
|
-
* **The bytes never travel on this socket.**
|
|
689
|
-
*
|
|
690
|
-
* tied to W8's rate limiting in the deferral register because it amplifies an
|
|
678
|
+
* **The bytes never travel on this socket.** A frame is capped at 2 MiB and a
|
|
679
|
+
* single mesh exceeds that routinely; raising the cap amplifies an
|
|
691
680
|
* unauthenticated path. So the socket carries the *conversation* — what exists,
|
|
692
681
|
* transfer this, here is how far I got — and the bytes go over HTTP with the
|
|
693
682
|
* robot's own credential.
|
|
@@ -703,7 +692,7 @@ export declare const bridgeAssetsAvailable: z.ZodObject<{
|
|
|
703
692
|
}, z.core.$strip>;
|
|
704
693
|
export type BridgeAssetsAvailable = z.infer<typeof bridgeAssetsAvailable>;
|
|
705
694
|
/**
|
|
706
|
-
* The explicit request
|
|
695
|
+
* The explicit request that starts a transfer — nothing moves without it.
|
|
707
696
|
*
|
|
708
697
|
* The upload credential is minted per sync and travels here rather than being
|
|
709
698
|
* derived from the robot token: it is scoped to one robot's assets and one
|