@fleetless/contracts 4.0.0-next.1 → 5.0.0-next.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.
- package/CHANGELOG.md +35 -5
- package/artifacts/constants.json +4 -14
- package/artifacts/openapi.json +46 -13
- package/artifacts/routes.json +2 -2
- package/artifacts/schema/bridge-hello.schema.json +1 -0
- package/artifacts/schema/bridge-job-status.schema.json +114 -0
- package/artifacts/schema/bridge-job-update.schema.json +21 -0
- package/artifacts/schema/busy-details.schema.json +12 -2
- package/artifacts/schema/cloud-job-query.schema.json +29 -0
- package/artifacts/schema/command-result.schema.json +12 -2
- package/artifacts/schema/invoke-or-service-response.schema.json +12 -2
- package/artifacts/schema/invoke-response.schema.json +12 -2
- package/artifacts/schema/job-event.schema.json +12 -2
- package/artifacts/schema/job-response.schema.json +12 -2
- package/artifacts/schema/job-run-list-response.schema.json +4 -3
- package/artifacts/schema/job-run-query.schema.json +2 -1
- package/artifacts/schema/job-run.schema.json +4 -3
- package/artifacts/schema/job-state.schema.json +1 -0
- package/artifacts/schema/job.schema.json +12 -2
- package/artifacts/schema/robot-jobs-response.schema.json +12 -2
- package/artifacts/schema-outgoing/bridge-hello.schema.json +1 -0
- package/artifacts/schema-outgoing/bridge-job-status.schema.json +117 -0
- package/artifacts/schema-outgoing/bridge-job-update.schema.json +21 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +39 -8
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/jobs.d.ts +55 -6
- package/dist/jobs.js +43 -14
- package/dist/protocol.d.ts +165 -44
- package/dist/protocol.js +144 -59
- package/dist/realtime.d.ts +5 -0
- package/dist/rest.d.ts +20 -0
- package/dist/routes.js +6 -3
- package/package.json +1 -1
package/dist/protocol.js
CHANGED
|
@@ -4,23 +4,38 @@ import { assetFailure } from './assets.js';
|
|
|
4
4
|
import { applyError, slug } from './common.js';
|
|
5
5
|
import { robotConfigDoc } from './config.js';
|
|
6
6
|
import { rosGraph, typeDefinition } from './introspection.js';
|
|
7
|
-
import { jobState } from './jobs.js';
|
|
7
|
+
import { jobOrigin, jobState } from './jobs.js';
|
|
8
8
|
import { rosTypeName } from './common.js';
|
|
9
9
|
/**
|
|
10
|
-
* Bridge <-> cloud protocol, version
|
|
10
|
+
* Bridge <-> cloud protocol, version 5.
|
|
11
11
|
*
|
|
12
12
|
* The version is exchanged in the hello handshake. Since 2026-09 the cloud
|
|
13
13
|
* serves a **window** of versions, not one: every entry of
|
|
14
14
|
* `PROTOCOL_VERSIONS` whose sunset has not passed. A version is deprecated
|
|
15
15
|
* by the cloud release that supersedes it and sunset `PROTOCOL_SUNSET_DAYS`
|
|
16
|
-
* later. Outside the window the cloud refuses
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* **
|
|
16
|
+
* later. Outside the window the cloud refuses the hello, and the refusal
|
|
17
|
+
* reaches the robot's detail view as `last_hello_error`: `bridge_too_old`,
|
|
18
|
+
* naming the bridge version to install, for a version below the window.
|
|
19
|
+
*
|
|
20
|
+
* **5 (2026-09-29):** a hard cut, not a window — protocols 2, 3 and 4 are
|
|
21
|
+
* unsupported from this release on, with no sunset (André, 2026-09-29: "we
|
|
22
|
+
* are still building up and need not take care"), so `PROTOCOL_VERSIONS`
|
|
23
|
+
* holds one entry. The bridge tracks every goal on a published action by
|
|
24
|
+
* goal id — its own and anyone else's — and reports them through
|
|
25
|
+
* `job_update`, which gains a required `origin` and `goal_id`: a goal it did
|
|
26
|
+
* not send arrives as `origin: 'external'` under a job id the bridge derives
|
|
27
|
+
* itself. `jobState` gains `unknown`, the cloud's non-terminal "I lost sight
|
|
28
|
+
* of it" (`bridge_disconnected`, `bridge_timeout`) that replaces settling
|
|
29
|
+
* `lost` on a guess; `lost` is final. While connected, the cloud asks about
|
|
30
|
+
* specific jobs with `job_query` and the bridge answers `job_status`. Goal
|
|
31
|
+
* state is reported once per `JOB_HEARTBEAT_INTERVAL_MS`, newest only; the
|
|
32
|
+
* end of a Fleetless job goes at once.
|
|
33
|
+
*
|
|
34
|
+
* **4 (2026-09-29):** the bridge sends a `job_update` heartbeat at
|
|
21
35
|
* `JOB_HEARTBEAT_INTERVAL_MS` for every running job, whether or not the
|
|
22
|
-
* action said anything new, and
|
|
23
|
-
* `
|
|
36
|
+
* action said anything new, and ends a job whose action server vanished
|
|
37
|
+
* `lost` with `action_server_lost` (a terminal `job_update`; `job_lost`
|
|
38
|
+
* gains an optional `error` for the same purpose). The cloud bounds
|
|
24
39
|
* a protocol-4 job's silence by the heartbeat (`JOB_HEARTBEAT_TIMEOUT_MS`)
|
|
25
40
|
* once it has heard from the job at all; `patience_ms` still bounds
|
|
26
41
|
* acceptance, the same as before. Offline tolerance is
|
|
@@ -41,25 +56,30 @@ import { rosTypeName } from './common.js';
|
|
|
41
56
|
* **2 (2026-08-21):** `config_applied.errors` entries gained `kind` and `code`
|
|
42
57
|
* beside `message`.
|
|
43
58
|
*/
|
|
44
|
-
export const PROTOCOL_VERSION =
|
|
59
|
+
export const PROTOCOL_VERSION = 5;
|
|
45
60
|
/** Days between a version's deprecation and its sunset. */
|
|
46
61
|
export const PROTOCOL_SUNSET_DAYS = 90;
|
|
47
62
|
/**
|
|
48
|
-
* Every protocol version the cloud
|
|
63
|
+
* Every protocol version the cloud serves, oldest first. A test keeps
|
|
49
64
|
* exactly one entry current and equal to `PROTOCOL_VERSION`; `test/changelog.test.ts`
|
|
50
65
|
* requires some CHANGELOG section — `[Unreleased]` or a dated one — to name
|
|
51
66
|
* the newest `bridge_from` together with the previous entry's `sunsetOf(...)`
|
|
52
67
|
* date, so the pull request that moves this window is the one that fails
|
|
53
68
|
* without saying so; and `scripts/verify-version-tag.mjs` requires a dated
|
|
54
69
|
* heading for the tag being released.
|
|
70
|
+
*
|
|
71
|
+
* **One entry since protocol 5**, which cut 2, 3 and 4 without a sunset
|
|
72
|
+
* rather than deprecating them. A version absent from the table is
|
|
73
|
+
* `unsupported`, which is exactly what a cut means, so the dropped entries
|
|
74
|
+
* are gone rather than kept with a past date. The changelog test's window
|
|
75
|
+
* check has no previous entry to read then; its hard-cut sibling holds the
|
|
76
|
+
* changelog to naming the cut instead.
|
|
55
77
|
*/
|
|
56
78
|
export const PROTOCOL_VERSIONS = [
|
|
57
|
-
{ version:
|
|
58
|
-
{ version: 3, bridge_from: '4.0.0', deprecated_at: '2026-09-28' },
|
|
59
|
-
{ version: 4, bridge_from: '4.1.0', deprecated_at: null },
|
|
79
|
+
{ version: 5, bridge_from: '6.0.0', deprecated_at: null },
|
|
60
80
|
];
|
|
61
81
|
/** The newest bridge package. The cloud mails organisations still below it. */
|
|
62
|
-
export const LATEST_BRIDGE_VERSION = '
|
|
82
|
+
export const LATEST_BRIDGE_VERSION = '6.0.0';
|
|
63
83
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
64
84
|
function isoDate(date) {
|
|
65
85
|
return date.toISOString().slice(0, 10);
|
|
@@ -162,37 +182,43 @@ export const MAX_PATIENCE_MS = 120_000;
|
|
|
162
182
|
*/
|
|
163
183
|
export const MIN_PATIENCE_MS = 1_000;
|
|
164
184
|
/**
|
|
165
|
-
* How often
|
|
166
|
-
*
|
|
167
|
-
*
|
|
185
|
+
* How often the bridge reports goal state: one `job_update` per active goal
|
|
186
|
+
* on a published action — its own and external ones — carrying the newest
|
|
187
|
+
* state and feedback, whether or not the action said anything new. Whatever
|
|
188
|
+
* happened in between is dropped, so an action that sends feedback at 100 Hz
|
|
189
|
+
* costs one frame a second; the end of a Fleetless job is the exception and
|
|
190
|
+
* goes at once. One second: often enough that `JOB_HEARTBEAT_TIMEOUT_MS`
|
|
168
191
|
* can be a small multiple of it and still absorb a missed beat or two, rare
|
|
169
192
|
* enough that it costs nothing next to the datapoint traffic a busy robot
|
|
170
193
|
* already sends.
|
|
171
194
|
*/
|
|
172
195
|
export const JOB_HEARTBEAT_INTERVAL_MS = 1_000;
|
|
173
196
|
/**
|
|
174
|
-
* How long a
|
|
175
|
-
*
|
|
197
|
+
* How long a running job may go without a `job_update` — heartbeat or real
|
|
198
|
+
* progress, either counts — before the cloud marks it `unknown` with
|
|
176
199
|
* `bridge_timeout`, once the bridge is connected. Five heartbeats: enough
|
|
177
200
|
* slack for an ordinary scheduling jitter, small next to `patience_ms`
|
|
178
|
-
* because it
|
|
179
|
-
* bounds only the time from `invoke` to the *first* update
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
* `
|
|
183
|
-
*
|
|
201
|
+
* because it does not have to cover the acceptance gap too. `patience_ms`
|
|
202
|
+
* bounds only the time from `invoke` to the *first* update; every rearm after
|
|
203
|
+
* that uses this constant instead.
|
|
204
|
+
*
|
|
205
|
+
* `unknown`, not `lost`: silence is the cloud's guess, not the bridge's
|
|
206
|
+
* statement. The cloud then asks with `job_query`, and asks again after the
|
|
207
|
+
* same interval for as long as no `job_status` answers and the bridge stays
|
|
208
|
+
* connected.
|
|
184
209
|
*/
|
|
185
210
|
export const JOB_HEARTBEAT_TIMEOUT_MS = 5_000;
|
|
186
211
|
/**
|
|
187
212
|
* How long a running job survives its robot going offline before the cloud
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
* result the cloud is waiting for is often still coming.
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
213
|
+
* marks it `unknown` with `bridge_disconnected`. Five minutes: long enough
|
|
214
|
+
* that an ordinary Wi-Fi dead zone — the case this constant exists for —
|
|
215
|
+
* never touches a job, since a robot with no safety layer of its own
|
|
216
|
+
* (§ Fleetless is not a safety layer) keeps driving through one and the
|
|
217
|
+
* result the cloud is waiting for is often still coming. Past it the job is
|
|
218
|
+
* still not given up: `unknown` keeps the slug occupied until the
|
|
219
|
+
* reconnecting bridge says how the job stands. A robot connected the whole
|
|
220
|
+
* time never reaches this bound at all: while online, silence is
|
|
221
|
+
* `JOB_HEARTBEAT_TIMEOUT_MS`'s question, never this one's.
|
|
196
222
|
*/
|
|
197
223
|
export const JOB_OFFLINE_GRACE_MS = 300_000;
|
|
198
224
|
/** Re-exported so consumers keep importing wire names from one place. */
|
|
@@ -211,6 +237,8 @@ export { slug } from './common.js';
|
|
|
211
237
|
* `state` is the bridge's own current answer, not a history. A bridge that
|
|
212
238
|
* has a terminal result still in hand reports it here and the cloud writes it
|
|
213
239
|
* down, instead of publishing `lost` over a job that in fact succeeded.
|
|
240
|
+
* Never `unknown`: that is the cloud's word for not having heard, and a
|
|
241
|
+
* bridge listing a job has, by definition, something to say about it.
|
|
214
242
|
*/
|
|
215
243
|
export const activeJob = z.object({
|
|
216
244
|
job_id: z.uuid(),
|
|
@@ -227,16 +255,14 @@ export const bridgeHello = z.object({
|
|
|
227
255
|
* Every job this bridge still knows about, right now.
|
|
228
256
|
*
|
|
229
257
|
* A reconnect and a restart look **identical** on the wire — same token,
|
|
230
|
-
* same version, same frame —
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
* the cloud needs. A breadcrumb file would only add a window in which the
|
|
239
|
-
* crash beat the write.
|
|
258
|
+
* same version, same frame — so the bridge enumerates what it still has:
|
|
259
|
+
* its live jobs, and after a restart every job whose goal it recognised
|
|
260
|
+
* again from its persisted job-to-goal mapping. A job the cloud holds
|
|
261
|
+
* `running` or `unknown` that is *not* named here is "not known to the
|
|
262
|
+
* bridge"; it becomes `lost` (`job_unknown_to_bridge`) only once the
|
|
263
|
+
* bridge's goal reports show its action free of goals it cannot
|
|
264
|
+
* attribute — one of those may be that very job — and at once for a
|
|
265
|
+
* service job, which has no goals to look at.
|
|
240
266
|
*
|
|
241
267
|
* Defaulted, so a bridge that sends no such field still parses; no jobs
|
|
242
268
|
* and no report both mean the same thing to the cloud: nothing to keep
|
|
@@ -465,12 +491,30 @@ export const cloudPublish = z.object({
|
|
|
465
491
|
/**
|
|
466
492
|
* Progress on a job, bridge → cloud. `timestamp_ms` is capture time, so a
|
|
467
493
|
* burst delivered late after a reconnect is visibly late.
|
|
494
|
+
*
|
|
495
|
+
* Since protocol 5 this frame reports **every goal active on a published
|
|
496
|
+
* action**, not only the ones the bridge sent. A goal the bridge cannot
|
|
497
|
+
* attribute to a job of its own arrives with `origin: 'external'` and a
|
|
498
|
+
* `job_id` the bridge derives from robot, slug and goal id, the same id on
|
|
499
|
+
* every report of that goal — the cloud mints an external job the first time
|
|
500
|
+
* it sees one and never recomputes the id itself. `goal_id` is the ROS 2
|
|
501
|
+
* goal id, so a cancel can name the goal; `null` for a service job, which
|
|
502
|
+
* has no goal.
|
|
503
|
+
*
|
|
504
|
+
* Sent once per `JOB_HEARTBEAT_INTERVAL_MS` per active goal, newest state
|
|
505
|
+
* only. The end of a Fleetless job is sent at once; an external goal's end at
|
|
506
|
+
* the next tick, and an external goal that started and ended between two
|
|
507
|
+
* ticks is never reported at all.
|
|
468
508
|
*/
|
|
469
509
|
export const bridgeJobUpdate = z.object({
|
|
470
510
|
type: z.literal('job_update'),
|
|
471
511
|
job_id: z.uuid(),
|
|
472
512
|
slug,
|
|
513
|
+
/** Never `unknown`: that is the cloud's word for not having heard. */
|
|
473
514
|
state: jobState,
|
|
515
|
+
origin: jobOrigin,
|
|
516
|
+
/** The ROS 2 goal id; `null` for a service job, which has no goal. */
|
|
517
|
+
goal_id: z.string().min(1).nullable(),
|
|
474
518
|
feedback: z.unknown().nullable(),
|
|
475
519
|
progress: z.number().min(0).max(1).nullable(),
|
|
476
520
|
result: z.unknown().nullable(),
|
|
@@ -481,29 +525,70 @@ export const bridgeJobUpdate = z.object({
|
|
|
481
525
|
timestamp_ms: z.number().int().nonnegative(),
|
|
482
526
|
});
|
|
483
527
|
/**
|
|
484
|
-
*
|
|
485
|
-
*
|
|
486
|
-
* the honest answer is "I lost this" rather
|
|
528
|
+
* The bridge's own, definite statement **while connected** that it no longer
|
|
529
|
+
* knows these jobs — an action server that vanished mid-goal, a goal the
|
|
530
|
+
* server no longer knows — where the honest answer is "I lost this" rather
|
|
531
|
+
* than a state. The cloud settles each named job `lost`, final.
|
|
487
532
|
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
* leaving a job reading "running" because nobody contradicted it.
|
|
533
|
+
* Only the bridge says `lost` now. The cloud's own guesses — offline past
|
|
534
|
+
* `JOB_OFFLINE_GRACE_MS`, silent past `JOB_HEARTBEAT_TIMEOUT_MS` — make a
|
|
535
|
+
* job `unknown` instead, and a restart is answered by `hello.active_jobs`.
|
|
492
536
|
*
|
|
493
|
-
* **`error`
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
* the cloud settles the job `lost` with no specific code, the same as a
|
|
499
|
-
* protocol-3 bridge's frame, which carries no `error` at all and still
|
|
500
|
-
* parses under this schema unchanged.
|
|
537
|
+
* **`error` is optional and, when present, applies to every job named in
|
|
538
|
+
* `job_ids`.** A vanished action server is discovered once, by the bridge's
|
|
539
|
+
* own liveness check on that one action, so a frame naming several jobs at
|
|
540
|
+
* once always shares the same cause. Absent, the cloud settles the job
|
|
541
|
+
* `lost` with no specific code.
|
|
501
542
|
*/
|
|
502
543
|
export const bridgeJobLost = z.object({
|
|
503
544
|
type: z.literal('job_lost'),
|
|
504
545
|
job_ids: z.array(z.uuid()),
|
|
505
546
|
error: z.object({ code: z.string().min(1), message: z.string().min(1) }).optional(),
|
|
506
547
|
});
|
|
548
|
+
/**
|
|
549
|
+
* The cloud asks the bridge how specific jobs stand, while connected;
|
|
550
|
+
* `request_id` correlates the `job_status` answer.
|
|
551
|
+
*
|
|
552
|
+
* Sent for a job that went `unknown` with `bridge_timeout`: the bridge is
|
|
553
|
+
* connected but the cloud has not heard about the job, so it asks instead of
|
|
554
|
+
* guessing. Unanswered within `JOB_HEARTBEAT_TIMEOUT_MS`, the job stays
|
|
555
|
+
* `unknown` and the cloud asks again after the same interval.
|
|
556
|
+
*/
|
|
557
|
+
export const cloudJobQuery = z.object({
|
|
558
|
+
type: z.literal('job_query'),
|
|
559
|
+
request_id: z.string().min(1).max(64),
|
|
560
|
+
job_ids: z.array(z.uuid()).min(1),
|
|
561
|
+
});
|
|
562
|
+
/** One job the bridge recognises, in a `job_status` answer. Same fields as `job_update`'s. */
|
|
563
|
+
export const bridgeJobStatusEntry = z.object({
|
|
564
|
+
job_id: z.uuid(),
|
|
565
|
+
/** Never `unknown` — the bridge only ever states a definite fact about a job it recognises. */
|
|
566
|
+
state: jobState,
|
|
567
|
+
feedback: z.unknown().nullable(),
|
|
568
|
+
progress: z.number().min(0).max(1).nullable(),
|
|
569
|
+
result: z.unknown().nullable(),
|
|
570
|
+
/** Same shape as `job.error`, `details` included — see `jobs.ts`. */
|
|
571
|
+
error: z
|
|
572
|
+
.object({ code: z.string().min(1), message: z.string().min(1), details: z.unknown().optional() })
|
|
573
|
+
.nullable(),
|
|
574
|
+
});
|
|
575
|
+
/**
|
|
576
|
+
* The bridge's answer to a `job_query`. Every queried id lands in exactly
|
|
577
|
+
* one of the two lists.
|
|
578
|
+
*
|
|
579
|
+
* `unknown_job_ids` is an answer, not a failure — the same stance
|
|
580
|
+
* `type_definitions.unresolved` takes. It names the queried jobs the bridge
|
|
581
|
+
* does not recognise at all; the cloud settles one `lost` with
|
|
582
|
+
* `job_unknown_to_bridge` once no goal the bridge cannot attribute is active
|
|
583
|
+
* on its action (one of those may be that very job), and at once for a
|
|
584
|
+
* service job.
|
|
585
|
+
*/
|
|
586
|
+
export const bridgeJobStatus = z.object({
|
|
587
|
+
type: z.literal('job_status'),
|
|
588
|
+
request_id: z.string().min(1).max(64),
|
|
589
|
+
jobs: z.array(bridgeJobStatusEntry),
|
|
590
|
+
unknown_job_ids: z.array(z.uuid()),
|
|
591
|
+
});
|
|
507
592
|
/** Cloud asks for a fresh ROS graph; `request_id` correlates the answer. */
|
|
508
593
|
export const cloudIntrospectRequest = z.object({
|
|
509
594
|
type: z.literal('introspect_request'),
|
package/dist/realtime.d.ts
CHANGED
|
@@ -121,12 +121,17 @@ export declare const commandResult: z.ZodObject<{
|
|
|
121
121
|
robot_id: z.ZodUUID;
|
|
122
122
|
slug: z.ZodString;
|
|
123
123
|
state: z.ZodEnum<{
|
|
124
|
+
unknown: "unknown";
|
|
124
125
|
failed: "failed";
|
|
125
126
|
running: "running";
|
|
126
127
|
succeeded: "succeeded";
|
|
127
128
|
cancelled: "cancelled";
|
|
128
129
|
lost: "lost";
|
|
129
130
|
}>;
|
|
131
|
+
origin: z.ZodEnum<{
|
|
132
|
+
fleetless: "fleetless";
|
|
133
|
+
external: "external";
|
|
134
|
+
}>;
|
|
130
135
|
started_at: z.ZodISODateTime;
|
|
131
136
|
updated_at: z.ZodISODateTime;
|
|
132
137
|
seq: z.ZodNumber;
|
package/dist/rest.d.ts
CHANGED
|
@@ -893,12 +893,17 @@ export declare const invokeResponse: z.ZodObject<{
|
|
|
893
893
|
robot_id: z.ZodUUID;
|
|
894
894
|
slug: z.ZodString;
|
|
895
895
|
state: z.ZodEnum<{
|
|
896
|
+
unknown: "unknown";
|
|
896
897
|
failed: "failed";
|
|
897
898
|
running: "running";
|
|
898
899
|
succeeded: "succeeded";
|
|
899
900
|
cancelled: "cancelled";
|
|
900
901
|
lost: "lost";
|
|
901
902
|
}>;
|
|
903
|
+
origin: z.ZodEnum<{
|
|
904
|
+
fleetless: "fleetless";
|
|
905
|
+
external: "external";
|
|
906
|
+
}>;
|
|
902
907
|
started_at: z.ZodISODateTime;
|
|
903
908
|
updated_at: z.ZodISODateTime;
|
|
904
909
|
seq: z.ZodNumber;
|
|
@@ -946,12 +951,17 @@ export declare const invokeOrServiceResponse: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
946
951
|
robot_id: z.ZodUUID;
|
|
947
952
|
slug: z.ZodString;
|
|
948
953
|
state: z.ZodEnum<{
|
|
954
|
+
unknown: "unknown";
|
|
949
955
|
failed: "failed";
|
|
950
956
|
running: "running";
|
|
951
957
|
succeeded: "succeeded";
|
|
952
958
|
cancelled: "cancelled";
|
|
953
959
|
lost: "lost";
|
|
954
960
|
}>;
|
|
961
|
+
origin: z.ZodEnum<{
|
|
962
|
+
fleetless: "fleetless";
|
|
963
|
+
external: "external";
|
|
964
|
+
}>;
|
|
955
965
|
started_at: z.ZodISODateTime;
|
|
956
966
|
updated_at: z.ZodISODateTime;
|
|
957
967
|
seq: z.ZodNumber;
|
|
@@ -995,12 +1005,17 @@ export declare const jobResponse: z.ZodObject<{
|
|
|
995
1005
|
robot_id: z.ZodUUID;
|
|
996
1006
|
slug: z.ZodString;
|
|
997
1007
|
state: z.ZodEnum<{
|
|
1008
|
+
unknown: "unknown";
|
|
998
1009
|
failed: "failed";
|
|
999
1010
|
running: "running";
|
|
1000
1011
|
succeeded: "succeeded";
|
|
1001
1012
|
cancelled: "cancelled";
|
|
1002
1013
|
lost: "lost";
|
|
1003
1014
|
}>;
|
|
1015
|
+
origin: z.ZodEnum<{
|
|
1016
|
+
fleetless: "fleetless";
|
|
1017
|
+
external: "external";
|
|
1018
|
+
}>;
|
|
1004
1019
|
started_at: z.ZodISODateTime;
|
|
1005
1020
|
updated_at: z.ZodISODateTime;
|
|
1006
1021
|
seq: z.ZodNumber;
|
|
@@ -1088,12 +1103,17 @@ export declare const robotJobsResponse: z.ZodObject<{
|
|
|
1088
1103
|
robot_id: z.ZodUUID;
|
|
1089
1104
|
slug: z.ZodString;
|
|
1090
1105
|
state: z.ZodEnum<{
|
|
1106
|
+
unknown: "unknown";
|
|
1091
1107
|
failed: "failed";
|
|
1092
1108
|
running: "running";
|
|
1093
1109
|
succeeded: "succeeded";
|
|
1094
1110
|
cancelled: "cancelled";
|
|
1095
1111
|
lost: "lost";
|
|
1096
1112
|
}>;
|
|
1113
|
+
origin: z.ZodEnum<{
|
|
1114
|
+
fleetless: "fleetless";
|
|
1115
|
+
external: "external";
|
|
1116
|
+
}>;
|
|
1097
1117
|
started_at: z.ZodISODateTime;
|
|
1098
1118
|
updated_at: z.ZodISODateTime;
|
|
1099
1119
|
seq: z.ZodNumber;
|
package/dist/routes.js
CHANGED
|
@@ -2086,7 +2086,9 @@ export const ROUTES = [
|
|
|
2086
2086
|
'`202` with an `invokeResponse` the moment the job exists; a service answers `200` with a `serviceCallResponse` once the result is in — ' +
|
|
2087
2087
|
'two shapes, carried by one union (`invokeOrServiceResponse`) and told apart by whether `kind` or a bare `result` arrives. Parameters are checked **before** anything about the world (offline, busy): ' +
|
|
2088
2088
|
'the same request must get the same verdict whether or not the robot happens to be reachable, or a developer testing against an offline ' +
|
|
2089
|
-
'robot never learns their parameters were wrong. A
|
|
2089
|
+
'robot never learns their parameters were wrong. A slug is `409 busy` while it holds a `running` job, an `unknown` one the robot has ' +
|
|
2090
|
+
'not accounted for yet, or an `external` goal someone else started; the refusal\'s `details.running` names that job, `state` and ' +
|
|
2091
|
+
'`origin` included. A service the robot reports as failed answers `502` carrying **the job\'s own error ' +
|
|
2090
2092
|
'code**, which is an open set and not one of the codes above.',
|
|
2091
2093
|
},
|
|
2092
2094
|
{
|
|
@@ -2113,8 +2115,9 @@ export const ROUTES = [
|
|
|
2113
2115
|
errors: [...CLIENT_GUARD, 'invalid_uuid', 'not_found', 'validation_error', 'not_cancellable', 'robot_offline'], transport: 'http',
|
|
2114
2116
|
notes: 'The body is optional: a bodyless `POST` was every caller\'s shape before `job_id` existed, and absent or `job_id: null` both mean ' +
|
|
2115
2117
|
'"cancel whatever is running". A named `job_id` that is **not** what is running cancels nothing and answers `404` — the caller named an ' +
|
|
2116
|
-
'id and thereby ruled the other one out.
|
|
2117
|
-
'
|
|
2118
|
+
'id and thereby ruled the other one out. An `external` job is cancelled the same way, through its goal id. Cancelling an `unknown` job ' +
|
|
2119
|
+
'also cancels every external goal on its action, since one of them may be that job. A service is `422 not_cancellable`: a service call ' +
|
|
2120
|
+
'has no goal to cancel. Nothing running is a `200` with `job: null`.',
|
|
2118
2121
|
},
|
|
2119
2122
|
{
|
|
2120
2123
|
method: 'POST', path: '/api/robots/:id/publishers/:slug', section: 'commands',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fleetless/contracts",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0-next.1",
|
|
4
4
|
"description": "Fleetless wire contracts: the bridge-cloud protocol, the REST API schemas and the error codes, as zod schemas with generated JSON Schema and OpenAPI artifacts.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Dehne Robotik GmbH",
|