@fleetless/sdk 1.0.0 → 2.0.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/CHANGELOG.md +101 -0
- package/LICENSE +21 -0
- package/README.md +155 -1134
- package/dist/index.cjs +2963 -1108
- package/dist/index.d.cts +421 -146
- package/dist/index.d.ts +421 -146
- package/dist/index.js +2963 -1108
- package/package.json +43 -7
package/dist/index.d.cts
CHANGED
|
@@ -119,7 +119,7 @@ type BusyDetails = z.infer<typeof busyDetails>;
|
|
|
119
119
|
/**
|
|
120
120
|
* The REST read of one datapoint. For bridge-captured data `timestamp_ms`
|
|
121
121
|
* is the capture time at the bridge (spec §6.3); for the cloud-observed
|
|
122
|
-
* built-in `
|
|
122
|
+
* built-in `bridge_state` it is the time the cloud observed the state.
|
|
123
123
|
*/
|
|
124
124
|
declare const datapointValue: z.ZodObject<{
|
|
125
125
|
slug: z.ZodString;
|
|
@@ -185,7 +185,7 @@ declare const cameraDescriptor: z.ZodObject<{
|
|
|
185
185
|
width: z.ZodNumber;
|
|
186
186
|
height: z.ZodNumber;
|
|
187
187
|
fps: z.ZodNumber;
|
|
188
|
-
|
|
188
|
+
snapshot_interval_seconds: z.ZodNumber;
|
|
189
189
|
}, z.core.$strip>;
|
|
190
190
|
type CameraDescriptor = z.infer<typeof cameraDescriptor>;
|
|
191
191
|
/**
|
|
@@ -241,7 +241,7 @@ type HistoryBucketsResponse = z.infer<typeof historyBucketsResponse>;
|
|
|
241
241
|
/**
|
|
242
242
|
* One datapoint sample pushed to a subscriber. The current value arrives
|
|
243
243
|
* immediately on subscribe, then every change. `timestamp_ms` semantics as
|
|
244
|
-
* in `datapointValue` (capture time; cloud-observed for `
|
|
244
|
+
* in `datapointValue` (capture time; cloud-observed for `bridge_state`).
|
|
245
245
|
*/
|
|
246
246
|
declare const datapointEvent: z.ZodObject<{
|
|
247
247
|
type: z.ZodLiteral<"datapoint">;
|
|
@@ -263,62 +263,57 @@ declare const sessionTokens: z.ZodObject<{
|
|
|
263
263
|
expires_in: z.ZodNumber;
|
|
264
264
|
}, z.core.$strip>;
|
|
265
265
|
type SessionTokens = z.infer<typeof sessionTokens>;
|
|
266
|
+
|
|
266
267
|
/**
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
* configured still issues invitations — it just cannot send them, and says so
|
|
270
|
-
* via `mail_sent`.
|
|
271
|
-
*/
|
|
272
|
-
/**
|
|
273
|
-
* What happened to the mail, in three words instead of one (W6c).
|
|
268
|
+
* **What logout can and cannot end, said in three separable facts (W9c,
|
|
269
|
+
* DEF-098).**
|
|
274
270
|
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
271
|
+
* Until now this route answered `204`: the Fleetless session was over and the
|
|
272
|
+
* response had nothing to say about the *other* session. For a federated user
|
|
273
|
+
* that is the larger half — they clicked "log out", the IdP's cookie survived,
|
|
274
|
+
* and the next login goes straight through without a password. The register
|
|
275
|
+
* row calls that an expectation gap, and it is: the word on the button is
|
|
276
|
+
* "log out", not "log out of this app".
|
|
281
277
|
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
* - `not_configured` — no SMTP is set up. **An expected state, not a failure**
|
|
286
|
-
* (spec §3.2: invitations work without mail; the link is
|
|
287
|
-
* the primary path). The console must not show it as an
|
|
288
|
-
* error.
|
|
289
|
-
* - `failed` — SMTP was configured, was tried, and refused or was
|
|
290
|
-
* unreachable. This one is worth someone's attention.
|
|
291
|
-
*/
|
|
292
|
-
declare const mailStatus: z.ZodEnum<{
|
|
293
|
-
failed: "failed";
|
|
294
|
-
sent: "sent";
|
|
295
|
-
not_configured: "not_configured";
|
|
296
|
-
}>;
|
|
297
|
-
type MailStatus = z.infer<typeof mailStatus>;
|
|
298
|
-
/**
|
|
299
|
-
* What registering answers — deliberately **the same for an address that is
|
|
300
|
-
* new and one that already has an account**.
|
|
278
|
+
* **The Fleetless session is ended before this is computed, unconditionally.**
|
|
279
|
+
* Nothing below can fail in a way that leaves the caller logged in here — a
|
|
280
|
+
* logout that depends on reaching a third party is not a logout.
|
|
301
281
|
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
282
|
+
* **Four outcomes**, and they are deliberately not collapsed into a nullable
|
|
283
|
+
* URL. *No IdP was involved* and *an IdP was involved and publishes no
|
|
284
|
+
* `end_session_endpoint`* are different things: the first needs no action and
|
|
285
|
+
* the second means a session survives that this platform cannot end. A caller
|
|
286
|
+
* that renders them identically is choosing to; a contract that cannot tell
|
|
287
|
+
* them apart makes the choice for everyone.
|
|
306
288
|
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
289
|
+
* **This sentence said "three" for a whole wave, directly above a four-branch
|
|
290
|
+
* union in this same file** — found by Momus-W9, along with the same number in
|
|
291
|
+
* `sdk/src/auth.ts` and `sdk/README.md`. The type is derived
|
|
292
|
+
* (`ClientLogoutResponse['idp_logout']`), so `tsc` had nothing to say, and the
|
|
293
|
+
* sweep shows the mechanism plainly: `sdk d065447` is literally titled *"logout
|
|
294
|
+
* says three separable things"* — correct when written, never carried forward
|
|
295
|
+
* when `hint_unavailable` arrived in `b417d2a`.
|
|
296
|
+
*
|
|
297
|
+
* The count is not the point. **`hint_unavailable` is precisely the case this
|
|
298
|
+
* comment warns about** — the IdP session survives — so a caller who handles
|
|
299
|
+
* the three documented branches drops it into an `else` they believe means
|
|
300
|
+
* *nothing to do*.
|
|
312
301
|
*/
|
|
313
|
-
declare const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
302
|
+
declare const clientLogoutResponse: z.ZodObject<{
|
|
303
|
+
idp_logout: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
304
|
+
status: z.ZodLiteral<"redirect">;
|
|
305
|
+
url: z.ZodURL;
|
|
306
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
307
|
+
status: z.ZodLiteral<"not_federated">;
|
|
308
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
309
|
+
status: z.ZodLiteral<"unsupported_by_idp">;
|
|
310
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
311
|
+
status: z.ZodLiteral<"hint_unavailable">;
|
|
312
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
313
|
+
status: z.ZodLiteral<"session_unknown">;
|
|
314
|
+
}, z.core.$strip>], "status">;
|
|
319
315
|
}, z.core.$strip>;
|
|
320
|
-
type
|
|
321
|
-
|
|
316
|
+
type ClientLogoutResponse = z.infer<typeof clientLogoutResponse>;
|
|
322
317
|
/**
|
|
323
318
|
* Who the caller turned out to be. Returned by the "who am I" endpoint and by
|
|
324
319
|
* the realtime `auth_ok` frame, so a client can render a session without
|
|
@@ -334,6 +329,25 @@ type ClientRegisterResponse = z.infer<typeof clientRegisterResponse>;
|
|
|
334
329
|
* `app_id` and `role_id` are null for them, and roles do not filter what they
|
|
335
330
|
* see. `kind` states this explicitly rather than leaving it to be inferred
|
|
336
331
|
* from which id happens to be set.
|
|
332
|
+
*
|
|
333
|
+
* **`act` is the real admin behind an impersonation** (spec
|
|
334
|
+
* `2026-08-29-org-identity-redesign`, D4, the `act`-claim pattern of RFC
|
|
335
|
+
* 8693). An Org Admins member entering an app through the interstitial
|
|
336
|
+
* (`impersonationChoice`) gets a token whose *effective* identity is the role
|
|
337
|
+
* or user they chose — that is what the rest of this shape describes — while
|
|
338
|
+
* `act` names **the admin who is actually driving**. So every action can
|
|
339
|
+
* audit as "Admin A as User B / as role X", and a client can render the "you
|
|
340
|
+
* are acting as …" banner without decoding the token.
|
|
341
|
+
*
|
|
342
|
+
* **Optional, not a nullable actor, for `orgUser.tier`'s reason:** absence
|
|
343
|
+
* means *this is an ordinary session, nobody is delegating*, which is not the
|
|
344
|
+
* same fact as *the actor is unknown*. The overwhelming majority of sessions
|
|
345
|
+
* are ordinary and carry no `act` at all; a session that has one is a
|
|
346
|
+
* delegation and says who by. The schema cannot check that `act` is present
|
|
347
|
+
* exactly when the effective identity was impersonated — that pairing is the
|
|
348
|
+
* cloud's, minted at the authorize step. Only the admin's **id** rides here:
|
|
349
|
+
* the label is resolved by whoever renders it, not carried as a second
|
|
350
|
+
* unverified name on the wire.
|
|
337
351
|
*/
|
|
338
352
|
declare const clientIdentity: z.ZodObject<{
|
|
339
353
|
kind: z.ZodEnum<{
|
|
@@ -347,6 +361,9 @@ declare const clientIdentity: z.ZodObject<{
|
|
|
347
361
|
app_id: z.ZodNullable<z.ZodUUID>;
|
|
348
362
|
role_id: z.ZodNullable<z.ZodUUID>;
|
|
349
363
|
email: z.ZodNullable<z.ZodEmail>;
|
|
364
|
+
act: z.ZodOptional<z.ZodObject<{
|
|
365
|
+
admin_user_id: z.ZodUUID;
|
|
366
|
+
}, z.core.$strict>>;
|
|
350
367
|
}, z.core.$strip>;
|
|
351
368
|
type ClientIdentity = z.infer<typeof clientIdentity>;
|
|
352
369
|
|
|
@@ -393,9 +410,43 @@ type Asset = z.infer<typeof asset>;
|
|
|
393
410
|
declare const urdfCompleteness: z.ZodObject<{
|
|
394
411
|
present: z.ZodBoolean;
|
|
395
412
|
mesh_count: z.ZodNumber;
|
|
396
|
-
missing: z.ZodArray<z.
|
|
413
|
+
missing: z.ZodArray<z.ZodObject<{
|
|
414
|
+
uri: z.ZodString;
|
|
415
|
+
element: z.ZodEnum<{
|
|
416
|
+
mesh: "mesh";
|
|
417
|
+
texture: "texture";
|
|
418
|
+
}>;
|
|
419
|
+
}, z.core.$strip>>;
|
|
397
420
|
}, z.core.$strip>;
|
|
398
421
|
type UrdfCompleteness = z.infer<typeof urdfCompleteness>;
|
|
422
|
+
declare const assetSyncStatus: z.ZodObject<{
|
|
423
|
+
sync_id: z.ZodUUID;
|
|
424
|
+
robot_id: z.ZodUUID;
|
|
425
|
+
state: z.ZodEnum<{
|
|
426
|
+
running: "running";
|
|
427
|
+
succeeded: "succeeded";
|
|
428
|
+
failed: "failed";
|
|
429
|
+
}>;
|
|
430
|
+
done: z.ZodNumber;
|
|
431
|
+
total: z.ZodNumber;
|
|
432
|
+
failed: z.ZodArray<z.ZodObject<{
|
|
433
|
+
reference: z.ZodString;
|
|
434
|
+
kind: z.ZodEnum<{
|
|
435
|
+
unresolvable: "unresolvable";
|
|
436
|
+
upload_failed: "upload_failed";
|
|
437
|
+
refused: "refused";
|
|
438
|
+
too_large: "too_large";
|
|
439
|
+
}>;
|
|
440
|
+
details: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
441
|
+
limit_bytes: z.ZodNumber;
|
|
442
|
+
size_bytes: z.ZodNumber;
|
|
443
|
+
}, z.core.$strip>>>;
|
|
444
|
+
}, z.core.$strip>>;
|
|
445
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
446
|
+
started_at: z.ZodISODateTime;
|
|
447
|
+
updated_at: z.ZodISODateTime;
|
|
448
|
+
}, z.core.$strip>;
|
|
449
|
+
type AssetSyncStatus = z.infer<typeof assetSyncStatus>;
|
|
399
450
|
declare const assetListResponse: z.ZodObject<{
|
|
400
451
|
assets: z.ZodArray<z.ZodObject<{
|
|
401
452
|
id: z.ZodUUID;
|
|
@@ -412,10 +463,43 @@ declare const assetListResponse: z.ZodObject<{
|
|
|
412
463
|
sha256: z.ZodString;
|
|
413
464
|
created_at: z.ZodISODateTime;
|
|
414
465
|
}, z.core.$strip>>;
|
|
466
|
+
active_sync: z.ZodNullable<z.ZodObject<{
|
|
467
|
+
sync_id: z.ZodUUID;
|
|
468
|
+
robot_id: z.ZodUUID;
|
|
469
|
+
state: z.ZodEnum<{
|
|
470
|
+
running: "running";
|
|
471
|
+
succeeded: "succeeded";
|
|
472
|
+
failed: "failed";
|
|
473
|
+
}>;
|
|
474
|
+
done: z.ZodNumber;
|
|
475
|
+
total: z.ZodNumber;
|
|
476
|
+
failed: z.ZodArray<z.ZodObject<{
|
|
477
|
+
reference: z.ZodString;
|
|
478
|
+
kind: z.ZodEnum<{
|
|
479
|
+
unresolvable: "unresolvable";
|
|
480
|
+
upload_failed: "upload_failed";
|
|
481
|
+
refused: "refused";
|
|
482
|
+
too_large: "too_large";
|
|
483
|
+
}>;
|
|
484
|
+
details: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
485
|
+
limit_bytes: z.ZodNumber;
|
|
486
|
+
size_bytes: z.ZodNumber;
|
|
487
|
+
}, z.core.$strip>>>;
|
|
488
|
+
}, z.core.$strip>>;
|
|
489
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
490
|
+
started_at: z.ZodISODateTime;
|
|
491
|
+
updated_at: z.ZodISODateTime;
|
|
492
|
+
}, z.core.$strip>>;
|
|
415
493
|
urdf: z.ZodObject<{
|
|
416
494
|
present: z.ZodBoolean;
|
|
417
495
|
mesh_count: z.ZodNumber;
|
|
418
|
-
missing: z.ZodArray<z.
|
|
496
|
+
missing: z.ZodArray<z.ZodObject<{
|
|
497
|
+
uri: z.ZodString;
|
|
498
|
+
element: z.ZodEnum<{
|
|
499
|
+
mesh: "mesh";
|
|
500
|
+
texture: "texture";
|
|
501
|
+
}>;
|
|
502
|
+
}, z.core.$strip>>;
|
|
419
503
|
}, z.core.$strip>;
|
|
420
504
|
urdf_available: z.ZodNullable<z.ZodBoolean>;
|
|
421
505
|
}, z.core.$strip>;
|
|
@@ -459,9 +543,79 @@ type ParameterInvalidDetails = z.infer<typeof parameterInvalidDetails>;
|
|
|
459
543
|
* list is the shared vocabulary, not a closed set, so a new refusal never
|
|
460
544
|
* needs a contracts release before it can be reported honestly.
|
|
461
545
|
*/
|
|
462
|
-
declare const ERROR_CODES: readonly ["not_found", "validation_error", "bad_request", "unknown_datapoint", "invalid_token", "protocol_mismatch", "invalid_frame", "duplicate_slug", "reserved_slug", "unknown_field_path", "unknown_type", "unknown_topic", "invalid_rate", "invalid_range", "config_conflict", "no_data", "robot_offline", "bridge_timeout", "unauthorized", "forbidden", "invalid_credentials", "token_expired", "token_revoked", "invite_expired", "invite_used", "email_taken", "identifier_taken", "weak_password", "
|
|
546
|
+
declare const ERROR_CODES: readonly ["not_found", "validation_error", "bad_request", "unknown_datapoint", "invalid_token", "protocol_mismatch", "invalid_frame", "duplicate_slug", "reserved_slug", "unknown_slug", "unknown_field_path", "unknown_type", "unknown_topic", "invalid_rate", "invalid_range", "config_conflict", "no_data", "robot_offline", "bridge_timeout", "unauthorized", "forbidden", "invalid_credentials", "token_expired", "token_revoked", "invite_expired", "invite_used", "email_taken", "identifier_taken", "weak_password", "account_blocked", "busy", "parameter_invalid", "job_lost", "publisher_busy", "unknown_command", "not_subscribable", "camera_offline", "no_snapshot_yet", "live_unavailable", "wrong_kind", "not_recorded", "not_aggregatable", "quota_exceeded", "credential_in_use", "goal_timeout", "robot_in_use", "robot_deletion_partial", "job_queue_full", "invalid_uuid", "rate_limited", "tier_required", "token_spent", "service_timeout", "asset_missing", "asset_too_large", "dynamic_registration_disabled", "client_limit_reached", "identity_conflict", "identity_not_provisioned", "idp_unavailable", "mcp_disabled", "tool_not_available", "capability_required", "last_owner", "group_not_deletable", "group_in_use", "target_state_conflict", "mcp_access_denied", "signup_closed"];
|
|
463
547
|
type ErrorCode = (typeof ERROR_CODES)[number];
|
|
464
548
|
|
|
549
|
+
/**
|
|
550
|
+
* **What an end user sees about their own consents, and why it is not
|
|
551
|
+
* `consentGrant` (W9c, DEF-099).**
|
|
552
|
+
*
|
|
553
|
+
* `consentGrant` is the *record* — four ids and a scope string. A person
|
|
554
|
+
* deciding whether to revoke something needs to recognise it, and an id is
|
|
555
|
+
* not recognisable. So this carries the names that were on the screen when
|
|
556
|
+
* they consented: the client's, the app's, and the role's.
|
|
557
|
+
*
|
|
558
|
+
* `client_id` stays, because it is what a revocation addresses — the names
|
|
559
|
+
* are for reading, the id is for acting.
|
|
560
|
+
*/
|
|
561
|
+
declare const consentGrantSummary: z.ZodObject<{
|
|
562
|
+
client_id: z.ZodString;
|
|
563
|
+
client_name: z.ZodString;
|
|
564
|
+
app_id: z.ZodUUID;
|
|
565
|
+
app_name: z.ZodString;
|
|
566
|
+
role_id: z.ZodUUID;
|
|
567
|
+
role_name: z.ZodString;
|
|
568
|
+
scope: z.ZodString;
|
|
569
|
+
granted_at: z.ZodISODateTime;
|
|
570
|
+
}, z.core.$strip>;
|
|
571
|
+
type ConsentGrantSummary = z.infer<typeof consentGrantSummary>;
|
|
572
|
+
/**
|
|
573
|
+
* **Revoking one grant must end the access it authorised, not merely forget
|
|
574
|
+
* that it happened (W9c, DEF-099).**
|
|
575
|
+
*
|
|
576
|
+
* The register row is about a user who wants a specific client to stop, and
|
|
577
|
+
* the failure mode to avoid is a revocation that deletes the consent row
|
|
578
|
+
* while every already-issued token keeps working until it expires. So the
|
|
579
|
+
* response says what was actually ended, and a caller can tell *nothing
|
|
580
|
+
* matched* from *matched and ended*.
|
|
581
|
+
*
|
|
582
|
+
* `tokens_revoked` is the count of refresh **families** ended. It is not a
|
|
583
|
+
* count of access tokens, and deliberately so: an access token is stateless
|
|
584
|
+
* and short-lived, and a number that claimed to have revoked one would be the
|
|
585
|
+
* kind of sentence this project keeps having to take back.
|
|
586
|
+
*
|
|
587
|
+
* **What actually happens to the access token is stronger than this comment
|
|
588
|
+
* first claimed, and narrower than its correction (W9c, 2026-08-19).** The
|
|
589
|
+
* first version said *"let the access token expire"*. It does not. The
|
|
590
|
+
* correction then said *"the same access token dies"*, which is true and
|
|
591
|
+
* under-specified — Data-W9c read `resolveAnyToken` instead of copying the
|
|
592
|
+
* sentence and found what the check is actually bound to:
|
|
593
|
+
*
|
|
594
|
+
* `if (claims.client_id) { ...consent-grant lookup... }`
|
|
595
|
+
*
|
|
596
|
+
* So the immediate death is scoped to **`client_id`, not to a session and not
|
|
597
|
+
* to the end user.** Every currently-valid token issued through *this
|
|
598
|
+
* client's* OAuth flow for this end user dies at once — including a second
|
|
599
|
+
* tab holding a different token from the same client. A plain `auth.login()`
|
|
600
|
+
* session is untouched, because it carries no `client_id` for the check to
|
|
601
|
+
* read, and a token bound to a *different* client is untouched too.
|
|
602
|
+
*
|
|
603
|
+
* That distinction is the whole point of revoking one grant rather than
|
|
604
|
+
* logging somebody out: *"without touching any other client's access"* is
|
|
605
|
+
* what this route promises, and the check is what makes it true.
|
|
606
|
+
*
|
|
607
|
+
* That is a better outcome than the contract promised, and it is written down
|
|
608
|
+
* here for one reason: **a caller must not build on the weaker sentence.** If
|
|
609
|
+
* this platform ever moves to stateless verification without the revocation
|
|
610
|
+
* re-check, the access token would start living out its TTL again, and
|
|
611
|
+
* anything that quietly relied on immediate death would break silently.
|
|
612
|
+
*/
|
|
613
|
+
declare const consentRevokeResponse: z.ZodObject<{
|
|
614
|
+
revoked: z.ZodBoolean;
|
|
615
|
+
tokens_revoked: z.ZodNumber;
|
|
616
|
+
}, z.core.$strip>;
|
|
617
|
+
type ConsentRevokeResponse = z.infer<typeof consentRevokeResponse>;
|
|
618
|
+
|
|
465
619
|
/**
|
|
466
620
|
* Codes the SDK produces itself rather than relaying from the server. Kept
|
|
467
621
|
* out of `@fleetless/contracts`' `ERROR_CODES` deliberately — that list is
|
|
@@ -771,7 +925,15 @@ interface UrdfSceneResources {
|
|
|
771
925
|
*/
|
|
772
926
|
urdfText: string;
|
|
773
927
|
/**
|
|
774
|
-
* The same
|
|
928
|
+
* The same entries `assets.list()`'s `urdf.missing` reports — verbatim,
|
|
929
|
+
* not reduced to bare strings (W9b, DEF-081). Each carries `element`
|
|
930
|
+
* (`'mesh' | 'texture'`) alongside `uri`: before this, both kinds arrived
|
|
931
|
+
* as an undifferentiated `string[]` and a caller could only ever say "N
|
|
932
|
+
* meshes missing", wrongly, for a URDF whose gap was actually a texture —
|
|
933
|
+
* the same defect W9b fixed one layer up, in the console. Reducing this
|
|
934
|
+
* field back to `string[]` here would throw the distinction away again at
|
|
935
|
+
* exactly the point a caller would render it. If you only need the URIs,
|
|
936
|
+
* `missing.map(m => m.uri)`.
|
|
775
937
|
*
|
|
776
938
|
* **Top-level only — not a `.dae`'s internal references (Kassandra-W7a
|
|
777
939
|
* review correction).** The cloud builds this list from the URDF text
|
|
@@ -791,7 +953,7 @@ interface UrdfSceneResources {
|
|
|
791
953
|
* reference NOT in this list that still fails to load at render time is a
|
|
792
954
|
* different failure — the store answered but the fetch itself did not.
|
|
793
955
|
*/
|
|
794
|
-
missing:
|
|
956
|
+
missing: UrdfCompleteness['missing'];
|
|
795
957
|
/**
|
|
796
958
|
* Revokes every `blob:` URL this call created. Call once the scene has
|
|
797
959
|
* finished loading (success or failure) or on unmount — safe to call more
|
|
@@ -816,6 +978,28 @@ interface AssetsApi {
|
|
|
816
978
|
* workspace by hand, the URIs are what they can act on.
|
|
817
979
|
*/
|
|
818
980
|
list(robotId: string): Promise<AssetListResponse>;
|
|
981
|
+
/**
|
|
982
|
+
* The status of one sync by id — for **reconnecting** to a sync already in
|
|
983
|
+
* flight, not for starting one (W9b, DEF-147).
|
|
984
|
+
*
|
|
985
|
+
* **Starting a sync stays out of this SDK, on purpose (spec §4.6):**
|
|
986
|
+
* "übertragen wird ausschließlich auf explizite Anforderung des
|
|
987
|
+
* Entwicklers über die Console" — a developer action, Owner-tier, done
|
|
988
|
+
* once, from the console. This method is a different thing: `list()`'s
|
|
989
|
+
* `active_sync` (or a `busy` refusal's `assetSyncBusyDetails`) hands a
|
|
990
|
+
* caller a `sync_id` for a sync that is **already running**, and before
|
|
991
|
+
* this method existed there was no way for anything built on this SDK to
|
|
992
|
+
* do anything with that id except throw it away. That was the actual
|
|
993
|
+
* shape of DEF-147: the id was recoverable server-side the whole time
|
|
994
|
+
* (`GET .../assets/sync/{id}` has existed since W7) — nothing reachable
|
|
995
|
+
* from this SDK ever called it.
|
|
996
|
+
*
|
|
997
|
+
* A page reload is the case this exists for: whatever held the `sync_id`
|
|
998
|
+
* in memory is gone, `list()` (or a fresh `busy` refusal) hands it back,
|
|
999
|
+
* and this is how a caller resumes watching the same sync instead of
|
|
1000
|
+
* either losing the progress bar or being told to start a second one.
|
|
1001
|
+
*/
|
|
1002
|
+
syncStatus(robotId: string, syncId: string): Promise<AssetSyncStatus>;
|
|
819
1003
|
/** One asset's bytes by id — a mesh, or any asset directly, addressed the same way `createMeshLoader` reaches one internally. */
|
|
820
1004
|
get(robotId: string, assetId: string): Promise<AssetBytes>;
|
|
821
1005
|
/**
|
|
@@ -1026,17 +1210,46 @@ interface BeginHostedLoginOptions {
|
|
|
1026
1210
|
redirectUri: string;
|
|
1027
1211
|
scope?: string;
|
|
1028
1212
|
/**
|
|
1029
|
-
* RFC 8707 audience binding (register row, W7b
|
|
1030
|
-
* session's token should be usable against
|
|
1031
|
-
*
|
|
1032
|
-
*
|
|
1033
|
-
*
|
|
1034
|
-
*
|
|
1035
|
-
*
|
|
1036
|
-
*
|
|
1037
|
-
*
|
|
1038
|
-
*
|
|
1039
|
-
*
|
|
1213
|
+
* RFC 8707 audience binding (register row, W7b): the resource this
|
|
1214
|
+
* session's token should be usable against. **Omit it for an ordinary app
|
|
1215
|
+
* login.** A token with no `resource` carries no `aud` and works
|
|
1216
|
+
* unrestricted against this app's own REST surface exactly as it always
|
|
1217
|
+
* has; that path is unaffected by this field's existence. Only a caller
|
|
1218
|
+
* that is itself going to present the token to an audience-checking
|
|
1219
|
+
* resource needs to ask for one.
|
|
1220
|
+
*
|
|
1221
|
+
* **`/oauth/authorize` accepts exactly two shapes** — anything else is
|
|
1222
|
+
* refused with `invalid_target` on the redirect back, before a code is
|
|
1223
|
+
* ever issued (`cloud/src/routes/oauth.ts`, `isKnownResource`):
|
|
1224
|
+
*
|
|
1225
|
+
* - `<base>/mcp-stub/resource` — the global OAuth resource stub, matched
|
|
1226
|
+
* byte-for-byte.
|
|
1227
|
+
* - `<base>/mcp-stub/resource/<app_identifier>` — the per-app stub, and
|
|
1228
|
+
* only for **the calling client's own app**. This is an existence check
|
|
1229
|
+
* plus an ownership check, not a shape check: the app must exist *and*
|
|
1230
|
+
* be the one this `clientId` is registered to, so a client on app A can
|
|
1231
|
+
* never be minted a token whose `aud` names app B.
|
|
1232
|
+
*
|
|
1233
|
+
* Both are served and validated by
|
|
1234
|
+
* `cloud/src/routes/oauth-resource-stub.ts`, whose validator refuses a
|
|
1235
|
+
* token with **no** `aud` exactly as hard as one with the wrong `aud` —
|
|
1236
|
+
* "unscoped" must never read as "for me" — comparing by equality, never
|
|
1237
|
+
* by prefix.
|
|
1238
|
+
*
|
|
1239
|
+
* **`<base>/mcp/<app_identifier>` is not a resource any more.** There is
|
|
1240
|
+
* no per-app MCP endpoint: the cloud registers one central, non-parametric
|
|
1241
|
+
* `POST /mcp` (`cloud/src/routes/mcp.ts`, contracts'
|
|
1242
|
+
* `MCP_ENDPOINT_PATH`), and the `/oauth/authorize` branch that used to
|
|
1243
|
+
* accept a `/mcp/<app>` resource was deleted along with the app-level
|
|
1244
|
+
* `mcp_enabled` flag. Asking for one now yields `invalid_target` for
|
|
1245
|
+
* every app, **including your own**. The central MCP endpoint has its own
|
|
1246
|
+
* OAuth flow (`cloud/src/routes/mcp-oauth.ts`) which this SDK's hosted
|
|
1247
|
+
* login does not drive — `beginHostedLogin` always targets
|
|
1248
|
+
* `OAUTH_PATHS.authorize`.
|
|
1249
|
+
*
|
|
1250
|
+
* Whatever you name here is re-checked at the token exchange: it must
|
|
1251
|
+
* match what the code was authorized for, and it must still name a
|
|
1252
|
+
* resource this client may be issued a token for.
|
|
1040
1253
|
*/
|
|
1041
1254
|
resource?: string;
|
|
1042
1255
|
}
|
|
@@ -1089,6 +1302,54 @@ interface CompleteHostedLoginOptions {
|
|
|
1089
1302
|
*/
|
|
1090
1303
|
resource?: string;
|
|
1091
1304
|
}
|
|
1305
|
+
/**
|
|
1306
|
+
* What `logout()` resolves with (W9c, DEF-098) — five separable facts, not
|
|
1307
|
+
* one nullable URL, mirroring the wire's `clientLogoutResponse`.
|
|
1308
|
+
*
|
|
1309
|
+
* `idp_logout` is `null` exactly when `revoked` is `false`: the server call
|
|
1310
|
+
* that would have produced it never got a chance to answer (no local
|
|
1311
|
+
* session, or the request itself failed), so there is nothing to report —
|
|
1312
|
+
* not even "not federated", because this client never learned that either.
|
|
1313
|
+
* When `revoked` is `true` and a real response came back, `idp_logout` is
|
|
1314
|
+
* one of:
|
|
1315
|
+
*
|
|
1316
|
+
* - `{ status: 'redirect', url }` — send the browser here to end the
|
|
1317
|
+
* session at the IdP too. Nothing else in this SDK does that navigation
|
|
1318
|
+
* for you (same "this SDK is thin" reasoning as `cameras.live`).
|
|
1319
|
+
* - `{ status: 'not_federated' }` — this session never came from an IdP;
|
|
1320
|
+
* there is nothing else to end.
|
|
1321
|
+
* - `{ status: 'unsupported_by_idp' }` — it did, and the IdP publishes no
|
|
1322
|
+
* `end_session_endpoint` (RP-initiated logout is optional in OIDC).
|
|
1323
|
+
* - `{ status: 'hint_unavailable' }` — it did, the IdP *can* end the
|
|
1324
|
+
* session, and Fleetless has nothing to ask it with: the stored
|
|
1325
|
+
* `id_token_hint` could not be decrypted, or the session predates the fix
|
|
1326
|
+
* that started keeping one.
|
|
1327
|
+
* - `{ status: 'session_unknown' }` — the server did not find this session at
|
|
1328
|
+
* all (the token was unknown, already superseded, revoked, or expired), so
|
|
1329
|
+
* it can say **nothing** about an IdP.
|
|
1330
|
+
*
|
|
1331
|
+
* **`unsupported_by_idp` and `hint_unavailable` both mean the IdP session
|
|
1332
|
+
* survives and this platform cannot end it** — do not render either one the
|
|
1333
|
+
* same as `not_federated`; that reports a session as fully ended when it
|
|
1334
|
+
* isn't.
|
|
1335
|
+
*
|
|
1336
|
+
* **`session_unknown` is a different kind of nothing, and the reason it
|
|
1337
|
+
* exists is a second logout** (W9 review). A double click, a repeated POST, an
|
|
1338
|
+
* app that logs out on unmount *and* on a route change: the last call wins,
|
|
1339
|
+
* and before this outcome existed it answered `not_federated` — a positive
|
|
1340
|
+
* claim about an IdP the server had never looked up. An app that treats it as
|
|
1341
|
+
* *"fully logged out"* skips a redirect the **first** call may well have
|
|
1342
|
+
* returned, and the user stays signed in at the IdP after clicking log out.
|
|
1343
|
+
*
|
|
1344
|
+
* Note that `revoked` cannot help you here: it reports whether the HTTP call
|
|
1345
|
+
* succeeded, not whether a session was found — so this case arrives as
|
|
1346
|
+
* `{ revoked: true, idp_logout: { status: 'session_unknown' } }`, never as the
|
|
1347
|
+
* `null` below.
|
|
1348
|
+
*/
|
|
1349
|
+
interface LogoutResult {
|
|
1350
|
+
revoked: boolean;
|
|
1351
|
+
idp_logout: ClientLogoutResponse['idp_logout'] | null;
|
|
1352
|
+
}
|
|
1092
1353
|
interface AuthApi {
|
|
1093
1354
|
/** Exchanges email + password, and the client's configured app identifier, for a session. */
|
|
1094
1355
|
login(email: string, password: string): Promise<void>;
|
|
@@ -1197,64 +1458,40 @@ interface AuthApi {
|
|
|
1197
1458
|
* change, a block, or a membership removal take effect on the very next
|
|
1198
1459
|
* request without a fresh token), not a bug — but a kiosk or shared
|
|
1199
1460
|
* workstation needs to know that number.
|
|
1200
|
-
*/
|
|
1201
|
-
logout(): Promise<{
|
|
1202
|
-
revoked: boolean;
|
|
1203
|
-
}>;
|
|
1204
|
-
/** Who the caller turned out to be, without decoding a token client-side. */
|
|
1205
|
-
me(): Promise<ClientIdentity>;
|
|
1206
|
-
/**
|
|
1207
|
-
* Starts self-registration into this app's pool (spec §3.2, W6c) — the
|
|
1208
|
-
* second of the pool's two entry paths, alongside a console invitation.
|
|
1209
|
-
* Sets the password here; `confirmRegistration` below only ever sees a
|
|
1210
|
-
* token.
|
|
1211
|
-
*
|
|
1212
|
-
* **This does not log the caller in — there is no session yet.** A domain
|
|
1213
|
-
* filter says *which* domains may register, never *whether the caller
|
|
1214
|
-
* owns the address*, so minting a session here would let anybody who
|
|
1215
|
-
* knows an allowed domain register as somebody else at it and receive
|
|
1216
|
-
* whatever role the app assigns — which on this platform can mean
|
|
1217
|
-
* permission to move a robot. So this mails a confirmation link and waits;
|
|
1218
|
-
* `confirmRegistration(token)` is what proves the address and returns a
|
|
1219
|
-
* session, the same two-step shape as `requestPasswordReset` /
|
|
1220
|
-
* `confirmPasswordReset` below.
|
|
1221
1461
|
*
|
|
1222
|
-
* **
|
|
1223
|
-
*
|
|
1224
|
-
*
|
|
1225
|
-
*
|
|
1226
|
-
*
|
|
1227
|
-
*
|
|
1228
|
-
*
|
|
1229
|
-
* confirmation link has no other channel.
|
|
1462
|
+
* **Nor does it end a federated session at the identity provider (W9c,
|
|
1463
|
+
* DEF-098).** Ending the Fleetless session and ending the IdP session are
|
|
1464
|
+
* two different things — see `LogoutResult.idp_logout`. This method does
|
|
1465
|
+
* not act on that information itself (no redirect, no fetch to the IdP);
|
|
1466
|
+
* it only reports what the server found, the same "this SDK stays thin"
|
|
1467
|
+
* boundary as everywhere else (`cameras.live` hands back a URL and a
|
|
1468
|
+
* token and stops there too).
|
|
1230
1469
|
*
|
|
1231
|
-
*
|
|
1232
|
-
*
|
|
1233
|
-
* has exactly one role per app), and a signature that accepted one would
|
|
1234
|
-
* be offering a choice the platform has to refuse anyway.
|
|
1470
|
+
* **`idp_logout` is `null` when there was no server answer to report** —
|
|
1471
|
+
* and that is *not* the same as `revoked === false`.
|
|
1235
1472
|
*
|
|
1236
|
-
*
|
|
1237
|
-
*
|
|
1238
|
-
*
|
|
1239
|
-
*
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1473
|
+
* This block used to state the biconditional (*"`null` exactly when
|
|
1474
|
+
* `revoked` is `false`"*), and **it is measurably wrong** (Argus-W9, W9
|
|
1475
|
+
* review): calling `logout()` with **no local session** returns
|
|
1476
|
+
* `{ revoked: true, idp_logout: null }`. The implementation says so six
|
|
1477
|
+
* lines above itself — *"Nothing to revoke: no server-side session lingers,
|
|
1478
|
+
* so this counts as revoked — but there is no IdP fact to report either"* —
|
|
1479
|
+
* so the public docblock and the code contradicted each other in one file.
|
|
1242
1480
|
*
|
|
1243
|
-
*
|
|
1244
|
-
*
|
|
1245
|
-
*
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
/**
|
|
1249
|
-
* Spends a self-registration confirmation token and returns the new
|
|
1250
|
-
* session — the counterpart to `register` above. Stores the session
|
|
1251
|
-
* exactly like `login`, so a caller who has just confirmed is not then
|
|
1252
|
-
* told to log in separately.
|
|
1481
|
+
* That mattered more than a wrong sentence usually does, because **this is
|
|
1482
|
+
* the rule the text tells a caller to branch on**. Someone who reads
|
|
1483
|
+
* `revoked === true` and trusts the promise does not expect `null`.
|
|
1484
|
+
* TypeScript catches it (the type is `| null`); a JavaScript caller does
|
|
1485
|
+
* not.
|
|
1253
1486
|
*
|
|
1254
|
-
*
|
|
1255
|
-
*
|
|
1487
|
+
* So: **`null` means this client had nothing to send or the request never
|
|
1488
|
+
* answered.** It is not `not_federated`, which is a real finding about a
|
|
1489
|
+
* real session — conflating the two is the ambiguity this shape exists to
|
|
1490
|
+
* remove, and it is still the reason to read both fields rather than one.
|
|
1256
1491
|
*/
|
|
1257
|
-
|
|
1492
|
+
logout(): Promise<LogoutResult>;
|
|
1493
|
+
/** Who the caller turned out to be, without decoding a token client-side. */
|
|
1494
|
+
me(): Promise<ClientIdentity>;
|
|
1258
1495
|
/**
|
|
1259
1496
|
* Changes the current end user's password (spec §3, W6c).
|
|
1260
1497
|
*
|
|
@@ -1280,33 +1517,17 @@ interface AuthApi {
|
|
|
1280
1517
|
*/
|
|
1281
1518
|
changePassword(currentPassword: string, newPassword: string): Promise<void>;
|
|
1282
1519
|
/**
|
|
1283
|
-
*
|
|
1284
|
-
*
|
|
1285
|
-
*
|
|
1286
|
-
*
|
|
1287
|
-
* **Resolves the same way whether or not `email` belongs to an account,
|
|
1288
|
-
* and always did — this is not a bug to work around.** It is the one
|
|
1289
|
-
* unauthenticated route in this SDK where revealing existence would be an
|
|
1290
|
-
* account-enumeration oracle (see `passwordResetRequest`'s doc comment in
|
|
1291
|
-
* `@fleetless/contracts`). There is nothing in this method's return value
|
|
1292
|
-
* or its error codes that distinguishes "sent" from "no such account" —
|
|
1293
|
-
* do not build a UI branch for "no such account" here, because there is
|
|
1294
|
-
* nothing to branch on, on purpose.
|
|
1295
|
-
*/
|
|
1296
|
-
requestPasswordReset(email: string): Promise<void>;
|
|
1297
|
-
/**
|
|
1298
|
-
* Completes a password reset using the token from the emailed link (spec
|
|
1299
|
-
* §3, W6c).
|
|
1520
|
+
* The hosted password-reset page, served by the platform on the API
|
|
1521
|
+
* origin (`/reset-password`). An app links a user there; nothing is
|
|
1522
|
+
* called. The two former methods that posted to `/api/client/password/…`
|
|
1523
|
+
* are gone with the routes they named (2.0.0).
|
|
1300
1524
|
*
|
|
1301
|
-
* The
|
|
1302
|
-
*
|
|
1303
|
-
*
|
|
1304
|
-
*
|
|
1305
|
-
* regardless — request a new link. Succeeding revokes every session of
|
|
1306
|
-
* that identity, the same as `changePassword` — a forgotten password is
|
|
1307
|
-
* one of the two states where somebody else may be holding a session.
|
|
1525
|
+
* The page owns the whole flow — it takes the address, mails a
|
|
1526
|
+
* single-use link, and takes the new password on the way back — so there
|
|
1527
|
+
* is nothing for an app to sequence and nothing here that could reveal
|
|
1528
|
+
* whether an address belongs to an account.
|
|
1308
1529
|
*/
|
|
1309
|
-
|
|
1530
|
+
passwordResetUrl(): string;
|
|
1310
1531
|
}
|
|
1311
1532
|
|
|
1312
1533
|
/**
|
|
@@ -1531,6 +1752,58 @@ interface DatapointsApi {
|
|
|
1531
1752
|
}): Promise<HistorySamplesResponse>;
|
|
1532
1753
|
}
|
|
1533
1754
|
|
|
1755
|
+
/**
|
|
1756
|
+
* An end user's own consent grants (spec §3.4/§17, W9c, DEF-099) — every
|
|
1757
|
+
* client this identity has ever authorized, and the means to take one back
|
|
1758
|
+
* without touching any of the others.
|
|
1759
|
+
*
|
|
1760
|
+
* **End-user only.** A server key acts with the app's own full rights and
|
|
1761
|
+
* never went through a consent screen itself — there is no "self" here for
|
|
1762
|
+
* it to list or revoke, same reasoning as `auth.login`/`auth.register` on a
|
|
1763
|
+
* `serverKey` client.
|
|
1764
|
+
*/
|
|
1765
|
+
interface GrantsApi {
|
|
1766
|
+
/**
|
|
1767
|
+
* Every client this end user has consented to, most-recently-granted
|
|
1768
|
+
* first. Each entry carries names, not only ids (`client_name`, `app_name`,
|
|
1769
|
+
* `role_name`) — the id is what `revoke()` addresses, but a person
|
|
1770
|
+
* deciding whether to revoke something needs to *recognise* it first, and
|
|
1771
|
+
* an id is not recognisable. **`client_name` is not trusted** — a
|
|
1772
|
+
* self-registered client chooses its own display name (W7c already
|
|
1773
|
+
* measured what that buys: one called itself "Fleetless Official
|
|
1774
|
+
* Helper") — do not render it as if Fleetless vouched for it.
|
|
1775
|
+
*/
|
|
1776
|
+
list(): Promise<ConsentGrantSummary[]>;
|
|
1777
|
+
/**
|
|
1778
|
+
* Revokes one grant by the client's id — the `client_id` from a
|
|
1779
|
+
* `list()` entry — without touching any other client's access.
|
|
1780
|
+
*
|
|
1781
|
+
* `revoked` tells "nothing matched" (`false`) from "matched and ended"
|
|
1782
|
+
* (`true`) — revoking a grant that is already gone (a stale id, a double
|
|
1783
|
+
* click) is not an error, just a no-op the caller can still tell apart
|
|
1784
|
+
* from a real revocation. `tokens_revoked` counts refresh **families**
|
|
1785
|
+
* ended, not access tokens — that count is deliberately never a claim
|
|
1786
|
+
* about access tokens, which are stateless and short-lived by design.
|
|
1787
|
+
*
|
|
1788
|
+
* **What actually happens to an already-issued access token is stronger
|
|
1789
|
+
* than that count implies, and it was measured, not assumed (W9c gate
|
|
1790
|
+
* step 1, 2026-08-19, end to end through this SDK against a real
|
|
1791
|
+
* cloud).** It does not simply expire on its own: the cloud re-checks
|
|
1792
|
+
* every request for a revoked grant, so **any** currently-valid access
|
|
1793
|
+
* token minted through this same client's OAuth flow for this end user
|
|
1794
|
+
* — not only the one used to call `revoke()` — answers `401
|
|
1795
|
+
* token_revoked` on its very next request, no wait for its TTL. This is
|
|
1796
|
+
* scoped to that one client: a session that never went through this
|
|
1797
|
+
* client's consent (a plain `auth.login()` session, or one bound to a
|
|
1798
|
+
* different client) carries no trace of this client's id and is
|
|
1799
|
+
* unaffected. Do not build on the weaker "it will expire eventually" —
|
|
1800
|
+
* if this platform ever moves to stateless verification without that
|
|
1801
|
+
* re-check, this immediacy would go away silently, which is exactly why
|
|
1802
|
+
* it is written down here instead of left implied.
|
|
1803
|
+
*/
|
|
1804
|
+
revoke(clientId: string): Promise<ConsentRevokeResponse>;
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1534
1807
|
interface JobsApi {
|
|
1535
1808
|
/**
|
|
1536
1809
|
* Every job the platform currently believes this robot has — `GET
|
|
@@ -1653,6 +1926,8 @@ interface FleetlessClientConfig {
|
|
|
1653
1926
|
interface FleetlessClient {
|
|
1654
1927
|
readonly config: FleetlessClientConfig;
|
|
1655
1928
|
readonly auth: AuthApi;
|
|
1929
|
+
/** An end user's own consent grants (spec §3.4/§17, W9c) — not available on a `serverKey` client, same reasoning as `auth`'s session-only methods. */
|
|
1930
|
+
readonly grants: GrantsApi;
|
|
1656
1931
|
readonly datapoints: DatapointsApi;
|
|
1657
1932
|
readonly actions: ActionsApi;
|
|
1658
1933
|
readonly services: ServicesApi;
|
|
@@ -1678,4 +1953,4 @@ interface FleetlessClient {
|
|
|
1678
1953
|
}
|
|
1679
1954
|
declare function createClient(options: FleetlessClientOptions): FleetlessClient;
|
|
1680
1955
|
|
|
1681
|
-
export { type ActionsApi, type Asset, type AssetBytes, type AssetListResponse, type AssetsApi, type AuthApi, type BeginHostedLoginOptions, type BusyDetails, type CameraDescriptor, type CameraLiveSession, type CameraSnapshot, type CameraSnapshotMeta, type CamerasApi, type ClientIdentity, type
|
|
1956
|
+
export { type ActionsApi, type Asset, type AssetBytes, type AssetListResponse, type AssetsApi, type AuthApi, type BeginHostedLoginOptions, type BusyDetails, type CameraDescriptor, type CameraLiveSession, type CameraSnapshot, type CameraSnapshotMeta, type CamerasApi, type ClientIdentity, type CompleteHostedLoginOptions, type ConsentGrantSummary, type ConsentRevokeResponse, type CreateMeshLoaderOptions, type DatapointEvent, type DatapointSubscription, type DatapointSubscriptionHandlers, type DatapointValue, type DatapointsApi, type FleetlessClient, type FleetlessClientConfig, type FleetlessClientOptions, FleetlessError, type FleetlessErrorCode, type FleetlessErrorOptions, type GrantsApi, type HistoryAggregation, type HistoryBucketsResponse, type HistoryOptions, type HistorySamplesResponse, type HostedLoginRequest, InMemoryTokenStore, type Job, type JobEvent, type JobState, type JobSubscription, type JobSubscriptionHandlers, type JobsApi, type LogoutResult, type MeshLoaderDelegate, type ParameterInvalidDetails, type ParameterViolation, type PrepareUrdfSceneOptions, type PublishersApi, type RateLimitDetails, SDK_ERROR_CODES, type SdkErrorCode, type SendCommandOptions, type ServicesApi, type StoredSession, type TokenStore, type UrdfCompleteness, type UrdfSceneManager, type UrdfSceneResources, createClient, parameterInvalidDetails };
|