@fleetless/contracts 1.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 +26 -0
- package/LICENSE +202 -0
- package/NOTICE +17 -0
- package/README.md +88 -0
- package/artifacts/constants.json +24 -0
- package/artifacts/openapi.json +17219 -0
- package/artifacts/routes.json +4605 -0
- package/artifacts/schema/accept-team-invite-request.schema.json +22 -0
- package/artifacts/schema/action-config.schema.json +198 -0
- package/artifacts/schema/alert-list-response.schema.json +172 -0
- package/artifacts/schema/api-error.schema.json +20 -0
- package/artifacts/schema/app-auth-config.schema.json +106 -0
- package/artifacts/schema/app-invitation-list-response.schema.json +57 -0
- package/artifacts/schema/app-invitation.schema.json +69 -0
- package/artifacts/schema/app-list-response.schema.json +82 -0
- package/artifacts/schema/app-mail-template-list-response.schema.json +68 -0
- package/artifacts/schema/app-mail-template.schema.json +54 -0
- package/artifacts/schema/app-oidc-provider-list-response.schema.json +93 -0
- package/artifacts/schema/app-oidc-provider.schema.json +80 -0
- package/artifacts/schema/app-user-list-response.schema.json +111 -0
- package/artifacts/schema/app-user.schema.json +98 -0
- package/artifacts/schema/app.schema.json +69 -0
- package/artifacts/schema/apply-error.schema.json +41 -0
- package/artifacts/schema/asset-list-response.schema.json +288 -0
- package/artifacts/schema/asset-sync-request.schema.json +17 -0
- package/artifacts/schema/asset-sync-response.schema.json +16 -0
- package/artifacts/schema/asset-sync-status.schema.json +136 -0
- package/artifacts/schema/asset.schema.json +68 -0
- package/artifacts/schema/audit-actor.schema.json +32 -0
- package/artifacts/schema/audit-event.schema.json +119 -0
- package/artifacts/schema/audit-list-response.schema.json +144 -0
- package/artifacts/schema/audit-query.schema.json +79 -0
- package/artifacts/schema/auth-error.schema.json +23 -0
- package/artifacts/schema/auth-me-response.schema.json +99 -0
- package/artifacts/schema/auth-ok.schema.json +115 -0
- package/artifacts/schema/authorization-server-metadata.schema.json +80 -0
- package/artifacts/schema/bridge-asset-progress.schema.json +99 -0
- package/artifacts/schema/bridge-assets-available.schema.json +25 -0
- package/artifacts/schema/bridge-camera-state.schema.json +78 -0
- package/artifacts/schema/bridge-config-applied.schema.json +67 -0
- package/artifacts/schema/bridge-hello.schema.json +65 -0
- package/artifacts/schema/bridge-introspect.schema.json +114 -0
- package/artifacts/schema/bridge-job-lost.schema.json +22 -0
- package/artifacts/schema/bridge-job-update.schema.json +100 -0
- package/artifacts/schema/bridge-pong.schema.json +19 -0
- package/artifacts/schema/bridge-pressure.schema.json +292 -0
- package/artifacts/schema/bridge-state.schema.json +24 -0
- package/artifacts/schema/bridge-type-definitions.schema.json +169 -0
- package/artifacts/schema/busy-details.schema.json +115 -0
- package/artifacts/schema/camera-descriptor.schema.json +45 -0
- package/artifacts/schema/camera-list-response.schema.json +58 -0
- package/artifacts/schema/camera-source.schema.json +240 -0
- package/artifacts/schema/cancel-request.schema.json +20 -0
- package/artifacts/schema/client-accept-invitation-request.schema.json +35 -0
- package/artifacts/schema/client-auth.schema.json +18 -0
- package/artifacts/schema/client-cancel.schema.json +45 -0
- package/artifacts/schema/client-identity.schema.json +103 -0
- package/artifacts/schema/client-invoke.schema.json +45 -0
- package/artifacts/schema/client-login-request.schema.json +29 -0
- package/artifacts/schema/client-logout-request.schema.json +14 -0
- package/artifacts/schema/client-mcp-interaction-decision-response.schema.json +15 -0
- package/artifacts/schema/client-mcp-interaction.schema.json +59 -0
- package/artifacts/schema/client-oidc-callback-query.schema.json +28 -0
- package/artifacts/schema/client-oidc-exchange-request.schema.json +21 -0
- package/artifacts/schema/client-oidc-start-query.schema.json +36 -0
- package/artifacts/schema/client-password-reset-confirm-request.schema.json +22 -0
- package/artifacts/schema/client-password-reset-request.schema.json +24 -0
- package/artifacts/schema/client-provider-list-query.schema.json +17 -0
- package/artifacts/schema/client-provider-list-response.schema.json +34 -0
- package/artifacts/schema/client-publish.schema.json +40 -0
- package/artifacts/schema/client-refresh-request.schema.json +14 -0
- package/artifacts/schema/client-register-request.schema.json +44 -0
- package/artifacts/schema/client-resend-verification-request.schema.json +24 -0
- package/artifacts/schema/client-subscribe.schema.json +43 -0
- package/artifacts/schema/client-unsubscribe.schema.json +26 -0
- package/artifacts/schema/client-verify-email-request.schema.json +15 -0
- package/artifacts/schema/cloud-asset-request.schema.json +37 -0
- package/artifacts/schema/cloud-camera-start.schema.json +41 -0
- package/artifacts/schema/cloud-camera-stop.schema.json +26 -0
- package/artifacts/schema/cloud-cancel.schema.json +33 -0
- package/artifacts/schema/cloud-config.schema.json +1635 -0
- package/artifacts/schema/cloud-hello-error.schema.json +23 -0
- package/artifacts/schema/cloud-hello-ok.schema.json +19 -0
- package/artifacts/schema/cloud-introspect-request.schema.json +19 -0
- package/artifacts/schema/cloud-invoke.schema.json +40 -0
- package/artifacts/schema/cloud-ping.schema.json +19 -0
- package/artifacts/schema/cloud-publish.schema.json +28 -0
- package/artifacts/schema/cloud-type-request.schema.json +30 -0
- package/artifacts/schema/command-result.schema.json +175 -0
- package/artifacts/schema/config-draft-response.schema.json +1695 -0
- package/artifacts/schema/config-state.schema.json +124 -0
- package/artifacts/schema/config-version-response.schema.json +1641 -0
- package/artifacts/schema/config-versions-response.schema.json +33 -0
- package/artifacts/schema/create-app-invitation-request.schema.json +40 -0
- package/artifacts/schema/create-app-oidc-provider-request.schema.json +70 -0
- package/artifacts/schema/create-app-request.schema.json +30 -0
- package/artifacts/schema/create-app-user-request.schema.json +42 -0
- package/artifacts/schema/create-robot-request.schema.json +14 -0
- package/artifacts/schema/create-robot-response.schema.json +44 -0
- package/artifacts/schema/create-server-key-response.schema.json +65 -0
- package/artifacts/schema/create-team-invite-request.schema.json +43 -0
- package/artifacts/schema/datapoint-alert-row.schema.json +160 -0
- package/artifacts/schema/datapoint-config.schema.json +366 -0
- package/artifacts/schema/datapoint-display.schema.json +31 -0
- package/artifacts/schema/datapoint-event.schema.json +34 -0
- package/artifacts/schema/datapoint-frame.schema.json +28 -0
- package/artifacts/schema/datapoint-list-response.schema.json +61 -0
- package/artifacts/schema/datapoint-value.schema.json +28 -0
- package/artifacts/schema/developer-login-request.schema.json +19 -0
- package/artifacts/schema/dynamic-client-registration-request.schema.json +60 -0
- package/artifacts/schema/dynamic-client-registration-response.schema.json +68 -0
- package/artifacts/schema/error-frame.schema.json +23 -0
- package/artifacts/schema/exposure-counts.schema.json +39 -0
- package/artifacts/schema/exposure-list-response.schema.json +43 -0
- package/artifacts/schema/fetch-types-request.schema.json +19 -0
- package/artifacts/schema/fetch-types-response.schema.json +163 -0
- package/artifacts/schema/fleetless-user-list-response.schema.json +73 -0
- package/artifacts/schema/fleetless-user.schema.json +60 -0
- package/artifacts/schema/history-buckets-response.schema.json +79 -0
- package/artifacts/schema/history-query.schema.json +58 -0
- package/artifacts/schema/history-response.schema.json +150 -0
- package/artifacts/schema/history-samples-response.schema.json +68 -0
- package/artifacts/schema/introspection-response.schema.json +118 -0
- package/artifacts/schema/invoke-or-service-response.schema.json +141 -0
- package/artifacts/schema/invoke-request.schema.json +23 -0
- package/artifacts/schema/invoke-response.schema.json +125 -0
- package/artifacts/schema/job-actor.schema.json +34 -0
- package/artifacts/schema/job-event.schema.json +158 -0
- package/artifacts/schema/job-response.schema.json +123 -0
- package/artifacts/schema/job-run-list-response.schema.json +222 -0
- package/artifacts/schema/job-run-query.schema.json +95 -0
- package/artifacts/schema/job-run-summary-query.schema.json +23 -0
- package/artifacts/schema/job-run-summary.schema.json +33 -0
- package/artifacts/schema/job-run.schema.json +195 -0
- package/artifacts/schema/job-state.schema.json +11 -0
- package/artifacts/schema/job.schema.json +106 -0
- package/artifacts/schema/latency-bucket.schema.json +63 -0
- package/artifacts/schema/live-session-response.schema.json +41 -0
- package/artifacts/schema/mail-outcome.schema.json +20 -0
- package/artifacts/schema/mail-template-preview-request.schema.json +35 -0
- package/artifacts/schema/mail-template-preview-response.schema.json +31 -0
- package/artifacts/schema/mail-template-problem-details.schema.json +24 -0
- package/artifacts/schema/mcp-consent-grant-list-response.schema.json +52 -0
- package/artifacts/schema/mcp-consent-grant.schema.json +39 -0
- package/artifacts/schema/mcp-robot-datasheet.schema.json +115 -0
- package/artifacts/schema/mcp-role-preview-response.schema.json +134 -0
- package/artifacts/schema/missing-asset-query.schema.json +11 -0
- package/artifacts/schema/oauth-authorize-query.schema.json +47 -0
- package/artifacts/schema/oauth-redirect-response.schema.json +15 -0
- package/artifacts/schema/oauth-token-request.schema.json +47 -0
- package/artifacts/schema/oauth-token-response.schema.json +38 -0
- package/artifacts/schema/org-alerts-query.schema.json +15 -0
- package/artifacts/schema/org-event-dropped.schema.json +26 -0
- package/artifacts/schema/org-event-replay.schema.json +97 -0
- package/artifacts/schema/org-event-subscribe.schema.json +14 -0
- package/artifacts/schema/org-event-unsubscribe.schema.json +14 -0
- package/artifacts/schema/org-event.schema.json +75 -0
- package/artifacts/schema/org-firing-alerts-response.schema.json +178 -0
- package/artifacts/schema/org-health-query.schema.json +13 -0
- package/artifacts/schema/org-latency-query.schema.json +42 -0
- package/artifacts/schema/org-latency-response.schema.json +124 -0
- package/artifacts/schema/org-quota-usage-counts.schema.json +42 -0
- package/artifacts/schema/org-quota-usage.schema.json +102 -0
- package/artifacts/schema/org-quotas.schema.json +51 -0
- package/artifacts/schema/org-usage-query.schema.json +19 -0
- package/artifacts/schema/org-usage-response.schema.json +77 -0
- package/artifacts/schema/org.schema.json +30 -0
- package/artifacts/schema/parameter-invalid-details.schema.json +37 -0
- package/artifacts/schema/parameter-spec.schema.json +120 -0
- package/artifacts/schema/parameter-violation.schema.json +24 -0
- package/artifacts/schema/password-change-request.schema.json +21 -0
- package/artifacts/schema/password-reset-confirm.schema.json +19 -0
- package/artifacts/schema/password-reset-request.schema.json +14 -0
- package/artifacts/schema/patch-app-oidc-provider-request.schema.json +50 -0
- package/artifacts/schema/patch-app-user-request.schema.json +34 -0
- package/artifacts/schema/patch-auth-me-request.schema.json +22 -0
- package/artifacts/schema/patch-fleetless-user-request.schema.json +20 -0
- package/artifacts/schema/patch-org-request.schema.json +15 -0
- package/artifacts/schema/patch-org-response.schema.json +40 -0
- package/artifacts/schema/patch-robot-request.schema.json +15 -0
- package/artifacts/schema/patch-robot-response.schema.json +40 -0
- package/artifacts/schema/pending-team-invite-list-response.schema.json +52 -0
- package/artifacts/schema/pending-team-invite.schema.json +39 -0
- package/artifacts/schema/protected-resource-metadata.schema.json +41 -0
- package/artifacts/schema/publish-config-response.schema.json +21 -0
- package/artifacts/schema/publish-request.schema.json +17 -0
- package/artifacts/schema/publisher-config.schema.json +285 -0
- package/artifacts/schema/put-app-auth-config-request.schema.json +93 -0
- package/artifacts/schema/put-app-mail-template-request.schema.json +35 -0
- package/artifacts/schema/put-config-draft-request.schema.json +13 -0
- package/artifacts/schema/put-datapoint-display-request.schema.json +31 -0
- package/artifacts/schema/put-robot-details-request.schema.json +41 -0
- package/artifacts/schema/put-robot-details-response.schema.json +43 -0
- package/artifacts/schema/rate-limit-details.schema.json +15 -0
- package/artifacts/schema/refresh-request.schema.json +13 -0
- package/artifacts/schema/release-live-query.schema.json +13 -0
- package/artifacts/schema/rename-slug-request.schema.json +23 -0
- package/artifacts/schema/rename-slug-response.schema.json +24 -0
- package/artifacts/schema/resource-health-event.schema.json +72 -0
- package/artifacts/schema/resource-health-list-response.schema.json +80 -0
- package/artifacts/schema/resource-health-state.schema.json +68 -0
- package/artifacts/schema/robot-config-doc.schema.json +1616 -0
- package/artifacts/schema/robot-delete-query.schema.json +12 -0
- package/artifacts/schema/robot-deletion-summary.schema.json +63 -0
- package/artifacts/schema/robot-detail-response.schema.json +262 -0
- package/artifacts/schema/robot-details-doc.schema.json +33 -0
- package/artifacts/schema/robot-jobs-response.schema.json +119 -0
- package/artifacts/schema/robot-latency-series.schema.json +81 -0
- package/artifacts/schema/robot-list-item.schema.json +94 -0
- package/artifacts/schema/robot-list-response.schema.json +106 -0
- package/artifacts/schema/robot.schema.json +30 -0
- package/artifacts/schema/role-list-response.schema.json +48 -0
- package/artifacts/schema/role-permissions.schema.json +61 -0
- package/artifacts/schema/role.schema.json +35 -0
- package/artifacts/schema/ros-graph.schema.json +99 -0
- package/artifacts/schema/server-key-list-response.schema.json +64 -0
- package/artifacts/schema/server-key.schema.json +51 -0
- package/artifacts/schema/service-call-response.schema.json +13 -0
- package/artifacts/schema/service-config.schema.json +198 -0
- package/artifacts/schema/session-tokens.schema.json +28 -0
- package/artifacts/schema/sign-up-request.schema.json +26 -0
- package/artifacts/schema/sign-up-response.schema.json +127 -0
- package/artifacts/schema/slug-usage-response.schema.json +32 -0
- package/artifacts/schema/snapshot-header.schema.json +44 -0
- package/artifacts/schema/snapshot-meta-response.schema.json +85 -0
- package/artifacts/schema/subscribe-error.schema.json +31 -0
- package/artifacts/schema/team-invite.schema.json +57 -0
- package/artifacts/schema/tier-change-request.schema.json +17 -0
- package/artifacts/schema/type-definition.schema.json +144 -0
- package/artifacts/schema/types-response.schema.json +156 -0
- package/artifacts/schema/update-app-request.schema.json +32 -0
- package/artifacts/schema/urdf-completeness.schema.json +50 -0
- package/artifacts/schema/validation-issue.schema.json +43 -0
- package/artifacts/schema/waitlist-request.schema.json +15 -0
- package/artifacts/schema-outgoing/bridge-asset-progress.schema.json +102 -0
- package/artifacts/schema-outgoing/bridge-assets-available.schema.json +26 -0
- package/artifacts/schema-outgoing/bridge-camera-state.schema.json +80 -0
- package/artifacts/schema-outgoing/bridge-config-applied.schema.json +69 -0
- package/artifacts/schema-outgoing/bridge-hello.schema.json +68 -0
- package/artifacts/schema-outgoing/bridge-introspect.schema.json +119 -0
- package/artifacts/schema-outgoing/bridge-job-lost.schema.json +23 -0
- package/artifacts/schema-outgoing/bridge-job-update.schema.json +102 -0
- package/artifacts/schema-outgoing/bridge-pong.schema.json +20 -0
- package/artifacts/schema-outgoing/bridge-type-definitions.schema.json +174 -0
- package/artifacts/schema-outgoing/datapoint-frame.schema.json +29 -0
- package/artifacts/schema-outgoing/snapshot-header.schema.json +45 -0
- package/dist/alerts.d.ts +255 -0
- package/dist/alerts.js +193 -0
- package/dist/app-users.d.ts +606 -0
- package/dist/app-users.js +696 -0
- package/dist/apps.d.ts +175 -0
- package/dist/apps.js +267 -0
- package/dist/assets.d.ts +434 -0
- package/dist/assets.js +546 -0
- package/dist/audit.d.ts +129 -0
- package/dist/audit.js +238 -0
- package/dist/client-auth.d.ts +409 -0
- package/dist/client-auth.js +487 -0
- package/dist/common.d.ts +186 -0
- package/dist/common.js +199 -0
- package/dist/config-issues.d.ts +175 -0
- package/dist/config-issues.js +339 -0
- package/dist/config.d.ts +862 -0
- package/dist/config.js +1988 -0
- package/dist/errors.d.ts +52 -0
- package/dist/errors.js +786 -0
- package/dist/identity.d.ts +549 -0
- package/dist/identity.js +503 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +51 -0
- package/dist/introspection.d.ts +99 -0
- package/dist/introspection.js +97 -0
- package/dist/jobs.d.ts +334 -0
- package/dist/jobs.js +345 -0
- package/dist/mcp.d.ts +239 -0
- package/dist/mcp.js +153 -0
- package/dist/oauth.d.ts +344 -0
- package/dist/oauth.js +488 -0
- package/dist/protocol.d.ts +781 -0
- package/dist/protocol.js +715 -0
- package/dist/realtime.d.ts +494 -0
- package/dist/realtime.js +512 -0
- package/dist/rest.d.ts +1989 -0
- package/dist/rest.js +1963 -0
- package/dist/routes.d.ts +94 -0
- package/dist/routes.js +2298 -0
- package/package.json +61 -0
package/dist/rest.d.ts
ADDED
|
@@ -0,0 +1,1989 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* REST shapes of the robot resource (spec §11.1). W1 scope: create, list,
|
|
4
|
+
* get, and the built-in `bridge_state` datapoint read.
|
|
5
|
+
*/
|
|
6
|
+
export declare const robot: z.ZodObject<{
|
|
7
|
+
id: z.ZodUUID;
|
|
8
|
+
name: z.ZodString;
|
|
9
|
+
created_at: z.ZodISODateTime;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
export type Robot = z.infer<typeof robot>;
|
|
12
|
+
/** What `PATCH /api/robots/:id` answers: the robot as it now stands. */
|
|
13
|
+
export declare const patchRobotResponse: z.ZodObject<{
|
|
14
|
+
robot: z.ZodObject<{
|
|
15
|
+
id: z.ZodUUID;
|
|
16
|
+
name: z.ZodString;
|
|
17
|
+
created_at: z.ZodISODateTime;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
export type PatchRobotResponse = z.infer<typeof patchRobotResponse>;
|
|
21
|
+
export declare const createRobotRequest: z.ZodObject<{
|
|
22
|
+
name: z.ZodString;
|
|
23
|
+
}, z.core.$strip>;
|
|
24
|
+
export type CreateRobotRequest = z.infer<typeof createRobotRequest>;
|
|
25
|
+
/**
|
|
26
|
+
* The robot token binds one bridge to one robot (spec §5). It is returned
|
|
27
|
+
* exactly once, here; the cloud stores only a hash of it.
|
|
28
|
+
*/
|
|
29
|
+
export declare const robotToken: z.ZodString;
|
|
30
|
+
export declare const createRobotResponse: z.ZodObject<{
|
|
31
|
+
robot: z.ZodObject<{
|
|
32
|
+
id: z.ZodUUID;
|
|
33
|
+
name: z.ZodString;
|
|
34
|
+
created_at: z.ZodISODateTime;
|
|
35
|
+
}, z.core.$strip>;
|
|
36
|
+
token: z.ZodString;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
export type CreateRobotResponse = z.infer<typeof createRobotResponse>;
|
|
39
|
+
/**
|
|
40
|
+
* How many things a robot exposes, per kind (spec `2026-08-21-exposure-and-revoke-design` D1).
|
|
41
|
+
*
|
|
42
|
+
* **Five numbers, never a sum.** `robotDeletionSummary.slug_count` already made
|
|
43
|
+
* this call and wrote down why: fold cameras in and the sentence "this deletes
|
|
44
|
+
* N slugs and M cameras" counts them twice. A list row has the same problem.
|
|
45
|
+
*
|
|
46
|
+
* **Counted from the published configuration, and excluding the built-ins.**
|
|
47
|
+
* `GET /api/robots/:id/exposures` answers *which* slugs and prepends the
|
|
48
|
+
* three built-in datapoints — `bridge_state`, `robot_details` and
|
|
49
|
+
* `bridge_pressure` — as `builtin: true`; this answers *how many* and counts
|
|
50
|
+
* only what somebody configured. So a robot with an empty published config
|
|
51
|
+
* reports `datapoints: 0` here and three entries there. That is intentional,
|
|
52
|
+
* and it is written on both sides so the disagreement is never mistaken for a
|
|
53
|
+
* bug.
|
|
54
|
+
*
|
|
55
|
+
* The number is "three" and not "two" as of `bridge_pressure`; the cloud
|
|
56
|
+
* builds that prefix from `PLANE_BUILTIN_DATAPOINTS` rather than a literal,
|
|
57
|
+
* so a further built-in moves this count again. Read the count off that set,
|
|
58
|
+
* not off this sentence, before filing the bug this comment exists to
|
|
59
|
+
* prevent.
|
|
60
|
+
*/
|
|
61
|
+
export declare const exposureCounts: z.ZodObject<{
|
|
62
|
+
datapoints: z.ZodNumber;
|
|
63
|
+
actions: z.ZodNumber;
|
|
64
|
+
services: z.ZodNumber;
|
|
65
|
+
publishers: z.ZodNumber;
|
|
66
|
+
cameras: z.ZodNumber;
|
|
67
|
+
}, z.core.$strip>;
|
|
68
|
+
export type ExposureCounts = z.infer<typeof exposureCounts>;
|
|
69
|
+
/** A robot as listed, with its current built-in `bridge_state`. */
|
|
70
|
+
export declare const robotListItem: z.ZodObject<{
|
|
71
|
+
bridge_state: z.ZodObject<{
|
|
72
|
+
online: z.ZodBoolean;
|
|
73
|
+
latency_ms: z.ZodNullable<z.ZodNumber>;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
exposes: z.ZodObject<{
|
|
76
|
+
datapoints: z.ZodNumber;
|
|
77
|
+
actions: z.ZodNumber;
|
|
78
|
+
services: z.ZodNumber;
|
|
79
|
+
publishers: z.ZodNumber;
|
|
80
|
+
cameras: z.ZodNumber;
|
|
81
|
+
}, z.core.$strip>;
|
|
82
|
+
id: z.ZodUUID;
|
|
83
|
+
name: z.ZodString;
|
|
84
|
+
created_at: z.ZodISODateTime;
|
|
85
|
+
}, z.core.$strip>;
|
|
86
|
+
export type RobotListItem = z.infer<typeof robotListItem>;
|
|
87
|
+
export declare const robotListResponse: z.ZodObject<{
|
|
88
|
+
robots: z.ZodArray<z.ZodObject<{
|
|
89
|
+
bridge_state: z.ZodObject<{
|
|
90
|
+
online: z.ZodBoolean;
|
|
91
|
+
latency_ms: z.ZodNullable<z.ZodNumber>;
|
|
92
|
+
}, z.core.$strip>;
|
|
93
|
+
exposes: z.ZodObject<{
|
|
94
|
+
datapoints: z.ZodNumber;
|
|
95
|
+
actions: z.ZodNumber;
|
|
96
|
+
services: z.ZodNumber;
|
|
97
|
+
publishers: z.ZodNumber;
|
|
98
|
+
cameras: z.ZodNumber;
|
|
99
|
+
}, z.core.$strip>;
|
|
100
|
+
id: z.ZodUUID;
|
|
101
|
+
name: z.ZodString;
|
|
102
|
+
created_at: z.ZodISODateTime;
|
|
103
|
+
}, z.core.$strip>>;
|
|
104
|
+
}, z.core.$strip>;
|
|
105
|
+
export type RobotListResponse = z.infer<typeof robotListResponse>;
|
|
106
|
+
/**
|
|
107
|
+
* The REST read of one datapoint. For bridge-captured data `timestamp_ms`
|
|
108
|
+
* is the capture time at the bridge (spec §6.3); for the cloud-observed
|
|
109
|
+
* built-in `bridge_state` it is the time the cloud observed the state.
|
|
110
|
+
*/
|
|
111
|
+
export declare const datapointValue: z.ZodObject<{
|
|
112
|
+
slug: z.ZodString;
|
|
113
|
+
value: z.ZodUnknown;
|
|
114
|
+
timestamp_ms: z.ZodNumber;
|
|
115
|
+
}, z.core.$strip>;
|
|
116
|
+
export type DatapointValue = z.infer<typeof datapointValue>;
|
|
117
|
+
/**
|
|
118
|
+
* One robot in full: what the list shows, plus what only the detail view
|
|
119
|
+
* needs — which bridge build is connected, why the last hello was refused,
|
|
120
|
+
* and where the configuration stands (spec §15.2, tab 1).
|
|
121
|
+
*/
|
|
122
|
+
export declare const robotDetailResponse: z.ZodObject<{
|
|
123
|
+
bridge_version: z.ZodNullable<z.ZodString>;
|
|
124
|
+
last_hello_error: z.ZodNullable<z.ZodObject<{
|
|
125
|
+
code: z.ZodString;
|
|
126
|
+
message: z.ZodString;
|
|
127
|
+
at: z.ZodISODateTime;
|
|
128
|
+
}, z.core.$strip>>;
|
|
129
|
+
config: z.ZodObject<{
|
|
130
|
+
published_version: z.ZodNullable<z.ZodNumber>;
|
|
131
|
+
published_at: z.ZodNullable<z.ZodISODateTime>;
|
|
132
|
+
draft_updated_at: z.ZodNullable<z.ZodISODateTime>;
|
|
133
|
+
applied_version: z.ZodNullable<z.ZodNumber>;
|
|
134
|
+
applied_ok: z.ZodNullable<z.ZodBoolean>;
|
|
135
|
+
applied_errors: z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
136
|
+
slug: z.ZodString;
|
|
137
|
+
kind: z.ZodEnum<{
|
|
138
|
+
datapoint: "datapoint";
|
|
139
|
+
action: "action";
|
|
140
|
+
service: "service";
|
|
141
|
+
publisher: "publisher";
|
|
142
|
+
camera: "camera";
|
|
143
|
+
}>;
|
|
144
|
+
code: z.ZodString;
|
|
145
|
+
message: z.ZodString;
|
|
146
|
+
details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
147
|
+
}, z.core.$strip>>>;
|
|
148
|
+
}, z.core.$strip>;
|
|
149
|
+
bridge_state: z.ZodObject<{
|
|
150
|
+
online: z.ZodBoolean;
|
|
151
|
+
latency_ms: z.ZodNullable<z.ZodNumber>;
|
|
152
|
+
}, z.core.$strip>;
|
|
153
|
+
exposes: z.ZodObject<{
|
|
154
|
+
datapoints: z.ZodNumber;
|
|
155
|
+
actions: z.ZodNumber;
|
|
156
|
+
services: z.ZodNumber;
|
|
157
|
+
publishers: z.ZodNumber;
|
|
158
|
+
cameras: z.ZodNumber;
|
|
159
|
+
}, z.core.$strip>;
|
|
160
|
+
id: z.ZodUUID;
|
|
161
|
+
name: z.ZodString;
|
|
162
|
+
created_at: z.ZodISODateTime;
|
|
163
|
+
}, z.core.$strip>;
|
|
164
|
+
export type RobotDetailResponse = z.infer<typeof robotDetailResponse>;
|
|
165
|
+
/**
|
|
166
|
+
* The editable configuration. `issues` is recomputed on every read and
|
|
167
|
+
* write, so the editor never has to guess whether it may publish.
|
|
168
|
+
*
|
|
169
|
+
* **`source` is the author's text and `doc` is what it parses to.** Both are
|
|
170
|
+
* sent because they answer different questions: an editor renders the text a
|
|
171
|
+
* developer wrote, comments and key order intact, while every other consumer —
|
|
172
|
+
* the robot page, the MCP tools, the bridge frame — reads the parsed document
|
|
173
|
+
* and should never have to parse YAML to do it.
|
|
174
|
+
*
|
|
175
|
+
* **`doc` is null when the text is valid YAML but not a fleetless document.**
|
|
176
|
+
* A draft is saved whenever it parses as YAML; publish is the gate that asks
|
|
177
|
+
* for a document. So a stored draft can genuinely have no document, and `null`
|
|
178
|
+
* says exactly that: *this text does not currently parse to a configuration*.
|
|
179
|
+
* It does **not** mean "nothing is configured" — the last published version is
|
|
180
|
+
* untouched — and a reader that renders a tree from `doc` has to tell those two
|
|
181
|
+
* apart before it draws anything.
|
|
182
|
+
*
|
|
183
|
+
* The alternative was to put the raw parsed YAML value in `doc`. It was
|
|
184
|
+
* rejected because a reader could then no longer tell whether what it holds is
|
|
185
|
+
* a document: every consumer would have to re-validate to find out, and the one
|
|
186
|
+
* that forgot would render a stranger's mapping as a configuration. `null`
|
|
187
|
+
* forces the question at the point of reading.
|
|
188
|
+
*
|
|
189
|
+
* `source` is never null, and that is what makes the pair `doc: null,
|
|
190
|
+
* source: null` unrepresentable here rather than merely discouraged. A draft
|
|
191
|
+
* exists from the moment a robot does, before anyone has typed anything; for
|
|
192
|
+
* that one the server renders the document instead, so a reader always has text
|
|
193
|
+
* to show and — when there is no document — always has the text that failed to
|
|
194
|
+
* become one.
|
|
195
|
+
*/
|
|
196
|
+
export declare const configDraftResponse: z.ZodObject<{
|
|
197
|
+
doc: z.ZodNullable<z.ZodObject<{
|
|
198
|
+
fleetless: z.ZodLiteral<1>;
|
|
199
|
+
messages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
200
|
+
datapoints: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
201
|
+
topic: z.ZodString;
|
|
202
|
+
type: z.ZodString;
|
|
203
|
+
field: z.ZodOptional<z.ZodString>;
|
|
204
|
+
rate_throttle_hz: z.ZodOptional<z.ZodNumber>;
|
|
205
|
+
description: z.ZodOptional<z.ZodString>;
|
|
206
|
+
numeric: z.ZodOptional<z.ZodObject<{
|
|
207
|
+
scale: z.ZodOptional<z.ZodNumber>;
|
|
208
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
209
|
+
unit: z.ZodOptional<z.ZodString>;
|
|
210
|
+
decimals: z.ZodOptional<z.ZodNumber>;
|
|
211
|
+
}, z.core.$strict>>;
|
|
212
|
+
retention: z.ZodOptional<z.ZodObject<{
|
|
213
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
214
|
+
interval_seconds: z.ZodOptional<z.ZodNumber>;
|
|
215
|
+
max_buffer_values: z.ZodOptional<z.ZodNumber>;
|
|
216
|
+
}, z.core.$strict>>;
|
|
217
|
+
chart: z.ZodOptional<z.ZodObject<{
|
|
218
|
+
y_min: z.ZodOptional<z.ZodNumber>;
|
|
219
|
+
y_max: z.ZodOptional<z.ZodNumber>;
|
|
220
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
221
|
+
line: "line";
|
|
222
|
+
step: "step";
|
|
223
|
+
}>>;
|
|
224
|
+
default_window_minutes: z.ZodOptional<z.ZodNumber>;
|
|
225
|
+
}, z.core.$strict>>;
|
|
226
|
+
alerts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
227
|
+
condition: z.ZodObject<{
|
|
228
|
+
fire_at: z.ZodUnion<readonly [z.ZodNumber, z.ZodString, z.ZodBoolean]>;
|
|
229
|
+
resolve_at: z.ZodOptional<z.ZodNumber>;
|
|
230
|
+
}, z.core.$strict>;
|
|
231
|
+
severity: z.ZodOptional<z.ZodEnum<{
|
|
232
|
+
error: "error";
|
|
233
|
+
warning: "warning";
|
|
234
|
+
}>>;
|
|
235
|
+
name: z.ZodOptional<z.ZodString>;
|
|
236
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
237
|
+
}, z.core.$strict>>>;
|
|
238
|
+
}, z.core.$strict>>>;
|
|
239
|
+
actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
240
|
+
ros_name: z.ZodString;
|
|
241
|
+
type: z.ZodString;
|
|
242
|
+
message: z.ZodOptional<z.ZodUnknown>;
|
|
243
|
+
parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
244
|
+
type: z.ZodEnum<{
|
|
245
|
+
string: "string";
|
|
246
|
+
bool: "bool";
|
|
247
|
+
byte: "byte";
|
|
248
|
+
char: "char";
|
|
249
|
+
int8: "int8";
|
|
250
|
+
uint8: "uint8";
|
|
251
|
+
int16: "int16";
|
|
252
|
+
uint16: "uint16";
|
|
253
|
+
int32: "int32";
|
|
254
|
+
uint32: "uint32";
|
|
255
|
+
int64: "int64";
|
|
256
|
+
uint64: "uint64";
|
|
257
|
+
float32: "float32";
|
|
258
|
+
float64: "float64";
|
|
259
|
+
wstring: "wstring";
|
|
260
|
+
}>;
|
|
261
|
+
default: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString, z.ZodBoolean]>>;
|
|
262
|
+
min_value: z.ZodOptional<z.ZodNumber>;
|
|
263
|
+
max_value: z.ZodOptional<z.ZodNumber>;
|
|
264
|
+
enum: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
265
|
+
regex: z.ZodOptional<z.ZodString>;
|
|
266
|
+
description: z.ZodOptional<z.ZodString>;
|
|
267
|
+
}, z.core.$strict>>>;
|
|
268
|
+
description: z.ZodOptional<z.ZodString>;
|
|
269
|
+
}, z.core.$strict>>>;
|
|
270
|
+
services: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
271
|
+
ros_name: z.ZodString;
|
|
272
|
+
type: z.ZodString;
|
|
273
|
+
message: z.ZodOptional<z.ZodUnknown>;
|
|
274
|
+
parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
275
|
+
type: z.ZodEnum<{
|
|
276
|
+
string: "string";
|
|
277
|
+
bool: "bool";
|
|
278
|
+
byte: "byte";
|
|
279
|
+
char: "char";
|
|
280
|
+
int8: "int8";
|
|
281
|
+
uint8: "uint8";
|
|
282
|
+
int16: "int16";
|
|
283
|
+
uint16: "uint16";
|
|
284
|
+
int32: "int32";
|
|
285
|
+
uint32: "uint32";
|
|
286
|
+
int64: "int64";
|
|
287
|
+
uint64: "uint64";
|
|
288
|
+
float32: "float32";
|
|
289
|
+
float64: "float64";
|
|
290
|
+
wstring: "wstring";
|
|
291
|
+
}>;
|
|
292
|
+
default: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString, z.ZodBoolean]>>;
|
|
293
|
+
min_value: z.ZodOptional<z.ZodNumber>;
|
|
294
|
+
max_value: z.ZodOptional<z.ZodNumber>;
|
|
295
|
+
enum: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
296
|
+
regex: z.ZodOptional<z.ZodString>;
|
|
297
|
+
description: z.ZodOptional<z.ZodString>;
|
|
298
|
+
}, z.core.$strict>>>;
|
|
299
|
+
description: z.ZodOptional<z.ZodString>;
|
|
300
|
+
}, z.core.$strict>>>;
|
|
301
|
+
publishers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
302
|
+
topic: z.ZodString;
|
|
303
|
+
type: z.ZodString;
|
|
304
|
+
message: z.ZodUnknown;
|
|
305
|
+
parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
306
|
+
type: z.ZodEnum<{
|
|
307
|
+
string: "string";
|
|
308
|
+
bool: "bool";
|
|
309
|
+
byte: "byte";
|
|
310
|
+
char: "char";
|
|
311
|
+
int8: "int8";
|
|
312
|
+
uint8: "uint8";
|
|
313
|
+
int16: "int16";
|
|
314
|
+
uint16: "uint16";
|
|
315
|
+
int32: "int32";
|
|
316
|
+
uint32: "uint32";
|
|
317
|
+
int64: "int64";
|
|
318
|
+
uint64: "uint64";
|
|
319
|
+
float32: "float32";
|
|
320
|
+
float64: "float64";
|
|
321
|
+
wstring: "wstring";
|
|
322
|
+
}>;
|
|
323
|
+
default: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString, z.ZodBoolean]>>;
|
|
324
|
+
min_value: z.ZodOptional<z.ZodNumber>;
|
|
325
|
+
max_value: z.ZodOptional<z.ZodNumber>;
|
|
326
|
+
enum: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
327
|
+
regex: z.ZodOptional<z.ZodString>;
|
|
328
|
+
description: z.ZodOptional<z.ZodString>;
|
|
329
|
+
}, z.core.$strict>>>;
|
|
330
|
+
failsafe: z.ZodObject<{
|
|
331
|
+
timeout_ms: z.ZodNumber;
|
|
332
|
+
message: z.ZodUnknown;
|
|
333
|
+
}, z.core.$strict>;
|
|
334
|
+
quiet_timeout_ms: z.ZodNumber;
|
|
335
|
+
description: z.ZodOptional<z.ZodString>;
|
|
336
|
+
}, z.core.$strict>>>;
|
|
337
|
+
cameras: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
338
|
+
source: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
339
|
+
kind: z.ZodLiteral<"ros">;
|
|
340
|
+
topic: z.ZodString;
|
|
341
|
+
type: z.ZodString;
|
|
342
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
343
|
+
kind: z.ZodLiteral<"rtsp">;
|
|
344
|
+
url: z.ZodString;
|
|
345
|
+
transport: z.ZodOptional<z.ZodEnum<{
|
|
346
|
+
tcp: "tcp";
|
|
347
|
+
udp: "udp";
|
|
348
|
+
}>>;
|
|
349
|
+
credentials: z.ZodOptional<z.ZodObject<{
|
|
350
|
+
username: z.ZodOptional<z.ZodString>;
|
|
351
|
+
password: z.ZodOptional<z.ZodString>;
|
|
352
|
+
}, z.core.$strict>>;
|
|
353
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
354
|
+
kind: z.ZodLiteral<"mjpeg">;
|
|
355
|
+
url: z.ZodString;
|
|
356
|
+
credentials: z.ZodOptional<z.ZodObject<{
|
|
357
|
+
username: z.ZodOptional<z.ZodString>;
|
|
358
|
+
password: z.ZodOptional<z.ZodString>;
|
|
359
|
+
}, z.core.$strict>>;
|
|
360
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
361
|
+
kind: z.ZodLiteral<"v4l2">;
|
|
362
|
+
device: z.ZodString;
|
|
363
|
+
}, z.core.$strict>], "kind">;
|
|
364
|
+
width: z.ZodNumber;
|
|
365
|
+
height: z.ZodNumber;
|
|
366
|
+
fps: z.ZodNumber;
|
|
367
|
+
bitrate_kbps: z.ZodNumber;
|
|
368
|
+
snapshot_interval_seconds: z.ZodNumber;
|
|
369
|
+
description: z.ZodOptional<z.ZodString>;
|
|
370
|
+
}, z.core.$strict>>>;
|
|
371
|
+
}, z.core.$strict>>;
|
|
372
|
+
source: z.ZodString;
|
|
373
|
+
updated_at: z.ZodNullable<z.ZodISODateTime>;
|
|
374
|
+
issues: z.ZodArray<z.ZodObject<{
|
|
375
|
+
path: z.ZodString;
|
|
376
|
+
slug: z.ZodNullable<z.ZodString>;
|
|
377
|
+
code: z.ZodString;
|
|
378
|
+
message: z.ZodString;
|
|
379
|
+
severity: z.ZodEnum<{
|
|
380
|
+
error: "error";
|
|
381
|
+
warning: "warning";
|
|
382
|
+
}>;
|
|
383
|
+
}, z.core.$strip>>;
|
|
384
|
+
}, z.core.$strip>;
|
|
385
|
+
export type ConfigDraftResponse = z.infer<typeof configDraftResponse>;
|
|
386
|
+
/**
|
|
387
|
+
* A write carries the **text only**, and that is the point.
|
|
388
|
+
*
|
|
389
|
+
* If it carried both the text and the parsed document, the two could
|
|
390
|
+
* disagree. Sending only the source makes that unrepresentable on the wire:
|
|
391
|
+
* the server parses it, and there is exactly one account of what the
|
|
392
|
+
* configuration says.
|
|
393
|
+
*
|
|
394
|
+
* It also settles who owns parsing, and **FL-005 D2 moved that line**. The
|
|
395
|
+
* sentence here used to read that the console refuses unparsable YAML before it
|
|
396
|
+
* sends, so a syntax error never reaches the server. That is no longer the
|
|
397
|
+
* rule: the **server** refuses text that is not valid YAML, with the line and
|
|
398
|
+
* column, and stores everything else — including valid YAML that is not a
|
|
399
|
+
* fleetless document, which comes back with `doc: null` and its issues. The
|
|
400
|
+
* console checks as you type so the answer is immediate; the server checks
|
|
401
|
+
* because it is the one that decides. Two checks of one question, and the
|
|
402
|
+
* server's is the one that binds.
|
|
403
|
+
*
|
|
404
|
+
* The pair that used to be called a defect — a stored source that does not
|
|
405
|
+
* parse to its stored document — is now a **represented state**: no document at
|
|
406
|
+
* all. See `configDraftResponse` above.
|
|
407
|
+
*/
|
|
408
|
+
export declare const putConfigDraftRequest: z.ZodObject<{
|
|
409
|
+
source: z.ZodString;
|
|
410
|
+
}, z.core.$strip>;
|
|
411
|
+
export type PutConfigDraftRequest = z.infer<typeof putConfigDraftRequest>;
|
|
412
|
+
/** Publishing freezes the draft into the next immutable version. */
|
|
413
|
+
export declare const publishConfigResponse: z.ZodObject<{
|
|
414
|
+
version: z.ZodNumber;
|
|
415
|
+
published_at: z.ZodISODateTime;
|
|
416
|
+
}, z.core.$strip>;
|
|
417
|
+
export type PublishConfigResponse = z.infer<typeof publishConfigResponse>;
|
|
418
|
+
export declare const configVersionsResponse: z.ZodObject<{
|
|
419
|
+
versions: z.ZodArray<z.ZodObject<{
|
|
420
|
+
version: z.ZodNumber;
|
|
421
|
+
published_at: z.ZodISODateTime;
|
|
422
|
+
}, z.core.$strip>>;
|
|
423
|
+
}, z.core.$strip>;
|
|
424
|
+
export type ConfigVersionsResponse = z.infer<typeof configVersionsResponse>;
|
|
425
|
+
/**
|
|
426
|
+
* One published version, with the text it was published from.
|
|
427
|
+
*
|
|
428
|
+
* The text is what makes a version diff readable and a restore honest: a
|
|
429
|
+
* restore that returned only the document would hand back a configuration
|
|
430
|
+
* stripped of every comment the author wrote, which is the loss this format
|
|
431
|
+
* exists to prevent.
|
|
432
|
+
*/
|
|
433
|
+
export declare const configVersionResponse: z.ZodObject<{
|
|
434
|
+
version: z.ZodNumber;
|
|
435
|
+
published_at: z.ZodISODateTime;
|
|
436
|
+
doc: z.ZodObject<{
|
|
437
|
+
fleetless: z.ZodLiteral<1>;
|
|
438
|
+
messages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
439
|
+
datapoints: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
440
|
+
topic: z.ZodString;
|
|
441
|
+
type: z.ZodString;
|
|
442
|
+
field: z.ZodOptional<z.ZodString>;
|
|
443
|
+
rate_throttle_hz: z.ZodOptional<z.ZodNumber>;
|
|
444
|
+
description: z.ZodOptional<z.ZodString>;
|
|
445
|
+
numeric: z.ZodOptional<z.ZodObject<{
|
|
446
|
+
scale: z.ZodOptional<z.ZodNumber>;
|
|
447
|
+
offset: z.ZodOptional<z.ZodNumber>;
|
|
448
|
+
unit: z.ZodOptional<z.ZodString>;
|
|
449
|
+
decimals: z.ZodOptional<z.ZodNumber>;
|
|
450
|
+
}, z.core.$strict>>;
|
|
451
|
+
retention: z.ZodOptional<z.ZodObject<{
|
|
452
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
453
|
+
interval_seconds: z.ZodOptional<z.ZodNumber>;
|
|
454
|
+
max_buffer_values: z.ZodOptional<z.ZodNumber>;
|
|
455
|
+
}, z.core.$strict>>;
|
|
456
|
+
chart: z.ZodOptional<z.ZodObject<{
|
|
457
|
+
y_min: z.ZodOptional<z.ZodNumber>;
|
|
458
|
+
y_max: z.ZodOptional<z.ZodNumber>;
|
|
459
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
460
|
+
line: "line";
|
|
461
|
+
step: "step";
|
|
462
|
+
}>>;
|
|
463
|
+
default_window_minutes: z.ZodOptional<z.ZodNumber>;
|
|
464
|
+
}, z.core.$strict>>;
|
|
465
|
+
alerts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
466
|
+
condition: z.ZodObject<{
|
|
467
|
+
fire_at: z.ZodUnion<readonly [z.ZodNumber, z.ZodString, z.ZodBoolean]>;
|
|
468
|
+
resolve_at: z.ZodOptional<z.ZodNumber>;
|
|
469
|
+
}, z.core.$strict>;
|
|
470
|
+
severity: z.ZodOptional<z.ZodEnum<{
|
|
471
|
+
error: "error";
|
|
472
|
+
warning: "warning";
|
|
473
|
+
}>>;
|
|
474
|
+
name: z.ZodOptional<z.ZodString>;
|
|
475
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
476
|
+
}, z.core.$strict>>>;
|
|
477
|
+
}, z.core.$strict>>>;
|
|
478
|
+
actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
479
|
+
ros_name: z.ZodString;
|
|
480
|
+
type: z.ZodString;
|
|
481
|
+
message: z.ZodOptional<z.ZodUnknown>;
|
|
482
|
+
parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
483
|
+
type: z.ZodEnum<{
|
|
484
|
+
string: "string";
|
|
485
|
+
bool: "bool";
|
|
486
|
+
byte: "byte";
|
|
487
|
+
char: "char";
|
|
488
|
+
int8: "int8";
|
|
489
|
+
uint8: "uint8";
|
|
490
|
+
int16: "int16";
|
|
491
|
+
uint16: "uint16";
|
|
492
|
+
int32: "int32";
|
|
493
|
+
uint32: "uint32";
|
|
494
|
+
int64: "int64";
|
|
495
|
+
uint64: "uint64";
|
|
496
|
+
float32: "float32";
|
|
497
|
+
float64: "float64";
|
|
498
|
+
wstring: "wstring";
|
|
499
|
+
}>;
|
|
500
|
+
default: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString, z.ZodBoolean]>>;
|
|
501
|
+
min_value: z.ZodOptional<z.ZodNumber>;
|
|
502
|
+
max_value: z.ZodOptional<z.ZodNumber>;
|
|
503
|
+
enum: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
504
|
+
regex: z.ZodOptional<z.ZodString>;
|
|
505
|
+
description: z.ZodOptional<z.ZodString>;
|
|
506
|
+
}, z.core.$strict>>>;
|
|
507
|
+
description: z.ZodOptional<z.ZodString>;
|
|
508
|
+
}, z.core.$strict>>>;
|
|
509
|
+
services: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
510
|
+
ros_name: z.ZodString;
|
|
511
|
+
type: z.ZodString;
|
|
512
|
+
message: z.ZodOptional<z.ZodUnknown>;
|
|
513
|
+
parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
514
|
+
type: z.ZodEnum<{
|
|
515
|
+
string: "string";
|
|
516
|
+
bool: "bool";
|
|
517
|
+
byte: "byte";
|
|
518
|
+
char: "char";
|
|
519
|
+
int8: "int8";
|
|
520
|
+
uint8: "uint8";
|
|
521
|
+
int16: "int16";
|
|
522
|
+
uint16: "uint16";
|
|
523
|
+
int32: "int32";
|
|
524
|
+
uint32: "uint32";
|
|
525
|
+
int64: "int64";
|
|
526
|
+
uint64: "uint64";
|
|
527
|
+
float32: "float32";
|
|
528
|
+
float64: "float64";
|
|
529
|
+
wstring: "wstring";
|
|
530
|
+
}>;
|
|
531
|
+
default: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString, z.ZodBoolean]>>;
|
|
532
|
+
min_value: z.ZodOptional<z.ZodNumber>;
|
|
533
|
+
max_value: z.ZodOptional<z.ZodNumber>;
|
|
534
|
+
enum: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
535
|
+
regex: z.ZodOptional<z.ZodString>;
|
|
536
|
+
description: z.ZodOptional<z.ZodString>;
|
|
537
|
+
}, z.core.$strict>>>;
|
|
538
|
+
description: z.ZodOptional<z.ZodString>;
|
|
539
|
+
}, z.core.$strict>>>;
|
|
540
|
+
publishers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
541
|
+
topic: z.ZodString;
|
|
542
|
+
type: z.ZodString;
|
|
543
|
+
message: z.ZodUnknown;
|
|
544
|
+
parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
545
|
+
type: z.ZodEnum<{
|
|
546
|
+
string: "string";
|
|
547
|
+
bool: "bool";
|
|
548
|
+
byte: "byte";
|
|
549
|
+
char: "char";
|
|
550
|
+
int8: "int8";
|
|
551
|
+
uint8: "uint8";
|
|
552
|
+
int16: "int16";
|
|
553
|
+
uint16: "uint16";
|
|
554
|
+
int32: "int32";
|
|
555
|
+
uint32: "uint32";
|
|
556
|
+
int64: "int64";
|
|
557
|
+
uint64: "uint64";
|
|
558
|
+
float32: "float32";
|
|
559
|
+
float64: "float64";
|
|
560
|
+
wstring: "wstring";
|
|
561
|
+
}>;
|
|
562
|
+
default: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString, z.ZodBoolean]>>;
|
|
563
|
+
min_value: z.ZodOptional<z.ZodNumber>;
|
|
564
|
+
max_value: z.ZodOptional<z.ZodNumber>;
|
|
565
|
+
enum: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
566
|
+
regex: z.ZodOptional<z.ZodString>;
|
|
567
|
+
description: z.ZodOptional<z.ZodString>;
|
|
568
|
+
}, z.core.$strict>>>;
|
|
569
|
+
failsafe: z.ZodObject<{
|
|
570
|
+
timeout_ms: z.ZodNumber;
|
|
571
|
+
message: z.ZodUnknown;
|
|
572
|
+
}, z.core.$strict>;
|
|
573
|
+
quiet_timeout_ms: z.ZodNumber;
|
|
574
|
+
description: z.ZodOptional<z.ZodString>;
|
|
575
|
+
}, z.core.$strict>>>;
|
|
576
|
+
cameras: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
577
|
+
source: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
578
|
+
kind: z.ZodLiteral<"ros">;
|
|
579
|
+
topic: z.ZodString;
|
|
580
|
+
type: z.ZodString;
|
|
581
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
582
|
+
kind: z.ZodLiteral<"rtsp">;
|
|
583
|
+
url: z.ZodString;
|
|
584
|
+
transport: z.ZodOptional<z.ZodEnum<{
|
|
585
|
+
tcp: "tcp";
|
|
586
|
+
udp: "udp";
|
|
587
|
+
}>>;
|
|
588
|
+
credentials: z.ZodOptional<z.ZodObject<{
|
|
589
|
+
username: z.ZodOptional<z.ZodString>;
|
|
590
|
+
password: z.ZodOptional<z.ZodString>;
|
|
591
|
+
}, z.core.$strict>>;
|
|
592
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
593
|
+
kind: z.ZodLiteral<"mjpeg">;
|
|
594
|
+
url: z.ZodString;
|
|
595
|
+
credentials: z.ZodOptional<z.ZodObject<{
|
|
596
|
+
username: z.ZodOptional<z.ZodString>;
|
|
597
|
+
password: z.ZodOptional<z.ZodString>;
|
|
598
|
+
}, z.core.$strict>>;
|
|
599
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
600
|
+
kind: z.ZodLiteral<"v4l2">;
|
|
601
|
+
device: z.ZodString;
|
|
602
|
+
}, z.core.$strict>], "kind">;
|
|
603
|
+
width: z.ZodNumber;
|
|
604
|
+
height: z.ZodNumber;
|
|
605
|
+
fps: z.ZodNumber;
|
|
606
|
+
bitrate_kbps: z.ZodNumber;
|
|
607
|
+
snapshot_interval_seconds: z.ZodNumber;
|
|
608
|
+
description: z.ZodOptional<z.ZodString>;
|
|
609
|
+
}, z.core.$strict>>>;
|
|
610
|
+
}, z.core.$strict>;
|
|
611
|
+
source: z.ZodString;
|
|
612
|
+
}, z.core.$strip>;
|
|
613
|
+
export type ConfigVersionResponse = z.infer<typeof configVersionResponse>;
|
|
614
|
+
/**
|
|
615
|
+
* The cached ROS graph. It survives the bridge going offline on purpose —
|
|
616
|
+
* a developer keeps configuring while the robot is off; `stale` says the
|
|
617
|
+
* bridge is not connected right now, `fetched_at` how old the picture is.
|
|
618
|
+
*/
|
|
619
|
+
export declare const introspectionResponse: z.ZodObject<{
|
|
620
|
+
graph: z.ZodObject<{
|
|
621
|
+
topics: z.ZodArray<z.ZodObject<{
|
|
622
|
+
name: z.ZodString;
|
|
623
|
+
types: z.ZodArray<z.ZodString>;
|
|
624
|
+
}, z.core.$strip>>;
|
|
625
|
+
services: z.ZodArray<z.ZodObject<{
|
|
626
|
+
name: z.ZodString;
|
|
627
|
+
types: z.ZodArray<z.ZodString>;
|
|
628
|
+
}, z.core.$strip>>;
|
|
629
|
+
actions: z.ZodArray<z.ZodObject<{
|
|
630
|
+
name: z.ZodString;
|
|
631
|
+
types: z.ZodArray<z.ZodString>;
|
|
632
|
+
}, z.core.$strip>>;
|
|
633
|
+
captured_at_ms: z.ZodNumber;
|
|
634
|
+
}, z.core.$strip>;
|
|
635
|
+
fetched_at: z.ZodISODateTime;
|
|
636
|
+
stale: z.ZodBoolean;
|
|
637
|
+
}, z.core.$strip>;
|
|
638
|
+
export type IntrospectionResponse = z.infer<typeof introspectionResponse>;
|
|
639
|
+
export declare const typesResponse: z.ZodObject<{
|
|
640
|
+
types: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
641
|
+
name: z.ZodString;
|
|
642
|
+
kind: z.ZodLiteral<"msg">;
|
|
643
|
+
fields: z.ZodArray<z.ZodType<import("./introspection.js").TypeField, unknown, z.core.$ZodTypeInternals<import("./introspection.js").TypeField, unknown>>>;
|
|
644
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
645
|
+
name: z.ZodString;
|
|
646
|
+
kind: z.ZodLiteral<"srv">;
|
|
647
|
+
request: z.ZodArray<z.ZodType<import("./introspection.js").TypeField, unknown, z.core.$ZodTypeInternals<import("./introspection.js").TypeField, unknown>>>;
|
|
648
|
+
response: z.ZodArray<z.ZodType<import("./introspection.js").TypeField, unknown, z.core.$ZodTypeInternals<import("./introspection.js").TypeField, unknown>>>;
|
|
649
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
650
|
+
name: z.ZodString;
|
|
651
|
+
kind: z.ZodLiteral<"action">;
|
|
652
|
+
goal: z.ZodArray<z.ZodType<import("./introspection.js").TypeField, unknown, z.core.$ZodTypeInternals<import("./introspection.js").TypeField, unknown>>>;
|
|
653
|
+
result: z.ZodArray<z.ZodType<import("./introspection.js").TypeField, unknown, z.core.$ZodTypeInternals<import("./introspection.js").TypeField, unknown>>>;
|
|
654
|
+
feedback: z.ZodArray<z.ZodType<import("./introspection.js").TypeField, unknown, z.core.$ZodTypeInternals<import("./introspection.js").TypeField, unknown>>>;
|
|
655
|
+
}, z.core.$strip>], "kind">>;
|
|
656
|
+
}, z.core.$strip>;
|
|
657
|
+
export type TypesResponse = z.infer<typeof typesResponse>;
|
|
658
|
+
/** Fetch (and store) type definitions for this robot from its bridge. */
|
|
659
|
+
export declare const fetchTypesRequest: z.ZodObject<{
|
|
660
|
+
type_names: z.ZodArray<z.ZodString>;
|
|
661
|
+
}, z.core.$strip>;
|
|
662
|
+
export type FetchTypesRequest = z.infer<typeof fetchTypesRequest>;
|
|
663
|
+
export declare const fetchTypesResponse: z.ZodObject<{
|
|
664
|
+
types: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
665
|
+
name: z.ZodString;
|
|
666
|
+
kind: z.ZodLiteral<"msg">;
|
|
667
|
+
fields: z.ZodArray<z.ZodType<import("./introspection.js").TypeField, unknown, z.core.$ZodTypeInternals<import("./introspection.js").TypeField, unknown>>>;
|
|
668
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
669
|
+
name: z.ZodString;
|
|
670
|
+
kind: z.ZodLiteral<"srv">;
|
|
671
|
+
request: z.ZodArray<z.ZodType<import("./introspection.js").TypeField, unknown, z.core.$ZodTypeInternals<import("./introspection.js").TypeField, unknown>>>;
|
|
672
|
+
response: z.ZodArray<z.ZodType<import("./introspection.js").TypeField, unknown, z.core.$ZodTypeInternals<import("./introspection.js").TypeField, unknown>>>;
|
|
673
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
674
|
+
name: z.ZodString;
|
|
675
|
+
kind: z.ZodLiteral<"action">;
|
|
676
|
+
goal: z.ZodArray<z.ZodType<import("./introspection.js").TypeField, unknown, z.core.$ZodTypeInternals<import("./introspection.js").TypeField, unknown>>>;
|
|
677
|
+
result: z.ZodArray<z.ZodType<import("./introspection.js").TypeField, unknown, z.core.$ZodTypeInternals<import("./introspection.js").TypeField, unknown>>>;
|
|
678
|
+
feedback: z.ZodArray<z.ZodType<import("./introspection.js").TypeField, unknown, z.core.$ZodTypeInternals<import("./introspection.js").TypeField, unknown>>>;
|
|
679
|
+
}, z.core.$strip>], "kind">>;
|
|
680
|
+
unresolved: z.ZodArray<z.ZodString>;
|
|
681
|
+
}, z.core.$strip>;
|
|
682
|
+
export type FetchTypesResponse = z.infer<typeof fetchTypesResponse>;
|
|
683
|
+
/**
|
|
684
|
+
* What a client can read on this robot: the built-ins plus everything the
|
|
685
|
+
* published configuration exposes. This is the seed of the generated
|
|
686
|
+
* per-robot API (§11.2).
|
|
687
|
+
*
|
|
688
|
+
* **The OpenAPI rendering exists since the route manifest (`routes.ts`):
|
|
689
|
+
* `artifacts/openapi.json`, derived from the manifest and these schemas by
|
|
690
|
+
* `scripts/export-schemas.ts`.**
|
|
691
|
+
*/
|
|
692
|
+
export declare const datapointDescriptor: z.ZodObject<{
|
|
693
|
+
slug: z.ZodString;
|
|
694
|
+
builtin: z.ZodBoolean;
|
|
695
|
+
unit: z.ZodNullable<z.ZodString>;
|
|
696
|
+
rate_throttle_hz: z.ZodNullable<z.ZodNumber>;
|
|
697
|
+
}, z.core.$strip>;
|
|
698
|
+
export type DatapointDescriptor = z.infer<typeof datapointDescriptor>;
|
|
699
|
+
export declare const datapointListResponse: z.ZodObject<{
|
|
700
|
+
datapoints: z.ZodArray<z.ZodObject<{
|
|
701
|
+
slug: z.ZodString;
|
|
702
|
+
builtin: z.ZodBoolean;
|
|
703
|
+
unit: z.ZodNullable<z.ZodString>;
|
|
704
|
+
rate_throttle_hz: z.ZodNullable<z.ZodNumber>;
|
|
705
|
+
}, z.core.$strip>>;
|
|
706
|
+
}, z.core.$strip>;
|
|
707
|
+
export type DatapointListResponse = z.infer<typeof datapointListResponse>;
|
|
708
|
+
/**
|
|
709
|
+
* The built-in `robot_details` datapoint (spec §4.3): static properties the
|
|
710
|
+
* developer maintains. Bounded so one robot cannot become a document store.
|
|
711
|
+
*/
|
|
712
|
+
export declare const robotDetailsDoc: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnknown>, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
713
|
+
export type RobotDetailsDoc = z.infer<typeof robotDetailsDoc>;
|
|
714
|
+
/** What `PUT /api/robots/:id/details` answers: the stored document, which is the one that was sent. */
|
|
715
|
+
export declare const putRobotDetailsResponse: z.ZodObject<{
|
|
716
|
+
details: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnknown>, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
717
|
+
}, z.core.$strip>;
|
|
718
|
+
export type PutRobotDetailsResponse = z.infer<typeof putRobotDetailsResponse>;
|
|
719
|
+
export declare const putRobotDetailsRequest: z.ZodObject<{
|
|
720
|
+
details: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodArray<z.ZodUnknown>, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
721
|
+
}, z.core.$strip>;
|
|
722
|
+
export type PutRobotDetailsRequest = z.infer<typeof putRobotDetailsRequest>;
|
|
723
|
+
/**
|
|
724
|
+
* Invoke an action or call a service; parameters by field path (§4.4).
|
|
725
|
+
*
|
|
726
|
+
* Flat, keyed by `parameterSpec.name` — see `cloudInvoke.params` for why the
|
|
727
|
+
* flat form is the one that makes a refusal legible.
|
|
728
|
+
*/
|
|
729
|
+
export declare const invokeRequest: z.ZodObject<{
|
|
730
|
+
params: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
731
|
+
patience_ms: z.ZodOptional<z.ZodNumber>;
|
|
732
|
+
}, z.core.$strip>;
|
|
733
|
+
export type InvokeRequest = z.infer<typeof invokeRequest>;
|
|
734
|
+
/**
|
|
735
|
+
* The answer to an invoke. The job id is informative (§11.3): state is
|
|
736
|
+
* observed by slug afterwards, over polling or a subscription.
|
|
737
|
+
*/
|
|
738
|
+
/**
|
|
739
|
+
* The body of a cancel (W6b). **Every field optional, and the body itself may
|
|
740
|
+
* be absent** — `POST .../cancel` was bodyless before this wave and every
|
|
741
|
+
* existing caller still sends nothing.
|
|
742
|
+
*
|
|
743
|
+
* That is not politeness, it is the W5 defect: a bodyless `POST` carrying
|
|
744
|
+
* `content-type: application/json` was rejected outright, which made
|
|
745
|
+
* `cameras.live()` unreachable through the SDK and took `cancel`, publish,
|
|
746
|
+
* restore, key rotation and member removal with it — unnoticed since W4. A
|
|
747
|
+
* schema that demands a body would reintroduce it on the one verb that stops
|
|
748
|
+
* a machine.
|
|
749
|
+
*
|
|
750
|
+
* **`.strict()`, and that is the whole point of the shape.** A plain object
|
|
751
|
+
* strips unknown keys, so a caller who *means* to name a job and misspells the
|
|
752
|
+
* field — `jobId` for `job_id` — has their id silently removed and gets the
|
|
753
|
+
* **slug-wide** cancel instead: the most destructive reading of a request they
|
|
754
|
+
* did not make. Measured in W6b's review: `{"jobId": "<some other job>"}`
|
|
755
|
+
* answered `200` and stopped the job that was actually running, which nobody
|
|
756
|
+
* had named. The `?force=true` precedent this route's design borrowed from
|
|
757
|
+
* fails *safe* on a typo — a misspelled `force` simply does not force.
|
|
758
|
+
* Stripping here fails unsafe, so unknown keys are refused instead.
|
|
759
|
+
*
|
|
760
|
+
* `job_id` absent and `job_id: null` mean the **same** thing here, and that is
|
|
761
|
+
* deliberate: over REST an absent body is how every caller written before this
|
|
762
|
+
* wave says "cancel whatever is running". On the socket, `clientCancel.job_id`
|
|
763
|
+
* is required-and-nullable instead, because a frame is assembled fresh by a
|
|
764
|
+
* client that has already been updated — there, `null` is a decision and an
|
|
765
|
+
* omission is a bug.
|
|
766
|
+
*/
|
|
767
|
+
export declare const cancelRequest: z.ZodObject<{
|
|
768
|
+
job_id: z.ZodOptional<z.ZodNullable<z.ZodUUID>>;
|
|
769
|
+
}, z.core.$strict>;
|
|
770
|
+
export type CancelRequest = z.infer<typeof cancelRequest>;
|
|
771
|
+
/**
|
|
772
|
+
* The query of a live release (W6b): `DELETE .../live?session_id=<uuid>`.
|
|
773
|
+
*
|
|
774
|
+
* A query parameter rather than a body, following `?force=true` on robot
|
|
775
|
+
* deletion — the precedent this repo already set for "a DELETE that needs one
|
|
776
|
+
* more fact". A body on a DELETE is carried inconsistently by proxies and by
|
|
777
|
+
* `fetch` itself, and this call runs from a browser tab that is often closing.
|
|
778
|
+
*
|
|
779
|
+
* **`.strict()`, for the reason `cancelRequest` is** — `?sessionid=` instead of
|
|
780
|
+
* `?session_id=` was measured releasing **both** of an identity's holds and
|
|
781
|
+
* stranding the other tab, which is precisely the defect this field was added
|
|
782
|
+
* to remove. A refused typo costs a round trip; a stripped one stops a robot
|
|
783
|
+
* somebody else is watching.
|
|
784
|
+
*
|
|
785
|
+
* Absent means today's meaning: release **all** of this identity's holds on
|
|
786
|
+
* this camera. A client that has lost its id, or is going away entirely, still
|
|
787
|
+
* needs a way to let go — it is the blunt form, and it is the one that strands
|
|
788
|
+
* the identity's other tabs.
|
|
789
|
+
*/
|
|
790
|
+
export declare const releaseLiveQuery: z.ZodObject<{
|
|
791
|
+
session_id: z.ZodOptional<z.ZodUUID>;
|
|
792
|
+
}, z.core.$strict>;
|
|
793
|
+
export type ReleaseLiveQuery = z.infer<typeof releaseLiveQuery>;
|
|
794
|
+
export declare const invokeResponse: z.ZodObject<{
|
|
795
|
+
job: z.ZodObject<{
|
|
796
|
+
id: z.ZodUUID;
|
|
797
|
+
robot_id: z.ZodUUID;
|
|
798
|
+
slug: z.ZodString;
|
|
799
|
+
state: z.ZodEnum<{
|
|
800
|
+
failed: "failed";
|
|
801
|
+
running: "running";
|
|
802
|
+
succeeded: "succeeded";
|
|
803
|
+
cancelled: "cancelled";
|
|
804
|
+
lost: "lost";
|
|
805
|
+
}>;
|
|
806
|
+
started_at: z.ZodISODateTime;
|
|
807
|
+
updated_at: z.ZodISODateTime;
|
|
808
|
+
seq: z.ZodNumber;
|
|
809
|
+
result: z.ZodNullable<z.ZodUnknown>;
|
|
810
|
+
error: z.ZodNullable<z.ZodObject<{
|
|
811
|
+
code: z.ZodString;
|
|
812
|
+
message: z.ZodString;
|
|
813
|
+
details: z.ZodOptional<z.ZodUnknown>;
|
|
814
|
+
}, z.core.$strip>>;
|
|
815
|
+
}, z.core.$strip>;
|
|
816
|
+
kind: z.ZodEnum<{
|
|
817
|
+
action: "action";
|
|
818
|
+
service: "service";
|
|
819
|
+
}>;
|
|
820
|
+
}, z.core.$strip>;
|
|
821
|
+
export type InvokeResponse = z.infer<typeof invokeResponse>;
|
|
822
|
+
/** A service call answers with its result directly — no job to observe. */
|
|
823
|
+
export declare const serviceCallResponse: z.ZodObject<{
|
|
824
|
+
result: z.ZodUnknown;
|
|
825
|
+
}, z.core.$strip>;
|
|
826
|
+
export type ServiceCallResponse = z.infer<typeof serviceCallResponse>;
|
|
827
|
+
/**
|
|
828
|
+
* **What `POST /api/robots/:id/jobs/:slug` answers, which is one of two
|
|
829
|
+
* shapes.**
|
|
830
|
+
*
|
|
831
|
+
* One route serves both kinds, because a path segment naming the kind would
|
|
832
|
+
* demand a fact a role grant does not carry. **The slug's kind decides, and
|
|
833
|
+
* nothing in the request does**: an *action* answers `202` with an
|
|
834
|
+
* `invokeResponse` the moment the job exists, a *service* answers `200` with
|
|
835
|
+
* a `serviceCallResponse` once the result is in. They differ only in what the
|
|
836
|
+
* cloud waits for before it answers.
|
|
837
|
+
*
|
|
838
|
+
* The two are told apart without inspecting the status code: `invokeResponse`
|
|
839
|
+
* carries `kind` and `job`, `serviceCallResponse` carries `result` alone.
|
|
840
|
+
*
|
|
841
|
+
* **This union exists so the route can name a response at all.** The entry
|
|
842
|
+
* carried `response: null` while the handler demonstrably answers something,
|
|
843
|
+
* which reads in the generated reference as *this route returns nothing* —
|
|
844
|
+
* the documented absence this project keeps paying for. A `null` there should
|
|
845
|
+
* mean `204`, and on this route it did not.
|
|
846
|
+
*/
|
|
847
|
+
export declare const invokeOrServiceResponse: z.ZodUnion<readonly [z.ZodObject<{
|
|
848
|
+
job: z.ZodObject<{
|
|
849
|
+
id: z.ZodUUID;
|
|
850
|
+
robot_id: z.ZodUUID;
|
|
851
|
+
slug: z.ZodString;
|
|
852
|
+
state: z.ZodEnum<{
|
|
853
|
+
failed: "failed";
|
|
854
|
+
running: "running";
|
|
855
|
+
succeeded: "succeeded";
|
|
856
|
+
cancelled: "cancelled";
|
|
857
|
+
lost: "lost";
|
|
858
|
+
}>;
|
|
859
|
+
started_at: z.ZodISODateTime;
|
|
860
|
+
updated_at: z.ZodISODateTime;
|
|
861
|
+
seq: z.ZodNumber;
|
|
862
|
+
result: z.ZodNullable<z.ZodUnknown>;
|
|
863
|
+
error: z.ZodNullable<z.ZodObject<{
|
|
864
|
+
code: z.ZodString;
|
|
865
|
+
message: z.ZodString;
|
|
866
|
+
details: z.ZodOptional<z.ZodUnknown>;
|
|
867
|
+
}, z.core.$strip>>;
|
|
868
|
+
}, z.core.$strip>;
|
|
869
|
+
kind: z.ZodEnum<{
|
|
870
|
+
action: "action";
|
|
871
|
+
service: "service";
|
|
872
|
+
}>;
|
|
873
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
874
|
+
result: z.ZodUnknown;
|
|
875
|
+
}, z.core.$strip>]>;
|
|
876
|
+
export type InvokeOrServiceResponse = z.infer<typeof invokeOrServiceResponse>;
|
|
877
|
+
export declare const publishRequest: z.ZodObject<{
|
|
878
|
+
message: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
879
|
+
}, z.core.$strip>;
|
|
880
|
+
export type PublishRequest = z.infer<typeof publishRequest>;
|
|
881
|
+
/**
|
|
882
|
+
* The **most recent** job on a slug — running or already finished — or null
|
|
883
|
+
* only when nothing has ever run there.
|
|
884
|
+
*
|
|
885
|
+
* It said "the job currently running" until W4's review, and that quietly
|
|
886
|
+
* made §11.3's first sentence false. The spec offers two equal ways to
|
|
887
|
+
* observe a slug — *"Polling (REST) oder Subscription (Realtime)"* — but a
|
|
888
|
+
* route that forgets a job the moment it settles lets a poller see only
|
|
889
|
+
* `running`, then `null`. Succeeded, failed, cancelled, `lost` and
|
|
890
|
+
* never-invoked all become the same answer, so §6.1's promise that a lost
|
|
891
|
+
* job is *said out loud* held for subscribers and silently did not hold for
|
|
892
|
+
* anyone polling. It is also the recovery `command_outcome_unknown` points
|
|
893
|
+
* a caller to.
|
|
894
|
+
*
|
|
895
|
+
* Read `job.state` to tell a live job from a finished one; that is what the
|
|
896
|
+
* field is for.
|
|
897
|
+
*/
|
|
898
|
+
export declare const jobResponse: z.ZodObject<{
|
|
899
|
+
job: z.ZodNullable<z.ZodObject<{
|
|
900
|
+
id: z.ZodUUID;
|
|
901
|
+
robot_id: z.ZodUUID;
|
|
902
|
+
slug: z.ZodString;
|
|
903
|
+
state: z.ZodEnum<{
|
|
904
|
+
failed: "failed";
|
|
905
|
+
running: "running";
|
|
906
|
+
succeeded: "succeeded";
|
|
907
|
+
cancelled: "cancelled";
|
|
908
|
+
lost: "lost";
|
|
909
|
+
}>;
|
|
910
|
+
started_at: z.ZodISODateTime;
|
|
911
|
+
updated_at: z.ZodISODateTime;
|
|
912
|
+
seq: z.ZodNumber;
|
|
913
|
+
result: z.ZodNullable<z.ZodUnknown>;
|
|
914
|
+
error: z.ZodNullable<z.ZodObject<{
|
|
915
|
+
code: z.ZodString;
|
|
916
|
+
message: z.ZodString;
|
|
917
|
+
details: z.ZodOptional<z.ZodUnknown>;
|
|
918
|
+
}, z.core.$strip>>;
|
|
919
|
+
}, z.core.$strip>>;
|
|
920
|
+
}, z.core.$strip>;
|
|
921
|
+
export type JobResponse = z.infer<typeof jobResponse>;
|
|
922
|
+
/**
|
|
923
|
+
* Every job the platform currently believes this robot has — `GET
|
|
924
|
+
* /api/robots/:id/jobs` (W6b).
|
|
925
|
+
*
|
|
926
|
+
* `jobResponse` answers "what is on this slug", which requires knowing the
|
|
927
|
+
* slug first. That was enough while a job could only exist on a slug the
|
|
928
|
+
* published configuration named. W6b breaks that assumption twice: a
|
|
929
|
+
* reconnecting bridge can name a job the cloud has **no row for** and the
|
|
930
|
+
* cloud adopts it, and a configuration change can leave a job on a slug the
|
|
931
|
+
* document no longer contains. Both are jobs nobody can ask about, because
|
|
932
|
+
* asking requires already knowing what to ask for.
|
|
933
|
+
*
|
|
934
|
+
* So this route exists to answer the question the per-slug route cannot: not
|
|
935
|
+
* "is something running here", but "what is this robot doing". A restarted
|
|
936
|
+
* cloud that has just reconciled a robot's `hello.active_jobs` has exactly
|
|
937
|
+
* this list and, until now, no way to say it out loud.
|
|
938
|
+
*
|
|
939
|
+
* The array is ordered newest first and is **never null**: a robot doing
|
|
940
|
+
* nothing answers `{ jobs: [] }`. "Nothing is running" and "we did not look"
|
|
941
|
+
* are different facts, and a nullable list would merge them — the same
|
|
942
|
+
* distinction `robotDeletionSummary` was made all-required for.
|
|
943
|
+
*
|
|
944
|
+
* **At most one entry per slug: the current job there, exactly what
|
|
945
|
+
* `jobResponse` would answer for that slug.** This is not a history endpoint
|
|
946
|
+
* and must not become one. The first implementation returned every job the
|
|
947
|
+
* registry still held — six rows and four complete Fibonacci results after a
|
|
948
|
+
* few minutes of gate traffic, and unbounded in both count and payload for a
|
|
949
|
+
* robot that has been working all day. The list would have grown until a
|
|
950
|
+
* console page carried a robot's entire past, and the one thing it exists to
|
|
951
|
+
* answer — *what is this robot doing* — would have been the first line of a
|
|
952
|
+
* scroll.
|
|
953
|
+
*
|
|
954
|
+
* A settled job stays visible as its slug's current entry until something
|
|
955
|
+
* else runs there, which is what makes a job that just failed still findable.
|
|
956
|
+
* Read `state` to tell a live one from a finished one, exactly as with
|
|
957
|
+
* `jobResponse`.
|
|
958
|
+
*/
|
|
959
|
+
/**
|
|
960
|
+
* What a `rate_limited` refusal tells the caller (W6c).
|
|
961
|
+
*
|
|
962
|
+
* One number, and it is the only one that matters: **when to come back.** A
|
|
963
|
+
* limit that says "too many" without saying "in 800 ms" produces a client that
|
|
964
|
+
* retries immediately, which is the behaviour the limit exists to stop — so
|
|
965
|
+
* omitting it would make the refusal part of the attack.
|
|
966
|
+
*
|
|
967
|
+
* Deliberately **not** carrying the limit, the window, or how many attempts
|
|
968
|
+
* remain: those describe the defence to whoever is probing it, and none of
|
|
969
|
+
* them changes what an honest caller does.
|
|
970
|
+
*/
|
|
971
|
+
export declare const rateLimitDetails: z.ZodObject<{
|
|
972
|
+
retry_after_ms: z.ZodNumber;
|
|
973
|
+
}, z.core.$strip>;
|
|
974
|
+
export type RateLimitDetails = z.infer<typeof rateLimitDetails>;
|
|
975
|
+
/**
|
|
976
|
+
* Every job this robot's registry currently holds, **ordered newest first by
|
|
977
|
+
* `started_at`, with `seq` as the tiebreaker** (W7, register rows 2j and 2l).
|
|
978
|
+
*
|
|
979
|
+
* The field is named because the previous version of this comment claimed an
|
|
980
|
+
* order without saying what produced it, and the answer turned out to matter
|
|
981
|
+
* twice over:
|
|
982
|
+
*
|
|
983
|
+
* 1. **`started_at` alone is not a total order.** Two jobs minted in the same
|
|
984
|
+
* millisecond sorted against each other arbitrarily — differently on each
|
|
985
|
+
* query — so a reader could see one twice and the other not at all. `seq`
|
|
986
|
+
* is monotonic in mint order and settles it. Note its scope, which is in
|
|
987
|
+
* `job.seq`'s own comment: per cloud process, per run, because job state
|
|
988
|
+
* lives in memory and the counter restarts with the registry it orders.
|
|
989
|
+
* 2. **For an adopted job, `started_at` is adoption time, not the real
|
|
990
|
+
* start.** The cloud learns of it at `hello`, having never minted it, and
|
|
991
|
+
* has no other honest value to put there. So this list is newest-*known*
|
|
992
|
+
* first, and a job the robot has been running for an hour can sit above one
|
|
993
|
+
* started a minute ago. Stated rather than smoothed over: the console's own
|
|
994
|
+
* "Known running since" wording exists for the same reason, and a contract
|
|
995
|
+
* that quietly implies otherwise would send somebody to debug the sort.
|
|
996
|
+
*/
|
|
997
|
+
export declare const robotJobsResponse: z.ZodObject<{
|
|
998
|
+
jobs: z.ZodArray<z.ZodObject<{
|
|
999
|
+
id: z.ZodUUID;
|
|
1000
|
+
robot_id: z.ZodUUID;
|
|
1001
|
+
slug: z.ZodString;
|
|
1002
|
+
state: z.ZodEnum<{
|
|
1003
|
+
failed: "failed";
|
|
1004
|
+
running: "running";
|
|
1005
|
+
succeeded: "succeeded";
|
|
1006
|
+
cancelled: "cancelled";
|
|
1007
|
+
lost: "lost";
|
|
1008
|
+
}>;
|
|
1009
|
+
started_at: z.ZodISODateTime;
|
|
1010
|
+
updated_at: z.ZodISODateTime;
|
|
1011
|
+
seq: z.ZodNumber;
|
|
1012
|
+
result: z.ZodNullable<z.ZodUnknown>;
|
|
1013
|
+
error: z.ZodNullable<z.ZodObject<{
|
|
1014
|
+
code: z.ZodString;
|
|
1015
|
+
message: z.ZodString;
|
|
1016
|
+
details: z.ZodOptional<z.ZodUnknown>;
|
|
1017
|
+
}, z.core.$strip>>;
|
|
1018
|
+
}, z.core.$strip>>;
|
|
1019
|
+
}, z.core.$strip>;
|
|
1020
|
+
export type RobotJobsResponse = z.infer<typeof robotJobsResponse>;
|
|
1021
|
+
/**
|
|
1022
|
+
* Every slug of a robot that a role can be granted, **with its kind**.
|
|
1023
|
+
*
|
|
1024
|
+
* The roles matrix was built in W3 against the datapoint list, which was the
|
|
1025
|
+
* only kind that existed. With four kinds it needs one list that names them,
|
|
1026
|
+
* or the matrix silently cannot grant an action.
|
|
1027
|
+
*/
|
|
1028
|
+
export declare const exposure: z.ZodObject<{
|
|
1029
|
+
slug: z.ZodString;
|
|
1030
|
+
kind: z.ZodEnum<{
|
|
1031
|
+
datapoint: "datapoint";
|
|
1032
|
+
action: "action";
|
|
1033
|
+
service: "service";
|
|
1034
|
+
publisher: "publisher";
|
|
1035
|
+
camera: "camera";
|
|
1036
|
+
}>;
|
|
1037
|
+
builtin: z.ZodBoolean;
|
|
1038
|
+
}, z.core.$strip>;
|
|
1039
|
+
export type Exposure = z.infer<typeof exposure>;
|
|
1040
|
+
export declare const exposureListResponse: z.ZodObject<{
|
|
1041
|
+
exposures: z.ZodArray<z.ZodObject<{
|
|
1042
|
+
slug: z.ZodString;
|
|
1043
|
+
kind: z.ZodEnum<{
|
|
1044
|
+
datapoint: "datapoint";
|
|
1045
|
+
action: "action";
|
|
1046
|
+
service: "service";
|
|
1047
|
+
publisher: "publisher";
|
|
1048
|
+
camera: "camera";
|
|
1049
|
+
}>;
|
|
1050
|
+
builtin: z.ZodBoolean;
|
|
1051
|
+
}, z.core.$strip>>;
|
|
1052
|
+
}, z.core.$strip>;
|
|
1053
|
+
export type ExposureListResponse = z.infer<typeof exposureListResponse>;
|
|
1054
|
+
/**
|
|
1055
|
+
* The response headers a binary snapshot carries, named here so the cloud and
|
|
1056
|
+
* every client agree without negotiating:
|
|
1057
|
+
*
|
|
1058
|
+
* - `Content-Type` — the image's mime, standard rather than invented.
|
|
1059
|
+
* - `X-Fleetless-Age-Ms` — how old the frame is, **computed by the cloud**.
|
|
1060
|
+
* - `X-Fleetless-Timestamp-Ms`— the bridge's capture time.
|
|
1061
|
+
* - `X-Fleetless-Width` / `X-Fleetless-Height`.
|
|
1062
|
+
*
|
|
1063
|
+
* A client must take `age_ms` from the header and **never** recompute it as
|
|
1064
|
+
* `Date.now() - timestamp_ms`: the cloud is the one clock that knows how long
|
|
1065
|
+
* it has actually been holding the frame, and recomputing reintroduces the
|
|
1066
|
+
* viewer's clock skew as a source of lying about freshness.
|
|
1067
|
+
*/
|
|
1068
|
+
export declare const SNAPSHOT_HEADERS: {
|
|
1069
|
+
readonly ageMs: "x-fleetless-age-ms";
|
|
1070
|
+
readonly timestampMs: "x-fleetless-timestamp-ms";
|
|
1071
|
+
readonly width: "x-fleetless-width";
|
|
1072
|
+
readonly height: "x-fleetless-height";
|
|
1073
|
+
};
|
|
1074
|
+
/**
|
|
1075
|
+
* The metadata an asset upload carries beside its raw body (W7).
|
|
1076
|
+
*
|
|
1077
|
+
* Here rather than as a convention documented on both sides, and the reason is
|
|
1078
|
+
* a scar. W5 shipped `x-fleetless-*` headers the CORS policy did not expose,
|
|
1079
|
+
* so `age_ms` was `null` in **every** browser while the SDK documented `null`
|
|
1080
|
+
* as "nothing captured yet" — a fresh frame reporting as no snapshot at all,
|
|
1081
|
+
* invisible to three test suites because none of them was a browser. And W6b
|
|
1082
|
+
* found the general form: three repos agreeing with each other about a payload
|
|
1083
|
+
* none of them exchanged, each right in its own tests.
|
|
1084
|
+
*
|
|
1085
|
+
* **A string shared by two repos and defined in both is a string that drifts.**
|
|
1086
|
+
* A zod schema cannot validate a header, which is an argument for writing the
|
|
1087
|
+
* names down once, not an argument for writing them down twice.
|
|
1088
|
+
*
|
|
1089
|
+
* `name` is the `package://` URI verbatim for a mesh — the same string
|
|
1090
|
+
* `asset.name` stores, and the same one `urdfCompleteness.missing` reports, so
|
|
1091
|
+
* a failed upload and a missing mesh can be matched by eye.
|
|
1092
|
+
*/
|
|
1093
|
+
/**
|
|
1094
|
+
* **`name` travels percent-encoded, and that is a fix rather than a
|
|
1095
|
+
* convention** (W7a review, André's decision to fix rather than defer).
|
|
1096
|
+
*
|
|
1097
|
+
* HTTP header values are latin-1 (`http.client` in Python, and the same is
|
|
1098
|
+
* true on the other side). So a texture called `textures/日本語.png` raised a
|
|
1099
|
+
* `UnicodeEncodeError` **inside `urllib`** — a `ValueError`, caught by neither
|
|
1100
|
+
* `HTTPError` nor `URLError` — which propagated to the sync's broad handler
|
|
1101
|
+
* and marked **everything still remaining** as failed. One non-ASCII filename
|
|
1102
|
+
* cost a developer every mesh after it in that sync, with no cause on the
|
|
1103
|
+
* wire. R6 made it ordinary rather than exotic: `.dae` internal names come
|
|
1104
|
+
* from 3D-authoring tools, where non-ASCII is Tuesday.
|
|
1105
|
+
*
|
|
1106
|
+
* The encoding is not invented here. **`GET .../assets/missing?name=` already
|
|
1107
|
+
* carries this exact string percent-encoded**, because a query parameter is
|
|
1108
|
+
* percent-encoded by definition — same value, same wire, question already
|
|
1109
|
+
* answered.
|
|
1110
|
+
*
|
|
1111
|
+
* **It is a SECOND header, and that is the whole design rather than a
|
|
1112
|
+
* detail.** The first version overloaded `name` itself: the producer would
|
|
1113
|
+
* encode, the store would `decodeURIComponent`. That decodes identically for
|
|
1114
|
+
* every name without a `%`, so an **older bridge and a newer cloud agree by
|
|
1115
|
+
* luck** — right up until a name contains `%2f`, which the store would then
|
|
1116
|
+
* silently turn into a `/`. A wire change whose breakage is invisible in the
|
|
1117
|
+
* common case and silent in the uncommon one is the worst of both (Argus-W7a,
|
|
1118
|
+
* reading the contract rather than the code).
|
|
1119
|
+
*
|
|
1120
|
+
* So `name` keeps meaning exactly what it always meant, and `nameEncoded`
|
|
1121
|
+
* carries the percent-encoded UTF-8 form. **The store prefers `nameEncoded`
|
|
1122
|
+
* when present and uses `name` otherwise**, so:
|
|
1123
|
+
*
|
|
1124
|
+
* - an older bridge sends only `name` and behaves exactly as before;
|
|
1125
|
+
* - a newer bridge sends both, and a name it cannot express in latin-1 travels
|
|
1126
|
+
* intact for the first time;
|
|
1127
|
+
* - no value is ever ambiguous about which encoding it is in.
|
|
1128
|
+
*
|
|
1129
|
+
* A producer that can send `nameEncoded` should send both, so a store older
|
|
1130
|
+
* than this contract keeps working too. Agreement by construction, not by the
|
|
1131
|
+
* absence of a `%`.
|
|
1132
|
+
*/
|
|
1133
|
+
export declare const ASSET_UPLOAD_HEADERS: {
|
|
1134
|
+
readonly kind: "x-fleetless-asset-kind";
|
|
1135
|
+
readonly name: "x-fleetless-asset-name";
|
|
1136
|
+
readonly nameEncoded: "x-fleetless-asset-name-encoded";
|
|
1137
|
+
readonly syncId: "x-fleetless-sync-id";
|
|
1138
|
+
/**
|
|
1139
|
+
* **Die angekündigte Größe, und sie ist der Grund, warum `asset_too_large`
|
|
1140
|
+
* überhaupt entstehen kann (W9b, DEF-116).**
|
|
1141
|
+
*
|
|
1142
|
+
* Fastifys `bodyLimit` greift im Content-Type-Parser, also **vor** dem
|
|
1143
|
+
* Handler — eine zu große Datei bekam damit ein blankes `413 bad_request`
|
|
1144
|
+
* ohne `limit_bytes` und ohne `size_bytes`, und der strukturierte Fehlercode,
|
|
1145
|
+
* den `assetTooLargeDetails` beschreibt, hatte schlicht keinen erreichbaren
|
|
1146
|
+
* Erzeuger (Momus-W7, M1, an den echten Routenoptionen reproduziert).
|
|
1147
|
+
*
|
|
1148
|
+
* Mit einer angekündigten Größe im Kopf kann die Ablehnung dort entstehen,
|
|
1149
|
+
* wo sie etwas sagen kann: bevor ein Byte gepuffert ist, mit beiden Zahlen.
|
|
1150
|
+
* Und die Bridge erfährt ihre Grenze, ohne 194 MB zu lesen, um sie zu
|
|
1151
|
+
* entdecken — was am 2026-08-18 auf rx1 genau so ausging (DEF-148).
|
|
1152
|
+
*
|
|
1153
|
+
* Der Kopf ist eine **Ankündigung, kein Beweis**: Ein Absender kann lügen.
|
|
1154
|
+
* Der Deckel gilt weiterhin auch am Körper — dies ersetzt die Durchsetzung
|
|
1155
|
+
* nicht, es macht die Absage nur beantwortbar.
|
|
1156
|
+
*/
|
|
1157
|
+
readonly size: "x-fleetless-asset-size";
|
|
1158
|
+
};
|
|
1159
|
+
export declare const cameraDescriptor: z.ZodObject<{
|
|
1160
|
+
slug: z.ZodString;
|
|
1161
|
+
width: z.ZodNumber;
|
|
1162
|
+
height: z.ZodNumber;
|
|
1163
|
+
fps: z.ZodNumber;
|
|
1164
|
+
snapshot_interval_seconds: z.ZodNumber;
|
|
1165
|
+
}, z.core.$strip>;
|
|
1166
|
+
export type CameraDescriptor = z.infer<typeof cameraDescriptor>;
|
|
1167
|
+
export declare const cameraListResponse: z.ZodObject<{
|
|
1168
|
+
cameras: z.ZodArray<z.ZodObject<{
|
|
1169
|
+
slug: z.ZodString;
|
|
1170
|
+
width: z.ZodNumber;
|
|
1171
|
+
height: z.ZodNumber;
|
|
1172
|
+
fps: z.ZodNumber;
|
|
1173
|
+
snapshot_interval_seconds: z.ZodNumber;
|
|
1174
|
+
}, z.core.$strip>>;
|
|
1175
|
+
}, z.core.$strip>;
|
|
1176
|
+
export type CameraListResponse = z.infer<typeof cameraListResponse>;
|
|
1177
|
+
/**
|
|
1178
|
+
* What a viewer needs to join, and **what it costs them to hold**.
|
|
1179
|
+
*
|
|
1180
|
+
* `POST` takes a refcount hold and `DELETE` releases it; the first hold
|
|
1181
|
+
* starts the robot publishing and the last release stops it (§10). A client
|
|
1182
|
+
* that forgets to release keeps a robot streaming to nobody, so the SDK hands
|
|
1183
|
+
* back a `release()` rather than a bare token.
|
|
1184
|
+
*
|
|
1185
|
+
* **`expires_at` is a join deadline, not a session backstop.** A LiveKit
|
|
1186
|
+
* token is checked when a participant connects and not again afterwards, so a
|
|
1187
|
+
* viewer who has already joined keeps receiving video straight past this
|
|
1188
|
+
* moment. Do not design cleanup around it. What actually ends a session is
|
|
1189
|
+
* `release()` together with disconnecting the room, the cloud reconciling the
|
|
1190
|
+
* hold away against LiveKit's real participants, or a revocation kicking the
|
|
1191
|
+
* participant out. This comment previously claimed the opposite and the SDK
|
|
1192
|
+
* inherited the claim from here — a developer reading it would reasonably
|
|
1193
|
+
* have skipped cleanup on purpose.
|
|
1194
|
+
*/
|
|
1195
|
+
export declare const liveSessionResponse: z.ZodObject<{
|
|
1196
|
+
session_id: z.ZodUUID;
|
|
1197
|
+
url: z.ZodString;
|
|
1198
|
+
room: z.ZodString;
|
|
1199
|
+
token: z.ZodString;
|
|
1200
|
+
expires_at: z.ZodISODateTime;
|
|
1201
|
+
}, z.core.$strip>;
|
|
1202
|
+
export type LiveSessionResponse = z.infer<typeof liveSessionResponse>;
|
|
1203
|
+
/**
|
|
1204
|
+
* The snapshot read **without the bytes**.
|
|
1205
|
+
*
|
|
1206
|
+
* A viewer polling at the camera's interval otherwise re-downloads a whole
|
|
1207
|
+
* image to discover whether a new one exists. This is the cheap question —
|
|
1208
|
+
* *how old is what you have?* — so a client can fetch pixels only when the
|
|
1209
|
+
* timestamp actually moved. It matters most on the console's snapshot view,
|
|
1210
|
+
* which polls continuously while a tab is open.
|
|
1211
|
+
*
|
|
1212
|
+
* `age_ms` is not a convenience: a cached frame served without its age is
|
|
1213
|
+
* indistinguishable from a live one, and §10 makes snapshots deliberately
|
|
1214
|
+
* cheap and therefore deliberately old. `null` values mean nothing has been
|
|
1215
|
+
* captured yet — which is an answer, not an error.
|
|
1216
|
+
*/
|
|
1217
|
+
export declare const snapshotMetaResponse: z.ZodObject<{
|
|
1218
|
+
slug: z.ZodString;
|
|
1219
|
+
timestamp_ms: z.ZodNullable<z.ZodNumber>;
|
|
1220
|
+
age_ms: z.ZodNullable<z.ZodNumber>;
|
|
1221
|
+
width: z.ZodNullable<z.ZodNumber>;
|
|
1222
|
+
height: z.ZodNullable<z.ZodNumber>;
|
|
1223
|
+
mime: z.ZodNullable<z.ZodString>;
|
|
1224
|
+
}, z.core.$strip>;
|
|
1225
|
+
export type SnapshotMetaResponse = z.infer<typeof snapshotMetaResponse>;
|
|
1226
|
+
/**
|
|
1227
|
+
* **Both history shapes answer the same boundary the same way: `[from, to)`
|
|
1228
|
+
* (W9d, DEF-062 — decision pre-made at the W6 boundary so no wave
|
|
1229
|
+
* re-litigates it).**
|
|
1230
|
+
*
|
|
1231
|
+
* They did not. `samples` was inclusive of `to`, `buckets` exclusive — same
|
|
1232
|
+
* range, same data, opposite answers for a point landing exactly on `to`, and
|
|
1233
|
+
* the buckets answer rendered as a gap tooltipped *"empty — no samples"*.
|
|
1234
|
+
* `sdk/README.md` documented the inclusive notation for the half-open path,
|
|
1235
|
+
* so it was wrong for one of the two whichever way you read it.
|
|
1236
|
+
*
|
|
1237
|
+
* Half-open wins because it is the only rule under which **adjacent windows
|
|
1238
|
+
* tile without overlap**: `[0,10)` then `[10,20)` covers every instant once.
|
|
1239
|
+
* With an inclusive upper bound a sample at exactly `10` belongs to both
|
|
1240
|
+
* windows, and any consumer summing them counts it twice.
|
|
1241
|
+
*
|
|
1242
|
+
* This is a statement about behaviour, not a field — nothing in the shapes
|
|
1243
|
+
* below can enforce it. It is written here because this is the one place both
|
|
1244
|
+
* shapes are defined together, and the cloud's `history-store` and the SDK's
|
|
1245
|
+
* README are the two places that have to agree with it.
|
|
1246
|
+
*/
|
|
1247
|
+
/**
|
|
1248
|
+
* A history query (§8). `from`/`to` accept **either** a relative expression
|
|
1249
|
+
* (`now-30s`, `now-5m`, `now-1h`) **or** absolute unix milliseconds, because
|
|
1250
|
+
* a chart asks the first way and a report asks the second, and making a
|
|
1251
|
+
* client convert is making it guess our clock.
|
|
1252
|
+
*
|
|
1253
|
+
* `window` without `agg` is meaningless and `agg` without `window` is
|
|
1254
|
+
* ambiguous — both are refused rather than assigned a default, since a
|
|
1255
|
+
* silently chosen aggregation is a chart that lies quietly.
|
|
1256
|
+
*/
|
|
1257
|
+
export declare const historyQuery: z.ZodObject<{
|
|
1258
|
+
from: z.ZodString;
|
|
1259
|
+
to: z.ZodOptional<z.ZodString>;
|
|
1260
|
+
window: z.ZodOptional<z.ZodString>;
|
|
1261
|
+
agg: z.ZodOptional<z.ZodEnum<{
|
|
1262
|
+
min: "min";
|
|
1263
|
+
max: "max";
|
|
1264
|
+
avg: "avg";
|
|
1265
|
+
}>>;
|
|
1266
|
+
field: z.ZodOptional<z.ZodString>;
|
|
1267
|
+
limit: z.ZodOptional<z.ZodPipe<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodTransform<number, string | number>>, z.ZodNumber>>;
|
|
1268
|
+
}, z.core.$strip>;
|
|
1269
|
+
export type HistoryQuery = z.infer<typeof historyQuery>;
|
|
1270
|
+
/**
|
|
1271
|
+
* Raw samples. `timestamp_ms` is the **bridge's capture time** (§6.3) — the
|
|
1272
|
+
* same instant the live value carried, so a recorded point and a live one can
|
|
1273
|
+
* be placed on one axis without apology.
|
|
1274
|
+
*
|
|
1275
|
+
* `truncated` says the response was cut short. A short array that does not
|
|
1276
|
+
* admit it is indistinguishable from a quiet period, and the two lead a
|
|
1277
|
+
* developer to opposite conclusions.
|
|
1278
|
+
*/
|
|
1279
|
+
export declare const historySamplesResponse: z.ZodObject<{
|
|
1280
|
+
slug: z.ZodString;
|
|
1281
|
+
kind: z.ZodLiteral<"samples">;
|
|
1282
|
+
samples: z.ZodArray<z.ZodObject<{
|
|
1283
|
+
timestamp_ms: z.ZodNumber;
|
|
1284
|
+
value: z.ZodUnknown;
|
|
1285
|
+
}, z.core.$strip>>;
|
|
1286
|
+
truncated: z.ZodBoolean;
|
|
1287
|
+
truncated_by: z.ZodNullable<z.ZodEnum<{
|
|
1288
|
+
limit: "limit";
|
|
1289
|
+
bytes: "bytes";
|
|
1290
|
+
}>>;
|
|
1291
|
+
}, z.core.$strip>;
|
|
1292
|
+
export type HistorySamplesResponse = z.infer<typeof historySamplesResponse>;
|
|
1293
|
+
/**
|
|
1294
|
+
* Aggregated buckets — a **separate shape**, not the samples shape with nulls
|
|
1295
|
+
* in it, so a client knows by type what it received rather than by
|
|
1296
|
+
* inspection.
|
|
1297
|
+
*
|
|
1298
|
+
* `sample_count` exists because an empty bucket and a bucket whose average is
|
|
1299
|
+
* zero are different facts. W5 established at some cost what happens when two
|
|
1300
|
+
* facts share one representation, and a chart is the easiest place in this
|
|
1301
|
+
* product to draw a gap as a line.
|
|
1302
|
+
*/
|
|
1303
|
+
export declare const historyBucketsResponse: z.ZodObject<{
|
|
1304
|
+
slug: z.ZodString;
|
|
1305
|
+
kind: z.ZodLiteral<"buckets">;
|
|
1306
|
+
window_ms: z.ZodNumber;
|
|
1307
|
+
agg: z.ZodEnum<{
|
|
1308
|
+
min: "min";
|
|
1309
|
+
max: "max";
|
|
1310
|
+
avg: "avg";
|
|
1311
|
+
}>;
|
|
1312
|
+
buckets: z.ZodArray<z.ZodObject<{
|
|
1313
|
+
bucket_start_ms: z.ZodNumber;
|
|
1314
|
+
value: z.ZodNullable<z.ZodNumber>;
|
|
1315
|
+
sample_count: z.ZodNumber;
|
|
1316
|
+
}, z.core.$strip>>;
|
|
1317
|
+
}, z.core.$strip>;
|
|
1318
|
+
export type HistoryBucketsResponse = z.infer<typeof historyBucketsResponse>;
|
|
1319
|
+
/**
|
|
1320
|
+
* **What `GET /api/robots/:id/datapoints/:slug/history` answers, which is one
|
|
1321
|
+
* of two shapes.**
|
|
1322
|
+
*
|
|
1323
|
+
* **The query decides, and only the query**: without `window` it is a
|
|
1324
|
+
* `historySamplesResponse`, with one it is a `historyBucketsResponse`.
|
|
1325
|
+
* `window` and `agg` must be given together or not at all — one without the
|
|
1326
|
+
* other is refused rather than defaulted, since a silently chosen aggregation
|
|
1327
|
+
* is a chart that lies quietly.
|
|
1328
|
+
*
|
|
1329
|
+
* Told apart by `kind`, which is `'samples'` or `'buckets'`, so a client
|
|
1330
|
+
* branches on a field rather than on which other fields happen to be present.
|
|
1331
|
+
* The two are deliberately not one shape with nullable halves: an aggregate
|
|
1332
|
+
* and a raw reading answer different questions, and `sample_count` exists on
|
|
1333
|
+
* only one of them.
|
|
1334
|
+
*
|
|
1335
|
+
* **This union exists so the route can name a response at all.** The entry
|
|
1336
|
+
* carried `response: null` while the handler demonstrably answers something,
|
|
1337
|
+
* which reads in the generated reference as *this route returns nothing*.
|
|
1338
|
+
*/
|
|
1339
|
+
export declare const historyResponse: z.ZodUnion<readonly [z.ZodObject<{
|
|
1340
|
+
slug: z.ZodString;
|
|
1341
|
+
kind: z.ZodLiteral<"samples">;
|
|
1342
|
+
samples: z.ZodArray<z.ZodObject<{
|
|
1343
|
+
timestamp_ms: z.ZodNumber;
|
|
1344
|
+
value: z.ZodUnknown;
|
|
1345
|
+
}, z.core.$strip>>;
|
|
1346
|
+
truncated: z.ZodBoolean;
|
|
1347
|
+
truncated_by: z.ZodNullable<z.ZodEnum<{
|
|
1348
|
+
limit: "limit";
|
|
1349
|
+
bytes: "bytes";
|
|
1350
|
+
}>>;
|
|
1351
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1352
|
+
slug: z.ZodString;
|
|
1353
|
+
kind: z.ZodLiteral<"buckets">;
|
|
1354
|
+
window_ms: z.ZodNumber;
|
|
1355
|
+
agg: z.ZodEnum<{
|
|
1356
|
+
min: "min";
|
|
1357
|
+
max: "max";
|
|
1358
|
+
avg: "avg";
|
|
1359
|
+
}>;
|
|
1360
|
+
buckets: z.ZodArray<z.ZodObject<{
|
|
1361
|
+
bucket_start_ms: z.ZodNumber;
|
|
1362
|
+
value: z.ZodNullable<z.ZodNumber>;
|
|
1363
|
+
sample_count: z.ZodNumber;
|
|
1364
|
+
}, z.core.$strip>>;
|
|
1365
|
+
}, z.core.$strip>]>;
|
|
1366
|
+
export type HistoryResponse = z.infer<typeof historyResponse>;
|
|
1367
|
+
/**
|
|
1368
|
+
* W6a — deletion, and the one channel that reports health.
|
|
1369
|
+
*
|
|
1370
|
+
* | Route | Body | Answer |
|
|
1371
|
+
* |---|---|---|
|
|
1372
|
+
* | `DELETE /api/robots/:id` | — | `204`. `?force=true` to proceed while a live session is open; without it, `409 robot_in_use` |
|
|
1373
|
+
* | `GET /api/robots/:id/deletion-preview` | — | `robotDeletionSummary` — the same shape the audit event carries |
|
|
1374
|
+
* | `GET /api/org/health` | — | `resourceHealthListResponse`; `?robot_id=` narrows it to one robot |
|
|
1375
|
+
*
|
|
1376
|
+
* Plus `resourceHealthEvent`, pushed on the **developer** realtime socket
|
|
1377
|
+
* and scoped to the org — not to a subscription, because its job is to reach
|
|
1378
|
+
* somebody who is *not* looking at the thing that broke.
|
|
1379
|
+
*
|
|
1380
|
+
* Two of these paths are worth stating rather than inferring:
|
|
1381
|
+
*
|
|
1382
|
+
* **The preview exists because a confirmation must be able to name what it
|
|
1383
|
+
* destroys.** `DELETE` answers `204` with no body, so the counts only ever
|
|
1384
|
+
* appear on the audit event — written *after* the irreversible click. A
|
|
1385
|
+
* dialog built on that can say nothing better than "are you sure?". The
|
|
1386
|
+
* preview returns the *same shape* as the audit record on purpose: the
|
|
1387
|
+
* warning and the receipt then agree by construction, and a disagreement
|
|
1388
|
+
* between them is a real finding rather than two estimates drifting.
|
|
1389
|
+
*
|
|
1390
|
+
* **The snapshot and the event share the org's scope**, and the snapshot
|
|
1391
|
+
* takes an optional `robot_id` filter rather than living at a per-robot
|
|
1392
|
+
* path.
|
|
1393
|
+
*
|
|
1394
|
+
* The first version of this table said the opposite, with a justification
|
|
1395
|
+
* that sounded right and was incomplete: it reasoned only from a page that
|
|
1396
|
+
* has just opened one robot. But the console shows health on the **robot
|
|
1397
|
+
* list** too, and a per-robot path makes that N requests to render one
|
|
1398
|
+
* screen — while the event that must keep it fresh arrives org-wide anyway.
|
|
1399
|
+
* A snapshot and a channel that disagree about scope are not two halves of
|
|
1400
|
+
* one thing; they are two things that have to be reconciled by every
|
|
1401
|
+
* consumer, separately, forever.
|
|
1402
|
+
*
|
|
1403
|
+
* So: same scope, one route, and `?robot_id=` for the narrow question. The
|
|
1404
|
+
* cloud owner proposed this while unblocking the console, and was right.
|
|
1405
|
+
*
|
|
1406
|
+
* This table was missing from the first W6a delta, and a teammate had to ask
|
|
1407
|
+
* three separate people for the paths — which is how a route becomes a fact
|
|
1408
|
+
* that lives only in an inbox.
|
|
1409
|
+
*/
|
|
1410
|
+
/**
|
|
1411
|
+
* What a `robot.deleted` audit event carries (W6a).
|
|
1412
|
+
*
|
|
1413
|
+
* A deletion record that says only *that* something was destroyed is a
|
|
1414
|
+
* receipt for an unknown amount. This names it: how many configured slugs,
|
|
1415
|
+
* how many stored samples, how many bytes that freed against the retention
|
|
1416
|
+
* quota, which cameras existed, how much attributed run history went with
|
|
1417
|
+
* it, and whether somebody was watching at the time. Those are the questions
|
|
1418
|
+
* asked afterwards, and afterwards is the one moment the data cannot be
|
|
1419
|
+
* consulted.
|
|
1420
|
+
*/
|
|
1421
|
+
export declare const robotDeletionSummary: z.ZodObject<{
|
|
1422
|
+
slug_count: z.ZodNumber;
|
|
1423
|
+
sample_rows: z.ZodNumber;
|
|
1424
|
+
bytes_freed: z.ZodNumber;
|
|
1425
|
+
cameras: z.ZodArray<z.ZodString>;
|
|
1426
|
+
asset_count: z.ZodNumber;
|
|
1427
|
+
asset_bytes_freed: z.ZodNumber;
|
|
1428
|
+
job_run_count: z.ZodNumber;
|
|
1429
|
+
had_live_session: z.ZodBoolean;
|
|
1430
|
+
had_unpublished_draft: z.ZodBoolean;
|
|
1431
|
+
}, z.core.$strip>;
|
|
1432
|
+
export type RobotDeletionSummary = z.infer<typeof robotDeletionSummary>;
|
|
1433
|
+
/**
|
|
1434
|
+
* The query of `DELETE /api/robots/:id`.
|
|
1435
|
+
*
|
|
1436
|
+
* **`force=true` or nothing, and every other value is refused.** The handler
|
|
1437
|
+
* parses the query with this schema and answers `400 validation_error` on
|
|
1438
|
+
* anything else, so `?force=1` and `?force=TRUE` are neither forced nor
|
|
1439
|
+
* quietly un-forced. That is the whole point of the strictness: silently
|
|
1440
|
+
* false was the worst answer available, because a caller who believes they
|
|
1441
|
+
* authorised a cascade and did not then gets a `409` naming the very flag
|
|
1442
|
+
* they passed, and cannot tell which of the two happened.
|
|
1443
|
+
*
|
|
1444
|
+
* Declared as the literal string because it is the only value that does
|
|
1445
|
+
* anything — a `z.boolean()` here would describe a wire shape a query string
|
|
1446
|
+
* cannot carry, and a `z.string()` would document nothing. The MCP door takes
|
|
1447
|
+
* a real boolean and cannot express the ambiguity at all, so the two are one
|
|
1448
|
+
* policy in two vocabularies rather than two policies.
|
|
1449
|
+
*/
|
|
1450
|
+
export declare const robotDeleteQuery: z.ZodObject<{
|
|
1451
|
+
force: z.ZodOptional<z.ZodLiteral<"true">>;
|
|
1452
|
+
}, z.core.$strip>;
|
|
1453
|
+
export type RobotDeleteQuery = z.infer<typeof robotDeleteQuery>;
|
|
1454
|
+
/**
|
|
1455
|
+
* The seven health states, declared **once** (W6a review).
|
|
1456
|
+
*
|
|
1457
|
+
* `resourceHealthState` and `resourceHealthEvent` are the snapshot and the
|
|
1458
|
+
* push of the same thing, and they had the same seven values written out
|
|
1459
|
+
* twice, linked by nothing — the artifacts published two independent copies
|
|
1460
|
+
* with no `$ref`. They agreed only because whoever added `unknown` remembered
|
|
1461
|
+
* to add it in both places, on the wave's last contract commit.
|
|
1462
|
+
*
|
|
1463
|
+
* One concept rendering as two artifacts that nothing keeps in step is its
|
|
1464
|
+
* own class of artifact-versus-source defect, distinct from `.default()`
|
|
1465
|
+
* publishing as `required` and from `z.coerce`'s unrepresentable input.
|
|
1466
|
+
*/
|
|
1467
|
+
export declare const RESOURCE_HEALTH_STATES: readonly ["ok", "unreachable", "auth_failed", "unreadable_credential", "credential_missing", "stopped_by_config_change", "publish_failed", "unknown"];
|
|
1468
|
+
/**
|
|
1469
|
+
* The health of one thing a developer configured, as the platform currently
|
|
1470
|
+
* sees it (W6a).
|
|
1471
|
+
*
|
|
1472
|
+
* This exists because four separate findings turned out to be one absence:
|
|
1473
|
+
* nothing carried the state of a camera, a source or a credential to a
|
|
1474
|
+
* developer who was not, at that exact moment, pressing a button. A publish
|
|
1475
|
+
* failure after the `201` never reached the viewer holding the token; a
|
|
1476
|
+
* source whose password was wrong failed at config-apply time with nobody
|
|
1477
|
+
* watching and stayed silent until someone pressed "Go live" days later; a
|
|
1478
|
+
* viewer could not learn *why* a stream ended, so the console had to offer
|
|
1479
|
+
* two possibilities and rank neither; and an undecryptable credential
|
|
1480
|
+
* reported as healthy.
|
|
1481
|
+
*
|
|
1482
|
+
* One shape, because four patches against four symptoms is how W5 nearly
|
|
1483
|
+
* wrote a failure report into `publishState` — a field the cloud writes and
|
|
1484
|
+
* reads in exactly one place, which would have been a dead end.
|
|
1485
|
+
*
|
|
1486
|
+
* `reason` is for a human and is **never** built from an exception message:
|
|
1487
|
+
* W6 found a camera password in a log through `log.exception`, and again in
|
|
1488
|
+
* `LiveStartError`'s message, which travels to the cloud on this very path.
|
|
1489
|
+
* Type names and fixed strings only.
|
|
1490
|
+
*/
|
|
1491
|
+
export declare const resourceHealthState: z.ZodObject<{
|
|
1492
|
+
robot_id: z.ZodUUID;
|
|
1493
|
+
kind: z.ZodEnum<{
|
|
1494
|
+
camera: "camera";
|
|
1495
|
+
}>;
|
|
1496
|
+
ref: z.ZodString;
|
|
1497
|
+
facet: z.ZodEnum<{
|
|
1498
|
+
source: "source";
|
|
1499
|
+
publish: "publish";
|
|
1500
|
+
}>;
|
|
1501
|
+
state: z.ZodEnum<{
|
|
1502
|
+
unknown: "unknown";
|
|
1503
|
+
ok: "ok";
|
|
1504
|
+
unreachable: "unreachable";
|
|
1505
|
+
auth_failed: "auth_failed";
|
|
1506
|
+
unreadable_credential: "unreadable_credential";
|
|
1507
|
+
credential_missing: "credential_missing";
|
|
1508
|
+
stopped_by_config_change: "stopped_by_config_change";
|
|
1509
|
+
publish_failed: "publish_failed";
|
|
1510
|
+
}>;
|
|
1511
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
1512
|
+
changed_at_ms: z.ZodNumber;
|
|
1513
|
+
}, z.core.$strip>;
|
|
1514
|
+
export type ResourceHealthState = z.infer<typeof resourceHealthState>;
|
|
1515
|
+
/**
|
|
1516
|
+
* The current state of everything in the **org**.
|
|
1517
|
+
*
|
|
1518
|
+
* This doc said "on one robot" until the W6a review found it: the route moved
|
|
1519
|
+
* to org scope in `2bb67c5` and the route table forty lines above spends a
|
|
1520
|
+
* paragraph explaining why the per-robot reading was wrong — while the schema
|
|
1521
|
+
* it describes still said the old thing. Cloud, console and SDK all implement
|
|
1522
|
+
* org-wide correctly; contracts was the only place still saying otherwise,
|
|
1523
|
+
* and it is the first place a fourth consumer reads.
|
|
1524
|
+
*
|
|
1525
|
+
* A channel with no snapshot cannot answer "what is the state now?" for a
|
|
1526
|
+
* page that just loaded — it can only report the next change, which may be
|
|
1527
|
+
* hours away. Both halves or neither.
|
|
1528
|
+
*/
|
|
1529
|
+
export declare const resourceHealthListResponse: z.ZodObject<{
|
|
1530
|
+
resources: z.ZodArray<z.ZodObject<{
|
|
1531
|
+
robot_id: z.ZodUUID;
|
|
1532
|
+
kind: z.ZodEnum<{
|
|
1533
|
+
camera: "camera";
|
|
1534
|
+
}>;
|
|
1535
|
+
ref: z.ZodString;
|
|
1536
|
+
facet: z.ZodEnum<{
|
|
1537
|
+
source: "source";
|
|
1538
|
+
publish: "publish";
|
|
1539
|
+
}>;
|
|
1540
|
+
state: z.ZodEnum<{
|
|
1541
|
+
unknown: "unknown";
|
|
1542
|
+
ok: "ok";
|
|
1543
|
+
unreachable: "unreachable";
|
|
1544
|
+
auth_failed: "auth_failed";
|
|
1545
|
+
unreadable_credential: "unreadable_credential";
|
|
1546
|
+
credential_missing: "credential_missing";
|
|
1547
|
+
stopped_by_config_change: "stopped_by_config_change";
|
|
1548
|
+
publish_failed: "publish_failed";
|
|
1549
|
+
}>;
|
|
1550
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
1551
|
+
changed_at_ms: z.ZodNumber;
|
|
1552
|
+
}, z.core.$strip>>;
|
|
1553
|
+
}, z.core.$strip>;
|
|
1554
|
+
export type ResourceHealthListResponse = z.infer<typeof resourceHealthListResponse>;
|
|
1555
|
+
/**
|
|
1556
|
+
* The query of `GET /api/org/health`: optionally one robot instead of the org.
|
|
1557
|
+
*
|
|
1558
|
+
* The narrowing lives in a query rather than at a per-robot path because the
|
|
1559
|
+
* console shows health on the robot list too, and a per-robot path would make
|
|
1560
|
+
* that N requests to render one screen.
|
|
1561
|
+
*/
|
|
1562
|
+
export declare const orgHealthQuery: z.ZodObject<{
|
|
1563
|
+
robot_id: z.ZodOptional<z.ZodUUID>;
|
|
1564
|
+
}, z.core.$strip>;
|
|
1565
|
+
export type OrgHealthQuery = z.infer<typeof orgHealthQuery>;
|
|
1566
|
+
/**
|
|
1567
|
+
* Org protection quotas (§12.4) — generous, server-side adjustable, visible
|
|
1568
|
+
* in Settings. Protection against runaway use, not a business model; a later
|
|
1569
|
+
* one docks onto the same dials.
|
|
1570
|
+
*/
|
|
1571
|
+
export declare const orgQuotas: z.ZodObject<{
|
|
1572
|
+
max_robots: z.ZodNumber;
|
|
1573
|
+
max_apps: z.ZodNumber;
|
|
1574
|
+
max_end_users: z.ZodNumber;
|
|
1575
|
+
max_retention_bytes: z.ZodNumber;
|
|
1576
|
+
max_retention_writes_per_minute: z.ZodNumber;
|
|
1577
|
+
max_realtime_connections: z.ZodNumber;
|
|
1578
|
+
max_asset_storage_bytes: z.ZodNumber;
|
|
1579
|
+
}, z.core.$strip>;
|
|
1580
|
+
export type OrgQuotas = z.infer<typeof orgQuotas>;
|
|
1581
|
+
/**
|
|
1582
|
+
* What an org is **actually using**, per quota.
|
|
1583
|
+
*
|
|
1584
|
+
* A separate shape rather than `orgQuotas.partial()`, which is what this was
|
|
1585
|
+
* first — and that was wrong in a way its own tests caught: a limit is
|
|
1586
|
+
* `positive()` because a quota of zero would forbid everything, but a
|
|
1587
|
+
* **usage** of zero is the honest answer for every org on the day it signs
|
|
1588
|
+
* up. Reusing one schema for a limit and a measurement is the same mistake as
|
|
1589
|
+
* letting an empty bucket and a zero average share a representation, which
|
|
1590
|
+
* this wave spent a lot of care avoiding one layer up.
|
|
1591
|
+
*
|
|
1592
|
+
* Every field is optional because a quota we do not measure must be
|
|
1593
|
+
* **absent**, never reported as `0` — "not measured" and "measured as zero"
|
|
1594
|
+
* are different facts, and a dashboard that renders the first as the second
|
|
1595
|
+
* is lying quietly.
|
|
1596
|
+
*/
|
|
1597
|
+
export declare const orgQuotaUsageCounts: z.ZodObject<{
|
|
1598
|
+
max_robots: z.ZodOptional<z.ZodNumber>;
|
|
1599
|
+
max_apps: z.ZodOptional<z.ZodNumber>;
|
|
1600
|
+
max_end_users: z.ZodOptional<z.ZodNumber>;
|
|
1601
|
+
max_retention_bytes: z.ZodOptional<z.ZodNumber>;
|
|
1602
|
+
max_asset_storage_bytes: z.ZodOptional<z.ZodNumber>;
|
|
1603
|
+
max_retention_writes_per_minute: z.ZodOptional<z.ZodNumber>;
|
|
1604
|
+
max_realtime_connections: z.ZodOptional<z.ZodNumber>;
|
|
1605
|
+
}, z.core.$strip>;
|
|
1606
|
+
export type OrgQuotaUsageCounts = z.infer<typeof orgQuotaUsageCounts>;
|
|
1607
|
+
/** Limits beside what is actually used — a limit alone tells nobody where they stand. */
|
|
1608
|
+
export declare const orgQuotaUsage: z.ZodObject<{
|
|
1609
|
+
quotas: z.ZodObject<{
|
|
1610
|
+
max_robots: z.ZodNumber;
|
|
1611
|
+
max_apps: z.ZodNumber;
|
|
1612
|
+
max_end_users: z.ZodNumber;
|
|
1613
|
+
max_retention_bytes: z.ZodNumber;
|
|
1614
|
+
max_retention_writes_per_minute: z.ZodNumber;
|
|
1615
|
+
max_realtime_connections: z.ZodNumber;
|
|
1616
|
+
max_asset_storage_bytes: z.ZodNumber;
|
|
1617
|
+
}, z.core.$strip>;
|
|
1618
|
+
usage: z.ZodObject<{
|
|
1619
|
+
max_robots: z.ZodOptional<z.ZodNumber>;
|
|
1620
|
+
max_apps: z.ZodOptional<z.ZodNumber>;
|
|
1621
|
+
max_end_users: z.ZodOptional<z.ZodNumber>;
|
|
1622
|
+
max_retention_bytes: z.ZodOptional<z.ZodNumber>;
|
|
1623
|
+
max_asset_storage_bytes: z.ZodOptional<z.ZodNumber>;
|
|
1624
|
+
max_retention_writes_per_minute: z.ZodOptional<z.ZodNumber>;
|
|
1625
|
+
max_realtime_connections: z.ZodOptional<z.ZodNumber>;
|
|
1626
|
+
}, z.core.$strip>;
|
|
1627
|
+
}, z.core.$strip>;
|
|
1628
|
+
export type OrgQuotaUsage = z.infer<typeof orgQuotaUsage>;
|
|
1629
|
+
/** One bucket is one minute. Stated here so the cloud and any client agree without guessing. */
|
|
1630
|
+
export declare const LATENCY_BUCKET_MS = 60000;
|
|
1631
|
+
/**
|
|
1632
|
+
* Latency buckets are **platform telemetry, not a customer datapoint**, and
|
|
1633
|
+
* this short retention is why that distinction was worth making: the cloud
|
|
1634
|
+
* pings every bridge every 2 seconds, ~43 200 measurements per robot per day,
|
|
1635
|
+
* and a sparkline needs about 60 points per hour. Seven days is generous for
|
|
1636
|
+
* what reads it and costs the org's retention quota nothing, because it is not
|
|
1637
|
+
* counted against it.
|
|
1638
|
+
*/
|
|
1639
|
+
export declare const BRIDGE_LATENCY_RETENTION_DAYS = 7;
|
|
1640
|
+
/**
|
|
1641
|
+
* Every read of the durable run history and the latency buckets: the three
|
|
1642
|
+
* org-wide ones the fleet overview is built on, and the one robot-scoped door
|
|
1643
|
+
* a client app has into the same table.
|
|
1644
|
+
*
|
|
1645
|
+
* | Route | Query | Answer |
|
|
1646
|
+
* |---|---|---|
|
|
1647
|
+
* | `GET /api/org/jobs` | `jobRunQuery` | `jobRunListResponse` — newest first, cursor-paged over the durable `seq` |
|
|
1648
|
+
* | `GET /api/org/jobs/summary` | `jobRunSummaryQuery` | `jobRunSummary` — three numbers over the window the caller named |
|
|
1649
|
+
* | `GET /api/org/latency` | `orgLatencyQuery` | `orgLatencyResponse` — one series per robot, truncation named |
|
|
1650
|
+
* | `GET /api/robots/:id/jobs/history` | `jobRunQuery` | `jobRunListResponse` — the same read, robot-scoped, developers **and** clients |
|
|
1651
|
+
*
|
|
1652
|
+
* **Written down here because the last time a delta shipped shapes without
|
|
1653
|
+
* their paths, a teammate had to ask three separate people** — see
|
|
1654
|
+
* `robotDeletionSummary`'s neighbouring table, which exists for exactly that
|
|
1655
|
+
* reason. The shapes landed one wave before the routes did, so this table is
|
|
1656
|
+
* the only place the two halves meet.
|
|
1657
|
+
*
|
|
1658
|
+
* Three things about them are worth stating rather than inferring:
|
|
1659
|
+
*
|
|
1660
|
+
* **The three `/api/org/…` reads are org-wide, and `?robot_id=` narrows
|
|
1661
|
+
* them** — the same choice `GET /api/org/health` already made, for the same
|
|
1662
|
+
* reason: the overview screen shows every robot at once, and a per-robot path
|
|
1663
|
+
* would make one screen N requests.
|
|
1664
|
+
*
|
|
1665
|
+
* **Those three are developer-only, and that is a property of their scope,
|
|
1666
|
+
* not of the data.** An org-wide read has no client meaning: an end user is
|
|
1667
|
+
* scoped to the robots their app assigns, never to an org.
|
|
1668
|
+
*
|
|
1669
|
+
* **The client-facing read of the same table is
|
|
1670
|
+
* `GET /api/robots/:id/jobs/history`** — robot-scoped, one route for
|
|
1671
|
+
* developers and clients like every other robot-scoped read (`.../jobs`,
|
|
1672
|
+
* `.../assets`, `.../datapoints`), never a parallel `/api/client/…` twin. An
|
|
1673
|
+
* end user reaches it only when their role's `capabilities.action_history`
|
|
1674
|
+
* says so — otherwise `403 capability_required`, naming the capability — and
|
|
1675
|
+
* sees only runs on slugs their role grants. On this route `?robot_id=` is
|
|
1676
|
+
* not a filter: the path already names the robot, and a query naming a
|
|
1677
|
+
* different one is refused rather than quietly answered about the path's.
|
|
1678
|
+
*
|
|
1679
|
+
* **It discloses the actor, and that is what a developer weighs before
|
|
1680
|
+
* granting the capability.** A `jobRun` names who invoked it — `jobActor`
|
|
1681
|
+
* carries an email — so an end user reading a robot's history learns which
|
|
1682
|
+
* other people have been driving that machine. Robot scope plus a role
|
|
1683
|
+
* capability is what makes that a decision a developer takes per role,
|
|
1684
|
+
* instead of something every session gets: an end-user-facing
|
|
1685
|
+
* `GET /api/org/jobs` would have handed over the whole org's actors with no
|
|
1686
|
+
* such decision anywhere, which is why there is none.
|
|
1687
|
+
*
|
|
1688
|
+
* **A page can be shorter than `limit` while `next_cursor` is non-null**, on
|
|
1689
|
+
* the robot-scoped route specifically: the slug filter is applied to the
|
|
1690
|
+
* page the store returned, so a role granting one slug in ten sees thin — and
|
|
1691
|
+
* sometimes empty — pages. That is what `jobRunListResponse.next_cursor`'s
|
|
1692
|
+
* own doc comment means by a promise rather than an observation; a client
|
|
1693
|
+
* keeps reading until it is null.
|
|
1694
|
+
*
|
|
1695
|
+
* **Neither window is optional, and neither has a default.** A summary over
|
|
1696
|
+
* an unnamed window is a number nobody can reproduce; an unbounded latency
|
|
1697
|
+
* window is a response size chosen by whoever forgot to pass one. Each
|
|
1698
|
+
* query's own doc comment says which of those two reasons applies to it.
|
|
1699
|
+
*/
|
|
1700
|
+
/** Seven days x 1440 buckets x N robots is otherwise an unbounded response. */
|
|
1701
|
+
export declare const MAX_LATENCY_BUCKETS_PER_RESPONSE = 20000;
|
|
1702
|
+
export declare const latencyBucket: z.ZodObject<{
|
|
1703
|
+
bucket_at: z.ZodISODateTime;
|
|
1704
|
+
min_ms: z.ZodNullable<z.ZodNumber>;
|
|
1705
|
+
avg_ms: z.ZodNullable<z.ZodNumber>;
|
|
1706
|
+
max_ms: z.ZodNullable<z.ZodNumber>;
|
|
1707
|
+
samples: z.ZodNumber;
|
|
1708
|
+
online_ms: z.ZodNumber;
|
|
1709
|
+
}, z.core.$strip>;
|
|
1710
|
+
export type LatencyBucket = z.infer<typeof latencyBucket>;
|
|
1711
|
+
export declare const robotLatencySeries: z.ZodObject<{
|
|
1712
|
+
robot_id: z.ZodUUID;
|
|
1713
|
+
buckets: z.ZodArray<z.ZodObject<{
|
|
1714
|
+
bucket_at: z.ZodISODateTime;
|
|
1715
|
+
min_ms: z.ZodNullable<z.ZodNumber>;
|
|
1716
|
+
avg_ms: z.ZodNullable<z.ZodNumber>;
|
|
1717
|
+
max_ms: z.ZodNullable<z.ZodNumber>;
|
|
1718
|
+
samples: z.ZodNumber;
|
|
1719
|
+
online_ms: z.ZodNumber;
|
|
1720
|
+
}, z.core.$strip>>;
|
|
1721
|
+
}, z.core.$strip>;
|
|
1722
|
+
export type RobotLatencySeries = z.infer<typeof robotLatencySeries>;
|
|
1723
|
+
/**
|
|
1724
|
+
* `GET /api/org/latency`'s query.
|
|
1725
|
+
*
|
|
1726
|
+
* **Both bounds are required**, for a reason narrower than
|
|
1727
|
+
* `jobRunSummaryQuery`'s: this table holds a bucket per robot per minute for
|
|
1728
|
+
* `BRIDGE_LATENCY_RETENTION_DAYS`, so "everything" is up to 10 080 rows per
|
|
1729
|
+
* robot, and a default window would be a response size chosen by whoever
|
|
1730
|
+
* forgot to pass one. `MAX_LATENCY_BUCKETS_PER_RESPONSE` still bounds the
|
|
1731
|
+
* answer; required bounds are what let a caller decide *which* buckets they
|
|
1732
|
+
* get instead of discovering the ceiling ate the ones they wanted.
|
|
1733
|
+
*
|
|
1734
|
+
* `wireTimestampMs` rather than a plain integer, for its own documented
|
|
1735
|
+
* reason: the union's input branch is what a query string actually carries,
|
|
1736
|
+
* and the year bound is what keeps `253402300800000` from reaching the
|
|
1737
|
+
* Postgres bind path as a `500` where a `400` belongs.
|
|
1738
|
+
*/
|
|
1739
|
+
export declare const orgLatencyQuery: z.ZodObject<{
|
|
1740
|
+
from_ms: z.ZodPipe<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodTransform<number, string | number>>, z.ZodNumber>;
|
|
1741
|
+
to_ms: z.ZodPipe<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodTransform<number, string | number>>, z.ZodNumber>;
|
|
1742
|
+
robot_id: z.ZodOptional<z.ZodUUID>;
|
|
1743
|
+
}, z.core.$strict>;
|
|
1744
|
+
export type OrgLatencyQuery = z.infer<typeof orgLatencyQuery>;
|
|
1745
|
+
export declare const orgLatencyResponse: z.ZodObject<{
|
|
1746
|
+
series: z.ZodArray<z.ZodObject<{
|
|
1747
|
+
robot_id: z.ZodUUID;
|
|
1748
|
+
buckets: z.ZodArray<z.ZodObject<{
|
|
1749
|
+
bucket_at: z.ZodISODateTime;
|
|
1750
|
+
min_ms: z.ZodNullable<z.ZodNumber>;
|
|
1751
|
+
avg_ms: z.ZodNullable<z.ZodNumber>;
|
|
1752
|
+
max_ms: z.ZodNullable<z.ZodNumber>;
|
|
1753
|
+
samples: z.ZodNumber;
|
|
1754
|
+
online_ms: z.ZodNumber;
|
|
1755
|
+
}, z.core.$strip>>;
|
|
1756
|
+
}, z.core.$strip>>;
|
|
1757
|
+
from_ms: z.ZodNumber;
|
|
1758
|
+
to_ms: z.ZodNumber;
|
|
1759
|
+
truncated: z.ZodBoolean;
|
|
1760
|
+
truncated_by: z.ZodNullable<z.ZodEnum<{
|
|
1761
|
+
limit: "limit";
|
|
1762
|
+
bytes: "bytes";
|
|
1763
|
+
}>>;
|
|
1764
|
+
}, z.core.$strip>;
|
|
1765
|
+
export type OrgLatencyResponse = z.infer<typeof orgLatencyResponse>;
|
|
1766
|
+
/**
|
|
1767
|
+
* How long a usage window may be, in days. **Refused above this, not capped** —
|
|
1768
|
+
* the rule `jobRunQuery.limit` already states: a caller who asked for more than
|
|
1769
|
+
* the platform will answer is owed a `400` naming the field, not a quietly
|
|
1770
|
+
* shorter answer they will mistake for the whole picture.
|
|
1771
|
+
*
|
|
1772
|
+
* 366 rather than 365, so "the last full year" is expressible in a leap year.
|
|
1773
|
+
*/
|
|
1774
|
+
export declare const USAGE_WINDOW_MAX_DAYS = 366;
|
|
1775
|
+
/**
|
|
1776
|
+
* The five things the meter records (spec D1).
|
|
1777
|
+
*
|
|
1778
|
+
* Storage is two metrics and not one summed byte count, for
|
|
1779
|
+
* `org_quotas.max_asset_storage_bytes`'s own reason applied to billing: a sync
|
|
1780
|
+
* grows storage in jumps and time series grow steadily, and one number would
|
|
1781
|
+
* let the first crowd out the second on the invoice the same way it would on
|
|
1782
|
+
* the quota.
|
|
1783
|
+
*/
|
|
1784
|
+
export declare const usageMetric: z.ZodEnum<{
|
|
1785
|
+
api_calls: "api_calls";
|
|
1786
|
+
live_session_ms: "live_session_ms";
|
|
1787
|
+
retention_bytes: "retention_bytes";
|
|
1788
|
+
asset_bytes: "asset_bytes";
|
|
1789
|
+
robot_online_ms: "robot_online_ms";
|
|
1790
|
+
}>;
|
|
1791
|
+
export type UsageMetric = z.infer<typeof usageMetric>;
|
|
1792
|
+
/**
|
|
1793
|
+
* A UTC calendar day, `YYYY-MM-DD`.
|
|
1794
|
+
*
|
|
1795
|
+
* A string and not a millisecond instant, because the thing being described is
|
|
1796
|
+
* a day and not a moment: a `Date` here would carry a time and a zone the
|
|
1797
|
+
* column does not have, and every bug in this area starts with one being
|
|
1798
|
+
* silently converted.
|
|
1799
|
+
*
|
|
1800
|
+
* **The regex checks shape, not validity** — `2026-13-45` and `2026-02-30`
|
|
1801
|
+
* both match `\d{4}-\d{2}-\d{2}$` — so the `.refine()` below round-trips the
|
|
1802
|
+
* string through `Date`'s UTC parser and rejects anything that does not come
|
|
1803
|
+
* back unchanged: `2026-13-45` parses to `Invalid Date`, and `2026-02-30`
|
|
1804
|
+
* (which `Date` rolls over rather than rejects) comes back as `2026-03-02`,
|
|
1805
|
+
* a mismatch either way. Same defect class as `auditQuery.from_ms`'s
|
|
1806
|
+
* `253402300800000`: a value that is the right *shape* reaching the Postgres
|
|
1807
|
+
* bind path for a `date` column and answering `500` where `400` belongs.
|
|
1808
|
+
*
|
|
1809
|
+
* **What the published artifact does not say:** `wireTimestampMs`'s own
|
|
1810
|
+
* note applies unchanged — a `.refine()` has no JSON Schema rendering, so
|
|
1811
|
+
* `org-usage-query.schema.json` shows only the shape-checking `pattern` and
|
|
1812
|
+
* a generated client that validates against the artifact alone will believe
|
|
1813
|
+
* `2026-02-30` is acceptable. The runtime is the authority for this field.
|
|
1814
|
+
*/
|
|
1815
|
+
export declare const usageDay: z.ZodString;
|
|
1816
|
+
/**
|
|
1817
|
+
* **The window is inclusive at both ends**, unlike every millisecond window in
|
|
1818
|
+
* this file (`from_ms`/`to_ms`, half-open per DEF-062).
|
|
1819
|
+
*
|
|
1820
|
+
* That inconsistency is deliberate and is stated here rather than left to be
|
|
1821
|
+
* discovered: a calendar day is a unit, not an instant, and a person asking for
|
|
1822
|
+
* July will write `from_day=2026-07-01&to_day=2026-07-31`. A half-open day
|
|
1823
|
+
* window would silently drop the 31st.
|
|
1824
|
+
*
|
|
1825
|
+
* Both parameters are required and have no default — the rule `/api/org/latency`
|
|
1826
|
+
* and `/api/org/jobs/summary` already follow. "This month" is a question only
|
|
1827
|
+
* the caller's calendar can answer, and a default window would be a query size
|
|
1828
|
+
* chosen by whoever forgot to pass one.
|
|
1829
|
+
*
|
|
1830
|
+
* **The published artifact cannot express any of this**, and that is worth
|
|
1831
|
+
* saying out loud rather than leaving a reader to assume the JSON Schema is
|
|
1832
|
+
* the whole contract, for `orgLatencyQuery`'s own reason: a cross-field
|
|
1833
|
+
* comparison has no JSON Schema rendering, so `org-usage-query.schema.json`
|
|
1834
|
+
* describes two independent pattern-matched strings and validates an
|
|
1835
|
+
* inverted window happily — the cloud is the only enforcement point for the
|
|
1836
|
+
* ordering. The artifact is equally silent about the inclusivity called out
|
|
1837
|
+
* above: nothing in the shape distinguishes an inclusive day window from a
|
|
1838
|
+
* half-open one, that is a fact about behaviour, not a field (the same gap
|
|
1839
|
+
* `historyQuery`/`historyBucketsResponse` name for their own half-open
|
|
1840
|
+
* boundary). And it says nothing about `USAGE_WINDOW_MAX_DAYS` at all — the
|
|
1841
|
+
* constant is not wired into this schema as a check on the span between
|
|
1842
|
+
* `from_day` and `to_day`; the cloud route is where a caller who asked for
|
|
1843
|
+
* more than the ceiling is refused, so a generated client validating against
|
|
1844
|
+
* the artifact alone can build a five-year window and get a `400` from the
|
|
1845
|
+
* route it did not predict.
|
|
1846
|
+
*/
|
|
1847
|
+
export declare const orgUsageQuery: z.ZodObject<{
|
|
1848
|
+
from_day: z.ZodString;
|
|
1849
|
+
to_day: z.ZodString;
|
|
1850
|
+
}, z.core.$strict>;
|
|
1851
|
+
export type OrgUsageQuery = z.infer<typeof orgUsageQuery>;
|
|
1852
|
+
/**
|
|
1853
|
+
* One day's reading for one metric.
|
|
1854
|
+
*
|
|
1855
|
+
* **`app_id` is `null` when the consumer is the org itself** (spec D2), and
|
|
1856
|
+
* what that `null` means for billing depends on the *metric*, not on
|
|
1857
|
+
* `app_id` alone. `api_calls` and `live_session_ms` are attributable to an
|
|
1858
|
+
* app: a `null` app_id on those two is the developer console's own traffic,
|
|
1859
|
+
* deliberately *not* billable. `retention_bytes`, `asset_bytes` and
|
|
1860
|
+
* `robot_online_ms` have no app dimension at all — every row for those three
|
|
1861
|
+
* carries `app_id: null` unconditionally, and every one is billable org-level
|
|
1862
|
+
* consumption. **A reader must check `metric` before treating `app_id ===
|
|
1863
|
+
* null` as "not billable"** — for three of the five metrics that reading is
|
|
1864
|
+
* always wrong.
|
|
1865
|
+
*
|
|
1866
|
+
* `app_name` is `null` whenever `app_id` is, and also when the app has since
|
|
1867
|
+
* been deleted — usage outlives the app it was attributed to, because an org
|
|
1868
|
+
* still owes for what it used. A UUID alone on an invoice line helps nobody,
|
|
1869
|
+
* and a copy of the name stored on every row would be a second truth that
|
|
1870
|
+
* drifts on the first rename.
|
|
1871
|
+
*
|
|
1872
|
+
* **What this number cannot promise**, and the bound is conditional rather
|
|
1873
|
+
* than flat. `api_calls` and `live_session_ms` are aggregated in memory and
|
|
1874
|
+
* written every 30 seconds.
|
|
1875
|
+
*
|
|
1876
|
+
* *While those writes are landing*, a `kill -9` loses up to 30 seconds of
|
|
1877
|
+
* counting — never more, and never against the caller, since an unflushed
|
|
1878
|
+
* count is simply not billed.
|
|
1879
|
+
*
|
|
1880
|
+
* *While they are failing* — an unreachable database, say — that bound does
|
|
1881
|
+
* not hold at all: everything counted since the last successful flush is
|
|
1882
|
+
* held in memory, deliberately uncapped, and a `kill -9` loses all of it.
|
|
1883
|
+
* The trade is intentional (dropping billing data to bound process memory is
|
|
1884
|
+
* the worse half of it), but "at most one interval" describes a platform
|
|
1885
|
+
* whose writes are landing, not a guarantee that survives an outage. This
|
|
1886
|
+
* sentence used to say "never more", and it was false.
|
|
1887
|
+
*
|
|
1888
|
+
* A row the database rejects **permanently** — most concretely one whose org
|
|
1889
|
+
* has been deleted since the count, since a usage row's `org_id` is `ON
|
|
1890
|
+
* DELETE NO ACTION` — is written off instead: given up on, reported with a
|
|
1891
|
+
* count, and never billed. That is a deliberate loss, and it is the smaller
|
|
1892
|
+
* one. Before it, a single such row failed the whole batched write on every
|
|
1893
|
+
* retry, forever, and stopped `api_calls` and `live_session_ms` reaching the
|
|
1894
|
+
* database for **every** org on the platform.
|
|
1895
|
+
*
|
|
1896
|
+
* A graceful shutdown loses nothing **provided its final flush succeeds**.
|
|
1897
|
+
* If that write fails, the process reports how many rows it is carrying and
|
|
1898
|
+
* exits carrying them — there is no second attempt, because there is no
|
|
1899
|
+
* longer a process to make one.
|
|
1900
|
+
*
|
|
1901
|
+
* The other three metrics never travel this path. They are sampled from
|
|
1902
|
+
* other tables on their own timer and can lag; what a missed sample costs,
|
|
1903
|
+
* per metric, is in the docs' `/api/org/usage` notes.
|
|
1904
|
+
*/
|
|
1905
|
+
export declare const usageRow: z.ZodObject<{
|
|
1906
|
+
app_id: z.ZodNullable<z.ZodUUID>;
|
|
1907
|
+
app_name: z.ZodNullable<z.ZodString>;
|
|
1908
|
+
metric: z.ZodEnum<{
|
|
1909
|
+
api_calls: "api_calls";
|
|
1910
|
+
live_session_ms: "live_session_ms";
|
|
1911
|
+
retention_bytes: "retention_bytes";
|
|
1912
|
+
asset_bytes: "asset_bytes";
|
|
1913
|
+
robot_online_ms: "robot_online_ms";
|
|
1914
|
+
}>;
|
|
1915
|
+
day: z.ZodString;
|
|
1916
|
+
value: z.ZodNumber;
|
|
1917
|
+
}, z.core.$strip>;
|
|
1918
|
+
export type UsageRow = z.infer<typeof usageRow>;
|
|
1919
|
+
/** The window is echoed back for `orgLatencyResponse`'s reason: a rendered total has to be able to say which window it describes. */
|
|
1920
|
+
export declare const orgUsageResponse: z.ZodObject<{
|
|
1921
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
1922
|
+
app_id: z.ZodNullable<z.ZodUUID>;
|
|
1923
|
+
app_name: z.ZodNullable<z.ZodString>;
|
|
1924
|
+
metric: z.ZodEnum<{
|
|
1925
|
+
api_calls: "api_calls";
|
|
1926
|
+
live_session_ms: "live_session_ms";
|
|
1927
|
+
retention_bytes: "retention_bytes";
|
|
1928
|
+
asset_bytes: "asset_bytes";
|
|
1929
|
+
robot_online_ms: "robot_online_ms";
|
|
1930
|
+
}>;
|
|
1931
|
+
day: z.ZodString;
|
|
1932
|
+
value: z.ZodNumber;
|
|
1933
|
+
}, z.core.$strip>>;
|
|
1934
|
+
from_day: z.ZodString;
|
|
1935
|
+
to_day: z.ZodString;
|
|
1936
|
+
}, z.core.$strip>;
|
|
1937
|
+
export type OrgUsageResponse = z.infer<typeof orgUsageResponse>;
|
|
1938
|
+
/** `PATCH /api/robots/:id` — rename the robot. Display-only: nothing references robot names. */
|
|
1939
|
+
export declare const patchRobotRequest: z.ZodObject<{
|
|
1940
|
+
name: z.ZodString;
|
|
1941
|
+
}, z.core.$strict>;
|
|
1942
|
+
export type PatchRobotRequest = z.infer<typeof patchRobotRequest>;
|
|
1943
|
+
/**
|
|
1944
|
+
* `POST /api/robots/:id/config/rename-slug` — atomic server-side rename:
|
|
1945
|
+
* rewrites the **draft** config, every app-role grant carrying
|
|
1946
|
+
* `{robot_id, from}`, and the recorded history rows, in one transaction.
|
|
1947
|
+
* Job runs and audit events keep the old slug as historical fact. The
|
|
1948
|
+
* published config is immutable, so the caller must publish afterwards
|
|
1949
|
+
* (`requires_publish`); samples arriving between rename and the applied
|
|
1950
|
+
* publish still land under the old slug — named residual, not migrated.
|
|
1951
|
+
* Second residual in that same window: grants and the draft already name
|
|
1952
|
+
* `to`, but the still-published config exposes only `from` until the
|
|
1953
|
+
* publish lands — an end user's app has no working name for the datapoint
|
|
1954
|
+
* at all for however long that gap lasts, since `to` isn't published yet
|
|
1955
|
+
* and `from` no longer has a grant behind it. The console must publish
|
|
1956
|
+
* immediately after a rename to keep this window short; nothing server-side
|
|
1957
|
+
* closes it.
|
|
1958
|
+
* This schema only enforces slug *shape*; whether `to` is reserved or
|
|
1959
|
+
* already in use on this robot is checked once, behind the cloud's
|
|
1960
|
+
* `validation.ts` door — one door, not a second copy of that rule here.
|
|
1961
|
+
*/
|
|
1962
|
+
export declare const renameSlugRequest: z.ZodObject<{
|
|
1963
|
+
from: z.ZodString;
|
|
1964
|
+
to: z.ZodString;
|
|
1965
|
+
}, z.core.$strict>;
|
|
1966
|
+
export type RenameSlugRequest = z.infer<typeof renameSlugRequest>;
|
|
1967
|
+
export declare const renameSlugResponse: z.ZodObject<{
|
|
1968
|
+
rewritten_grants: z.ZodNumber;
|
|
1969
|
+
history_moved: z.ZodBoolean;
|
|
1970
|
+
requires_publish: z.ZodLiteral<true>;
|
|
1971
|
+
}, z.core.$strip>;
|
|
1972
|
+
export type RenameSlugResponse = z.infer<typeof renameSlugResponse>;
|
|
1973
|
+
/**
|
|
1974
|
+
* `GET /api/robots/:id/config/slug-usage/:slug` — what a rename would touch;
|
|
1975
|
+
* feeds the console's confirm dialog.
|
|
1976
|
+
*
|
|
1977
|
+
* `alert_count` (spec `2026-08-28-alerts-and-datapoint-modal-design`, D5)
|
|
1978
|
+
* joined the atomic rename transaction alongside grants and history: alerts
|
|
1979
|
+
* are keyed by `(robot_id, slug)` too, and a rename that silently moved the
|
|
1980
|
+
* alert row while the usage preview stayed silent about it would show a
|
|
1981
|
+
* developer a smaller blast radius than the rename actually has.
|
|
1982
|
+
*/
|
|
1983
|
+
export declare const slugUsageResponse: z.ZodObject<{
|
|
1984
|
+
grant_count: z.ZodNumber;
|
|
1985
|
+
app_identifiers: z.ZodArray<z.ZodString>;
|
|
1986
|
+
has_recorded_history: z.ZodBoolean;
|
|
1987
|
+
alert_count: z.ZodNumber;
|
|
1988
|
+
}, z.core.$strip>;
|
|
1989
|
+
export type SlugUsageResponse = z.infer<typeof slugUsageResponse>;
|